/* Modern Health, Everlab direction: base stylesheet.
   Reset, type system, nav, buttons, eyebrow chips, containers, section
   rhythm, cards, footer, reveal classes, responsive rules. Shared across
   all pages of this mockup. */

/* ---------- Reset ---------- */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--size-body);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

img, svg { display: block; max-width: 100%; }

a { color: inherit; }

ul { margin: 0; padding: 0; list-style: none; }

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}

h1, h2, h3, h4, p { margin: 0; }

/* ---------- Focus ---------- */

/* One designed focus-visible ring for every link and button on every
   page, so keyboard users get a consistent, branded indicator rather
   than the browser default. Components with their own tighter focus
   treatment (the booking demo controls) simply override this with a
   more specific rule; they do not need to duplicate it. */
a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

.skip {
  position: absolute;
  left: -999px;
  top: 0;
  background: var(--ink);
  color: var(--paper);
  padding: 0.75rem 1.25rem;
  border-radius: var(--radius-md);
  z-index: 200;
}
.skip:focus { left: 1rem; top: 1rem; }

/* ---------- Type system ---------- */

.u-display,
h1.u-display,
h2.u-display {
  font-family: var(--display);
  font-weight: 400;
  letter-spacing: -0.02em;
}

h1.u-display { font-size: var(--size-h1); line-height: 1.1; }
h2.u-display { font-size: var(--size-h2); line-height: 1.05; }
h3.u-display { font-size: var(--size-h3); line-height: 1.2; }

.u-display .fade,
.u-display span.fade {
  color: var(--ink-faint);
}

[data-tone="dark"] .u-display .fade,
[data-tone="dark"] .u-display span.fade {
  color: var(--paper-faint);
}

.body-lg { font-size: var(--size-body-lg); }
.body-sm { font-size: var(--size-small); }

.stat-num {
  display: block;
  font-family: var(--display);
  font-weight: 400;
  font-size: var(--size-stat);
  line-height: 1;
  letter-spacing: -0.02em;
}

/* Eyebrow chip */

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.4rem 0.9rem 0.4rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  background: transparent;
}

.eyebrow::before {
  content: '';
  width: 8px;
  height: 8px;
  flex: none;
  background: var(--accent);
  border-radius: 2px;
}

[data-tone="dark"] .eyebrow {
  border-color: var(--paper-line);
  color: var(--paper-soft);
}

/* Olive detail: a nested eyebrow (inside a card, one level down from a
   section heading) gets an olive marker dot instead of brass, so the
   accent hierarchy quietly signals primary vs secondary label. Used
   sparingly, not a swap-out of the eyebrow pattern generally. */
.eyebrow--quiet::before {
  background: var(--olive);
}

/* Micro-delight: the eyebrow's accent square blinks once, the moment
   its eyebrow enters view via the reveal system. Transform + opacity
   only, plays once (no iteration), and is skipped entirely under
   reduced motion. */
.eyebrow.reveal.is-in::before {
  animation: eyebrow-blink 0.9s var(--ease-reveal) 0.15s both;
}
@keyframes eyebrow-blink {
  0% { opacity: 0.3; transform: scale(0.55); }
  45% { opacity: 1; transform: scale(1.2); }
  100% { opacity: 1; transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .eyebrow.reveal.is-in::before { animation: none; }
}

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.85rem 1.6rem;
  border-radius: var(--radius-pill);
  font-family: var(--sans);
  font-size: 0.95rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  transition: transform 0.35s var(--ease-reveal), background 0.25s ease, color 0.25s ease, box-shadow 0.35s var(--ease-reveal);
}

/* Hover lift + shadow deepen: the button rises slightly and a soft
   shadow grows underneath it. Dark-tone sections get a faint light
   glow instead of a dark shadow, since a dark shadow will not read
   against a near-black field. */
.btn:hover { transform: translateY(-2px); box-shadow: 0 12px 26px rgba(15, 15, 15, 0.14); }
[data-tone="dark"] .btn:hover { box-shadow: 0 12px 26px rgba(0, 0, 0, 0.35); }

