/* ==========================================================================
   Evara Dental Clinic — Lumina reference layout with the client's exact
   style-guide tokens, tuned to clear WCAG AA contrast.
   Noto Serif headlines, Hanken Grotesk body.
   ========================================================================== */

:root {
  /* color — client style guide, with text/icon values darkened to clear WCAG AA.
     Guide values kept verbatim wherever they are used as FILLS (dark content on
     top passes); darkened only where the color itself had to carry contrast. */
  --neutral:    #F8F9F8;   /* Neutral: page background (guide) */
  --sage:       #8FBAB6;   /* Primary: fills — buttons, pills, icon chips (guide) */
  --sage-hover: #7BA9A4;   /* Primary, pressed */
  --sage-ink:   #4F7873;   /* Primary, darkened: icons + stars that carry meaning */
  --gray:       #595959;   /* Secondary, darkened from #7A7A7A: body text */
  --beige:      #EAE4DA;   /* Tertiary: bands, portrait bg (guide) */
  --beige-deep: #DFD8CB;   /* darker tertiary: footer */
  --surface-alt:#F0F0ED;   /* treatments band */
  --white:      #FFFFFF;
  --dark:       #2C3937;   /* buttons / inverted, from the guide's primary button */
  --dark-hover: #202B29;
  --ink:        #222827;   /* headings */
  --line:       #E2E1DB;   /* decorative hairlines (cards, dividers) */
  --line-strong:#8E8E8E;   /* borders that identify a control (inputs, outline btn) */
  --error:      #A33B2A;
  --placeholder:#6B6B6B;

  /* type families — client style guide; not swapped. Metric-matched fallbacks
     (defined below) sit ahead of the system fonts to minimise load shift. */
  --font-display: "Spectral", "Spectral Fallback", Georgia, serif;
  --font-body: "Hanken Grotesk", "Hanken Fallback", "Segoe UI", system-ui, sans-serif;

  /* type scale — practical ramp anchored at 1rem/16px body, strong contrast at
     the display end. Only the two headline steps are fluid; everything else is
     fixed so the layout stays predictable. Semantic names, never by-value. */
  --text-xs:   0.8125rem;  /* 13px — uppercase pills + form labels */
  --text-sm:   0.875rem;   /* 14px — nav, captions, metadata, buttons */
  --text-base: 1rem;       /* 16px — body (WCAG floor; stops iOS input zoom) */
  --text-md:   1.125rem;   /* 18px — lead lines, pull quote */
  --text-lg:   1.25rem;    /* 20px — card headings */
  --text-xl:   1.5rem;     /* 24px — panel titles */
  --text-2xl:  clamp(2rem, 1.35rem + 2.6vw, 3rem);     /* section headings */
  --text-3xl:  clamp(2.5rem, 1.6rem + 3.6vw, 3.6rem);  /* hero */

  /* rhythm */
  --space-section: clamp(4rem, 9vw, 7rem);
  --container: 72rem;
  --radius: 12px;
  --radius-lg: 16px;

  /* z-index scale */
  --z-header: 10;
  --z-fab: 20;
  --z-skip: 100;

  /* motion — the clinic's promise is "unhurried", so everything decelerates
     into place and nothing overshoots. No bounce, no elastic, anywhere. */
  --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
  --ease-out-expo:  cubic-bezier(0.16, 1, 0.3, 1);
  --dur-press:  120ms;   /* presses and colour shifts: under the 80-150ms feel-instant band */
  --dur-state:  260ms;   /* hovers, focus rings, menu items */
  --dur-layout: 400ms;   /* menu open, card lift */
  --dur-enter:  700ms;   /* entrances, deliberately slow for a nervous audience */
}

/* Metric-matched fallbacks: hold the fallback close to the web font's box so
   text does not reflow when Noto Serif / Hanken Grotesk swap in. Values are
   approximate; tune with Fontaine if a measured CLS pass is ever run. */
@font-face {
  font-family: "Hanken Fallback";
  src: local("Segoe UI"), local("Arial");
  size-adjust: 105%;
  ascent-override: 90%;
  descent-override: 23.5%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Spectral Fallback";
  src: local("Georgia");
  size-adjust: 100%;
  ascent-override: 92%;
  descent-override: 24%;
  line-gap-override: 0%;
}

/* ---------- reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; }
img { max-width: 100%; display: block; }
/* <picture> is only a source selector; let the <img> lay out as if direct child */
picture { display: contents; }
h1, h2, h3, p, ul, ol, dl, figure, blockquote { margin: 0; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: 5rem;
}

body {
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.65;
  color: var(--gray);
  background: var(--neutral);
  -webkit-font-smoothing: antialiased;
  font-optical-sizing: auto;
  font-kerning: normal;
  text-rendering: optimizeLegibility;
}

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute;
  left: 0.75rem;
  top: -100%;
  z-index: var(--z-skip);
  padding: 0.75rem 1.25rem;
  background: var(--dark);
  color: var(--white);
  font-size: var(--text-sm);
  font-weight: 600;
  border-radius: 0 0 8px 8px;
  text-decoration: none;
}
.skip-link:focus { top: 0; }

.container {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 4vw, 2.5rem);
}

a { color: var(--dark); }

:focus-visible {
  outline: 3px solid var(--dark);
  outline-offset: 3px;
  border-radius: 2px;
}

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

/* ---------- type ---------- */
h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 500;
  color: var(--ink);
  line-height: 1.15;
  letter-spacing: -0.015em;
  text-wrap: balance;
}
h2 { font-size: var(--text-2xl); }
p { max-width: 66ch; text-wrap: pretty; }

.pill {
  display: inline-block;
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--dark);
  background: var(--sage);
  padding: 0.4rem 0.9rem;
  border-radius: 999px;
  margin-bottom: 1.1rem;
}

/* Section heads sit on the left edge with their introduction set beside the
   title, baseline to baseline, rather than a centred title over a centred
   line: the page reads down one strong left margin. */
.section-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 0.9rem clamp(2rem, 6vw, 5rem);
  align-items: end;
  margin-bottom: clamp(2.5rem, 6vw, 4rem);
}
.section-head:has(> :only-child) { grid-template-columns: 1fr; }
.section-head p { font-size: var(--text-md); }
@media (max-width: 860px) {
  .section-head { grid-template-columns: 1fr; }
}

/* One quiet kicker style, used sparingly where a role needs naming. */
.kicker {
  display: block;
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--sage-ink);
  margin-bottom: 0.75rem;
}

.arrow-link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 44px;            /* WCAG 2.5.5 tap target */
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--dark);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: gap var(--dur-state) var(--ease-out-quart), border-color var(--dur-state) var(--ease-out-quart);
}
.arrow-link svg { width: 1.05rem; height: 1.05rem; }
.arrow-link:hover { gap: 0.8rem; border-bottom-color: var(--dark); }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.8rem 1.6rem;
  border-radius: 8px;
  border: 1px solid transparent;
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--dur-state) var(--ease-out-quart),
              color var(--dur-state) var(--ease-out-quart),
              border-color var(--dur-state) var(--ease-out-quart),
              box-shadow var(--dur-state) var(--ease-out-quart),
              transform var(--dur-press) var(--ease-out-quart);
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(1px); transition-duration: var(--dur-press); }

