/* =====================================================================
   Dr Sarhan Dental Emergency 24/7
   Dark clinical system: near-black stage, one blue.
   Two typefaces only: Adventor for titles, Helvetica for everything else.

   Adventor is TeX Gyre Adventor, the GUST-licensed free cut of ITC Avant
   Garde Gothic - the face the 700 slot was already set in. It replaced the
   Monotype Century Gothic + ITC Avant Garde files on 2026-08-18: those are
   desktop fonts, and the bold one carried fsType 4 (no embedding), so
   serving them publicly was not covered by any licence held here. Both
   weights now come from one matched family instead of two mixed ones, the
   subset is smaller than what it replaced, and it carries the middot the
   old subset was missing. Advance widths land within ~5% of the old files,
   so nothing reflows.
   ===================================================================== */

@font-face{
  font-family:"Adventor";
  src:url("../assets/fonts/Adventor-Regular.woff2") format("woff2"),
      url("../assets/fonts/Adventor-Regular.woff") format("woff");
  font-weight:400;
  font-style:normal;
  font-display:swap;
}
@font-face{
  font-family:"Adventor";
  src:url("../assets/fonts/Adventor-Bold.woff2") format("woff2"),
      url("../assets/fonts/Adventor-Bold.woff") format("woff");
  font-weight:700;
  font-style:normal;
  font-display:swap;
}


:root{
  --display: "Adventor", "Century Gothic", "Avant Garde", "Avenir Next", "Helvetica Neue", sans-serif;
  --sans:    "Helvetica Neue", Helvetica, Arial, sans-serif;

  /* --- surface --------------------------------------------------- */
  --bg:            #000205;          /* near-black, cool cast, never flat #000 */
  --bg-raise:      #04070d;
  --surface-1:     rgba(255,255,255,.028);
  --surface-2:     rgba(255,255,255,.052);
  --border:        rgba(255,255,255,.09);
  --border-soft:   rgba(255,255,255,.055);

  /* --- ink ------------------------------------------------------- */
  --text:          #ffffff;
  --text-2:        #99a2b2;
  /* Was #626b7b, which measured 3.87:1 on this background and failed WCAG AA
     for body text. This carries the quiet copy - the areas note, the step
     times, the form labels, the footer - and half of it is read at 2am by
     someone in pain, which is the worst possible case for a dim grey.
     #727c8d is 4.93:1, still clearly the third tier, now legible. */
  --text-3:        #727c8d;

  /* --- accent ---------------------------------------------------- */
  --blue:          #4da2ff;
  --blue-hot:      #7cbcff;
  --blue-deep:     #1668e3;
  --blue-ink:      #051a35;
  --logo-mark:     var(--blue);
  --logo-word:     #ffffff;


  /* --- geometry -------------------------------------------------- */
  --r-ctl:  8px;
  --r-card: 14px;
  --r-stage: 26px;
  --r-pill: 999px;
  --wrap: 1400px;
  --gut: clamp(20px, 4vw, 48px);
  --nav-h: 74px;

  /* Entrances and exits take --ease, movement on screen takes --ease-io.
     --ease was cubic-bezier(.22,.61,.36,1), which leaves too much of its
     travel in the tail: everything it drove - buttons, nav, the reveal,
     the accordions - arrived softly rather than promptly. This curve puts
     the distance up front, so the moment you are actually watching is the
     fast one. Both are the standard strong pair. */
  --ease:    cubic-bezier(.23,1,.32,1);
  --ease-io: cubic-bezier(.77,0,.175,1);

  /* --- accordions ------------------------------------------------
     Emergencies, first aid and the FAQ are the same component three
     times over. They had drifted to .97/.98/1.02rem, line-heights of
     1.3 and 1.55, and three different paddings, which is why they read
     as three different things. One set of values now drives all three;
     change it here, not in the component. */
  --acc-size: 1.02rem;
  --acc-lh:   1.35;
  --acc-pad:  18px 20px;
  --acc-gap:  16px;
}

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

html{ scroll-behavior:smooth; scroll-padding-top: calc(var(--nav-h) + 18px); }
@media (prefers-reduced-motion: reduce){ html{ scroll-behavior:auto; } }

body{
  margin:0;
  background:var(--bg);
  color:var(--text);
  font-family:var(--sans);
  font-weight:400;
  font-size:16px;
  line-height:1.55;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  overflow-x:hidden;
}

img,svg,iframe{ max-width:100%; display:block; }
a{ color:inherit; text-decoration:none; }
button{ font:inherit; color:inherit; background:none; border:0; cursor:pointer; }

