/* ==========================================================================
   ELITE Sports Medicine — Typography System v2
   --------------------------------------------------------------------------
   Self-contained. Drop this file into any site and the whole system comes
   with it: fonts, colour, scale, spacing, motion, components.

   THREE FAMILIES, ONE JOB EACH
     Display  Instrument Serif (400 + italic) .. headlines; italic is the
                                                 accent voice
     Body     DM Sans (300-600) ............... all running text
     Labels   IBM Plex Mono (400/500) ......... eyebrows, nav, tags, captions
                                                uppercase, .14-.18em tracking

   The rules that carry the look:
     - Fluid sizing via clamp(); headlines run to 7rem against an 11px label,
       a ~10:1 display-to-label ratio
     - Tight display leading (.96) against generous body leading (1.6)
     - Measure capped in ch: body 52ch, headlines 16ch
     - Never pure black or pure white
     - Custom easing only, never ease/linear
   ========================================================================== */

/* Duplicate of the <link> in <head>, byte-identical so the browser serves it
   from cache. Present so the file works standalone when dropped elsewhere. */
@import url("https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=DM+Sans:opsz,wght@9..40,300;9..40,400;9..40,500;9..40,600&family=IBM+Plex+Mono:wght@400;500&display=swap");

/* --------------------------------------------------------------------------
   1. TOKENS
   -------------------------------------------------------------------------- */
:root {
  /* -- Families ---------------------------------------------------------- */
  --font-display: "Instrument Serif", "Iowan Old Style", Georgia, serif;
  --font-body: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* -- Colour ------------------------------------------------------------
     The brand palette, taken from the practice's live site (Elementor kit):
     navy #143D63, sky #72CEF3, pale #E5EBFA. Everything below is derived from
     those three and every pairing is measured, ratio noted against the ground
     it actually sits on.

     The --brass* names are historical: they are the accent slots, and 216
     call sites across the CSS and HTML read them. Renaming buys nothing and
     risks a lot, so the brand tokens below are the source of truth and the
     accent slots alias them.                                                */
  --brand-navy: #143D63;   /* practice navy — dark surfaces and primary text */
  --brand-sky:  #72CEF3;   /* practice sky  — fills, never small text on paper */
  --brand-pale: #E5EBFA;   /* practice pale — borders and tints             */

  --ink: var(--brand-navy);  /* 10.70:1 on paper */
  --ink-2: #1B5184;          /* raised surface on navy */
  --ink-3: #2165A4;          /* hairlines on navy */
  --ink-deep: #0D2840;       /* the deepest ground, under the footer         */

  /* Small accent text sits on paper, paper-2 and paper-3 alike, so the two
     accent tokens below are set against paper-3, the darkest of them. Tuned
     to --paper alone they measured 4.6:1 there but only 4.37:1 on paper-2,
     failing 1.4.3 on every eyebrow on the site. */
  --paper: #f8fafd;
  --paper-2: #eff4fb;
  --paper-3: var(--brand-pale);

  --brass: var(--brand-sky); /* FILL slot: 6.31:1 carrying a navy label      */
  --brass-ink: #0d729c;      /* 4.51:1 on paper-3, the darkest light ground  */
  --brass-lit: var(--brand-sky); /* 6.31:1 on navy — accent text over dark   */

  --body-on-paper: #1e5b94;  /* 6.74:1 */
  --muted-on-paper: #236db1; /* 4.52:1 on paper-3 */
  --body-on-ink: #becdf2;    /* 7.03:1 */
  --muted-on-ink: #8ba5e9;   /* 4.61:1 */

  --rule: rgba(20, 61, 99, 0.16);         /* hairline on paper */
  --rule-strong: rgba(20, 61, 99, 0.30);
  --rule-on-ink: rgba(229, 235, 250, 0.18);

  /* Context-aware pair. Sections flip these two and every component that
     reads them re-colours itself — no per-section overrides needed. */
  --fg: var(--ink);
  --fg-body: var(--body-on-paper);
  --fg-muted: var(--muted-on-paper);
  --bg: var(--paper);
  --accent: var(--brass-ink);   /* 4.61:1 on paper — reads as text and as icons */
  --accent-text: var(--brass-ink);
  --hairline: var(--rule);

  /* -- Type scale --------------------------------------------------------
     Fluid throughout. step-5 is the headline voice: 44px -> 112px.
     The reading steps (--2 through 3) were raised ~12% over the original
     spec for legibility; the display ceiling is unchanged, so the
     display-to-label ratio sits at ~8.9:1 rather than 10:1.               */
  --step--2: clamp(0.76rem, 0.735rem + 0.11vw, 0.79rem);  /* labels  ~12.6px */
  --step--1: clamp(0.92rem, 0.88rem + 0.16vw, 1.02rem);   /* captions       */
  --step-0:  clamp(1.12rem, 1.09rem + 0.16vw, 1.2rem);    /* body    ~19.2px */
  --step-1:  clamp(1.28rem, 1.2rem + 0.38vw, 1.55rem);    /* lede           */
  --step-2:  clamp(1.55rem, 1.37rem + 0.86vw, 2.2rem);    /* h3             */
  --step-3:  clamp(2.2rem, 1.76rem + 2.1vw, 3.7rem);      /* h2             */
  --step-4:  clamp(2.4rem, 1.85rem + 2.7vw, 4.6rem);      /* feature        */
  --step-5:  clamp(2.8rem, 2rem + 5.4vw, 7rem);           /* headline       */

  /* -- Leading & tracking ------------------------------------------------ */
  --lh-display: 0.96;
  --lh-heading: 1.05;
  --lh-body: 1.6;
  --lh-tight: 1.35;
  --tr-display: -0.01em;
  --tr-label: 0.16em;

  /* -- Measure ----------------------------------------------------------- */
  --measure: 52ch;
  --measure-display: 16ch;
  --measure-lede: 40ch;

  /* -- Space -------------------------------------------------------------
     A single scale. Section rhythm is fluid so density scales with the
     viewport instead of collapsing.                                        */
  --sp-3xs: 0.25rem;
  --sp-2xs: 0.5rem;
  --sp-xs: 0.75rem;
  --sp-sm: 1rem;
  --sp-md: 1.5rem;
  --sp-lg: 2.25rem;
  --sp-xl: 3.5rem;
  --sp-2xl: 5rem;
  --sp-section: clamp(3.25rem, 2.2rem + 3.6vw, 5.5rem);
  --sp-section-lg: clamp(4.5rem, 3rem + 5.5vw, 7.5rem);
  --gutter: clamp(1.25rem, 0.6rem + 3.2vw, 3.5rem);

  /* -- Structure --------------------------------------------------------- */
  --container: 1280px;
  --container-narrow: 860px;
  --radius: 2px;

  /* -- Motion ------------------------------------------------------------
     Custom curves only. Never ease, never linear.                          */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);        /* expo out — the house curve */
  --ease-quart: cubic-bezier(0.25, 1, 0.5, 1);  /* quart out — short moves    */
  --ease-inout: cubic-bezier(0.87, 0, 0.13, 1); /* expo in-out — travel       */
  --dur-fast: 0.28s;
  --dur: 0.5s;
  --dur-slow: 0.9s;

  /* -- Legacy aliases ----------------------------------------------------
     The pages carry inline styles from v1. These keep them coherent inside
     the new palette rather than leaving orphaned colours behind.           */
  --gold: var(--brass);
  --gold-bright: var(--brass-lit);
  --navy: var(--ink);
  --navy-2: var(--ink-2);
  --ink-soft: var(--ink-2);
  --steel: var(--body-on-paper);
  --steel-light: var(--muted-on-ink);
  --white: var(--paper);
  --line: var(--rule-on-ink);
  --line-dark: var(--rule);
}

/* Dark context. Any section that sets this flips every child component. */
.section--dark,
.cta-band,
.site-footer,
.hero--dark,
[data-tone="dark"] {
  --fg: var(--paper);
  --fg-body: var(--body-on-ink);
  --fg-muted: var(--muted-on-ink);
  --bg: var(--ink);
  --accent: var(--brass-lit);
  --accent-text: var(--brass-lit);
  --hairline: var(--rule-on-ink);
}

/* --------------------------------------------------------------------------
   2. BASE
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: 6rem;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--body-on-paper);
  font-family: var(--font-body);
  font-size: var(--step-0);
  font-weight: 400;
  line-height: var(--lh-body);
  font-optical-sizing: auto;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

img, svg, video { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; }

/* --------------------------------------------------------------------------
   3. TYPOGRAPHY
   -------------------------------------------------------------------------- */

/* Display — Instrument Serif. Tight leading, slight negative tracking, and a
   measure cap so a headline never runs past 16ch. */
h1, h2, h3, h4,
.display {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: var(--lh-display);
  letter-spacing: var(--tr-display);
  color: var(--fg);
  margin: 0 0 0.4em;
  text-wrap: balance;
  font-variant-ligatures: common-ligatures;
}

h1 { font-size: var(--step-5); max-width: var(--measure-display); }
h2 { font-size: var(--step-3); max-width: 18ch; line-height: var(--lh-heading); }
h3 { font-size: var(--step-2); max-width: 22ch; line-height: var(--lh-heading); }
h4 { font-size: var(--step-1); line-height: var(--lh-heading); }

