:root{
  --paper:#FAFAF8; --ink:#111110; --grey:#6b6b68; --hair:rgba(17,17,16,.14);
  --serif:"Fraunces",Georgia,serif; --sans:"Alan Sans","Inter",-apple-system,sans-serif;
  --teal:#13556b; --teal-deep:#00475F;
  --serif2:"Cactus Classical Serif",var(--serif); --sans2:"Alan Sans",var(--sans);
}
*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth}
body{background:var(--paper);color:var(--ink);font-family:var(--sans);line-height:1.6;-webkit-font-smoothing:antialiased}
img{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
.shell{max-width:1200px;margin:0 auto;padding:0 clamp(20px,4vw,48px)}
.mono{font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:var(--grey);font-weight:600}

/* photographs: black and white carries the whole site */
.bw{filter:grayscale(1) contrast(1.04);}

/* nav */
nav{position:fixed;inset:0 0 auto;z-index:50;background:rgba(250,250,248,.92);backdrop-filter:blur(8px);border-bottom:1px solid #eee}
nav.scrolled{border-bottom-color:var(--hair)}
.navrow{display:flex;align-items:center;justify-content:space-between;height:68px}
.brand{display:flex;align-items:center;gap:12px;font-family:var(--serif);font-size:19px;letter-spacing:.02em}
.brand svg{width:30px;height:30px}
.navlinks{display:flex;gap:32px;font-size:13.5px;font-weight:500;letter-spacing:.04em}
.navlinks a{opacity:.75;transition:opacity .25s}
.navlinks a:hover{opacity:1}
.wa-pill{background:var(--ink);color:var(--paper);padding:10px 20px;border-radius:999px;font-size:13.5px;font-weight:600;letter-spacing:.02em;transition:transform .25s ease,opacity .25s}
/* .wa-pill:hover motion defined in the MOTION PASS block below */
@media(max-width:820px){.navlinks{display:none}}

/* hero */
.hero{padding:clamp(130px,18vh,190px) 0 clamp(48px,7vw,84px)}
h1{font-family:var(--serif);font-weight:300;font-size:clamp(40px,6.4vw,84px);line-height:1.02;letter-spacing:-.015em;max-width:13em}
.hero p.sub{margin-top:26px;font-size:clamp(16px,1.5vw,19px);color:var(--grey);max-width:36em}
.cta-row{display:flex;align-items:center;gap:26px;margin-top:36px;flex-wrap:wrap}
.cta{background:var(--ink);color:var(--paper);padding:16px 30px;border-radius:999px;font-weight:600;font-size:15px;display:inline-flex;align-items:center;gap:10px;transition:transform .25s ease,opacity .25s}
/* .cta:hover motion defined in the MOTION PASS block below */
.cta svg{width:17px;height:17px}
.cta-sec{font-weight:600;font-size:15px;border-bottom:1.5px solid var(--hair);padding-bottom:2px;transition:border-color .3s}
/* .cta-sec:hover underline-slide defined in the MOTION PASS block below */
.heroimg{margin-top:clamp(40px,6vw,72px);aspect-ratio:16/8.4;overflow:hidden;border-radius:2px}
.heroimg img{width:100%;height:100%;object-fit:cover;object-position:center 30%}

/* trust strip */
.strip{border-top:1px solid var(--hair);border-bottom:1px solid var(--hair);margin-top:clamp(48px,7vw,84px)}
.striprow{display:grid;grid-template-columns:repeat(4,1fr);gap:24px;padding:26px 0}
.striprow div{font-size:13.5px;color:var(--grey);letter-spacing:.02em;line-height:1.45}
.striprow b{display:block;color:var(--ink);font-family:var(--serif);font-size:19px;font-weight:400;margin-bottom:3px}
@media(max-width:820px){.striprow{grid-template-columns:repeat(2,1fr)}}

section{padding:clamp(64px,9vw,120px) 0}
h2{font-family:var(--serif);font-weight:300;font-size:clamp(30px,3.6vw,48px);letter-spacing:-.01em;line-height:1.08}
.kicker{margin-bottom:14px}
.sectionhead{max-width:34em;margin-bottom:clamp(36px,5vw,60px)}
.sectionhead p{margin-top:14px;color:var(--grey);font-size:16.5px}

/* doctors */
.docs{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(20px,3vw,40px)}
.doc .ph{aspect-ratio:3/3.1;overflow:hidden;border-radius:2px;background:#e8e8e4}
.doc .ph img{width:100%;height:100%;object-fit:cover;transition:transform .6s ease}
.doc:hover .ph img{transform:scale(1.025)}
.doc h3{font-family:var(--serif);font-weight:400;font-size:22px;margin-top:18px;letter-spacing:-.005em}
.doc .role{font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--grey);font-weight:600;margin-top:4px}
/* same small-label as .role, used as the heading over each doctor's bullet list */
.doc .qhead{font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--grey);font-weight:600;margin:20px 0 0}
.doc p.bio{margin-top:12px;font-size:14.5px;color:var(--grey);line-height:1.65}
/* Verified qualifications only, sourced from doctors-verified-credentials.md.
   Nothing here may be added without a public source. */
.doc .quals{list-style:none;margin:14px 0 0;padding:0;display:flex;flex-direction:column;gap:6px}
.doc .quals li{position:relative;padding-left:14px;font-size:13px;line-height:1.5;color:var(--grey)}
.doc .quals li::before{content:"";position:absolute;left:0;top:.62em;width:5px;height:1px;background:var(--teal);opacity:.6}
.newphoto{font-size:11px;color:var(--grey);letter-spacing:.06em;margin-top:8px;font-style:italic}
@media(max-width:820px){.docs{grid-template-columns:1fr;max-width:440px}}

/* treatments */
.treats{background:var(--ink);color:var(--paper)}
.treats .kicker,.treats .sectionhead p{color:rgba(250,250,248,.55)}
.trio{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:rgba(250,250,248,.16);border:1px solid rgba(250,250,248,.16)}
.trio div{background:var(--ink);padding:clamp(24px,3vw,40px)}
.trio h3{font-family:var(--serif);font-weight:300;font-size:clamp(22px,2.2vw,30px);line-height:1.15}
.trio p{margin-top:14px;font-size:14.5px;color:rgba(250,250,248,.66);line-height:1.65}
.trio .num{font-family:var(--serif);font-size:14px;color:rgba(250,250,248,.4);display:block;margin-bottom:18px}
.also{margin-top:clamp(32px,4vw,52px);display:flex;flex-wrap:wrap;gap:10px}
.also span{border:1px solid rgba(250,250,248,.25);border-radius:999px;padding:8px 18px;font-size:13px;color:rgba(250,250,248,.75)}
@media(max-width:820px){.trio{grid-template-columns:1fr}}

/* care */
.care .two{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(32px,5vw,64px);align-items:center}
.care .ph{aspect-ratio:4/3.4;overflow:hidden;border-radius:2px}
.care .ph img{width:100%;height:100%;object-fit:cover}
.care blockquote{font-family:var(--serif);font-weight:300;font-size:clamp(22px,2.6vw,32px);line-height:1.3;letter-spacing:-.01em}
.care p{margin-top:18px;color:var(--grey);font-size:16px}
@media(max-width:820px){.care .two{grid-template-columns:1fr}}

/* contact */
.contact .two{display:grid;grid-template-columns:1fr 1fr;gap:clamp(32px,5vw,64px)}
.cline{padding:18px 0;border-bottom:1px solid var(--hair);display:flex;justify-content:space-between;align-items:baseline;gap:20px;font-size:15.5px}
.cline .mono{flex-shrink:0}
.cline a{border-bottom:1.5px solid transparent;transition:border-color .3s}
.cline a:hover{border-color:var(--ink)}
.mapwrap{border-radius:2px;overflow:hidden;filter:grayscale(1) contrast(1.02);min-height:340px}
.mapwrap iframe{width:100%;height:100%;min-height:340px;border:0;display:block}
@media(max-width:820px){.contact .two{grid-template-columns:1fr}}

footer{border-top:1px solid var(--hair);padding:40px 0 48px}
.frow{display:flex;justify-content:space-between;align-items:center;gap:20px;flex-wrap:wrap}
.frow .brand{font-size:17px}
.frow p{font-size:12.5px;color:var(--grey)}

/* reveals — default visible (no-JS/JS-failure safe); html.js gate enhances with the hidden->in transition */
.rv{opacity:1;transform:none}
html.js .rv{opacity:0;transform:translateY(18px);transition:opacity .6s cubic-bezier(.22,1,.36,1),transform .6s cubic-bezier(.22,1,.36,1)}
html.js .rv.in{opacity:1;transform:none}
@media(prefers-reduced-motion:reduce){html.js .rv{opacity:0;transform:none;transition:opacity .6s ease;transition-delay:0ms !important}html.js .rv.in{opacity:1}}

/* ===================================================================
   MULTI-PAGE STRUCTURE PASS (new; structure + copy only).
   Reuses the tokens above. Visual design will be redone in Figma next.
   =================================================================== */

/* clear the fixed nav on interior pages whose first element is a section */
.page-top{padding-top:clamp(116px,15vh,150px)}

/* doctors.html is the last page still on the legacy 1200px .shell, so its content
   sat 104px inside its own nav and footer (content left 168px vs chrome 64px at
   1440). Match the container the rest of the site already uses (.t5shell on home,
   .cvshell on contact, .tx .shell on treatments): 1440 cap, same 64px gutter. */
#doctors.page-top>.shell{max-width:1440px;padding:0 clamp(20px,4.44vw,64px)}

/* active nav link (current page) */
.navlinks a.active{opacity:1;border-bottom:1.5px solid var(--ink);padding-bottom:3px}

/* condensed teasers on the home page (doctors + treatments) */
.teaser-row{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(20px,3vw,40px)}
.teaser-row .item{border-top:1px solid var(--hair);padding-top:22px}
.teaser-row h3{font-family:var(--serif);font-weight:400;font-size:clamp(20px,2.1vw,24px);letter-spacing:-.005em}
.teaser-row .role{font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--grey);font-weight:600;margin-top:6px}
.teaser-row p.note{margin-top:10px;font-size:14.5px;color:var(--grey);line-height:1.6}
@media(max-width:820px){.teaser-row{grid-template-columns:1fr;max-width:460px}}

