/* Framework Health · production stylesheet · Shoreline design */
/* Palette note: the greens were lightened in July 2026 at the practice's request
   ("can all this dark green be a lighter color, make it pop more"). Every value
   below was checked against its own background rather than picked by eye:
   --sage on white is 5.1:1, --sage-2 is 4.7:1, and the announce bar is 7.6:1,
   so the lighter look still clears WCAG AA for small text. Do not nudge these
   lighter without re-checking, because they no longer have much headroom. */
:root{
  /* --ink-3 was #7C8781, which is 3.6:1 on paper and 3.4:1 on the soft band.
     It carries real 12px to 13px text (the results-vary disclaimer, review
     attributions, blog dates, the optional-field hints), so it was failing AA
     on the smallest type on the site. #68726C is 4.9:1 on paper and 4.6:1 on
     the soft band and still reads as a muted grey. */
  --paper:#FDFCFA; --soft:#F1F6F1; --card:#FFFFFF; --ink:#22302A; --ink-2:#4E5A54; --ink-3:#68726C;
  --sage:#4A7761; --sage-2:#4F7D68; --sage-deep:#2F5343; --sage-hover:#3C6551;
  --sage-tint:#E8F3EB; --sage-line:#BFDACB; --line:#E9E7E0;
  /* Wordmark tokens. The practice's logo sets the words in a neutral grey rather
     than in the site's green, and frames them in the same sage as the rest of the
     site's rules. #575757 is 7.1:1 on paper, so the lighter grey still clears AA.
     --logo-pad, --logo-tick and the .72em overhang below were set by eye against
     the real logo in logo-overlay.html, which puts the file itself underneath a
     live copy of this CSS. They are not derived, and they should not be nudged
     without going back to that page, because the mark stops matching quickly.
     --logo-tick is deliberately shorter than the distance to the cap line, so
     each vertical rule stops with visible air before the letters begin rather
     than running up against them.
     --logo-rule-w has a px floor on purpose. The nav renders the mark as small as
     15px, where a purely em-based hairline would round to nothing, so the em term
     only takes over above about 85px, which is where the mark is shown large. */
  --logo-ink:#575757; --logo-rule:var(--sage-line); --logo-rule-w:max(1.5px,.018em);
  --logo-pad:.58em; --logo-tick:.53em;
  --logo-face:var(--serif); --logo-weight:500;
  --serif:'Lora',Georgia,serif; --sans:'Inter',sans-serif;
  --sh:0 1px 2px rgba(34,46,40,.05),0 10px 30px -12px rgba(34,46,40,.14);
  /* The open mobile menu carries its own shadow rather than --sh. --sh is a
     resting-card shadow, and at 14% it disappears entirely under a panel that
     is nearly the same colour as the page it drops onto. This one is a menu
     shadow: it has to be the thing that tells you the panel is in front. */
  --sh-menu:0 3px 8px rgba(34,46,40,.10),0 26px 46px -10px rgba(34,46,40,.44);
}
*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}*,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important}}
body{font-family:var(--sans);background:var(--paper);color:var(--ink);font-size:16px;line-height:1.65;-webkit-font-smoothing:antialiased}
.wrap{max-width:1120px;margin:0 auto;padding:0 24px}
h1,h2,h3{font-family:var(--serif);font-weight:500;line-height:1.18;letter-spacing:-.008em}
a{color:var(--sage)}
:focus-visible{outline:3px solid var(--sage-2);outline-offset:2px;border-radius:6px}
img,video{max-width:100%;height:auto;display:block}
button{cursor:pointer;font-family:var(--sans)}
section{padding:72px 0}

/* skip link: off-screen until focused, so keyboard users are not made to tab
   through the whole nav on every page */
.skip{position:absolute;left:-9999px;top:0;z-index:200;background:var(--sage);color:#fff;
      font-size:14px;font-weight:600;text-decoration:none;padding:12px 20px;border-radius:0 0 10px 0}
.skip:focus{left:0}

/* announce + nav */
.announce{background:var(--sage-tint);color:var(--sage-deep);border-bottom:1px solid var(--sage-line);
          text-align:center;font-size:13px;font-weight:500;padding:9px 16px}
.announce a{color:var(--sage-deep);font-weight:700;text-decoration:none;white-space:nowrap}
.announce a:hover{text-decoration:underline}
/* The new sentence is long enough to take three lines on a phone, which pushes
   the whole page down before anyone has read a word. Tightening it to two is
   the difference between a banner and a wall. */
@media(max-width:640px){.announce{font-size:12px;line-height:1.45;padding:8px 14px}}
nav.main{position:sticky;top:0;z-index:90;background:rgba(253,252,250,.96);backdrop-filter:blur(12px);border-bottom:1px solid var(--line)}

/* Desktop nav is three columns: links, wordmark, links. Both outer columns are
   1fr, which is what actually keeps the wordmark on the true centre line of the
   viewport, and each column is space-between so the row reaches both edges
   rather than clustering in the middle. The phone number and the Book a consult
   button live inside the link groups on purpose: they balance each other at the
   two ends and leave the centre column holding nothing but the wordmark. */