/* Italic is the accent voice — the one place the display face changes colour. */
h1 em, h2 em, h3 em, .display em {
  font-style: italic;
  color: var(--accent);
  /* Instrument Serif italic sits marginally left; nudge it back optically. */
  margin-inline-start: 0.02em;
}

/* Body — DM Sans. Generous leading against the tight display, measure at 52ch. */
p {
  margin: 0 0 1.15em;
  max-width: var(--measure);
  color: var(--fg-body);
  text-wrap: pretty;
}
p:last-child { margin-bottom: 0; }

.lede {
  font-size: var(--step-1);
  font-weight: 300;
  line-height: 1.5;
  max-width: var(--measure-lede);
  color: var(--fg-body);
}

strong, b { font-weight: 600; color: var(--fg); }

/* Labels — IBM Plex Mono. Uppercase, wide tracking, small. The counterweight
   that makes the display type read as large. */
.eyebrow,
.label,
.faq-cat {
  display: inline-flex;
  align-items: center;
  gap: 0.85em;
  margin: 0 0 var(--sp-md);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--accent-text);
  max-width: none;
}
.eyebrow::before {
  content: "";
  width: clamp(20px, 3vw, 38px);
  height: 1px;
  background: currentColor;
  opacity: 0.65;
  flex: none;
}

/* --------------------------------------------------------------------------
   4. LAYOUT
   -------------------------------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* Section rhythm. Density is varied on purpose — --tight and --vast exist so
   the page breathes unevenly rather than marching at one interval. */
.section {
  position: relative;
  padding-block: var(--sp-section);
  background: var(--bg);
  color: var(--fg-body);
}
/* A section carries its own breathing room above and below. Where two meet,
   both paddings land in the same gap and it reads as a hole rather than a
   rhythm — the seam was 2x the interval everywhere. So a seam between two
   sections on the SAME ground collapses to roughly one interval; a seam where
   the ground changes keeps the full pair, because the colour change needs the
   room to land. */
.section + .section { padding-top: calc(var(--sp-section) * 0.4); }
.section + .section--dark,
.section + .section--paper2,
.section--dark + .section,
.section--paper2 + .section { padding-top: var(--sp-section); }

.section--tight { padding-block: clamp(2.25rem, 1.5rem + 2.6vw, 3.5rem); }
.section--vast { padding-block: var(--sp-section-lg); }
.section--dark { background: var(--ink); }
.section--paper2 { background: var(--paper-2); }
.section--ruled { border-top: 1px solid var(--hairline); }

/* Section heading block. Asymmetric by default — centred is the exception. */
.section-head {
  max-width: 46rem;
  margin: 0 0 clamp(2.5rem, 1.5rem + 3vw, 4.5rem);
}
.section-head p { color: var(--fg-muted); }
.section-head.center {
  margin-inline: auto;
  text-align: center;
}
.section-head.center h2 { margin-inline: auto; }
.section-head.center p { margin-inline: auto; }
.section-head.center .eyebrow { justify-content: center; }
.section-head.center .eyebrow::before { display: none; }

/* Narrower reading columns. Measure is controlled here, not per-page.
   Their left edge is pinned to the main grid rather than centred, so the type
   keeps one rag down the whole page instead of stepping inward after the hero. */
.container--reading { max-width: 47.5rem; }

/* Breadcrumbs. Generated from each page's BreadcrumbList so the visible trail
   and the structured data cannot disagree. */
.crumbs { margin-bottom: var(--sp-md); }
.crumbs ol {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5em;
  margin: 0;
  padding: 0;
  list-style: none;
}
.crumbs li { display: inline-flex; align-items: center; gap: 0.5em; }
.crumbs a, .crumbs span {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.crumbs a { color: var(--muted-on-paper); }
.crumbs a:hover, .crumbs a:focus-visible { color: var(--brass-ink); }
.crumbs [aria-current="page"] { color: var(--brass-ink); }
.crumbs svg { color: var(--hairline-strong, var(--hairline)); flex: none; }
.section--dark .crumbs a, .hero--dark .crumbs a { color: var(--body-on-ink); }

.container--narrow { max-width: 53rem; }
.container--reading,
.container--narrow {
  margin-inline-start: max(0px, calc((100% - var(--container)) / 2));
  margin-inline-end: auto;
}

/* Reading column with a sticky figure beside it. The rule above pins a reading
   column to the container's LEFT edge so body copy lines up under the hero h1.
   That alignment is the point, but it strands 600px of empty page at 1440 and
   840px at 1920. Where a page has its own image, it goes there: the column
   keeps its position and its measure, and the dead space carries the picture.
   The body column is 40.5rem rather than 47.5 because .container--reading spent
   two gutters of its 47.5 on padding — this keeps the same line length. */
.reading-figure {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
  display: grid;
  grid-template-columns: minmax(0, 40.5rem) minmax(0, 1fr);
  gap: clamp(2rem, 1rem + 3vw, 4.5rem);
}
.reading-figure__body { min-width: 0; }
/* The aside is the grid item and must STRETCH to the row's full height, because
   a sticky box can only travel inside its containing block. Sticking the grid
   item itself does nothing: its area is exactly its own height, so there is no
   room to move. The frame inside it is what sticks. */
.reading-figure__aside { min-width: 0; }
/* Selector is deliberately specific: .split-media sets position:relative and is
   declared later in this file, so a bare .reading-figure__frame loses the cascade
   at equal specificity and the figure silently stops sticking. */
.reading-figure__aside > .reading-figure__frame {
  position: sticky;
  top: 6.5rem;
  margin: 0;
}

@media (max-width: 62rem) {
  .reading-figure { grid-template-columns: minmax(0, 1fr); }
  /* Above the wall of text on a phone, not buried under it. */
  .reading-figure__aside { order: -1; margin-bottom: var(--sp-lg); }
  .reading-figure__aside > .reading-figure__frame { position: static; max-width: 26rem; }
}
@media (prefers-reduced-motion: reduce) {
  .reading-figure__aside > .reading-figure__frame { position: static; }
}

.grid { display: grid; gap: clamp(1.25rem, 0.8rem + 1.6vw, 2rem); }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }

/* Asymmetric split — the narrow column is the media, the wide one reads. */
.split {
  display: grid;
  grid-template-columns: 0.82fr 1.18fr;
  gap: clamp(2rem, 1rem + 4.5vw, 5.5rem);
  align-items: center;
}
.split-media {
  position: relative;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  border-radius: var(--radius);
  background: linear-gradient(160deg, var(--paper-3), var(--paper-2));
}
.split-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 1.2s var(--ease);
}
.split-media:hover img { transform: scale(1.03); }
/* Wide figures (diagrams) keep their native ratio instead of the 4:5 slab —
   cropping an annotated illustration loses its labels. */
.figure-wide {
  margin: var(--sp-lg) 0;
  border-radius: var(--radius);
  overflow: hidden;
}
.figure-wide img { display: block; width: 100%; height: auto; }

@media (max-width: 900px) {
  .grid--2, .grid--3 { grid-template-columns: 1fr; }
  .split { grid-template-columns: 1fr; gap: var(--sp-xl); }
  .split-media { max-width: 30rem; margin-inline: auto; }
}

/* --------------------------------------------------------------------------
   5. HEADER / NAV
   Ink on paper at rest; a paper bar with a hairline once scrolled. Nav items
   are mono labels, which is what keeps the header quiet under a 7rem headline.
   -------------------------------------------------------------------------- */
.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  padding-block: clamp(1rem, 0.6rem + 1.2vw, 1.6rem);
  color: var(--ink);
  transition: background var(--dur) var(--ease),
              padding var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease);
}
.site-header::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 1px;
  background: var(--rule);
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
}
.site-header.is-scrolled {
  background: rgba(248, 250, 253, 0.86);
  backdrop-filter: blur(14px) saturate(1.4);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  padding-block: 0.7rem;
}
.site-header.is-scrolled::after { opacity: 1; }
.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-lg);
}

.brand { display: flex; flex-direction: column; line-height: 1; color: var(--ink); }
/* The practice logo is drawn for a dark ground (sky + white on transparent),
   which is what the old site used. This header is paper, so the mark ships in
   two grounds and the header shows whichever matches the surface under it. */
.brand-logo { display: block; width: auto; height: clamp(1.6rem, 1.35rem + 1vw, 2.15rem); }
.brand-logo--on-dark { display: none; }
body[data-hero="media"] .site-header:not(.is-scrolled) .brand-logo--on-light { display: none; }
body[data-hero="media"] .site-header:not(.is-scrolled) .brand-logo--on-dark { display: block; }
.brand strong {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.15rem, 1rem + 0.55vw, 1.5rem);
  letter-spacing: 0;
  white-space: nowrap;
  color: var(--ink);
}
.brand span {
  margin-top: 0.5em;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 400;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--brass-ink);
}

.nav-desktop { display: flex; align-items: center; gap: clamp(1rem, 0.2rem + 1.5vw, 1.9rem); }
.nav-desktop a {
  position: relative;
  padding-block: 0.4em;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 400;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--ink);
}
.nav-desktop a::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 1px;
  background: var(--brass);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform var(--dur) var(--ease);
}
.nav-desktop a:hover::after,
.nav-desktop a:focus-visible::after { transform: scaleX(1); transform-origin: left; }

/* --- Services mega-menu -------------------------------------------------
   The trigger is a real <button>, so it works from the keyboard and reports
   its state; hover only mirrors what click/focus already does. */