.btn--dark {
  background: var(--ink);
  color: var(--paper);
}
.btn--dark:hover { background: #000; }

.btn--light {
  background: var(--paper);
  color: var(--ink);
}
.btn--light:hover { background: #fff; }

.btn--ghost {
  background: transparent;
  color: inherit;
  border: 1px solid var(--line);
}
[data-tone="dark"] .btn--ghost { border-color: var(--paper-line); }

.link-quiet {
  color: var(--ink-soft);
  text-decoration: underline;
  text-decoration-color: currentColor;
  text-underline-offset: 3px;
  font-size: 0.95rem;
  transition: color 0.25s ease, text-decoration-color 0.25s ease, text-underline-offset 0.25s var(--ease-reveal);
}
[data-tone="dark"] .link-quiet { color: var(--paper-soft); }
/* Olive detail: on hover/focus the underline turns olive and draws out
   slightly, while the letterforms keep their existing brass hover (link
   hovers are one of brass's sanctioned small uses per the design spec).
   A quiet two-tone hover, not a second accent competing with brass. */
.link-quiet:hover,
.link-quiet:focus-visible { color: var(--accent); text-decoration-color: var(--olive); text-underline-offset: 5px; }

/* ---------- Containers and section rhythm ---------- */

.container {
  max-width: var(--container);
  margin: 0 auto;
  padding-left: var(--pad-x);
  padding-right: var(--pad-x);
}

.container-narrow {
  max-width: var(--container-narrow);
  margin: 0 auto;
  padding-left: var(--pad-x);
  padding-right: var(--pad-x);
}

.section {
  padding-top: var(--section-pad);
  padding-bottom: var(--section-pad);
}

.section--tight { padding-top: 4rem; padding-bottom: 4rem; }

[data-tone="dark"] { background: var(--bg-black); color: var(--paper); }
[data-tone="dark"] .body-lg,
[data-tone="dark"] p { color: var(--paper-soft); }

.section-head {
  max-width: 40rem;
  margin: 0 auto 3.5rem;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.1rem;
}

.section-head--left {
  margin-left: 0;
  text-align: left;
  align-items: flex-start;
}

/* A .section-head that is not the first thing in its section: used
   where several eyebrow-labelled groups run inside one shared section
   (index.html round 1B: Therapies, Consultations, Packages read as one
   continuous block, "separated only by the small floating titles"), so
   each group after the first needs its own top spacing instead of
   inheriting the section's own top padding. 3.5rem split the difference
   of the "roughly 3 to 4rem between groups" brief. */
.section-head--grouped {
  margin-top: 3.5rem;
}

.section-head p.body-lg { color: var(--ink-soft); }
[data-tone="dark"] .section-head p.body-lg { color: var(--paper-soft); }

/* Inset rounded card bands (hero, footer, cream band) */

.inset-card {
  margin: 0.75rem;
  border-radius: var(--radius-lg);
  overflow: hidden;
}

@media (min-width: 640px) {
  .inset-card { margin: 1rem; }
}

.field-dark { background: var(--bg-black); color: var(--paper); }
.field-cream { background: var(--bg-cream); color: var(--ink); }

/* ---------- Nav ---------- */

/* Adaptive nav: wide open on the hero, consolidates into the capsule on
   scroll. Ported from Option 3 (site/src/components/nav.css); see
   app.js's initNav for the behaviour and HANDOFF notes for why.

   The trick that makes the animation cheap: shape and paint are separate.
   border-radius stays var(--radius-pill) THE WHOLE TIME, in both states.
   The open state simply has no visible pill because its background and
   border are transparent, so the row reads as a plain full-width bar even
   though it is, technically, a very wide invisible pill. Only max-width,
   background and backdrop-filter change on scroll; padding and shape do
   not, so nothing reflows around the wordmark or button. max-width IS a
   layout property and animating one is normally wrong, but it is
   justified here exactly as it was in Option 3: it fires once on a
   discrete threshold crossing (JS toggles .stuck at scrollY > 80), not
   per scroll frame. */
.nav {
  position: fixed;
  top: 1rem;
  left: 0;
  right: 0;
  z-index: 100;
  display: flex;
  justify-content: center;
  padding: 0 1rem;
}

.nav-capsule {
  width: 100%;
  max-width: min(78rem, 100%);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 0.65rem 0.65rem 0.65rem 1.4rem;
  border-radius: var(--radius-pill);
  background: transparent;
  transition: background 380ms ease,
              backdrop-filter 380ms ease,
              max-width 480ms var(--ease-reveal);
}

.nav.stuck .nav-capsule {
  max-width: min(64rem, calc(100% - 2rem));
  background: rgba(20, 20, 20, 0.55);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}

@media (prefers-reduced-motion: reduce) {
  .nav,
  .nav-capsule,
  .nav-mark,
  .nav-links a,
  .nav-cta { transition: none; }
}

/* Text and button colour: two "grounds" the nav can sit on, independent
   of the open/stuck shape above. Default is ink on a light hero (the
   common case: index, services, booking all open on a light field). The
   stuck capsule is always a dark glass pill, so it always reads paper,
   regardless of what is under it. A page whose FIRST section is dark
   (service-longevity-assessment.html's hero-service) carries
   data-open-tone="dark" on <nav> so its open state also reads paper,
   the same way Option 3's app.js flips .on-dark by reading the section
   under the pill, except here it is fixed per page rather than tracked
   on scroll, because the open state never travels: it only ever sits on
   the page's own first section. */
.nav-mark {
  font-size: 1.15rem;
  color: var(--ink);
  text-decoration: none;
  flex: none;
  display: inline-flex;
  align-items: center;
  /* No gap here: the emblem/wordmark spacing lives on the wordmark's own
     margin-left below (see the fade rules further down this file), so
     the fade has a margin it can transition to zero alongside max-width
     instead of a fixed flex gap it cannot animate away. */
  transition: opacity 0.3s ease, color 0.3s ease;
}
.nav-mark:hover,
.nav-mark:focus-visible { opacity: 0.72; }

/* Brand logotype SVG, sized off the .nav-mark font-size so it tracks the
   1.15rem / 1rem responsive step below and fill="currentColor" (set on
   the SVG root, inherited by every path) follows whichever ink/paper
   tone the adaptive header currently reads. Ratio locked to the source
   mark's own viewBox (915.73 x 68.35).

   Two svgs live inside .nav-mark: the full wordmark and the emblem
   (M+H monogram, viewBox 412.26 x 276.79), emblem first in source order.
   At the top of the page (not .stuck) both show side by side, emblem
   then wordmark, joined by the 0.6em gap set on .nav-mark above so they
   stay vertically aligned on the shared inline-flex baseline. Once the
   nav consolidates into the stuck capsule the wordmark hides and only
   the emblem remains, same as the same 900px breakpoint the nav already
   collapses .nav-links at, where the capsule has the least room to
   spare. */
.nav-mark svg {
  display: block;
  height: 0.72em;
  width: auto;
}
/* The toggle selectors below are deliberately scoped through .nav-mark
   (two classes, not one) so they always outrank the single-class
   ".nav-mark svg" default above regardless of source order; a bare
   ".nav-mark-emblem { display: none }" has lower specificity than
   ".nav-mark svg" and would lose to it, leaving both svgs visible. */
/* The emblem is a much squarer mark than the wordmark (412x277 vs
   915x68), so at the shared wordmark height it read as a speck (Ryan,
   2026-08-26). It gets its own larger height instead, tuned to roughly
   match the wordmark's own cap height so the two sit together as one
   lockup rather than one dwarfing the other: still shorter than the
   Book pill, so the capsule's height never grows. */
.nav-mark .nav-mark-emblem { display: block; height: 1.55em; }

/* Wordmark fade, 2026-09-30 (design round 1B, item 4): the wordmark used
   to vanish outright the instant .stuck landed (display: none), a hard
   snap. Real fade instead: opacity, max-width and margin-left all
   transition together so the wordmark's own box folds away smoothly
   rather than blinking out. The gap between the two svgs used to come
   from .nav-mark's own `gap`; that is now 0 and the 0.6em is carried on
   the wordmark's margin-left instead, purely so it has something to
   transition to zero alongside max-width (same visual spacing at rest,
   nothing to look at differently before the first scroll).
   The emblem never moves: it is the FIRST svg in source order inside a
   flex-start row, so collapsing the second item's box, however it is
   collapsed, was never going to shift it. display: none is never used
   here, a collapsed max-width plus overflow: hidden reads the same to a
   pointer as gone. */
.nav-mark .nav-mark-word {
  overflow: hidden;
  opacity: 1;
  max-width: 12rem;
  margin-left: 0.6em;
  transition: opacity 0.28s var(--ease-reveal), max-width 0.28s var(--ease-reveal), margin-left 0.28s var(--ease-reveal);
}
.nav.stuck .nav-mark .nav-mark-word {
  opacity: 0;
  max-width: 0;
  margin-left: 0;
}
.nav.stuck .nav-mark .nav-mark-emblem { display: block; }
@media (max-width: 900px) {
  .nav-mark .nav-mark-word { display: none; }
  .nav-mark .nav-mark-emblem { display: block; }
}
@media (prefers-reduced-motion: reduce) {
  .nav-mark .nav-mark-word { transition: none; }
}

.nav-links {
  display: flex;
  align-items: center;
  gap: 1.75rem;
}

/* The sage underline is the current-page indicator only. It used to also
   draw in on hover, but that doubled up with the liquid-glass hover
   bubble below (client call 2026-08-26: bubble stays, hover line goes). */
.nav-links a {
  position: relative;
  color: var(--ink-soft);
  text-decoration: none;
  font-size: 0.92rem;
  transition: color 0.25s ease;
}
.nav-links a:hover { color: var(--ink); }

.nav-links a::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.35rem;
  height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.4s var(--ease-reveal);
}
/* Current-page indicator, shared by any page beyond index.html */
.nav-links a[aria-current="page"] {
  color: var(--ink);
}
.nav-links a[aria-current="page"]::after {
  transform: scaleX(1);
}
@media (prefers-reduced-motion: reduce) {
  .nav-links a::after { transition: none; }
}

/* Liquid glass hover bubble, 2026-08-26 client call: every nav link (not
   just the Book Consultation pill) gets a soft glass pill behind it on
   hover/focus-visible, so the row "pushes out a little bit" the way the
   CTA pill already does. Idle stays exactly as before: background and
   border are transparent, so there is no chrome to see until you hover.

   The padding + matching negative margin is the trick that makes this
   free: it grows each link's own hit area and paint box without moving
   its neighbours, since the negative margin gives the extra padding back
   to the shared `gap`. Nothing here touches layout at idle.

   Two grounds, one rule each: the light open header uses a dark-alpha
   glass (readable on the light hero field), the stuck dark capsule and
   any page whose open header sits on a dark first section use a
   white-alpha glass instead of colouring the link text sage, which the
   brand-book contrast cheat sheet already flags as failing on charcoal
   (3.63:1). Background/border/shadow only, no scale or transform, so the
   existing blanket `transition: none` under reduced motion above already
   makes this land instantly with no extra media query needed. */
.nav-links a {
  padding: 0.4rem 0.85rem;
  margin: -0.4rem -0.85rem;
  border-radius: var(--radius-pill);
  background: transparent;
  border: 1px solid transparent;
  box-shadow: none;
  transition: color 0.25s ease, background 220ms ease, border-color 220ms ease, box-shadow 220ms ease;
}
.nav-links a:hover,
.nav-links a:focus-visible {
  background: color-mix(in srgb, var(--ink) 6%, transparent);
  border-color: color-mix(in srgb, var(--ink) 10%, transparent);
  box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 55%, transparent), 0 6px 16px color-mix(in srgb, var(--ink) 10%, transparent);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.nav.stuck .nav-links a:hover,
.nav.stuck .nav-links a:focus-visible,
.nav[data-open-tone="dark"]:not(.stuck) .nav-links a:hover,
.nav[data-open-tone="dark"]:not(.stuck) .nav-links a:focus-visible {
  background: color-mix(in srgb, var(--paper) 16%, transparent);
  border-color: color-mix(in srgb, var(--paper) 26%, transparent);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--paper) 35%, transparent), 0 6px 18px rgba(0, 0, 0, 0.3);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

