/* ==========================================================================
   LIPHOOK SMILE STUDIO — design system
   HTML5 · CSS3 · Bootstrap 5 · vanilla JS. No framework, no build step.

   ── A NOTE ON THE PALETTE ────────────────────────────────────────────────
   The brief suggested Deep Forest Green #183C36 as the primary, and said to
   treat it as "a starting direction" after analysing the logo.

   The logo was sampled programmatically. Every saturated colour in it falls
   between hue 199 and 225 — deep indigo #253E86 in the LIPHOOK wordmark and
   mid blue #2E86AB in SMILE STUDIO and the tooth. There is no green in it at
   all. #183C36 is hue 168, so a forest-green site would have left the logo
   looking pasted on rather than part of the brand.

   So the primary is re-hued into the logo's own family — a deep petrol ink
   that is dark and desaturated enough to read as quiet luxury rather than
   "corporate medical blue", which is what the brief's "avoid excessive bright
   blue" is guarding against. Everything else in the suggested system is kept:
   warm ivory ground, sand sections, charcoal text, muted gold used sparingly.
   That warm-neutral foundation is what makes the design feel premium; only
   the hue of the dark anchor has moved.

   To revert to the brief's green, change --brand-deep and --brand-deeper.
   Nothing else depends on the hue.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */

:root {
  /* Brand — sampled from the logo ------------------------------------- */
  --brand-deep:     #253E86;   /* PRIMARY — client-specified               */
  --brand-deeper:   #172653;   /* footer ground: primary darkened to 62%   */
  --brand-mid:      #19729F;   /* SECONDARY — client-specified             */
  --brand-indigo:   #253E86;   /* alias of the primary                     */
  --brand-mist:     #A9BDC2;   /* supporting soft tone (sage, cooled)      */

  /* Warm neutrals — from the brief, kept ------------------------------ */
  --ivory:          #F8F6F1;   /* main background                          */
  --sand:           #E8E0D4;   /* section backgrounds, cards               */
  --sand-deep:      #DCD1C0;   /* hover / borders on sand                  */
  --charcoal:       #262F33;   /* body text                                */
  --charcoal-soft:  #5A666B;   /* secondary text                           */
  --gold:           #B79A6B;   /* premium accent — RULES AND FILLS ONLY    */

  /* Text-safe variants.
     The brief's muted gold is beautiful as a hairline rule, and unreadable
     as small text: measured 2.48:1 on ivory against the 4.5:1 minimum. The
     logo's mid blue failed too, at 4.11:1 on white. Both were darkened until
     they clear 4.5:1 on the DARKEST light ground they sit on (sand #E8E0D4),
     so they are safe everywhere rather than only on white. The original
     values are kept above for rules, borders and icons on dark grounds,
     where contrast rules for text do not apply. */
  --gold-ink:       #736143;   /* gold as text — 4.56:1 on sand, 5.97 on white */
  --blue-ink:       #176A94;   /* SECONDARY as text — 4.55:1 on sand, 5.96 on white */
  --white:          #FFFFFF;
  --line:           rgba(37, 62, 134, .13);
  --line-strong:    rgba(37, 62, 134, .24);

  /* Feedback ---------------------------------------------------------- */
  --error:          #A33A31;
  --error-bg:       #FBF0EE;
  --success:        #2C6B52;
  --success-bg:     #EEF5F1;

  /* Type -------------------------------------------------------------- */
  --font-heading: "DM Serif Display", Georgia, "Times New Roman", serif;
  --font-body:    "Plus Jakarta Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  --fs-display: clamp(2.6rem, 1.9rem + 3.1vw, 4.4rem);
  --fs-h1:      clamp(2.2rem, 1.7rem + 2.2vw, 3.4rem);
  --fs-h2:      clamp(1.85rem, 1.5rem + 1.5vw, 2.7rem);
  --fs-h3:      clamp(1.3rem, 1.15rem + .6vw, 1.65rem);
  --fs-h4:      1.15rem;
  --fs-body:    1.0625rem;   /* 17px — comfortable, never tiny */
  --fs-sm:      .9375rem;
  --fs-xs:      .8125rem;
  --lh-body:    1.75;

  /* Space — one scale, used everywhere -------------------------------- */
  --s-1: .25rem;  --s-2: .5rem;   --s-3: .75rem;  --s-4: 1rem;
  --s-5: 1.5rem;  --s-6: 2rem;    --s-7: 3rem;    --s-8: 4rem;
  --s-9: 5.5rem;  --s-10: 7rem;

  --section-y:    clamp(3.5rem, 2.5rem + 3vw, 6.5rem);
  --container:    1240px;
  --container-nr: 900px;      /* narrow, for reading */

  /* Shape — refined, not childish ------------------------------------- */
  --r-sm:   8px;
  --r:      14px;
  --r-lg:   22px;
  --r-xl:   28px;
  --r-pill: 999px;

  --shadow:      0 2px 10px rgba(23, 38, 83, .06);
  --shadow-lift: 0 14px 40px rgba(23, 38, 83, .12);

  --t:      .28s cubic-bezier(.4, 0, .2, 1);
  --t-slow: .55s cubic-bezier(.4, 0, .2, 1);

  --header-h: 92px;
}

/* --------------------------------------------------------------------------
   2. Base
   -------------------------------------------------------------------------- */

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

/* The sideways-scroll guard lives on <html>, not <body>.

   It was on <body>, and `overflow: clip` there establishes a clip context.
   Unlike `overflow: hidden` — which leaves a fixed descendant alone, because
   its containing block is the viewport and therefore outside the clipper —
   `clip` clips every descendant including fixed ones, and WebKit additionally
   treats the clipping box as their containing block. On iOS Safari that turns
   the fixed bottom bar into an effectively absolute one, so it scrolls away
   with the page instead of staying put. Reported from a phone, 16 Sep 2026.

   On <html> it still stops a stray wide element scrolling the page sideways,
   because overflow on the root element propagates to the viewport — but it no
   longer sits between the action rail and the viewport. */
html {
  scroll-behavior: smooth;
  overflow-x: clip;
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  font-weight: 400;
  color: var(--charcoal);
  background: var(--ivory);
  -webkit-font-smoothing: antialiased;

  /* No overflow property here on purpose — see the note on <html> above.
     `overflow-x: hidden` would be worse still: it forces the computed
     overflow-y to `auto`, turning <body> into its own scroll container, at
     which point window.scrollY stops driving the page and html's
     scroll-behavior:smooth stops applying to anchor jumps. */
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading);
  font-weight: 400;
  line-height: 1.16;
  color: var(--brand-deep);
  letter-spacing: -.01em;
  margin: 0 0 var(--s-4);
}

h1 { font-size: var(--fs-h1); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); }
h4 { font-size: var(--fs-h4); font-family: var(--font-body); font-weight: 700; letter-spacing: 0; }

p { margin: 0 0 var(--s-4); }
p:last-child { margin-bottom: 0; }

a { color: var(--brand-deep); text-decoration: none; transition: color var(--t); }
a:hover { color: var(--brand-mid); }

img { max-width: 100%; height: auto; display: block; }

strong, b { font-weight: 700; }

/* Focus — visible on everything interactive, never removed. */
a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible, summary:focus-visible,
[tabindex]:focus-visible {
  outline: 3px solid var(--brand-mid);
  outline-offset: 3px;
  border-radius: 4px;
}

.visually-hidden, .screen-reader-text {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute; left: var(--s-4); top: -100px;
  z-index: 2000;
  background: var(--white); color: var(--brand-deep);
  padding: var(--s-3) var(--s-5);
  border-radius: var(--r-sm);
  font-weight: 700; font-size: var(--fs-sm);
  box-shadow: var(--shadow-lift);
  transition: top var(--t);
}
.skip-link:focus { top: var(--s-4); }

.container, .container-fluid { max-width: var(--container); }
.container-narrow { max-width: var(--container-nr); margin-inline: auto; }

/* --------------------------------------------------------------------------
   3. Section rhythm and grounds
   -------------------------------------------------------------------------- */

.section        { padding-block: var(--section-y); }
.section--tight { padding-block: clamp(2.2rem, 1.8rem + 1.6vw, 3.5rem); }

