/* ============================================================
   Dr Nim Cabraal — Homepage
   Static implementation of the Claude Design source
   (Homepage.html + home-part1.jsx + home-part2.jsx).
   Design tokens come from _ds/.../tokens/*.css — never hard-code
   a brand colour or type ramp here, reference the token.
   ============================================================ */

/* ---------- base ---------- */
/* Any class that sets `display` outranks the UA sheet's [hidden]{display:none},
   which silently breaks JS that toggles the hidden property (the stepped
   referral form). Restate it globally so `hidden` always wins. */
[hidden]{display:none!important}
html{scroll-behavior:smooth}
body{margin:0;background:var(--surface-page)}
a{color:var(--teal-700);text-decoration-color:var(--blush-300);text-underline-offset:3px}
a:hover{color:var(--blush-500)}
img{max-width:100%}
/* Visually hidden but available to screen readers. The blog filters are
   the first controls on the site whose only visible label is a
   placeholder, and a placeholder is not a label. */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}

/* The source renders inside <div style="min-width:1240px">. This is a
   desktop-only comp; the min-width is preserved deliberately so the
   review matches the design tool rather than inventing breakpoints. */
.page{min-width:1240px}

.wrap{max-width:1280px;margin:0 auto;padding:0 28px}

.eyebrow{font:var(--text-subheading);letter-spacing:var(--subheading-tracking);text-transform:uppercase;color:var(--blush-500)}
.eyebrow--dark{color:var(--blush-300)}


/* ---------- buttons (DS Button component, flattened) ---------- */
.btn{font:var(--text-button);font-family:var(--font-body);border:none;border-radius:var(--radius-pill);cursor:pointer;
  height:var(--control-h);padding:0 30px;display:inline-flex;align-items:center;justify-content:center;gap:8px;
  text-decoration:none;transition:background .2s ease,color .2s ease}
.btn--sm{height:var(--control-h-sm);padding:0 22px}
.btn--primary{background:var(--teal-800);color:var(--cream-50)}
.btn--primary:hover{background:var(--teal-700);color:var(--cream-50)}
.btn--secondary{background:var(--blush-300);color:var(--teal-800)}
.btn--secondary:hover{background:var(--blush-400);color:var(--teal-800)}
.btn--ghost{background:transparent;color:var(--teal-800);box-shadow:inset 0 0 0 1.5px var(--teal-800)}
.btn--ghost:hover{background:var(--teal-50);color:var(--teal-800)}
.btn--outline-light{background:transparent;color:var(--cream-50);box-shadow:inset 0 0 0 1.5px var(--cream-50)}
.btn--outline-light:hover{background:rgba(251,247,245,.12);color:var(--cream-50)}
/* Two buttons side by side inside a .split-copy, which is a column flex. */
.btn-row{display:flex;flex-wrap:wrap;gap:12px}

/* ---------- header ---------- */
.hdr{position:sticky;top:0;z-index:100;background:var(--cream-50);border-bottom:1px solid var(--border-soft);
  transition:background .3s ease-out,border-color .3s ease-out,backdrop-filter .3s ease-out}
/* Once the page scrolls, the bar goes translucent over the content behind it.
   cream-50 is #FBF7F5; the blur is what keeps 15px nav text legible against
   photography, so keep it if the alpha is ever lowered further. */
.hdr--scrolled{background:rgba(251,247,245,.78);border-bottom-color:rgba(234,221,214,.6);
  -webkit-backdrop-filter:saturate(180%) blur(14px);backdrop-filter:saturate(180%) blur(14px)}
@supports not (backdrop-filter:blur(1px)){.hdr--scrolled{background:rgba(251,247,245,.94)}}
.hdr-inner{display:flex;align-items:center;justify-content:space-between;gap:16px;height:84px}
.hdr-logo{display:flex;align-items:center;flex-shrink:0}
/* Logo height and nav gap are coupled, so change them together.
   .hdr-inner is space-between, which pins the logo to the left content
   margin and the phone/button group to the right one. That alignment only
   holds while the three groups plus their 16px minimum gaps fit the
   content width, and the tightest case is the 1240px floor set by
   .page{min-width}, where the content box is 1184px rather than the 1280px
   the design was drawn at.
   At 34px the wordmark is 261px wide and the bar had 14px to spare there.
   38px takes it to 292px, which alone overruns the floor; recovering 20px
   by tightening the nav from 14px to 10px puts it back with 10px spare.
   Measured, not guessed: 40px does not fit at the floor at any sane nav
   gap, and the right-hand group starts overhanging the content margin. */
.hdr-logo img{height:38px;width:auto}
.hdr-nav{display:flex;align-items:center;gap:10px}
.hdr-right{display:flex;align-items:center;gap:16px;flex-shrink:0}
.hdr-tel{display:inline-flex;align-items:center;gap:8px;font:500 15px/1 var(--font-body);color:var(--teal-800);text-decoration:none;white-space:nowrap}

.nav-link{font:500 15px/1 var(--font-body);color:var(--teal-800);text-decoration:none;padding:10px 2px;display:inline-flex;align-items:center;gap:5px;white-space:nowrap;transition:color .2s ease-out}
.nav-link:hover{color:var(--blush-500)}
/* Current page. Uses the same blush the nav already goes to on hover,
   so the marker reads as "you are here" rather than a new colour. */
.nav-link[aria-current="page"]{color:var(--blush-500)}
.nav-item{position:relative}
.nav-dd{position:absolute;top:100%;left:50%;transform:translateX(-50%) translateY(6px);background:var(--white);border:1px solid var(--border-soft);border-radius:16px;box-shadow:var(--shadow-card);padding:14px;opacity:0;visibility:hidden;transition:opacity .2s ease-out,transform .2s ease-out;z-index:60}
.nav-item:hover .nav-dd,.nav-item:focus-within .nav-dd{opacity:1;visibility:visible;transform:translateX(-50%) translateY(0)}
.nav-dd a{display:block;font:400 14px/1.4 var(--font-body);color:var(--teal-800);text-decoration:none;padding:9px 14px;border-radius:10px;white-space:nowrap;transition:background .2s ease-out,color .2s ease-out}
.nav-dd a:hover{background:var(--blush-50);color:var(--blush-500)}
/* Current page inside a dropdown, plus the parent label that owns it.
   Mirrors WordPress's current-menu-item / current-menu-ancestor pair, so
   the nav bar still shows where you are while the child is hidden. */
.nav-dd a[aria-current="page"]{background:var(--blush-50);color:var(--blush-500)}
.nav-link--ancestor{color:var(--blush-500)}
.nav-dd--wide{display:grid;grid-template-columns:1fr 1fr;gap:0 8px;width:560px}

/* ---------- photo slots ----------
   Stands in for the design tool's <image-slot> custom element. The
   placeholder sits behind the <img>; if the file is absent the img is
   hidden by its onerror handler and the placeholder shows through. */
.photo{position:relative;overflow:hidden;background:var(--blush-50)}
.photo::after{content:attr(data-label);position:absolute;inset:0;display:grid;align-content:center;justify-items:center;gap:10px;
  padding:24px;text-align:center;font:400 12px/1.5 var(--font-body);color:var(--blush-500);
  background:var(--blush-50) url('../assets/logo-icon-dark.png') no-repeat center calc(50% - 26px);
  background-size:38px auto;opacity:.85}
.photo > img{position:relative;z-index:1;width:100%;height:100%;object-fit:cover;display:block}
.photo--dark{background:var(--teal-700)}
.photo--dark::after{color:rgba(251,247,245,.75);background-color:var(--teal-700);background-image:url('../assets/logo-icon-white.png')}
.photo--r20{border-radius:20px}

/* ---------- hero ---------- */
.hero{position:relative;overflow:hidden;background:var(--teal-800)}
.hero-bg{position:absolute;top:0;left:0;right:0;height:125%}
.hero-scrim{position:absolute;inset:0;background:linear-gradient(90deg,rgba(0,0,0,.72) 0%,rgba(0,0,0,.45) 55%,rgba(0,0,0,.15) 100%);pointer-events:none;z-index:2}
.hero-wrap{position:relative;z-index:3;pointer-events:none;min-height:38vw;display:flex;align-items:center}
.hero-copy{max-width:560px;display:flex;flex-direction:column;gap:28px;align-items:flex-start;padding:90px 0 100px}
/* The eyebrow is a one-line label, not body copy, so it opts out of the
   560px measure that sets the h1 and paragraph line length. It needs 666px
   and the hero wrap gives it 1280px, so it overhangs the column without
   coming near the edge. Keep the h1 and paragraph on 560px: widening the
   column instead would change where the headline breaks. */
.hero-copy .eyebrow{white-space:nowrap}
.hero-copy h1{font:var(--text-display);color:var(--white);text-wrap:pretty}
.hero-copy p{font:var(--text-body-lg);color:rgba(255,255,255,.88);margin:0;max-width:480px}
/* Row, not column: every other hero carries a single button so the old
   column direction never showed, and a stacked pair reads as two
   competing primaries. Matches .cta-actions. */
.hero-actions{display:flex;flex-wrap:wrap;align-items:center;gap:14px;pointer-events:auto}
/* Interior hero. Was 26vw, which showed only about 666px of a 2560px-wide
   plate: the slice visible is height x plateWidth / viewportWidth, so it
   is fixed at any supported width but it is small. That wasn't enough to
   hold a subject — on the blog plate the seated woman alone spans 736px,
   so no object-position value could keep her head in frame, only choose
   which end got cut.

   36vw shows ~922px, which clears her with room and leaves only the top
   of the standing figure's hair trimmed. It also brings the interior
   heroes up near the homepage at 38vw and the specialty pages at 40vw,
   so the three read as one family instead of the interiors looking
   clipped. One rule: About, Specialties, For Patients, Referral Guide,
   Blog and the article template all move together. */
.hero--page .hero-wrap{min-height:36vw}
.hero--page .hero-copy{padding:80px 0 84px}