.nav-has-mega { position: static; }
.nav-mega-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  padding: 0.4em 0;
  border: 0;
  background: none;
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink);
}
.nav-chev { transition: transform var(--dur) var(--ease); }
.nav-mega-toggle[aria-expanded="true"] .nav-chev { transform: rotate(180deg); }

.nav-mega {
  position: absolute;
  inset: 100% 0 auto 0;
  z-index: 120;
  padding: var(--sp-xl) var(--gutter) var(--sp-md);
  background: var(--paper);
  border-top: 1px solid var(--hairline);
  box-shadow: 0 24px 48px -28px rgba(20, 61, 99, 0.4);
}
.nav-mega[hidden] { display: none; }
.nav-mega-inner {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--sp-lg);
  max-width: var(--container);
  margin-inline: auto;
}
.mega-head {
  margin: 0 0 0.9em;
  padding-bottom: 0.6em;
  border-bottom: 1px solid var(--hairline);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brass-ink);
}
.nav-mega ul { margin: 0; padding: 0; list-style: none; }
.nav-mega li + li { margin-top: 0.55em; }
.nav-mega a {
  font-family: var(--font-body);
  font-size: var(--step--1);
  letter-spacing: 0;
  text-transform: none;
  color: var(--body-on-paper);
}
.nav-mega a:hover, .nav-mega a:focus-visible { color: var(--brass-ink); }
.nav-mega-foot {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-lg);
  max-width: var(--container);
  margin: var(--sp-lg) auto 0;
  padding-top: var(--sp-md);
  border-top: 1px solid var(--hairline);
}
.nav-mega-foot a {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--brass-ink);
}

/* --- Mobile services group ---------------------------------------------- */
.m-group-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  font: inherit;
  color: inherit;
  text-align: left;
}
.m-group-toggle[aria-expanded="true"] .nav-chev { transform: rotate(180deg); }
.m-group-panel[hidden] { display: none; }
.m-group-panel {
  padding: var(--sp-sm) 0 var(--sp-sm) var(--sp-md);
  border-left: 1px solid var(--hairline);
  margin-block: var(--sp-sm);
}
.m-sub-head {
  margin: var(--sp-md) 0 0.5em;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brass-ink);
}
.m-group-panel a { display: block; padding-block: 0.42em; font-size: var(--step--1); }


.nav-cta { display: flex; align-items: center; gap: clamp(0.75rem, 0.3rem + 1vw, 1.5rem); }
/* The header CTA must never wrap — a two-line button doubles the header height
   and shoves the hero down. Padding tightens before the label breaks. */
.nav-cta .btn {
  white-space: nowrap;
  padding-inline: clamp(1rem, 0.3rem + 1.1vw, 1.75rem);
}
.nav-phone {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.1em;
  color: var(--ink);
  white-space: nowrap;
}
.nav-phone svg { flex: none; color: var(--brass-ink); }

.nav-toggle {
  display: none;
  flex-direction: column;
  gap: 5px;
  padding: 0.5rem;
  background: none;
  border: none;
  cursor: pointer;
}
.nav-toggle span {
  width: 26px; height: 1.5px;
  background: var(--ink);
  transition: transform var(--dur-fast) var(--ease-quart), opacity var(--dur-fast);
}
.nav-toggle[aria-expanded="true"] span { background: var(--paper); }
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

@media (max-width: 980px) {
  .nav-desktop { display: none; }
  .nav-cta .btn { display: none; }
  .nav-toggle { display: flex; position: relative; z-index: 101; }
  /* The desktop gap plus a full-width brand pushed the menu button past the
     right edge of every phone — it was unreachable, so the menu could not be
     opened at all. Tighten the gap and let the brand shrink. */
  .site-header .container { gap: var(--sp-sm); }
  .brand { min-width: 0; }
  .brand strong { font-size: clamp(0.95rem, 0.6rem + 1.6vw, 1.25rem); }
  .brand span { white-space: nowrap; }
}

@media (max-width: 560px) {
  /* Brand + full phone number + menu button do not fit together on a phone.
     The header keeps a one-tap call target (the icon, labelled for screen
     readers) and the digits stay in the menu and the footer. */
  .nav-phone-label { display: none; }
  .nav-phone {
    justify-content: center;
    gap: 0;
    min-width: 44px;
    min-height: 44px;
  }
}

/* Mobile nav. Hidden with visibility + inert-style pointer handling, not by
   transform alone — an off-screen-but-visible panel still takes tab focus and
   still widens the document. */
.mobile-nav {
  position: fixed;
  inset: 0;
  z-index: 99;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.25rem;
  padding: 6.5rem var(--gutter) 3rem;
  background: var(--ink);
  transform: translateX(100%);
  visibility: hidden;
  pointer-events: none;
  overflow-y: auto;
  transition: transform var(--dur-slow) var(--ease),
              visibility 0s linear var(--dur-slow);
}
.mobile-nav.is-open {
  transform: translateX(0);
  visibility: visible;
  pointer-events: auto;
  transition: transform var(--dur-slow) var(--ease), visibility 0s;
}
.mobile-nav a {
  padding-block: 0.7rem;
  border-bottom: 1px solid var(--rule-on-ink);
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.75rem, 1.2rem + 2.8vw, 2.6rem);
  line-height: 1.15;
  color: var(--paper);
}
.mobile-nav a:last-of-type { border-bottom: 0; }

/* The Services row opens the submenu, so it is a control — but it sat at 29px
   because it inherits `font: inherit` rather than the drawer's own link
   treatment. Match the links beside it and hold the 44px touch minimum. */
.mobile-nav .m-group-toggle {
  padding-block: 0.7rem;
  min-height: 44px;
  border-bottom: 1px solid var(--rule-on-ink);
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.75rem, 1.2rem + 2.8vw, 2.6rem);
  line-height: 1.15;
  color: var(--paper);
}
.mobile-nav .m-group-toggle .nav-chev { flex: none; width: 0.5em; height: 0.5em; }
.mobile-nav .nav-phone {
  margin-top: var(--sp-lg);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  color: var(--brass-lit);
}

/* --------------------------------------------------------------------------
   6. HERO
   The signature moment. Paper, not dark — the headline is the whole image.
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 100vh;
  min-height: 100svh;
  padding-top: clamp(6rem, 4.5rem + 3.6vw, 7.75rem);
  padding-bottom: var(--sp-xl);
  background: var(--paper);
  color: var(--fg-body);
  overflow: clip;
}
/* Warm brass wash, top-right. Decorative only — nothing reads on top of it. */
.hero-glow {
  position: absolute;
  top: -18vw;
  right: -12vw;
  width: min(62vw, 780px);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(114, 206, 243, 0.16), rgba(114, 206, 243, 0) 68%);
  pointer-events: none;
  animation: heroDrift 18s var(--ease-inout) infinite alternate;
  will-change: transform;
}
@keyframes heroDrift {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(-3vw, 4vw, 0) scale(1.14); }
}
/* Hairline field, masked to a corner. Reads as a chart grid, not decoration. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(var(--rule) 1px, transparent 1px),
    linear-gradient(90deg, var(--rule) 1px, transparent 1px);
  background-size: clamp(48px, 6vw, 84px) clamp(48px, 6vw, 84px);
  -webkit-mask-image: radial-gradient(circle at 22% 18%, #000, transparent 62%);
  mask-image: radial-gradient(circle at 22% 18%, #000, transparent 62%);
  opacity: 0.75;
  pointer-events: none;
}
.hero > .container { position: relative; z-index: 1; }

/* --- Interior (service) hero ---------------------------------------------
   These were a pale slab carrying a bare h1 and one button: half a screen of
   near-empty porcelain with nothing to look at and nothing to read. The
   homepage already owns the photographic hero, so rather than repeat it (and
   re-download an image the article below already shows), the interior hero
   goes dark and typographic. The ink block also gives the porcelain article
   underneath an edge to start against.                                      */
.hero--dark { background: var(--ink); }
.hero--service {
  min-height: 0;
  padding-top: clamp(8rem, 6rem + 6vw, 11.5rem);
  padding-bottom: clamp(3.5rem, 2.5rem + 3.5vw, 5.5rem);
}
/* The base grid is drawn in --rule, which is tuned for paper and disappears
   on ink. Redraw it in the dark-context hairline and pull the mask to the
   headline's corner. */