.btn-primary {
  background: var(--sage);
  color: var(--dark);
}
.btn-primary:hover {
  background: var(--sage-hover);
  box-shadow: 0 6px 18px rgba(79, 120, 115, 0.28);
}

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

.btn-wide { width: 100%; }

/* ---------- shared media / split layouts ---------- */
.band-beige { background: var(--beige); }

.split-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(2.5rem, 6vw, 5rem);
  align-items: center;
}
.split-media img {
  width: 100%;
  height: auto;          /* let aspect-ratio win over the width/height attrs */
  border-radius: var(--radius-lg);
  aspect-ratio: 5 / 4;
  object-fit: cover;
}
@media (max-width: 860px) {
  .split-grid { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Header / navigation
   ========================================================================== */
.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  background: rgba(248, 249, 248, 0.92);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur-layout) var(--ease-out-quart),
              box-shadow var(--dur-layout) var(--ease-out-quart);
}
.site-header.scrolled {
  border-bottom-color: var(--line);
  box-shadow: 0 4px 20px rgba(34, 40, 39, 0.06);
}

.nav {
  max-width: var(--container);
  margin-inline: auto;
  padding: 0.9rem clamp(1.25rem, 4vw, 2.5rem);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.brand {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 600;
  color: var(--ink);
  text-decoration: none;
}

.nav-menu {
  display: flex;
  align-items: center;
  gap: 2rem;
}
.nav-links {
  display: flex;
  gap: 1.6rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.nav-links a {
  position: relative;
  color: var(--gray);
  text-decoration: none;
  font-size: var(--text-sm);
  font-weight: 500;
  padding-block: 0.35rem;
  transition: color var(--dur-state) var(--ease-out-quart);
}
.nav-links a:hover { color: var(--ink); }
.nav-links a.active { color: var(--dark); }

/* Underline grows from the left rather than blinking on. Desktop only:
   on mobile the links use a bottom border as a list divider. */
@media (min-width: 861px) {
  .nav-links a::after {
    content: "";
    position: absolute;
    inset: auto 0 0 0;
    height: 2px;
    background: var(--dark);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform var(--dur-state) var(--ease-out-quart);
  }
  .nav-links a:hover::after,
  .nav-links a.active::after { transform: scaleX(1); }
}
.nav-cta { padding: 0.6rem 1.25rem; font-size: var(--text-sm); }

.nav-toggle {
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 7px;
  width: 44px;                 /* WCAG 2.5.5 tap target */
  height: 44px;
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
}
.nav-toggle-bar {
  width: 26px;
  height: 2px;
  background: var(--ink);
  transition: transform var(--dur-state) var(--ease-out-quart);
}
/* NB: the button's last child is the sr-only label, not a bar, so these must
   target the bars by position among the bars themselves. */
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(1) { transform: translateY(4.5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(2) { transform: translateY(-4.5px) rotate(-45deg); }

@media (max-width: 860px) {
  .nav-toggle { display: flex; }
  .nav-menu {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 0.5rem 1.5rem 1.5rem;
    background: var(--neutral);
    border-bottom: 1px solid var(--line);
    display: none;
  }
  .nav-menu.open {
    display: flex;
    animation: menu-in var(--dur-layout) var(--ease-out-quart) both;
  }
  @keyframes menu-in {
    from { opacity: 0; transform: translateY(-10px); }
    to   { opacity: 1; transform: none; }
  }
  /* Each row arrives just after the panel, so the menu unfolds. */
  .nav-menu.open .nav-links li,
  .nav-menu.open .nav-cta {
    animation: rise 380ms var(--ease-out-quart) both;
    animation-delay: calc(90ms + var(--i, 0) * 45ms);
  }
  .nav-links { flex-direction: column; gap: 0; }
  .nav-links a {
    display: block;
    padding: 0.85rem 0;
    font-size: var(--text-base);
    border-bottom: 1px solid var(--line);
  }
  .nav-cta { margin-top: 1.25rem; }
}

/* ==========================================================================
   Hero — full-bleed video background with the copy overlaid on a warm scrim
   ========================================================================== */
.hero--video {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  min-height: min(84vh, 720px);
  padding-block: clamp(4rem, 10vh, 7rem);
}

.hero-bg { position: absolute; inset: 0; z-index: 0; }
.hero-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 72% center;   /* keep the subject framed as it crops */
}
/* Warm dark-green scrim, heaviest on the left where the copy sits, opening up
   on the right so the video reads through. A faint floor gradient anchors it. */
.hero-scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(95deg,
      rgba(28, 36, 34, 0.9) 0%,
      rgba(28, 36, 34, 0.74) 38%,
      rgba(28, 36, 34, 0.4) 66%,
      rgba(28, 36, 34, 0.22) 100%),
    linear-gradient(to top, rgba(28, 36, 34, 0.45), transparent 45%);
}

.hero--video .container { position: relative; z-index: 1; width: 100%; }
.hero--video .hero-copy { max-width: 40rem; }

/* Compact hero copy: the background video is the focus, so the headline is
   sized down from the display step and the supporting line stays to one row. */
.hero-copy h1 {
  font-size: var(--text-3xl);
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: -0.025em;
  color: var(--white);
}
.hero--video .hero-copy p {
  margin-top: 1rem;
  font-size: var(--text-md);
  max-width: 40ch;
  color: rgba(255, 255, 255, 0.92);
}
.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.8rem;
  margin-top: 2rem;
}
.hero-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 1.75rem;
  margin-top: 2.25rem;
}
.hero-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--white);
}
.hero-badge svg {
  width: 1.05rem;
  height: 1.05rem;
  color: var(--sage);   /* lighter sage reads on the dark scrim */
  flex-shrink: 0;
}

/* Outline button, light variant, for use over the video */
.btn-outline--light {
  color: var(--white);
  border-color: rgba(255, 255, 255, 0.6);
}
.btn-outline--light:hover {
  color: var(--white);
  border-color: var(--white);
  background: rgba(255, 255, 255, 0.12);
}

@media (max-width: 860px) {
  .hero--video {
    min-height: 78vh;
    align-items: flex-end;       /* copy sits low; the face reads up top */
    padding-bottom: clamp(2.5rem, 8vh, 4rem);
  }
  /* Heavier, bottom-weighted scrim so the overlaid copy stays legible when
     the video crops to centre and the subject sits behind the text. */
  .hero-scrim {
    background: linear-gradient(to top,
      rgba(28, 36, 34, 0.92) 0%,
      rgba(28, 36, 34, 0.7) 34%,
      rgba(28, 36, 34, 0.4) 62%,
      rgba(28, 36, 34, 0.3) 100%);
  }
}