/* ---------- generic section furniture ---------- */
.sec{padding:120px 0}
.sec--white{background:var(--white)}
.sec--cream{background:var(--cream-50);position:relative;overflow:hidden}
/* The blush tint already carries photo placeholders, service icons and the
   tick bullets; --surface-tint is its section-level alias. It exists so a
   page with more light sections than the homepage can still alternate
   without ever putting two creams or two whites next to each other. */
/* position:relative so a .sec-texture layer has something to be inset
   against — but deliberately no overflow:hidden, unlike .sec--cream.
   The texture is inset:0 at 100%/100% so it cannot overflow anyway, and
   the clip would kill the sticky .steps-intro this surface is used for. */
.sec--tint{background:var(--surface-tint);position:relative}
/* Cream, and position:relative so a .sec-texture layer has something to be
   inset against — but deliberately WITHOUT the overflow:hidden that
   .sec--cream carries. That clip would kill the article layout's sticky
   contents rail and would cut the contact portrait where it lifts above
   its band. The texture is inset:0 at 100%/100% so it cannot overflow
   anyway, which is what makes the clip unnecessary. */
.sec--paper{background:var(--cream-50);position:relative}
/* Pairs with .blog-filters: keep the two values the same or the row goes
   lopsided again. */
.sec--tight-top{padding-top:52px}
.sec--dark{position:relative;overflow:hidden;background:var(--teal-800)}
.sec-texture{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:.1;pointer-events:none}
.sec-scrim{position:absolute;inset:0;background:rgba(0,0,0,.6);pointer-events:none;z-index:2}
.rel{position:relative;z-index:3}

.sec-head{display:flex;flex-direction:column;gap:18px;align-items:center;text-align:center;max-width:640px;margin:0 auto 56px}
.sec-head h2{font:var(--text-h1);text-wrap:pretty}
.sec-head p{font:var(--text-body-md);color:var(--text-soft);margin:0}
.sec-head--dark h2{color:var(--cream-50)}
.sec-head--tight{gap:16px;max-width:620px;margin-bottom:52px}

.split{display:grid;gap:72px;align-items:center}
.split--media-first{grid-template-columns:1fr 1.05fr}
.split--copy-first{grid-template-columns:1.05fr 1fr}
.split-copy{display:flex;flex-direction:column;gap:24px;align-items:flex-start}
.split-copy h2{font:var(--text-h1);text-wrap:pretty}
.split-copy p{font:var(--text-body-md);color:var(--text-soft);margin:0}
.split-media{height:480px;border-radius:24px;overflow:hidden}

/* ---------- services ---------- */
.svc-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:20px}
.svc-card{background:var(--white);border:1px solid var(--border-soft);border-radius:20px;box-shadow:var(--shadow-card);padding:28px;display:flex;flex-direction:column;gap:14px;text-decoration:none;color:var(--teal-800);transition:border-color .3s cubic-bezier(.22,.61,.36,1),background .3s cubic-bezier(.22,.61,.36,1),color .3s cubic-bezier(.22,.61,.36,1)}
.svc-card:hover{border-color:var(--teal-800);background:var(--teal-800);color:var(--cream-50)}
/* The title box is given the tallest title's height at runtime so the
   blurbs line up (balanceServiceCards in app.js). Centring the text
   inside that box splits the leftover space above and below the
   heading instead of pooling it all underneath, which is what made
   one- and two-line cards look bottom-heavy. */
.svc-card .svc-title{font:400 21px/1.3 var(--font-display);text-wrap:pretty;display:flex;align-items:center}
/* Softened to separate the blurb from the heading. .9 lands at 5.01:1 on
   the white card; .85 measures 4.47:1, just under the 4.5:1 AA floor for
   14px text, which matters on a site built for a 50+ audience. */
.svc-card .svc-sub{color:var(--text-soft);font:var(--text-body-sm);opacity:.9;transition:color .3s cubic-bezier(.22,.61,.36,1)}
.svc-card:hover .svc-sub{color:rgba(251,247,245,.8)}
.svc-card .svc-icon{width:44px;height:44px;border-radius:999px;display:grid;place-items:center;position:relative;background:var(--blush-50);transition:background .3s cubic-bezier(.22,.61,.36,1)}
.svc-card:hover .svc-icon{background:rgba(251,247,245,.12)}
.svc-card .icon-dark,.svc-card .icon-white{transition:none;width:24px;height:auto}
.svc-card .icon-white{position:absolute;inset:0;margin:auto;opacity:0}
.svc-card:hover .icon-white{opacity:1}
.svc-card:hover .icon-dark{opacity:0}

/* ---------- USP marquee ---------- */
.usp-bg{position:absolute;top:-35%;left:0;right:0;height:150%}
.usp-marquee{pointer-events:auto;overflow:hidden;
  mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent)}
.usp-track{display:flex;gap:24px;width:max-content;animation:uspScroll 36s linear infinite}
.usp-marquee:hover .usp-track{animation-play-state:paused}
@keyframes uspScroll{from{transform:translateX(0)}to{transform:translateX(-50%)}}
.usp-card{width:320px;flex-shrink:0;border-radius:20px;padding:28px;display:flex;flex-direction:column;gap:12px;box-sizing:border-box;
  background:linear-gradient(180deg,rgba(18,63,67,.85),rgba(11,42,45,.97))}
.usp-card .usp-icon{height:30px;display:flex;align-items:center}
.usp-card .usp-title{font:400 22px/1.3 var(--font-display);color:var(--cream-50)}
.usp-card .usp-body{font:var(--text-body-sm);color:rgba(251,247,245,.8)}

/* ---------- why us list ---------- */
.tick-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:12px}
.tick-list li{display:flex;gap:12px;align-items:center;font:var(--text-body-md);color:var(--teal-800)}
.tick{width:22px;height:22px;border-radius:999px;background:var(--blush-50);color:var(--blush-500);display:grid;place-items:center;flex-shrink:0}

/* ---------- recovery steps ----------
   An editorial two-column block rather than a centred list: the heading
   holds in the left column while the steps scroll past it, which is what
   lets the section use the full content width instead of leaving half of
   it empty. Nothing here is a card, deliberately — services and the USP
   marquee either side of it are both card grids, so this one earns its
   separation from hairlines, whitespace and the display face instead.

   The intro can stick because no ancestor of it clips: .sec--tint sets a
   background and nothing else, unlike .sec--cream and .sec--dark which
   both carry overflow:hidden for their texture layers. If this block is
   ever moved into one of those, the heading will silently stop sticking. */
.steps{display:grid;grid-template-columns:420px minmax(0,1fr);gap:96px;align-items:start}
/* 84px header + 32px breathing room. */
.steps-intro{position:sticky;top:116px;display:flex;flex-direction:column;gap:22px;align-items:flex-start}
.steps-intro h2{font:var(--text-h1);text-wrap:pretty}
.steps-intro p{font:var(--text-body-md);color:var(--text-soft);margin:0}

.steps-list{list-style:none;margin:0;padding:0}
/* Hairlines between steps, not around them: the rule belongs to the gap,
   so the first step opens flush with the heading beside it and the last
   one closes without a trailing edge. */
/* Baseline, not start: the numeral and the title are set at 44px and 26px
   of the same face, so aligning their first baselines is what actually
   makes them sit on a line together. .step-body is a flex column, whose
   baseline is its first item, so this resolves to the h3. */
.step{display:grid;grid-template-columns:72px minmax(0,1fr);gap:32px;align-items:baseline;
  padding:40px 0;border-top:1px solid var(--border-strong)}
.step:first-child{border-top:none;padding-top:0}
.step:last-child{padding-bottom:0}
/* The numerals are the one piece of pure ornament on the page, so they run
   large in the display face and sit back in blush-400 — read as texture
   first and as a number second. The order they carry is already obvious
   from the stacking, so they are not load-bearing for meaning. */
.step-num{font:400 44px/1 var(--font-display);color:var(--blush-400);
  font-variant-numeric:lining-nums tabular-nums}
.step-body{display:flex;flex-direction:column;gap:12px}
.step-body h3{font:400 26px/1.35 var(--font-display);color:var(--teal-800);margin:0;text-wrap:pretty}
.step-body p{font:var(--text-body-md);color:var(--text-soft);margin:0;max-width:60ch}

/* ---------- document downloads ----------
   A single column of link rows rather than a grid: these titles are long
   clinical names, and a row lets one wrap without dragging four siblings
   taller. Distinguished from the recovery steps and the FAQ rows above —
   both hairline lists — by being real cards with a hover state, because
   unlike those two these are things you click. The arrow nudges down on
   hover, which is the only cue that says download rather than navigate. */
.dl-list{display:flex;flex-direction:column;gap:14px}
.dl-row{display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:22px;align-items:center;
  background:var(--white);border:1px solid var(--border-soft);border-radius:16px;box-shadow:var(--shadow-card);
  padding:20px 26px;text-decoration:none;color:var(--teal-800);
  transition:border-color .3s cubic-bezier(.22,.61,.36,1)}
.dl-row:hover{border-color:var(--teal-800);color:var(--teal-800)}
.dl-icon{width:44px;height:44px;border-radius:999px;background:var(--blush-50);color:var(--blush-500);
  display:grid;place-items:center;
  transition:background .3s cubic-bezier(.22,.61,.36,1),color .3s cubic-bezier(.22,.61,.36,1)}
.dl-row:hover .dl-icon{background:var(--teal-800);color:var(--cream-50)}
.dl-title{font:400 20px/1.35 var(--font-display);text-wrap:pretty}
/* text-faint at rest so the row reads title-first; the label is a cue, not
   a second heading. It only comes forward once the row is hovered. */
.dl-action{display:inline-flex;align-items:center;gap:9px;white-space:nowrap;
  font:500 14px/1 var(--font-body);color:var(--text-faint);
  transition:color .3s cubic-bezier(.22,.61,.36,1)}