.hero--service::before {
  background-image:
    linear-gradient(var(--rule-on-ink) 1px, transparent 1px),
    linear-gradient(90deg, var(--rule-on-ink) 1px, transparent 1px);
  -webkit-mask-image: radial-gradient(circle at 18% 12%, #000, transparent 58%);
  mask-image: radial-gradient(circle at 18% 12%, #000, transparent 58%);
  opacity: 0.9;
}
.hero--service .crumbs { margin-bottom: var(--sp-lg); }
.hero--service .crumbs a { color: var(--muted-on-ink); }
.hero--service .crumbs a:hover,
.hero--service .crumbs a:focus-visible { color: var(--brass-lit); }
.hero--service .crumbs [aria-current="page"] { color: var(--body-on-ink); }

/* A short accent rule above the headline, so the h1 starts from something
   rather than floating in the middle of the block. */
.hero-rule {
  width: 3.25rem;
  height: 2px;
  background: var(--brass-lit);
  margin-bottom: var(--sp-md);
}
.hero--service h1 { color: var(--paper); margin: 0; }
.hero--service .hero-lede {
  margin: var(--sp-md) 0 0;
  max-width: 46ch;
  font-size: var(--step-1);
  line-height: 1.5;
  color: var(--body-on-ink);
  text-wrap: pretty;
}
.hero--service .hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1rem;
  margin-top: var(--sp-lg);
}

.hero-grid {
  display: grid;
  grid-template-columns: 1.12fr 0.88fr;
  gap: clamp(2rem, 0.5rem + 5vw, 5rem);
  align-items: center;
}

/* Homepage hero. The headline takes the full measure of the container and the
   portrait becomes a vertical slab beside the supporting copy — the type is
   the image, so nothing is allowed to crop it into a narrow column. */

/* Header over a media hero. It is a sibling of <main>, so it cannot inherit the
   hero's dark context — body[data-hero="media"] carries that signal instead.
   Only while un-scrolled: .is-scrolled restores the paper bar and ink text. */
body[data-hero="media"] .site-header:not(.is-scrolled) {
  color: var(--paper);
  /* The header needs contrast against a 230-luma sky. Giving it its own
     backdrop confines that to the header strip, so the scrim above the
     footage can be lighter than it otherwise would have to be. */
  background: linear-gradient(to bottom,
    rgba(13, 40, 64, 0.88) 0%,
    rgba(13, 40, 64, 0.62) 55%,
    rgba(13, 40, 64, 0) 100%);
}
body[data-hero="media"] .site-header:not(.is-scrolled) .brand,
body[data-hero="media"] .site-header:not(.is-scrolled) .brand strong,
/* Direct children only. The mega-menu panel lives inside .nav-desktop but
   renders on its own paper-white background, so a blanket descendant
   selector painted every panel link white-on-white — the headings are
   <p> elements, so they stayed visible and the links vanished. */
body[data-hero="media"] .site-header:not(.is-scrolled) .nav-desktop > a,
body[data-hero="media"] .site-header:not(.is-scrolled) .nav-mega-toggle,
body[data-hero="media"] .site-header:not(.is-scrolled) .nav-phone {
  color: var(--paper);
}
body[data-hero="media"] .site-header:not(.is-scrolled) .brand span {
  color: var(--paper);
  opacity: 0.86;
}
body[data-hero="media"] .site-header:not(.is-scrolled) .nav-toggle span {
  background: var(--paper);
}
body[data-hero="media"] .site-header:not(.is-scrolled) .nav-desktop a::after {
  background: var(--brass-lit);
}

/* --- Scroll-linked section motion ----------------------------------------- */
/* Media wipes open from the bottom. Only applied once JS has added .wipe, so
   a no-JS page shows the image outright rather than a clipped sliver. */
.wipe {
  clip-path: inset(0 0 100% 0);
  transition: clip-path 1.1s var(--ease);
}
.wipe.is-wiped { clip-path: inset(0 0 0 0); }
.wipe img { transform: scale(1.06); transition: transform 1.4s var(--ease); }
.wipe.is-wiped img { transform: scale(1); }

/* Section headings settle rather than arrive. */
.section-head { will-change: transform; }

/* Cards gain depth on approach, not just on hover. */
.card {
  transition: transform var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease);
}
.card:hover, .card:focus-within {
  transform: translate3d(0, -5px, 0);
  border-color: var(--accent);
  box-shadow: 0 20px 44px -28px rgba(20, 61, 99, 0.5);
}

/* The section label sticks while its section passes, so the reader always
   knows which chapter they are in. Contained, not pinned scroll-jacking. */
.section-head.center { position: static; }

@media (prefers-reduced-motion: reduce) {
  .wipe, .wipe.is-wiped { clip-path: none; transition: none; }
  .wipe img, .wipe.is-wiped img { transform: none; transition: none; }
  .section-head { transform: none !important; }
  .card:hover, .card:focus-within { transform: none; }
}

/* --- Odometer numbers ----------------------------------------------------
   Each digit is a 0-9 column clipped to one line; the column slides so the
   right digit lands. Digits stagger, so the number assembles left to right. */
.odo { display: inline-flex; align-items: baseline; }
.odo-d {
  display: inline-block;
  overflow: hidden;
  height: 1em;
  line-height: 1;
  vertical-align: baseline;
}
.odo-strip { display: block; will-change: transform; }
.odo-strip > span {
  display: block;
  height: 1em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

/* --- Offices and catchment ------------------------------------------------
   Replaced a 3x2 grid of cards that were roughly 70% empty: a city name, a
   link, and a lot of nothing. The two real offices carry the weight now and
   the catchment is one compact row. */
.offices {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
  gap: clamp(1rem, 0.6rem + 1.4vw, 1.75rem);
}
.office {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding: clamp(1.4rem, 1rem + 1.4vw, 2.1rem);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--fg-body);
  transition: transform var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease);
}
.office:hover, .office:focus-visible {
  transform: translate3d(0, -4px, 0);
  border-color: var(--accent);
  box-shadow: 0 18px 40px -26px rgba(20, 61, 99, 0.55);
}
.office-tag {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent-text);
}
.office-city {
  font-family: var(--font-display);
  font-size: var(--step-2);
  line-height: 1.1;
  color: var(--fg);
}
.office-addr { font-size: var(--step--1); line-height: 1.5; }
.office-go {
  margin-top: 0.5rem;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent-text);
}
.office-go::after { content: "\2192"; display: inline-block; margin-left: 0.5em; transition: transform var(--dur) var(--ease); }
.office:hover .office-go::after { transform: translate3d(4px, 0, 0); }

.area-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.6rem 0.9rem;
  margin-top: clamp(1.5rem, 1rem + 1.6vw, 2.5rem);
  padding-top: var(--sp-md);
  border-top: 1px solid var(--hairline);
}
.area-row-label {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--fg-muted);
}
.area-row ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.area-row a {
  display: inline-block;
  padding: 0.38em 0.85em;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  font-size: var(--step--1);
  color: var(--fg-body);
  transition: border-color var(--dur-fast) var(--ease-quart),
              color var(--dur-fast) var(--ease-quart),
              transform var(--dur-fast) var(--ease-quart);
}
.area-row a:hover, .area-row a:focus-visible {
  border-color: var(--accent);
  color: var(--accent-text);
  transform: translate3d(0, -2px, 0);
}
.area-row-all { border-color: var(--accent); color: var(--accent-text); }

/* --- Motion: progress and header recession ------------------------------- */
.scroll-progress {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 300;
  height: 2px;
  background: var(--brand-sky);
  transform: scaleX(0);
  transform-origin: 0 50%;
  pointer-events: none;
}

.site-header { will-change: transform; }
.site-header.is-receded {
  transform: translate3d(0, -100%, 0);
  transition: transform var(--dur) var(--ease-inout),
              background var(--dur) var(--ease);
}

/* --- Hero with background footage -----------------------------------------
   Full-bleed video behind the hero. The poster carries the first paint, so the
   video is never in the critical path; main.js decides which rendition (or
   none) to load. .hero--dark already flips every child to the on-ink palette,
   so nothing here restates component colours. */
.hero--media {
  background: var(--ink-deep);
  align-items: flex-end;
  /* One screen wherever the copy fits — that is what keeps the sunset sky
     above it completely untouched. It is a floor, not a cage: locking height
     and max-height here clipped the eyebrow and the top of the headline clean
     off a 568px phone, because the copy is bottom-anchored and overflowed
     upward into `overflow: clip`. Let short screens grow instead. */
  min-height: 100svh;
  padding-top: clamp(5.5rem, 4.5rem + 3vw, 7rem);
}
/* The copy is anchored low, so the hero no longer needs to clear a portrait
   column and can sit at exactly one screen. */
.hero--media .hero-layout { padding-bottom: clamp(3.25rem, 2rem + 4vw, 5.5rem); }
/* The hairline grid and brass wash read as noise over footage. */
.hero--media::before { display: none; }
.hero--media .hero-glow { display: none; }

.hero-media {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}
.hero-video {
  width: 100%;
  /* Headroom for the parallax drift, so the frame never exposes an edge as it
     moves. Decorative footage only — nothing readable rides on this. */
  height: 118%;
  top: -9%;
  position: absolute;
  left: 0;
  object-fit: cover;
  will-change: transform;
  /* The poster is the same frame, so an unloaded video is not an empty box. */
  background: var(--ink) center / cover no-repeat;
}

/* Two gradients, not one: the horizontal pass protects the copy column, the
   vertical pass holds the header and the scroll cue. The footage is brightest
   in the top-left sky, which is exactly where the headline sits. */
.hero-scrim {
  position: absolute;
  inset: 0;
  /* A bottom band and nothing else — transparent above 34%, so the top third
     and a half of the frame carries no overlay at all.

     The values are tuned, not chosen: stepping the whole band down in
     increments and re-measuring contrast under the actual glyphs, 0.70 of the
     original is the lightest that still clears AA (headline 3.61, lede 4.98).
     This sits at 0.74 for a little margin. Sampling every other frame of the
     clip confirms the poster is as bright as the footage ever gets in the copy
     region, so the margin holds while it plays. */
  background-image:
    linear-gradient(to bottom,
      rgba(13, 40, 64, 0) 0%,
      rgba(13, 40, 64, 0) 34%,
      rgba(13, 40, 64, 0.25) 39%,
      rgba(13, 40, 64, 0.46) 45%,
      rgba(13, 40, 64, 0.52) 52%,
      rgba(13, 40, 64, 0.55) 66%,
      rgba(13, 40, 64, 0.64) 82%,
      rgba(13, 40, 64, 0.68) 100%);
}