/* ==========================================================================
   Philosophy
   ========================================================================== */
.philosophy { padding-block: var(--space-section); }
.philosophy .split-grid { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); align-items: start; }
.philosophy .split-media img { aspect-ratio: 4 / 5; }
.philosophy h2 { margin-bottom: 1.5rem; }
/* The first paragraph is the argument; set it as a serif lead so the three
   paragraphs read as a claim and its evidence, not as one grey block. */
.philosophy .split-copy > p:first-of-type {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  line-height: 1.45;
  color: var(--ink);
  margin-bottom: 1.5rem;
}
.philosophy p + p { margin-top: 0.9rem; }
.philosophy .arrow-link { margin-top: 1.6rem; }
@media (min-width: 861px) {
  .philosophy .split-copy { padding-top: clamp(1rem, 4vw, 3rem); }
}
@media (max-width: 860px) {
  .philosophy .split-grid { grid-template-columns: 1fr; }
  .philosophy .split-media img { aspect-ratio: 4 / 3; }
  .philosophy .split-copy > p:first-of-type { font-size: var(--text-lg); }
}

/* ==========================================================================
   A visit, step by step — five steps on one rail
   No cards, no icons: the sequence is the content, so the numerals and the
   rail carry it. Each step owns one segment of the rail (its top border on
   desktop, its left border on mobile); script.js writes --f (0 to 1) on each
   step as the visitor scrolls, and the segment fills. A step counts as
   "reached" once its segment starts filling.
   ========================================================================== */
.journey {
  padding-block: var(--space-section);
  background: var(--white);
}


.journey-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
}

.journey-step {
  --f: 1;                       /* fully drawn unless script.js says otherwise */
  position: relative;
  padding: 1.75rem clamp(1rem, 2.4vw, 2rem) 0 0;
}

/* The rail: a hairline, and on top of it the fill that grows with scroll. */
.journey-step::before,
.journey-step::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
}
.journey-step::before { background: var(--line); }
.journey-step::after {
  background: var(--sage-ink);
  transform: scaleX(var(--f));
  transform-origin: left center;
}

.journey-no {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(2.6rem, 1.8rem + 2.4vw, 3.75rem);
  line-height: 1;
  font-weight: 400;
  color: var(--sage-ink);
  margin-bottom: 1.1rem;
  font-variant-numeric: lining-nums;
  transition: color var(--dur-layout) var(--ease-out-quart);
}
.journey-step h3 {
  font-size: var(--text-lg);
  margin-bottom: 0.45rem;
}
.journey-step p {
  font-size: var(--text-base);
  transition: opacity var(--dur-layout) var(--ease-out-quart);
}

/* Unreached steps are drawn in outline, and only when the script is running
   the rail: without JS every step is simply fully visible. */
body.js .journey-step:not(.is-reached) .journey-no { color: #CFCDC5; }

@media (max-width: 900px) {
  .journey-steps { grid-template-columns: 1fr; }
  .journey-step {
    display: grid;
    grid-template-columns: 3.25rem minmax(0, 1fr);
    column-gap: 1rem;
    padding: 0 0 1.75rem 1.5rem;
  }
  .journey-step:last-child { padding-bottom: 0; }
  .journey-step::before,
  .journey-step::after {
    top: 0;
    bottom: 0;
    right: auto;
    width: 2px;
    height: auto;
  }
  .journey-step::after {
    transform: scaleY(var(--f));
    transform-origin: center top;
  }
  .journey-no {
    grid-row: span 2;
    font-size: 2.4rem;
    margin-bottom: 0;
  }
}

/* ---------- treatment pages: the same rail on the numbered process ----------
   The step numbers already sit in their own column; the rail runs down the
   left edge of each row and fills as that step is read. */
.steps[data-rail] li {
  --f: 1;
  position: relative;
  padding-left: 1.5rem;
}
.steps[data-rail] li::before,
.steps[data-rail] li::after {
  content: "";
  position: absolute;
  left: 0;
  top: 1.6rem;
  bottom: 0;
  width: 2px;
}
.steps[data-rail] li::before { background: rgba(255, 255, 255, 0.14); }
.steps[data-rail] li::after {
  background: var(--sage);
  transform: scaleY(var(--f));
  transform-origin: center top;
}
.steps[data-rail] .step-no { transition: color var(--dur-layout) var(--ease-out-quart); }
body.js .steps[data-rail] li:not(.is-reached) .step-no { color: rgba(255, 255, 255, 0.4); }

/* ==========================================================================
   Statement band — one dominant idea, set large on the dark green
   ========================================================================== */
.statement {
  padding-block: clamp(4.5rem, 11vw, 8rem);
  background: var(--dark);
  color: var(--white);
}
.statement-text {
  max-width: 44ch;
  margin-inline: auto;
  font-family: var(--font-display);
  font-size: clamp(1.65rem, 1.1rem + 2.2vw, 2.6rem);
  line-height: 1.3;
  letter-spacing: -0.01em;
  text-align: center;
  text-wrap: balance;
  color: var(--white);
}
.statement-by {
  max-width: none;
  margin: 1.75rem auto 0;
  text-align: center;
  font-size: var(--text-sm);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sage);
}
/* The page's one authored moment. The promise is about knowing what happens
   before it happens, so it is read into view: script.js wraps each word and
   writes --sp (0 to 1) as the band crosses the viewport, and the words ink in
   from faint to full in reading order, a couple of words ahead of each other.
   Fully visible by default, and fully inked under reduced motion. */
.statement-text .word { display: inline-block; }
@media (prefers-reduced-motion: no-preference) {
  body.js .statement-text[data-scrub] .word {
    opacity: clamp(0.18, calc(var(--sp, 1) * (var(--n, 1) + 3) - var(--w, 0)), 1);
  }
}

/* ==========================================================================
   FAQ — native details/summary, animated with grid-template-rows
   ========================================================================== */
.faq { padding-block: var(--space-section); }

/* Heading on the left, held in view while the questions scroll past it. */
.faq-layout {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: 2rem clamp(2rem, 6vw, 5rem);
  align-items: start;
}
.faq-layout > .section-head {
  grid-template-columns: 1fr;
  margin-bottom: 0;
}
.faq-layout > .section-head h2 { font-size: clamp(1.9rem, 1.3rem + 1.9vw, 2.5rem); }
@media (min-width: 861px) {
  .faq-layout > .section-head { position: sticky; top: 6.5rem; }
}
@media (max-width: 860px) {
  .faq-layout { grid-template-columns: 1fr; }
}