.dl-row:hover .dl-action{color:var(--blush-500)}
.dl-action svg{transition:transform .3s cubic-bezier(.22,.61,.36,1)}
.dl-row:hover .dl-action svg{transform:translateY(2px)}

/* ---------- referral condition groups ----------
   The eight groups are not the same weight: four carry three to five
   referral criteria, four are a single qualifying line. A uniform grid
   set a five-item card beside a one-item card and left two thirds of
   that row empty, which reads as unfinished rather than airy. So the
   section splits on that fault line instead of hiding it — the
   substantial groups as a 2x2 of full cards, the single-line ones as one
   divided band beneath. Two columns rather than three also lets the
   pre-consultation investigations reuse this exact component: its four
   groups carry three items each and fall into a 2x2 with nothing to pad.

   Rows stretch, so pairs level with each other. The malignancy groups
   sit together on the top row because that pairing is clinically
   obvious; the couple of spare lines that leaves under the shorter card
   read as breathing room at this padding, which they did not at three
   columns where the same slack was proportionally twice as wide. */
.cond-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:24px}
.cond-card{background:var(--white);border:1px solid var(--border-soft);border-radius:var(--radius-lg);
  box-shadow:var(--shadow-card);padding:34px 36px 36px;display:flex;flex-direction:column;gap:20px}
/* The rule under the heading is what separates a titled card from a
   labelled box: it says the list below is the card's content, not a
   continuation of its name. */
.cond-card h3{font:400 24px/1.3 var(--font-display);color:var(--teal-800);margin:0;
  padding-bottom:18px;border-bottom:1px solid var(--border-soft);text-wrap:pretty}
.cond-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:12px}
.cond-list li{position:relative;padding-left:20px;font:var(--text-body-sm);color:var(--text-soft)}
/* .42em rather than a fixed top: the dot then tracks the first line's
   optical centre if the body size is ever changed. */
.cond-list li::before{content:"";position:absolute;left:0;top:.42em;width:5px;height:5px;
  border-radius:var(--radius-pill);background:var(--blush-300)}

/* The label earns the split: without it the band below reads as four
   groups that got demoted, with it as a deliberate second tier. */
.cond-also-head{font:var(--text-subheading);letter-spacing:var(--subheading-tracking);
  text-transform:uppercase;color:var(--blush-500);text-align:center;margin:52px 0 20px}
/* One panel divided by hairlines rather than four undersized cards: at a
   quarter width a card is mostly border. Dividers go on the left edge of
   every item but the first, so they land between columns and never on
   the panel's own rounded edge. */
.cond-also{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  background:var(--white);border:1px solid var(--border-soft);border-radius:var(--radius-lg);
  box-shadow:var(--shadow-card);overflow:hidden}
.cond-also > div{padding:30px 28px;display:flex;flex-direction:column;gap:10px;
  border-left:1px solid var(--border-soft)}
.cond-also > div:first-child{border-left:none}
.cond-also h3{font:400 20px/1.3 var(--font-display);color:var(--teal-800);margin:0;text-wrap:pretty}
.cond-also p{font:var(--text-body-sm);color:var(--text-soft);margin:0}

/* ---------- pre-consultation investigations (for-referrers) ----------
   A ledger, not a card grid: one presentation per row, one investigation
   type per column, so a referrer scans across rather than reading four
   short lists. The dark header band is the only heavy element on the
   cream section, which is what makes the panel read as a reference table
   and not another content block. Column ratios give the presentation
   column room for its two-line title. */
.inv{background:var(--white);border:1px solid var(--border-soft);border-radius:var(--radius-lg);
  box-shadow:var(--shadow-raised);overflow:hidden}
.inv-head,.inv-row{display:grid;grid-template-columns:1.15fr 1fr 1fr .85fr;column-gap:36px}
.inv-head{background:var(--teal-800);padding:18px 40px}
.inv-head span{font:var(--text-subheading);letter-spacing:var(--subheading-tracking);
  text-transform:uppercase;color:var(--blush-300);font-size:12px}
.inv-row{padding:34px 40px;border-top:1px solid var(--border-soft);align-items:start;
  transition:background-color .25s ease-out}
.inv-row:first-of-type{border-top:none}
.inv-row:hover{background:var(--cream-50)}
/* The numeral is set in the display face and sits back in blush, the same
   treatment as .step-num but at caption size: a wayfinding mark, not a
   headline. */
.inv-cond{display:flex;flex-direction:column;gap:6px}
.inv-num{font:400 13px/1 var(--font-body);letter-spacing:.18em;color:var(--blush-500);margin-bottom:6px}
.inv-cond h3{font:400 24px/1.25 var(--font-display);color:var(--teal-800);margin:0;text-wrap:pretty}
.inv-cond p{font:var(--text-caption);color:var(--text-faint);margin:0;letter-spacing:.02em}
.inv-list{list-style:none;margin:0;padding:6px 0 0;display:flex;flex-direction:column;gap:10px}
/* Body colour rather than text-soft: these are the values a GP acts on,
   so they carry the row. The qualifier after them drops to faint. */
.inv-list li{position:relative;padding-left:18px;font:500 14px/1.55 var(--font-body);color:var(--teal-800)}
.inv-list li::before{content:"";position:absolute;left:0;top:.5em;width:6px;height:6px;
  border-radius:var(--radius-pill);background:var(--blush-400)}
.inv-note{display:block;font:var(--text-caption);color:var(--text-faint);font-weight:400;margin-top:1px}
.inv-list--none li{color:var(--text-faint);font-weight:400;font-style:italic}
.inv-list--none li::before{background:var(--border-strong)}
/* The footer note sits on the blush tint so the panel closes on a soft
   edge rather than a hairline, and the icon takes the rose so it reads
   as a note, not a warning. */
.inv-foot{display:flex;align-items:center;gap:16px;padding:22px 40px;
  background:var(--surface-tint);border-top:1px solid var(--border-soft)}
.inv-foot-icon{width:34px;height:34px;flex-shrink:0;border-radius:var(--radius-pill);
  background:var(--white);color:var(--blush-500);display:grid;place-items:center;
  box-shadow:var(--shadow-card)}
.inv-foot p{font:var(--text-body-sm);color:var(--text-soft);margin:0}
.inv-foot strong{font-weight:600;color:var(--teal-800)}

/* ---------- bio (about) ----------
   Two columns on the same rhythm as .steps: a sticky profile card on the
   left, a long read on the right. The card takes the dark teal so the
   credentials read as a plate, the one heavy block on a cream band.
   Type runs a step larger than the rest of the site here on purpose: the
   audience is largely 50+, and this is the page they read slowly.
   Section is .sec--paper, not .sec--cream: the cream clip would kill the
   sticky card. Column widths mirror .steps (420px rail). */
.bio{display:grid;grid-template-columns:420px minmax(0,1fr);gap:88px;align-items:start}
.bio-card{position:sticky;top:116px;background:var(--teal-800);color:var(--cream-50);
  border-radius:var(--radius-lg);padding:44px 42px 42px;box-shadow:var(--shadow-raised);
  display:flex;flex-direction:column;gap:30px;overflow:hidden}
/* The mark sits large and faint in the corner, the same way the brochure
   profile card carries it: texture, not a logo lockup. */
.bio-card-mark{position:absolute;right:-30px;top:-22px;width:170px;opacity:.10;pointer-events:none}
.bio-card-head{display:flex;flex-direction:column;gap:10px;position:relative}
/* Blush ring, offset like the contact portrait's disc, so the photo reads
   as placed rather than dropped in. */
.bio-card-portrait{display:block;width:112px;height:112px;border-radius:var(--radius-pill);
  overflow:hidden;box-shadow:0 0 0 3px var(--teal-800),0 0 0 5px var(--blush-300);margin-bottom:22px}
.bio-card-portrait img{width:100%;height:100%;object-fit:cover;display:block}
.bio-card-head .eyebrow{font-size:13px}
.bio-card-head h3{font:400 34px/1.15 var(--font-display);color:var(--cream-50);margin:0}
.bio-card-role{font:400 17px/1.45 var(--font-body);color:var(--cream-50);margin:4px 0 0}
.bio-card-quals{font:500 14px/1.5 var(--font-body);letter-spacing:.08em;color:var(--blush-300);margin:2px 0 0}
.bio-creds{margin:0;display:flex;flex-direction:column;border-top:1px solid rgba(251,247,245,.18)}
.bio-creds > div{padding:18px 0;border-bottom:1px solid rgba(251,247,245,.18);
  display:flex;flex-direction:column;gap:6px}
.bio-creds dt{font:var(--text-subheading);letter-spacing:var(--subheading-tracking);
  text-transform:uppercase;font-size:12px;color:var(--blush-300)}
.bio-creds dd{margin:0;font:400 16px/1.6 var(--font-body);color:rgba(251,247,245,.92)}
.bio-card .btn{align-self:stretch;justify-content:center;font-size:16px;height:56px}

.bio-copy{display:flex;flex-direction:column;gap:24px;align-items:flex-start;padding-top:4px}
.bio-copy h2{font:var(--text-h1);margin:0 0 4px;text-wrap:pretty;max-width:14ch}
.bio-copy p{font:400 18px/1.7 var(--font-body);color:var(--text-soft);margin:0;max-width:60ch}
.bio-copy .bio-lead{font:400 22px/1.55 var(--font-body);color:var(--teal-800)}
.bio-sub{font:400 28px/1.3 var(--font-display);color:var(--teal-800);margin:18px 0 -8px;text-wrap:pretty}
/* Three pillars as one hairline-divided strip rather than three cards,
   for the reason .cond-also gives: at a third of a column a card is
   mostly border. Numerals in blush, like .step-num, so they read as
   ornament first. */
.bio-pillars{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));width:100%;
  margin:22px 0 12px;border-top:1px solid var(--border-strong);border-bottom:1px solid var(--border-strong)}