/* The location line is small mono text sitting at the very top of the copy,
   where the band is deliberately still light. Rather than drag the gradient
   further up the frame for one label, it carries its own chip — the same
   language as the footage credit. */
.hero--media .eyebrow {
  display: inline-flex;
  align-items: center;
  align-self: start;
  width: auto;
  padding: 0.55em 0.9em;
  /* The chip wraps to two lines on a phone; the display line-height it
     inherits sets them almost touching. */
  line-height: 1.5;
  border-radius: 1.1em;
  background: rgba(13, 40, 64, 0.72);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: var(--paper);
}
.hero--media .eyebrow::before { display: none; }

/* Local contrast, so the wash can stay light. A tight shadow plus a wide soft
   one reads as depth rather than as a glow. */
.hero--media .hero-intro h1,
.hero--media .hero-lede,
.hero--media .hero-stats strong,
.hero--media .hero-stats span,
.hero--media .eyebrow {
  text-shadow: 0 1px 2px rgba(13, 40, 64, 0.55), 0 2px 22px rgba(13, 40, 64, 0.45);
}

/* Everything that is not the media layer sits above it. */
.hero--media > .container,
.hero--media > .scroll-cue { position: relative; z-index: 1; }

.hero-credit {
  position: absolute;
  z-index: 2;
  /* Clears the 58px assistant launcher, which is fixed in this same corner.
     Anchored to the first viewport, not the foot of the hero: on a short phone
     the hero grows past one screen and a bottom-anchored credit is stranded
     below the fold, which is the same trap .scroll-cue documents above. */
  right: calc(1.5rem + 58px + 0.75rem);
  top: calc(100svh - 2.9rem);
  bottom: auto;
  margin: 0;
  padding: 0.4em 0.75em;
  border-radius: 999px;
  background: rgba(13, 40, 64, 0.88);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(6px);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--paper);
}

/* Short viewports are the exception: there the copy genuinely does not fit one
   screen, so the first-screen line falls in the middle of it and the credit
   lands on a button. Anchor to the foot of the hero instead — it costs a short
   scroll, which is better than sitting on top of a call to action. Keyed to
   height, not width: it is the screen being short that causes this. */
@media (max-height: 700px) {
  .hero-credit { top: auto; bottom: 0.9rem; }
}

@media (max-width: 900px) {
  /* A portrait crop gives the copy proportionally more of the frame, so the
     ramp has to start earlier than it does on desktop. It still starts at
     zero: laying 0.58 over the top of the frame — as this rule used to —
     covered the sunset on exactly the devices most people arrive on, which is
     the opposite of the point. Measured under the real glyphs below. */
  .hero-scrim {
    background-image: linear-gradient(to bottom,
      rgba(13, 40, 64, 0) 0%,
      rgba(13, 40, 64, 0) 24%,
      rgba(13, 40, 64, 0.30) 32%,
      rgba(13, 40, 64, 0.52) 42%,
      rgba(13, 40, 64, 0.60) 55%,
      rgba(13, 40, 64, 0.66) 75%,
      rgba(13, 40, 64, 0.70) 100%);
  }
}

.hero-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  row-gap: clamp(1.25rem, 0.8rem + 1.6vw, 2.25rem);
  align-items: end;
  width: 100%;
}
.hero-intro { grid-column: 1 / -1; }
/* This headline is long (60 characters). At the full --step-5 ceiling it runs
   to five lines and pushes the call to action past the fold, so the homepage
   headline is sized to land in three lines and keep the hero within a viewport.
   Short headlines on the inner pages keep the full --step-5 ceiling. */
.hero .hero-intro h1 {
  max-width: none;
  margin-bottom: 0;
  font-size: clamp(2.6rem, 1.9rem + 4.3vw, 5.5rem);
}
.hero--media .hero-intro h1 {
  max-width: 17ch;
  font-size: clamp(1.9rem, 1.2rem + 2.4vw, 3.3rem);
  line-height: 1.04;
}
.hero--media .hero-lede {
  max-width: 40ch;
  font-size: var(--step-0);
  line-height: 1.45;
}
.hero--media .hero-layout { row-gap: clamp(0.75rem, 0.5rem + 0.9vw, 1.2rem); }
.hero--media .hero-actions { margin-top: clamp(0.5rem, 0.3rem + 0.6vw, 1rem); }
.hero--media .hero-stats {
  margin-top: clamp(1.25rem, 0.8rem + 1.4vw, 2rem);
  padding-top: var(--sp-md);
}
.hero-support { grid-column: 1; min-width: 0; }
.hero-support .hero-lede { max-width: 46ch; }
.hero-layout .hero-portrait {
  grid-column: 2;
  grid-row: 2;
  /* The portrait file is square (head to crossed arms). Matching the box to
     the image's own ratio shows the whole headshot instead of a letterboxed
     crop of the face; align-self start keeps the grid row from stretching it. */
  align-self: start;
  aspect-ratio: 1 / 1;
  height: auto;
  min-height: clamp(18rem, 12rem + 12vw, 24rem);
}
.hero-layout .hero-stats { margin-top: clamp(1.75rem, 1.2rem + 1.6vw, 2.75rem); }

@media (max-width: 900px) {
  .hero-layout { grid-template-columns: 1fr; }
  .hero-intro, .hero-support { grid-column: 1; }
  .hero-layout .hero-portrait {
    grid-column: 1;
    grid-row: auto;
    aspect-ratio: 1 / 1;
    height: auto;
    max-width: 26rem;
    margin-inline: auto;
  }
  .hero .hero-intro h1 { max-width: 14ch; font-size: clamp(2.6rem, 1.7rem + 5vw, 4rem); }
}

.hero h1 {
  margin-bottom: var(--sp-md);
  max-width: var(--measure-display);
  color: var(--fg);
}
.hero-lede {
  max-width: var(--measure-lede);
  font-size: var(--step-1);
  font-weight: 300;
  line-height: 1.5;
  color: var(--fg-body);
}
.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-sm);
  margin-top: var(--sp-lg);
}

/* Hero stats — mono labels under display numerals, divided by hairlines. */
.hero-stats {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(1.5rem, 0.5rem + 3vw, 3rem);
  margin-top: clamp(2.5rem, 1.5rem + 3vw, 4rem);
  padding-top: var(--sp-lg);
  border-top: 1px solid var(--rule);
}
.hero-stats div { display: flex; flex-direction: column; gap: 0.35rem; }
/* Desktop: three equal columns so the band never wraps to a 2+1 row at laptop
   widths — the mono labels wrap to two lines instead. Mobile keeps the
   content-sized wrap (stats stack there by design). */
@media (min-width: 901px) {
  .hero-stats > div { flex: 1 1 0; min-width: 0; }
}
.hero-stats div strong {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.95rem, 1.55rem + 1.35vw, 2.8rem);
  line-height: 1;
  letter-spacing: -0.01em;
  color: var(--brass-ink);
}
/* Direct child only — the counter <span> sits inside <strong> and must keep
   the display face, not the label face. */
.hero-stats div > span {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted-on-paper);
}

.hero-portrait {
  position: relative;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  border-radius: var(--radius);
  background: linear-gradient(160deg, var(--paper-3), var(--paper-2));
}
.hero-portrait img { width: 100%; height: 100%; object-fit: cover; }
/* Caption tag sits on the image, so it uses the over-dark brass. */
.hero-portrait .tag {
  position: absolute;
  left: 0; bottom: 0;
  padding: var(--sp-sm) var(--sp-md);
  background: rgba(20, 61, 99, 0.82);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  line-height: 1.5;
  color: var(--body-on-ink);
}
.hero-portrait .tag strong {
  display: block;
  margin-bottom: 0.25em;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.15rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--brass-lit);
}

@media (max-width: 900px) {
  .hero { min-height: auto; }
  /* ...except the media hero, which is a full-screen frame by design: the
     footage needs the height, and the credit is anchored to that first screen.
     Collapsing it to content height put the credit outside the hero's own
     `overflow: clip` and deleted it from the page on every phone. */
  .hero--media { min-height: 100svh; }
  .hero-grid { grid-template-columns: 1fr; }
  .hero-portrait { max-width: 26rem; margin-inline: auto; }
}

.scroll-cue {
  /* Anchored to the first viewport rather than the foot of the hero — the hero
     runs taller than the screen, so bottom-anchoring would strand it. */
  position: absolute;
  left: 50%;
  top: calc(100svh - 5.5rem);
  bottom: auto;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.7rem;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--fg-muted);
}
.scroll-cue::after {
  content: "";
  width: 1px; height: 36px;
  background: linear-gradient(var(--brass), transparent);
  animation: scrollCue 2s var(--ease-inout) infinite;
}
@keyframes scrollCue {
  0%   { opacity: 0; transform: scaleY(0.3); transform-origin: top; }
  40%  { opacity: 1; }
  100% { opacity: 0; transform: scaleY(1); transform-origin: top; }
}
@media (max-width: 900px) { .scroll-cue { display: none; } }