.faq-list {
  display: grid;
  border-top: 1px solid rgba(34, 40, 39, 0.16);
}
.faq-item {
  border-bottom: 1px solid rgba(34, 40, 39, 0.16);
}
.faq-item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding-block: 1.35rem;
  min-height: 44px;
  cursor: pointer;
  list-style: none;
  font-family: var(--font-display);
  font-size: var(--text-lg);
  line-height: 1.35;
  color: var(--ink);
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary:hover { color: var(--sage-ink); }

/* Plus that becomes a minus, drawn with two bars. */
.faq-mark {
  position: relative;
  flex-shrink: 0;
  width: 1.4rem;
  height: 1.4rem;
}
.faq-mark::before,
.faq-mark::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  height: 2px;
  border-radius: 2px;
  background: var(--sage-ink);
  transition: transform var(--dur-state) var(--ease-out-quart);
}
.faq-mark::after { transform: rotate(90deg); }
.faq-item[open] .faq-mark::after { transform: rotate(0deg); }

/* grid 0fr -> 1fr expands without animating height directly. */
.faq-answer {
  display: grid;
  grid-template-rows: 1fr;   /* open state; closed handled below */
}
.faq-answer > div { overflow: hidden; padding: 0 clamp(0rem, 4vw, 3rem) 1.5rem 0; }
.faq-answer p { font-size: var(--text-base); }
@media (prefers-reduced-motion: no-preference) {
  .faq-item:not([open]) .faq-answer { grid-template-rows: 0fr; }
  .faq-answer { transition: grid-template-rows var(--dur-layout) var(--ease-out-quart); }
}

/* ==========================================================================
   Lead dentist
   ========================================================================== */
.dentist { padding-block: var(--space-section); }
.dentist-card {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: clamp(2rem, 6vw, 5rem);
  align-items: center;
}
.dentist-portrait {
  position: relative;
  aspect-ratio: 4 / 5;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--beige);
}
.dentist-portrait img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.dentist-portrait img.missing { display: none; }
/* Nameplate: dark green, an inset hairline frame, large serif initials. */
.dentist-monogram {
  position: absolute;
  inset: 0;
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  padding: 2rem;
  text-align: center;
  color: var(--white);
  background: var(--dark);
}
.dentist-monogram::before {
  content: "";
  position: absolute;
  inset: 0.9rem;
  border: 1px solid rgba(143, 186, 182, 0.4);
  border-radius: 6px;
  pointer-events: none;
}
.dentist-portrait.no-photo .dentist-monogram { display: flex; }
.monogram-initials {
  font-family: var(--font-display);
  font-size: clamp(4.5rem, 3rem + 5vw, 7rem);
  font-weight: 400;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--sage);
}
.monogram-rule {
  width: 2.5rem;
  height: 1px;
  margin-block: 0.9rem 0.4rem;
  background: rgba(143, 186, 182, 0.6);
}
.monogram-name {
  font-family: var(--font-display);
  font-size: var(--text-lg);
}
.monogram-meta {
  font-size: var(--text-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.72);
}
.dentist-copy h2 { margin-bottom: 1rem; }
.dentist-quote {
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--text-xl);
  line-height: 1.4;
  color: var(--ink);
  margin-bottom: 1.25rem;
}
.dentist-bio { margin-bottom: 1.6rem; }
.dentist-creds {
  list-style: none;
  margin: 0;
  padding: 1.5rem 0 0;
  border-top: 1px solid var(--line);
  display: grid;
  gap: 0.85rem;
}
.dentist-creds li {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-size: var(--text-base);
  color: var(--ink);
}
.dentist-creds svg {
  width: 1.15rem;
  height: 1.15rem;
  color: var(--sage-ink);
  flex-shrink: 0;
}
@media (max-width: 860px) {
  .dentist-card { grid-template-columns: 1fr; }
  .dentist-portrait { max-width: 26rem; }
  .dentist-portrait.no-photo { aspect-ratio: 5 / 4; }
}
@media (max-width: 480px) {
  .hero-actions .btn { flex: 1 1 100%; }
}

/* ==========================================================================
   Services
   ========================================================================== */
.services { padding-block: var(--space-section); background: var(--surface-alt); }
.service-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(1.25rem, 2vw, 1.75rem);
}
@media (max-width: 900px) { .service-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .service-grid { grid-template-columns: 1fr; } }

.service-card {
  display: flex;
  flex-direction: column;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  transition: transform var(--dur-layout) var(--ease-out-quart),
              box-shadow var(--dur-layout) var(--ease-out-quart),
              border-color var(--dur-layout) var(--ease-out-quart);
}
/* Only cards that lead somewhere respond to hover; lifting a card that is not
   a link promises a click that does nothing. */
.service-card:has(a):hover {
  transform: translateY(-3px);
  border-color: var(--sage);
  box-shadow: 0 12px 30px rgba(34, 40, 39, 0.08);
}
.service-media {
  aspect-ratio: 3 / 2;
  overflow: hidden;
  background: var(--beige);
}
.service-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Light unifying treatment so the varied clinical stock coheres with the
     calm, warm palette; restored on hover. */
  filter: saturate(0.88) contrast(1.02);
  transition: transform 600ms var(--ease-out-quart), filter var(--dur-layout) var(--ease-out-quart);
}
.service-card:has(a):hover .service-media img {
  transform: scale(1.04);
  filter: saturate(1) contrast(1.02);
}
.service-body {
  padding: 1.35rem 1.4rem 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}
.service-body h3 { font-size: var(--text-lg); }
.service-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.4rem;
}
.service-list li {
  position: relative;
  padding-left: 1.4rem;
  font-size: var(--text-sm);
  color: var(--gray);
}
.service-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.5em;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--sage);
}
/* ---------- index layout ----------
   Nine same-size cards made a long wall of stock photography. As an index,
   each category is one ruled row: a small photograph, the name, then what it
   covers as running text, so the whole range can be scanned in one screen. */