.bio-pillar{padding:30px 28px 32px 0;margin-right:28px;display:flex;flex-direction:column;gap:12px}
.bio-pillar + .bio-pillar{padding-left:28px;border-left:1px solid var(--border-strong)}
.bio-pillar:last-child{margin-right:0;padding-right:0}
.bio-pillar-num{font:400 13px/1 var(--font-body);letter-spacing:.18em;color:var(--blush-500)}
.bio-pillar h3{font:400 23px/1.3 var(--font-display);color:var(--teal-800);margin:0;text-wrap:pretty}
.bio-copy .bio-pillar p{font:400 16px/1.65 var(--font-body)}
/* The closing line is hers, so it gets the pull-quote treatment: display
   face, the mark as a quote glyph, blush rule on the left. */
.bio-quote{margin:18px 0 0;padding:8px 0 8px 32px;border-left:2px solid var(--blush-300);
  position:relative;max-width:56ch}
.bio-quote img{width:32px;height:auto;display:block;margin-bottom:16px;opacity:.7}
.bio-copy .bio-quote p{font:400 27px/1.45 var(--font-display);color:var(--teal-800);max-width:none}

/* ---------- forms ----------
   Controls take --control-h and --radius-sm from the token file rather
   than numbers of their own: that height carries a comment in the tokens
   about hit targets for a 50+ audience, so it is a decision worth
   inheriting rather than re-making here. --focus-ring likewise. */
.frm{display:flex;flex-direction:column;gap:38px}
.frm-step{display:flex;flex-direction:column;gap:38px}
.frm-set{border:none;margin:0;padding:0;display:flex;flex-direction:column;gap:18px}
.frm-legend{font:var(--text-subheading);letter-spacing:var(--subheading-tracking);
  text-transform:uppercase;color:var(--blush-500);padding:0}
.frm-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:18px}
.frm-field{display:flex;flex-direction:column;gap:8px;min-width:0}
.frm-field--full{grid-column:1/-1}
.frm-field label{font:500 14px/1.4 var(--font-body);color:var(--teal-800)}
.req{color:var(--blush-500)}
.inp{height:var(--control-h);box-sizing:border-box;width:100%;border:1px solid var(--border-strong);
  border-radius:var(--radius-sm);background:var(--white);color:var(--teal-800);padding:0 16px;
  font:400 15px/1 var(--font-body);outline:none;
  transition:border-color .2s ease-out,box-shadow .2s ease-out}
.inp::placeholder{color:var(--text-faint)}
/* Border and ring both teal: --focus-ring is a teal alpha, so pairing it
   with a blush border made the focused field read muddy rather than
   deliberate. */
.inp:focus{border-color:var(--teal-800);box-shadow:0 0 0 3px var(--focus-ring)}
/* A file input cannot be styled like a text field, so it gets the same
   box but a line-height that lets the browser's button sit inside it. */
.inp--file{padding:0 10px;line-height:calc(var(--control-h) - 2px);cursor:pointer;
  font:400 14px/calc(var(--control-h) - 2px) var(--font-body)}
.inp--file::file-selector-button{font:500 13px/1 var(--font-body);color:var(--teal-800);
  background:var(--blush-50);border:0;border-radius:var(--radius-sm);padding:8px 12px;
  margin-right:12px;cursor:pointer}
.frm-hint{font:var(--text-body-sm);color:var(--text-soft);margin:-2px 0 0}
.frm.on-dark .frm-hint{color:rgba(251,247,245,.78)}
textarea.inp{height:auto;min-height:150px;padding:15px 16px;line-height:1.6;resize:vertical;
  font-family:var(--font-body)}
select.inp{appearance:none;-webkit-appearance:none;padding-right:46px;cursor:pointer;
  background-repeat:no-repeat;background-position:right 16px center;background-size:14px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23123F43' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E")}
/* ---------- form stepper ----------
   Numbered markers joined by a rail. The rail is drawn on each item except
   the first, inset by the marker radius at both ends, so it spans the gap
   between two circles and never passes behind one — which means the marker
   can stay transparent at rest instead of needing a solid knock-out. */
.stepper{list-style:none;display:grid;grid-auto-flow:column;grid-auto-columns:1fr;
  margin:0;padding:0}
.stepper-item{position:relative;display:flex;flex-direction:column;align-items:center;gap:10px;
  text-align:center;font:500 13px/1.4 var(--font-body);color:rgba(251,247,245,.6);
  transition:color .3s ease-out}
.stepper-item::before{content:"";position:absolute;top:17px;left:calc(-50% + 22px);
  right:calc(50% + 22px);height:1px;background:rgba(251,247,245,.25)}
.stepper-item:first-child::before{display:none}
.stepper-n{width:34px;height:34px;border-radius:var(--radius-pill);display:grid;place-items:center;
  border:1px solid rgba(251,247,245,.35);color:rgba(251,247,245,.7);
  font:400 15px/1 var(--font-display);
  transition:background .3s ease-out,border-color .3s ease-out,color .3s ease-out}
.stepper-item.is-done{color:rgba(251,247,245,.85)}
.stepper-item.is-done .stepper-n{background:rgba(225,192,181,.22);border-color:var(--blush-300);
  color:var(--cream-50)}
.stepper-item.is-current{color:var(--cream-50)}
.stepper-item.is-current .stepper-n{background:var(--blush-300);border-color:var(--blush-300);
  color:var(--teal-800)}

/* Back and Continue sit hard against the form's outer edges with the note
   centred between them. The side columns are a fixed width rather than auto
   so the note stays centred on step 1, where Back is hidden and an auto
   column would collapse to nothing and drag the note left. That width also
   equalises the three buttons, whose labels differ in length ("Back" vs
   "Submit referral"), so it is sized to the longest of them. */
.frm-actions{display:grid;grid-template-columns:190px 1fr 190px;
  align-items:center;gap:22px;padding-top:4px}
.frm-actions .btn{width:100%;padding:0 16px}
.frm-actions [data-step-back]{grid-area:1/1}
.frm-actions [data-step-next],.frm-actions [type="submit"]{grid-area:1/3}
.frm-actions .frm-note{grid-area:1/2;justify-self:center;text-align:center}
.frm-note{font:var(--text-body-sm);color:var(--text-soft);margin:0;max-width:52ch}

/* The same form on a dark section. Controls stay white — against teal-800
   they carry themselves and need no border — but the furniture inverts:
   labels come off the teal, and legends and asterisks step up from
   blush-500 to blush-300, which is the pair the rest of the site already
   uses for small text on dark (see .eyebrow--dark). The focus ring has to
   switch too: --focus-ring is a teal alpha, so on teal it would be
   drawing the ring in the background colour. Named .on-dark to match
   .arrow-btn.on-dark rather than inventing a second convention.
   Border stays 1px and only goes transparent, so focus does not resize
   the field. */
.frm.on-dark .frm-legend{color:var(--blush-300)}
.frm.on-dark .frm-field label{color:var(--cream-50)}
.frm.on-dark .req{color:var(--blush-300)}
.frm.on-dark .frm-note{color:rgba(251,247,245,.78)}
.frm.on-dark .inp{border-color:transparent}
.frm.on-dark .inp:focus{border-color:var(--blush-300);box-shadow:0 0 0 3px rgba(251,247,245,.28)}

/* ---------- trust bar ----------
   The band that sits immediately under an interior hero, picking the page
   back up from the dark hero before the content starts. teal-700 rather
   than teal-800 so it reads as a step out of the hero rather than more of
   it. Icons take blush-300, the same pair the footer and .eyebrow--dark
   use for accents on teal. */
.trustbar{background:var(--teal-700)}
.trustbar-inner{display:flex;align-items:center;justify-content:space-between;gap:28px;padding:24px 0}
/* 20px not 30px: with the referrer button added, the four badges plus the
   two actions ran 22px past the 1240px floor and put the whole page into
   horizontal scroll. Only blog.html uses this row. */
.trustbar-items{display:flex;align-items:center;gap:20px}
.trustbar-item{display:inline-flex;align-items:center;gap:11px;white-space:nowrap;
  font:500 15px/1.3 var(--font-body);color:var(--cream-50)}
.trustbar-item svg{flex-shrink:0;color:var(--blush-300)}

/* ---------- blog filters ----------
   Both controls are .inp with a pill radius: the newsletter field in the
   footer is already a pill, so search-shaped controls read as pills on
   this site and boxy ones as form fields. The leading icon is absolutely
   placed and non-interactive, so the padding on the field is what keeps
   text clear of it. */
/* The row sits between the trust bar and the grid with equal air on
   both sides, so it reads as one band rather than as a section head.
   A section's full 120px lead-in put nearly all the space above it and
   left it floating off the grid it belongs to — hence the paired
   .sec--tight-top below, which has to match this value. */
.blog-filters{display:flex;justify-content:center;gap:16px;margin-bottom:52px;flex-wrap:wrap}
.filter{position:relative;display:flex;align-items:center}
.filter > svg{position:absolute;left:20px;color:var(--text-faint);pointer-events:none;z-index:1}
.filter .inp{border-radius:var(--radius-pill);padding-left:50px}
.filter--search{width:420px}
.filter--topic{width:230px}

/* ---------- post grid ----------
   The same card language as .news-card in the carousel, rearranged for an
   index: the category moves off the meta row and onto the image as an
   overlay, and a read-more affordance is pinned to the bottom so it lines
   up across a row whatever length the excerpts run to. */
.post-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:24px}
.post-card{background:var(--white);border:1px solid var(--border-soft);border-radius:var(--radius-lg);
  box-shadow:var(--shadow-card);overflow:hidden;display:flex;flex-direction:column;text-decoration:none;
  color:var(--teal-800);transition:border-color .3s cubic-bezier(.22,.61,.36,1),box-shadow .3s cubic-bezier(.22,.61,.36,1)}