.nav-cta {
  flex: none;
  background: var(--ink);
  color: var(--paper);
}
.nav-cta:hover { background: #000; }

/* Dark ground: the stuck capsule (always dark glass) and any page whose
   open state sits on a dark first section share the same paper/light-pill
   treatment. Combined selector, one place to keep the two in sync. */
.nav.stuck .nav-mark,
.nav[data-open-tone="dark"]:not(.stuck) .nav-mark {
  color: var(--paper);
}
.nav.stuck .nav-links a,
.nav[data-open-tone="dark"]:not(.stuck) .nav-links a {
  color: var(--paper-soft);
}
.nav.stuck .nav-links a:hover,
.nav[data-open-tone="dark"]:not(.stuck) .nav-links a:hover {
  color: var(--paper);
}
.nav.stuck .nav-links a[aria-current="page"],
.nav[data-open-tone="dark"]:not(.stuck) .nav-links a[aria-current="page"] {
  color: var(--paper);
}
/* An ink button would vanish into a dark ground, so it inverts: paper
   pill, ink text, same idiom as .btn--light elsewhere on the page. */
.nav.stuck .nav-cta,
.nav[data-open-tone="dark"]:not(.stuck) .nav-cta {
  background: var(--paper);
  color: var(--ink);
}
.nav.stuck .nav-cta:hover,
.nav[data-open-tone="dark"]:not(.stuck) .nav-cta:hover {
  background: #fff;
}

/* Services dropdown: hover- and keyboard-driven only, no JS. .nav-dd
   wraps the existing "Services" link plus a .nav-dd-menu list; it is an
   ordinary flex item inside .nav-links (the menu itself is taken out of
   flow with position: absolute, so it never affects row layout or the
   1.75rem gap between the other links).

   Opens on :hover for a mouse and :focus-within for the keyboard, so
   tabbing onto the Services link (or into the menu itself) reveals it
   exactly as hovering does. The ::after bridge fills the 0.5rem gap
   between the link and the menu with a transparent, still-hoverable box
   so the mouse can travel diagonally from one to the other without the
   menu closing underneath it.

   Card surface is always the light --bg-card with dark ink text, on
   purpose, regardless of .nav.stuck or data-open-tone="dark": those
   states swap the SURROUNDING capsule to dark glass, but a dropdown
   menu is its own small card floating below it, not part of the
   capsule's own paint, so it keeps reading like every other plain-text
   surface on the page. */
.nav-dd {
  position: relative;
  display: inline-flex;
  align-items: center;
}
.nav-dd::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  height: 0.5rem;
  background: transparent;
}
.nav-dd-menu {
  position: absolute;
  top: calc(100% + 0.5rem);
  left: 0;
  z-index: 20;
  min-width: 14rem;
  margin: 0;
  padding: 0.4rem;
  list-style: none;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  box-shadow: 0 16px 32px rgba(24, 24, 24, 0.14);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateY(4px);
  transition: opacity 0.2s ease, transform 0.2s var(--ease-reveal), visibility 0s linear 0.2s;
}
.nav-dd:hover .nav-dd-menu,
.nav-dd:focus-within .nav-dd-menu {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translateY(0);
  transition: opacity 0.2s ease, transform 0.2s var(--ease-reveal);
}
@media (prefers-reduced-motion: reduce) {
  .nav-dd-menu { transition: opacity 0.15s ease, visibility 0s linear 0.15s; }
  .nav-dd:hover .nav-dd-menu,
  .nav-dd:focus-within .nav-dd-menu { transition: opacity 0.15s ease; transform: none; }
}
/* Reset every nav-links link treatment (glass hover bubble, negative
   margin, underline pseudo-element) back to a plain text list item;
   selector specificity (two nav-links/nav-dd-menu classes) beats the
   single-class ".nav-links a" rules above regardless of source order. */