.bg-ivory  { background: var(--ivory); }
.bg-white  { background: var(--white); }
.bg-sand   { background: var(--sand); }
.bg-deep   { background: var(--brand-deep); color: rgba(255, 255, 255, .82); }
.bg-deeper { background: var(--brand-deeper); color: rgba(255, 255, 255, .8); }

.bg-deep h1, .bg-deep h2, .bg-deep h3, .bg-deep h4,
.bg-deeper h1, .bg-deeper h2, .bg-deeper h3, .bg-deeper h4 { color: var(--white); }
.bg-deep a, .bg-deeper a { color: var(--brand-mist); }
.bg-deep a:hover, .bg-deeper a:hover { color: var(--white); }

/* Section heading ---------------------------------------------------------- */
.sec-head { margin-bottom: clamp(2rem, 1.6rem + 1.4vw, 3.25rem); }
.sec-head--center { text-align: center; }
.sec-head--center .sec-head__lead { margin-inline: auto; }

.eyebrow {
  display: inline-block;
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--gold-ink);
  margin-bottom: var(--s-3);
}
.bg-deep .eyebrow, .bg-deeper .eyebrow, .hero .eyebrow { color: var(--brand-mist); }

.sec-head__lead {
  max-width: 62ch;
  font-size: 1.125rem;
  color: var(--charcoal-soft);
  margin-bottom: 0;
}
.bg-deep .sec-head__lead, .bg-deeper .sec-head__lead { color: rgba(255, 255, 255, .78); }

/* A hairline rule under a heading — one restrained flourish, used sparingly */
.rule-gold::after {
  content: "";
  display: block;
  width: 54px; height: 2px;
  background: var(--gold);
  margin-top: var(--s-4);
}
.sec-head--center .rule-gold::after { margin-inline: auto; }

/* --------------------------------------------------------------------------
   4. Buttons
   -------------------------------------------------------------------------- */

.btn-ls {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: 52px;
  padding: var(--s-3) var(--s-6);
  border: 1.5px solid transparent;
  border-radius: var(--r-pill);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: .01em;
  line-height: 1.3;
  text-align: center;
  cursor: pointer;
  transition: background var(--t), color var(--t), border-color var(--t), transform var(--t);
}
.btn-ls:hover { transform: translateY(-2px); }

.btn-ls--primary { background: var(--brand-deep); border-color: var(--brand-deep); color: var(--white); }
.btn-ls--primary:hover { background: var(--brand-deeper); border-color: var(--brand-deeper); color: var(--white); }

.btn-ls--outline { background: transparent; border-color: var(--brand-deep); color: var(--brand-deep); }
.btn-ls--outline:hover { background: var(--brand-deep); color: var(--white); }

.btn-ls--gold { background: var(--gold); border-color: var(--gold); color: var(--brand-deeper); }
.btn-ls--gold:hover { background: #A88B5C; border-color: #A88B5C; color: var(--brand-deeper); }

/* On dark grounds the outline has to invert. */
.bg-deep .btn-ls--outline, .bg-deeper .btn-ls--outline, .hero .btn-ls--outline {
  border-color: rgba(255, 255, 255, .55); color: var(--white);
}
.bg-deep .btn-ls--outline:hover, .bg-deeper .btn-ls--outline:hover, .hero .btn-ls--outline:hover {
  background: var(--white); color: var(--brand-deep); border-color: var(--white);
}
.bg-deep .btn-ls--primary, .bg-deeper .btn-ls--primary, .hero .btn-ls--primary {
  background: var(--white); border-color: var(--white); color: var(--brand-deep);
}
.bg-deep .btn-ls--primary:hover, .bg-deeper .btn-ls--primary:hover, .hero .btn-ls--primary:hover {
  background: var(--sand); border-color: var(--sand); color: var(--brand-deeper);
}

.btn-ls--sm { min-height: 44px; padding: var(--s-2) var(--s-5); font-size: var(--fs-xs); }
.btn-ls--block { width: 100%; }

/* A quiet text link with a moving arrow — the "Learn more" affordance. */
.link-more {
  display: inline-flex; align-items: center; gap: var(--s-2);
  font-size: var(--fs-sm); font-weight: 700;
  color: var(--brand-deep);
}
.link-more i { transition: transform var(--t); }
.link-more:hover i { transform: translateX(4px); }

/* --------------------------------------------------------------------------
   5. Top bar + header
   -------------------------------------------------------------------------- */

.topbar {
  background: var(--brand-deeper);
  color: rgba(255, 255, 255, .78);
  font-size: var(--fs-xs);
  padding: var(--s-2) 0;
}
.topbar a { color: rgba(255, 255, 255, .88); }
.topbar a:hover { color: var(--white); }
/* Practice details left, the two actions right. They share one flex row so
   the gap between the groups absorbs the slack rather than a fixed width
   deciding where each sits. */
.topbar__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2) var(--s-5);
}
.topbar__list { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2) var(--s-6); margin: 0; padding: 0; list-style: none; }
.topbar__list--end { gap: var(--s-2) var(--s-5); }
.topbar__list li { display: inline-flex; align-items: center; gap: var(--s-2); }
.topbar i { color: var(--brand-mist); }

/* "Get directions" is an action, not a detail, so it reads as one. */
.topbar__dir {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: 3px var(--s-3);
  border: 1px solid rgba(255, 255, 255, .28);
  border-radius: var(--r-pill);
  text-decoration: none;
  transition: background .2s ease, border-color .2s ease;
}
.topbar__dir:hover,
.topbar__dir:focus-visible { background: rgba(255, 255, 255, .12); border-color: rgba(255, 255, 255, .5); }
.topbar__dir:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* The phone number, given its own weight.

   It used to sit in the left-hand list styled exactly like the address, the
   hours and the email — 13px, regular weight, the same near-white. Contrast
   was never the problem (about 12:1 on the navy); prominence was. It is the
   single most valuable link on a practice site, so it now reads as a control
   rather than as one more line of small print: a filled pill, the number
   itself bold and a step larger than everything around it.

   White number, requested 16 September 2026. It could not simply go white on
   the gold: white on `--gold` measures 2.68:1, which fails AA at any size,
   large-text included. So the fill moved to `--brand-mid`, the client's own
   secondary — dark enough to carry white at 5.32:1 — and the gold stays as a
   hairline ring, which is what gives the pill its separation from the navy
   strip (5.46:1 ring-to-ground) now that the fill no longer provides it. */
.topbar__call {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: 4px var(--s-3);
  border-radius: var(--r-pill);
  background: var(--brand-mid);
  border: 1px solid var(--gold);
  color: var(--white);
  text-decoration: none;
  transition: background var(--t), transform var(--t);
}
.topbar__call i { color: var(--white); }
.topbar__call strong {
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: .01em;
  white-space: nowrap;           /* a phone number must never wrap mid-number */
}
.topbar__call-label { text-transform: uppercase; letter-spacing: .08em; font-weight: 600; }

/* The topbar sets `a { color: rgba(255,255,255,.88) }` for its own ground —
   near-white, not white. This link needs the full white it was asked for, and
   needs to keep it on hover, so it states both. */
.topbar a.topbar__call,
.topbar a.topbar__call:hover,
.topbar a.topbar__call:focus-visible { color: var(--white); }

/* Hover darkens rather than lightens: going lighter would erode the white
   text's 5.32:1. `--blue-ink` is the same hue a step down, and takes it to
   6.3:1. */
.topbar__call:hover { background: var(--blue-ink); }
.topbar__call:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* On a phone the label is dropped — the icon plus the number is unambiguous,
   and the strip is tight enough already. */