.post-card:hover{border-color:var(--blush-300);box-shadow:var(--shadow-raised);color:var(--teal-800)}
.post-media{height:210px}
/* Above .photo > img, which sits at z-index 1. */
.post-cat{position:absolute;left:16px;top:16px;z-index:2;background:rgba(251,247,245,.94);color:var(--teal-800);
  border-radius:var(--radius-pill);padding:7px 13px;font:500 11px/1 var(--font-body);
  letter-spacing:.1em;text-transform:uppercase;
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.post-body{padding:24px 26px 26px;display:flex;flex-direction:column;gap:12px;flex:1}
.post-date{font:var(--text-caption);color:var(--text-faint)}
.post-title{font:400 23px/1.32 var(--font-display);text-wrap:pretty}
.post-excerpt{font:var(--text-body-sm);color:var(--text-soft)}
/* margin-top:auto pins this to the card foot so the row's read-mores align. */
.post-more{margin-top:auto;padding-top:10px;display:inline-flex;align-items:center;gap:8px;
  font:500 14px/1 var(--font-body);color:var(--teal-700);
  transition:color .3s cubic-bezier(.22,.61,.36,1)}
.post-card:hover .post-more{color:var(--blush-500)}
.post-more svg{transition:transform .3s cubic-bezier(.22,.61,.36,1)}
.post-card:hover .post-more svg{transform:translateX(3px)}
.load-more{display:flex;justify-content:center;margin-top:48px}

/* ---------- article hero ----------
   Category, title, date and nothing else — no lead paragraph and no
   buttons, so the stack is tighter than a page hero's and the measure is
   the title's rather than the copy column's. */
.hero--article .hero-copy{gap:18px;max-width:760px}
.hero-meta{font:var(--text-body-sm);color:rgba(255,255,255,.8)}

/* ---------- article layout ----------
   A fixed rail beside a fixed measure, the pair centred, rather than one
   centred column with two dead gutters. The rail was the empty 288px the
   old layout left on each side; giving it the contents list turns the
   page's widest wasted space into its main navigation aid.
   240 + 80 + 760 = 1080, inside the 1184 the wrap gives at the 1240 floor. */
/* No align-items:start here on purpose. The rail column has to stretch to
   the row height, because a sticky child can only travel inside its own
   containing block — pin it inside a column that is only as tall as the
   list and it scrolls away with the first screen. */
.article-layout{display:grid;grid-template-columns:240px 760px;gap:80px;
  max-width:1080px;margin:0 auto}

/* ---------- contents rail ----------
   Sticky, so it stays put through a long read. .sec--paper is what makes
   that possible; on .sec--cream the texture layer's overflow:hidden would
   clip it. The active link is set from scroll position in app.js. */
/* 84px header + 32px. The label travels with the list, so both sit inside
   the sticky block rather than only the nav. */
.toc-inner{position:sticky;top:116px}
.toc-h{font:var(--text-caption);letter-spacing:.14em;text-transform:uppercase;
  color:var(--blush-500);margin-bottom:14px}
.toc a{display:block;font:400 14px/1.45 var(--font-body);color:var(--text-soft);
  text-decoration:none;padding:9px 0 9px 16px;border-left:1px solid var(--border-soft);
  transition:color .25s ease-out,border-left-color .25s ease-out}
.toc a:hover{color:var(--teal-800);border-left-color:var(--blush-300)}
.toc a.on{color:var(--teal-800);border-left-color:var(--blush-500)}

/* ---------- byline ---------- */
.byline{display:flex;align-items:center;gap:14px;padding-bottom:24px;margin-bottom:36px;
  border-bottom:1px solid var(--border-soft)}
.byline-avatar{width:48px;height:48px;border-radius:var(--radius-pill);overflow:hidden;flex-shrink:0}
/* aboutimage is 1920x1000, so a square crop of it has no vertical slack
   at all — object-position can only slide it sideways, and the whole
   1000px height stays in frame with her face a fraction of it. Scaling
   about her face is the only way to get a portrait out of a landscape
   plate. The container already clips. Replace both of these the moment
   there is a real headshot. */
.byline-avatar img{width:100%;height:100%;object-fit:cover;display:block;
  transform:scale(2.6);transform-origin:57% 28%}
.byline-name{font:500 15px/1.4 var(--font-body);color:var(--teal-800)}
.byline-meta{font:var(--text-body-sm);color:var(--text-faint)}

/* ---------- article body ----------
   Long-form measure, held near 84 characters. The page this layout came
   from runs about 140 to the line; this site is built for a 50+ audience
   and the token file already reasons that way about control heights and
   contrast, so the measure follows.

   Margins sit on the elements rather than a > * + * rule so a heading can
   carry more space above it than below, which is what separates a section
   from the paragraph it introduces. */
.article{max-width:760px}
.article > :first-child{margin-top:0}
.article p{font:var(--text-body-lg);color:var(--text-soft);margin:0 0 22px}
/* Clears the 84px sticky header when the contents rail jumps to a heading. */
.article h2{font:var(--text-h2);color:var(--teal-800);margin:60px 0 20px;
  text-wrap:pretty;scroll-margin-top:110px}
.article h3{font:var(--text-h3);color:var(--teal-800);margin:40px 0 14px;text-wrap:pretty}
.article ul{list-style:none;margin:0 0 22px;padding:0;display:flex;flex-direction:column;gap:12px}
.article ul li{position:relative;padding-left:22px;font:var(--text-body-lg);color:var(--text-soft)}
.article ul li::before{content:"";position:absolute;left:0;top:.62em;width:6px;height:6px;
  border-radius:var(--radius-pill);background:var(--blush-300)}
/* Lead-in terms. Teal against the softer body colour so the eye can scan
   the bolded openings down the column. */
.article strong{font-weight:600;color:var(--teal-800)}

/* ---------- key takeaways ----------
   A white card on the cream ground so the summary reads as a thing you can
   stop at, not just the article's first heading. Sits above the contents
   rail's first target deliberately: someone who only reads one block
   should get this one. */
.takeaways{background:var(--white);border:1px solid var(--border-soft);
  border-radius:var(--radius-lg);box-shadow:var(--shadow-card);padding:32px 36px 34px;margin:0 0 40px}
.takeaways h2{font:400 24px/1.3 var(--font-display);margin:0 0 18px;
  display:flex;align-items:center;gap:12px;scroll-margin-top:110px}
.takeaways h2 img{height:24px;width:auto}
.takeaways ul{margin:0}
.takeaways ul li{font:var(--text-body-md)}

/* ---------- pull quote ----------
   Cormorant Italic is a real face in the design system, so this is a drawn
   italic rather than a slanted roman. */
.pullquote{margin:46px 0;padding:4px 0 4px 30px;border-left:2px solid var(--blush-300)}
.pullquote p{font:400 27px/1.45 var(--font-display);font-style:italic;
  color:var(--teal-800);margin:0;text-wrap:pretty}

/* ---------- author card ---------- */
.authorcard{display:grid;grid-template-columns:112px minmax(0,1fr);gap:28px;align-items:start;
  margin-top:60px;padding-top:36px;border-top:1px solid var(--border-soft)}
.authorcard-photo{width:112px;height:112px;border-radius:var(--radius-md);overflow:hidden}
.authorcard-photo img{width:100%;height:100%;object-fit:cover;display:block;
  transform:scale(1.9);transform-origin:59% 21%}
.authorcard-body{display:flex;flex-direction:column;gap:10px;align-items:flex-start}
.authorcard .lbl{font:var(--text-caption);letter-spacing:.14em;text-transform:uppercase;color:var(--blush-500)}
.authorcard h3{font:400 24px/1.3 var(--font-display);color:var(--teal-800);margin:0}
.authorcard .creds{font:var(--text-body-sm);color:var(--text-faint);margin:0}
.authorcard p{font:var(--text-body-sm);color:var(--text-soft);margin:0}
.authorcard a{font:500 14px/1 var(--font-body);color:var(--teal-700);text-decoration:none;
  display:inline-flex;align-items:center;gap:8px;margin-top:4px}
.authorcard a:hover{color:var(--blush-500)}

/* ---------- article CTA ----------
   The closing block on an article: heading, lead, the three steps of
   getting seen, then the practice details. Richer than the site's standard
   .cta-copy because it is doing the whole job of a footer call to action
   on a page that has no other conversion point. */
.artcta{text-align:center;max-width:920px;margin:0 auto}
.artcta h2{font:var(--text-h1);color:var(--cream-50);text-wrap:pretty}
.artcta-lead{font:var(--text-body-lg);color:rgba(251,247,245,.85);margin:20px auto 30px;max-width:56ch}
/* Hairline over each step rather than a box around it: three bordered
   cards on teal would read as heavier than the article they follow. */
.artcta-steps{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:28px;
  margin-top:56px;text-align:left}
.artcta-step{display:flex;flex-direction:column;gap:9px;padding-top:22px;
  border-top:1px solid rgba(251,247,245,.28)}
.artcta-step .step-n{font:400 20px/1 var(--font-display);color:var(--blush-300)}
.artcta-step h3{font:400 22px/1.3 var(--font-display);color:var(--cream-50);margin:0;text-wrap:pretty}
.artcta-step p{font:var(--text-body-sm);color:rgba(251,247,245,.78);margin:0}
.artcta-details{display:flex;justify-content:center;gap:56px;flex-wrap:wrap;
  margin-top:52px;padding-top:34px;border-top:1px solid rgba(251,247,245,.18);text-align:left}
.artcta-detail{display:flex;flex-direction:column;gap:5px;
  font:var(--text-body-sm);color:rgba(251,247,245,.78)}
.artcta-detail .lbl{font:var(--text-caption);letter-spacing:.14em;text-transform:uppercase;color:var(--blush-300)}
.artcta-detail a{color:rgba(251,247,245,.78);text-decoration:none}
.artcta-detail a:hover{color:var(--blush-300)}

/* ---------- service hero ----------
   Two columns over the hero image: breadcrumb and title on the left, the
   sibling specialties on the right. The list is the point — it is how you
   move between the ten specialty pages without going back to the nav.
   .hero-wrap sets pointer-events:none so the scrim never eats clicks, so
   anything interactive in here has to switch them back on. */
/* No min-height of its own: the specialty hero takes .hero--page's 36vw so
   it matches the Referral Guide and the other interior pages exactly. A
   separate value here would only drift away from them. See the note on
   .hero--page for what that height buys and what the visible slice of a
   2560px plate works out to. */
/* The default hero scrim fades to .15 on the right, which is fine when
   nothing is over there. This variant puts a list of white links on that
   side, and they landed on a white coat. Darken both ends and keep the
   middle open so the photograph still reads. Deepened from .72/.46/.64
   when the lede was added: an h1 is large text and clears AA at 3:1, but
   18px body copy on the same plate needs 4.5:1, and the old scrim measured
   3.24:1 at worst across the ten plates. These values measure 5.48:1. */
.hero--service .hero-scrim{background:linear-gradient(90deg,rgba(0,0,0,.76) 0%,
  rgba(0,0,0,.56) 52%,rgba(0,0,0,.68) 100%)}
.hero--service .hero-copy{padding:76px 0 80px;max-width:none;width:100%}
/* width:100% is load-bearing: .hero-copy is a flex column with
   align-items:flex-start, so without it this grid shrinks to its
   content and the sibling list lands mid-hero instead of on the right
   margin. */
.hero-service-grid{display:grid;grid-template-columns:minmax(0,1fr) 400px;gap:72px;
  align-items:center;width:100%}
.crumbs{font:var(--text-body-sm);color:rgba(255,255,255,.72);margin-bottom:16px;pointer-events:auto}
/* Short lede under the specialty h1. Inherits type and colour from
   .hero-copy p; this rule only sets the spacing and measure, and needs the
   two-class form to outrank .hero-copy p's margin:0 and 480px cap. Kept
   narrower than the grid column so it reads as a lede, not body copy. */
.hero-copy .hero-lede{margin:16px 0 0;max-width:560px;text-wrap:pretty;color:#fff}
.crumbs a{color:rgba(255,255,255,.72);text-decoration:none}
.crumbs a:hover{color:var(--blush-300)}
.hero-sibs{pointer-events:auto}
/* Five rows, then scroll. Each .hero-sib is 12px padding either side of a
   14px/1.35 line plus its 1px rule, so 44px a row and 220px for five —
   keep these in step if the row padding or type size changes. Styling the
   webkit scrollbar at all is what stops macOS hiding it as an overlay,
   which matters here: the track is the only cue that there are more. */
.hero-sibs-list{max-height:220px;overflow-y:auto;padding-right:16px}
/* Deliberately NOT setting scrollbar-width/scrollbar-color here. Chrome
   supports those standard properties, and declaring either one makes it
   ignore the ::-webkit-scrollbar rules below completely — including any
   border-radius, which the standard properties have no way to express.
   That is why the track stayed square-ended while the thumb looked
   rounded: the rounding was Chrome's own default thin-scrollbar drawing,
   not this stylesheet. Styling the pseudo-elements is also what keeps
   macOS from hiding the bar as an overlay, so the cue stays visible. */
.hero-sibs-list::-webkit-scrollbar{width:6px;background:transparent}
.hero-sibs-list::-webkit-scrollbar-track{background:rgba(251,247,245,.1);
  border-radius:var(--radius-pill)}
.hero-sibs-list::-webkit-scrollbar-thumb{background:var(--blush-300);
  border-radius:var(--radius-pill)}
.hero-sibs-list::-webkit-scrollbar-thumb:hover{background:var(--blush-400)}
/* Firefox has no scrollbar pseudo-elements, so it gets the standard
   properties — but only where the pseudo-elements are unavailable, so
   this never reaches Chrome and never disables the rules above. */
@supports not selector(::-webkit-scrollbar){
  .hero-sibs-list{scrollbar-width:thin;scrollbar-color:var(--blush-300) rgba(251,247,245,.1)}
}
.hero-sibs-h{font:var(--text-caption);letter-spacing:.14em;text-transform:uppercase;
  color:var(--blush-300);margin-bottom:6px}
.hero-sib{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 0;
  border-bottom:1px solid rgba(251,247,245,.24);font:500 14px/1.35 var(--font-body);
  color:var(--cream-50);text-decoration:none;
  transition:color .25s ease-out,border-bottom-color .25s ease-out}
.hero-sib:hover{color:var(--blush-300);border-bottom-color:var(--blush-300)}
.hero-sib svg{flex-shrink:0;opacity:.6}
.hero-sib:hover svg{opacity:1}

/* ---------- band CTA ----------
   The strip that sits under a hero. Shares .trustbar's ground and padding;
   only the left-hand content differs, so it is a content variant rather
   than a second bar. */
.trustbar-copy{display:flex;flex-direction:column;gap:5px}
.trustbar-copy h2{font:400 26px/1.3 var(--font-display);color:var(--cream-50);margin:0}
.trustbar-copy p{font:var(--text-body-sm);color:rgba(251,247,245,.8);margin:0}
/* The strip's two calls to action. Grouped in one flex box so the strip's
   space-between keeps them together on the right rather than pushing them
   to opposite ends. Booking stays the filled primary; the referrer link is
   the outlined secondary, reusing .btn--outline-light because the strip's
   teal ground is the same dark surface that variant already serves. */
.trustbar-actions{display:flex;align-items:center;gap:12px;flex-shrink:0}

/* ---------- contact intro ----------
   Copy left, portrait right, lifting above the band's top edge the way the
   reference layout does. The lift is a negative margin, so the band must
   not clip — .sec--paper rather than .sec--cream for that reason. Tighter
   than a standard .sec: this page earns its opening from the form below,
   not from a tall hero. */
.contact-intro{display:grid;grid-template-columns:minmax(0,1fr) 176px;gap:56px;align-items:center}
.contact-intro h1{font:var(--text-h1);text-wrap:pretty;margin-bottom:18px}
.contact-intro p{font:var(--text-body-lg);color:var(--text-soft);margin:0;max-width:54ch}
/* No negative lift any more. It pulled the circle up out of the grid row,
   which meant the band's padding read as 24px above and 72px below even
   though the declared values were 56 and 72. With the portrait sitting in
   the row, equal padding actually looks equal. */
.contact-portrait{position:relative;width:176px;height:176px;justify-self:end}
/* The teal disc sits behind and offset, which is what gives the portrait a
   composed edge rather than a floating circle. */
.contact-portrait .disc{position:absolute;inset:0;border-radius:var(--radius-pill);
  background:var(--teal-800);transform:translate(13px,-13px)}
/* display:block is load-bearing — .frame is a span, and an inline element
   ignores width, height and overflow, so the scaled image escapes it. The
   clip lives here and NOT as a radius on the image: transform scales a
   border-radius along with everything else, so a radius on the image draws
   the circle at scale x its stated size and spills into the row below. */
.contact-portrait .frame{display:block;position:relative;width:100%;height:100%;
  border-radius:var(--radius-pill);overflow:hidden}
/* portrait-headshot.jpg is a square crop supplied by the client, so no
   rescue transform is needed here any more. */
.contact-portrait img{width:100%;height:100%;object-fit:cover;display:block}

/* ---------- contact grid ----------
   The details sit beside the form rather than in a sparse row above it, so
   the page has one place to look and the width is actually used. */
.contact-grid{display:grid;grid-template-columns:340px minmax(0,1fr);gap:72px;align-items:start}
.contact-block{padding-bottom:26px;margin-bottom:26px;border-bottom:1px solid var(--border-soft)}
.contact-block:last-child{padding-bottom:0;margin-bottom:0;border-bottom:none}
.contact-block .lbl{font:var(--text-caption);letter-spacing:.14em;text-transform:uppercase;
  color:var(--blush-500);display:block;margin-bottom:12px}
.contact-block p{font:var(--text-body-sm);color:var(--text-soft);margin:10px 0 0}
.contact-block a.inline{color:var(--teal-700);text-decoration:none;font-weight:500}
.contact-block a.inline:hover{color:var(--blush-500)}
.contact-big{display:inline-block;font:400 30px/1.2 var(--font-display);color:var(--teal-800);
  text-decoration:none}
.contact-big:hover{color:var(--blush-500)}
.contact-socials{display:flex;gap:16px;align-items:center}
.contact-socials a{width:24px;height:24px;color:var(--teal-800);display:grid;place-items:center;
  transition:color .2s ease-out}
.contact-socials a:hover{color:var(--blush-500)}

/* ---------- enquiry form card ----------
   The form itself is the same .frm/.inp set the referral form uses; only the
   card around it is new. */
.formcard{background:var(--white);border:1px solid var(--border-soft);
  border-radius:var(--radius-lg);box-shadow:var(--shadow-card);overflow:hidden}
.formcard-head{background:var(--teal-800);color:var(--cream-50);text-align:center;padding:22px 28px;
  font:400 24px/1.3 var(--font-display)}
.formcard-body{padding:38px 42px 42px}
.btn--block{width:100%}

/* ---------- office card ---------- */
/* ---------- clinic locations (contact) ----------
   Four across in one row. At the 1240px floor that is a 281px card, so the
   map, heading and padding all sit below the site's usual ramp.
   The action is a text link with a rule above it, not a full-width pill:
   at this card width a stretched button read as a form control and gave
   four heavy blush bars across the row. .loc-body is a flex column with
   the footer on margin-top:auto, so the four rules and links stay on one
   line even though the address runs one to two lines. */
.loc-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:20px}
.loc-card{background:var(--white);border:1px solid var(--border-soft);
  border-radius:var(--radius-lg);box-shadow:var(--shadow-card);overflow:hidden;
  display:flex;flex-direction:column;
  transition:transform .35s cubic-bezier(.22,.61,.36,1),box-shadow .35s ease-out,
             border-color .35s ease-out}
.loc-card:hover{transform:translateY(-4px);box-shadow:var(--shadow-raised);
  border-color:var(--border-strong)}
.loc-map{height:150px;background:var(--teal-50);flex-shrink:0;position:relative}
.loc-map iframe{width:100%;height:100%;border:0;display:block}
/* hairline between the live map and the card body, so the embed reads as a
   seated panel rather than a raw iframe butted against the text */
.loc-map::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1px;
  background:var(--border-soft);pointer-events:none}