.service-grid--index {
  grid-template-columns: 1fr;
  gap: 0;
  border-top: 1px solid rgba(34, 40, 39, 0.14);
}
.service-grid--index .service-card {
  display: grid;
  grid-template-columns: 10rem minmax(0, 1fr);
  gap: clamp(1.25rem, 3vw, 2.5rem);
  align-items: start;
  padding-block: clamp(1.4rem, 2.5vw, 1.9rem);
  background: none;
  border: 0;
  border-bottom: 1px solid rgba(34, 40, 39, 0.14);
  border-radius: 0;
  overflow: visible;
}
.service-grid--index .service-card:not(:has(.service-media)) { grid-template-columns: 1fr; }
.service-grid--index .service-card:has(a):hover {
  transform: none;
  box-shadow: none;
  border-color: rgba(34, 40, 39, 0.14);
}
.service-grid--index .service-media {
  aspect-ratio: 4 / 3;
  border-radius: 8px;
}
.service-grid--index .service-body {
  padding: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.35fr);
  gap: 0.6rem clamp(1.5rem, 4vw, 3.5rem);
  align-items: start;
}
.service-grid--index .service-body h3 {
  grid-column: 1;
  font-size: var(--text-xl);
  line-height: 1.2;
}
.service-grid--index .service-body > p {
  grid-column: 1;
  font-size: var(--text-base);
}
.service-grid--index .service-list {
  grid-column: 2;
  grid-row: 1 / span 3;
  display: block;
  padding-top: 0.3rem;
}
.service-grid--index .service-list li {
  display: inline;
  padding-left: 0;
  font-size: var(--text-base);
  color: var(--gray);
}
.service-grid--index .service-list li::before { content: none; }
.service-grid--index .service-list li:not(:last-child)::after {
  content: "\00B7";
  margin-inline: 0.55rem;
  color: var(--sage-ink);
}
.service-grid--index .service-body .arrow-link {
  grid-column: 1;
  margin-top: 0;
  align-self: start;
}
@media (min-width: 761px) {
  /* Keep each treatment name whole; only the gaps between them may wrap. */
  .service-grid--index .service-list li { white-space: nowrap; }
}
@media (max-width: 760px) {
  .service-grid--index .service-card { grid-template-columns: 5.5rem minmax(0, 1fr); gap: 1rem; }
  .service-grid--index .service-body { grid-template-columns: 1fr; }
  .service-grid--index .service-list { grid-column: 1; grid-row: auto; padding-top: 0; }
  .service-grid--index .service-body h3 { font-size: var(--text-lg); }
  .service-grid--index .service-list li { font-size: var(--text-sm); }
}

.services-cta {
  max-width: none;
  text-align: left;
  margin-top: clamp(2rem, 4vw, 3rem);
  font-size: var(--text-md);
  color: var(--ink);
}

/* ==========================================================================
   Features + interior
   ========================================================================== */
.features { padding-block: var(--space-section); }
/* A ruled list, not an icon grid: each fact is a serif term over its line of
   explanation, separated by hairlines like entries in a notebook. */
.feature-list {
  margin: 0;
  display: grid;
  border-top: 1px solid var(--line);
}
.feature {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
  gap: 0.35rem 2rem;
  align-content: start;
  padding-block: 1.35rem;
  border-bottom: 1px solid var(--line);
}
.feature dt {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  line-height: 1.3;
  color: var(--ink);
}
.feature dd { margin: 0; font-size: var(--text-base); }
@media (max-width: 560px) {
  .feature { grid-template-columns: 1fr; }
}
/* Full-width variant (treatments hub): two columns of entries. */
.feature-list--wide {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: clamp(2rem, 5vw, 4rem);
  border-top: 0;
}
.feature-list--wide .feature {
  grid-template-columns: 1fr;
  border-top: 1px solid var(--line);
  border-bottom: 0;
}
@media (max-width: 760px) {
  .feature-list--wide { grid-template-columns: 1fr; }
}
.features .split-media img { aspect-ratio: 4 / 5; }
.features-copy h2 { margin-bottom: clamp(1.75rem, 4vw, 2.5rem); }
@media (max-width: 860px) {
  .features .split-media img { aspect-ratio: 4 / 3; }
}

/* ==========================================================================
   Patient stories
   ========================================================================== */
.stories { padding-block: var(--space-section); }
/* Reviews as three columns of type under a rule, not three white boxes. */
.story-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
  gap: 2.5rem clamp(2rem, 4vw, 3.5rem);
}
.story-card {
  position: relative;
  padding-top: 1.5rem;
  border-top: 1px solid rgba(34, 40, 39, 0.2);
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.stars {
  display: flex;
  gap: 0.2rem;
  color: var(--sage-ink);
}
.stars svg { width: 0.95rem; height: 0.95rem; }
/* Reviews are set upright in the serif: long passages read better upright,
   and the quotation marks already mark it as a quote. */
.story-card blockquote {
  font-family: var(--font-display);
  font-size: var(--text-md);
  line-height: 1.55;
  color: var(--ink);
  flex-grow: 1;
  text-wrap: pretty;
}
.story-card figcaption {
  font-size: var(--text-sm);
  color: var(--gray);
}
.story-name {
  display: block;
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 0.1rem;
}

.stories-cta {
  display: flex;
  justify-content: flex-start;
  margin-top: clamp(2rem, 4vw, 2.75rem);
}
.btn-google {
  background: var(--white);
  gap: 0.65rem;
}
.g-logo {
  width: 1.15rem;
  height: 1.15rem;
  flex-shrink: 0;
}

/* ==========================================================================
   Gallery
   ========================================================================== */
.gallery { padding-block: var(--space-section); }
.gallery-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
}
.gallery-item {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--beige);
}
.gallery-item img {
  width: 100%;
  height: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  transition: transform 600ms var(--ease-out-quart);
}
.gallery-item:hover img { transform: scale(1.04); }
/* portrait sources in wide frames: bias the crop toward faces */
.gallery-item img.focus-top { object-position: center 32%; }
.gallery-wide { grid-column: span 2; }
.gallery-wide img { aspect-ratio: 2 / 1; }
.gallery-item figcaption {
  position: absolute;
  inset: auto 0 0 0;
  padding: 1.5rem 1rem 0.85rem;
  font-size: var(--text-sm);
  font-weight: 500;
  color: #fff;
  background: linear-gradient(to top, rgba(34, 40, 39, 0.78), transparent);
}
@media (max-width: 860px) {
  .gallery-grid { grid-template-columns: repeat(2, 1fr); }
  .gallery-wide { grid-column: span 2; }
}

/* ==========================================================================
   Contact
   ========================================================================== */
.contact { padding-block: var(--space-section); }
.contact-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(2.5rem, 6vw, 5rem);
  align-items: start;
}
.contact-copy h2 { margin-bottom: 0.9rem; }
.contact-rows {
  list-style: none;
  margin: 2rem 0 0;
  padding: 0;
  display: grid;
  gap: 1.5rem;
}
.contact-rows li {
  display: flex;
  gap: 1rem;
  align-items: flex-start;
}
.contact-rows svg {
  width: 1.25rem;
  height: 1.25rem;
  color: var(--sage-ink);
  flex-shrink: 0;
  margin-top: 0.2rem;
}
.contact-rows h3 {
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: 600;
  margin-bottom: 0.15rem;
}
.contact-rows p { font-size: var(--text-base); }
/* tel: and WhatsApp are the primary mobile conversions — full tap target */
.contact-rows a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}
/* The phone number is the fastest route to a human, so it is set as display
   type rather than as one more underlined link. */
.contact-rows a[href^="tel:"] {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid var(--sage);
  min-height: 0;
  padding-block: 0.2rem;
}
.contact-rows a[href^="tel:"]:hover { border-bottom-color: var(--ink); }

.map-wrap {
  margin-top: 2.25rem;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--line);
}
.map-wrap iframe {
  display: block;
  width: 100%;
  height: 15rem;
  border: 0;
}