.nav-links .nav-dd-menu a {
  position: static;
  display: block;
  padding: 0.55rem 1rem;
  margin: 0;
  border-radius: calc(var(--radius-md) - 6px);
  background: transparent;
  border-color: transparent;
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  color: var(--ink-soft);
  font-family: var(--sans);
  font-size: 0.9rem;
  white-space: nowrap;
  text-decoration: none;
}
.nav-links .nav-dd-menu a::after { content: none; }
.nav-links .nav-dd-menu a:hover,
.nav-links .nav-dd-menu a:focus-visible {
  color: var(--ink);
  background: color-mix(in srgb, var(--ink) 6%, transparent);
  border-color: transparent;
  box-shadow: none;
}
/* Keep the light-card/dark-text reading even inside the stuck dark
   capsule or a dark-open-tone header (see the block comment above). */
.nav.stuck .nav-links .nav-dd-menu a,
.nav[data-open-tone="dark"]:not(.stuck) .nav-links .nav-dd-menu a {
  color: var(--ink-soft);
}
.nav.stuck .nav-links .nav-dd-menu a:hover,
.nav.stuck .nav-links .nav-dd-menu a:focus-visible,
.nav[data-open-tone="dark"]:not(.stuck) .nav-links .nav-dd-menu a:hover,
.nav[data-open-tone="dark"]:not(.stuck) .nav-links .nav-dd-menu a:focus-visible {
  color: var(--ink);
  background: color-mix(in srgb, var(--ink) 6%, transparent);
}