/* --------------------------------------------------------------------------
   7. BUTTONS
   Mono labels. --outline reads from --fg, so the same class works on paper
   and on ink without a variant per context.
   -------------------------------------------------------------------------- */
.btn {
  --btn-shift: 0px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6em;
  padding: 1.05em 2em;
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  line-height: 1;
  cursor: pointer;
  transform: translate3d(var(--btn-shift), 0, 0);
  transition: background var(--dur-fast) var(--ease-quart),
              color var(--dur-fast) var(--ease-quart),
              border-color var(--dur-fast) var(--ease-quart),
              transform var(--dur) var(--ease-quart);
}
.btn--gold { background: var(--brass); color: var(--ink); border-color: var(--brass); }
.btn--gold:hover { background: var(--brass-ink); border-color: var(--brass-ink); color: var(--paper); }

.btn--outline { background: transparent; color: var(--fg); border-color: var(--fg); }
.btn--outline:hover { background: var(--fg); color: var(--bg); }

.btn--outline-dark { background: transparent; color: var(--ink); border-color: var(--ink); }
.btn--outline-dark:hover { background: var(--ink); color: var(--paper); }

/* --------------------------------------------------------------------------
   8. CARDS
   -------------------------------------------------------------------------- */
.card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: clamp(1.75rem, 1.2rem + 1.6vw, 2.5rem);
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  transition: transform var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease);
}
.section:not(.section--dark) .card,
.section--paper2 .card { background: var(--paper); }
.section--dark .card { background: var(--ink-2); border-color: var(--rule-on-ink); }

.card::after {
  content: "";
  position: absolute;
  inset: auto 0 -1px 0;
  height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-slow) var(--ease);
}
.card:hover { transform: translateY(-5px); }
.card:hover::after { transform: scaleX(1); }

/* Index numeral — mono, not display. It is a label, so it reads as data. */
.card .num {
  display: block;
  margin-bottom: var(--sp-md);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.18em;
  color: var(--accent-text);
}
.card h3 { font-size: var(--step-2); margin-bottom: 0.5em; }
.card p { font-size: var(--step-0); color: var(--fg-body); }
.card .card-link {
  display: inline-flex;
  align-items: center;
  gap: 0.55em;
  margin-top: auto;
  padding-top: var(--sp-md);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-text);
}
.card .card-link svg { transition: transform var(--dur) var(--ease-quart); }
.card:hover .card-link svg { transform: translateX(6px); }

/* --------------------------------------------------------------------------
   9. STAT BAND / CREDENTIALS
   -------------------------------------------------------------------------- */
.stat-band {
  display: grid;
  /* Auto-fit rather than a fixed four: the homepage carries five stats, and a
     hard four-column track orphaned the fifth onto a row of its own beside
     three empty cells. This fills the row at any count. */
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: var(--sp-lg);
  padding-block: clamp(2rem, 1.4rem + 2vw, 3.25rem);
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
}
.stat-band .stat { display: flex; flex-direction: column; gap: 0.4rem; }
.stat-band .stat strong {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--step-3);
  line-height: 1;
  letter-spacing: -0.01em;
  color: var(--brass-ink);
}
.section--dark .stat-band .stat strong { color: var(--brass-lit); }
/* Direct child only — see the note on .hero-stats. */
.stat-band .stat > span {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  line-height: 1.5;
  color: var(--fg-muted);
}
@media (max-width: 860px) { .stat-band { grid-template-columns: repeat(2, 1fr); gap: var(--sp-md); } }

.credential-list {
  display: grid;
  gap: var(--sp-sm);
  margin-block: var(--sp-lg);
  padding: 0;
  list-style: none;
}
.credential-list li {
  display: flex;
  gap: 0.85rem;
  align-items: flex-start;
  max-width: var(--measure);
  font-size: var(--step--1);
  line-height: 1.55;
  color: var(--fg-body);
}
.credential-list svg { flex: none; margin-top: 0.28em; color: var(--accent); }

/* --------------------------------------------------------------------------
   10. TESTIMONIALS
   Quotes are set in the display face at lede size — the italic accent voice
   doing the emotional work the mono labels deliberately cannot.
   -------------------------------------------------------------------------- */
.quote-track { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(1.25rem, 0.8rem + 1.6vw, 2rem); }
@media (max-width: 900px) { .quote-track { grid-template-columns: 1fr; } }

.quote-card {
  display: flex;
  flex-direction: column;
  gap: var(--sp-md);
  padding: clamp(1.75rem, 1.2rem + 1.8vw, 2.75rem);
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
}
.quote-card .stars {
  font-size: 0.9rem;
  letter-spacing: 0.22em;
  color: var(--brass-ink);
}
.quote-card p {
  margin: 0;
  max-width: none;
  font-family: var(--font-display);
  font-weight: 400;
  font-style: italic;
  font-size: var(--step-2);
  line-height: 1.25;
  letter-spacing: -0.005em;
  color: var(--ink);
}
.quote-card footer {
  margin-top: auto;
  padding-top: var(--sp-xs);
  border-top: 1px solid var(--hairline);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink);
}
.quote-card footer span {
  display: block;
  margin-top: 0.4em;
  font-weight: 400;
  letter-spacing: 0.12em;
  color: var(--muted-on-paper);
}

/* --------------------------------------------------------------------------
   11. CTA BAND
   -------------------------------------------------------------------------- */
.cta-band {
  position: relative;
  padding-block: var(--sp-section);
  background: var(--ink);
  color: var(--body-on-ink);
  text-align: center;
  overflow: clip;
}
.cta-band::before {
  content: "";
  position: absolute;
  left: 50%; top: -40%;
  width: min(70vw, 900px);
  aspect-ratio: 1;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(circle, rgba(217, 166, 95, 0.13), transparent 66%);
  pointer-events: none;
}
.cta-band .container { position: relative; z-index: 1; }
.cta-band .eyebrow { justify-content: center; color: var(--brass-lit); }
.cta-band .eyebrow::before { display: none; }
.cta-band h2 {
  margin-inline: auto;
  max-width: 14ch;
  font-size: var(--step-4);
  color: var(--paper);
}
.cta-band p { margin-inline: auto; color: var(--body-on-ink); }
.cta-band .btn { margin: 0.4rem; }

/* --------------------------------------------------------------------------
   12. FOOTER
   -------------------------------------------------------------------------- */
.site-footer {
  padding: var(--sp-2xl) 0 var(--sp-lg);
  background: var(--ink);
  color: var(--body-on-ink);
}
.footer-grid {
  display: grid;
  grid-template-columns: 1.5fr 1fr 1.2fr 1fr;
  gap: clamp(2rem, 1rem + 3vw, 3.5rem);
  padding-bottom: var(--sp-xl);
  border-bottom: 1px solid var(--rule-on-ink);
}
@media (max-width: 900px) { .footer-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .footer-grid { grid-template-columns: 1fr; } }

.footer-logo { display: block; width: auto; height: 2.2rem; margin-bottom: var(--sp-sm); }
.footer-brand {
  display: block;
  margin-bottom: var(--sp-sm);
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.45rem;
  letter-spacing: 0;
  color: var(--paper);
}

.footer-grid p.foot-label {
  margin-bottom: var(--sp-md);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--brass-lit);
}
.footer-grid p { color: var(--body-on-ink); font-size: var(--step--1); }
.footer-grid ul {
  display: grid;
  gap: 0.7rem;
  margin: 0; padding: 0;
  list-style: none;
  font-size: var(--step--1);
  line-height: 1.5;
  color: var(--body-on-ink);
}
.footer-grid a { transition: color var(--dur-fast) var(--ease-quart); }
.footer-grid a:hover { color: var(--brass-lit); }

.footer-social { display: flex; gap: 0.75rem; }
.footer-social a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px; height: 40px;
  border: 1px solid var(--rule-on-ink);
  border-radius: 50%;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  color: var(--body-on-ink);
  transition: background var(--dur-fast) var(--ease-quart),
              border-color var(--dur-fast) var(--ease-quart),
              color var(--dur-fast) var(--ease-quart);
}
.footer-social a:hover { background: var(--brass); border-color: var(--brass); color: var(--ink); }

.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--sp-sm);
  padding-top: var(--sp-lg);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.1em;
  color: var(--muted-on-ink);
}
.footer-bottom a { color: var(--brass-lit); }

/* --------------------------------------------------------------------------
   13. FAQ
   -------------------------------------------------------------------------- */