.appointment-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: clamp(1.5rem, 3.5vw, 2.25rem);
  display: grid;
  gap: 1.15rem;
}
.appointment-title {
  font-size: var(--text-xl);
  margin-bottom: 0.35rem;
}
.form-field { display: grid; gap: 0.4rem; }
.form-field label {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--gray);
}
.form-field input,
.form-field select {
  font: inherit;
  font-size: var(--text-base);
  color: var(--ink);
  background: var(--white);
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  padding: 0.75rem 0.9rem;
  width: 100%;
  transition: border-color var(--dur-state) var(--ease-out-quart), box-shadow var(--dur-state) var(--ease-out-quart);
}
.form-field input::placeholder { color: var(--placeholder); }
.form-field input:focus,
.form-field select:focus {
  border-color: var(--dark);
  box-shadow: 0 0 0 3px rgba(143, 186, 182, 0.35);
  outline: none;
}
/* The field that blocked submission shakes once, so the eye is taken to it
   rather than only to the message underneath. */
.form-field.shake input { animation: shake 400ms var(--ease-out-quart) both; }
@keyframes shake {
  20% { transform: translateX(-4px); }
  40% { transform: translateX(4px); }
  60% { transform: translateX(-3px); }
  80% { transform: translateX(2px); }
  to  { transform: none; }
}

/* Submitting hands off to WhatsApp in another tab, so the button says so. */
.btn.is-sending { pointer-events: none; }
.btn.is-sending .btn-label { opacity: 0.6; }
.form-field select {
  appearance: none;
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="8"><path d="M1 1l5 5 5-5" fill="none" stroke="%232C3937" stroke-width="2" stroke-linecap="round"/></svg>');
  background-repeat: no-repeat;
  background-position: right 0.9rem center;
}
.req { color: var(--error); }
.form-field input[aria-invalid="true"] { border-color: var(--error); }
.form-error {
  color: var(--error);
  font-size: var(--text-sm);
}
.form-note {
  font-size: var(--text-sm);
  text-align: center;
}
@media (max-width: 860px) {
  .contact-grid { grid-template-columns: 1fr; }
  /* On one column the booking form comes straight after the contact rows,
     and the map drops to the end: the form is the conversion, the map is
     reference. */
  .contact-grid { row-gap: 0; }
  .contact-copy { display: contents; }
  .appointment-card { order: 1; margin-top: 2.5rem; }
  .map-wrap { order: 2; margin-top: 1.5rem; }
}

/* ==========================================================================
   Footer
   ========================================================================== */
/* Dark green footer: closes the page on the same colour as the statement
   band, so the page ends rather than fading out on another beige. */
.site-footer {
  background: var(--dark);
  padding: clamp(3rem, 6vw, 4.5rem) 0 2.75rem;
  color: rgba(255, 255, 255, 0.72);
}
.site-footer .footer-brand { color: var(--white); }
.site-footer .footer-fine { color: rgba(255, 255, 255, 0.72); }
.site-footer .footer-col a { color: rgba(255, 255, 255, 0.78); }
.site-footer .footer-col a:hover { color: var(--white); }
.site-footer :focus-visible { outline-color: var(--sage); }
.footer-grid {
  display: grid;
  grid-template-columns: 2fr repeat(3, 1fr);
  gap: 2rem;
}
.footer-brand {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 0.5rem;
}
.footer-fine {
  font-size: var(--text-sm);
  color: var(--gray);
}
.footer-col {
  display: grid;
  gap: 0;
  align-content: start;
}
.footer-col a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--gray);
  text-decoration: none;
  font-size: var(--text-sm);
}
.footer-col a:hover { color: var(--dark); }
@media (max-width: 900px) {
  .footer-grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 700px) {
  .footer-grid { grid-template-columns: 1fr 1fr; gap: 1.5rem 1rem; }
  .footer-grid > :first-child { grid-column: 1 / -1; }
}

/* ==========================================================================
   Floating action buttons
   ========================================================================== */