@media (max-width: 575.98px) {
  .topbar__call-label { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .topbar__call { transition: none; }
}

/* Below the header's own breakpoint the bar sheds detail rather than wrapping
   into a four-row block 99px tall. What survives is what a phone user taps:
   the number and the directions. The address and email are a tap away in the
   visit strip and the footer of every page, so nothing is lost. */
@media (max-width: 991.98px) {
  .topbar__inner { justify-content: center; gap: var(--s-2) var(--s-4); }
  .topbar__list { justify-content: center; gap: var(--s-2) var(--s-4); }
  /* :not(--end) matters — both groups carry .topbar__list, so an unscoped
     li:first-child would take the email out with the address. */
  .topbar__list:not(.topbar__list--end) li:first-child { display: none; }  /* address */
}
@media (max-width: 575.98px) {
  .topbar__list--end li:first-child { display: none; }   /* email */
}

@media (prefers-reduced-motion: reduce) { .topbar__dir { transition: none; } }

.site-header {
  position: sticky; top: 0; z-index: 1040;
  background: var(--ivory);
  border-bottom: 1px solid var(--line);
  transition: box-shadow var(--t), background var(--t);
}
.site-header.is-stuck { box-shadow: 0 6px 24px rgba(23, 38, 83, .10); background: rgba(248, 246, 241, .96); backdrop-filter: blur(8px); }

.site-header__inner { display: flex; align-items: center; gap: var(--s-5); min-height: var(--header-h); }

.brand { flex: none; display: inline-flex; align-items: center; padding-block: var(--s-3); }
.brand img { height: 58px; width: auto; }
@media (max-width: 991.98px) { .brand img { height: 48px; } }

/* Navigation --------------------------------------------------------------- */
.main-nav { margin-left: auto; }
.main-nav .navbar-nav { gap: var(--s-1); align-items: center; }

.main-nav .nav-link {
  position: relative;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--charcoal);
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-sm);
  transition: color var(--t);
}
.main-nav .nav-link:hover, .main-nav .nav-link:focus { color: var(--brand-deep); }

.main-nav .nav-link[aria-current="page"] { color: var(--brand-deep); }
.main-nav .nav-link[aria-current="page"]::after {
  content: ""; position: absolute;
  left: var(--s-3); right: var(--s-3); bottom: 2px;
  height: 2px; background: var(--gold);
}

.main-nav .dropdown-toggle::after { margin-left: var(--s-2); vertical-align: .13em; }

/* Mega menu — the treatments panel. Three real categories, not a long list. */
.mega {
  border: 0;
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lift);
  padding: var(--s-6);
  margin-top: var(--s-3);
  background: var(--white);
}
@media (min-width: 992px) {
  .mega { width: min(940px, calc(100vw - 3rem)); }
  .mega__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-6); }
}
.mega__col-title {
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--gold-ink);
  padding-bottom: var(--s-3);
  margin-bottom: var(--s-3);
  border-bottom: 1px solid var(--line);
}
.mega__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.mega__list a {
  display: block;
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--charcoal);
  transition: background var(--t), color var(--t);
}
.mega__list a:hover, .mega__list a:focus { background: var(--ivory); color: var(--brand-deep); }
.mega__foot {
  margin-top: var(--s-5); padding-top: var(--s-4);
  border-top: 1px solid var(--line);
  display: flex; flex-wrap: wrap; gap: var(--s-4); justify-content: space-between; align-items: center;
}

.header__cta { flex: none; }

.nav-toggle {
  margin-left: auto;
  background: transparent;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  color: var(--brand-deep);
  padding: 10px 13px;
  line-height: 1;
}

@media (max-width: 991.98px) {
  :root { --header-h: 76px; }
  .main-nav {
    margin-left: 0; width: 100%;
    border-top: 1px solid var(--line);
    margin-top: var(--s-3); padding-top: var(--s-3);
    max-height: calc(100vh - var(--header-h) - 2rem);
    overflow-y: auto;
  }
  .main-nav .navbar-nav { align-items: stretch; gap: 0; }
  .main-nav .nav-link { padding: var(--s-3) var(--s-2); font-size: 1.0625rem; }
  .main-nav .nav-link[aria-current="page"]::after { left: var(--s-2); right: auto; width: 24px; }
  .mega { box-shadow: none; padding: var(--s-3) 0 var(--s-4); margin: 0; background: transparent; }
  .mega__grid { display: grid; gap: var(--s-5); }
  .mega__list a { padding-left: var(--s-4); }
  .header__cta { width: 100%; margin: var(--s-3) 0 var(--s-4); }
  .header__cta .btn-ls { width: 100%; }
}

/* --------------------------------------------------------------------------
   6. Hero
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  background: var(--brand-deep);
  color: rgba(255, 255, 255, .85);
  overflow: hidden;
}
.hero__bg { position: absolute; inset: 0; }
.hero__bg img { width: 100%; height: 100%; object-fit: cover; }
/* The wash over the hero photograph.

   It was originally near-opaque (.94), which crushed the practice's own
   photography into flat navy once real images went in. These stops were set
   by compositing the actual hero image against candidate gradients on a
   canvas and measuring the worst pixel behind the headline and the lead:
   this version leaves white text at 4.9:1 at its weakest point, against the
   4.5:1 minimum. A lighter wash measured 3.33:1 and was rejected — the photo
   looked better and the lead paragraph became unreadable over it. */
.hero::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(100deg,
    rgba(23, 38, 83, .91) 0%,
    rgba(23, 38, 83, .82) 42%,
    rgba(23, 38, 83, .56) 70%,
    rgba(37, 62, 134, .32) 100%);
}
.hero > .container { position: relative; z-index: 2; }
.hero h1 { color: var(--white); font-size: var(--fs-display); margin-bottom: var(--s-5); }
.hero__lead { font-size: 1.1875rem; color: rgba(255, 255, 255, .84); max-width: 54ch; }
.hero__actions { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-top: var(--s-6); }

.hero--home { padding-block: clamp(4.5rem, 3rem + 9vw, 9.5rem); }
.hero--page { padding-block: clamp(3.5rem, 2.6rem + 4vw, 6rem); }
.hero--page h1 { font-size: var(--fs-h1); }

/* A small trust line under the hero CTAs. */
.hero__trust {
  margin-top: var(--s-6); padding-top: var(--s-5);
  border-top: 1px solid rgba(255, 255, 255, .16);
  display: flex; flex-wrap: wrap; gap: var(--s-3) var(--s-6);
  font-size: var(--fs-sm); color: rgba(255, 255, 255, .78);
}
.hero__trust span { display: inline-flex; align-items: center; gap: var(--s-2); }
.hero__trust i { color: var(--brand-mist); }
/* Kept white rather than the link colour: on the navy wash the default
   blue is close to invisible, and iOS auto-links bare numbers the same
   way — hence the telephone=no meta on every page. */
.hero__trust a { color: var(--white); text-decoration: none; font-weight: 600; }
.hero__trust a:hover, .hero__trust a:focus-visible { text-decoration: underline; }

/* On a phone the hero is tall and narrow, so the 100deg wash — which is at
   its lightest in the bottom-right corner — runs out exactly where the
   address, hours and phone sit. Below 767px the wash goes vertical and
   deepens towards the foot of the hero so the trust line keeps its
   contrast, and the line itself goes full white. */
@media (max-width: 767.98px) {
  .hero::after {
    background: linear-gradient(180deg,
      rgba(23, 38, 83, .88) 0%,
      rgba(23, 38, 83, .80) 45%,
      rgba(23, 38, 83, .88) 100%);
  }
  .hero__trust { color: rgba(255, 255, 255, .94); gap: var(--s-3); }
  .hero__trust span { width: 100%; }
}

/* --------------------------------------------------------------------------
   7. Breadcrumbs
   -------------------------------------------------------------------------- */

.crumbs { background: var(--sand); padding: var(--s-3) 0; font-size: var(--fs-sm); }
.crumbs ol { display: flex; flex-wrap: wrap; gap: var(--s-2); margin: 0; padding: 0; list-style: none; }
.crumbs li { color: var(--charcoal-soft); }
.crumbs li + li::before { content: "/"; margin-right: var(--s-2); color: var(--line-strong); }
.crumbs a { color: var(--brand-deep); font-weight: 600; }
.crumbs [aria-current="page"] { color: var(--charcoal-soft); }

/* --------------------------------------------------------------------------
   8. Cards
   -------------------------------------------------------------------------- */

/* Treatment card */
.t-card {
  display: flex; flex-direction: column; height: 100%;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  transition: transform var(--t), box-shadow var(--t), border-color var(--t);
}
.t-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lift); border-color: transparent; }

.t-card__media { aspect-ratio: 4 / 3; overflow: hidden; background: var(--sand); }
.t-card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--t-slow); }
.t-card:hover .t-card__media img { transform: scale(1.05); }