.faq-list { border-top: 1px solid var(--hairline); }
.faq-item { border-bottom: 1px solid var(--hairline); }
.faq-q {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--sp-md);
  width: 100%;
  padding-block: clamp(1.25rem, 1rem + 0.8vw, 1.75rem);
  background: none;
  border: none;
  text-align: left;
  cursor: pointer;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--step-2);
  line-height: var(--lh-heading);
  letter-spacing: var(--tr-display);
  color: var(--ink);
  transition: color var(--dur-fast) var(--ease-quart);
}
.faq-q:hover { color: var(--brass-ink); }
.faq-q .plus { position: relative; flex: none; width: 20px; height: 20px; }
.faq-q .plus::before,
.faq-q .plus::after {
  content: "";
  position: absolute;
  background: var(--brass);
  transition: transform var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.faq-q .plus::before { left: 0; top: 50%; width: 100%; height: 1.5px; transform: translateY(-50%); }
.faq-q .plus::after { top: 0; left: 50%; width: 1.5px; height: 100%; transform: translateX(-50%); }
.faq-item.is-open .plus::after { transform: translateX(-50%) rotate(90deg); opacity: 0; }

.faq-a { max-height: 0; overflow: hidden; transition: max-height var(--dur) var(--ease); }
.faq-a p { padding-bottom: clamp(1.25rem, 1rem + 0.8vw, 1.75rem); margin: 0; }
.faq-item.is-open .faq-a { max-height: 40rem; }

.faq-cat { margin: var(--sp-xl) 0 var(--sp-sm); }
.faq-cat:first-child { margin-top: 0; }

/* --------------------------------------------------------------------------
   14. FORMS
   Nothing here is a browser default. Mono labels, hairline fields, a brass
   focus ring that is visible before it is pretty.
   -------------------------------------------------------------------------- */
input, select, textarea {
  width: 100%;
  padding: 0.95rem 1rem;
  background: var(--paper);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.4;
  color: var(--ink);
  transition: border-color var(--dur-fast) var(--ease-quart),
              box-shadow var(--dur-fast) var(--ease-quart);
}
input::placeholder, textarea::placeholder {
  color: var(--muted-on-paper);
  opacity: 0.85;
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--brass-ink);
  box-shadow: 0 0 0 3px rgba(114, 206, 243, 0.22);
}
textarea { resize: vertical; min-height: 8rem; }

/* A checkbox or radio is a glyph, not a field. The blanket width above is
   written for text inputs; left to apply here it stretches the control across
   the full row and shoves its own label past the edge of the screen. Scoped
   overrides existed for the form-page contexts but not for .form-consent, so
   the appointment page blew its layout out by 160px on every phone. Fix it
   once, at the type, rather than per context. */
input[type="checkbox"],
input[type="radio"] {
  width: 24px;
  height: 24px;
  min-height: 0;
  flex: none;
  padding: 0;
  accent-color: var(--brass-ink);
}

/* Field stack. Labels are visible mono, not placeholders — a placeholder
   disappears the moment someone starts typing. */
.form-stack {
  display: grid;
  gap: var(--sp-md);
  max-width: 34rem;
}
.field { display: grid; gap: 0; }
label {
  display: block;
  margin-bottom: 0.5rem;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted-on-paper);
}

/* Long-form patient forms (intake, consent, records request). */
.form-stack--wide { max-width: 44rem; }
/* Grid items default to min-width:auto, so a wide child (the history tables)
   would push the whole page wider instead of scrolling inside its own box. */
.form-stack > * { min-width: 0; }
.form-section {
  min-width: 0;
  padding-top: var(--sp-lg);
  margin-top: var(--sp-lg);
  border-top: 1px solid var(--hairline);
}
.form-section:first-child { padding-top: 0; margin-top: 0; border-top: none; }
.form-section h3 { margin-bottom: var(--sp-2xs); }
.form-section > p:first-of-type { margin-top: 0; }

.check-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 11rem), 1fr));
  gap: 0.6rem 1.25rem;
  margin: var(--sp-sm) 0;
  padding: 0;
  list-style: none;
}
.check-item, .radio-row {
  display: flex;
  align-items: center;
  gap: 0.55rem;
}
.check-item input[type="checkbox"],
.radio-row input[type="radio"] {
  width: 1.05rem;
  height: 1.05rem;
  flex: none;
  accent-color: var(--brass-ink);
}
.check-item label, .radio-row label {
  margin-bottom: 0;
  font-family: var(--font-body);
  font-size: var(--step--1);
  font-weight: 400;
  letter-spacing: normal;
  text-transform: none;
  color: var(--fg-body);
}
.radio-group { display: flex; flex-wrap: wrap; gap: 1.25rem; margin: var(--sp-2xs) 0 var(--sp-sm); }

.consent-box {
  padding: clamp(1.25rem, 1rem + 1vw, 1.75rem);
  margin: var(--sp-sm) 0;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  font-size: var(--step--1);
  color: var(--fg-body);
}
.consent-box p { margin: 0 0 0.85em; }
.consent-box p:last-child { margin-bottom: 0; }
.consent-box h3,
.consent-box h4 { margin: 0 0 0.5em; font-size: var(--step-0); }

.simple-table { width: 100%; border-collapse: collapse; margin: var(--sp-sm) 0; font-size: var(--step--1); }
.simple-table th, .simple-table td {
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--hairline);
  text-align: left;
}
.simple-table th {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted-on-paper);
  background: var(--paper-2);
}
.simple-table input, .simple-table select { padding: 0.55rem 0.65rem; font-size: var(--step--1); }

/* iOS Safari zooms the viewport when a focused field renders text under 16px,
   and leaves it zoomed. The compact sizes above are wanted on a wide screen;
   on a narrow one legibility and the zoom both argue for 16px. */
@media (max-width: 640px) {
  .simple-table input,
  .simple-table select { font-size: 1rem; }
}
/* Narrow screens scroll the table inside this wrapper rather than crushing
   the columns; the table keeps a usable minimum width. */
.table-scroll { max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
@media (max-width: 640px) { .simple-table { min-width: 32rem; } }

/* A table wider than the screen scrolls, but nothing on screen says so, and a
   column the patient never sees is a column they never fill in. */
.table-hint { display: none; }
@media (max-width: 640px) {
  .table-hint {
    display: flex;
    align-items: center;
    gap: 0.5em;
    margin: 0 0 0.6rem;
    font-family: var(--font-mono);
    font-size: var(--step--2);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--muted-on-paper);
  }
}

.field-note { margin: 0.4rem 0 0; font-size: var(--step--2); color: var(--muted-on-paper); }

/* --------------------------------------------------------------------------
   15. LOCATION / DIRECTIONS
   -------------------------------------------------------------------------- */
.directions-card {
  padding: clamp(1.5rem, 1.1rem + 1.4vw, 2.25rem);
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
}
.directions-card h3,
.directions-card h4 {
  margin-bottom: var(--sp-sm);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--brass-ink);
}
.directions-card ol {
  display: grid;
  gap: 0.6rem;
  margin: 0;
  padding-left: 1.15rem;
  font-size: var(--step--1);
  line-height: 1.55;
  color: var(--body-on-paper);
}
.map-embed {
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
}
.map-embed iframe { width: 100%; height: 100%; border: 0; }

/* --------------------------------------------------------------------------
   16. MOTION
   Every curve is custom. Nothing animates but transform and opacity.
   -------------------------------------------------------------------------- */

/* Scroll reveal */
.reveal { opacity: 1; }
.js .reveal {
  opacity: 0;
  transform: translate3d(0, 26px, 0);
  transition: opacity var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease);
}
.reveal.is-visible { opacity: 1; transform: translate3d(0, 0, 0); }
.reveal-stagger.is-visible > * { transition-delay: calc(var(--i, 0) * 90ms); }

/* Headline word stagger — words rise out of an overflow mask, one per beat. */
[data-split-words] { display: block; }
.word-wrap {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
  padding-bottom: 0.1em;
  /* A single word can be wider than a phone's content column — DOLORCLAST at
     the h1 size is. Without this the mask clips the last few pixels off it
     instead of letting it break. */
  max-width: 100%;
}
.word { display: inline-block; max-width: 100%; overflow-wrap: break-word; }
.js .word {
  display: inline-block;
  transform: translate3d(0, 115%, 0) rotate(3deg);
  transition: transform var(--dur-slow) var(--ease);
  will-change: transform;
}
[data-split-words].is-in .word { transform: translate3d(0, 0, 0) rotate(0deg); }

/* Counters — tabular figures so the number does not jitter as it climbs. */
[data-count] { display: inline-block; font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------------------------
   17. ACCESSIBILITY & DETAIL
   -------------------------------------------------------------------------- */
:focus-visible {
  outline: 2px solid var(--brass-ink);
  outline-offset: 3px;
  border-radius: 1px;
}
.section--dark :focus-visible,
.cta-band :focus-visible,
.site-footer :focus-visible,
.mobile-nav :focus-visible { outline-color: var(--brass-lit); }

::selection { background: var(--brass); color: var(--ink); }

.skip-link {
  /* Fixed, not absolute — an absolute skip link sits at the top of the
     document, so focusing it partway down the page scrolls it out of sight. */
  position: fixed;
  top: -60px; left: var(--gutter);
  z-index: 1000;
  padding: 0.85rem 1.4rem;
  background: var(--brass);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  transition: top var(--dur-fast) var(--ease-quart);
}
.skip-link:focus { top: 1rem; }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

.text-gold { color: var(--accent-text); }
.mt-0 { margin-top: 0; }

/* Honour the OS setting. Content must be complete without any of the above. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .reveal, .js .reveal { opacity: 1; transform: none; }
  /* Background footage holds still: no drift and no headroom, so the frame
     sits exactly where the poster did. The header stays put too. */
  .hero-video { height: 100%; top: 0; transform: none; }
  .site-header.is-receded { transform: none; }
  .word { transform: none; }
  .hero-glow { animation: none; }
}

/* --------------------------------------------------------------------------
   18. FRONT DESK ASSISTANT
   -------------------------------------------------------------------------- */