.loc-body{flex:1;display:flex;flex-direction:column;padding:16px 22px 20px}
.loc-body h3{display:flex;align-items:center;gap:10px;margin:0 0 16px;
  font:400 19px/1.32 var(--font-display);color:var(--teal-800);text-wrap:pretty}
/* The brand mark is a thin-stroke drawing -- only ~9.5% of its box is ink --
   so on its own at this size the strokes fall under a pixel and grey out.
   The teal disc carries it: white mark on the dark ground reads cleanly
   and matches how the same mark is used on every other dark surface. */
.loc-mark{width:34px;height:34px;flex-shrink:0;
  border-radius:var(--radius-pill);background:var(--teal-800);
  display:grid;place-items:center}
.loc-mark img{width:22px;height:auto;display:block}
.loc-addr{font:400 13.5px/1.6 var(--font-body);color:var(--text-soft);margin:0 0 14px}
/* Sits under the address as a quiet practical line, pulled up so it
   reads as part of the address block rather than a separate paragraph. */
.loc-note{font:500 13px/1.5 var(--font-body);color:var(--teal-800);margin:-8px 0 14px}
.loc-foot{margin-top:auto;padding-top:14px;border-top:1px solid var(--border-soft);
  display:flex;flex-direction:column;gap:9px}
.loc-tel,.loc-link{display:inline-flex;align-items:center;gap:7px;text-decoration:none;
  white-space:nowrap;transition:color .2s ease-out}