@media (max-width: 900px) {
  .nav-links { display: none; }
  .nav-capsule { padding: 0.55rem 0.55rem 0.55rem 1.1rem; }
}

/* Round 1C: mobile nav. Below 900px .nav-links (Services, Patient
   journey, About, Team, Contact) simply disappears above, with nothing
   in its place, so a phone visitor has no way to reach any of those
   pages from the nav at all. .nav-toggle is a 44x44 hamburger button,
   hidden above 900px, sitting between .nav-links and .nav-cta in
   source order inside .nav-capsule (so, with .nav-links gone at this
   width, it lands immediately left of the Book pill); .nav-mobile-
   panel is a sibling of .nav-capsule, absolutely positioned the same
   way .nav-dd-menu positions itself off .nav-dd (top: 100% of its own
   positioned ancestor, here .nav itself since .nav-capsule is its only
   in-flow child and so IS .nav's own rendered height), left: 0 and
   right: 0 so it spans exactly .nav's own content box, i.e. flush with
   the capsule's edges, a true full-width panel rather than a narrower
   dropdown card. Same surface language as .nav-dd-menu further up
   (--bg-card, --line border, a card shadow) at a larger radius
   (--radius-lg, matching the capsule's own pill-adjacent scale rather
   than the smaller dropdown's --radius-md). All open/close/focus
   behaviour lives in app.js (initMobileNav); this file only ever
   toggles the .is-open class and [hidden] attribute JS already
   manages, it does not run either on its own. */