/* "see more" text links under the teasers */
.morelink{margin-top:clamp(28px,4vw,40px);font-size:15px;font-weight:600}
.morelink a{border-bottom:1.5px solid var(--hair);padding-bottom:2px;transition:border-color .3s}
/* .morelink a:hover underline-slide defined in the MOTION PASS block below */

/* testimonials (home) */
.reviews{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(20px,3vw,40px)}
.review{border-top:1px solid var(--hair);padding-top:24px}
.review blockquote{font-family:var(--serif);font-weight:300;font-size:clamp(18px,1.8vw,21px);line-height:1.42;letter-spacing:-.005em}
.review .who{margin-top:16px;font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--grey);font-weight:600}
@media(max-width:820px){.reviews{grid-template-columns:1fr;max-width:460px}}

/* light contact close (home) */
.book{border-top:1px solid var(--hair)}

/* ===================================================================
   FIGMA REDESIGN PASS (2026-07-16) — nodes 26:1430 (home hero+nav+footer)
   and 26:1493 (contact page). New nav pill, home hero, credential band,
   two footer variants. Colors/type pulled from Figma via get_design_context.
   =================================================================== */

/* nav: brand + links move to Alan Sans, pill recolored teal, exact Figma opacity */
.brand{font-family:var(--sans2);font-weight:400}
.navlinks{font-family:var(--sans2)}
.navlinks a{opacity:.62;font-weight:500}
.navlinks a.active{opacity:1;font-weight:600;border-bottom:1.5px solid var(--ink);padding-bottom:3px}
.wa-pill{background:var(--teal);font-family:var(--sans2);display:inline-flex;align-items:center;gap:8px}
.wa-pill svg{width:16px;height:16px;flex-shrink:0}

/* ── HOME HERO ──────────────────────────────────────────────────────────────
   Exact transcription of Figma node 26:1728 (Desktop-15 hero, 1440x888). The
   node is an ABSOLUTE composition, not a flow layout: every element carries the
   node's literal px values multiplied by --s (= stage width / 1440), which
   main.js sets from the header's own clientWidth (not vw, so the scrollbar can
   never cause overflow). At 1440 the render is 1:1 with the frame; it scales
   linearly either way. Below 900px it reflows to a stacked mobile layout.
   Nav is fixed and floats over this, exactly as the node draws it.           */