.t-card__body { padding: var(--s-5); display: flex; flex-direction: column; gap: var(--s-3); flex: 1 1 auto; }
.t-card__tag {
  font-size: var(--fs-xs); font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; color: var(--gold-ink);
}
.t-card h3 { font-size: 1.3rem; margin: 0; }
.t-card p { font-size: var(--fs-sm); color: var(--charcoal-soft); margin: 0; }
.t-card .link-more { margin-top: auto; padding-top: var(--s-2); }

/* Feature / benefit card */
.f-card {
  height: 100%;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--s-6);
  transition: border-color var(--t), box-shadow var(--t);
}
.f-card:hover { border-color: var(--brand-mist); box-shadow: var(--shadow); }
.f-card__icon {
  width: 54px; height: 54px;
  border-radius: 50%;
  background: var(--sand);
  color: var(--brand-deep);
  display: grid; place-items: center;
  font-size: 1.4rem;
  margin-bottom: var(--s-4);
}
.f-card h3 { font-size: 1.2rem; margin-bottom: var(--s-2); }
.f-card p { font-size: var(--fs-sm); color: var(--charcoal-soft); margin: 0; }

.bg-deep .f-card, .bg-deeper .f-card {
  background: rgba(255, 255, 255, .05);
  border-color: rgba(255, 255, 255, .14);
}
.bg-deep .f-card__icon, .bg-deeper .f-card__icon { background: rgba(255, 255, 255, .1); color: var(--brand-mist); }
.bg-deep .f-card p, .bg-deeper .f-card p { color: rgba(255, 255, 255, .76); }

/* Clinician card */
.c-card { height: 100%; display: flex; flex-direction: column; }
/* Square, not 3:4. The practice's headshots are square, circular portraits
   (1254x1254); a 3:4 frame cropped 25% off each side and sliced through the
   circle. A square frame crops them not at all, and takes only 15% off the
   height of the one portrait-shaped photo, where the face stays centred. */
.c-card__photo {
  aspect-ratio: 1 / 1;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--sand);
  margin-bottom: var(--s-4);
}
.c-card__photo img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--t-slow); }
.c-card:hover .c-card__photo img { transform: scale(1.04); }
.c-card h3 { font-size: 1.25rem; margin-bottom: var(--s-1); }
.c-card__role { font-size: var(--fs-sm); font-weight: 600; color: var(--blue-ink); margin-bottom: var(--s-2); }
.c-card__gdc { font-size: var(--fs-xs); color: var(--charcoal-soft); letter-spacing: .04em; }
.c-card__bio { font-size: var(--fs-sm); color: var(--charcoal-soft); margin-top: var(--s-3); }

/* Testimonial */
.quote {
  height: 100%;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--s-6);
  display: flex; flex-direction: column; gap: var(--s-4);
}
.quote__mark { font-family: var(--font-heading); font-size: 3rem; line-height: .6; color: var(--sand-deep); }
.quote p { font-size: 1.0625rem; color: var(--charcoal); margin: 0; }
.quote__by { font-size: var(--fs-sm); font-weight: 700; color: var(--brand-deep); margin-top: auto; }

/* --------------------------------------------------------------------------
   9. Image + text split
   -------------------------------------------------------------------------- */

.split { display: grid; gap: clamp(2rem, 1.5rem + 3vw, 4.5rem); align-items: center; }
@media (min-width: 992px) { .split { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.split--reverse > *:first-child { order: 2; }
@media (max-width: 991.98px) { .split--reverse > *:first-child { order: 0; } }

.split__media { border-radius: var(--r-xl); overflow: hidden; background: var(--sand); aspect-ratio: 4 / 3; }
.split__media img { width: 100%; height: 100%; object-fit: cover; }

/* --------------------------------------------------------------------------
   10. Image placeholders
   The practice's own photography is not available, so every image slot shows
   a labelled frame rather than generic stock. Swap the src and delete .ph.
   -------------------------------------------------------------------------- */

.ph {
  width: 100%; height: 100%;
  display: grid; place-items: center; align-content: center; gap: var(--s-2);
  text-align: center; padding: var(--s-5);
  background:
    linear-gradient(135deg, rgba(25, 114, 159, .12), rgba(232, 224, 212, .5)),
    repeating-linear-gradient(45deg, transparent 0 16px, rgba(37, 62, 134, .04) 16px 32px);
  color: var(--charcoal-soft);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  line-height: 1.6;
}
.ph i { font-size: 1.6rem; color: var(--brand-mist); }
.hero .ph { background: var(--brand-deeper); }

/* --------------------------------------------------------------------------
   11. Process timeline
   -------------------------------------------------------------------------- */

/* These really are a sequence, so the structure says so: each number sits in
   a node on a rail that runs from one step to the next. The rail is a
   horizontal line through the node centres on desktop and a vertical one down
   the left on phones, which is the same information in the shape each screen
   can hold. */

.steps { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-5); counter-reset: step; }
@media (min-width: 768px) { .steps { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: var(--s-4); } }

.steps li { position: relative; counter-increment: step; }

/* The node. The numeral carries the step order, so it is content, not
   decoration — it takes the text-safe gold on light grounds. On the dark band
   the original gold is already well clear of the threshold. */
.steps li::before {
  content: counter(step, decimal-leading-zero);
  position: absolute; top: 0; left: 0;
  z-index: 1;                                  /* sits over the rail */
  width: 48px; height: 48px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--ivory);
  border: 1px solid var(--line-strong);
  font-family: var(--font-heading);
  font-size: 1.15rem;
  line-height: 1;
  color: var(--gold-ink);
}
.bg-deep .steps li::before,
.bg-deeper .steps li::before {
  background: rgba(255, 255, 255, .10);
  border-color: rgba(183, 154, 107, .55);      /* --gold at low alpha */
  color: var(--gold);
}

/* The rail. It runs from the node's edge across the grid gap to the next
   node, so the line is continuous rather than a stub under each number. */
.steps li::after {
  content: "";
  position: absolute;
  background: var(--line-strong);
}
.steps li:last-child::after { display: none; }
.bg-deep .steps li::after { background: rgba(255, 255, 255, .22); }

@media (min-width: 768px) {
  .steps li { padding-top: 68px; }
  .steps li::after {
    top: 24px;                                 /* the node's centre line */
    left: 48px;
    right: calc(-1 * var(--s-4));              /* reaches across the gap */
    height: 1px;
  }
}

/* Phones: the same rail, turned on its side. */
@media (max-width: 767.98px) {
  .steps li { padding-left: 68px; min-height: 48px; }
  .steps li::after {
    left: 23px;                                /* centred under the node */
    top: 52px;
    bottom: calc(-1 * var(--s-5));             /* down into the next step */
    width: 1px;
  }
}

.steps h3 {
  font-size: 1.15rem;
  font-family: var(--font-body);
  font-weight: 700;
  letter-spacing: -.01em;
  margin-bottom: var(--s-2);
}
.steps p { font-size: var(--fs-sm); line-height: 1.65; color: var(--charcoal-soft); margin: 0; }
.bg-deep .steps p { color: rgba(255, 255, 255, .82); }

/* --------------------------------------------------------------------------
   12. Accordion (FAQ + treatment details)
   -------------------------------------------------------------------------- */

.acc { display: grid; gap: var(--s-3); }

.acc__item {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
  transition: border-color var(--t);
}
.acc__item[open] { border-color: var(--brand-mist); }

.acc__q {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s-4);
  padding: var(--s-4) var(--s-5);
  cursor: pointer;
  font-weight: 700;
  font-size: 1.0625rem;
  color: var(--brand-deep);
  list-style: none;
  transition: background var(--t);
}
.acc__q::-webkit-details-marker { display: none; }
.acc__q:hover { background: var(--ivory); }

/* A plus that becomes a minus — says what the control does more plainly
   than a chevron, and it is drawn, so no icon font can fail it. */
.acc__q::after {
  content: ""; flex: none;
  width: 14px; height: 14px; margin-top: 7px;
  background:
    linear-gradient(currentColor, currentColor) center / 100% 2px no-repeat,
    linear-gradient(currentColor, currentColor) center / 2px 100% no-repeat;
  opacity: .5;
  transition: transform var(--t), opacity var(--t);
}
.acc__item[open] .acc__q::after {
  background: linear-gradient(currentColor, currentColor) center / 100% 2px no-repeat;
  transform: rotate(90deg);
  opacity: 1;
}