.nav-toggle {
  display: none;
  flex: none;
  width: 44px;
  height: 44px;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 5px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  padding: 0;
  cursor: pointer;
  transition: background 220ms ease, border-color 220ms ease;
}
.nav-toggle:hover,
.nav-toggle:focus-visible {
  background: color-mix(in srgb, var(--ink) 6%, transparent);
  border-color: color-mix(in srgb, var(--ink) 10%, transparent);
}
.nav-toggle-bar {
  display: block;
  width: 20px;
  height: 2px;
  border-radius: 2px;
  background: var(--ink);
  transition: transform 220ms var(--ease-reveal), opacity 180ms ease;
}
/* Dark ground (stuck capsule, or a page whose open header sits on a
   dark first section): same treatment as .nav-mark/.nav-links above. */
.nav.stuck .nav-toggle-bar,
.nav[data-open-tone="dark"]:not(.stuck) .nav-toggle-bar {
  background: var(--paper);
}
.nav.stuck .nav-toggle:hover,
.nav.stuck .nav-toggle:focus-visible,
.nav[data-open-tone="dark"]:not(.stuck) .nav-toggle:hover,
.nav[data-open-tone="dark"]:not(.stuck) .nav-toggle:focus-visible {
  background: color-mix(in srgb, var(--paper) 16%, transparent);
  border-color: color-mix(in srgb, var(--paper) 26%, transparent);
}
/* Open state: three bars fold into an X. app.js sets aria-expanded, no
   separate JS-owned class needed for this part. 5px gap + 2px bar
   height = 7px centre-to-centre, so the outer two bars travel exactly
   that far to meet the (now invisible) middle bar's former centre. */
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(2) {
  opacity: 0;
}
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