.newhero{--s:1;position:relative;width:100%;height:calc(888px * var(--s));background:#fafaf8;overflow:hidden}

/* Teal ellipse, node 26:1746: a 1543x567 box at (-420,588), rotate(180deg),
   with the SVG overflowing its box by the node's exact insets. Fill #00475F. */
.hero-ellipse{position:absolute;left:calc(-420px * var(--s));top:calc(588px * var(--s));width:calc(1543px * var(--s));height:calc(567px * var(--s));transform:rotate(180deg)}
.hero-ellipse img{position:absolute;left:-6.48%;top:-17.64%;width:112.96%;height:135.28%;display:block;max-width:none}

/* Doctor photo, node 26:1747: 978x689 at (689,199). This is a CUTOUT png, which
   is what lets the subject sit over the teal band with no edge. The inner crop
   is the node's literal fill transform. Bleeds past the right edge by design. */
/* RIGHT-ANCHORED: in the node the photo bleeds 227px past the frame's right edge
   (689+978-1440). Anchoring from the right keeps that exact bleed when --s is
   height-capped on short viewports (where the stage is narrower than the screen);
   when --s is width-driven the two anchorings are pixel-identical. */
.hero-photo{position:absolute;right:calc(-227px * var(--s));top:calc(199px * var(--s));width:calc(978px * var(--s));height:calc(689px * var(--s))}
.hero-photo-clip{position:absolute;inset:0;overflow:hidden}
.hero-photo-clip img{position:absolute;left:5.54%;top:-76.78%;width:94.48%;height:176.78%;display:block;max-width:none}

/* Blur transition, node 26:1748: DISABLED. In the browser a backdrop-filter here
   blurs the photo behind it, landing exactly across the doctor's face (client:
   "her face has become blurred"). The Figma reference renders her face crisp, so
   the strip is dropped; the div stays in the DOM in case a gradient treatment
   replaces it later. */
.hero-blur{display:none}

/* Text block, node 26:1749: left 80, top 144, column gap 40; inner headgroup
   gap 24. Headline is Cactus Classical Serif 62/1.02, tracking -0.93, w662,
   which is what produces the three-line wrap. */
.hero-text{position:absolute;left:calc(80px * var(--s));top:calc(144px * var(--s));display:flex;flex-direction:column;align-items:flex-start;gap:calc(40px * var(--s));z-index:2}
.hero-headgroup{display:flex;flex-direction:column;align-items:flex-start;gap:calc(24px * var(--s))}
.newhero h1{font-family:var(--serif2);font-weight:400;font-size:calc(62px * var(--s));line-height:1.02;letter-spacing:calc(-0.93px * var(--s));width:calc(552px * var(--s));color:#111110;margin:0;max-width:none}
.newhero .sub{font-family:var(--sans2);font-weight:300;font-size:calc(18px * var(--s));line-height:normal;letter-spacing:calc(0.36px * var(--s));width:calc(552px * var(--s));color:#111110;opacity:.8;margin:0;max-width:none}
.newhero .cta-row{display:flex;align-items:center;gap:calc(24px * var(--s));margin:0}
.newhero .cta{background:#111110;color:#fafaf8;border-radius:calc(16px * var(--s));padding:calc(16px * var(--s)) calc(24px * var(--s));display:inline-flex;align-items:center;gap:calc(24px * var(--s));font-family:var(--sans2);font-weight:600;font-size:calc(16px * var(--s));letter-spacing:calc(0.32px * var(--s));line-height:normal;white-space:nowrap}
.newhero .cta svg{width:calc(24px * var(--s));height:calc(24px * var(--s));flex-shrink:0}
.newhero .cta-sec{font-family:var(--sans2);font-weight:500;font-size:calc(16px * var(--s));letter-spacing:calc(0.32px * var(--s));color:#111110;border-bottom:calc(1.5px * var(--s)) solid #132c6b;padding-bottom:calc(2px * var(--s));background:none;white-space:nowrap}

/* Credential logos, node 26:1757: left 80, top 698, row gap 40, items-end.
   Marks are white-on-transparent straight from the node (no plates, no boxes),
   each with its label BELOW it, gap 12. */
.hero-credband{display:contents}
.hero-creds{position:absolute;left:calc(80px * var(--s));top:calc(698px * var(--s));display:flex;align-items:flex-end;gap:calc(40px * var(--s));z-index:2}
.hero-creds .cred{display:flex;flex-direction:column;align-items:center;gap:calc(12px * var(--s));background:none}
.hero-creds .cred span:last-child{font-family:var(--sans2);font-weight:600;font-size:calc(14px * var(--s));letter-spacing:calc(0.28px * var(--s));text-transform:uppercase;color:#fafaf8;text-align:center;white-space:nowrap;line-height:normal;max-width:none}
.hero-creds .cred-army{justify-content:flex-end}
.hero-creds .cred-army img{width:calc(105px * var(--s));height:calc(112px * var(--s));display:block;max-width:none;object-fit:contain}
/* Max credential is text only from 15 Sep 2026, client asked for the logo to come off. */
.hero-creds .cred-max{justify-content:flex-end}
.hero-creds .cred-max span:last-child{white-space:normal;max-width:calc(150px * var(--s));text-align:center;text-wrap:pretty}
.hero-creds .cred-max{align-items:center}

/* Invisalign badge, node 26:1766: 294.417x99 at (1146,144), ground #009ace.
   Lives inside .hero-photo so it stays pinned to the photo's corner when the
   layout reflows on mobile; its offsets are the node's absolutes minus the
   photo's origin (1146-689=457, 144-199=-55). Asset is the 2x lockup. */
.hero-invis{position:absolute;right:calc(226.583px * var(--s));top:calc(-55px * var(--s));width:calc(294.417px * var(--s));height:calc(99px * var(--s));background:#009ace;overflow:hidden;z-index:2}
/* contain, not cover: the lockup then survives any box the responsive rules give
   it, and since the asset's own ground is the same #009ace as the box, the fit
   is seamless at every size. */
.hero-invis img{width:100%;height:100%;display:block;object-fit:contain}

/* shared override for the two other Figma-spec buttons (contact page CTA, nav pill already has its own rule) */
.cta-fig{border-radius:16px;font-family:var(--sans2)}

/* contact heading uses the taller Cactus Classical Serif display face; needs more clearance under the fixed nav than the old Fraunces page-top headings */
.contact.page-top{padding-top:clamp(150px,20vh,190px)}

/* Below 900px the 1440 composition would scale text to unreadable sizes, so the
   hero reflows: text, then the cutout photo on cream, then a real teal band
   carrying the two marks. Same content and order, legible sizes. */
@media(max-width:900px){
  /* overflow-x clip (not full hidden): the photo's 1.015 entrance scale spills
     ~3px past the viewport mid-transition, which reads as sideways scroll wiggle */
  .newhero{--s:1 !important;height:auto;overflow:visible;overflow-x:clip;padding:calc(84px + 3vw) 0 0;display:flex;flex-direction:column}
  .hero-ellipse,.hero-blur{display:none}
  .hero-text{position:static;order:1;padding:0 24px;gap:26px}
  .hero-headgroup{gap:18px}
  .newhero h1{font-size:clamp(32px,8.4vw,46px);letter-spacing:-.02em;width:auto;max-width:14ch}
  .newhero .sub{font-size:16px;line-height:1.6;width:auto;max-width:46ch}
  .newhero .cta-row{gap:18px;flex-wrap:wrap}
  .newhero .cta{font-size:15px;padding:14px 20px;gap:14px;border-radius:14px}
  .newhero .cta svg{width:18px;height:18px}
  .newhero .cta-sec{font-size:15px}
  /* photo below the text, badge stays pinned to its top-right corner */
  .hero-photo{position:relative;order:2;left:auto;right:auto;top:auto;width:100%;height:auto;aspect-ratio:4/3;margin-top:28px}
  .hero-photo-clip{overflow:hidden}
  /* cover, not a percentage crop. The desktop rule's 94.48/176.78 pair was
     tuned against the frame's 978x689 box; this box is 978x560, so reusing
     percentages stretched the photo. cover cannot distort at any box. */
  /* 2026-09-15 mobile fix: the source is a 896x1183 portrait whose subjects sit in
     the bottom 57 percent, the top of the file being empty. The old 978/560 box at
     50% 28% framed that empty area and cut both faces off below the crop. A 4/3 box
     anchored to the bottom shows the same region the desktop composition shows. */
  .hero-photo-clip img{left:0;top:0;width:100%;height:100%;object-fit:cover;object-position:50% 100%}
  /* flush to the photo's top-right corner, reading as a tag on the image */
  .hero-invis{left:auto;right:0;top:0;width:158px;height:53px}
  .hero-credband{display:block;order:3;background:#00475F;margin-top:-1px;padding:26px 24px 30px}
  /* Phone: the two credentials read as one unit each, both centred in the band
     and vertically centred against each other. Crest sized down so the pair balances. */
  .hero-creds{position:static;justify-content:center;align-items:center;gap:20px;padding:0 8px}
  .hero-creds .cred{gap:8px;justify-content:center;align-items:center;flex:0 1 auto}
  .hero-creds .cred span:last-child{font-size:10.5px;white-space:normal;max-width:130px;line-height:1.28;text-align:center}
  .hero-creds .cred-army img{width:48px;height:51px}
  .hero-creds .cred-army{justify-content:center}
  .hero-creds .cred-max span:last-child{max-width:136px;text-align:center}
  .hero-creds .cred-max{align-items:center;justify-content:center}
}
/* Nav at phone widths: links are already hidden below 820, and the full brand
   plus a labelled pill cannot both fit. Keep the brand (it is the identity) and
   collapse the pill to its WhatsApp glyph; the hero carries the labelled CTA a
   few hundred pixels below. font-size:0 hides the label without touching markup,
   and the text stays in the DOM for screen readers. */
@media(max-width:560px){
  .brand span{font-size:15px;white-space:nowrap}
  .brand svg{width:24px;height:24px}
  .brand{gap:8px}
  .wa-pill{font-size:0;padding:10px;gap:0;border-radius:999px;flex-shrink:0;min-width:44px;justify-content:center}
  .wa-pill svg{width:18px;height:18px}
  /* 2026-09-15: the 14ch measure broke the headline into four lines on a 390px
     phone. 18ch is 293px against the 342px the padded hero column offers, so the
     same words settle onto three lines at the same size. Tablets keep 14ch. */
  .newhero h1{max-width:18ch}
}

/* footer variants used on index.html + contact.html only (doctors/treatments keep the old .frow footer, untouched) */
.ffooter{border-top:1px solid var(--hair);padding:clamp(48px,5.55vw,80px) 0}
/* node 67:2710: full-width footer, 64px sides (not the 1200 shell) */
.ffooter .shell{max-width:none;padding:0 clamp(20px,4.44vw,64px)}
.ffooter.teal{background:var(--teal);border-top-color:rgba(250,250,248,.18)}
.frow2{display:flex;justify-content:space-between;align-items:stretch;gap:32px;flex-wrap:wrap}
.fcol{display:flex;flex-direction:column;justify-content:space-between;gap:20px;min-height:164px}
.fcol .brand{font-size:20px}
.fmeta{font-family:var(--sans2);font-size:16px;color:var(--grey);line-height:1.5}
.fcopy{font-family:var(--sans2);font-size:16px;color:var(--grey)}
.fc-sym{font-size:24px;vertical-align:-2px;margin-right:2px}
.ffooter.teal .fmeta,.ffooter.teal .fcopy,.ffooter.teal .fcol .brand{color:var(--paper)}
.fnav{display:flex;flex-direction:column;align-items:flex-end;justify-content:center;gap:32px;font-size:14px;letter-spacing:.56px;font-family:var(--sans)}
.fnav a{opacity:.62;font-weight:500;color:var(--ink);transition:opacity .25s}
/* footer links had no hover while the nav links did; same .62 -> 1 lift */
.fnav a:hover{opacity:1}
.fnav a.active{opacity:1;font-weight:600}
.ffooter.teal .fnav a{color:var(--paper)}

/* Keyboard focus: .tx-tab and .tst-arrow already carried this ring, but the nav
   and footer never got one. Same token, so every focusable is consistent. */
nav .brand:focus-visible,.navlinks a:focus-visible,.wa-pill:focus-visible,
footer .brand:focus-visible,.fnav a:focus-visible{outline:2px solid var(--teal);outline-offset:3px}
.ffooter.teal .brand:focus-visible,.ffooter.teal .fnav a:focus-visible{outline-color:var(--paper)}
/* Phone footer (2026-09-15). Two changes, both mobile only, desktop untouched:
   the page links move above the copyright line, so the copyright closes the page
   the way it does on desktop; and the address line drops to 14px so it stops
   competing with the brand. .fcol becomes display:contents at this width, which
   lifts the brand, address and copyright into .frow2 as flex items so order can
   interleave them with .fnav. Uniform 16px gap plus a 16px lead on .fnav keeps
   the footer the same height it had with the nested column. */
@media(max-width:600px){
  .frow2{flex-direction:column;gap:16px}
  .fcol{display:contents}
  .fcol .brand{order:1}
  .fmeta{order:2;font-size:14px}
  .fnav{order:3;margin-top:16px;flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:flex-start;gap:18px 24px}
  .fcopy{order:4}
}

/* ===================================================================
   MOTION PASS (2026-07-16) — vanilla CSS transitions/keyframes layered
   on the existing .rv + IntersectionObserver system. Easing
   cubic-bezier(.22,1,.36,1) throughout, transform+opacity only,
   no pins/parallax/scroll-linked effects. See .rv base rule above for
   the JS-enhancement gate (content is visible by default if JS fails).
   =================================================================== */

/* home hero: headline -> subtext -> CTA row, staggered on mount */
.newhero h1.rv{transition-duration:.7s}
.newhero .sub.rv{transition-delay:90ms}
.newhero .cta-row.rv{transition-delay:180ms}

/* hero photo: fade + gentle scale-settle, no rise, no hover zoom */
html.js .rv-photo{transform:scale(1.015);transition:opacity 1s cubic-bezier(.22,1,.36,1),transform 1s cubic-bezier(.22,1,.36,1);transition-delay:60ms}
html.js .rv-photo.in{opacity:1;transform:scale(1)}
.newherophoto img{transition:none}
.doc:hover .ph img{transform:none}

/* invisalign badge: last in the hero sequence, small rise */
html.js .rv-badge{transform:translateY(12px);transition-delay:400ms}
html.js .rv-badge.in{transform:none}

/* credential band: gradient is static (never animates); the two logo blocks stagger 80ms, after the CTA row */
.cred.rv:nth-child(1){transition-delay:270ms}
.cred.rv:nth-child(2){transition-delay:350ms}

/* middle sections: kicker, then heading +80ms, then content */
.sectionhead .kicker.rv{transition-delay:0ms}
.sectionhead h2.rv{transition-delay:80ms}

/* teaser cards / testimonials / treatment trio / doctor cards: left-to-right stagger, 80ms apart */
.teaser-row .item.rv:nth-child(1),.reviews .review.rv:nth-child(1),.docs .doc.rv:nth-child(1),.trio>.rv:nth-child(1){transition-delay:0ms}
.teaser-row .item.rv:nth-child(2),.reviews .review.rv:nth-child(2),.docs .doc.rv:nth-child(2),.trio>.rv:nth-child(2){transition-delay:80ms}
.teaser-row .item.rv:nth-child(3),.reviews .review.rv:nth-child(3),.docs .doc.rv:nth-child(3),.trio>.rv:nth-child(3){transition-delay:160ms}

/* practice/care section: image fades only (no rise, no zoom); text column keeps the normal rise */
html.js .care .ph.rv{transform:none}
html.js .care .ph.rv.in{transform:none}

/* contact page: heading rises, five rows stagger 60ms apart, map +200ms, CTA pill last */
.cline.rv:nth-child(1){transition-delay:0ms}
.cline.rv:nth-child(2){transition-delay:60ms}
.cline.rv:nth-child(3){transition-delay:120ms}
.cline.rv:nth-child(4){transition-delay:180ms}
.cline.rv:nth-child(5){transition-delay:240ms}
.contact .cta-row.rv{transition-delay:320ms}
.mapwrap.rv{transition-delay:200ms}
.cline{transition:none} /* no hover state on info rows */

/* footers (both new variants): one soft fade-up, no stagger */
.ffooter .frow2.rv{transition-delay:0ms}

/* buttons/links: the only hover motion on the site */
.cta,.cta-fig,.wa-pill{transition:transform .25s cubic-bezier(.22,1,.36,1),filter .25s cubic-bezier(.22,1,.36,1);opacity:1}
.cta:hover,.cta-fig:hover,.wa-pill:hover{transform:translateY(-1px);filter:brightness(.9)}

.cta-sec,.morelink a{
  border-bottom:none;
  background-image:linear-gradient(currentColor,currentColor);
  background-repeat:no-repeat;
  background-position:left bottom;
  background-size:0% 1.5px;
  transition:background-size .3s cubic-bezier(.22,1,.36,1);
  padding-bottom:2px;
}
.cta-sec:hover,.morelink a:hover{background-size:100% 1.5px}

@media(prefers-reduced-motion:reduce){
  .cred.rv:nth-child(2),.teaser-row .item.rv:nth-child(2),.reviews .review.rv:nth-child(2),.docs .doc.rv:nth-child(2),.trio>.rv:nth-child(2),
  .teaser-row .item.rv:nth-child(3),.reviews .review.rv:nth-child(3),.docs .doc.rv:nth-child(3),.trio>.rv:nth-child(3),
  .cline.rv:nth-child(2),.cline.rv:nth-child(3),.cline.rv:nth-child(4),.cline.rv:nth-child(5),
  .contact .cta-row.rv,.mapwrap.rv,.sectionhead h2.rv,.newhero .sub.rv,.newhero .cta-row.rv,html.js .rv-badge,html.js .rv-photo{transition-delay:0ms}
  html.js .rv-photo{transform:none}
  .cta:hover,.cta-fig:hover,.wa-pill:hover{transform:none}
}

/* ===================================================================
   NAV V2 + CONTACT V2 (Figma nodes 67:2563 HOME FINAL + 67:2630
   CONTACT FINAL, Jul 18). Later-in-file rules deliberately override the
   originals above so the older blocks stay untouched as reference.
   =================================================================== */

/* NAV, both frames: 88px bar, 64px side padding (full width, no shell cap),
   Alan Sans brand 20/0.4, links Alan Sans 14/0.28 at 62% (active semibold,
   full opacity, no underline), teal pill radius 16, py 12 px 24, icon 24. */
nav .shell{max-width:none;padding:0 clamp(20px,4.44vw,64px)}
.navrow{height:88px}
.brand{gap:12px}
.brand span{font-family:var(--sans2);font-weight:400;font-size:20px;letter-spacing:.4px}
.navlinks{gap:32px;font-family:var(--sans2);font-size:14px;font-weight:500;letter-spacing:.28px}
.navlinks a{opacity:.62}
.navlinks a:hover{opacity:1}
.navlinks a.active{opacity:1;font-weight:600;border-bottom:none;padding-bottom:0}
/* The pill is fixed nav chrome, so it must NOT ride --s. --s is the home hero's
   1440-composition scale, which main.js writes onto :root only when .newhero
   exists. On doctors/contact there is no hero, --s stayed unset, the calc()
   fallback of 1 applied, and the pill rendered ~12% larger than on home (and on
   home it grew unbounded past 1440). Static px keeps every page identical. */
.wa-pill{display:inline-flex;align-items:center;gap:22px;background:var(--teal);color:#fafaf8;border-radius:14px;padding:11px 22px;font-family:var(--sans2);font-weight:600;font-size:14px;letter-spacing:.28px;line-height:normal;white-space:nowrap}
.wa-pill svg{width:22px;height:22px}
@media(max-width:1180px){.wa-pill{gap:14px;font-size:14px;padding:10px 18px}.wa-pill svg{width:18px;height:18px}}
@media(max-width:560px){
  .wa-pill{font-size:0;padding:10px;gap:0;border-radius:999px}
  .wa-pill svg{width:18px;height:18px}
  .navrow{height:72px}
}

/* CONTACT V2: heading + contact cluster row, then two clinic cards. */
/* FOLD-FIT (like the hero): the section is exactly one fold on constrained
   viewports; the MAPS are the flexible element that absorbs compression, all
   text/spacing (64/64/64) stays true to the frame. Natural cap ~828px so tall
   screens render the frame's own proportions and the next content follows. */
.contactv2{padding-bottom:64px;display:flex;flex-direction:column;box-sizing:border-box;height:min(100svh,828px)}
.contactv2.page-top{padding-top:calc(88px + 64px)}
.cvshell{display:flex;flex-direction:column;flex:1;min-height:0;width:100%}
.cvshell{max-width:1440px;margin:0 auto;padding:0 clamp(20px,4.44vw,64px)}
.cv2-head{display:flex;align-items:flex-start;justify-content:space-between;gap:32px;margin-bottom:clamp(28px,4.44vw,64px)}
.cv2-head h1{font-family:var(--serif2);font-weight:400;font-size:clamp(38px,4.3vw,62px);line-height:1.02;letter-spacing:-.015em;color:var(--ink);white-space:nowrap}
.cv2-cluster{display:flex;gap:24px;align-items:flex-start;opacity:.6;padding-top:10px}
.cv2-col{display:flex;flex-direction:column;gap:16px}
.cv2-line{display:flex;gap:12px;align-items:center;font-family:var(--sans2);font-size:16px;line-height:1.4;color:#000}
.cv2-line img{width:20px;height:22px;object-fit:contain}
/* 12px, not 20px: the numbers column has to start on the same vertical line as
   the WhatsApp and email text, and .cv2-line uses a 12px icon gap. */
.cv2-callgroup{display:flex;gap:12px;align-items:flex-start}
.cv2-callgroup>img{width:20px;height:22px;object-fit:contain}
.cv2-nums{display:flex;flex-direction:column;gap:8px;align-items:flex-end;font-family:var(--sans2);font-size:16px;line-height:1.4}
.cv2-nums a,.cv2-line span{color:#000}
.cv2-line:hover,.cv2-nums a:hover{opacity:.75}
.cv2-cards{display:grid;grid-template-columns:1fr 1fr;gap:clamp(24px,3.33vw,48px);flex:1;min-height:0}
.clinic-card{display:flex;flex-direction:column;gap:24px;min-height:0}
.mapwrap2{position:relative;flex:1;min-height:170px;max-height:341px;border-radius:2px;overflow:hidden;background:#d9d9d4}
.mapwrap2 iframe{width:100%;height:100%;border:0;display:block;filter:grayscale(1) contrast(1.02)}
.chip{position:absolute;top:0;right:16px;display:flex;overflow:hidden;border-radius:0 0 4px 4px}
.chip span{background:var(--teal);color:#fff;font-family:var(--sans2);font-weight:600;font-size:12px;letter-spacing:2.16px;text-transform:uppercase;padding:8px}
.chip .pin{opacity:.9}
/* the chip must stay teal above the grayscaled map: lift it out of the filter */
.mapwrap2 .chip{z-index:2}
.clinic-id{display:flex;gap:24px;align-items:center}
.clinic-id>img{width:32px;height:32px;flex-shrink:0}
.clinic-id .cname{font-family:var(--sans2);font-weight:400;font-size:clamp(16px,1.25vw,18px);line-height:1.4;color:var(--ink)}
.clinic-id .caddr{font-family:var(--sans2);font-weight:300;font-size:14px;line-height:1.4;color:var(--ink)}
.clinic-hours{display:flex;gap:20px;align-items:center}
.clinic-hours .hl{display:flex;gap:16px;align-items:center;opacity:.5;font-family:var(--sans2);font-weight:600;font-size:12px;letter-spacing:2.16px;color:#000}
.clinic-hours .hl img{width:16px;height:16px}
.clinic-hours>span:last-child{font-family:var(--sans2);font-size:14px;line-height:1.4;color:var(--ink)}
/* contact reveal choreography: head first, then the two cards in sequence */
html.js .contactv2 .clinic-card.rv:first-child{transition-delay:140ms}
html.js .contactv2 .clinic-card.rv:last-child{transition-delay:300ms}
@media(prefers-reduced-motion:reduce){html.js .contactv2 .clinic-card.rv{transition-delay:0ms !important}}
@media(max-width:1100px){
  .cv2-head{flex-direction:column;gap:28px}
  .cv2-head h1{white-space:normal}
  .cv2-cluster{padding-top:0}
}
@media(max-width:860px){
  .contactv2{height:auto}
  .contactv2.page-top{padding-top:120px}
  .cv2-cards{grid-template-columns:1fr}
  .mapwrap2{flex:none;height:min(62vw,341px);max-height:none;min-height:0}
  /* 10px, not 16: the stacked numbers each carry a 44px tap target, so the run of
     three already reads long. Pulling the call group up against the email row is
     the only vertical air in the block that can come out without dropping a
     target below 44px. See the note on .cv2-nums in the 820px block. */
  .cv2-cluster{flex-direction:column;gap:6px}
  .cv2-nums{align-items:flex-start}
}

/* ===================================================================
   HOME TREATMENTS (node 88:247) + DOCTORS BAND (node 89:333), Jul 20.
   FOLD-FIT (Nihal, Jul 22): each section must sit inside ONE fold.
   Levers he approved: section padding 96/96 -> 64/64, icons may shrink
   to 80% (64px). Internal gaps ride svh clamps so the natural height
   tracks under the viewport: 798px at maxes, ~746 at 790svh, ~709 at
   720svh. No JS, text sizes stay exact; only air and icons compress.
   =================================================================== */
.t5{background:var(--paper);padding:clamp(44px,7.2svh,64px) 0}
.t5shell{max-width:1440px;margin:0 auto;padding:0 clamp(20px,4.44vw,64px)}
.t5-head{display:flex;align-items:flex-end;justify-content:space-between;gap:32px}
.t5-headL{display:flex;flex-direction:column;gap:16px;max-width:516px}
.t5 h2,.d5 h2{font-family:var(--serif2);font-weight:400;font-size:clamp(36px,3.75vw,54px);line-height:1.02;letter-spacing:-.015em;color:var(--ink)}
/* 16, not the frame's 18: matches what the hero sub actually renders at fold
   scale (18 x --s). Nihal, Jul 22: heading/sub sizes consistent across sections. */
.t5-sub{font-family:var(--sans2);font-weight:300;font-size:16px;letter-spacing:.32px;line-height:normal;color:var(--ink);opacity:.8}
/* persistent underline link (frame rest state); hover eases opacity, no slide.
   Size rides --s to match the hero's "Or call the clinic" rendered size (Nihal, Jul 22). */
/* --s is the desktop hero scale; on phones it collapses toward .27 and was
   shrinking these links to ~4px, hence the max() floor */
.t5-link{font-family:var(--sans2);font-weight:500;font-size:max(15px, calc(16px * var(--s,1)));letter-spacing:max(.3px, calc(.32px * var(--s,1)));color:var(--ink);border-bottom:1.5px solid #132c6b;padding-bottom:2px;white-space:nowrap;transition:opacity .25s}
.t5-link:hover{opacity:.55}
.d5-link:hover{opacity:.7} /* Read More hover approved as-is; keep it */
.t5-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(40px,7.2svh,64px) 64px;margin-top:clamp(56px,13.28svh,118px)}
.t5-card{display:flex;flex-direction:column;gap:clamp(14px,2.7svh,24px)}
.t5-card>img{width:clamp(60px,9svh,80px);height:clamp(60px,9svh,80px)}
.t5-card h3{font-family:var(--sans2);font-weight:400;font-size:18px;line-height:1.4;letter-spacing:0;color:var(--ink)}
.t5-card p{font-family:var(--sans2);font-weight:300;font-size:14px;line-height:1.4;color:var(--ink);margin-top:8px}

/* node 90:104 final: content-driven height (~678 at 1440), photos flush bottom */
.d5{background:var(--teal);padding:64px clamp(20px,4.44vw,64px) 0;display:flex;justify-content:center}
.d5-inner{display:flex;flex-direction:column;align-items:center;gap:64px}
.d5-head{display:flex;flex-direction:column;align-items:center;gap:16px;text-align:center}
/* flex-end: bios wrap to different line counts, bottom-aligning the columns is
   what keeps all three photos flush with the section's bottom edge */
.d5-row{display:flex;gap:80px;align-items:flex-end}
.d5-doc{width:300px;display:flex;flex-direction:column;align-items:center;gap:24px}
.d5-doc-text{display:flex;flex-direction:column;gap:8px;align-items:center;text-align:center;color:var(--paper)}
.d5-nr{display:flex;flex-direction:column;gap:4px}
.d5-doc h3{font-family:var(--sans2);font-weight:400;font-size:18px;line-height:1.4;color:var(--paper);margin:0}
.d5-role{font-family:var(--sans2);font-weight:600;font-size:14px;letter-spacing:.28px;text-transform:uppercase;opacity:.7}
.d5-bio{font-family:var(--sans2);font-weight:300;font-size:14px;line-height:1.4;max-width:295px}
.d5-photo{width:277px;height:255px;object-fit:cover;object-position:bottom}
/* Kalha, node 90:184: the frame crops his photo zoomed and shifted left */
.d5-photo-crop{position:relative;overflow:hidden}
.d5-photo-crop img{position:absolute;width:132.16%;height:171.14%;left:-16.08%;top:-10.75%;max-width:none;object-fit:cover}
.d5 h2{color:var(--paper)}
.d5-sub{font-family:var(--sans2);font-weight:300;font-size:16px;letter-spacing:.32px;line-height:normal;max-width:610px;color:var(--paper)}
.d5-link{color:var(--paper);border-bottom-color:var(--paper)}

/* choreography: header settles first, cards sweep L->R 80ms apart (row 2
   continues the sweep when it enters); band mirrors the hero h2->sub->link */
.t5-card.rv:nth-child(1){transition-delay:0ms}
.t5-card.rv:nth-child(2){transition-delay:80ms}
.t5-card.rv:nth-child(3){transition-delay:160ms}
.t5-card.rv:nth-child(4){transition-delay:0ms}
.t5-card.rv:nth-child(5){transition-delay:80ms}
.d5-head.rv{transition-delay:0ms}
.d5-doc.rv:nth-child(1){transition-delay:0ms}
.d5-doc.rv:nth-child(2){transition-delay:80ms}
.d5-doc.rv:nth-child(3){transition-delay:160ms}
@media(prefers-reduced-motion:reduce){.t5-card.rv,.d5-doc.rv{transition-delay:0ms !important}}

@media(max-width:1100px){
  .t5-grid{grid-template-columns:repeat(2,1fr);gap:48px}
}
@media(max-width:1240px){
  .d5-row{gap:40px}
}
@media(max-width:1000px) and (min-width:701px){
  .d5-row{flex-wrap:wrap;justify-content:center;padding-bottom:0}
}
@media(max-width:700px){
  .t5-head{flex-direction:column;align-items:flex-start;gap:24px}
  .t5-grid{grid-template-columns:1fr;gap:40px;max-width:460px}
  .t5-card>img{width:64px;height:64px}
  .d5{padding:64px 24px 0}
  .d5-row{flex-direction:column;gap:56px}
}

/* ─────────────────────────────────────────────────────────────────
   TREATMENTS PAGE, rebuilt 14 Sep as the two-pane finder. This is lab
   variant V2 (workspace/bouri-treatments-lab/build.py, build_v2), chosen
   by Nihal on 14 September. It replaces the 3 Aug rail-and-cards layout
   from Figma frame 102:839 entirely, along with its arrows and its
   right-hand rail.
   Group list on the left, sticky under the nav. Detail pane on the right,
   swapped on click by the controller in main.js.
   Two rules here are load-bearing and must not be "tidied":
     1. .tx-pane{padding:0} cancels the global section{padding} rule, since
        each pane is a <section>.
     2. the sibling margin that stacks the panes without JS is scoped to
        html:not(.js). Unscoped, it also applies to whichever single pane
        is showing (display:none on a previous sibling does not break the
        adjacent-sibling match), so every group after the first started
        40 to 72px lower than Implant Dentistry. Do not unscope it.
   ───────────────────────────────────────────────────────────────── */
/* 1440 shell on 64px gutters, the same box the nav, the footer and the
   other pages use, so the h1 lines up under the brand mark */
.tx .shell{max-width:1440px;margin-inline:auto;padding:0 clamp(20px,4.44vw,64px)}
/* the body grid carries its own bottom padding, so the section drops the
   global section{padding} bottom */
.tx.page-top{padding-bottom:0}

.tx-head{padding-bottom:clamp(30px,4vw,52px);border-bottom:1px solid var(--hair);
         display:flex;flex-wrap:wrap;gap:24px 48px;align-items:flex-end;
         justify-content:space-between}
.tx-head h1{font-family:var(--serif);font-weight:300;font-size:clamp(36px,5.2vw,64px);
            line-height:1.03;letter-spacing:-.018em;margin-top:12px;max-width:none}
.tx-lede{color:var(--grey);font-size:16.5px;max-width:30em}

.tx-body{display:grid;grid-template-columns:330px minmax(0,1fr);
         gap:clamp(28px,4vw,64px);
         padding:clamp(28px,4vw,52px) 0 clamp(56px,8vw,110px)}
/* 88px of fixed nav plus 16px of clear space */
.tx-list{display:flex;flex-direction:column;gap:6px;position:sticky;top:104px;align-self:start}
.tx-btn{display:flex;gap:14px;align-items:center;text-align:left;width:100%;
        background:none;border:1px solid transparent;border-radius:3px;padding:16px;
        cursor:pointer;font:inherit;color:var(--grey);min-height:44px;
        transition:background .25s,color .25s,border-color .25s}
.tx-btn:hover{background:rgba(17,17,16,.035);color:var(--ink)}
.tx-btn:focus-visible{outline:2px solid var(--teal);outline-offset:3px}
.tx-btn img{width:24px;height:24px;flex:0 0 24px;margin-top:0;opacity:.55}
.tx-btn b{display:block;font-family:var(--serif);font-weight:400;font-size:19px;
          line-height:1.22;color:var(--ink);letter-spacing:-.005em}
.tx-btn.is-on{background:var(--teal);border-color:var(--teal);color:var(--paper)}
.tx-btn.is-on b{color:var(--paper)}
.tx-btn.is-on img{filter:invert(1) brightness(2);opacity:.95}

.tx-pane{padding:0;margin:0}
html:not(.js) .tx-pane+.tx-pane{margin-top:clamp(40px,6vw,72px)}
html.js .tx-pane{display:none}
html.js .tx-pane.is-on{display:block}
.tx-pane h2{font-family:var(--serif);font-weight:300;font-size:clamp(28px,3.4vw,42px);
            line-height:1.08;letter-spacing:-.012em}
.tx-blurb{margin-top:14px;color:var(--grey);font-size:16.5px;max-width:40em;
          padding-bottom:clamp(22px,3vw,34px);border-bottom:1px solid var(--hair)}

.tx-row{padding:clamp(20px,2.6vw,30px) 0;border-bottom:1px solid var(--hair);
        display:grid;grid-template-columns:minmax(0,1fr) 148px;gap:24px;align-items:start}
.tx-row h3{font-family:var(--serif);font-weight:400;font-size:clamp(19px,2vw,25px);
           line-height:1.2;letter-spacing:-.008em}
.tx-row p{margin-top:9px;color:var(--grey);font-size:15.5px;max-width:40em}
.tx-thumb{aspect-ratio:3/2;overflow:hidden;border-radius:2px;background:#e8e8e4}
.tx-thumb img{width:100%;height:100%;object-fit:cover;filter:grayscale(1) contrast(1.04)}

@media(max-width:900px){
  .tx-body{grid-template-columns:1fr;gap:26px}
  .tx-list{position:static}
  /* the pill radius made the phone tabs read as a different component from the
     desktop list; they now carry the same 3px the desktop .tx-btn uses */
  .tx-btn{border-color:var(--hair);border-radius:3px;align-items:center;padding:12px 16px}
  .tx-btn img{margin-top:0}
  .tx-btn b{font-size:17px}
  /* 72px of nav under 560 plus clear space */
  .tx-panes{scroll-margin-top:88px}
  .tx-row{grid-template-columns:1fr;gap:14px}
  .tx-thumb{width:100%;max-width:100%;order:-1}
}
@media(prefers-reduced-motion:reduce){.tx-btn{transition:none}}
/* ─────────────────────────────────────────────────────────────────
   TESTIMONIALS + SECONDARY CTA, Figma node 117:4 (the current copy of
   116:3). Testimonials 1440x710 on 100px vertical padding, 120px gutters,
   a 1200 row: 48px arrow, 1104 of cards, 48px arrow, no gaps. Cards are
   352 wide on a 24px gutter, 36px padding, 16px radius.
   Secondary CTA 1440x365. Figma draws it on 80px vertical padding against
   the testimonials' 100px; per Nihal's note the two bands now share the
   same 100px so they read as one size.
   ───────────────────────────────────────────────────────────────── */
.tst{background:var(--paper);padding:clamp(56px,7.5vw,100px) 0}
.tst .shell{max-width:none;padding:0 clamp(20px,8.33vw,120px)}
.tst-head{display:flex;flex-direction:column;gap:16px;align-items:center;text-align:center;
          color:var(--ink);margin-bottom:clamp(32px,4vw,52px)}
.tst-head h2{font-family:var(--serif2);font-weight:400;font-size:clamp(30px,3.75vw,54px);
             line-height:1.02;letter-spacing:-.015em}
.tst-head p{font-family:var(--sans2);font-weight:300;font-size:clamp(15px,1.25vw,18px);
            line-height:normal;letter-spacing:.02em;opacity:.8;max-width:610px}

/* 48 + 1104 + 48 = the frame's 1200 row, arrows flush against the cards.
   Capped and centred so the arrows stay beside the cards above 1440. */
/* 28 Sep: the arrows sat flush against the cards at gap:0, so the 48px circle
   touched the card edge on both sides. A 24px gap each side clears them, and
   max-width grows by the same 48px so the viewport keeps its 1104px. */
.tst-row{display:flex;align-items:center;justify-content:center;gap:24px;
         max-width:1248px;margin-inline:auto}
.tst-arrow{flex:0 0 48px;width:48px;height:48px;border-radius:24px;background:var(--paper);
           border:1px solid rgba(17,17,16,.08);display:grid;place-items:center;cursor:pointer;
           transition:background .3s var(--ease,cubic-bezier(.22,1,.36,1)),border-color .3s,opacity .3s,transform .3s}
.tst-arrow img{width:20px;height:20px;display:block}
.tst-arrow:hover:not(:disabled){background:#fff;border-color:rgba(17,17,16,.22);transform:scale(1.06)}
.tst-arrow:disabled{opacity:.3;cursor:default}
.tst-arrow:focus-visible{outline:2px solid var(--teal);outline-offset:3px}

/* The clip box is pushed 26px above and below the cards and pulled straight
   back with a matching negative margin, so layout is untouched but a card's
   hover lift (-3px) and its drop shadow (14px past the foot) are no longer
   sliced off. Left and right stay flush: nothing moves sideways on hover,
   so an inline bleed would only let the next card peek through. */
.tst-viewport{flex:1;min-width:0;max-width:1104px;
              padding-block:26px;margin-block:-26px;overflow:hidden}
.tst-track{display:flex;gap:24px;list-style:none;margin:0;padding:0;
           transition:transform .28s cubic-bezier(.22,1,.36,1)}
.tst-card{flex:0 0 calc((100% - 48px) / 3);display:flex;flex-direction:column;gap:24px;
          background:var(--paper);border:1px solid rgba(17,17,16,.08);border-radius:16px;
          padding:clamp(22px,2.5vw,36px);transition:border-color .35s,box-shadow .35s,transform .35s}
.tst-card:hover{border-color:rgba(19,85,107,.28);box-shadow:0 20px 44px -28px rgba(19,85,107,.4);transform:translateY(-3px)}
/* A 72px glyph in a 20px box clipped its own ascender against the card's top
   padding. The box is now tall enough to hold the mark and the glyph sits on
   its own baseline inside it. */
.tst-quote{font-family:var(--serif2);font-size:72px;line-height:1;height:auto;
           color:var(--teal);opacity:.9;display:block;margin-top:4px}
.tst-stars{display:flex;gap:4px;align-items:center}
.tst-stars img{width:16px;height:16px;display:block}
.tst-text{font-family:var(--sans2);font-weight:300;font-size:clamp(15px,1.11vw,16px);
          line-height:1.5;letter-spacing:.01em;color:var(--ink)}
/* pushes the attribution to the card foot so every card in a row aligns */
.tst-author{margin-top:auto;display:flex;flex-direction:column;gap:4px}
.tst-author b{font-family:var(--sans2);font-weight:600;font-size:15px;letter-spacing:.01em;color:var(--ink)}
.tst-author span{font-family:var(--sans2);font-weight:400;font-size:13px;letter-spacing:.01em;color:var(--grey)}

/* ── secondary CTA band ── */
/* same vertical padding as .tst so the two bands are one size (defect 4).
   Figma 117:33 draws 80px here against 117:5's 100px; Nihal's note wins. */
.cta2{background:var(--teal);padding:clamp(56px,7.5vw,100px) 0;color:var(--paper)}
.cta2 .shell{max-width:none;padding:0 clamp(20px,8.33vw,120px);
             display:flex;flex-direction:column;align-items:center;gap:32px}
.cta2-text{display:flex;flex-direction:column;gap:16px;align-items:center;text-align:center}
.cta2-text h2{font-family:var(--serif2);font-weight:400;font-size:clamp(30px,3.75vw,54px);
              line-height:1.02;letter-spacing:-.015em}
.cta2-text p{font-family:var(--sans2);font-weight:300;font-size:clamp(15px,1.25vw,18px);
             line-height:normal;letter-spacing:.02em;opacity:.9;max-width:610px}
.cta2-row{display:flex;gap:24px;align-items:center;justify-content:center;flex-wrap:wrap}
.cta2-btn{background:var(--paper);color:#000;border-radius:16px;padding:16px 24px;
          display:inline-flex;align-items:center;gap:24px;font-family:var(--sans2);font-weight:600;
          font-size:16px;letter-spacing:.02em;white-space:nowrap;
          transition:transform .3s cubic-bezier(.22,1,.36,1),box-shadow .3s}
.cta2-btn svg{width:24px;height:24px;flex-shrink:0}
.cta2-btn:hover{transform:translateY(-2px);box-shadow:0 14px 30px -16px rgba(0,0,0,.45)}
.cta2-link{font-family:var(--sans2);font-weight:500;font-size:16px;letter-spacing:.02em;
           color:var(--paper);border-bottom:1.5px solid var(--paper);padding-bottom:2px;
           transition:opacity .3s}
.cta2-link:hover{opacity:.75}

@media(max-width:1024px){
  .tst-card{flex-basis:calc((100% - 24px) / 2)}
}
@media(max-width:720px){
  /* arrows would crowd a phone; the track becomes a native swipe rail */
  .tst-arrow{display:none}
  /* scroll-padding matches padding-inline so the first card snaps to the
     gutter instead of the viewport edge; without it the rail rests flush left */
  .tst-viewport{overflow-x:auto;scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;
                scrollbar-width:none;margin-inline:calc(clamp(20px,8.33vw,120px) * -1);
                padding-inline:clamp(20px,8.33vw,120px);
                scroll-padding-inline:clamp(20px,8.33vw,120px)}
  .tst-viewport::-webkit-scrollbar{display:none}
  .tst-track{transform:none !important;gap:16px}
  .tst-card{flex-basis:82vw;max-width:340px;scroll-snap-align:start}
  .cta2-row{flex-direction:column;gap:20px}
  .cta2-btn{width:100%;justify-content:center;max-width:340px}
}
@media(prefers-reduced-motion:reduce){
  .tst-track{transition:none}
  .tst-card:hover,.cta2-btn:hover,.tst-arrow:hover:not(:disabled){transform:none}
}

/* ─────────────────────────────────────────────────────────────────
   TOUCH TARGETS (audit 29 Jul). At <=820px the brand link, the booking
   pill, the footer nav links and the contact rows all rendered between
   22px and 38px tall. 44px is the accepted minimum for a reliable tap,
   so each gets a min-height and centres its own content. Using
   min-height rather than padding keeps the visual rhythm unchanged.
   ───────────────────────────────────────────────────────────────── */
@media(max-width:820px){
  .brand{min-height:44px}
  .wa-pill{min-height:44px;display:inline-flex;align-items:center}
  .fnav a{min-height:44px;display:inline-flex;align-items:center}
  .fnav{gap:4px 24px}
  .cv2-line{min-height:44px;display:flex;align-items:center}
  .cline a{min-height:44px;display:inline-flex;align-items:center}
  /* the stacked phone numbers on Contact are separate links; each needs its own target */
  .cv2-nums a{min-height:44px;display:inline-flex;align-items:center;line-height:1.1}
  /* the 44px targets already separate the numbers; an 8px gap on top of them
     put 52px between lines and broke the hierarchy against the two rows above */
  .cv2-nums{gap:0}
  /* the icon top-aligns while the first number's text sits centred inside its
     44px target, so the icon gets the same box and centres with it */
  /* the icon top-aligns while the first number's text sits centred inside its
     44px target, so the icon is nudged down to centre with it. It keeps its own
     22px height: the Figma export carries preserveAspectRatio="none", so a 44px
     box stretched the glyph to double height rather than letterboxing it. */
  .cv2-callgroup>img{height:22px;align-self:flex-start;margin-top:11px}
  .t5-link,.d5-link{min-height:44px;display:inline-flex;align-items:center}
  /* the two "Or call the clinic" links carry the same 1.5px underline as
     .t5-link and get the same treatment, so all four text links on mobile
     share one hit-area rule instead of three of them having it and one not */
  .cta-sec,.cta2-link{min-height:44px;display:inline-flex;align-items:center}
}

/* 28 Sep: a blinking text caret appeared wherever Nihal clicked. Nothing in the
   markup or the JS creates one: there is no contenteditable, no tabindex and no
   focus() call anywhere in the four pages. The cause is Chrome caret browsing,
   which F7 toggles on, and it affects every site not just this one. This rule
   suppresses the caret on this site regardless. Any input, textarea or editable
   region added later keeps a working caret. */
*{caret-color:transparent}
input,textarea,select,[contenteditable]{caret-color:auto}

/* 28 Sep: secondary clinical detail under a treatment entry. Sits quieter than
   the main description so the entry still reads as one paragraph plus a note. */
.tx-note{margin-top:10px;font-size:14px;line-height:1.6;color:var(--grey)}
.tx-note b{color:var(--ink);font-weight:600}