.acc__a {
  padding: 0 var(--s-5) var(--s-5);
  font-size: var(--fs-sm);
  color: var(--charcoal-soft);
}
.acc__a > :first-child { margin-top: 0; }

/* --------------------------------------------------------------------------
   13. Price tables
   -------------------------------------------------------------------------- */

.price-block { margin-bottom: var(--s-8); }
.price-block__title {
  display: flex; align-items: baseline; gap: var(--s-3);
  padding-bottom: var(--s-3);
  border-bottom: 2px solid var(--brand-deep);
  margin-bottom: 0;
}
.price-block__title h3 { margin: 0; }

.price-table { width: 100%; border-collapse: collapse; }
.price-table caption { text-align: left; padding-bottom: var(--s-3); color: var(--charcoal-soft); font-size: var(--fs-sm); }
.price-table th, .price-table td {
  padding: var(--s-4) var(--s-3);
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: top;
}
.price-table th {
  font-weight: 500;
  font-size: var(--fs-body);
  color: var(--charcoal);
}
.price-table td {
  text-align: right;
  white-space: nowrap;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--brand-deep);
  width: 1%;
}
.price-table tbody tr:hover { background: var(--white); }
.price-table .is-quote { font-weight: 600; color: var(--charcoal-soft); font-size: var(--fs-sm); }

.price-note {
  background: var(--white);
  border-left: 3px solid var(--gold);
  border-radius: var(--r-sm);
  padding: var(--s-5);
  font-size: var(--fs-sm);
  color: var(--charcoal-soft);
}

/* Sticky in-page price nav */
.price-nav { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.price-nav a {
  display: inline-block;
  padding: var(--s-2) var(--s-4);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--brand-deep);
  transition: background var(--t), color var(--t), border-color var(--t);
}
.price-nav a:hover { background: var(--brand-deep); border-color: var(--brand-deep); color: var(--white); }

/* Clinician availability */
.avail { display: grid; gap: var(--s-4); }
@media (min-width: 768px) { .avail { grid-template-columns: repeat(3, 1fr); } }
.avail__card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--s-5);
}
.avail__who {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding-bottom: var(--s-4);
  margin-bottom: var(--s-4);
  border-bottom: 1px solid var(--line);
}
.avail__ini {
  width: 52px; height: 52px; flex: none;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--brand-deep) 0%, var(--brand-mid) 100%);
  color: var(--white);
  display: grid; place-items: center;
  font-family: var(--font-heading);
  font-size: 1.05rem;
  letter-spacing: .02em;
}

/* Name above role. They were two inline spans with nothing between them, so
   they rendered as "Dr VinoDentist". */
.avail__id { display: grid; gap: 2px; min-width: 0; }
.avail__name { font-weight: 700; line-height: 1.25; color: var(--brand-deep); }
.avail__role {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--gold-ink);
}

.avail__days { list-style: none; margin: 0; padding: 0; display: grid; font-size: var(--fs-sm); }
.avail__days li {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3) 0;
  border-bottom: 1px dashed var(--line);
}
.avail__days li:first-child { padding-top: 0; }
.avail__days li:last-child { border-bottom: 0; padding-bottom: 0; }

.avail__day { display: inline-flex; align-items: center; gap: var(--s-2); font-weight: 600; }
.avail__day i { color: var(--brand-mid); font-size: .95em; }

/* The time is the thing being looked up, so it is the thing that stands out. */
.avail__time {
  flex: none;
  padding: 3px var(--s-3);
  border-radius: var(--r-pill);
  background: rgba(25, 114, 159, .10);
  color: var(--blue-ink);
  font-size: var(--fs-xs);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.avail__card { transition: box-shadow var(--t), transform var(--t), border-color var(--t); }
.avail__card:hover { box-shadow: var(--shadow-lift); border-color: transparent; transform: translateY(-3px); }
@media (prefers-reduced-motion: reduce) {
  .avail__card, .avail__card:hover { transition: none; transform: none; }
}

/* --------------------------------------------------------------------------
   14. Forms
   -------------------------------------------------------------------------- */

.contact-form-wrapper {
  background: var(--ivory);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  padding: clamp(1.5rem, 1.2rem + 1.4vw, 2.5rem);
}
.bg-deep .contact-form-wrapper, .bg-deeper .contact-form-wrapper {
  background: rgba(255, 255, 255, .05);
  border-color: rgba(255, 255, 255, .16);
}

.form-head { margin-bottom: var(--s-5); }
.form-head h3 { margin-bottom: var(--s-2); }
.form-head p { font-size: var(--fs-sm); color: var(--charcoal-soft); margin: 0; }
.bg-deep .form-head p { color: rgba(255, 255, 255, .76); }

.field { margin-bottom: var(--s-4); }
.field label {
  display: block;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--brand-deep);
  margin-bottom: var(--s-2);
}
.bg-deep .field label { color: var(--white); }
.field .req { color: var(--error); }
.bg-deep .field .req { color: #F0A9A2; }

.contact-form-wrapper input,
.contact-form-wrapper select,
.contact-form-wrapper textarea {
  width: 100%;
  min-height: 52px;
  border: 1px solid #D8DED8;
  border-radius: 12px;
  padding: 13px 16px;
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.6;
  background: var(--white);
  color: var(--charcoal);
  transition: border-color var(--t), box-shadow var(--t);
}
.contact-form-wrapper textarea { min-height: 140px; resize: vertical; }

.contact-form-wrapper input:focus,
.contact-form-wrapper select:focus,
.contact-form-wrapper textarea:focus {
  outline: none;
  border-color: var(--brand-deep);
  box-shadow: 0 0 0 3px rgba(37, 62, 134, .14);
}

.contact-form-wrapper input[type="submit"],
.contact-form-wrapper button[type="submit"],
.btn-submit {
  width: auto;
  min-height: 52px;
  background: var(--brand-deep);
  color: var(--white);
  border: none;
  border-radius: var(--r-pill);
  padding: 14px 32px;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--fs-sm);
  cursor: pointer;
  transition: background var(--t);
}
.contact-form-wrapper button[type="submit"]:hover, .btn-submit:hover { background: var(--brand-deeper); }
.btn-submit:disabled { opacity: .6; cursor: default; }
.bg-deep .btn-submit { background: var(--white); color: var(--brand-deep); }
.bg-deep .btn-submit:hover { background: var(--sand); }

.field__help { font-size: var(--fs-xs); color: var(--charcoal-soft); margin-top: var(--s-2); }
.field__error { display: none; font-size: var(--fs-xs); color: var(--error); margin-top: var(--s-2); font-weight: 600; }
.field.is-invalid input,
.field.is-invalid select,
.field.is-invalid textarea { border-color: var(--error); }
.field.is-invalid .field__error { display: block; }
.field.is-valid input, .field.is-valid select, .field.is-valid textarea { border-color: var(--brand-mist); }

.form-note {
  display: none;
  padding: var(--s-4) var(--s-5);
  border-radius: var(--r);
  border-left: 4px solid;
  font-size: var(--fs-sm);
  margin-bottom: var(--s-5);
}
.form-note.is-shown { display: block; }
.form-note--ok { background: var(--success-bg); border-color: var(--success); color: #204E3C; }
.form-note--err { background: var(--error-bg); border-color: var(--error); color: #7B2B24; }

.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* The shortcode marker shown in the prototype only. */
.cf7-marker {
  display: flex; align-items: flex-start; gap: var(--s-3);
  background: rgba(183, 154, 107, .1);
  border: 1px dashed var(--gold);
  border-radius: var(--r-sm);
  padding: var(--s-3) var(--s-4);
  margin-bottom: var(--s-5);
  font-size: var(--fs-xs);
  line-height: 1.6;
  color: var(--charcoal-soft);
}
.cf7-marker code { font-size: var(--fs-xs); color: var(--brand-deep); background: var(--white); padding: 1px 6px; border-radius: 4px; word-break: break-all; }
.cf7-marker i { color: var(--gold); margin-top: 3px; }
.bg-deep .cf7-marker { background: rgba(255, 255, 255, .06); color: rgba(255, 255, 255, .8); }
.bg-deep .cf7-marker code { background: rgba(0, 0, 0, .25); color: var(--white); }

/* --------------------------------------------------------------------------
   15. Contact details, map, gallery
   -------------------------------------------------------------------------- */

.detail-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-5); }
.detail-list li { display: flex; gap: var(--s-4); }
.detail-list i { font-size: 1.15rem; color: var(--blue-ink); flex: none; margin-top: 5px; }
.detail-list strong { display: block; font-size: var(--fs-sm); color: var(--brand-deep); margin-bottom: 2px; }
.detail-list a, .detail-list address, .detail-list span { font-size: var(--fs-sm); font-style: normal; color: var(--charcoal-soft); margin: 0; }
.detail-list a { text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--line-strong); }
.detail-list a:hover { color: var(--brand-deep); text-decoration-color: currentColor; }
/* The footer is a dark ground too, but it carries .site-footer rather than
   .bg-deeper — so these overrides have to name it, or the labels render
   #123647 on #0C2632 and vanish. That is exactly what happened. */