nav.main .wrap{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:24px;height:78px}
.navlinks{display:flex;align-items:center;gap:16px}
.navlinks-l{justify-content:space-between;padding-right:8px}
.navlinks-r{justify-content:space-between;padding-left:8px}
.navlinks a{font-size:15px;font-weight:500;color:var(--ink-2);text-decoration:none;white-space:nowrap;
            padding:12px 2px;display:inline-flex;align-items:center;min-height:44px}
.navlinks a:hover{color:var(--sage)}
.navlinks a.on{color:var(--sage);font-weight:600}

/* The wordmark is not text in a box, and the box does not go all the way round.
   In the practice's logo the top and bottom rules run the full width, but each
   vertical rule stops at the cap line and picks up again at the baseline: the
   band of the rectangle where the words are is simply not drawn. The rectangle is
   also narrower than the words, so the F and the final h hang past it entirely.
   Hence a pseudo-element inset in em rather than a border with padding, and
   verticals drawn as background segments rather than as a border, so they can
   stop. Both have to hold at every size the clamp produces.
   isolation:isolate is load-bearing. nav.main is a sticky, z-indexed element, so
   it opens a stacking context, and without an isolating context of its own the
   z-index:-1 frame paints behind the nav's own background and disappears. */
.logo{position:relative;isolation:isolate;display:inline-block;white-space:nowrap;width:fit-content;
      font-family:var(--logo-face);font-weight:var(--logo-weight);
      font-size:clamp(15px,1.55vw,21px);line-height:1;letter-spacing:.011em;
      color:var(--logo-ink);text-decoration:none;padding:var(--logo-pad) 0}
/* .72em is the overhang: each vertical rule sits that far in from the end of the
   words, so the F and the final h break out of the box on either side. Every
   number here is in em, so the whole mark scales with the clamp above and the
   proportions hold from 15px in the phone nav to any size it is shown at. */
.logo::before{content:"";position:absolute;top:0;bottom:0;left:.72em;right:.72em;
      border-top:var(--logo-rule-w) solid var(--logo-rule);
      border-bottom:var(--logo-rule-w) solid var(--logo-rule);
      background-image:linear-gradient(var(--logo-rule),var(--logo-rule)),
                       linear-gradient(var(--logo-rule),var(--logo-rule)),
                       linear-gradient(var(--logo-rule),var(--logo-rule)),
                       linear-gradient(var(--logo-rule),var(--logo-rule));
      background-size:var(--logo-rule-w) var(--logo-tick);background-repeat:no-repeat;
      background-origin:border-box;
      background-position:left top,left bottom,right top,right bottom;
      z-index:-1;pointer-events:none}
.navlinks a.nav-phone{font-size:14px;font-weight:700;color:var(--sage);letter-spacing:.01em}
.navlinks a.nav-book{background:var(--sage);color:#fff;font-size:14px;font-weight:600;
                     border-radius:10px;padding:11px 20px;min-height:44px}