.loc-tel{font:500 14px/1.4 var(--font-body);color:var(--teal-800)}
.loc-tel:hover{color:var(--blush-500)}
.loc-link{font:500 13px/1.4 var(--font-body);color:var(--blush-500);
  letter-spacing:.01em;align-self:flex-start}
.loc-link svg{transition:transform .25s ease-out}
.loc-link:hover{color:var(--teal-800)}
.loc-link:hover svg{transform:translateX(3px)}

/* ---------- carousel arrows (news) ---------- */
.arrow-btn{width:52px;height:52px;border-radius:999px;border:1px solid var(--teal-800);background:transparent;color:var(--teal-800);display:grid;place-items:center;cursor:pointer;transition:background .2s ease-out,color .2s ease-out}
.arrow-btn:hover{background:var(--teal-800);color:var(--cream-50)}
.arrow-btn.on-dark{border-color:var(--cream-50);color:var(--cream-50)}
.arrow-btn.on-dark:hover{background:var(--cream-50);color:var(--teal-800)}
/* ---------- FAQs ---------- */
.faq-row{border-bottom:1px solid var(--border-soft)}
.faq-q{width:100%;background:none;border:none;cursor:pointer;display:flex;justify-content:space-between;align-items:center;gap:16px;padding:24px 0;text-align:left;font:400 22px/1.3 var(--font-display);color:var(--teal-800)}
.faq-q:hover{color:var(--blush-500)}
.faq-q img{flex-shrink:0;width:26px;height:auto;transition:transform .45s cubic-bezier(.22,.61,.36,1)}
.faq-q[aria-expanded="true"] img{transform:rotate(180deg)}
.faq-a{font:var(--text-body-md);color:var(--text-soft);opacity:.75;margin:0 0 26px;max-width:680px}
.faq-a[hidden]{display:none}

/* ---------- news ---------- */
.news-head{display:flex;justify-content:space-between;align-items:flex-end;gap:32px;margin-bottom:48px}
.news-head-copy{display:flex;flex-direction:column;gap:14px}
.news-head-copy h2{font:var(--text-h1)}
.news-controls{display:flex;gap:14px;align-items:center}
.news-viewport{overflow:hidden;margin:0 -12px}
.news-track{display:flex;transition:transform 700ms cubic-bezier(.22,.61,.36,1)}
.news-cell{flex:0 0 33.3333%;min-width:0;padding:0 12px;box-sizing:border-box;display:flex}
.news-card{background:var(--white);border:1px solid var(--border-soft);border-radius:20px;box-shadow:var(--shadow-card);overflow:hidden;display:flex;flex-direction:column;text-decoration:none;color:var(--teal-800);transition:border-color .2s ease-out;flex:1}
.news-card:hover{border-color:var(--blush-300);color:var(--teal-800)}
.news-media{height:220px}
.news-body{padding:24px 26px 28px;display:flex;flex-direction:column;gap:12px}
.news-meta{display:flex;gap:10px;align-items:center;font:var(--text-caption);color:var(--text-faint)}
.news-cat{background:var(--blush-50);color:var(--blush-500);border-radius:999px;padding:5px 12px;font:500 12px/1 var(--font-body)}
.news-title{font:400 23px/1.3 var(--font-display);text-wrap:pretty}
.news-excerpt{font:var(--text-body-sm);color:var(--text-soft)}

/* ---------- CTA ---------- */
.cta-bg{position:absolute;inset:0}
.cta-copy{display:flex;flex-direction:column;gap:24px;align-items:center;text-align:center;max-width:680px;margin:0 auto}
.cta-copy img{height:44px;width:auto;opacity:.9}
.cta-copy h2{font:var(--text-display);color:var(--cream-50);text-wrap:pretty}
.cta-copy p{font:var(--text-body-lg);color:rgba(251,247,245,.85);margin:0}
.cta-actions{display:flex;gap:16px;pointer-events:auto;flex-wrap:wrap;justify-content:center}