.nav-mobile-panel {
  position: absolute;
  top: calc(100% + 0.5rem);
  left: 0;
  right: 0;
  z-index: 99;
  max-height: calc(100vh - 7rem);
  overflow-y: auto;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: 0 24px 48px rgba(24, 24, 24, 0.18);
  padding: 0.5rem;
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity 220ms ease, transform 220ms var(--ease-reveal);
}
.nav-mobile-panel.is-open {
  opacity: 1;
  transform: translateY(0);
}
.nav-mobile-links {
  display: flex;
  flex-direction: column;
}
.nav-mobile-links > a,
.nav-mobile-dd > a {
  display: block;
  padding: 0.85rem 0.75rem;
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1rem;
  text-decoration: none;
  border-radius: var(--radius-md);
}
.nav-mobile-links > a:hover,
.nav-mobile-links > a:focus-visible,
.nav-mobile-dd > a:hover,
.nav-mobile-dd > a:focus-visible {
  background: color-mix(in srgb, var(--ink) 6%, transparent);
}
.nav-mobile-dd-menu {
  margin: 0 0 0.25rem;
  padding: 0;
  list-style: none;
}
.nav-mobile-dd-menu a {
  display: block;
  padding: 0.65rem 0.75rem 0.65rem 1.75rem;
  color: var(--ink-soft);
  font-family: var(--sans);
  font-size: 0.92rem;
  text-decoration: none;
  border-radius: var(--radius-md);
}
.nav-mobile-dd-menu a:hover,
.nav-mobile-dd-menu a:focus-visible {
  color: var(--ink);
  background: color-mix(in srgb, var(--ink) 6%, transparent);
}
.nav-mobile-cta {
  margin-top: 0.4rem;
  text-align: center;
  justify-content: center;
}
@media (max-width: 900px) {
  .nav-toggle { display: inline-flex; margin-left: auto; }
}
@media (prefers-reduced-motion: reduce) {
  .nav-toggle-bar,
  .nav-mobile-panel { transition: none; }
}

/* Stuck-nav-on-phones, same fix as Option 3's overrides.css: below 56rem
   the contracted max-width leaves too little room for the wordmark plus
   the booking pill, which pushes the button past the glass edge once
   scrolled. Full width below tablet, stuck state only (the open state at
   these widths is already effectively full width via min(78rem,100%)). */
@media (max-width: 56rem) {
  .nav.stuck .nav-capsule { max-width: 100%; }
}

/* Narrow-phone clearance, same reasoning as Option 3's overrides.css: the
   nowrap wordmark plus the button's min-content need more room than a
   390px viewport reliably gives once real copy (not "Modern Health") is
   swapped in. Tighten below 380px only; 390px and up are untouched. */
@media (max-width: 23.75rem) {
  .nav-capsule { gap: 1rem; padding-left: 1rem; }
  .nav-mark { font-size: 1rem; }
}

/* ---------- Cards ---------- */

.card-surface {
  background: var(--bg-card);
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
}

.hairline-row {
  border-top: 1px solid var(--line);
}
[data-tone="dark"] .hairline-row { border-top-color: var(--paper-line); }

/* ---------- Footer ---------- */

.footer {
  background: var(--bg-black);
  color: var(--paper-soft);
  border-radius: var(--radius-lg);
}

.footer-grid {
  display: grid;
  grid-template-columns: 1.1fr 1fr 1fr 1fr;
  gap: 2.5rem;
}

.footer-promo {
  background: linear-gradient(160deg, var(--accent-tint-deep), var(--accent));
  border-radius: var(--radius-md);
  padding: 2rem;
  color: var(--accent-ink);
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
  /* Centred rather than space-between: the CTA button that used to
     anchor the bottom of the card is gone (footer copy update,
     2026-09-16), so a single eyebrow+heading block now sits centred in
     the available min-height instead of pinned to the top with dead
     space below it. */
  justify-content: center;
  min-height: 12rem;
}

.footer h4 {
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--paper-faint);
  margin-bottom: 1rem;
}

.footer a:not(.btn) {
  display: block;
  color: var(--paper-soft);
  text-decoration: none;
  padding: 0.35rem 0;
  font-size: 0.95rem;
  transition: color 0.25s ease, transform 0.3s var(--ease-reveal);
}
.footer a:not(.btn):hover,
.footer a:not(.btn):focus-visible { color: var(--paper); transform: translateX(3px); }