.fab-stack {
  position: fixed;
  right: 1.25rem;
  bottom: 1.25rem;
  z-index: var(--z-fab);
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.fab {
  width: 3.25rem;
  height: 3.25rem;
  border-radius: 50%;
  display: grid;
  place-items: center;
  color: #fff;
  box-shadow: 0 8px 24px rgba(34, 40, 39, 0.28);
  transition: transform var(--dur-state) var(--ease-out-quart), box-shadow var(--dur-state) var(--ease-out-quart);
}
.fab:hover {
  transform: translateY(-3px);
  box-shadow: 0 12px 30px rgba(34, 40, 39, 0.35);
}
.fab-whatsapp { background: #25D366; }
.fab-instagram {
  background: radial-gradient(circle at 30% 110%, #FDF497 0%, #FD5949 45%, #D6249F 60%, #285AEB 90%);
}

/* ==========================================================================
   Reveals
   Four behaviours, each matched to what it reveals, rather than one
   fade-and-rise on every section.

   IMPORTANT: the DEFAULT state of every revealed element is fully visible.
   The hidden start frame lives ONLY inside the @keyframes, and is applied by
   `animation` when the IntersectionObserver adds `.in`. So if the observer
   never runs (JS off or failed, restored scroll, a background tab), the page
   is simply visible, never blank. This is the reason it is animation-based
   rather than an `opacity: 0` base state that a class has to undo.
   ========================================================================== */
@media (prefers-reduced-motion: no-preference) {
  /* 1. Copy blocks: opacity only. Sliding paragraphs read as restless, and
        the whole brand claim is that nothing here is rushed. */
  body.js [data-reveal="copy"].in {
    animation: rv-fade var(--dur-enter) var(--ease-out-quart) both;
  }

  /* 2. Photographs: a wipe upward out of a slight over-scale, so the room
        appears to open rather than slide in from nowhere. */
  body.js [data-reveal="media"].in {
    animation: rv-media var(--dur-enter) var(--ease-out-expo) both;
  }

  /* 3. Genuine sibling lists (treatments, reviews, gallery, features). Stagger
        is legitimate here because these ARE lists; capped at 6 so the last
        item never waits more than ~350ms. */
  body.js [data-reveal="item"].in {
    animation: rv-item 520ms var(--ease-out-quart) both;
    animation-delay: calc(var(--i, 0) * 70ms);
  }

  /* 4. Single composed panels (dentist card, booking form): they settle down
        out of a slight under-scale, like something set on a table. */
  body.js [data-reveal="panel"].in {
    animation: rv-panel var(--dur-enter) var(--ease-out-expo) both;
  }
}

@keyframes rv-fade  { from { opacity: 0; }                                              to { opacity: 1; } }
@keyframes rv-item  { from { opacity: 0; transform: translateY(16px); }                 to { opacity: 1; transform: none; } }
@keyframes rv-panel { from { opacity: 0; transform: translateY(18px) scale(0.99); }     to { opacity: 1; transform: none; } }
@keyframes rv-media { from { opacity: 0; clip-path: inset(14% 0 0 0); transform: scale(1.03); }
                      to   { opacity: 1; clip-path: inset(0 0 0 0);  transform: none; } }

/* ==========================================================================
   Hero entrance — the one rehearsed moment on the page
   ========================================================================== */
body.js .hero-bg       { animation: bg-in 1200ms var(--ease-out-expo) both; }
body.js .hero-copy > p { animation: rise 800ms var(--ease-out-expo) 460ms both; }
body.js .hero-actions  { animation: rise 800ms var(--ease-out-expo) 580ms both; }
body.js .hero-badges   { animation: rise 800ms var(--ease-out-expo) 680ms both; }

@keyframes bg-in {
  from { opacity: 0; transform: scale(1.06); }
  to   { opacity: 1; transform: none; }
}

/* Hero headline: each line rises out from behind its own clip box, so the
   words appear to lift into place. This is the page's signature text moment. */
.hero-title .line { display: block; overflow: hidden; padding-bottom: 0.08em; }
.hero-title .line > span { display: block; }
body.js .hero-title .line > span {
  transform: translateY(115%);
  animation: line-rise 950ms var(--ease-out-expo) forwards;
}
body.js .hero-title .line:nth-child(1) > span { animation-delay: 150ms; }
body.js .hero-title .line:nth-child(2) > span { animation-delay: 300ms; }

@keyframes rise {
  from { opacity: 0; transform: translateY(20px); }
  to   { opacity: 1; transform: none; }
}
@keyframes line-rise {
  to { transform: translateY(0); }
}

/* ==========================================================================
   Reduced motion — every animation above has a still equivalent
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  /* Scroll reveals are already off here: every reveal animation lives inside
     `prefers-reduced-motion: no-preference`, and the default state is visible.
     Only the load-triggered entrances need explicitly cancelling. */
  body.js .hero-bg,
  body.js .hero-copy > p,
  body.js .hero-actions,
  body.js .hero-badges,
  body.js .hero-title .line > span,
  .nav-menu.open,
  .form-field.shake input {
    animation: none;
  }

  /* The masked hero lines must reset to visible, not sit at their hidden start. */
  body.js .hero-title .line > span { transform: none; }

  /* Hovers and presses become instant colour changes only. */
  .btn, .arrow-link, .fab, .gallery-item img, .gallery-item figcaption,
  .service-card, .nav-links a::after, .site-header {
    transition-duration: 1ms;
  }
  .btn:hover, .btn:active, .fab:hover, .service-card:hover,
  .gallery-item:hover img { transform: none; }

  /* Rails are drawn in full and every step reads as reached (script.js skips
     the scrub); statement words sit fully inked (the scrub rule lives inside
     no-preference); FAQ opens instantly; hero parallax is cancelled in JS. */
  .journey-no, .journey-step p, .steps[data-rail] .step-no { transition: none; }
  .faq-answer { transition: none; }
  .faq-mark::before, .faq-mark::after { transition: none; }
}

/* ==========================================================================
   Treatment pages (services/*.html)
   A second page type: photo hero, long-form explanation, numbered process,
   aftercare and FAQ. It borrows the section grammar and every token from the
   home page, so nothing new is introduced except layout.
   ========================================================================== */

/* ---------- page hero ----------
   The photographs behind this band range from near-white (an X-ray monitor) to
   near-black (an implant model), so the scrim has to carry the contrast on its
   own: at 0.88 alpha over the lightest photo, white text still clears 9:1. */
.page-hero {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: flex-end;
  min-height: clamp(19rem, 42vw, 27rem);
  padding-block: clamp(2.75rem, 7vw, 4.5rem) clamp(2.5rem, 6vw, 3.75rem);
  background: var(--ink);
  overflow: hidden;
}
.page-hero-img {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(0.85);
}
.page-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(100deg,
    rgba(24, 32, 30, 0.94) 0%,
    rgba(24, 32, 30, 0.88) 46%,
    rgba(24, 32, 30, 0.60) 100%);
}

/* No photo (the hub page): a quiet sage wash instead of a picture. */
.page-hero--plain { min-height: 0; }
.page-hero--plain::after {
  background:
    radial-gradient(60rem 26rem at 88% 8%, rgba(143, 186, 182, 0.24), transparent 70%),
    linear-gradient(100deg, rgba(24, 32, 30, 0.97), rgba(24, 32, 30, 0.9));
}

.page-hero .container { position: relative; z-index: 1; width: 100%; }
.page-hero-copy { max-width: 46rem; }
.page-hero h1 {
  color: var(--white);
  font-size: var(--text-3xl);
  margin-block: 0.55rem 0.9rem;
}
.page-hero-lead {
  color: rgba(255, 255, 255, 0.86);
  font-size: var(--text-md);
  max-width: 46ch;
}
/* The breadcrumb already says where you are; a second tracked label under it
   repeated the same word. */
.page-hero .pill { display: none; }
.page-hero .breadcrumb { margin-bottom: 1.25rem; }
.page-hero .hero-actions { margin-top: 1.9rem; }

/* ---------- breadcrumb ---------- */
.breadcrumb { font-size: var(--text-sm); }
.breadcrumb ol {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  list-style: none;
  margin: 0;
  padding: 0;
  color: rgba(255, 255, 255, 0.7);
}
.breadcrumb li + li::before {
  content: "/";
  margin-right: 0.5rem;
  color: rgba(255, 255, 255, 0.45);
}
.breadcrumb a {
  color: rgba(255, 255, 255, 0.82);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.breadcrumb a:hover { border-bottom-color: currentColor; }
.breadcrumb [aria-current="page"] { color: var(--sage); }

/* ---------- jump links ---------- */
.jump-nav {
  border-bottom: 1px solid var(--line);
  background: var(--neutral);
}
.jump-nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 0.6rem;
  list-style: none;
  margin: 0;
  padding: 0.9rem 0;
}
.jump-nav a {
  display: inline-flex;
  align-items: center;
  min-height: 36px;
  padding: 0.3rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--white);
  font-size: var(--text-sm);
  color: var(--gray);
  text-decoration: none;
  transition: border-color var(--dur-state) var(--ease-out-quart),
              color var(--dur-state) var(--ease-out-quart);
}
.jump-nav a:hover { border-color: var(--sage); color: var(--ink); }

/* ---------- long-form body ---------- */
.svc-section { padding-block: var(--space-section); }
.svc-section--tight { padding-block: clamp(3rem, 6vw, 4.5rem); }

.svc-split {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: clamp(2.25rem, 5vw, 4rem);
  align-items: start;
}
@media (max-width: 860px) { .svc-split { grid-template-columns: 1fr; } }