.bg-deep .detail-list strong, .bg-deeper .detail-list strong,
.site-footer .detail-list strong { color: var(--white); }
.bg-deep .detail-list i, .bg-deeper .detail-list i,
.site-footer .detail-list i { color: var(--brand-mist); }
.bg-deep .detail-list a, .bg-deep .detail-list address, .bg-deep .detail-list span,
.bg-deeper .detail-list a, .bg-deeper .detail-list address, .bg-deeper .detail-list span,
.site-footer .detail-list a, .site-footer .detail-list address, .site-footer .detail-list span { color: rgba(255, 255, 255, .78); }

.map-frame { border-radius: var(--r-xl); overflow: hidden; border: 1px solid var(--line); background: var(--sand); }
.map-frame iframe { display: block; width: 100%; height: 430px; border: 0; }
.map-frame .ph { height: 430px; }

.gallery { display: grid; gap: var(--s-3); grid-template-columns: repeat(2, 1fr); }
@media (min-width: 768px) { .gallery { grid-template-columns: repeat(4, 1fr); } }
.gallery__item { aspect-ratio: 1 / 1; border-radius: var(--r); overflow: hidden; background: var(--sand); }
.gallery__item img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--t-slow); }
.gallery__item:hover img { transform: scale(1.06); }

/* --------------------------------------------------------------------------
   16. CTA band
   -------------------------------------------------------------------------- */

.cta-band { text-align: center; }
.cta-band h2 { max-width: 20ch; margin-inline: auto; }
.cta-band p { max-width: 58ch; margin-inline: auto; }
.cta-band__actions { display: flex; flex-wrap: wrap; gap: var(--s-3); justify-content: center; margin-top: var(--s-6); }

/* --------------------------------------------------------------------------
   17. Footer
   -------------------------------------------------------------------------- */

.site-footer { background: var(--brand-deeper); color: rgba(255, 255, 255, .72); padding-top: var(--s-9); font-size: var(--fs-sm); }
.site-footer h2, .site-footer h3 { color: var(--white); }
.site-footer__brand img {
  height: 76px; width: auto;
  /* The logo is dark blue on transparent; on the deep ground it needs to be
     light. Until a white version is supplied, this inverts and re-tints it —
     the mark is unchanged in shape and proportion. Replace with the supplied
     reversed logo when available (see README §3). */
  filter: brightness(0) invert(1) opacity(.92);
}
.site-footer__intro { margin-top: var(--s-4); max-width: 34ch; color: rgba(255, 255, 255, .66); }

.footer-title {
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--white);
  margin-bottom: var(--s-4);
}
.site-footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-2); }
.site-footer a { color: rgba(255, 255, 255, .72); }
.site-footer a:hover { color: var(--white); }

/* The socials list appears on two different grounds — the dark footer and the
   light Contact Us page — so it is self-contained here rather than borrowing
   list-style and padding from `.site-footer ul`. It borrowed them before, and
   the copy on Contact Us was left with visible list bullets and white icons on
   a white ground.

   `.site-footer ul` also sets display:grid and, carrying one more element than
   a bare `.socials`, was winning the display contest and stacking the icons
   into a column — hence the qualified selectors. */
.socials,
.site-footer ul.socials,
.site-footer .socials {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3);
  list-style: none;
  margin: var(--s-5) 0 0;
  padding: 0;
}
.socials li { display: inline-flex; }          /* no marker box to leave a gap */

/* Default: the light ground. The footer overrides below. */
.socials a {
  width: 44px; height: 44px;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  display: grid; place-items: center;
  /* Belt and braces: `place-items` centres the glyph while this is a grid,
     but `justify-content` keeps it centred if anything ever flips the box to
     flex again, as the footer tap-target rule once did. */
  justify-content: center;
  color: var(--brand-deep);
  background: var(--white);
  font-size: 1.05rem;
  text-decoration: none;
  transition: background var(--t), border-color var(--t), color var(--t), transform var(--t);
}
.socials a:hover,
.socials a:focus-visible {
  background: var(--brand-deep);
  border-color: var(--brand-deep);
  color: var(--white);
  transform: translateY(-2px);
}
.socials a:focus-visible { outline: 3px solid var(--gold); outline-offset: 2px; }

/* Dark ground — the footer. */
.site-footer .socials a,
.bg-deep .socials a,
.bg-deeper .socials a {
  border-color: rgba(255, 255, 255, .22);
  background: rgba(255, 255, 255, .06);
  color: rgba(255, 255, 255, .85);
}
.site-footer .socials a:hover,
.site-footer .socials a:focus-visible,
.bg-deep .socials a:hover,
.bg-deeper .socials a:hover {
  background: var(--white);
  border-color: var(--white);
  color: var(--brand-deeper);
}

@media (prefers-reduced-motion: reduce) {
  .socials a, .socials a:hover, .socials a:focus-visible { transition: none; transform: none; }
}

.footer-bottom {
  margin-top: var(--s-8);
  border-top: 1px solid rgba(255, 255, 255, .14);
  padding-block: var(--s-5);
  font-size: var(--fs-xs);
  color: rgba(255, 255, 255, .6);
}
.footer-bottom ul { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-5); }

/* --------------------------------------------------------------------------
   18. Motion — subtle, and fully opt-out
   -------------------------------------------------------------------------- */

.reveal { opacity: 0; transform: translateY(18px); transition: opacity .7s ease, transform .7s ease; }
.reveal.is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; }
  .reveal { opacity: 1; transform: none; transition: none; }
  .btn-ls:hover, .t-card:hover { transform: none; }
  .t-card:hover .t-card__media img, .gallery__item:hover img, .c-card:hover .c-card__photo img { transform: none; }
}

/* --------------------------------------------------------------------------
   19. Mobile refinements
   -------------------------------------------------------------------------- */

@media (max-width: 575.98px) {
  .hero__actions .btn-ls, .cta-band__actions .btn-ls { width: 100%; }
  .price-table th, .price-table td { padding: var(--s-3) var(--s-2); font-size: var(--fs-sm); }
  .t-card__body, .f-card, .quote { padding: var(--s-5); }
  .map-frame iframe, .map-frame .ph { height: 320px; }
}

/* Phone and email are the most-tapped links on a practice site. Inline they
   are ~21px tall, which is awkward on a phone. */
@media (max-width: 767.98px) {
  .detail-list a[href^="tel:"],
  .detail-list a[href^="mailto:"],
  .topbar a[href^="tel:"],
  .site-footer a[href^="tel:"],
  .site-footer a[href^="mailto:"] { display: inline-flex; align-items: center; min-height: 44px; }

  /* Footer and legal links are navigation on a phone, and inline they
     measured 18px tall. Given a real tap target without changing the type.

     `.socials` is excluded deliberately. Those anchors are already 44px
     circles centred with `place-items: center`, and `.site-footer ul a`
     (0,1,2) outranks `.socials a` (0,1,1) — so this rule was replacing their
     grid box with a flex one. `justify-items` does nothing in flex, which
     left every icon glyph hard against the left edge of its circle: the
     off-centre Facebook and Instagram icons reported from a phone, and in
     fact all five, but only visible on the ones whose glyph fills its box. */
  .site-footer ul:not(.socials) a,
  .footer-bottom ul a { display: inline-flex; align-items: center; min-height: 44px; }
  .site-footer ul:not(.socials) { gap: 0; }
}