.navlinks a.nav-book:hover{background:var(--sage-hover);color:#fff}
/* The wordmark no longer carries horizontal padding, so it gives the link groups
   back roughly 56px at this breakpoint on its own and needs no override here. */
@media(max-width:1180px){nav.main .wrap{gap:16px}.navlinks{gap:10px}.navlinks a{font-size:14px}}
@media(max-width:1040px){.navlinks a.nav-phone{display:none}}

/* mobile menu.
   Below 960px the two link groups collapse and reopen as stacked rows inside
   the same grid, rather than as an absolutely positioned panel. With the links
   split across two sibling containers there is no single element left to
   position, and expanding in flow keeps both groups in source order for a
   screen reader. The wordmark, the CTA and the toggle stay pinned to row 1. */
.nav-menu{display:none;background:none;border:1.5px solid var(--sage-line);border-radius:10px;width:44px;height:44px;align-items:center;justify-content:center;color:var(--sage);flex-shrink:0}
@media(max-width:960px){
  nav.main .wrap{grid-template-columns:1fr auto auto;gap:10px;height:auto;min-height:66px;align-content:center;padding-top:10px;padding-bottom:10px}
  .logo{grid-column:1;grid-row:1;justify-self:start}
  .nav-menu{display:inline-flex;grid-column:3;grid-row:1;justify-self:end}
  .navlinks-l{display:none}
  .navlinks-r{display:contents}
  .navlinks-r a:not(.nav-book){display:none}
  .navlinks a.nav-book{grid-column:2;grid-row:1;justify-self:end}

  /* The open panel needs three selectors, because it has to win the same
     cascade fight three times over. On its own, `nav.main.open` is two classes,
     and the home and services rules further down the file are at least that
     specific: `body.vhero-top nav.main` paints the nav transparent over the
     video, and `.solid` repaints it once you scroll past the hero. Both of them
     beat a bare `.open`, so on those two pages the menu used to open with no
     background at all, dark links straight onto the video with the hero
     headline running through them. Naming .vhero-top and .solid here is what
     actually puts a surface under the links.
     The surface is --card and not --paper on purpose. The page behind it is
     --paper, so a paper panel was findable only by its dividers, which is the
     other half of the same complaint. White, a sage bottom edge and a real menu
     shadow read as a sheet in front of the page rather than a hole cut in it.
     The z-index lifts the open panel over the mobile call bar (95); at the
     resting 90 the bar sat on top of the menu's own shadow. */
  nav.main.open,
  body.vhero-top nav.main.open,
  body.vhero-top nav.main.solid.open{background:var(--card);border-bottom:1.5px solid var(--sage-line);
                            box-shadow:var(--sh-menu);z-index:97}
  /* padding-right on .navlinks-l is a desktop rule: it keeps the left group off
     the wordmark. Stacked, it only made the left three dividers 8px shorter
     than the right three. */
  nav.main.open .navlinks-l{display:flex;flex-direction:column;align-items:stretch;gap:0;
                            grid-column:1/-1;grid-row:2;margin-top:8px;padding-right:0}
  nav.main.open .navlinks-r a:not(.nav-book){display:flex;grid-column:1/-1}
  nav.main.open .navlinks a:not(.nav-book){padding:13px 2px;font-size:15.5px;min-height:46px;
                                           color:var(--ink-2);border-top:1px solid var(--line)}
  nav.main.open .navlinks a.on{color:var(--sage)}
  nav.main.open .navlinks a.nav-phone{display:flex;color:var(--sage)}
  body.vhero-top nav.main:not(.solid).open .navlinks a:not(.nav-book){color:var(--ink-2)}
  body.vhero-top nav.main:not(.solid).open .navlinks a:not(.nav-book):hover{color:var(--sage)}
  body.vhero-top nav.main:not(.solid).open .logo{color:var(--logo-ink);--logo-rule:var(--sage-line)}
  body.vhero-top nav.main:not(.solid).open .nav-menu{color:var(--sage);border-color:var(--sage-line)}
  /* Over the video the CTA is a white button, which was the right call against
     the footage and the wrong one the moment there is a white panel behind it:
     the button disappears and only its label is left. Everything else in the
     open nav already flips back to the on-paper treatment, so this does too. */
  body.vhero-top nav.main:not(.solid).open .navlinks a.nav-book{background:var(--sage);color:#fff}
  body.vhero-top nav.main:not(.solid).open .navlinks a.nav-book:hover{background:var(--sage-hover);color:#fff}
}
@media(max-width:640px){nav.main .wrap{gap:8px}.navlinks a.nav-book{padding:9px 13px;font-size:12.5px}.nav-menu{width:42px;height:42px}}

/* home nav over video */
body.vhero-top nav.main{position:absolute;top:37px;left:0;right:0;background:transparent;border-bottom:0;backdrop-filter:none}
body.vhero-top nav.main:not(.solid) .nav-menu{color:#fff;border-color:rgba(255,255,255,.55)}
body.vhero-top nav.main.solid{position:fixed;background:rgba(253,252,250,.96);backdrop-filter:blur(12px);border-bottom:1px solid var(--line)}
body.vhero-top nav.main:not(.solid) .logo{color:#fff;--logo-rule:rgba(255,255,255,.55)}
body.vhero-top nav.main:not(.solid) .navlinks a{color:rgba(255,255,255,.92)}
body.vhero-top nav.main:not(.solid) .navlinks a:hover{color:#fff}
/* These two need the a.class form, not the bare class. The rule directly above
   is one element more specific, so `.nav-book` on its own lost the colour war
   and the button came out white-on-white. */
body.vhero-top nav.main:not(.solid) .navlinks a.nav-phone{color:#fff}
body.vhero-top nav.main:not(.solid) .navlinks a.nav-book{background:#fff;color:var(--sage)}
body.vhero-top nav.main:not(.solid) .navlinks a.nav-book:hover{background:var(--sage-tint);color:var(--sage)}

/* buttons */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;font-size:14.5px;font-weight:600;text-decoration:none;border-radius:12px;padding:14px 26px;min-height:48px;transition:all .18s;cursor:pointer}
.btn.p{background:var(--sage);color:#fff;box-shadow:var(--sh)}
.btn.p:hover{background:var(--sage-hover)}
.btn.s{background:#fff;color:var(--sage);border:1.5px solid var(--sage)}
.btn.s:hover{background:var(--sage-tint)}
.btn.w{background:#fff;color:var(--sage)}
.btn.w:hover{background:#EDF3EE;transform:translateY(-1px)}
.btn.o{background:rgba(255,255,255,.08);color:#fff;border:1.5px solid rgba(255,255,255,.75);backdrop-filter:blur(4px)}
.btn.o:hover{background:rgba(255,255,255,.18)}

/* full-bleed video hero (home) */
.vhero{position:relative;min-height:94vh;min-height:94svh;display:flex;align-items:center;justify-content:center;overflow:hidden;background:var(--ink)}
.vhero video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.vhero .shade{position:absolute;inset:0;background:linear-gradient(180deg,rgba(18,28,23,.62) 0%,rgba(18,28,23,.28) 42%,rgba(18,28,23,.58) 100%)}
.vhero .inner{position:relative;z-index:2;text-align:center;color:#fff;max-width:900px;padding:150px 24px 110px}
@media(max-width:640px){
  .vhero{min-height:74vh;min-height:74svh;--vidh:min(100%,133.334vw)}
  /* What survives object-fit: cover is decided by the shape of the box, not by
     the file. The hero box on a phone is about 3:8 once two paragraphs of intro
     copy have stretched it, so a 16:9 clip had 24% of its width left and the
     couple on the beach lost a person: object-position could pick which half
     went, never keep both.
     Capping the clip at 3:4 of the viewport width fixes the box instead. The
     portrait cuts in assets/video are that same 3:4, so they now show whole,
     and the scrim finishes on ink at the cut line so the picture hands off to
     the copy rather than stopping on a hard edge. --mpos, set per clip in the
     markup, aims the poster frame at the same part of the shot the portrait
     cut is centred on; it is inert on the clip itself, which already fits. */
  .vhero video{height:var(--vidh);bottom:auto;object-position:var(--mpos,50%) 50%}
  .vhero .shade{background:linear-gradient(180deg,rgba(18,28,23,.56) 0,rgba(18,28,23,.2) calc(var(--vidh)*.32),rgba(20,31,26,.62) calc(var(--vidh)*.8),var(--ink) var(--vidh))}
  .vhero .inner{padding:118px 20px 64px}
  .vhero .hero-ctas{flex-direction:column;align-items:stretch;margin-top:26px}
  .vhero .hero-ctas .btn{width:100%}
  .vhero h1{font-size:clamp(34px,9vw,44px)}
  /* The practice's intro copy is two full paragraphs. At the desktop size it
     runs past the fold on a phone and buries both calls to action, so the
     type steps down here rather than the copy being cut. */
  .vhero .eyebrow{letter-spacing:.14em;margin-bottom:16px}
  .vhero .sub{font-size:15px;line-height:1.55;margin-top:20px}
  .vhero .sub+.sub{font-size:14px;margin-top:12px}
}
.vhero .eyebrow{font-size:12px;font-weight:700;letter-spacing:.22em;text-transform:uppercase;color:rgba(255,255,255,.85);margin-bottom:22px}
.vhero h1{font-size:clamp(40px,6.4vw,76px);color:#fff;text-wrap:balance;text-shadow:0 2px 30px rgba(0,0,0,.25)}
.vhero .sub{font-size:clamp(15.5px,1.6vw,18px);color:rgba(255,255,255,.92);margin:26px auto 0;max-width:686px}
/* The practice supplied two paragraphs of intro copy, not one. The second is
   the specialty note, so it is stepped down rather than repeated at full size. */
.vhero .sub+.sub{margin-top:15px;font-size:clamp(14.5px,1.4vw,16px);color:rgba(255,255,255,.86)}
.vhero .sub b{color:#fff}
.vhero .hero-ctas{justify-content:center}
.vhero .hero-trust{justify-content:center}
.scrolldown{position:absolute;bottom:26px;left:50%;transform:translateX(-50%);z-index:2;color:rgba(255,255,255,.8);font-size:11px;letter-spacing:.18em;text-transform:uppercase;text-decoration:none;display:flex;flex-direction:column;align-items:center;gap:8px}
.scrolldown svg{animation:drift 2.2s ease-in-out infinite}
@keyframes drift{0%,100%{transform:translateY(0)}50%{transform:translateY(6px)}}

/* page hero (subpages) */
.phero{background:linear-gradient(180deg,var(--soft),var(--paper));padding:64px 0 52px;border-bottom:1px solid var(--line)}
.phero h1{font-size:clamp(32px,4.6vw,50px);max-width:800px}
.phero .lede{color:var(--ink-2);margin-top:14px;font-size:16px;max-width:660px}
.eyebrow{font-size:11.5px;font-weight:700;letter-spacing:.15em;text-transform:uppercase;color:var(--sage-2);margin-bottom:14px}

/* shared section head */
.sec-head{max-width:660px;margin-bottom:38px}
.sec-head h2{font-size:clamp(26px,3.8vw,38px)}
.sec-head p{color:var(--ink-2);margin-top:10px;font-size:15px}
.sec-head p.sec-lede{font-family:var(--serif);font-style:italic;font-size:clamp(17.5px,2vw,21px);line-height:1.5;margin-top:16px;text-wrap:balance}
.sec-head p.sec-lede+p{margin-top:16px}
.sec-head p.fine{font-size:13px;color:var(--ink-3);margin-top:8px}
.alt{background:var(--soft)}
.hero-ctas{display:flex;flex-wrap:wrap;gap:14px;margin-top:34px}
.hero-trust{display:flex;flex-wrap:wrap;gap:10px 26px;margin-top:36px}
.hero-trust span{display:flex;align-items:center;gap:7px;font-size:12.5px;color:rgba(255,255,255,.88);font-weight:500}

/* "every service is included" note + mission statement.
   The practice asked twice for one thing to be unmissable: these are not a la
   carte services, they all come with the membership. So it gets a rule and a
   tinted panel rather than another sentence in the body copy. */
.sec-head p.svc-included{background:var(--card);border:1px solid var(--sage-line);
  border-left:4px solid var(--sage);border-radius:12px;padding:14px 18px;margin-top:18px;font-size:14.5px}
.sec-head p.svc-included b{color:var(--ink)}
.mission{background:var(--sage-tint);border:1px solid var(--sage-line);border-radius:16px;
  padding:24px 28px;margin-bottom:26px;max-width:840px}
.mission .eyebrow{margin-bottom:8px}
.mission p{font-family:var(--serif);font-size:clamp(16.5px,1.8vw,19px);line-height:1.55;color:var(--ink);text-wrap:balance}
@media(max-width:600px){.mission{padding:20px 20px}}

/* Deep links land under the sticky nav without this. The alias span is the
   retired #testosterone anchor, kept so old links and the footer still resolve
   after that section was merged into male hormone therapy.
   It has to be taken out of flow, not just collapsed: its parent .svc-detail
   .wrap is a two-column grid, and an in-flow empty span becomes a third grid
   item that pushes the copy into the wrong cell. */
[id]{scroll-margin-top:96px}
.anchor-alias{position:absolute;top:0;left:0;width:0;height:0;overflow:hidden}

/* services grid */
.svc-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
@media(max-width:920px){.svc-grid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:600px){.svc-grid{grid-template-columns:1fr}}
.svc{background:var(--card);border:1px solid var(--line);border-radius:16px;padding:26px;text-decoration:none;color:var(--ink);display:flex;flex-direction:column;gap:10px;transition:transform .18s,box-shadow .18s;box-shadow:0 1px 2px rgba(34,46,40,.04)}
.svc:hover{transform:translateY(-3px);box-shadow:var(--sh)}
.svc .ic{width:38px;height:38px;border-radius:10px;background:var(--sage-tint);color:var(--sage);display:flex;align-items:center;justify-content:center}
.svc h3{font-size:18.5px}
.svc p{font-size:13.8px;color:var(--ink-2)}
.svc .lm{font-size:13px;font-weight:600;color:var(--sage);margin-top:auto}

/* service detail rows */
.svc-detail{border-bottom:1px solid var(--line);padding:56px 0}
.svc-detail:last-of-type{border-bottom:0}
.svc-detail .wrap{position:relative;display:grid;grid-template-columns:.9fr 1.1fr;gap:44px;align-items:start}
@media(max-width:880px){.svc-detail .wrap{grid-template-columns:1fr;gap:20px}}
.svc-detail h2{font-size:clamp(24px,3.4vw,34px)}
.svc-detail .body p{color:var(--ink-2);font-size:15px;margin-bottom:14px}
.svc-detail .body p:last-child{margin-bottom:0}
.svc-detail ul{list-style:none;margin-top:6px;display:flex;flex-direction:column;gap:10px}
.svc-detail li{display:flex;gap:10px;align-items:flex-start;font-size:14.5px;color:var(--ink-2)}
.svc-detail li svg{flex-shrink:0;margin-top:4px;color:var(--sage)}

/* intro video */
.video-sec .wrap{display:grid;grid-template-columns:1fr .9fr;gap:46px;align-items:center}
@media(max-width:880px){.video-sec .wrap{grid-template-columns:1fr;gap:28px}}
.video-sec h2{font-size:clamp(26px,3.8vw,38px)}
.video-sec p{color:var(--ink-2);margin-top:12px;font-size:15px}
.video-sec .fine{font-size:13px;color:var(--ink-3)}
.phone{width:min(290px,80vw);margin:0 auto;border-radius:30px;overflow:hidden;border:5px solid var(--ink);box-shadow:0 24px 60px -22px rgba(34,46,40,.38);background:#000}
.phone video{width:100%;aspect-ratio:9/16;object-fit:cover;display:block}

/* quote band over video */
.qband{position:relative;overflow:hidden;padding:120px 24px;text-align:center;color:#fff;background:var(--ink)}
.qband video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.qband .shade{position:absolute;inset:0;background:rgba(16,26,21,.58)}
.qband .inner{position:relative;z-index:2;max-width:840px;margin:0 auto}
.qband .stars{color:#F2C879;letter-spacing:.3em;font-size:15px;margin-bottom:22px}
.qband blockquote{font-family:var(--serif);font-style:italic;font-weight:500;font-size:clamp(23px,3.4vw,38px);line-height:1.35;text-wrap:balance}
.qband .who{margin-top:24px;font-size:12.5px;letter-spacing:.14em;text-transform:uppercase;color:rgba(255,255,255,.8)}
.qband .note{margin-top:30px;font-size:12px;color:rgba(255,255,255,.6)}
.qband .note a{color:rgba(255,255,255,.85)}
.qband .qslides{display:grid}
.qband .qslide{grid-area:1/1;display:flex;flex-direction:column;justify-content:center;opacity:0;transform:translateY(16px);transition:opacity .9s ease,transform .9s ease;pointer-events:none}
.qband .qslide.on{opacity:1;transform:none;pointer-events:auto}
@media (prefers-reduced-motion:reduce){.qband .qslide{transition:none;transform:none}}
/* A band sized only by its quote is a different shape on every page: the three
   rotating reviews on the home page made a 3:4 box, the one-line bands on
   services a 4:3 one, and object-fit: cover reads that difference as a zoom, so
   the same clip went from a whole surfer to a tight slice of one. Holding the
   band at 3:4 on a phone, the shape the portrait cuts in assets/ are made for,
   gives one framing across every band instead of one per quote length. The svh
   term is for a phone turned sideways, where 133vw is taller than the screen. */
@media(max-width:640px){
  .qband{padding:80px 20px;min-height:min(133.334vw,80svh);display:flex;align-items:center;justify-content:center}
  .qband .inner{width:100%}
  /* --mpos, set per clip in the markup, aims the 16:9 poster frame at the same
     subject the cut is centred on. It is near enough inert on the cut itself. */
  .qband video{object-position:var(--mpos,50%) 50%}
}

/* testimonials page. The reviews run from ~190 to ~560 characters, so a row
   grid would stretch the short ones to match the tall one in their row and
   leave dead space under the quote. Columns let each card end where its text
   ends and still balance the two columns to roughly equal height. */
.t-wall{columns:2;column-gap:18px}
@media(max-width:820px){.t-wall{columns:1}}
.t-card{background:var(--card);border:1px solid var(--line);border-radius:16px;padding:26px;
  break-inside:avoid;-webkit-column-break-inside:avoid;margin:0 0 18px}
.t-card .stars{color:#C9A24B;letter-spacing:.18em;font-size:13px;margin-bottom:12px}
.t-card blockquote{font-family:var(--serif);font-size:16px;line-height:1.65;color:var(--ink)}
.t-card .who{margin-top:14px;font-size:12px;color:var(--ink-3);letter-spacing:.06em;text-transform:uppercase;font-weight:600}
.t-source{margin-top:12px;font-size:14px;color:var(--ink-2);max-width:660px}

/* bios */
.bio{border-bottom:1px solid var(--line);padding:56px 0}
.bio:last-of-type{border-bottom:0}
.bio .wrap{display:grid;grid-template-columns:.62fr 1.38fr;gap:44px;align-items:start}
@media(max-width:820px){.bio .wrap{grid-template-columns:1fr;gap:24px}}
.bio img{width:100%;max-width:340px;height:auto;border-radius:18px;box-shadow:var(--sh);object-fit:cover;aspect-ratio:4/5}
/* Leslie sits in the right third of her frame, so anchor the crop to that edge */
#leslie img{object-position:100% 30%}
/* single column on small screens: show each portrait whole, at its own native ratio
   (stated explicitly, not `auto`, so the box is reserved before a lazy image loads) */
@media(max-width:820px){#leslie img{aspect-ratio:1400/1358}#devan img{aspect-ratio:1/1}}
.bio h2{font-size:clamp(24px,3.4vw,34px)}
.bio .cr{font-size:12px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--sage-2);margin:6px 0 16px}
.bio .body p{color:var(--ink-2);font-size:15px;margin-bottom:14px}
.bio .badges{display:flex;flex-wrap:wrap;gap:8px;margin-top:16px}
.bio .badge{font-size:12px;font-weight:600;color:var(--sage);background:var(--sage-tint);border-radius:999px;padding:6px 13px}
.staff-grid{display:grid;grid-template-columns:1fr 1fr;gap:18px}
@media(max-width:720px){.staff-grid{grid-template-columns:1fr}}
.staff{display:flex;gap:18px;align-items:flex-start;background:var(--card);border:1px solid var(--line);border-radius:16px;padding:20px}
.staff img{width:92px;height:92px;border-radius:50%;object-fit:cover;flex-shrink:0}
.staff h3{font-size:17px}
.staff .cr{font-size:11.5px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--sage-2);margin:2px 0 8px}
.staff p{font-size:13.5px;color:var(--ink-2)}

/* faq */
.faq{display:flex;flex-direction:column;gap:12px;max-width:820px}
.faq details{background:var(--card);border:1px solid var(--line);border-radius:14px}
.faq summary{cursor:pointer;list-style:none;display:flex;justify-content:space-between;align-items:center;gap:14px;padding:17px 20px;font-weight:600;font-size:15px;min-height:44px}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"+";font-family:var(--serif);font-size:20px;color:var(--sage);flex-shrink:0;transition:transform .2s}
.faq details[open] summary::after{transform:rotate(45deg)}
.faq details p{padding:0 20px 18px;font-size:14px;color:var(--ink-2)}
.faq-cta{margin-top:20px;font-size:14px;color:var(--ink-2)}
.faq-cta a{font-weight:600}

/* blog */
.blog-wait{background:var(--card);border:1.5px dashed var(--sage-line);border-radius:16px;padding:26px 28px;max-width:640px;display:flex;flex-direction:column;gap:12px;align-items:flex-start}
.blog-wait p{font-size:14.5px;color:var(--ink-2)}
.soon-chip{font-size:11px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--sage-2);background:var(--sage-tint);border-radius:999px;padding:6px 12px}

/* published article cards, rendered from /api/approved */
.bloglist{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:18px;align-items:start}
.bloglist:has(.blog-wait){display:block}
.bcard{display:flex;flex-direction:column;gap:9px;background:var(--card);border:1px solid var(--line);border-radius:16px;padding:24px 26px;text-decoration:none;box-shadow:0 1px 2px rgba(34,46,40,.04);transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease}
.bcard:hover,.bcard:focus-visible{transform:translateY(-2px);box-shadow:var(--sh);border-color:var(--sage-line)}
.bcard:focus-visible{outline:2px solid var(--sage-2);outline-offset:3px}
.bcard .bcat{font-size:10.5px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--sage-2)}
.bcard h3{font-family:var(--serif);font-size:19px;line-height:1.3;color:var(--ink);margin:0}
.bcard p{font-size:14px;line-height:1.6;color:var(--ink-2);margin:0}
.bcard .bmeta{font-size:12px;color:var(--ink-3);margin-top:auto;padding-top:4px}
/* "read all articles", revealed by bloglist.js once there is something to read */
.sec-more{margin-top:22px;font-size:14.5px;font-weight:600}
.sec-more a{text-decoration:none}
.sec-more a:hover{text-decoration:underline}
@media(prefers-reduced-motion:reduce){.bcard{transition:none}.bcard:hover,.bcard:focus-visible{transform:none}}

/* request-a-call form */
.reqbox{display:grid;grid-template-columns:1fr 1fr;gap:44px;align-items:start}
@media(max-width:880px){.reqbox{grid-template-columns:1fr;gap:28px}}
.reqcopy h2{font-size:clamp(24px,3.4vw,34px)}
.reqcopy>p{color:var(--ink-2);margin-top:12px;font-size:15px}
.reqwhy{list-style:none;margin-top:20px;display:flex;flex-direction:column;gap:10px}
.reqwhy li{display:flex;gap:10px;align-items:flex-start;font-size:14.5px;color:var(--ink-2)}
.reqwhy svg{flex-shrink:0;margin-top:4px;color:var(--sage)}
.reqform{background:var(--card);border:1px solid var(--line);border-radius:20px;padding:28px;box-shadow:var(--sh);display:flex;flex-direction:column;gap:14px}
@media(max-width:520px){.reqform{padding:22px 18px}}
.field{display:flex;flex-direction:column;gap:6px}
.field label{font-size:13px;font-weight:600;color:var(--ink)}
.field .opt{font-weight:400;color:var(--ink-3)}
.field input,.field select{font-family:var(--sans);font-size:15px;color:var(--ink);background:var(--paper);
  border:1.5px solid var(--line);border-radius:11px;padding:12px 14px;min-height:48px;width:100%}
.field input:focus,.field select:focus{outline:none;border-color:var(--sage-2);box-shadow:0 0 0 3px var(--sage-tint)}
.field select{appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%234E6E5E' stroke-width='2.4'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 14px center;padding-right:40px}
/* bot trap: out of the layout and out of the tab order, never display:none,
   which some bots specifically skip */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.reqfine{font-size:12.5px;color:var(--ink-3);margin-top:2px}
.reqform .btn{width:100%}
.reqmsg{font-size:13.5px;margin:0}
.reqmsg:empty{display:none}
.reqmsg.bad{color:#A33A2E;font-weight:600}
.reqdone{text-align:center;padding:14px 4px}
.reqdone b{font-family:var(--serif);font-size:19px;font-weight:600;display:block;margin-bottom:8px}
.reqdone p{font-size:14.5px;color:var(--ink-2)}
.reqnote{border-radius:14px;padding:14px 18px;font-size:14.5px;margin-bottom:22px;border:1px solid var(--sage-line);background:var(--sage-tint);color:var(--ink)}
.reqnote.bad{border-color:#F0CFC8;background:#FBEAE7;color:#A33A2E}

/* contact */
.contact-box{background:var(--card);border:1px solid var(--line);border-radius:20px;padding:40px;display:grid;grid-template-columns:1.2fr .8fr;gap:40px;align-items:center;box-shadow:var(--sh)}
@media(max-width:880px){.contact-box{grid-template-columns:1fr;padding:28px}}
.contact-box h2{font-size:clamp(24px,3.4vw,34px)}
.contact-box>div>p{color:var(--ink-2);margin-top:10px;font-size:15px}
.clist{list-style:none;margin-top:20px;display:flex;flex-direction:column;gap:12px}
.clist li{display:flex;gap:12px;align-items:flex-start;font-size:14px;color:var(--ink-2)}
.clist svg{flex-shrink:0;margin-top:3px;color:var(--sage)}
.clist b{color:var(--ink)}
.stack{display:flex;flex-direction:column;gap:12px}
.stack-row{display:flex;flex-wrap:wrap;gap:12px}
.stack-row .btn{flex:1 1 118px;padding:14px 10px;white-space:nowrap}
.map-link{display:block;border-radius:16px;overflow:hidden;border:1px solid var(--line);box-shadow:var(--sh)}
.dpc{background:var(--sage-tint);border:1px solid var(--sage-line);border-radius:16px;padding:24px 26px;max-width:820px}
.dpc h2{font-size:20px;margin-bottom:8px}
.dpc p{font-size:14.5px;color:var(--ink-2)}

/* footer */
footer{background:#2C3B33;color:#B9C5BE;padding:56px 0 90px;font-size:13.5px}
footer .cols{display:grid;grid-template-columns:1.4fr 1fr 1fr;gap:36px}
@media(max-width:760px){footer .cols{grid-template-columns:1fr}}
footer h4{font-family:var(--serif);color:#fff;font-size:16px;margin-bottom:12px;font-weight:500}
footer ul{list-style:none}
footer li{margin-bottom:8px}
footer a{color:#B9C5BE;text-decoration:none}
footer a:hover{color:#fff}
/* was #7E8A83, which came out at 3.3:1 on the old footer and would have been
   worse on the lighter one. #9AA7A0 is 4.7:1 and still reads as fine print. */
.legal{border-top:1px solid rgba(255,255,255,.14);margin-top:36px;padding-top:20px;font-size:12px;color:#9AA7A0}
/* The three required legal notices sit above the copyright line rather than in
   the Practice column, because CalOPPA and 45 CFR 164.520(c)(3)(i) both turn on
   the link being conspicuous, and a fourth item buried in a list of five is not.
   #DCE6E0 is 9.1:1 on the footer green, so the smallest links on the site are
   also the highest contrast ones. */
.legal-links{display:flex;flex-wrap:wrap;gap:10px 18px;align-items:center;margin-bottom:14px}
.legal-links a{color:#DCE6E0;font-weight:600;font-size:12.5px;text-decoration:underline;text-underline-offset:3px}
.legal-links a:hover{color:#fff}
.legal-links .sep{color:#6C7A73;font-size:12.5px}
@media(max-width:520px){.legal-links{gap:8px 14px}.legal-links .sep{display:none}}

/* mobile sticky */
.msticky{display:none;position:fixed;bottom:0;left:0;right:0;z-index:95;background:rgba(253,252,250,.97);backdrop-filter:blur(10px);border-top:1px solid var(--line);padding:10px 12px calc(10px + env(safe-area-inset-bottom));gap:8px}
@media(max-width:640px){.msticky{display:flex}}
.msticky a{flex:1;text-align:center;font-size:13.5px;font-weight:600;text-decoration:none;border-radius:10px;padding:12px 8px;min-height:44px;display:inline-flex;align-items:center;justify-content:center}
.msticky .m1{background:var(--sage);color:#fff}
.msticky .m2{background:#fff;color:var(--sage);border:1.5px solid var(--sage-line)}

/* legal documents (privacy, notice of privacy practices, good faith estimate)
 *
 * These are the only long-form prose pages on the site that are not blog
 * articles, and they are read differently: nobody reads a privacy policy top to
 * bottom, they scan for the one heading that answers their question. So the
 * measure is narrower than the blog's, the headings are heavier than the body,
 * and every section carries an id so a specific clause can be linked directly
 * when the practice's attorney or a patient asks about one.
 *
 * 68ch rather than the blog's wider measure: legal prose has longer sentences,
 * and the same line length that reads fine in an article becomes hard to track
 * back when the sentence is a definition. */
.legaldoc{max-width:68ch;margin:0 auto}
.legaldoc h2{font-size:clamp(21px,2.6vw,26px);margin:44px 0 14px;scroll-margin-top:96px}
/* Only collapse the top margin when the heading really is the first thing in
   the document. Both of these pages open with intro prose before the first
   h2, and :first-of-type matched that heading anyway, so it sat 44px too close
   to the paragraph above it. */
.legaldoc>h2:first-child{margin-top:0}
.legaldoc h3{font-size:17.5px;margin:28px 0 10px;color:var(--ink)}
.legaldoc p{color:var(--ink-2);margin-bottom:14px;font-size:16px}
.legaldoc ul,.legaldoc ol{margin:0 0 16px 22px;color:var(--ink-2);font-size:16px}
.legaldoc li{margin-bottom:9px}
.legaldoc li>strong{color:var(--ink);font-weight:600}
.legaldoc a{text-decoration:underline;text-underline-offset:2px}
.legaldoc hr{border:0;border-top:1px solid var(--line);margin:40px 0}

/* The effective-date stamp. A privacy policy without one is missing a CalOPPA
   required element, so it is a component rather than a line of prose that can
   be forgotten on the next edit. */
.doc-stamp{display:flex;flex-wrap:wrap;gap:6px 18px;align-items:center;padding:14px 18px;
           background:var(--soft);border:1px solid var(--line);border-radius:10px;
           font-size:13.5px;color:var(--ink-2);margin-bottom:36px}
.doc-stamp b{color:var(--ink);font-weight:600}

/* Pull-out for the statements that carry legal weight on their own: the Do Not
   Track answer, the $400 dispute threshold, the fact that a notice is not the
   same as an estimate. */
.doc-note{border:1px solid var(--sage-line);background:var(--sage-tint);border-radius:12px;
          padding:18px 22px;margin:24px 0;color:var(--sage-deep);font-size:15.5px}
.doc-note p{color:var(--sage-deep);margin-bottom:10px}
.doc-note p:last-child{margin-bottom:0}
.doc-note strong{font-weight:700}

/* Definition rows, used for "what we collect" and the patient-rights list.
   Grid rather than a real <dl> layout so the term column stays aligned when a
   definition wraps to four lines. */
.doc-rows{border-top:1px solid var(--line);margin:20px 0 24px}
.doc-row{display:grid;grid-template-columns:210px 1fr;gap:12px 28px;padding:16px 0;border-bottom:1px solid var(--line)}
@media(max-width:640px){.doc-row{grid-template-columns:1fr;gap:4px}}
.doc-row dt{font-weight:600;color:var(--ink);font-size:15px}
.doc-row dd{color:var(--ink-2);font-size:15px}
.doc-row dd p{font-size:15px;margin-bottom:8px}
.doc-row dd p:last-child{margin-bottom:0}