/* ---------- footer ---------- */
.ftr{background:linear-gradient(180deg,var(--teal-800),var(--teal-900) 55%,#071D1F);color:var(--cream-50)}
.ftr-top{display:flex;justify-content:space-between;align-items:center;gap:32px;padding:56px 0 44px;border-bottom:1px solid rgba(251,247,245,.18);flex-wrap:wrap}
.ftr-brand{display:flex;align-items:center;gap:44px}
.ftr-brand > img{height:44px;width:auto}
/* Consulting locations stack under the logo, one line each, sharing the
   original address styling. Ipswich and Cleveland stay suburb-only until
   their street addresses are confirmed: a wrong local-SEO citation is
   worse than a missing one. */
.ftr-addrs{display:flex;flex-direction:column;gap:9px}
.ftr-addr{display:flex;align-items:center;gap:8px;font:400 16px/1.5 var(--font-body);color:rgba(251,247,245,.78)}
.ftr-addr img{width:16px;height:16px;flex-shrink:0}
.ftr-top-right{display:flex;align-items:center;gap:32px}
.ftr-tel{display:inline-flex;align-items:center;gap:10px;color:var(--cream-50);text-decoration:none;font:500 16px/1 var(--font-body)}
.ftr-cols{display:grid;grid-template-columns:auto auto auto 340px;justify-content:space-between;column-gap:48px;padding:52px 0 48px}
.ftr-h{font:var(--text-subheading);letter-spacing:var(--subheading-tracking);text-transform:uppercase;color:var(--blush-300);margin-bottom:14px}
.footer-link{display:block;font:400 14px/1.5 var(--font-body);color:rgba(251,247,245,.78);text-decoration:none;padding:4px 0;transition:color .2s ease-out}
.footer-link:hover{color:var(--blush-300)}
.ftr-nl{display:flex;flex-direction:column;gap:16px;align-items:flex-start}
/* Credentials sit at the foot of the newsletter column so their last line
   lands level with the end of the Specialties list beside them. The auto
   margin does the work: the grid row is as tall as Specialties, so pushing
   this block down aligns the two columns without hard-coding a height. */
.ftr-creds{margin-top:auto;width:100%}
.ftr-creds .ftr-h{margin-bottom:10px}
.ftr-creds p{font:400 14px/1.5 var(--font-body);color:rgba(251,247,245,.78);margin:0;padding:2px 0}
.ftr-nl .ftr-h{margin-bottom:0}
.ftr-nl p{font:var(--text-body-sm);color:rgba(251,247,245,.78);margin:0}
.ftr-nl form{display:flex;gap:10px;width:100%;align-items:center}
input.nl{height:52px;border-radius:999px;border:1px solid rgba(251,247,245,.35);background:var(--white);color:var(--teal-800);padding:0 22px;font:400 15px/1 var(--font-body);flex:1;min-width:0;outline:none}
input.nl::placeholder{color:var(--text-faint)}
input.nl:focus{border-color:var(--blush-300)}
input.nl--sm{height:44px;box-sizing:border-box}
.socials{display:flex;gap:14px}
.soc{width:24px;height:24px;color:var(--cream-50);display:grid;place-items:center;transition:color .2s ease-out}
.soc:hover{color:var(--blush-300)}
.ftr-legal{border-top:1px solid rgba(251,247,245,.18);display:flex;justify-content:space-between;align-items:center;gap:40px;padding:26px 0 36px}
/* Definite flex basis, so the paragraph's width — and therefore its
   height — does not depend on how wide the badge beside it is. Without
   this the two feed back into each other: badge height sets badge width,
   which squeezes the paragraph, which changes the height the badge is
   measured against. */
.ftr-legal p{font:var(--text-body-sm);color:var(--cream-50);opacity:.38;margin:0;flex:0 1 820px;max-width:820px}
/* The badge matches the height of the legal paragraph beside it. The
   height is set from that paragraph at runtime (balanceFooterBadge in
   app.js) rather than hard-coded: stretching it in CSS fails because the
   badge's own 213px intrinsic height drives the row instead of following
   it. Measured, so it holds when the placeholder copy is replaced. */
.ftr-badge{display:flex;align-items:center;flex-shrink:0}
.ftr-badge img{height:100%;width:auto;object-fit:contain;display:block}
/* Instagram sits beside the Google badge as the same social component used
   under the newsletter, just drawn larger so it carries at this size. .soc
   supplies the colour and hover, so only the dimensions are overridden.
   align-items:center rather than stretch: .ftr-badge still takes its height
   from balanceFooterBadge() and sets the row, and the icon centres against
   it instead of trying to match it. The pair costs 34 + 20 + 213, which is
   why .ftr-legal p is back on its original 820px measure. */
.ftr-badges{display:flex;align-items:center;gap:20px;flex-shrink:0}
.soc--lg{width:34px;height:34px}
.soc--lg svg{width:34px;height:34px}
.ftr-base{border-top:1px solid rgba(251,247,245,.18);padding:26px 0 34px;display:flex;justify-content:space-between;align-items:center;gap:24px;flex-wrap:wrap}
/* 14px so the copyright matches Privacy / Terms of Use beside it — those
   take .footer-link's size, not the row's. */
.ftr-base-left{display:flex;gap:26px;align-items:center;font:400 14px/1.5 var(--font-body);color:rgba(251,247,245,.7)}
.ftr-base-left .footer-link{display:inline}
/* 14px to match Privacy / Terms of Use, which pick up .footer-link's size
   rather than the 12px --text-caption on the row around them. */
.ftr-credit{display:inline-flex;align-items:center;gap:8px;font:400 14px/1.5 var(--font-body);color:rgba(251,247,245,.7);text-decoration:none}
.ftr-credit img{height:14px;width:auto}

/* ---------- scroll reveal ---------- */
.rv{opacity:0;transform:translateY(20px);transition:opacity 1050ms cubic-bezier(.22,.61,.36,1),transform 1050ms cubic-bezier(.22,.61,.36,1);will-change:opacity,transform}
.rv-img{transform:scale(1.02)}
.rv-in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){.rv{opacity:1;transform:none;transition:none}}

/* ---------- coming soon (index.html) ----------
   The public gate. This is the one page not inside .page, so it is also
   the one page with real breakpoints -- everything else in this build is
   a fixed 1240px desktop comp. Type scales with clamp() rather than
   media queries so it holds at any width between the two ends.
   Colours, radii, controls and the form treatment are all existing tokens
   and classes; the only new thing here is the layout. */
.cs{position:relative;box-sizing:border-box;min-height:100vh;min-height:100svh;
  display:flex;align-items:center;justify-content:center;
  padding:clamp(36px,4.2vw,54px) 24px;background:var(--teal-900,#0E3134)}

/* One photograph behind the whole page. Both layers are fixed, so the
   content scrolls over a still image instead of the page cutting from a
   photo band into a flat panel -- that cut is what stopped it reading as
   one piece. A fixed element beats background-attachment:fixed, which
   iOS ignores. */
.cs-bg{position:fixed;inset:0;z-index:0;overflow:hidden}
/* Zoomed in and nudged down so the doctor's face clears the type and sits
   in the open upper right, rather than the heading running across it.
   object-position cannot do this: the plate is 3:2 against a ~1.67
   viewport, so cover leaves ~100px of vertical slack and none at all
   horizontally. Scaling about the centre is what pushes the pair apart
   and out from under centred copy. Past ~1.5 the doctor starts clipping
   on the right and the 1536px source visibly softens, so this is the
   furthest it is worth taking.
   The -11% shifts the pair so the gap between the two faces lands on the
   centreline, putting the logo and heading between them. Because the
   translate is a share of viewport width and the scale is about the
   centre, that framing holds at any viewport wider than the plate's 3:2;
   below that cover flips to height-driven and the crop tightens. */
.cs-bg img{width:100%;height:100%;object-fit:cover;object-position:50% 32%;display:block;
  transform:translate(-11%,4%) scale(1.45);transform-origin:50% 50%}
/* The USP plate (her face turned to the patient, BugHerd #22) already has
   the two of them either side of centre, so it needs none of the push
   above. Pinned to the bottom of the plate: cover leaves ~100px of
   vertical slack at desktop, and spending all of it upward is what lifts
   both faces into the band between the logo and the panel instead of
   burying them behind the form. */
.cs-bg img.cs-bg--usp{transform:none;object-position:50% 100%}
/* Same black-alpha family as .hero-scrim, running vertically because this
   copy is centred rather than left-aligned. Measured over the plate. */
.cs-scrim{position:fixed;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(180deg,rgba(0,0,0,.74) 0%,rgba(0,0,0,.64) 42%,rgba(0,0,0,.80) 100%)}

.cs-inner{position:relative;z-index:2;width:100%;max-width:1040px;
  display:flex;flex-direction:column;align-items:center;text-align:center}

/* Entrance. reveal() is scroll-driven and scoped to .page, neither of which
   applies here -- so this fires on load instead, using .rv's exact
   distance, duration and easing so it reads as the same motion the rest of
   the site uses. */
@keyframes cs-rise{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:none}}
.cs-rise{opacity:0;animation:cs-rise 1050ms cubic-bezier(.22,.61,.36,1) forwards}
.cs-logo.cs-rise{animation-delay:60ms}
.cs-h1.cs-rise{animation-delay:200ms}
.cs-lede.cs-rise{animation-delay:340ms}
.cs-card.cs-rise{animation-delay:480ms}
@media (prefers-reduced-motion:reduce){
  .cs-rise{opacity:1;animation:none}
}

.cs-logo{display:block;width:min(360px,76vw);margin:0 0 clamp(24px,3vw,32px);
  transition:opacity .3s ease-out,transform .3s ease-out}
.cs-logo img{width:100%;height:auto;display:block}
.cs-logo:hover{opacity:.82;transform:translateY(-2px)}
.cs-logo:focus-visible{outline:2px solid var(--blush-300);outline-offset:14px;border-radius:4px}

.cs-h1{font-family:var(--font-display);font-weight:400;color:var(--white);
  font-size:clamp(36px,6vw,58px);line-height:1.1;margin:0}
.cs-lede{font-family:var(--font-body);color:rgba(255,255,255,.9);
  font-size:clamp(15px,2.2vw,18px);line-height:1.7;text-wrap:pretty;
  margin:14px 0 clamp(28px,3.6vw,38px);max-width:52ch}

/* The one container the locations and the form share. Translucent rather
   than solid so the photograph still carries through it, with the blur
   doing the legibility work; the rgba alone is enough where
   backdrop-filter is unsupported. */
.cs-card{width:100%;box-sizing:border-box;text-align:left;
  /* border-box or the padding and border are added to width:100% and the
     card hangs past its column -- the DS sheet sets no global border-box */
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:clamp(32px,4.5vw,56px);
  padding:clamp(26px,3.2vw,40px);
  border-radius:var(--radius-lg);
  background:rgba(12,42,45,.52);
  border:1px solid rgba(251,247,245,.16);
  box-shadow:0 24px 60px rgba(0,0,0,.28);
  -webkit-backdrop-filter:blur(14px) saturate(115%);
  backdrop-filter:blur(14px) saturate(115%)}

.cs-h2{font:400 clamp(20px,2.6vw,25px)/1.3 var(--font-display);
  color:var(--cream-50);margin:0 0 22px}

.cs-locs{list-style:none;margin:0 0 30px;padding:0;
  display:flex;flex-direction:column;gap:18px}
.cs-loc{display:flex;align-items:flex-start;gap:13px}
.cs-loc div{font:400 13.5px/1.6 var(--font-body);color:rgba(251,247,245,.8);min-width:0}
.cs-loc strong{display:block;font:500 15px/1.4 var(--font-body);color:var(--cream-50);
  margin-bottom:2px}
/* the teal disc used on the contact page would vanish against this panel */
.cs-loc .loc-mark{width:30px;height:30px;background:rgba(251,247,245,.13);
  border:1px solid rgba(251,247,245,.2)}
.cs-loc .loc-mark img{width:18px}

.cs-contact{padding-top:24px;border-top:1px solid rgba(251,247,245,.18)}
.cs-contact .lbl{display:block;font:var(--text-caption);letter-spacing:.14em;
  text-transform:uppercase;color:var(--blush-300)}
.cs-contact .contact-big{margin-top:6px;color:var(--cream-50)}
.cs-contact .contact-big:hover{color:var(--blush-300)}
.cs-contact p{font:var(--text-body-sm);color:rgba(251,247,245,.78);margin:9px 0 0}

.cs-col--form textarea.inp{min-height:104px;padding-top:13px;resize:vertical}
.cs-col--form .frm{gap:20px}

.cs-done{display:flex;align-items:flex-start;gap:11px;margin:0;
  font:500 15px/1.6 var(--font-body);color:var(--cream-50);
  background:rgba(251,247,245,.1);border:1px solid rgba(251,247,245,.24);
  border-radius:var(--radius-md);padding:20px 22px}
.cs-done svg{flex-shrink:0;margin-top:3px;color:var(--blush-300)}
/* focused programmatically so screen readers announce it; it is not
   interactive, so the UA's focus ring would be off-brand noise */
.cs-done:focus{outline:none}

/* Shown by app.js when the enquiry did not send. The palette has no error
   colour, so it reuses .cs-done's cream on the dark panel and marks itself
   out with a solid blush edge instead; role="alert" does the announcing. */
.cs-error{margin:0;font:500 15px/1.6 var(--font-body);color:var(--cream-50);
  background:rgba(251,247,245,.1);border:1px solid rgba(251,247,245,.24);
  border-left:3px solid var(--blush-300);border-radius:var(--radius-md);
  padding:14px 18px}

/* Spam trap for the enquiry form: off-screen rather than display:none, so
   form-filling bots still see it. aria-hidden and tabindex=-1 in the
   markup keep it away from screen readers and the keyboard. */
.hp{position:absolute;left:-9999px;top:auto;width:1px;height:1px;overflow:hidden}

@media (max-width:860px){
  .cs-card{grid-template-columns:minmax(0,1fr)}
}
@media (max-width:600px){
  .cs{padding:40px 16px}
  .cs-card{padding:24px 20px;gap:32px}
  .cs-col--form .frm-grid{grid-template-columns:minmax(0,1fr)}
}
/* Short viewports (landscape phones): stop the logo eating the fold. */
@media (max-height:560px){
  .cs-logo{width:min(240px,58vw);margin-bottom:20px}
}