/* Long price tables scroll inside their own container, never the page. */
.table-scroll { overflow-x: auto; }

@media print {
  .site-header, .topbar, .site-footer, .cta-band, .map-frame, .btn-ls { display: none !important; }
  body { background: #fff; font-size: 11pt; }
}

/* --------------------------------------------------------------------------
   20. Visit strip — sits above the closing CTA on every page

   Address, opening hours, how to reach us, Google reviews and directions. It
   repeats site-wide on purpose: whatever page a patient lands on, the details
   they need to actually visit are one scroll from the bottom.
   -------------------------------------------------------------------------- */

.visit-strip {
  background: var(--sand);
  border-top: 1px solid var(--line);
  padding-block: clamp(2.5rem, 2rem + 2vw, 4rem);
}

.visit-grid { display: grid; gap: var(--s-6); }
@media (min-width: 768px)  { .visit-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1200px) { .visit-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s-5); } }

.visit-cell { display: flex; gap: var(--s-4); align-items: flex-start; }

.visit-cell__icon {
  flex: none;
  width: 44px; height: 44px;
  border-radius: 50%;
  background: var(--white);
  color: var(--brand-deep);
  display: grid; place-items: center;
  font-size: 1.15rem;
}

.visit-cell__label {
  display: block;
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--gold-ink);
  margin-bottom: var(--s-2);
}

.visit-cell__body {
  font-size: var(--fs-sm);
  line-height: 1.7;
  color: var(--charcoal);
  font-style: normal;
  margin: 0;
}
.visit-cell__body a { color: var(--charcoal); text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--line-strong); }
.visit-cell__body a:hover { color: var(--brand-deep); text-decoration-color: currentColor; }

.visit-cell__note { font-size: var(--fs-xs); color: var(--charcoal-soft); margin-top: var(--s-2); }

/* The actions column stacks its two controls and fills the cell. */
.visit-cell--actions { flex-direction: column; align-items: stretch; gap: var(--s-3); }

/* Google review badge.

   Deliberately carries no star rating and no review count — the practice
   publishes neither, and a fabricated one would be an invented credential.
   It is a door to the real reviews, not a claim about them. */
.gbadge {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r);
  transition: border-color var(--t), box-shadow var(--t), transform var(--t);
}
.gbadge:hover { border-color: var(--brand-mid); box-shadow: var(--shadow); transform: translateY(-2px); }

.gbadge__g {
  flex: none;
  width: 38px; height: 38px;
  border-radius: 50%;
  background: var(--ivory);
  display: grid; place-items: center;
}
.gbadge__g svg { display: block; }

.gbadge__title {
  display: block;
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--brand-deep);
  line-height: 1.3;
}
.gbadge__sub { display: block; font-size: var(--fs-xs); color: var(--charcoal-soft); margin-top: 2px; }

.visit-cell--actions .btn-ls { width: 100%; }

@media (prefers-reduced-motion: reduce) { .gbadge:hover { transform: none; } }

/* On a phone the whole strip is the thing people tap. */
@media (max-width: 767.98px) {
  .visit-cell__body a[href^="tel:"],
  .visit-cell__body a[href^="mailto:"] { display: inline-flex; align-items: center; min-height: 44px; }
}

/* --------------------------------------------------------------------------
   21. How to reach us — tabbed travel guidance beside the map
   -------------------------------------------------------------------------- */

.reach { background: var(--ivory); }

.reach__grid { display: grid; gap: clamp(2rem, 1.5rem + 2.5vw, 3.5rem); align-items: start; }
@media (min-width: 992px) { .reach__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }

/* Tabs ------------------------------------------------------------------- */
.reach__tabs {
  display: flex; flex-wrap: wrap; gap: var(--s-2);
  margin-bottom: var(--s-5);
}

.reach__tab {
  display: inline-flex; align-items: center; gap: var(--s-2);
  min-height: 44px;
  padding: var(--s-2) var(--s-4);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  background: transparent;
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--brand-deep);
  cursor: pointer;
  transition: background var(--t), color var(--t), border-color var(--t);
}
.reach__tab:hover { background: var(--white); border-color: var(--brand-mid); }

/* The selected tab is filled AND carries an icon — never colour alone. */
.reach__tab.is-active,
.reach__tab[aria-selected="true"] {
  background: var(--brand-deep);
  border-color: var(--brand-deep);
  color: var(--white);
}

.reach__body { min-height: 230px; }
.reach__body h3 { font-size: 1.25rem; margin-bottom: var(--s-3); }
.reach__body p { font-size: var(--fs-sm); line-height: 1.75; color: var(--charcoal); }

.reach__list { list-style: none; margin: 0 0 var(--s-4); padding: 0; display: grid; gap: var(--s-3); }
.reach__list li {
  position: relative;
  padding-left: var(--s-5);
  font-size: var(--fs-sm);
  line-height: 1.7;
}
.reach__list li::before {
  content: ""; position: absolute; left: 0; top: .65em;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--brand-mid);
}

.reach__confirm { font-size: var(--fs-xs) !important; color: var(--charcoal-soft) !important; }

.reach__actions { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-5); }

/* Map side --------------------------------------------------------------- */
.reach__map .map-frame iframe { height: 420px; }
.reach__addr {
  margin-top: var(--s-4);
  font-size: var(--fs-sm);
  line-height: 1.7;
  color: var(--charcoal-soft);
}
.reach__addr strong { color: var(--brand-deep); }

@media (max-width: 575.98px) {
  .reach__tab { flex: 1 1 auto; justify-content: center; }
  .reach__body { min-height: 0; }
  .reach__map .map-frame iframe { height: 300px; }
  .reach__actions .btn-ls { flex: 1 1 100%; }
}

/* --------------------------------------------------------------------------
   22. Cookie banner

   A card in the corner rather than a full-width bar: it does not cover the
   page, the choice is genuine (reject is as prominent as accept, not hidden
   behind "customise"), and nothing is loaded before consent is given.
   -------------------------------------------------------------------------- */

.cookie {
  position: fixed;
  left: var(--s-5); bottom: var(--s-5);
  z-index: 1080;
  width: min(430px, calc(100vw - 2 * var(--s-5)));
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  box-shadow: 0 24px 60px rgba(23, 38, 83, .20), 0 4px 12px rgba(23, 38, 83, .08);
  padding: var(--s-6);
  animation: cookie-in .45s cubic-bezier(.4, 0, .2, 1) both;
}
.cookie[hidden] { display: none; }

@keyframes cookie-in {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: none; }
}

.cookie__inner { display: grid; gap: var(--s-4); }

.cookie__icon {
  width: 46px; height: 46px;
  border-radius: 50%;
  background: var(--brand-deep);
  color: var(--white);
  display: grid; place-items: center;
  font-size: 1.25rem;
}

.cookie__title { font-size: 1.3rem; margin: 0 0 var(--s-2); }

.cookie__text p {
  font-size: var(--fs-sm);
  line-height: 1.65;
  color: var(--charcoal-soft);
  margin: 0;
}
.cookie__text a { color: var(--brand-deep); text-decoration: underline; text-underline-offset: 3px; }

.cookie__options {
  display: grid; gap: var(--s-3);
  margin-top: var(--s-4);
  padding-top: var(--s-4);
  border-top: 1px solid var(--line);
}
.cookie__options[hidden] { display: none; }

.cookie__opt { display: flex; gap: var(--s-3); align-items: flex-start; font-size: var(--fs-xs); line-height: 1.6; color: var(--charcoal-soft); cursor: pointer; }
.cookie__opt input { width: 18px; height: 18px; margin-top: 2px; flex: none; accent-color: var(--brand-deep); }
.cookie__opt input:disabled { opacity: .55; cursor: default; }
.cookie__opt strong { color: var(--brand-deep); }

.cookie__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); }
.cookie__actions .btn-ls { flex: 1 1 auto; }