::selection{ background:var(--blue); color:#00111f; }

/* ---------------------------------------------------------------- cursor
   A tooth follows the pointer, blended with `difference`: white over the
   near-black page, inverted over the blue buttons and the white of the
   map. A native CSS cursor cannot blend, so this has to be a real element.

   `cursor:none` is applied by the .has-cursor class, which main.js adds
   only once the element is actually running. If the script never loads the
   class is never added and the normal arrow stays - the page must never
   end up with no pointer at all. Touch devices get nothing: `display:none`
   and no listeners. */
/* The outer element ONLY ever carries the position, and the visible dot is
   the pseudo-element. They have to be separate: `scale` is its own property
   and composes before `transform`, so a `scale` on this element multiplied
   the position translate with it - touching any link threw the cursor to
   1.9x its own coordinates. That was the jump. */
.cursor{
  position:fixed; top:0; left:0; z-index:300;
  width:0; height:0;
  pointer-events:none;
  opacity:0;
  transition:opacity .2s var(--ease);
  will-change:transform;
  /* The blend has to be HERE, not on the dot. mix-blend-mode composites
     against the parent stacking context, and this element makes one
     (fixed + z-index), so a blend on the child was mixing inside an empty
     group and just painted flat white. On the element itself it composites
     against the page, which is the point. */
  mix-blend-mode:difference;
}
.cursor::before{
  content:""; position:absolute;
  left:-9px; top:-9px; width:18px; height:18px;
  border-radius:50%;
  background:#fff;
  transition:transform .2s var(--ease);
}
.cursor.on{ opacity:1; }
/* grows on anything clickable, which is the affordance the pointer hand
   used to carry; without it a custom cursor quietly removes the main
   signal that a thing can be clicked */
.cursor.over::before{ transform:scale(1.9); }

html.has-cursor,
html.has-cursor body,
html.has-cursor a,
html.has-cursor button,
html.has-cursor summary,
html.has-cursor label,
html.has-cursor [role="button"]{ cursor:none; }
/* a text field still needs its caret to be usable */
html.has-cursor input,
html.has-cursor textarea{ cursor:text; }

@media (hover:none), (pointer:coarse){ .cursor{ display:none; } }

/* -------------------------------------------------------- back to top
   Same glass as the dock icons so it belongs to that family. It appears
   only once there is something to come back from, and on mobile it sits
   clear of the dock rather than on top of the WhatsApp button. */
.to-top{
  position:fixed; z-index:97;
  right:var(--gut); bottom:28px;
  width:46px; height:46px;
  display:grid; place-items:center;
  color:#fff; border-radius:50%;
  background:rgba(10,16,26,.92); border:1px solid var(--border);
  backdrop-filter:blur(14px);
  box-shadow:0 14px 34px -18px rgba(0,0,0,.9);
  opacity:0; visibility:hidden; transform:translateY(8px);
  transition:opacity .25s var(--ease), transform .25s var(--ease),
             visibility .25s, border-color .2s;
}
.to-top.on{ opacity:1; visibility:visible; transform:none; }
.to-top:hover{ border-color:rgba(77,162,255,.45); }
.to-top svg{
  width:17px; height:17px; fill:none;
  stroke:currentColor; stroke-width:1.7;
  stroke-linecap:round; stroke-linejoin:round;
}
@media (max-width:860px){
  /* the dock is 54px tall and sits 12px off the bottom, plus the safe area */
  .to-top{ right:12px; bottom:calc(78px + env(safe-area-inset-bottom)); width:42px; height:42px; }
}
@media (prefers-reduced-motion: reduce){
  .to-top{ transition:opacity .01s, visibility .01s; transform:none; }
}

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

.skip{
  position:fixed; left:-999px; top:12px; z-index:200;
  background:var(--blue); color:#001; padding:10px 16px; border-radius:var(--r-pill);
}
.skip:focus{ left:12px; }

.wrap{ width:100%; max-width:var(--wrap); margin-inline:auto; padding-inline:var(--gut); }

/* ---------------------------------------------------------------- type */
/* Adventor carries every title. Only two cuts exist here, 400 and 700, so
   the hero takes the bold and every section heading takes the regular.
   That split is the hierarchy. */
h1,h2{
  margin:0;
  font-family:var(--display);
  font-synthesis:none;
  letter-spacing:-.03em;
  line-height:1.05;
}
h1{ font-weight:700; }
h2{
  font-weight:700; letter-spacing:-.03em;
  text-wrap:balance;          /* spreads the last line instead of orphaning a word */
}
h3{ margin:0; font-size:1.06rem; font-weight:500; letter-spacing:-.01em; line-height:1.3; }

/* One slope, 5.6vw, held across every breakpoint. The floor is 3.4rem
   rather than 2.6rem so the curve meets the mobile rule exactly at 860
   instead of stepping: below 860 the hero is one column and the headline
   is sized off the full width, above it the headline sits in half the
   width, and the two used to disagree by 9px across that one pixel. */
h1{ font-size:clamp(3.4rem, 5.6vw, 6.2rem); line-height:1.0; letter-spacing:-.042em; font-weight:700; text-wrap:balance; }
h2{ font-size:clamp(1.6rem, 2.7vw, 3rem); }

.t-display{ font-family:var(--display); font-weight:700; font-synthesis:none; letter-spacing:-.035em; }

/* the one word that carries the promise */
.hl{ color:var(--blue); }

/* Adventor sets its solidus off-centre: measured in the browser at the hero
   size, "24/7" clears .061em before the slash and .091em after it. The
   slash therefore hangs toward the 7 and crowds the 4, which is what reads
   as wrong - the problem was never the amount of space, it was that the two
   gaps are unequal.

   So this shifts the slash right by half the difference instead of
   tightening it. Both gaps land on .076em, and because the two margins
   cancel out the string keeps exactly the width it would have had, so
   nothing reflows. Measured with a canvas in the page itself: PIL renders
   this pair noticeably looser than the browser does, and trusting it cost
   two wrong fixes. Verify any change by measuring on the live page, not in
   an image. Body copy is Helvetica and needs none of this. */
.sl{ margin-left:.015em; margin-right:-.015em; }

p{ margin:0 0 1em; text-wrap:pretty; }
p:last-child{ margin-bottom:0; }

.dim{ color:var(--text-3); }
.on-mob{ display:none; }        /* swapped in the mobile block below */
.muted{ color:var(--text-3); font-size:.9rem; }

.label{
  display:inline-block;
  font-size:.63rem; font-weight:400;
  letter-spacing:.16em; text-transform:uppercase;
  color:var(--text-2);
  border:1px solid var(--border);
  border-radius:5px;
  padding:5px 9px;
  background:rgba(255,255,255,.02);
}

/* ------------------------------------------------------------- buttons */
.btn{
  --bh: 42px;
  display:inline-flex; align-items:center; gap:9px;
  height:var(--bh); padding:0 16px;
  border-radius:var(--r-pill);
  font-size:.92rem; font-weight:400; letter-spacing:-.01em;
  white-space:nowrap;
  transition:transform .2s var(--ease), background .2s var(--ease),
             border-color .2s var(--ease), box-shadow .2s var(--ease);
}
.btn svg{ width:15px; height:15px; flex:none; }
.btn svg path{ fill:none; stroke:currentColor; stroke-width:1.5; stroke-linecap:round; stroke-linejoin:round; }
.btn .ico path{ fill:currentColor; stroke:none; }
.btn:hover{ transform:translateY(-2px); }
/* Press feedback. The hover lift says "this can be clicked"; nothing said
   "you clicked it", so on a mouse the button was inert at the one moment
   the user was watching it. Gated to a fine pointer because touch already
   has its own :active further down, and 120ms because acknowledgement has
   to land inside the same gesture. */
@media (hover:hover) and (pointer:fine){
  .btn:active{ transform:translateY(-1px) scale(.975); transition-duration:.12s; }
}

/* Flat. The blue bloom that used to sit under this read as a glow effect
   rather than as a button; only the hairline highlight along the top edge
   is kept, which is shading, not light. */
/* Flat. The blue bloom that used to sit under this read as a glow effect
   rather than as a button; only the hairline highlight along the top edge
   is kept, which is shading, not light. */
.btn-primary{
  background:var(--blue); color:#00111f;
  box-shadow:inset 0 1px 1px rgba(255,255,255,.42);
}
.btn-primary:hover{ background:var(--blue-hot); box-shadow:inset 0 1px 1px rgba(255,255,255,.5); }

.btn-ghost{
  background:var(--surface-1);
  border:1px solid var(--border);
  color:var(--text);
  box-shadow:inset 0 1px 1px rgba(255,255,255,.07);
}
.btn-ghost:hover{ background:var(--surface-2); border-color:rgba(255,255,255,.17); }

.btn-sm{ --bh:34px; font-size:.84rem; padding:0 13px; }
.btn-lg{ --bh:52px; font-size:1rem; padding:0 22px; }
.btn-xl{ --bh:60px; font-size:1.08rem; padding:0 28px; }

/* =====================================================================
   NAV
   ===================================================================== */
.nav{
  position:fixed; inset:0 0 auto 0; z-index:100;
  height:var(--nav-h);
  display:flex; align-items:center;
  transition:background .3s var(--ease), border-color .3s var(--ease), backdrop-filter .3s;
  border-bottom:1px solid transparent;
}
.nav.stuck{
  background:rgba(0,2,5,.72);
  backdrop-filter:blur(18px) saturate(1.5);
  -webkit-backdrop-filter:blur(18px) saturate(1.5);
  border-bottom-color:var(--border-soft);
}
.nav-in{
  width:100%; max-width:var(--wrap); margin-inline:auto;
  padding-inline:var(--gut);
  display:flex; align-items:center; gap:16px;
}
.nav-logo{ flex:none; }
.nav-logo img{ width:146px; height:auto; }

.nav-links{ display:flex; gap:2px; margin-inline:auto; }
.nav-links a{
  padding:8px 11px; border-radius:var(--r-pill);
  font-size:.85rem; color:var(--text-2); white-space:nowrap;
  transition:color .2s, background .2s;
}
.nav-links a:hover{ color:var(--text); background:rgba(255,255,255,.06); }

/* --- 06 underline wipe -------------------------------------------------
   ::before, not ::after: the footer nav already uses ::after for its dotted
   separator, and both rows should behave identically. */
.nav-links a::before,
.foot-nav a::before{
  content:""; position:absolute; left:11px; right:11px; bottom:5px; height:1px;
  background:var(--blue);
  transform:scaleX(0); transform-origin:left;
  transition:transform .34s var(--ease);
}
.nav-links a{ position:relative; }
.nav-links a:hover::before,
.nav-links a.active::before,
.foot-nav a:hover::before{ transform:scaleX(1); }
.foot-nav a::before{ left:0; right:14px; bottom:4px; }
@media (prefers-reduced-motion: reduce){
  .nav-links a::before,.foot-nav a::before{ transition:none; }
}

.nav-cta{ display:flex; align-items:center; gap:9px; margin-left:0; flex:none; }

.nav-burger{ display:none; width:40px; height:40px; border:1px solid var(--border); border-radius:var(--r-ctl); position:relative; }
.nav-burger span{ position:absolute; left:11px; right:11px; height:1.5px; background:#fff; transition:transform .25s var(--ease), opacity .2s; }
.nav-burger span:nth-child(1){ top:16px } .nav-burger span:nth-child(2){ top:22px }
.nav-burger[aria-expanded="true"] span:nth-child(1){ transform:translateY(3px) rotate(45deg) }
.nav-burger[aria-expanded="true"] span:nth-child(2){ transform:translateY(-3px) rotate(-45deg) }

.mobile-menu{
  position:fixed; inset:var(--nav-h) 0 0 0; z-index:99;
  background:rgba(0,2,5,.96);
  backdrop-filter:blur(22px) saturate(1.4);
  -webkit-backdrop-filter:blur(22px) saturate(1.4);
  padding:22px var(--gut) 40px;
  display:flex; flex-direction:column; gap:2px;
  overflow-y:auto;
}
.mobile-menu[hidden]{ display:none; }
.mobile-menu a{
  font-family:var(--display); font-size:1.35rem; font-weight:400; font-synthesis:none; letter-spacing:-.02em;
  padding:14px 0; border-bottom:1px solid var(--border-soft);
}
.mobile-menu-foot{ display:flex; flex-direction:column; gap:10px; margin-top:26px; }
.mobile-menu-foot .btn{ justify-content:center; }
.mobile-menu-foot a{ font-size:1rem; padding:0; border:0; }
.mobile-menu-foot .btn-ghost{ border:1px solid var(--border); }

/* =====================================================================
   HERO
   ===================================================================== */
.hero{
  position:relative;
  min-height:100svh;
  padding:calc(var(--nav-h) + 20px) 0 44px;
  display:flex; align-items:center;
  overflow:hidden;
  isolation:isolate;
}

/* Layer order inside the hero, bottom up:
     0  canvas  - opaque, cleared to the page colour
     1  lights  - screened OVER the canvas so its edges never show
     3  wash    - fades the bottom of the scene into the next section
     4  content
   The lights sit above the canvas rather than behind it because the WebGL
   buffer is opaque: with the gradient underneath, the canvas rectangle
   punches a visible hole straight through the key light. */
/* The three lights were one stack of background layers on this element,
   which meant they could only ever move together. One span each lets them
   drift independently, on periods long enough and unequal enough
   (34s / 47s / 29s) that the scene never visibly repeats. The container
   still bleeds 10% past the hero on every side, so a light can travel a
   few percent without its edge ever coming into view. */
.hero-lights{
  position:absolute; inset:-10% -10% 0; z-index:1; pointer-events:none;
  mix-blend-mode:screen;
}
.hero-lights span{ position:absolute; inset:0; will-change:transform; }
.hero-lights span:nth-child(1){
  background:radial-gradient(64% 52% at 72% 20%, rgba(41,110,196,.30) 0%, rgba(28,78,150,.10) 40%, transparent 72%);
  animation:lampA 34s ease-in-out infinite alternate;
}
.hero-lights span:nth-child(2){
  background:radial-gradient(70% 60% at 16% 92%, rgba(20,66,128,.20) 0%, transparent 68%);
  animation:lampB 47s ease-in-out infinite alternate;
}
.hero-lights span:nth-child(3){
  background:radial-gradient(46% 40% at 50% 62%, rgba(77,162,255,.14) 0%, transparent 70%);
  animation:lampC 29s ease-in-out infinite alternate;
}
@keyframes lampA{
  from{ transform:translate3d(-3%, -2%, 0) scale(1);    opacity:.85; }
  to  { transform:translate3d(5%, 4%, 0)   scale(1.12); opacity:1; }
}
@keyframes lampB{
  from{ transform:translate3d(2%, 3%, 0)   scale(1.06); opacity:1; }
  to  { transform:translate3d(-4%, -3%, 0) scale(1);    opacity:.8; }
}
@keyframes lampC{
  from{ transform:translate3d(3%, -3%, 0)  scale(1.04); opacity:.75; }
  to  { transform:translate3d(-5%, 2%, 0)  scale(1.16); opacity:1; }
}
@media (prefers-reduced-motion: reduce){
  .hero-lights span{ animation:none; }
}
.hero::after{      /* horizon wash tying the hero into the next section */
  content:""; position:absolute; left:0; right:0; bottom:0; height:34vh; z-index:3;
  background:linear-gradient(to top, var(--bg) 12%, rgba(0,2,5,0) 100%);
  pointer-events:none;
}

/* The hero visual is a photograph of the dentist, cut out and stood on the
   baseline of the section. He fades into the black at the bottom rather
   than being sliced off by the section edge. */
.hero-visual{ position:relative; }
/* His head sits level with the headline, so the frame starts at the title
   line and he is cropped at the hip rather than shrunk to fit. */
.hero-portrait{
  position:relative; z-index:2;
  height:min(46vh, 452px);
  display:flex; justify-content:center; align-items:flex-start;
}
.hero-portrait picture{ display:block; }


.hero-doc{
  position:relative; z-index:2;
  height:min(62vh, 640px); width:auto; max-width:none;
  object-fit:contain; object-position:top;
  filter:contrast(1.04) saturate(.92) brightness(.96);
  /* Masking the image rather than laying a band over the container means
     the fade follows his silhouette, so no rectangle shows against the
     black. The watch sits at 89% of the cutout, so the mask has to stay
     solid past that: at the old 48/60/70 he was erased from the chest
     down and the hand in the pocket never appeared at all. */
  -webkit-mask-image:linear-gradient(to bottom, #000 90%, rgba(0,0,0,.5) 96%, transparent 100%);
  mask-image:linear-gradient(to bottom, #000 90%, rgba(0,0,0,.5) 96%, transparent 100%);
}

/* Concentric rings spreading out of him, like a scan. It lives inside
   .hero-visual rather than the hero, so the origin follows the portrait to
   wherever the layout puts it - centre-right on desktop, centre on mobile -
   instead of being pinned to one spot that only lines up at one width.
   The hero clips the overflow, so the rings can be far wider than the
   column they sit in. The mask fades them out well before the copy so the
   headline never has to read across a ring. */
.hero-rings{
  position:absolute; z-index:0; pointer-events:none;
  left:50%; top:32%;
  width:min(190vmax, 2100px); aspect-ratio:1;
  translate:-50% -50%;
  background:repeating-radial-gradient(circle at 50% 50%,
    rgba(120,185,255,.115) 0 1px, transparent 1px 46px);
  -webkit-mask-image:radial-gradient(circle at 50% 50%, #000 0%, rgba(0,0,0,.55) 22%, transparent 40%);
  mask-image:radial-gradient(circle at 50% 50%, #000 0%, rgba(0,0,0,.55) 22%, transparent 40%);
  will-change:transform;
  animation:heroRings 19s ease-in-out infinite alternate;
}
@keyframes heroRings{
  from{ transform:scale(1);    opacity:.75; }
  to  { transform:scale(1.13); opacity:1; }
}

/* Light leaving him: three rings expanding on one long staggered cycle, so
   there is always one in flight and the loop never lands on itself. Only
   transform and opacity move, so this composites and costs no layout. */
.hero-rings i{
  position:absolute; left:50%; top:50%;
  width:34%; aspect-ratio:1;
  translate:-50% -50%;
  border-radius:50%;
  border:1px solid rgba(150,205,255,.55);
  will-change:transform, opacity;
  animation:ringPulse 10.5s cubic-bezier(.22,.55,.3,1) infinite;
}
.hero-rings i:nth-child(2){ animation-delay:-3.5s; }
.hero-rings i:nth-child(3){ animation-delay:-7s; }
@keyframes ringPulse{
  0%  { transform:scale(.10); opacity:0; }
  10% { opacity:.65; }
  70% { opacity:.16; }
  100%{ transform:scale(2.9); opacity:0; }
}

@media (prefers-reduced-motion: reduce){
  .hero-rings{ animation:none; }
  .hero-rings i{ animation:none; opacity:.18; }
}

/* A slow light behind him. Two lamps on different periods so the movement
   never lands on an obvious loop, and slow enough to read as atmosphere
   rather than as an animation asking to be watched. */
.hero-halo{
  position:absolute; z-index:0; left:54%; bottom:16%;
  width:120%; aspect-ratio:1;
  /* The centring lives on `translate` and the breathe on `scale`, which
     leaves `transform` free for the pointer parallax below. All three are
     separate properties and compose in order, so none overwrites another.
     Written as one shorthand `transform` they would fight. */
  translate:-50% 0;
  background:radial-gradient(closest-side,
    rgba(77,162,255,.30) 0%, rgba(38,96,180,.16) 42%, transparent 72%);
  pointer-events:none;
  animation:haloBreathe 14s ease-in-out infinite alternate;
  will-change:transform, scale, opacity;
}
.hero-halo::after{
  content:""; position:absolute; inset:8% 14%;
  border-radius:50%;
  background:radial-gradient(closest-side,
    rgba(140,200,255,.22) 0%, rgba(60,130,220,.10) 46%, transparent 74%);
  animation:haloDrift 22s ease-in-out infinite alternate;
}
@keyframes haloBreathe{
  from{ scale:1;    opacity:.78; }
  to  { scale:1.07; opacity:1; }
}
@keyframes haloDrift{
  from{ transform:translate3d(-3%, 2%, 0) scale(1.02); opacity:.6; }
  to  { transform:translate3d(4%, -3%, 0) scale(.94);  opacity:1; }
}
@media (prefers-reduced-motion: reduce){
  .hero-halo, .hero-halo::after{ animation:none; }
}

/* ------------------------------------------------------ pointer parallax
   main.js eases --px and --py toward the pointer, both in the range -1..1.
   Every layer multiplies them by a fixed px amount, never a percentage:
   the portrait is the only element with anything to collide with, and a
   hard 9px ceiling cannot reach the copy column at any width. Nearer
   layers move further, so the depth order reads correctly.
   --par trims the whole effect where the columns sit closer together. */
/* Two inputs drive every light on the page. --px/--py are the pointer,
   -1..1, set on the root so sections far below the hero can read them.
   --sp is set per section by main.js: how far that section has travelled
   through the viewport, -1 above to 1 below. Scroll is what a phone can
   actually offer, so it drives the lights on touch as well. */
:root{ --px:0; --py:0; --sp:0; }
.hero-stage{ --par:1; }
/* Deliberately NOT on .hero-lights itself. That element carries
   mix-blend-mode:screen, and giving a blended element its own transform
   promotes it to a compositing layer; iOS then clips the blend to that
   layer's box and the hero gets a hard rectangle drawn over it. Moving
   the lights individually keeps the blend group unpromoted.
   `translate`, not `transform`, because the drift keyframes own transform. */
/* The lights travel a good deal further than the portrait. They are huge
   and soft, so 20px reads as the light shifting rather than as a plane
   sliding; at the 4px they had before, nothing was visible. */
.hero-lights span{
  translate:calc(var(--px) * var(--par) * 20px)
            calc(var(--py) * var(--par) * 14px + var(--sp) * 26px);
}
.hero-halo{
  transform:translate3d(calc(var(--px) * var(--par) * 12px),
                        calc(var(--py) * var(--par) * 8px + var(--sp) * 16px), 0);
}
.hero-doc{
  transform:translate3d(calc(var(--px) * var(--par) * 9px),
                        calc(var(--py) * var(--par) * 5px), 0);
}
@media (max-width:1180px){ .hero-stage{ --par:.55; } }
@media (prefers-reduced-motion: reduce){ .hero-stage{ --par:0; } }

.hero-in{
  position:relative; z-index:4;
  width:100%; max-width:var(--wrap); margin-inline:auto; padding-inline:var(--gut);
  display:grid; grid-template-columns:1.02fr .98fr;
  gap:clamp(20px, 3vw, 44px);
  align-items:end;
}
.hero-copy{
  display:flex; flex-direction:column; align-items:flex-start;
  justify-content:flex-end; padding-bottom:8px;
}
.hero-visual{ position:relative; display:flex; flex-direction:column; gap:18px; min-width:0; }


/* if WebGL is unavailable the hero keeps its light source */
.hero-stage.no-webgl .hero-copy{ display:flex; flex-direction:column; align-items:flex-start; justify-content:flex-end; }
/* the tooth and the three stat cards share the right column, so the copy
   column is not the only thing carrying weight */
.hero-visual{ display:flex; flex-direction:column; align-items:stretch; gap:20px; min-width:0; }

.eyebrow{ display:flex; flex-wrap:wrap; gap:8px; margin:0 0 18px; }
/* Every uppercase micro-label on the page sits at .72rem / 11.5px. They had
   drifted to .62, .63, .65 and .66rem, which renders between 9.9 and 10.6px:
   under the 11px floor where letterspaced caps stop being read and start
   being a texture. Uppercase and .12em tracking already cost legibility, so
   these need more size than lowercase copy, not less. */
.tag{
  display:inline-flex; align-items:center; gap:7px;
    font-size:.72rem; letter-spacing:.13em; text-transform:uppercase;
  color:var(--text-2);
  border:1px solid var(--border); border-radius:var(--r-pill);
  padding:6px 12px;
  background:rgba(255,255,255,.022);
  backdrop-filter:blur(8px);
}

h1{
  max-width:15ch;
  /* the hero is a drag surface, so a missed grab used to leave a torn
     selection across the headline instead of spinning the tooth */
  user-select:none; -webkit-user-select:none;
}
.hero-sub{
  margin:20px 0 26px;
  max-width:50ch;
  font-size:clamp(1rem, 1.2vw, 1.24rem);
  color:var(--text-2);
  line-height:1.62;
}

.hero-actions{ display:flex; flex-wrap:wrap; gap:12px; }

/* Lifted above the portrait at every width. He is z-index 2 and now runs
   down past the watch, so without this he covers the middle card. */
.hero-trust{ position:relative; z-index:3; display:grid; grid-template-columns:repeat(3,1fr); gap:10px; }

/* These cards are glass, and glass cannot survive a filter on an ancestor:
   a `filter` starts a new backdrop root, so the cards' backdrop-filter has
   nothing left to sample and they render as flat panels. The row therefore
   reveals on opacity and transform only. With the blur it spent its first
   second as three solid rectangles with the portrait sharp behind them.

   Both states are listed because `.reveal.in` sets filter:blur(0), and
   blur(0) is still a filter and still starts a backdrop root. It has the
   same specificity as a bare .reveal rule and is declared later, so it has
   to be beaten on specificity rather than on order. */
.hero-trust.reveal,
.hero-trust.reveal.in{ filter:none; }
.hero-trust.reveal.in{
  transition:opacity .6s var(--ease), transform .6s var(--ease);
}
.trust-card{
  display:flex; flex-direction:column; gap:8px;
  min-width:0; padding:20px 22px;
  border:1px solid var(--border); border-radius:var(--r-card);
  background:var(--surface-1);
  /* the -webkit- prefix is not optional: every other glass surface in this
     file carries it, and without it these three cards were plain panels in
     Safari while looking correct in Chrome */
  backdrop-filter:blur(10px);
  -webkit-backdrop-filter:blur(10px);
  box-shadow:
    inset 0 1px 1px rgba(255,255,255,.10),
    inset 0 -22px 34px -26px rgba(140,180,230,.5),
    0 12px 28px -18px rgba(0,0,0,.8);
  transition:transform .2s var(--ease), border-color .2s;
}
a.trust-card:hover{ transform:translateY(-2px); border-color:rgba(77,162,255,.35); }

/* --- 05 tilt and sheen ------------------------------------------------
   The cards tip toward the pointer and a soft light tracks the glass.
   main.js writes the transform inline, so it wins over the hover lift
   above while the pointer is on the card and releases when it leaves. */
.hero-trust{ perspective:820px; }
.trust-card{ transform-style:preserve-3d; }
.trust-card::after{
  content:""; position:absolute; inset:0; border-radius:inherit;
  pointer-events:none; opacity:0;
  background:radial-gradient(200px 150px at var(--sx,50%) var(--sy,50%),
             rgba(150,205,255,.16), transparent 62%);
  transition:opacity .3s var(--ease);
}
.trust-card{ position:relative; }
.trust-card.lit::after{ opacity:1; }

/* the count-up must not make the card jiggle as the digits change width */
.hero-trust .rate{ font-variant-numeric:tabular-nums; }

@media (hover:none),(pointer:coarse){
  .trust-card::after{ display:none; }
}
/* "4.8", "20+" and "24/7" are one set. The suffixes used to be shrunk and
   dimmed, which made the three cards look like three different things. */
.rate{ font-family:var(--display); font-size:1.95rem; font-weight:400; font-synthesis:none; letter-spacing:-.03em; line-height:1; }
.trust-meta{ font-size:.82rem; color:var(--text-3); line-height:1.35; white-space:nowrap; }

.stars{ display:inline-flex; gap:2px; }
.stars svg{ width:12px; height:12px; fill:var(--blue); }
.stars-lg svg{ width:16px; height:16px; }
.stars .off{ fill:rgba(255,255,255,.15); }

.hero-scroll{
  position:absolute; left:50%; bottom:26px; transform:translateX(-50%);
  width:1px; height:52px; background:linear-gradient(to bottom, transparent, var(--border));
  overflow:hidden;
}
.hero-scroll span{
  position:absolute; inset:0; background:linear-gradient(to bottom, transparent, var(--blue));
  animation:scrollLine 2.4s var(--ease) infinite;
}
@keyframes scrollLine{ 0%{ transform:translateY(-100%) } 60%,100%{ transform:translateY(100%) } }
@media (prefers-reduced-motion: reduce){ .hero-scroll span{ animation:none } }

/* =====================================================================
   SECTIONS
   ===================================================================== */
.sec{ position:relative; padding:clamp(64px, 7vw, 112px) 0; }

/* The same slow blue drift as the hero lamps, carried through the page so
   the sections below are lit rather than flat. Inset past the section on
   every side, so the light can travel without its own edge appearing.

   The section must clip it. A glow that hangs 14% past the edge, or a
   scale() that grows it, counts as scrollable overflow and widens the
   whole document: it put 220px of horizontal scroll on a 1920 screen.
   `clip` rather than `hidden` so this never becomes a scroll container. */
.sec-glow{ overflow:hidden; overflow:clip; }
.sec-glow::before{
  content:""; position:absolute; inset:-14%; z-index:-1; pointer-events:none;
  background:radial-gradient(58% 46% at 74% 12%, rgba(35,96,178,.17) 0%, transparent 70%);
  /* the drift owns `transform`, so the pointer and scroll response goes on
     `translate` - the two compose instead of overwriting each other */
  translate:calc(var(--px) * 26px) calc(var(--py) * 12px + var(--sp) * 70px);
  will-change:transform, translate;
  animation:secGlow 38s ease-in-out infinite alternate;
}
/* the three glowing sections run on different clocks, so scrolling from
   one to the next never shows two lights breathing in step */
.sec-glow:nth-of-type(even)::before{ animation-duration:53s; animation-delay:-17s; }
@keyframes secGlow{
  from{ transform:translate3d(-2%, -1.5%, 0) scale(1);   opacity:.8; }
  to  { transform:translate3d(3%, 2%, 0)     scale(1.1); opacity:1; }
}
@media (prefers-reduced-motion: reduce){
  .sec-glow::before{ animation:none; }
}

.sec-head{
  /* same ratio as .find-grid below it, so an aside lines up with the card
     it introduces rather than sitting a few dozen pixels to its left */
  display:grid; grid-template-columns:1.15fr .85fr; gap:clamp(28px,5vw,72px);
  align-items:end;
  margin-bottom:clamp(38px, 5vw, 62px);
}
.sec-aside{ display:flex; flex-direction:column; align-items:flex-start; gap:16px; }
.sec-aside p{ color:var(--text-2); max-width:44ch; font-size:.98rem; }

.sec-foot{
  display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between;
  gap:16px; margin-top:30px;
}
.foot-note{ color:var(--text-3); font-size:.92rem; margin:0; }

/* ------------------------------------------------- numbered emergencies
   This was six full-width rows in an accordion with one open, so five of the
   six symptoms were behind a click and the section read as a grey list. A
   person working out whether their own symptom counts needs to scan all six
   at once. It is now an open three-up grid, and the numeral - previously a
   26px chip - is the graphic that carries it. */
.cards{ display:grid; grid-template-columns:repeat(3,1fr); gap:10px; }

.num-card{
  position:relative; overflow:hidden;
  display:flex; flex-direction:column;
  border:1px solid var(--border); border-radius:var(--r-card);
  background:linear-gradient(180deg, rgba(255,255,255,.045), rgba(255,255,255,.012));
  box-shadow:
    inset 0 1px 1px rgba(255,255,255,.09),
    inset 0 -70px 100px -70px rgba(77,162,255,.13),
    0 16px 40px -28px rgba(0,0,0,.9);
  transition:border-color .25s var(--ease), transform .25s var(--ease);
}
.num-card:hover{ border-color:rgba(77,162,255,.34); transform:translateY(-3px); }
/* the light along the top edge only arrives on the card you are pointing at */
.num-card::before{
  content:""; position:absolute; inset:0 0 auto; height:1px;
  background:linear-gradient(90deg, transparent, var(--blue), transparent);
  opacity:0; transition:opacity .25s var(--ease);
}
.num-card:hover::before{ opacity:1; }

/* The head is a <button> so the phone layout can collapse it. On a wide
   screen the grid is always open, so it is a heading that happens to be a
   button: no pointer, no toggle mark, and the click handler returns early. */
.num-head{
  width:100%; cursor:default;
  display:flex; flex-direction:column; align-items:flex-start; gap:9px;
  padding:24px 22px 0; text-align:left;
}
.num-head .plus{ display:none; }
/* Set in the display face at the size the section headings use, so it reads
   as a number in the brand rather than as a badge. */
.num{
  font-family:var(--display); font-weight:700; font-synthesis:none;
  font-size:2.7rem; line-height:.85; letter-spacing:-.05em;
  color:var(--blue);
}
.num-title{ font-size:1.06rem; font-weight:500; letter-spacing:-.02em; line-height:1.3; }

/* .plus is still the first-aid and FAQ toggle mark; only the emergency
   cards stopped using it */
.plus{ flex:none; position:relative; width:24px; height:24px; border:1px solid var(--border); border-radius:5px; transition:.25s var(--ease); }
.plus::before,.plus::after{
  content:""; position:absolute; left:50%; top:50%; background:currentColor;
  transform:translate(-50%,-50%); transition:transform .25s var(--ease), opacity .25s;
}
.plus::before{ width:9px; height:1.5px; }
.plus::after{ width:1.5px; height:9px; }

.num-body > p{
  margin:0; padding:11px 22px 24px;
  font-size:.94rem; line-height:1.6; color:var(--text-2);
}

/* -------------------------------------------------------------- steps */
/* Three boxes in a row said "three things". This is a sequence - call, get
   seen, leave without the pain - so it is drawn as one path with three stops
   instead. The boxes are gone: the line and the numerals carry it, which is
   less furniture and considerably more structure. */
.steps{
  list-style:none; margin:0; padding:0;
  display:grid; grid-template-columns:repeat(3,1fr);
  gap:clamp(18px,3vw,44px);
  position:relative; counter-reset:s;
}
/* the path. It fades out after the last stop rather than running to the
   edge, so it has an end the way the process does */
.steps::before{
  content:""; position:absolute; z-index:0;
  left:0; right:0; top:16px; height:1px;
  background:linear-gradient(90deg, rgba(77,162,255,.34) 0 68%, transparent 100%);
}
.step{
  position:relative; z-index:1;
  padding:0; border:0; background:none; box-shadow:none;
  display:flex; flex-direction:column; gap:12px;
}
/* the stop on the path. The ring is painted in the page colour so the line
   is punched out behind the node instead of running through it. */
.step::before{
  content:""; position:absolute; left:0; top:11px;
  width:11px; height:11px; border-radius:50%;
  background:var(--blue);
  box-shadow:0 0 0 5px var(--bg), 0 0 0 6px rgba(77,162,255,.34);
}
.step-n{
  font-family:var(--display); font-weight:700; font-synthesis:none;
  font-size:2.4rem; line-height:1; letter-spacing:-.05em;
  color:var(--blue); padding-top:38px;
}
.step h3{ font-family:var(--display); font-size:1.14rem; font-weight:700; font-synthesis:none; letter-spacing:-.02em; line-height:1.26; }
.step p{ color:var(--text-2); font-size:.94rem; margin:0; }
.step-time{
  margin-top:auto; padding-top:14px; border-top:1px solid var(--border-soft);
    font-size:.72rem; letter-spacing:.12em; text-transform:uppercase; color:var(--text-3);
}

/* -------------------------------------------------------------- tiles */
.tiles{ display:grid; grid-template-columns:repeat(3,1fr); gap:12px; }
.tile{
  padding:24px;
  border:1px solid var(--border); border-radius:var(--r-card);
  background:var(--surface-1);
  box-shadow:inset 0 1px 1px rgba(255,255,255,.07), 0 14px 34px -26px rgba(0,0,0,.9);
  display:flex; flex-direction:column; gap:12px;
  transition:transform .25s var(--ease), border-color .25s, background .25s;
}
.tile:hover{ transform:translateY(-2px); border-color:rgba(255,255,255,.17); background:var(--surface-2); }
.tile h3{ font-family:var(--display); font-size:1.16rem; font-weight:700; font-synthesis:none; letter-spacing:-.02em; line-height:1.26; }
.tile p{ color:var(--text-2); font-size:.93rem; margin:0; }
.tile .label{ align-self:flex-start; }

.tile-wide{
  grid-column:span 2;
  background:
    radial-gradient(120% 140% at 88% 8%, rgba(77,162,255,.20) 0%, transparent 62%),
    linear-gradient(180deg, rgba(255,255,255,.05), rgba(255,255,255,.012));
  border-color:rgba(77,162,255,.24);
  box-shadow:
    inset 0 1px 1px rgba(255,255,255,.12),
    inset 0 -70px 110px -70px rgba(120,180,255,.55),
    0 20px 50px -30px rgba(0,0,0,.95);
}
.tile-wide h3{ font-size:clamp(1.2rem,1.9vw,1.6rem); }
.tile-wide p{ max-width:52ch; color:#b9c4d4; }

.chips{ list-style:none; display:flex; flex-wrap:wrap; gap:7px; margin:6px 0 0; padding:0; }
.chips li{
    font-size:.65rem; letter-spacing:.1em; text-transform:uppercase;
  color:#cfe1f7;
  border:1px solid rgba(255,255,255,.14); border-radius:var(--r-pill);
  padding:5px 10px; background:rgba(255,255,255,.05);
}

/* =====================================================================
   FIRST AID + AREAS
   ===================================================================== */
.aid{ display:grid; grid-template-columns:1fr 1fr; gap:8px; align-items:start; }

/* first aid collapses the same way the FAQ does: the headings are what you
   scan when you are in pain, the detail is there when you want it */
.aid-item{
  border:1px solid var(--border); border-radius:var(--r-card);
  background:var(--surface-1);
  box-shadow:inset 0 1px 1px rgba(255,255,255,.06);
  transition:border-color .25s, background .25s;
}
.aid-item.is-open{ border-color:rgba(77,162,255,.34); background:rgba(77,162,255,.05); }
.aid-q{
  width:100%; display:flex; align-items:center; justify-content:space-between; gap:var(--acc-gap);
  padding:var(--acc-pad); text-align:left;
  font-size:var(--acc-size); font-weight:500; letter-spacing:-.02em;
  line-height:var(--acc-lh); color:#fff;
}
.aid-a{ display:grid; grid-template-rows:0fr; transition:grid-template-rows .26s var(--ease-io); }
.aid-item.is-open .aid-a{ grid-template-rows:1fr; }
.aid-body{
  overflow:hidden; padding:0 20px;
  color:var(--text-2); font-size:.94rem; line-height:1.62; max-width:62ch;
  transition:padding .26s var(--ease-io);
}
.aid-body p{ margin:0; }
.aid-item.is-open .aid-body{ padding:0 20px 20px; }
.aid-item.is-open .plus::after{ transform:translate(-50%,-50%) scaleY(0); opacity:0; }

.areas{
  list-style:none; margin:0; padding:0;
  /* Three up, not two, and the drive time stacked under the area rather than
     pushed to the far side of a wide row. Ten places now read as one dense
     block you take in at a glance instead of a long two-column ledger. */
  display:grid; grid-template-columns:repeat(3,1fr); gap:1px;
  border:1px solid var(--border-soft); border-radius:var(--r-card); overflow:hidden;
  background:var(--border-soft);
}
.areas li{
  display:flex; flex-direction:column; align-items:flex-start; gap:5px;
  padding:17px 20px; background:var(--bg);
  transition:background .25s var(--ease);
}
.areas li:hover{ background:var(--bg-raise); }
/* Ten places into three columns leaves the last one alone with two empty
   cells beside it, and because this grid paints its own gaps those cells
   read as a grey block. The last entry takes the whole row instead, which
   lands as the furthest-out one rather than as a hole. Only above 860: the
   two-column phone layout divides into ten exactly and needs no help. */
@media (min-width:861px){
  .areas li:last-child{ grid-column:1 / -1; }
}
.areas span{ color:var(--text-2); font-size:.94rem; line-height:1.35; }
.areas b{
  font-family:var(--display); font-weight:400; font-synthesis:none;
  color:var(--blue); font-size:1.12rem; letter-spacing:-.02em; white-space:nowrap;
}
.areas-note{ margin-top:16px; color:var(--text-3); font-size:.9rem; max-width:70ch; }

/* =====================================================================
   DOCTOR
   ===================================================================== */
.doctor-grid{
  display:grid; grid-template-columns:.9fr 1.1fr;
  gap:clamp(28px,5vw,74px);
  align-items:stretch;          /* the clip fills its column instead of floating in it */
}

.doctor-media{ position:relative; align-self:center; justify-self:center; margin:0; border-radius:var(--r-stage); overflow:hidden; border:1px solid var(--border); }
/* A YouTube Short is 9:16, so the panel is phone-shaped and height-led
   rather than stretched to the copy column. */
.doctor-media{
  height:min(68vh, 600px);
  aspect-ratio:9/16;
  width:auto;
}
.doctor-media img,
.doctor-media iframe{
  position:absolute; inset:0;
  width:100%; height:100%; display:block; border:0;
  object-fit:cover;
}
/* the facade keeps the site's cool grade; the real player does not, since
   filtering a playing video is both ugly and expensive */
.doctor-media .yt img{ filter:grayscale(.35) contrast(1.05) brightness(.86); }
.doctor-media::after{      /* blue duotone over the desaturated plate */
  content:""; position:absolute; inset:0; pointer-events:none;
  background:
    linear-gradient(200deg, rgba(77,162,255,.30), rgba(3,12,28,.55) 62%, rgba(0,2,5,.9)),
    radial-gradient(80% 60% at 20% 10%, rgba(124,188,255,.22), transparent 70%);
  mix-blend-mode:screen;
}
.doctor-media::before{
  content:""; position:absolute; inset:0; z-index:2; pointer-events:none;
  box-shadow:inset 0 1px 1px rgba(255,255,255,.14), inset 0 -80px 120px -70px rgba(0,2,5,.95);
}
.doctor-media figcaption{ position:absolute; left:16px; bottom:16px; z-index:3; }

.doctor-copy{ display:flex; flex-direction:column; align-items:flex-start; gap:18px; }
.doctor-copy h2{ margin:2px 0 0; }
.doctor-copy p{ color:var(--text-2); max-width:52ch; margin:0; font-size:.98rem; }
.doctor-copy .lead{ color:#c6cfdc; font-size:1.1rem; line-height:1.55; }

.creds{ margin:8px 0 4px; display:grid; gap:0; width:100%; max-width:520px; }
.creds > div{ display:grid; grid-template-columns:130px 1fr; gap:16px; padding:13px 0; border-top:1px solid var(--border-soft); }
.creds dt{
    font-size:.72rem; letter-spacing:.12em; text-transform:uppercase; color:var(--text-3);
}
.creds dd{ margin:0; font-size:.94rem; color:var(--text-2); }

/* ------------------------------------------------------- youtube facade */
.yt{
  position:absolute; inset:0; padding:0; width:100%; height:100%;
  display:block; cursor:pointer; background:#05080e;
  border-radius:inherit; overflow:hidden;
}
.yt::after{                       /* legibility scrim under the caption */
  content:""; position:absolute; inset:0; pointer-events:none;
  background:linear-gradient(to top, rgba(0,2,5,.85) 0%, rgba(0,2,5,.12) 42%, rgba(0,2,5,.35) 100%);
}
.yt-play{
  position:absolute; left:50%; top:46%; transform:translate(-50%,-50%);
  width:66px; height:66px; border-radius:50%; z-index:2;
  display:grid; place-items:center;
  background:rgba(255,255,255,.94);
  box-shadow:0 10px 34px -8px rgba(0,0,0,.7);
  transition:transform .2s var(--ease), background .2s var(--ease);
}
.yt-play svg{ width:26px; height:26px; fill:#06101d; margin-left:3px; }
.yt:hover .yt-play{ transform:translate(-50%,-50%) scale(1.07); background:#fff; }
.yt:active .yt-play{ transform:translate(-50%,-50%) scale(.96); }

.yt-label{
  position:absolute; left:0; right:0; bottom:0; z-index:2;
  display:flex; flex-direction:column; gap:3px;
  padding:18px 18px 20px; text-align:left;
}
.yt-label b{
  font-family:var(--display); font-weight:400; font-synthesis:none;
  font-size:.98rem; letter-spacing:-.02em; color:#fff; line-height:1.3;
}
.yt-label i{
  font-style:normal; font-size:.74rem; letter-spacing:.1em;
  text-transform:uppercase; color:var(--text-2);
}

/* =====================================================================
   REVIEWS
   ===================================================================== */
.reviews-head{ align-items:start; }

.gscore{
  border:1px solid var(--border); border-radius:var(--r-card);
  background:var(--surface-1);
  box-shadow:inset 0 1px 1px rgba(255,255,255,.08), inset 0 -50px 80px -60px rgba(120,170,230,.4);
  padding:20px 22px;
  display:flex; flex-direction:column; gap:12px; align-items:flex-start;
}
.gscore-top{ display:flex; align-items:center; gap:10px; }
.glogo{ width:17px; height:17px; }
.gscore-num{ display:flex; align-items:baseline; gap:12px; }
.gscore-num strong{ font-family:var(--display); font-size:3.1rem; font-weight:400; font-synthesis:none; letter-spacing:-.03em; line-height:1; }
.gscore-num .stars{ align-self:center; }
.gscore-count{ margin:0; font-size:.86rem; color:var(--text-3); }

.bars{ width:100%; display:grid; gap:5px; margin:2px 0 4px; }
.bar{ display:grid; grid-template-columns:12px 1fr; gap:9px; align-items:center; }
.bar span{ font-size:.64rem; color:var(--text-3); }
.bar i{ display:block; height:3px; border-radius:2px; background:rgba(255,255,255,.09); overflow:hidden; }
.bar i::after{ content:""; display:block; height:100%; width:var(--w,0%); background:var(--blue); border-radius:2px; }

.topics{ list-style:none; display:flex; flex-wrap:wrap; gap:7px; padding:0; margin:0 0 22px; }
.topics li{
  display:inline-flex; align-items:center; gap:7px;
  font-size:.8rem; color:var(--text-2);
  border:1px solid var(--border); border-radius:var(--r-pill);
  padding:6px 12px; background:var(--surface-1);
}
.topics li b{ font-weight:500; color:var(--blue); font-size:.7rem; }

.rail-wrap{ position:relative; }
.rail{
  display:flex; gap:12px;
  overflow-x:auto; scroll-snap-type:x mandatory;
  padding:2px 2px 18px;
  margin-inline:calc(var(--gut) * -1);
  padding-inline:var(--gut);
  scrollbar-width:none;
}
.rail::-webkit-scrollbar{ display:none; }

.rv{
  flex:0 0 min(400px, 82vw); scroll-snap-align:start;
  display:flex; flex-direction:column; gap:13px;
  padding:22px;
  border:1px solid var(--border); border-radius:var(--r-card);
  background:linear-gradient(180deg, rgba(255,255,255,.042), rgba(255,255,255,.012));
  box-shadow:inset 0 1px 1px rgba(255,255,255,.09), 0 16px 40px -28px rgba(0,0,0,.9);
}
.rv-top{ display:flex; align-items:center; gap:11px; }
.rv-av{
  width:36px; height:36px; flex:none; border-radius:50%; display:grid; place-items:center;
  font-size:.86rem; font-weight:500; color:#00111f;
  background:linear-gradient(150deg, #cfe4ff, #4da2ff);
}
.rv-who{ display:flex; flex-direction:column; line-height:1.3; }
.rv-name{ font-size:.94rem; font-weight:500; letter-spacing:-.01em; }
.rv-meta{ font-size:.72rem; color:var(--text-3); }
.rv-when{ margin-left:auto; font-size:.72rem; color:var(--text-3); white-space:nowrap; }
.rv-text{ font-size:.95rem; line-height:1.62; color:var(--text-2); margin:0; }

.rail-nav{ display:flex; align-items:center; gap:9px; margin-top:6px; }
.rail-btn{
  width:40px; height:40px; display:grid; place-items:center;
  border:1px solid var(--border); border-radius:50%;
  background:var(--surface-1);
  transition:background .2s, border-color .2s, opacity .2s;
}
.rail-btn svg{ width:15px; height:15px; }
.rail-btn svg path{ fill:none; stroke:#fff; stroke-width:1.5; stroke-linecap:round; stroke-linejoin:round; }
.rail-btn:hover{ background:var(--surface-2); border-color:rgba(255,255,255,.2); }
.rail-btn[disabled]{ opacity:.3; cursor:default; }
.rail-write{ margin-left:auto; font-size:.86rem; color:var(--text-2); border-bottom:1px solid var(--border); padding-bottom:2px; }
.rail-write:hover{ color:#fff; border-color:var(--blue); }

/* =====================================================================
   FIND US
   ===================================================================== */
.find-grid{ display:grid; grid-template-columns:1.15fr .85fr; gap:12px; }

.map-card{
  position:relative; border-radius:var(--r-card); overflow:hidden;
  border:1px solid var(--border); min-height:430px;
  background:#04070d;
  /* keeps the filtered iframe from repainting the rest of the page */
  contain:paint;
}
/* The filter goes on a wrapper, not on the iframe itself. Applied directly
   to a cross-origin iframe it is computed but not composited reliably, and
   promoting that same element with translateZ made it drop out entirely.
   Filtering the parent subtree works, and gives the compositor one stable
   layer to reuse while the page scrolls. */
.map-frame{
  position:absolute; inset:0;
  isolation:isolate;
}
/* The static image is already toned to the palette when it is built, so it
   needs no filter at all - which is faster than the old one, since nothing
   is recoloured at paint time. The filter is kept for the interactive map,
   which is Google's own colours and still needs correcting. It stays on the
   wrapper, never the iframe: on the iframe it computes but never composites
   and it stutters the whole section on scroll. */
.map-frame.live{
  filter:invert(.93) hue-rotate(190deg) saturate(.55) brightness(.92) contrast(1.06);
}
.map-frame img{ width:100%; height:100%; object-fit:cover; }

/* The static render carries no marker of its own, so the clinic gets one
   here. There is no Google pin to collide with until the interactive map
   loads, and this is removed at that moment. */
.map-pin{
  position:absolute; left:50%; top:50%; z-index:2;
  width:14px; height:14px; margin:-7px 0 0 -7px;
  border-radius:50%;
  background:var(--blue);
  box-shadow:
    0 0 0 4px rgba(77,162,255,.20),
    0 0 0 11px rgba(77,162,255,.08),
    0 2px 12px rgba(0,0,0,.75);
}
.map-load{
  position:absolute; z-index:3; left:50%; bottom:16px;
  translate:-50% 0;
  display:inline-flex; align-items:center; gap:8px;
  padding:9px 16px; border-radius:var(--r-pill);
  font-size:.84rem; color:var(--text-2);
  background:rgba(6,10,17,.88); border:1px solid var(--border);
  backdrop-filter:blur(12px);
  transition:color .2s, border-color .2s, background .2s;
}
.map-load:hover{ color:#fff; border-color:rgba(77,162,255,.45); background:rgba(10,18,30,.92); }
.map-load svg{ width:13px; height:13px; fill:none; stroke:currentColor; stroke-width:1.6; stroke-linecap:round; stroke-linejoin:round; }
.map-credit{
  position:absolute; z-index:3; right:9px; bottom:7px; margin:0;
  font-size:.69rem; letter-spacing:.02em; color:rgba(255,255,255,.52);
  pointer-events:none;
}
.map-card iframe{
  position:absolute; inset:0; width:100%; height:100%; border:0;
}
/* static vignette, no blend mode: multiply over a dark tint blacked the map out */
.map-veil{
  position:absolute; inset:0; pointer-events:none; z-index:2;
  background:
    radial-gradient(66% 60% at 50% 48%, transparent 34%, rgba(0,2,5,.38) 100%),
    linear-gradient(180deg, rgba(0,2,5,.30), transparent 24%,
                    transparent 76%, rgba(0,2,5,.46));
  box-shadow:inset 0 1px 1px rgba(255,255,255,.1);
}

.find-info{
  border:1px solid var(--border); border-radius:var(--r-card);
  background:var(--surface-1);
  box-shadow:inset 0 1px 1px rgba(255,255,255,.07);
  padding:26px; display:flex; flex-direction:column; gap:2px;
}
.info-row{ padding:18px 0; border-bottom:1px solid var(--border-soft); display:flex; flex-direction:column; gap:7px; align-items:flex-start; }
.info-row:first-child{ padding-top:0; }
.info-row p{ margin:0; font-size:.96rem; line-height:1.55; }
.info-row a:hover{ color:var(--blue); }
.find-actions{ display:flex; flex-wrap:wrap; gap:9px; padding-top:20px; }

/* =====================================================================
   FAQ
   ===================================================================== */
.faq{ display:grid; gap:8px; }
.faq-item{
  border:1px solid var(--border); border-radius:var(--r-card);
  background:var(--surface-1);
  box-shadow:inset 0 1px 1px rgba(255,255,255,.06);
  transition:border-color .25s, background .25s;
}
.faq-item.is-open{ border-color:rgba(77,162,255,.3); background:rgba(77,162,255,.045); }

/* --- 07 border trace ---------------------------------------------------
   A light travels the border of whichever row is open. Drawn as a rotating
   conic gradient masked down to a 1px ring, so nothing moves and nothing
   is repainted but the border itself.

   The emergency cards are deliberately left out: an open one turns solid
   blue already, and a blue light on a blue card is invisible.

   @property is what makes the angle animatable. Where it is unsupported
   the gradient simply sits still, which is a static blue edge - fine. */
@property --trace{ syntax:"<angle>"; initial-value:0deg; inherits:false; }

.aid-item, .faq-item{ position:relative; }
.aid-item.is-open::before,
.faq-item.is-open::before{
  content:""; position:absolute; inset:0; border-radius:inherit;
  padding:1px; pointer-events:none;
  background:conic-gradient(from var(--trace),
    transparent 0deg, rgba(77,162,255,.05) 18deg,
    var(--blue-hot) 40deg, rgba(77,162,255,.05) 62deg, transparent 80deg);
  -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;
  mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite:exclude;
  animation:borderTrace 3.2s linear infinite;
}
@keyframes borderTrace{ to{ --trace:360deg; } }
@media (prefers-reduced-motion: reduce){
  .aid-item.is-open::before,.faq-item.is-open::before{ animation:none; }
}
.faq-q{
  width:100%; display:flex; align-items:center; justify-content:space-between; gap:var(--acc-gap);
  padding:var(--acc-pad); text-align:left;
  font-size:var(--acc-size); font-weight:500; letter-spacing:-.02em;
  line-height:var(--acc-lh);
}
.faq-a{ display:grid; grid-template-rows:0fr; transition:grid-template-rows .26s var(--ease-io); }
.faq-item.is-open .faq-a{ grid-template-rows:1fr; }
.faq-body{ overflow:hidden; padding:0 20px; color:var(--text-2); font-size:.96rem; line-height:1.62; max-width:80ch; transition:padding .26s var(--ease-io); }
.faq-body p{ margin:0 0 .9em; }
.faq-body p:last-child{ margin-bottom:0; }
.faq-item.is-open .faq-body{ padding:0 20px 21px; }

/* published prices, so nobody has to ask */
.price-list{ list-style:none; margin:14px 0; padding:0; display:grid; gap:1px; max-width:520px; }
.price-list li{
  display:flex; align-items:baseline; justify-content:space-between; gap:16px;
  padding:11px 14px;
  background:rgba(255,255,255,.032);
  border:1px solid var(--border-soft);
}
.price-list li:first-child{ border-radius:10px 10px 0 0; }
.price-list li:last-child{ border-radius:0 0 10px 10px; }
.price-list span{ color:var(--text-2); font-size:.93rem; }
.price-list b{
  font-family:var(--display); font-weight:400; font-synthesis:none;
  color:#fff; font-size:1.02rem; letter-spacing:-.01em; white-space:nowrap;
}
.faq-item.is-open .plus::after{ transform:translate(-50%,-50%) scaleY(0); opacity:0; }

/* =====================================================================
   CONTACT
   ===================================================================== */
.contact-grid{ display:grid; grid-template-columns:.92fr 1.08fr; gap:clamp(28px,5vw,72px); align-items:start; }
.contact-copy{ display:flex; flex-direction:column; align-items:flex-start; gap:16px; }
.contact-copy p{ color:var(--text-2); max-width:40ch; margin:0; }
.big-tel{
  font-family:var(--display); font-size:clamp(1.45rem,3vw,2.3rem); font-weight:400; font-synthesis:none; letter-spacing:-.03em;
  color:#fff; border-bottom:1px solid var(--border); padding-bottom:6px;
  transition:border-color .2s, color .2s;
}
.big-tel:hover{ color:var(--blue); border-color:var(--blue); }

.contact-form{
  border:1px solid var(--border); border-radius:var(--r-stage);
  background:linear-gradient(180deg, rgba(255,255,255,.042), rgba(255,255,255,.01));
  box-shadow:
    inset 0 1px 1px rgba(255,255,255,.1),
    inset 0 -90px 140px -80px rgba(120,170,230,.42),
    0 24px 60px -34px rgba(0,0,0,.95);
  padding:clamp(22px,3vw,32px);
  display:grid; gap:14px;
}
.f-row{ display:grid; grid-template-columns:1fr 1fr; gap:14px; }
.field{ display:flex; flex-direction:column; gap:7px; }
.field > span{
    font-size:.72rem; letter-spacing:.12em; text-transform:uppercase; color:var(--text-3);
}
.field > span i{ font-style:normal; color:var(--blue); }
.field input, .field textarea{
  width:100%; font:inherit; font-size:16px; color:#fff;
  background:rgba(255,255,255,.035);
  border:1px solid var(--border); border-radius:var(--r-ctl);
  padding:12px 14px; resize:vertical;
  transition:border-color .2s, background .2s, box-shadow .2s;
}
.field input:focus, .field textarea:focus{
  outline:none; border-color:rgba(77,162,255,.55); background:rgba(77,162,255,.06);
  box-shadow:0 0 0 3px rgba(77,162,255,.14);
}
.field.invalid input, .field.invalid textarea{ border-color:#ff6b6b; }
.contact-form .btn{ justify-self:start; margin-top:4px; }
.form-note{ margin:0; font-size:.85rem; color:var(--text-2); white-space:nowrap; min-height:1.2em; }
.form-note.ok{ color:#5ee08f; }
.form-note.err{ color:#ff8f8f; }

/* =====================================================================
   CTA + FOOTER
   ===================================================================== */
.cta{ position:relative; padding:clamp(80px,11vw,150px) 0; text-align:center; overflow:hidden; }
.cta-glow{
  position:absolute; left:50%; bottom:-52%;
  width:min(1200px,140vw); aspect-ratio:1.5;
  background:radial-gradient(50% 50% at 50% 50%, rgba(77,162,255,.34) 0%, rgba(30,90,180,.12) 42%, transparent 72%);
  pointer-events:none;
  /* centring and the reactive offset share `translate`; the breathe keeps
     `transform`. .cta already has overflow:hidden, so this cannot widen
     the page however far the light travels. */
  translate:calc(-50% + var(--px) * 22px) calc(var(--sp) * 56px);
  will-change:transform, translate;
  animation:ctaGlow 41s ease-in-out infinite alternate;
}
@keyframes ctaGlow{
  from{ transform:scale(1);    opacity:.82; }
  to  { transform:scale(1.14); opacity:1; }
}
@media (prefers-reduced-motion: reduce){
  .cta-glow{ animation:none; }
}
.cta-in{ position:relative; display:flex; flex-direction:column; align-items:center; gap:24px; }
.cta h2{ font-size:clamp(2.3rem,5.6vw,4.6rem); }
.cta .muted{ margin:0; }

/* Footer. Two blocks that mean something - who this is, and how to reach
   him - then one quiet row of links. The old version was three unlabelled
   columns of grey text, which read as filler. */
.foot{ border-top:1px solid var(--border-soft); padding-top:clamp(44px, 5vw, 72px); }

.foot-top{
  display:grid; grid-template-columns:1fr 1fr;
  gap:clamp(28px, 5vw, 72px);
  align-items:start;
  padding-bottom:clamp(32px, 4vw, 52px);
}
.foot-brand img{ width:180px; margin-bottom:18px; }
.foot-brand p{ color:var(--text-3); font-size:.92rem; max-width:38ch; margin:0; }

.foot-reach{
  display:flex; flex-direction:column; gap:12px;
  align-items:flex-end; text-align:right; justify-self:end;
}
.foot-tel{
  font-family:var(--display); font-weight:700; font-synthesis:none;
  font-size:clamp(1.5rem, 2.6vw, 2.2rem); letter-spacing:-.035em;
  color:#fff; line-height:1;
  transition:color .2s var(--ease);
}
.foot-tel:hover{ color:var(--blue); }
.foot-reach p{ color:var(--text-3); font-size:.92rem; max-width:36ch; margin:0; }

.foot-links{ display:flex; flex-wrap:wrap; justify-content:flex-end; gap:8px; margin-top:4px; }
.foot-links a{
  font-size:.86rem; color:var(--text-2);
  border:1px solid var(--border); border-radius:var(--r-pill);
  padding:8px 15px; background:var(--surface-1);
  transition:color .2s, border-color .2s, background .2s;
}
.foot-links a:hover{ color:#fff; border-color:rgba(77,162,255,.4); background:var(--surface-2); }

.foot-nav{
  display:flex; flex-wrap:wrap; gap:4px 2px;
  padding-block:18px;
  border-top:1px solid var(--border-soft);
}
.foot-nav a{
  font-size:.88rem; color:var(--text-3);
  padding:8px 14px 8px 0; margin-right:14px;
  position:relative;
  transition:color .2s;
}
.foot-nav a:not(:last-child)::after{
  content:""; position:absolute; right:0; top:50%;
  width:3px; height:3px; margin-top:-1.5px; border-radius:50%;
  background:var(--border);
}
.foot-nav a:hover{ color:#fff; }

.foot-bar{
  display:flex; justify-content:space-between; gap:16px; flex-wrap:wrap;
  padding-block:20px 26px; border-top:1px solid var(--border-soft);
  font-size:.8rem; color:var(--text-3);
}

/* =====================================================================
   MOBILE DOCK
   ===================================================================== */
.dock{
  position:fixed; z-index:98; left:12px; right:12px;
  bottom:calc(12px + env(safe-area-inset-bottom));
  display:none; gap:9px;
}
.dock::before{      /* content must not appear to run into the buttons */
  content:""; position:absolute; z-index:-1;
  left:-12px; right:-12px; bottom:calc(-12px - env(safe-area-inset-bottom));
  height:calc(100% + 46px + env(safe-area-inset-bottom));
  background:linear-gradient(to top, var(--bg) 42%, rgba(0,2,5,.86) 68%, transparent);
  pointer-events:none;
}
.dock a{
  height:54px; border-radius:var(--r-pill);
  display:flex; align-items:center; justify-content:center; gap:9px;
  font-size:1rem;
}
.dock svg{ width:19px; height:19px; fill:currentColor; }
.dock-call{
  flex:1; background:var(--blue); color:#00111f;
  box-shadow:inset 0 1px 1px rgba(255,255,255,.42);
}
.dock-icon{
  width:54px; flex:none; color:#fff;
  background:rgba(10,16,26,.92); border:1px solid var(--border);
  backdrop-filter:blur(14px);
}
.dock-icon:active{ background:rgba(28,40,58,.95); }
.dock-call:active{ background:var(--blue-hot); }

/* =====================================================================
   REVEAL
   ===================================================================== */
/* One reveal for the whole page: 9px and half a second, the same on a
   heading as on a card. main.js attaches this to the rest of the sections
   and sets --rd so siblings arrive in sequence rather than as a block.
   The class is added by script, never in the markup, so a page with no
   JavaScript renders everything visible instead of blank. */
/* Everything that is not a heading resolves out of a blur. Softer than a
   slide, and it suits body copy, which is most of what gets revealed. */
.reveal{ opacity:0; filter:blur(8px); transform:translateY(6px); }
.reveal.in{
  opacity:1; filter:blur(0); transform:none;
  transition:opacity .6s var(--ease), filter .6s var(--ease), transform .6s var(--ease);
  transition-delay:var(--rd, 0ms);
}
/* main.js adds this once the transition ends. A lingering blur(0) is still
   a filter, and a filter is both a stacking context and a containing block
   - 71 of them left on the page for nothing. */
.reveal.done{ filter:none; }

/* Headings arrive a line at a time instead, each sliding up from behind its
   own edge. main.js builds the .ln wrappers from the <br>s already in the
   markup, so the HTML stays readable. The padding/margin pair gives
   descenders and the blue 24/7 room inside the mask. */
.lines .ln{
  display:block; overflow:hidden;
  padding-bottom:.14em; margin-bottom:-.14em;
}
.lines .ln > i{ display:block; font-style:normal; transform:translateY(104%); }
.lines.in .ln > i{
  transform:none;
  /* .62s, not .74s. With the stronger curve the line covers most of its
     travel in the first third either way, so the extra 120ms was only tail:
     it held the last few pixels long enough to notice. */
  transition:transform .62s var(--ease);
  transition-delay:calc(var(--li, 0) * 88ms + var(--rd, 0ms));
}

@media (prefers-reduced-motion: reduce){
  .reveal{ opacity:1; filter:none; transform:none; }
  .reveal.in{ transition:none; transition-delay:0ms; }
  .lines .ln > i{ transform:none; }
  .lines.in .ln > i{ transition:none; transition-delay:0ms; }
}

/* Wide monitors. The content used to stay capped at a narrow column while
   the gutters grew, so the page read as a small card floating in black.
   Here the frame, the type and the portrait all scale with the screen. */
@media (min-width:1600px){
  :root{ --wrap:1680px; --gut:72px; }
  .hero{ min-height:88svh; padding-top:calc(var(--nav-h) + 8px); padding-bottom:32px; }
  /* Same slopes as below 1600 (5.6vw / 2.7vw), only the floor and ceiling
     move. A different slope here made both headings shrink by a few px at
     the moment the window crossed 1600. */
  h1{ font-size:clamp(4rem, 5.6vw, 7.4rem); }
  h2{ font-size:clamp(2.2rem, 2.7vw, 3.4rem); }
  .hero-sub{ font-size:1.3rem; max-width:52ch; }
  .hero-portrait{ height:min(51vh, 560px); }
  .hero-doc{ height:min(70vh, 800px); }
  .rate{ font-size:2.3rem; }
  .trust-meta{ font-size:.85rem; }
  .sec{ padding:clamp(80px, 6.5vw, 124px) 0; }
}
@media (min-width:2100px){
  :root{ --wrap:1880px; }
  .hero{ min-height:84svh; }
}

/* =====================================================================
   RESPONSIVE
   ===================================================================== */
@media (max-width:1080px){
  .nav-links{ display:none; }
  .nav-burger{ display:block; }
  .nav-cta{ margin-left:auto; }
  .doctor-grid, .contact-grid{ grid-template-columns:1fr; }
  /* same reasoning as the hero portrait: the toolbar must not resize it */
  .doctor-media{
    aspect-ratio:9/16; width:auto;
    height:min(62vh, 460px);
    height:min(clamp(380px, 118vw, 460px), 62lvh);
  }
  .find-grid{ grid-template-columns:1fr; }
  .map-card{ min-height:340px; }
  .tiles{ grid-template-columns:repeat(2,1fr); }
  .tile-wide{ grid-column:span 2; }
  .cards{ grid-template-columns:repeat(2,1fr); }
  /* the path turns vertical rather than disappearing */
  .steps{ grid-template-columns:1fr; gap:28px; }
  .steps::before{
    left:5px; right:auto; top:8px; bottom:44px; width:1px; height:auto;
    background:linear-gradient(180deg, rgba(77,162,255,.34) 0 88%, transparent 100%);
  }
  .step{ padding-left:32px; }
  .step::before{ top:6px; }
  .step-n{ padding-top:0; font-size:2rem; }
}

@media (max-width:860px){
  :root{ --nav-h:62px; --gut:18px; }

  /* --- copy switches --- */
  .on-desk{ display:none; }
  .on-mob{ display:inline; }

  /* --- nav: the dock already owns calling, so the bar is just brand + menu.
     .nav-links is hidden here, so the `.nav-links + .nav-cta` reset that
     kills the auto margin would otherwise pin the burger to the logo. --- */
  .nav-cta,
  .nav-links + .nav-cta{ gap:0; margin-left:auto; }
  .nav-cta > .btn-primary{ display:none; }
  .nav-logo img{ width:132px; }
  .nav.stuck{ background:rgba(0,2,5,.9); }

  /* --- section rhythm: desktop padding is far too generous at this width --- */
  .sec{ padding:56px 0; }
  .sec-head{ grid-template-columns:1fr; align-items:start; gap:16px; margin-bottom:26px; }
  .sec-aside{ flex-direction:column-reverse; align-items:flex-start; gap:12px; }
  .sec-aside p{ font-size:.94rem; }
  .cards{ grid-template-columns:1fr; }

  /* --- hero --- */
  .hero{
    display:block;
    min-height:auto;
    padding-top:calc(var(--nav-h) + 18px);
    /* room for the tail of the portrait. The hero clips its overflow, and
       now that the mask stays solid to 90% the clip would land on solid
       pixels and cut a straight line across him at 860 and 430. */
    padding-bottom:64px;
  }
  .hero-in{ grid-template-columns:1fr; gap:16px; align-items:stretch; }
  .hero-copy{ justify-content:flex-start; }
  .hero-visual{ gap:14px; }
  /* Same treatment as desktop, just smaller: sized by height and faded at
     the hip. An object-fit:cover here cropped straight to his face. */
  /* Sized from the WIDTH, not the height. In vh he resized every time the
     viewport height moved: Safari collapsing its toolbar on the first
     scroll, or an in-app browser adding its own bars, swung him between
     388px and 322px on the same phone. Width does not move while reading.
     `lvh` is only a ceiling, for a landscape phone that is genuinely too
     short - it is the LARGE viewport unit, so a collapsing toolbar does
     not change it either. The plain-vh line above is the fallback for
     anything that predates lvh. */
  /* The frame is the layout box; the image is taller and fades out through
     it. So his rendered size and the space he occupies are set separately:
     the image grows, the frame does not, and the stat cards below stay
     exactly where they were instead of being pushed under the dock.
     The image is sized so the mask finishes at the frame's bottom edge
     (70% of 105vw = 73.5vw), which is what keeps the fade on his silhouette
     rather than cutting a line across him. */
  .hero-portrait{
    height:min(34vh, 290px);
    height:min(clamp(270px, 73.5vw, 310px), 40lvh);
  }
  .hero-doc{
    width:auto;
    height:min(46vh, 400px);
    height:min(clamp(430px, 118vw, 510px), 66lvh);
    /* mask inherited from the base rule: solid past the watch, then out.
       He runs down behind the stat cards, which are lifted over him by
       z-index and blur what is left of him through their glass. */
  }
  .hero-halo{ width:150%; bottom:2%; }
  /* the portrait sits lower in the stacked layout, so the rings follow it */
  .hero-rings{ top:46%; }
  .hero-scroll{ display:none; }
  /* 3.4rem, not 3.6rem: this cap is what the desktop floor above meets at
     860, so the headline is the same size on both sides of the switch. */
  h1{ max-width:none; font-size:clamp(2.6rem, 15vw, 3.4rem); }
  .eyebrow{ margin-bottom:18px; gap:6px; }
  .tag{ font-size:.7rem; padding:5px 10px; }
  .hero-sub{ margin:14px 0 0; font-size:.98rem; line-height:1.55; }

  /* The dock is pinned to the bottom of every screen with Call, WhatsApp
     and Directions, so hero buttons here would only repeat it and crowd
     the fold. The dock is the call to action on mobile. */
  .hero-actions{ display:none; }

  .hero-trust{ grid-template-columns:repeat(3,1fr); gap:7px; }
  .trust-card{ padding:13px 12px; gap:5px; }
  .rate{ font-size:1.5rem; }
  .trust-meta{ font-size:.72rem; line-height:1.3; white-space:normal; }
  .stars svg{ width:10px; height:10px; }

  /* One override for all three accordions. Previously each set its own
     size and padding here - .97rem, .98rem, .98rem, and three paddings -
     which is exactly how they drifted apart in the first place. */
  :root{ --acc-size:.98rem; --acc-pad:16px 15px; --acc-gap:14px; }

  /* --- emergency cards: an accordion again. Six cards fully open is the
     right call at three columns and the wrong one at one - stacked, it is
     roughly five screens of scrolling before the next section. Collapsed,
     the six headings are a single screen you can scan, and the numeral goes
     back inline so a closed row is one line tall. --- */
  .cards{ gap:7px; }
  .num-head{
    flex-direction:row; align-items:center; gap:13px;
    padding:15px 16px; cursor:pointer;
  }
  .num{ font-size:1.5rem; flex:none; min-width:17px; }
  .num-title{ flex:1; font-size:1rem; line-height:1.3; }
  .num-head .plus{ display:block; }
  .num-card.is-open .plus::after{ transform:translate(-50%,-50%) scaleY(0); opacity:0; }
  .num-body{ display:grid; grid-template-rows:0fr; transition:grid-template-rows .26s var(--ease-io); }
  .num-card.is-open .num-body{ grid-template-rows:1fr; }
  .num-body > p{
    overflow:hidden; margin:0; padding:0 16px; font-size:.92rem;
    transition:padding .26s var(--ease-io);
  }
  .num-card.is-open .num-body > p{ padding:2px 16px 17px; }

  /* --- steps: these used to be cards, and this block still padded them like
     cards. With the boxes gone that shorthand only shoved the copy off the
     timeline rule and wiped the 32px indent the vertical path needs. --- */
  .steps{ gap:24px; }
  .step{ padding:0 0 0 32px; gap:10px; }

  /* --- first aid + areas --- */
  .aid{ grid-template-columns:1fr; gap:7px; }
  .aid-body{ padding:0 15px; font-size:.92rem; }
  .aid-item.is-open .aid-body{ padding:0 15px 17px; }
  /* two up, not one: the cells are compact now that the time sits under the
     area, so a single column would make ten of them an endless scroll */
  .areas{ grid-template-columns:repeat(2,1fr); }
  .areas li{ padding:14px 15px; }
  .areas span{ font-size:.88rem; }
  .areas b{ font-size:1rem; }

  /* --- doctor --- */
  .doctor-grid{ gap:24px; }
  .doctor-copy .lead{ font-size:1.02rem; }
  .creds > div{ padding:11px 0; }

  /* --- reviews: swipe, so the arrows are dead weight --- */
  .reviews-head{ gap:20px; }
  .gscore{ padding:16px 18px; }
  .gscore-num strong{ font-size:2.6rem; }
  .rail{ scroll-padding-left:var(--gut); }
  .rv{ flex-basis:min(340px, 86vw); padding:18px; }
  .rv-text{ font-size:.92rem; }
  .rail-btn{ display:none; }
  .rail-nav{ justify-content:flex-start; margin-top:2px; }
  .rail-write{ margin-left:0; }
  .topics{ gap:6px; margin-bottom:16px; }
  .topics li{ font-size:.74rem; padding:5px 10px; }

  /* --- find us --- */
  .find-grid{ gap:8px; }
  .map-card{ min-height:280px; }
  .find-info{ padding:20px; }
  .find-actions .btn{ flex:1 1 auto; justify-content:center; }

  /* --- faq --- */
  .faq-body{ padding:0 14px; font-size:.93rem; }
  .faq-item.is-open .faq-body{ padding:0 14px 17px; }
  .price-list li{ padding:10px 12px; }
  .price-list span{ font-size:.88rem; }
  .price-list b{ font-size:.95rem; }

  /* --- contact --- */
  .contact-copy{ order:-1; }
  .contact-form{ padding:20px 18px; }
  .contact-form .btn{ justify-self:stretch; justify-content:center; }

  /* --- touch targets: the audit floor is 40px --- */
  .btn-sm{ --bh:42px; font-size:.88rem; }
  .rail-write{ padding:11px 0; }
  .foot-nav a{ padding:10px 14px 10px 0; }
  .mobile-menu a{ padding:15px 0; }
  .info-row a{ display:inline-block; padding:10px 0; font-size:1.02rem; }
  /* These three were the last under the floor. The footer number is the
     second-biggest call target on the page and its line-height:1 left it
     24px tall, which is a miss on a phone held one-handed at 3am. */
  .foot-tel{ display:inline-block; padding-block:9px; }
  .foot-links a{ padding:10px 15px; }

  /* --- cta + footer --- */
  .cta{ padding:64px 0 56px; }
  .foot-top{ grid-template-columns:1fr; gap:30px; }
  .foot-reach{ align-items:flex-start; text-align:left; justify-self:start; }
  .foot-links{ justify-content:flex-start; }
  .foot-nav{ gap:0; }

  /* the dock floats over everything, so the page needs room to end above it */
  .foot-bar{ padding-bottom:calc(78px + env(safe-area-inset-bottom)); }
  .dock{ display:flex; }
}

@media (max-width:640px){
  .f-row{ grid-template-columns:1fr; }
  .creds > div{ grid-template-columns:1fr; gap:3px; }
  .btn-lg, .btn-xl{ --bh:50px; font-size:.95rem; }
  .foot-bar{ flex-direction:column; gap:6px; }
  .foot-brand img{ width:158px; }
}

/* only the genuinely narrow phones; 390px is the common iPhone width and
   the two-up button row still fits comfortably there */
@media (max-width:344px){
  .hero-actions{ grid-template-columns:1fr; }
  .trust-card{ padding:11px 9px; }
  .trust-meta{ font-size:.7rem; }
}

/* pointer-coarse: hover lift is meaningless and the press state is what reads */
@media (hover:none){
  .btn:hover{ transform:none; }
  .btn:active{ transform:scale(.97); }
  .tile:hover, a.trust-card:hover, .num-card:hover{ transform:none; }
  .num-card:active, .faq-item:active{ background:var(--surface-2); }
}

/* ================================== footer privacy link ================ */
.foot-bar a{ color:inherit; text-decoration:none; border-bottom:1px solid var(--border); padding-bottom:1px; }
.foot-bar a:hover{ color:var(--text); border-color:var(--text-2); }

/* =====================================================================
   OPENING FILM  (phones, behind ?intro=1 while it is being tried)
   The clip is 9:16 and the viewport rarely is, so the iframe is sized to
   cover: one of the two max() arms always resolves to the proportional
   value, which keeps the frame at 9:16 while filling the screen. An
   iframe cannot be object-fit, which is why this is done in maths.
   ===================================================================== */
.intro{ display:none; }
@media (max-width:860px){
  html.intro-on .intro{
    display:block; position:relative; z-index:1;
    height:100svh; width:100%; overflow:hidden; background:#000;
  }
}
.intro-frame{ position:absolute; inset:0; overflow:hidden; }
.intro-frame iframe{
  position:absolute; top:50%; left:50%;
  /* scale past the crop so YouTube's title strip and control bar, which
     sit hard against the top and bottom edges and survive controls=0,
     fall outside the visible area */
  transform:translate(-50%,-50%) scale(1.2);
  width:max(100vw, calc(100svh * 9 / 16));
  height:max(100svh, calc(100vw * 16 / 9));
  /* the global `img,svg,iframe{max-width:100%}` would clamp the cover
     width straight back to the container and letterbox the film */
  max-width:none; max-height:none;
  border:0;
  /* taps belong to our own controls, never to YouTube's chrome */
  pointer-events:none;
}
/* keeps the nav and the controls legible over whatever frame is showing */
.intro::after{
  content:""; position:absolute; inset:0; pointer-events:none; z-index:2;
  background:linear-gradient(to bottom,
    rgba(0,2,5,.62) 0%, rgba(0,2,5,.08) 20%,
    rgba(0,2,5,.10) 55%, rgba(0,2,5,.80) 100%);
}
.intro-ui{
  position:absolute; z-index:3; left:0; right:0;
  bottom:calc(86px + env(safe-area-inset-bottom));
  display:flex; flex-direction:column; align-items:center; gap:16px;
}
.intro-cue{
  display:inline-flex; flex-direction:column; align-items:center; gap:5px;
  background:none; border:0; cursor:pointer; padding:6px 10px;
  color:rgba(255,255,255,.72);
  font-size:.68rem; letter-spacing:.22em; text-transform:uppercase;
}
.intro-cue svg{ width:15px; height:15px; fill:none; stroke:currentColor; stroke-width:1.6; stroke-linecap:round; animation:introCue 2.1s var(--ease) infinite; }
@keyframes introCue{ 0%,100%{ transform:translateY(0); opacity:.55 } 50%{ transform:translateY(4px); opacity:1 } }
@media (prefers-reduced-motion: reduce){ .intro-cue svg{ animation:none } }