.svc-prose h2 { margin-bottom: 1.1rem; }
.svc-prose h3 {
  font-size: var(--text-lg);
  margin-top: 1.9rem;
  margin-bottom: 0.6rem;
}
.svc-prose p + p { margin-top: 0.9rem; }
.svc-prose > ul {
  margin-top: 1rem;
  padding-left: 0;
  list-style: none;
  display: grid;
  gap: 0.55rem;
}
.svc-prose > ul li {
  position: relative;
  padding-left: 1.5rem;
}
.svc-prose > ul li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--sage);
}

/* Side card: the symptom checklist that tells a visitor whether this page is
   about their problem at all. */
.check-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: clamp(1.4rem, 3vw, 1.9rem);
  position: sticky;
  top: 5.5rem;
}
.check-card h2,
.check-card h3 {
  font-size: var(--text-xl);
  margin-bottom: 1rem;
}
.check-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.8rem;
}
.check-list li {
  display: grid;
  grid-template-columns: 1.15rem 1fr;
  gap: 0.7rem;
  font-size: var(--text-sm);
  color: var(--gray);
}
.check-list svg {
  width: 1.15rem;
  height: 1.15rem;
  margin-top: 0.2em;
  color: var(--sage-ink);
}
.check-note {
  margin-top: 1.2rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--line);
  font-size: var(--text-sm);
}
@media (max-width: 860px) { .check-card { position: static; } }

/* ---------- quick facts strip ---------- */
.facts {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
.facts > div {
  background: var(--white);
  padding: 1.25rem 1.35rem;
}
.facts dt {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--sage-ink);
  margin-bottom: 0.4rem;
}
.facts dd {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-md);
  color: var(--ink);
  line-height: 1.35;
}
@media (max-width: 780px) { .facts { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 420px) { .facts { grid-template-columns: 1fr; } }

/* ---------- figure ---------- */
.svc-figure { margin: 0; }
.svc-figure img {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius-lg);
  filter: saturate(0.88);
}
.svc-figure figcaption {
  margin-top: 0.75rem;
  font-size: var(--text-sm);
  color: var(--gray);
}

/* ---------- numbered process, on the dark band ---------- */
.steps-band {
  background: var(--ink);
  color: rgba(255, 255, 255, 0.78);
  padding-block: var(--space-section);
}
.steps-band h2 { color: var(--white); margin-bottom: 1rem; }
.steps-band .steps-intro { color: rgba(255, 255, 255, 0.74); }
.steps-rule {
  display: block;
  width: 3.5rem;
  height: 2px;
  background: var(--sage);
  margin-bottom: 1.4rem;
}
.steps {
  list-style: none;
  margin: clamp(2rem, 4vw, 3rem) 0 0;
  padding: 0;
  max-width: 58rem;
}
.steps li {
  display: grid;
  grid-template-columns: 3rem 1fr;
  gap: 0.5rem 1.25rem;
  padding-block: 1.6rem;
  border-top: 1px solid rgba(255, 255, 255, 0.14);
}
.steps li:last-child { border-bottom: 1px solid rgba(255, 255, 255, 0.14); }
.steps .step-no {
  font-family: var(--font-display);
  font-size: var(--text-md);
  color: var(--sage);
  font-variant-numeric: tabular-nums;
}
.steps h3 {
  color: var(--white);
  font-size: var(--text-lg);
  font-weight: 400;
}
.steps p {
  grid-column: 2;
  margin-top: 0.45rem;
  color: rgba(255, 255, 255, 0.76);
}
@media (max-width: 560px) {
  .steps li { grid-template-columns: 2.2rem 1fr; }
}

/* ---------- aftercare ---------- */
.dot-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1.1rem;
}
.dot-list li {
  position: relative;
  padding-left: 1.75rem;
}
.dot-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  background: var(--sage-ink);
}

/* ---------- honest-cost note ---------- */
.note-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: clamp(1.3rem, 3vw, 1.75rem);
}
.note-card h3 {
  font-size: var(--text-lg);
  margin-bottom: 0.6rem;
}

/* ---------- related treatments ---------- */
.link-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(1rem, 2vw, 1.5rem);
}
@media (max-width: 780px) { .link-grid { grid-template-columns: 1fr; } }

.link-card {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 1.4rem 1.5rem 1.5rem;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  text-decoration: none;
  transition: transform var(--dur-layout) var(--ease-out-quart),
              border-color var(--dur-layout) var(--ease-out-quart),
              box-shadow var(--dur-layout) var(--ease-out-quart);
}
.link-card:hover {
  transform: translateY(-3px);
  border-color: var(--sage);
  box-shadow: 0 12px 30px rgba(34, 40, 39, 0.08);
}
.link-card h3 { font-size: var(--text-lg); }
.link-card p { font-size: var(--text-sm); color: var(--gray); }
.link-card .link-more {
  margin-top: 0.35rem;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--sage-ink);
}

/* ---------- closing call to action ---------- */
.cta-band {
  background: var(--beige);
  padding-block: clamp(3rem, 7vw, 4.5rem);
}
.cta-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.75rem;
}
.cta-inner h2 { margin-bottom: 0.5rem; }
.cta-actions { display: flex; flex-wrap: wrap; gap: 0.75rem; }

/* ---------- hub page: cards that lead somewhere ----------
   The whole card is the hit area; the stretched link sits under the heading so
   assistive tech announces the treatment name, not "read more". */
.service-card--linked { position: relative; }
.service-card--linked h3 a {
  color: inherit;
  text-decoration: none;
}
.service-card--linked h3 a::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}
.service-card--linked:hover h3 a { color: var(--sage-ink); }
.service-card .service-more {
  margin-top: auto;
  padding-top: 0.35rem;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--sage-ink);
}

@media (prefers-reduced-motion: reduce) {
  .link-card, .jump-nav a { transition-duration: 1ms; }
  .link-card:hover { transform: none; }
}

/* Hub page: the four detailed treatments read better as a 2x2 of larger cards
   than as a row of three with a lone fourth underneath. */
.service-grid--feature { grid-template-columns: repeat(2, 1fr); }
/* Photo beside the text rather than above it, so the four guides read as a
   compact 2x2 instead of four poster-sized cards. */
@media (min-width: 900px) {
  .service-grid--feature .service-card { flex-direction: row; }
  .service-grid--feature .service-media { flex: 0 0 42%; aspect-ratio: auto; min-height: 15rem; }
}
@media (max-width: 560px) { .service-grid--feature { grid-template-columns: 1fr; } }

/* .services sets the grey surface after .band-beige is declared, so a
   services band that asks for beige has to say so explicitly. */
.services.band-beige { background: var(--beige); }

/* Quiet alternate surface, so a section does not merge into the beige CTA
   band that follows it. Same value the home page uses behind the services. */
.band-alt { background: var(--surface-alt); }
.cta-band { border-top: 1px solid rgba(34, 40, 39, 0.06); }

/* Cards whose lists differ in length still line their "explained" link up at
   the foot of the card. */
.service-body { flex: 1 1 auto; }
.service-body .arrow-link { margin-top: auto; }