/* Footer brand lockup: the design spec never carried a footer wordmark
   (only the nav did), so the brand-book swap adds one here, alongside
   the legal line rather than as its own divided row, reusing the
   existing hairline. Olive detail: the one hairline divider on the page
   that is not the neutral --line/--paper-line colour. Quiet, 1px, no
   background tint. */
.footer-bottom {
  margin-top: 3rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--olive);
  display: flex;
  align-items: flex-start;
  gap: 1.5rem;
  flex-wrap: wrap;
}
.footer-mark {
  flex: none;
  display: inline-flex;
  align-items: center;
  color: var(--paper);
  opacity: 0.9;
}
.footer-mark svg {
  display: block;
  height: 0.7rem;
  width: auto;
}
.footer-legal {
  margin: 0;
  font-size: 0.82rem;
  color: var(--paper-faint);
  max-width: 46rem;
  flex: 1 1 20rem;
}

@media (max-width: 900px) {
  .footer-grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 560px) {
  .footer-grid { grid-template-columns: 1fr; }
}

/* ---------- Photography bands ----------
   Shared full-bleed decorative photo band, used on index.html (kelp,
   45 to 55vh) and as a restrained variant on services.html and
   service-longevity-assessment.html (shore-mist, sea-swell). Always
   decorative: empty alt on the img, aria-hidden on the section, no text
   ever sits on top of it. */

.photo-band {
  position: relative;
  overflow: hidden;
  height: 50vh;
  min-height: 20rem;
  max-height: 34rem;
}
.photo-band img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.photo-band--sm {
  height: 38vh;
  min-height: 15rem;
  max-height: 24rem;
}
@media (max-width: 640px) {
  .photo-band { height: 42vh; min-height: 16rem; }
  .photo-band--sm { height: 30vh; min-height: 12rem; }
}

/* ---------- Reveal / motion ---------- */

.reveal {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 0.6s var(--ease-reveal), transform 0.6s var(--ease-reveal);
}

.reveal.is-in {
  opacity: 1;
  transform: translateY(0);
}

.reveal-1 { transition-delay: 0.05s; }
.reveal-2 { transition-delay: 0.12s; }
.reveal-3 { transition-delay: 0.19s; }
.reveal-4 { transition-delay: 0.26s; }

@media (prefers-reduced-motion: reduce) {
  .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* ---------- Responsive base ---------- */

@media (max-width: 900px) {
  .section { padding-top: var(--section-pad-mobile); padding-bottom: var(--section-pad-mobile); }
}

/* ---------- Dead-end link stubs ---------- */

.is-stub { cursor: default; pointer-events: none; opacity: 0.55; }

/* ---------- WhatsApp quick-contact pill ---------- */

.wa-fab {
  position: fixed;
  bottom: 1.4rem;
  right: 1.4rem;
  z-index: 9998;
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.7rem 1.1rem 0.7rem 0.75rem;
  border-radius: var(--radius-pill);
  background: var(--ink);
  color: var(--paper);
  font-family: var(--sans);
  font-weight: 600;
  font-size: 0.85rem;
  text-decoration: none;
  cursor: pointer;
  box-shadow: 0 12px 26px rgba(15, 15, 15, 0.14);
  transition: transform 0.3s var(--ease-reveal), box-shadow 0.3s var(--ease-reveal);
}

.wa-fab__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.15rem;
  height: 1.15rem;
  color: #25D366;
}

.wa-fab__icon svg {
  width: 100%;
  height: 100%;
}

.wa-fab__label {
  white-space: nowrap;
}

.wa-fab:hover {
  transform: translateY(-2px);
  box-shadow: 0 16px 34px rgba(0, 0, 0, 0.35);
}

.wa-fab:focus-visible {
  outline: 2px solid var(--paper);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  .wa-fab {
    transition: box-shadow 0.3s ease;
  }
  .wa-fab:hover {
    transform: none;
  }
}

@media (max-width: 820px) {
  .wa-fab {
    bottom: 5rem;
    right: 1rem;
  }
}