#ai-assistant-launcher {
  position: fixed;
  right: 1.5rem; bottom: 1.5rem;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 58px; height: 58px;
  border: none;
  border-radius: 50%;
  background: var(--brass);
  color: var(--ink);
  cursor: pointer;
  box-shadow: 0 14px 34px rgba(20, 61, 99, 0.28);
  transition: transform var(--dur) var(--ease-quart), background var(--dur-fast);
}
#ai-assistant-launcher:hover { transform: scale(1.06); background: var(--brass-ink); color: var(--paper); }

#ai-assistant-panel {
  position: fixed;
  right: 1.5rem; bottom: 5.5rem;
  z-index: 200;
  display: flex;
  flex-direction: column;
  width: min(380px, calc(100vw - 3rem));
  height: min(560px, calc(100vh - 9rem));
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: 0 30px 70px -22px rgba(20, 61, 99, 0.42);
  opacity: 0;
  transform: translate3d(0, 14px, 0) scale(0.98);
  pointer-events: none;
  visibility: hidden;
  transition: transform var(--dur) var(--ease), opacity var(--dur-fast) var(--ease),
              visibility 0s linear var(--dur);
}
#ai-assistant-panel.is-open {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1);
  pointer-events: auto;
  visibility: visible;
  transition: transform var(--dur) var(--ease), opacity var(--dur-fast) var(--ease), visibility 0s;
}
.ai-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1.1rem 1.25rem;
  background: var(--ink);
  color: var(--paper);
}
.ai-header strong { font-family: var(--font-display); font-weight: 400; font-size: 1.1rem; }
.ai-header span {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--brass-lit);
}
.ai-header button {
  background: none; border: none; cursor: pointer;
  font-size: 1.4rem; line-height: 1; color: var(--paper);
}
.ai-messages {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  padding: 1.15rem;
  overflow-y: auto;
}
.ai-msg {
  max-width: 88%;
  padding: 0.7rem 0.95rem;
  border-radius: var(--radius);
  font-size: 0.92rem;
  line-height: 1.5;
}
.ai-msg.bot { align-self: flex-start; background: var(--paper-2); color: var(--ink); }
.ai-msg.user { align-self: flex-end; background: var(--ink); color: var(--paper); }
.ai-msg.disclaimer {
  max-width: none;
  padding: 0 0.2rem;
  background: none;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  line-height: 1.6;
  letter-spacing: 0.04em;
  color: var(--muted-on-paper);
}
.ai-input-row {
  display: flex;
  gap: 0.5rem;
  padding: 0.75rem;
  border-top: 1px solid var(--rule);
}
.ai-input-row input { flex: 1; padding: 0.65rem 0.85rem; font-size: 0.92rem; }
/* Same 16px floor as the form fields: under it, iOS zooms on focus. */
@media (max-width: 640px) { .ai-input-row input { font-size: 1rem; } }
.ai-input-row button {
  padding-inline: 1.1rem;
  background: var(--brass);
  border: none;
  border-radius: var(--radius);
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink);
  transition: background var(--dur-fast) var(--ease-quart);
}
.ai-input-row button:hover { background: var(--brass-ink); color: var(--paper); }
.ai-typing { display: flex; gap: 4px; padding: 0.4rem 0; }
.ai-typing span {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--muted-on-paper);
  animation: aiType 1.1s var(--ease-inout) infinite;
}
.ai-typing span:nth-child(2) { animation-delay: 0.15s; }
.ai-typing span:nth-child(3) { animation-delay: 0.3s; }
@keyframes aiType {
  0%, 60%, 100% { transform: translateY(0); opacity: 0.4; }
  30% { transform: translateY(-4px); opacity: 1; }
}
/* ── Office card ────────────────────────────────────────────────────────────
   The practice's real NAP, on the office's own page. <address> is the correct
   element here and browsers italicise it by default, which fights the type
   system, so it is reset. */
.office-card {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  margin: var(--sp-md) 0;
  padding: var(--sp-md) var(--sp-lg);
  border-left: 2px solid var(--brass);
  background: var(--paper-2);
  border-radius: 0 var(--radius) var(--radius) 0;
  font-style: normal;
}
.office-card .office-street { font-size: var(--step-1); color: var(--ink); }
.office-card .office-city { color: var(--body-on-paper); }
.office-card .office-phone,
.office-card .office-email {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  color: var(--brass-ink);
}
.office-card .office-phone { margin-top: 0.4rem; }
.office-note {
  margin: 0 0 var(--sp-md);
  font-size: var(--step--1);
  color: var(--muted-on-paper);
}
/* Plain list of destination links — used where "Learn More" anchors would
   otherwise repeat the same wording down the page. */
.link-list {
  margin: var(--sp-md) 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
  gap: 0.55rem var(--sp-lg);
}
.link-list li { padding-left: 1rem; position: relative; }
.link-list li::before {
  content: "";
  position: absolute;
  left: 0; top: 0.72em;
  width: 0.4rem; height: 1px;
  background: var(--brass);
}

/* ── Touch targets ──────────────────────────────────────────────────────────
   Measured at 390px: the assistant's close button was 25x24, its send button
   and input 43px, the nav toggle 42x31, every .btn 40px, and every checkbox
   and radio 17x17. Apple's HIG asks 44pt and Material 48dp; WCAG 2.2 AA
   (2.5.8) sets the floor at 24x24 CSS px. */

/* Buttons carry the 44px floor. Padding is untouched so desktop proportions
   do not move — this only raises the ones that fell short. */
.btn { min-height: 44px; }

#ai-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  /* The glyph stays small; the hit area does not. */
  margin: -0.5rem -0.5rem -0.5rem 0;
}
.ai-input-row input,
.ai-input-row button { min-height: 44px; }

.nav-toggle {
  min-width: 44px;
  min-height: 44px;
  align-items: center;
  justify-content: center;
}

/* A 44px checkbox looks wrong, so the control takes WCAG's 24px minimum and
   the row around it carries the rest of the target: the label is clickable,
   so the effective tap area is the whole row. */
.check-item,
.check-grid label,
.consent-box label {
  display: flex;
  align-items: flex-start;
  gap: 0.65rem;
  min-height: 44px;
  padding-block: 0.35rem;
}
.check-item input[type="checkbox"],
.check-item input[type="radio"],
.check-grid input[type="checkbox"],
.check-grid input[type="radio"],
.consent-box input[type="checkbox"],
.consent-box input[type="radio"],
.form-section input[type="checkbox"],
.form-section input[type="radio"] {
  flex: none;
  width: 24px;
  height: 24px;
  margin-top: 0.1rem;
  accent-color: var(--brass-ink);
}

/* --------------------------------------------------------------------------
   19. LEGAL & COMPLIANCE ELEMENTS
   -------------------------------------------------------------------------- */
.notice-box {
  border: 1px solid var(--rule);
  border-left: 3px solid var(--brass-ink);
  background: var(--paper-2);
  border-radius: var(--radius);
  padding: var(--sp-md) var(--sp-lg);
  margin-block: var(--sp-md) var(--sp-lg);
}
.notice-box p { font-size: var(--step--1); line-height: 1.65; margin: 0; }

.form-note {
  font-size: var(--step--1);
  color: var(--muted-on-paper);
  max-width: 60ch;
}
.form-consent {
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
  max-width: 60ch;
  font-size: var(--step--1);
  line-height: 1.55;
  cursor: pointer;
}
.form-consent input { margin-top: 0.15em; flex-shrink: 0; }
/* This is a sentence someone has to read and agree to, not a field label. The
   mono/uppercase/tracked treatment above is for two-word labels; applied to 40
   words of consent copy it ran to eleven shouted lines on a phone. */
.form-consent,
.form-consent span {
  font-family: var(--font-body);
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--body-on-paper);
}

.footer-disclaimer p {
  font-size: var(--step--2);
  color: var(--body-on-ink);
  opacity: 0.75;
  max-width: 90ch;
  margin-top: var(--sp-lg);
}
.footer-legal {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.75rem;
  margin-top: var(--sp-sm);
}
.footer-legal a {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--body-on-ink);
  text-decoration: none;
}
.footer-legal a:hover { color: var(--brass-lit); }

@media print {
  .site-header, .mobile-nav, .site-footer, .scroll-cue, .hero-glow,
  #ai-assistant-launcher, #ai-assistant-panel, .notice-box, .cta-band { display: none !important; }
  .print-form input, .print-form textarea, .print-form select {
    border: 1px solid #999 !important;
    background: #fff !important;
  }
  body { background: #fff !important; color: #000 !important; }
}

/* --- Sister practices strip (footer, every page) ---------------------------
   Abacoa Podiatry & Leg Vein Center and RegenOrtho Palm Beach, which link back
   here from their own footers. Sits between .footer-grid and the disclaimer. */
.footer-sisters {
  padding: var(--sp-lg) 0;
  border-bottom: 1px solid var(--rule-on-ink);
}
.footer-sisters .foot-label {
  margin-bottom: var(--sp-sm);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--brass-lit);
}
.footer-sisters ul {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
  gap: 0.9rem clamp(2rem, 1rem + 3vw, 3.5rem);
  margin: 0; padding: 0;
  list-style: none;
  font-size: var(--step--1);
  line-height: 1.5;
}
.footer-sisters a { display: block; color: var(--body-on-ink); text-decoration: none; }
.footer-sisters strong { display: block; font-weight: 600; color: var(--paper); transition: color var(--dur-fast) var(--ease-quart); }
.footer-sisters a:hover strong { color: var(--brass-lit); }