.cookie__link {
  background: none; border: 0;
  padding: var(--s-2) var(--s-3);
  min-height: 44px;
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--charcoal-soft);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
  flex: 0 0 auto;
}
.cookie__link:hover { color: var(--brand-deep); }

@media (max-width: 575.98px) {
  .cookie {
    left: var(--s-3); right: var(--s-3); bottom: var(--s-3);
    width: auto;
    padding: var(--s-5);
    border-radius: var(--r-lg);
  }
  .cookie__actions .btn-ls { flex: 1 1 100%; }
}

@media (prefers-reduced-motion: reduce) { .cookie { animation: none; } }

/* --------------------------------------------------------------------------
   23. Why choose us — four points around a central illustration
   -------------------------------------------------------------------------- */

.why { background: var(--sand); }

.why__grid { display: grid; gap: var(--s-5); align-items: center; }

/* Mobile: image first, then the four cards. The illustration is the anchor,
   so it leads rather than being buried between card pairs. */
.why__media { order: -1; }

@media (min-width: 992px) {
  .why__grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr) minmax(0, 1fr);
    gap: var(--s-6);
  }
  .why__media { order: 0; }
}

.why__col { display: grid; gap: var(--s-5); }

.why__card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--s-5);
  transition: transform var(--t), box-shadow var(--t);
}
.why__card:hover { transform: translateY(-3px); box-shadow: var(--shadow-lift); }

.why__icon {
  width: 52px; height: 52px;
  border-radius: 50%;
  background: var(--brand-deep);
  color: var(--white);
  display: grid; place-items: center;
  font-size: 1.3rem;
  margin-bottom: var(--s-4);
}

.why__card h3 { font-size: 1.15rem; margin-bottom: var(--s-2); }
.why__card p { font-size: var(--fs-sm); line-height: 1.7; color: var(--charcoal-soft); margin: 0; }

.why__media img { width: 100%; height: auto; max-width: 520px; margin-inline: auto; }

@media (prefers-reduced-motion: reduce) { .why__card:hover { transform: none; } }

/* --------------------------------------------------------------------------
   Sticky action rail — book / call / email / find us

   Fixed to the right edge on desktop, centred vertically. On phones it
   becomes a bottom bar: a vertical rail on a 375px screen sits on top of the
   content it exists to support, and a thumb reaches the bottom of a phone far
   more easily than its right edge.

   It sits above the header (1040) and below the cookie banner (1080), so a
   first-time visitor's consent choice is never obscured by it.
   -------------------------------------------------------------------------- */

.rail {
  position: fixed;
  right: var(--s-4);
  top: 50%;
  transform: translateY(-50%);
  z-index: 1050;
}

.rail__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1px;                                    /* hairline between items */
  background: var(--line);                     /* shows through the gaps */
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: 0 14px 40px rgba(23, 38, 83, .16), 0 2px 8px rgba(23, 38, 83, .08);
}

.rail__item {
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 4px;
  width: 84px;
  min-height: 78px;
  padding: var(--s-3) var(--s-2);
  background: var(--white);
  color: var(--brand-deep);
  text-decoration: none;
  transition: background .2s ease, color .2s ease;
}

.rail__icon { font-size: 1.35rem; line-height: 1; }

.rail__label {
  font-size: .625rem;                          /* a label, not running text */
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  text-align: center;
  line-height: 1.25;
}

.rail__item:hover,
.rail__item:focus-visible { background: var(--brand-deep); color: var(--white); }

/* Book Now leads, so it carries the fill rather than waiting for a hover. */
.rail__item--accent { background: var(--brand-deep); color: var(--white); }
.rail__item--accent:hover,
.rail__item--accent:focus-visible { background: var(--brand-deeper); }

.rail__item:focus-visible { outline: 3px solid var(--gold); outline-offset: -3px; }

/* Tablet and down: a bottom bar, five equal columns. */
@media (max-width: 991.98px) {
  .rail {
    right: 0; left: 0; top: auto; bottom: 0;
    transform: none;
  }
  .rail__list {
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    border-radius: 0;
    box-shadow: 0 -6px 24px rgba(23, 38, 83, .16);
  }
  .rail__item { width: auto; min-height: 60px; padding: var(--s-2) var(--s-1); }
  .rail__icon { font-size: 1.2rem; }
  .rail__label { font-size: .5625rem; letter-spacing: .06em; }

  /* The bar owns the bottom of the screen, so everything that also lives
     there is lifted clear of it rather than hidden behind it. */
  body { padding-bottom: 60px; }
  .cookie { bottom: calc(60px + var(--s-3)); }
}

@media (max-width: 575.98px) {
  .rail__item { padding: var(--s-2) 2px; }
}

@media (prefers-reduced-motion: reduce) {
  .rail__item { transition: none; }
}

/* --------------------------------------------------------------------------
   Back to top

   Bottom-right, below the rail's vertical band on desktop and above the
   bottom bar on mobile. Hidden until JavaScript decides there is enough page
   behind you to warrant it.
   -------------------------------------------------------------------------- */

.to-top {
  position: fixed;
  right: var(--s-4);
  bottom: var(--s-5);
  z-index: 1050;
  width: 46px; height: 46px;
  display: grid; place-items: center;
  border-radius: var(--r-pill);
  background: var(--white);
  color: var(--brand-deep);
  border: 1px solid var(--line);
  box-shadow: 0 10px 28px rgba(23, 38, 83, .16);
  font-size: 1.1rem;
  text-decoration: none;
  animation: to-top-in .25s ease both;
  transition: background .2s ease, color .2s ease, transform .2s ease;
}
.to-top[hidden] { display: none; }
.to-top:hover,
.to-top:focus-visible { background: var(--brand-deep); color: var(--white); transform: translateY(-3px); }
.to-top:focus-visible { outline: 3px solid var(--gold); outline-offset: 2px; }

@keyframes to-top-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* #main receives focus programmatically after the jump; it should not then
   draw a focus ring around the entire page. */
#main:focus { outline: none; }

@media (max-width: 991.98px) {
  .to-top { bottom: calc(60px + var(--s-3)); }
}

@media (prefers-reduced-motion: reduce) {
  .to-top { animation: none; transition: none; }
  .to-top:hover, .to-top:focus-visible { transform: none; }
}

/* --------------------------------------------------------------------------
   Practice highlights — the stats band

   Six tiles on the primary ground. The two awaiting a confirmed figure are
   deliberately not disguised: a dashed edge, a dash instead of a number and a
   label saying what is needed. A placeholder that looks like data is how an
   invented number reaches a live site.
   -------------------------------------------------------------------------- */

.stats-band .sec-head { margin-bottom: var(--s-7); }

.stats-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: var(--s-4);
}

.stat {
  display: grid;
  justify-items: center;
  align-content: start;
  gap: var(--s-2);
  padding: var(--s-5) var(--s-3);
  text-align: center;
  border-radius: var(--r-lg);
  background: rgba(255, 255, 255, .08);
  border: 1px solid rgba(255, 255, 255, .16);
  color: var(--white);
}

.stat__icon {
  display: grid; place-items: center;
  width: 54px; height: 54px;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, .12);
  font-size: 1.4rem;
  margin-bottom: var(--s-1);
}

.stat__n {
  font-family: var(--font-heading);
  font-size: clamp(2rem, 1.5rem + 1.4vw, 2.9rem);
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
}

.stat__label {
  font-size: var(--fs-sm);
  font-weight: 600;
  line-height: 1.4;
  color: rgba(255, 255, 255, .88);
}

/* Awaiting a real figure — visibly a slot, never mistaken for data. */
.stat--pending {
  background: rgba(255, 255, 255, .04);
  border-style: dashed;
  border-color: rgba(255, 255, 255, .32);
}
.stat--pending .stat__icon { background: rgba(255, 255, 255, .07); }
.stat__n--slot { color: rgba(255, 255, 255, .45); }
.stat__need {
  font-size: var(--fs-xs);
  letter-spacing: .06em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--gold);
  margin-top: var(--s-1);
}

@media (max-width: 991.98px) { .stats-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 575.98px) {
  .stats-grid { grid-template-columns: repeat(2, 1fr); gap: var(--s-3); }
  .stat { padding: var(--s-4) var(--s-2); }
  .stat__icon { width: 44px; height: 44px; font-size: 1.15rem; }
}
