/* ============ Tokens ============ */
:root{
  --paper:#f2f6f5; --white:#fdfefd; --ink:#102d35; --green:#092229;
  --ox:#8ed8e8; --oxwash:#dbeef2; --gold:#e84d38; --gold-deep:#c2371f;
  --muted:#51666c; --muted-dark:#9fb8bd;
  --line:#d3dedd; --line-dark:rgba(255,255,255,.18);
  --pad:clamp(20px,4vw,56px); --rad:22px; --rad-img:14px;
  --serif:"Libre Caslon Display",Georgia,serif; --serif-i:"Libre Caslon Text",Georgia,serif; --sans:"DM Sans",Arial,sans-serif;
  --shadow:0 24px 60px rgba(9,34,41,.16),0 4px 14px rgba(9,34,41,.08);
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
html,body{overflow-x:clip}
body{margin:0;background:var(--paper);color:var(--ink);font-family:var(--sans);font-size:16.5px;line-height:1.55}
a{color:inherit;text-decoration:none}
button,input,textarea{font:inherit}
button{color:inherit}
/* height:auto is REQUIRED — images carry intrinsic width/height attributes (for CLS),
   and without this the raw pixel height wins wherever CSS only sets width. */
img{max-width:100%;height:auto;display:block}
.skip-link{position:fixed;top:0;left:1rem;z-index:1000;padding:.75rem 1rem;background:var(--white);border-radius:0 0 12px 12px;transform:translateY(-120%)}
.skip-link:focus{transform:none}

/* ============ Kicker system ============ */
.kicker,.eyebrow{display:flex;align-items:center;gap:.8rem;font-size:.7rem;font-weight:600;text-transform:uppercase;letter-spacing:.16em;margin:0 0 1.6rem}
.kicker:before{content:"";width:44px;height:2px;background:var(--gold);flex:none}
.mini-kicker{font-size:.68rem;font-weight:600;text-transform:uppercase;letter-spacing:.14em;margin:0 0 1rem}

/* ============ Buttons & links ============ */
.button{display:inline-flex;align-items:center;justify-content:center;gap:.7rem;border:0;border-radius:999px;padding:1rem 1.75rem;font-size:.95rem;font-weight:600;cursor:pointer;transition:transform .2s,box-shadow .2s,background .2s;line-height:1}
.button:hover{transform:translateY(-2px);box-shadow:0 10px 24px rgba(9,34,41,.18)}
.button-gold{background:var(--gold);color:#07181d}
.button:focus-visible,.text-link:focus-visible,a:focus-visible,button:focus-visible,input:focus-visible+*,.ba input:focus-visible~.ba-handle{outline:2px solid var(--gold);outline-offset:3px}


/* ============ Header (pill nav) ============ */
.site-header{position:sticky;top:0;z-index:100;display:grid;grid-template-columns:1fr auto 1fr;align-items:center;min-height:76px;padding:0 var(--pad);background:rgba(242,246,245,.85);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);border-bottom:1px solid var(--line);transition:box-shadow .25s,background .25s}
.site-header.compact{min-height:62px;background:rgba(242,246,245,.95);box-shadow:0 8px 24px rgba(9,34,41,.08)}
.brand{display:inline-flex;align-items:center;gap:.72rem;font-size:1.1rem;font-weight:600;letter-spacing:-.03em}
.brand em{font-family:var(--serif);font-weight:400}
.brand-mark{position:relative;width:26px;height:26px;display:block}
.brand-mark i{position:absolute;width:9px;height:9px;border-color:currentColor;border-style:solid}
.brand-mark i:nth-child(1){top:0;left:0;border-width:1.5px 0 0 1.5px}
.brand-mark i:nth-child(2){top:0;right:0;border-width:1.5px 1.5px 0 0}
.brand-mark i:nth-child(3){bottom:0;left:0;border-width:0 0 1.5px 1.5px}
.brand-mark i:nth-child(4){right:0;bottom:0;border-width:0 1.5px 1.5px 0}
.site-header nav{display:flex;gap:.4rem}
.site-header nav a{padding:.55rem 1.05rem;border-radius:999px;font-size:.85rem;font-weight:500;transition:background .2s}
.site-header nav a:hover,.site-header nav a:focus-visible{background:rgba(9,34,41,.07)}
.header-cta{justify-self:end;padding:.8rem 1.4rem;font-size:.85rem}
.menu-button{display:none;background:none;border:0;font-weight:600;cursor:pointer;padding:.6rem 1rem;border-radius:999px;border:1px solid var(--line)}
/* Legal and thanks pages carry no nav and no menu button. The 1020px rule hides
   .header-cta and hands over to .menu-button — with no menu button on those pages
   that would leave them with no way back, so .header-plain opts out of the swap. */
.site-header.header-plain{grid-template-columns:1fr auto}

/* ============ Hero ============ */
.hero{position:relative;padding:clamp(4rem,9vh,7.5rem) var(--pad) 0;text-align:center}

.hero-inner{position:relative;z-index:1;max-width:1280px;margin:0 auto}

.booking-chip:hover,.booking-chip:focus-visible{color:var(--ink)}


.booking-chip:hover .chip-arrow{transform:translateY(2px)}
.hero h1{font-family:var(--serif);font-weight:400;font-size:clamp(3.2rem,7.4vw,7.5rem);line-height:.96;letter-spacing:-.04em;margin:0 0 1.8rem;text-wrap:balance}


.hs1:after{content:"";position:absolute;inset:18%;border-radius:50%;border:1px solid rgba(16,45,53,.09)}


@keyframes drift1{to{transform:translate(-34px,42px) rotate(6deg)}}
@keyframes drift2{to{transform:translate(26px,-30px) rotate(-4deg)}}
@keyframes drift3{to{transform:translate(44px,26px)}}


.service-bar .button{margin-left:clamp(.5rem,2vw,1.5rem)}

/* ============ Ticker ============ */
.ticker{overflow:hidden;background:var(--ox);padding:1.05rem 0}
.ticker div{display:flex;gap:2rem;width:max-content;animation:ticker 28s linear infinite;text-transform:uppercase;font-size:.7rem;font-weight:600;letter-spacing:.14em}
.ticker i{font-style:normal;color:var(--gold-deep)}
@keyframes ticker{to{transform:translateX(-50%)}}

/* ============ Section scaffolding ============ */
.section{padding:clamp(90px,12vh,150px) var(--pad)}
.section>.kicker,.section>h2,.section>.lead,.section>.steps-row,.section>.service-list,.section>.addon,.section>.note,.section>.team-row,.section>.work-head,.section>.case-card,.section>.feat-head,.section>.feat-row,.aftercare-row,.contact-grid,.ed-row{max-width:1240px;margin-left:auto;margin-right:auto}
.section h2{font-family:var(--serif);font-weight:400;font-size:clamp(2.6rem,4.6vw,4.4rem);line-height:1;letter-spacing:-.035em;margin:0 0 1.6rem;text-wrap:balance}
.section h2 em{font-weight:400}
.lead{font-size:1.1rem;max-width:58ch;margin:0 0 2.2rem}
.lead-center{margin:0 auto 3.5rem;text-align:center}

.dark-pass{background:var(--green);color:var(--paper)}
.dark-pass .lead,.dark-pass .note{color:var(--muted-dark)}
.sky-pass{background:var(--oxwash)}
.sky-pass .lead{color:#274850}


.chip-list li:before{content:"";width:8px;height:8px;background:var(--gold);flex:none}
.fact-stack{list-style:none;margin:0;padding:0;border-top:1px solid var(--line-dark)}
.fact-stack li{padding:1.15rem 0;border-bottom:1px solid var(--line-dark)}
.fact-stack b{display:flex;align-items:center;font-family:var(--serif);font-weight:400;font-size:1.35rem;line-height:1.1}
.fact-stack b:before{content:"";width:8px;height:8px;background:var(--gold);margin-right:.85rem;flex:none}
.fact-stack span{display:block;margin:.4rem 0 0 1.35rem;font-size:.92rem;color:var(--muted-dark)}

/* ============ Editorial rows ============ */
.ed-row{display:grid;grid-template-columns:1.05fr 1fr;gap:clamp(2.5rem,6vw,6rem);align-items:center}
.ed-flip .ed-text{order:1}
.ed-flip .ed-visual{order:0}


/* Websites visual: layered site sheets */
.ed-visual{position:relative}


/* ============ Video feature ============ *
   Ported verbatim from the umbrella sheet (root index.html §414-425) so the
   therapist video section is the same component, not a lookalike. The one
   addition is the dark-pass pair at the end: the root runs this section on sky,
   but on this page #work is paper and #answers is sky, so a sky video section
   would put two sky grounds side by side. It runs on green here instead, and
   .vlist needs light text on that ground. */
.vframe{position:relative;aspect-ratio:16/9;border-radius:var(--rad-img);overflow:hidden;
  background:var(--green);box-shadow:0 30px 60px -30px rgba(16,45,53,.45)}
.vplayer{display:block;width:100%;height:100%;object-fit:cover;background:var(--green)}
/* No dividers: five ruled rows beside a single image read as a table and made the
   column look twice as long as the player. Markers and tight leading instead. */
.vlist{list-style:none;margin:1.6rem 0 0;padding:0;display:flex;flex-direction:column;gap:.62rem}
.vlist li{position:relative;padding-left:1.3rem;font-size:.95rem;line-height:1.42;color:#274850}
.vlist li:before{content:"";position:absolute;left:0;top:.5em;width:7px;height:7px;background:var(--gold)}
.vlist b{font-weight:600;color:var(--ink)}
#video .ed-row{align-items:center}
@media(min-width:1021px){#video .ed-row{grid-template-columns:1.32fr .88fr;gap:clamp(2rem,4vw,3.5rem)}}
/* Green ground: #274850 body text and ink bold both disappear on it. */
.dark-pass .vlist li{color:var(--muted-dark)}
.dark-pass .vlist b{color:var(--paper)}

/* ============ Work / portfolio ============ */
.work-head{margin-bottom:2.6rem}
.work-head h2{margin:0}

.case-card{position:relative;margin:0 auto;background:var(--white);border:1px solid var(--line);border-radius:calc(var(--rad) + 6px);padding:clamp(.8rem,1.6vw,1.4rem);box-shadow:var(--shadow)}
.frame-corner,.photo-slot:before,.photo-slot:after{position:absolute;width:16px;height:16px;border-color:var(--gold);border-style:solid;pointer-events:none}
.case-card .frame-corner.tl{top:-6px;left:-6px;border-width:2px 0 0 2px}
.case-card .frame-corner.br{right:-6px;bottom:-6px;border-width:0 2px 2px 0}
.photo-slot:before{content:"";top:12px;left:12px;border-width:1.5px 0 0 1.5px;border-color:var(--gold-deep);z-index:3}
.photo-slot:after{content:"";right:12px;bottom:12px;border-width:0 1.5px 1.5px 0;border-color:var(--gold-deep);z-index:3}


.ba-handle:before{content:"";position:absolute;top:0;bottom:0;left:-1.5px;width:3px;background:var(--gold)}


.case-row{display:grid;grid-template-columns:1.55fr 1fr;gap:clamp(2rem,4vw,3.8rem);align-items:start;max-width:1240px;margin:0 auto}
.case-row>*{min-width:0}
.case-main{width:100%}
.case-side{display:flex;flex-direction:column;align-items:flex-start;gap:1.3rem;padding-top:.4rem}
.case-head{font-family:var(--serif);font-weight:400;font-size:clamp(2rem,3vw,2.7rem);line-height:1.08;letter-spacing:-.02em;margin:0;max-width:16ch}
.case-head em{font-style:italic}


.did-stack b:before{content:"";width:8px;height:8px;background:var(--gold);margin-right:.85rem;flex:none}


.drag-hint:before{content:"◂ ▸";color:var(--gold);letter-spacing:.05em;margin-right:.55rem}
.feat-head{display:flex;align-items:baseline;gap:1.4rem;margin:5rem auto 1.8rem;flex-wrap:wrap}
.feat-head h3{font-family:var(--serif);font-weight:400;font-size:clamp(1.7rem,2.4vw,2.2rem);margin:0}

.feat-row{display:grid;grid-template-columns:repeat(3,1fr);gap:1.4rem}

/* Padding is EQUAL top and bottom so the button + line sit optically centred between
   the hairline rule above and the section edge below. The section's own bottom padding
   is zeroed out so it can't add space on one side only. */
.cta-band{display:flex;align-items:center;justify-content:flex-start;gap:1.1rem 2.2rem;flex-wrap:wrap;max-width:1240px;margin:clamp(2.2rem,4vh,3.2rem) auto 0;padding:2.4rem 0;border-top:1px solid var(--line)}
.section:has(> .cta-band:last-child){padding-bottom:0}
.cta-band .button{flex:none}
.cta-band p{margin:0;font-family:var(--serif);font-weight:400;font-size:clamp(1.35rem,2.2vw,1.85rem);line-height:1.15;letter-spacing:-.01em;max-width:26ch}
.sky-pass .cta-band{border-top-color:rgba(9,34,41,.16)}
.feat{background:var(--white);border:1px solid var(--line);border-radius:var(--rad);padding:1.1rem 1.1rem 1.4rem;transition:transform .25s,box-shadow .25s}
.feat:hover{transform:translateY(-4px);box-shadow:var(--shadow)}
.feat h4{font-family:var(--serif);font-weight:400;font-size:1.2rem;margin:1.1rem .3rem .3rem}
.feat p{margin:0 .3rem;font-size:.85rem;color:var(--muted)}


.feat-shot:hover img,.feat-shot:focus-visible img{transform:scale(1.03)}
.lightbox{border:0;border-radius:var(--rad);padding:.9rem .9rem 1rem;width:min(1080px,94vw);background:var(--white);box-shadow:var(--shadow)}
.lightbox::backdrop{background:rgba(9,34,41,.74);backdrop-filter:blur(5px)}
.lightbox img{width:100%;border-radius:var(--rad-img);border:1px solid var(--line)}
.lb-cap{margin:.85rem .3rem .1rem;font-size:.86rem;color:var(--muted)}
.lb-close{position:absolute;top:1.3rem;right:1.3rem;width:42px;height:42px;border-radius:50%;border:0;background:var(--ink);color:var(--paper);cursor:pointer;font-size:.95rem;line-height:1}
.lb-close:hover{background:var(--gold);color:#07181d}


/* ============ Studio ============ */
.studio{text-align:center}
.studio .kicker{justify-content:center}
.studio .kicker:before{display:none}
.studio .kicker:after{content:"";width:44px;height:2px;background:var(--gold);order:-1;margin-right:.8rem}
.team-row{display:grid;grid-template-columns:repeat(2,minmax(0,420px));gap:2rem;justify-content:center;margin:0 auto}
.person{background:var(--white);border:1px solid var(--line);border-radius:var(--rad);padding:1.2rem 1.2rem 1.8rem;text-align:left}
.photo-slot{position:relative;aspect-ratio:1000/564;border-radius:var(--rad-img);overflow:hidden;
  background:radial-gradient(135% 115% at 50% 6%,#f2fbfd 0%,var(--oxwash) 48%,#a8dfec 100%)}
.photo-slot>img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;object-position:bottom;z-index:2;
  filter:drop-shadow(0 14px 24px rgba(16,45,53,.22))}
.photo-slot .ps-ring,.photo-slot .ps-sq,.photo-slot .ps-dot{position:absolute;z-index:1;pointer-events:none}
.photo-slot .ps-ring{width:58%;aspect-ratio:1;border-radius:50%;border:1px solid rgba(16,45,53,.14);right:-13%;top:-24%}
.photo-slot .ps-ring:after{content:"";position:absolute;inset:17%;border-radius:50%;border:1px solid rgba(16,45,53,.09)}
.photo-slot .ps-sq{width:26%;aspect-ratio:1;border:1px solid rgba(232,77,56,.34);border-radius:9px;left:-7%;bottom:-14%;transform:rotate(11deg)}
.photo-slot .ps-dot{width:13%;aspect-ratio:1;border-radius:50%;background:rgba(253,254,253,.55);left:9%;top:13%}
.person h3{font-family:var(--serif);font-weight:400;font-size:1.7rem;margin:1.3rem .4rem .2rem}
.person .role{margin:0 .4rem .8rem;font-size:.78rem;font-weight:600;text-transform:uppercase;letter-spacing:.12em;color:var(--gold-deep)}
.person p{margin:0 .4rem;font-size:.92rem;color:var(--muted)}


.z-row:nth-child(even) .z-text{order:1}
.z-row:nth-child(even) .z-vis{order:0}


.z-row:nth-child(even) .mock-panel{margin-left:0;margin-right:auto}


.mp-search i:after{content:"";position:absolute;right:-4px;bottom:-3px;width:5px;height:2px;background:var(--ox);transform:rotate(45deg)}


.mp-map:before{content:"";position:absolute;inset:0;background:linear-gradient(115deg,transparent 42%,rgba(255,255,255,.9) 44%,transparent 46%),linear-gradient(200deg,transparent 60%,rgba(255,255,255,.85) 62%,transparent 64%)}


.mp-acts .is-call{background:var(--gold);color:#25120d}


.mp-row span:before{content:"✓";font-size:.66rem}


.mp-chart:before{content:"";position:absolute;left:0;right:0;bottom:1.25rem;border-bottom:1px solid var(--line)}


.mp-chart .is-now i{background:linear-gradient(180deg,var(--gold) 0%,#f07a68 100%)}

.mp-chart .is-now small{color:var(--gold-deep);font-weight:600}


.z-row.visible .mp-chart i{animation:barRise .85s cubic-bezier(.2,.7,.2,1) backwards}


@keyframes barRise{from{height:0}to{height:var(--h)}}


.care-card li:before{content:"✓";display:grid;place-items:center;width:23px;height:23px;border-radius:50%;background:rgba(232,77,56,.13);color:var(--gold-deep);font-size:.72rem;font-weight:700;flex:none}


/* ============ Contact ============ */
.contact-grid{display:grid;grid-template-columns:1fr 1.1fr;gap:clamp(2.5rem,6vw,6rem);align-items:start}
.contact-copy p{max-width:44ch}
.contact-copy>p:not(.kicker):not(.contact-note){font-size:1.08rem;color:var(--muted-dark);margin:0 0 2rem}
.contact-note{font-size:.74rem;font-weight:600;text-transform:uppercase;letter-spacing:.13em;color:var(--ox);margin:0}
.inquiry-form{background:var(--white);color:var(--ink);border-radius:var(--rad);padding:clamp(1.5rem,3.5vw,2.6rem);box-shadow:var(--shadow)}
.field-row{display:grid;grid-template-columns:1fr 1fr;gap:1.3rem}
.inquiry-form label{display:block;margin-bottom:1.3rem}
.inquiry-form label>span{display:block;font-size:.72rem;font-weight:600;text-transform:uppercase;letter-spacing:.11em;margin-bottom:.45rem}
.inquiry-form input,.inquiry-form textarea{width:100%;border:1px solid var(--line);border-radius:12px;background:var(--paper);padding:.8rem .95rem;outline:none;transition:border-color .2s,box-shadow .2s}
.inquiry-form input:focus,.inquiry-form textarea:focus{border-color:var(--ink);box-shadow:0 0 0 3px rgba(142,216,232,.4)}
.inquiry-form textarea{resize:vertical}
.inquiry-form input:user-invalid,.inquiry-form textarea:user-invalid{border-color:var(--gold-deep);box-shadow:0 0 0 3px rgba(232,77,56,.18)}
.inquiry-form .button{width:100%;margin-top:.4rem}
.field-hint{display:block;margin-top:.5rem;font-size:.78rem;line-height:1.5;font-weight:400;text-transform:none;letter-spacing:0;color:var(--muted)}
.contact-alt{margin:.9rem 0 0;font-size:.92rem;color:var(--muted-dark)}
.contact-alt a{border-bottom:1.5px solid var(--gold);padding-bottom:.12rem;font-weight:600;color:#e8f1f2}
.footer-bottom a{border-bottom:1px solid rgba(255,255,255,.3)}
.form-note{font-size:.72rem;color:var(--muted);margin:1rem 0 0}
.honey{position:absolute;left:-9999px}

/* ============ Footer ============ */
footer{padding:4rem var(--pad) 1.5rem;background:var(--green);color:var(--paper);display:grid;grid-template-columns:1fr 1fr;gap:2.5rem;border-top:1px solid var(--line-dark)}
.footer-brand{font-size:1.25rem}
footer>p{max-width:420px;margin:0;justify-self:end;color:var(--muted-dark)}
.footer-links{display:flex;gap:1.8rem;font-size:.85rem;flex-wrap:wrap}
.footer-links a{display:inline-block;padding:.28rem 0;border-bottom:1px solid transparent;transition:border-color .2s}
.footer-links a:hover{border-color:currentColor}
.footer-bottom{grid-column:1/-1;display:flex;justify-content:space-between;border-top:1px solid var(--line-dark);padding-top:1.1rem;color:var(--muted-dark);font-size:.72rem;text-transform:uppercase;letter-spacing:.1em}

/* ============ Legal pages & thanks (shared) ============ */
.legal-page{max-width:850px;margin:0 auto;padding:clamp(5rem,10vw,9rem) var(--pad)}
.legal-page h1{font-family:var(--serif);font-size:clamp(3rem,7vw,5.5rem);font-weight:400;line-height:.95;letter-spacing:-.04em;margin:0 0 1rem}
.legal-page h2{font-family:var(--serif);font-size:1.7rem;font-weight:400;margin:2.6rem 0 .5rem}
.legal-page p{font-size:1.02rem;max-width:68ch}
.legal-date{color:var(--muted);font-size:.72rem!important;text-transform:uppercase;letter-spacing:.1em}
.contact.section .contact-copy .eyebrow{color:inherit}

/* ============ Motion ============ */
.reveal{opacity:0;transform:translateY(24px);transition:opacity .7s cubic-bezier(.2,.7,.2,1),transform .7s cubic-bezier(.2,.7,.2,1)}
.reveal.visible{opacity:1;transform:none}
.no-js .reveal{opacity:1;transform:none}


.service-list li.reveal:nth-child(even){transition-delay:.12s}

/* ============ Responsive ============ */
@media(max-width:1020px){
  .site-header{grid-template-columns:1fr auto}
  .site-header nav,.header-cta{display:none}
  .site-header.header-plain .header-cta{display:inline-flex}
  .menu-button{display:inline-flex;align-items:center;gap:.5rem}
  .site-header.open nav{display:flex;position:absolute;top:100%;left:0;right:0;flex-direction:column;gap:0;background:var(--paper);padding:.6rem var(--pad) 1.2rem;border-bottom:1px solid var(--line)}
  .site-header.open nav a{padding:1rem .4rem;border-radius:0;border-bottom:1px solid var(--line)}
  .ed-row{grid-template-columns:1fr;gap:3rem}
  .case-row{grid-template-columns:1fr;gap:2.6rem}

  .case-head{max-width:24ch}
  .ed-flip .ed-visual{order:1}


  .feat-row{grid-template-columns:1fr 1fr}

  .z-row:nth-child(even) .z-text{order:0}
  .z-row:nth-child(even) .z-vis{order:1}
  .z-vis .mock-panel,.z-row:nth-child(even) .mock-panel{margin:0}
  .aftercare-row,.contact-grid{grid-template-columns:1fr}
  .team-row{grid-template-columns:repeat(2,1fr)}
}
@media(max-width:680px){
  .site-header.header-plain .header-cta{padding:.6rem 1rem;font-size:.8rem}
  body{font-size:16px}

  .hero h1{font-size:clamp(2.7rem,13vw,4rem)}


  .service-bar .button{margin:1.2rem 0 0}
  .steps-row,.team-row,.field-row,.aftercare-cards{grid-template-columns:1fr}
  /* Portfolio becomes a swipe carousel: all six stay reachable without six screens of scrolling */
  .feat-row{display:flex;grid-template-columns:none;gap:1rem;overflow-x:auto;scroll-snap-type:x mandatory;
    scroll-padding-left:var(--pad);padding:.25rem var(--pad) 1.1rem;margin-left:calc(var(--pad)*-1);margin-right:calc(var(--pad)*-1);
    -webkit-overflow-scrolling:touch;scrollbar-width:none}
  .feat-row::-webkit-scrollbar{display:none}
  .feat-row:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
  .feat{flex:0 0 82%;scroll-snap-align:start}

  .cta-band{margin-top:2rem;padding:1.9rem 0}
  .cta-band .button{width:100%;text-align:center}


  footer{grid-template-columns:1fr}
  footer>p{justify-self:start}
  .footer-bottom{flex-direction:column;gap:.5rem}
}
@media(prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}
  .reveal{opacity:1;transform:none}
  .ticker div{animation:none}
}

/* Libre Caslon Display ships no italic — Chrome would synthesize a fake slant.
   Libre Caslon Text is its companion face and has a true drawn italic. */
/* Libre Caslon Text is a text-optimised face: larger x-height than Display, so at the
   same px it reads oversized. .94em optically matches it to the Display roman. */
h1 em,h2 em,h3 em,.case-head em,.brand em,.hero h1 em{font-family:var(--serif-i);font-style:italic;font-size:.94em}

/* ================================================================
   THERAPISTS VERTICAL — additions only.
   Everything above is the shared Firm & Frame system, inherited from
   law-firms/styles.css unchanged. Four new components live here:
   .doors, .screen-check, .terms-card, .tier-not-yet — all built from
   existing primitives. No new radii, shadows, hues, or motion types.
   See therapists/DESIGN.md.
   ================================================================ */


/* Label variant: the row names the ways in rather than quoting survey shares. */
.doors-top.is-labels b{font-size:clamp(1.05rem,1.7vw,1.4rem);line-height:1.15}


.doors.visible .doors-web path{stroke-dashoffset:0}
.no-js .doors-web path{stroke-dashoffset:0}


.sc-q:before{content:"";width:8px;height:8px;background:var(--gold);margin-right:.85rem;flex:none;position:relative;top:-.24em}


.fit-col.is-out h3 i{background:none;border:1.5px solid rgba(9,34,41,.34)}


.fit-col.is-out li{color:#4d666f}  /* quieter than the left column but still AA on sky wash */

/* --- .terms-card — ownership, deliberately document-like --- */
.terms-card{position:relative;max-width:920px;margin:3rem auto 0;background:var(--white);border:1px solid var(--line);
  border-radius:calc(var(--rad) + 6px);padding:clamp(1.6rem,3.4vw,2.8rem);box-shadow:var(--shadow)}
.terms-card .frame-corner.tl{top:-6px;left:-6px;border-width:2px 0 0 2px}
.terms-card .frame-corner.br{right:-6px;bottom:-6px;border-width:0 2px 2px 0}


.terms-card dt:before{content:"";width:8px;height:8px;background:var(--gold);margin-right:.8rem;flex:none;position:relative;top:-.2em}


/* --- Group practices --- */
/* .fact-stack is drawn for dark passes; this is its light-ground variant. */
.sky-pass .fact-stack{border-top-color:rgba(9,34,41,.16)}
.sky-pass .fact-stack li{border-bottom-color:rgba(9,34,41,.16)}
.sky-pass .fact-stack span{color:#33555e}


.is-open{background:rgba(46,158,91,.16);color:#1e6b41}
.is-full{background:rgba(9,34,41,.09);color:var(--muted)}

/* --- Placeholder study frames (swapped for real shots later) --- */
.slot{aspect-ratio:16/10;border-radius:var(--rad-img);border:1px solid var(--line);position:relative;overflow:hidden;
  background:radial-gradient(120% 110% at 50% 4%,#f4fcfd 0%,var(--oxwash) 55%,#bce5ef 100%)}
.slot .frame-corner.tl{top:12px;left:12px;border-width:1.5px 0 0 1.5px;border-color:var(--gold-deep)}
.slot .frame-corner.br{right:12px;bottom:12px;border-width:0 1.5px 1.5px 0;border-color:var(--gold-deep)}


/* Inline footer mail link was 16px tall — below the 24px target floor. */
.footer-bottom a{display:inline-block;padding:.34rem 0}


@media(max-width:680px){


  .sc-most:before{content:"Most sites: ";font-weight:600;color:var(--ox);opacity:.7}
  .sc-ours:before{content:"Ours: ";font-weight:600;color:var(--ox)}


}

/* `.section>h2` is given `margin-left/right:auto` by the max-width rule, but the
   later `.section h2` block ties it on specificity and its `margin` shorthand
   resets both to 0 — so every h2 sat 44px left of its own kicker and lead, and
   the centred `.studio` heading was off-centre. Matches the root fix. */
.section>h2{margin-inline:auto}

/* ============================================================================
   2026-08-19 copy replacement — components the new text needs.
   Nothing here is a new visual language: each rule either lets an existing
   component hold longer copy, or gives an existing component a second column
   count. See the section notes below.
   ============================================================================ */


/* --- Featured design study: the .case-row from the law page, carrying prose
   instead of a before/after slider. --- */
.case-side p{margin:0;font-size:.98rem;line-height:1.6;color:var(--muted);max-width:46ch}

.case-side .case-head{margin-bottom:-.2rem}
.case-main .case-card .slot{border:0}
.feat-row.is-two{grid-template-columns:repeat(2,1fr)}

/* --- How we work: four steps at four across were 20 words each. The rewritten
   steps run two paragraphs, so they need half the row each. --- */
.steps-row.is-two{grid-template-columns:repeat(2,1fr)}


.terms-card .did-stack b:before{position:relative;top:-.2em}


/* .cta-band's hairline is drawn for light ground; on the green pass the light
   line was brighter than the type above it. */
.dark-pass .cta-band{border-top-color:var(--line-dark)}

/* --- Contact: practice size replaces the states + clinicians pair --- */
.inquiry-form select{width:100%;border:1px solid var(--line);border-radius:12px;background:var(--paper);
  padding:.8rem 2.4rem .8rem .95rem;outline:none;font:inherit;color:inherit;cursor:pointer;
  transition:border-color .2s,box-shadow .2s;-webkit-appearance:none;appearance:none;
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='%23092229' stroke-width='1.6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right .95rem center;background-size:12px 8px}
.inquiry-form select:focus{border-color:var(--ink);box-shadow:0 0 0 3px rgba(142,216,232,.4)}

/* The nav carries five items now and the button label is longer. Between the
   1020px nav cutoff and 1180px the three header cells were colliding. */
@media(max-width:1180px) and (min-width:1021px){
  .site-header nav a{padding:.55rem .72rem}
  .header-cta{padding:.75rem 1.1rem;font-size:.8rem}
}
@media(max-width:1020px){
  .steps-row.is-two{grid-template-columns:1fr 1fr}
}
@media(max-width:680px){
  .steps-row.is-two,.feat-row.is-two{grid-template-columns:1fr}
  .feat-row.is-two{display:grid}

}


.service-bar .button{white-space:nowrap}


@media(max-width:680px){
  .sc-most:before{color:var(--muted)}
  .sc-ours:before{color:var(--gold-deep)}
}

/* --- Alignment and contrast corrections found in the browser --- */


/* The six-question section now closes on two centred lines; the note above them
   was the only left-ranged element in that coda. */
.note.is-coda{text-align:center}

/* The contact note grew from one line to a sentence; at 44ch of letterspaced
   uppercase it stacked three lines tight against the email line. */
.contact-copy .contact-note{max-width:54ch}
/* Brad, 2026-08-21: more air under the uppercase reassurance line so "Prefer
   email?" reads as a separate offer rather than a continuation of it.
   ⚠️ Scoped by id on purpose. The shared rule up at
   `.contact-copy>p:not(.kicker):not(.contact-note){margin:0 0 2rem}` scores
   (0,3,1) — each :not() contributes its argument — and had silently beaten the
   plain `.contact-alt{margin-top:1.3rem}` that used to sit here, so that override
   had never once applied. `.contact-copy>p.contact-alt` is only (0,2,1) and loses
   too. The id settles it.
   The same collision eats `.contact-alt{font-size:.92rem}`, so this line renders
   at 1.08rem, not .92rem. Both colliding rules sit above the THERAPISTS marker,
   so law-firms has it too. Left as found — only the spacing Brad asked about is
   fixed here. */
#contact .contact-copy>p.contact-alt{margin-top:2.6rem}

/* --- "Before the first message" (#answers) ---------------------------------
   Rebuilt 2026-08-20 from Brad's canvas design 2a
   (Desktop/Therapy Website Section Design 2/Six Questions Section.dc.html).
   An accordion: six question rows, each opening onto a "most therapy sites"
   vs "the sites we build" pair. This RESTORES the comparison that design 1
   had dropped. The canvas export drives every state through inline style
   strings from JS; here the states are classes and attribute selectors, so
   the styling stays in CSS and script.js only flips flags.               */
.qa-head{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));
  gap:clamp(2rem,5vw,5rem);align-items:end;max-width:1240px;margin:0 auto clamp(2.5rem,5vw,4rem)}
.qa-head h2{max-width:20ch;text-wrap:pretty;margin:0}
.qa-intro .lead{max-width:46ch;color:var(--muted);margin:0 0 1.4rem}
.qa-controls{display:flex;align-items:center;gap:1rem;flex-wrap:wrap}
.qa-all{background:none;border:1px solid var(--line);border-radius:999px;padding:.55rem 1.1rem;
  font-size:.78rem;font-weight:600;letter-spacing:.11em;text-transform:uppercase;
  cursor:pointer;transition:border-color .2s,transform .2s}
.qa-all:hover{border-color:var(--ink);transform:translateY(-1px)}
.qa-count{font-size:.78rem;font-weight:600;letter-spacing:.11em;text-transform:uppercase;color:var(--muted)}

.qa{list-style:none;margin:0 auto;padding:0;max-width:1240px;border-top:1px solid var(--line);counter-reset:qa}
.qa>li{counter-increment:qa;border-bottom:1px solid var(--line)}
.qa-h{margin:0;font-weight:400}
.qa-btn{width:100%;display:grid;grid-template-columns:auto auto 1fr auto;gap:1rem;align-items:center;
  text-align:left;background:none;border:0;padding:1.35rem .25rem;cursor:pointer;color:inherit;transition:background .2s}
/* Numeral from a counter, not markup — see .q-list note in the 2026-08-20 handover. */
.qa-btn:before{content:counter(qa,decimal-leading-zero);font-size:.72rem;font-weight:600;
  letter-spacing:.14em;color:var(--muted);min-width:1.6rem}
.qa-btn:hover{background:rgba(253,254,253,.55)}
.qa-sq{width:8px;height:8px;display:block;background:var(--gold);transition:transform .4s cubic-bezier(.2,.7,.2,1)}
.qa-btn[aria-expanded="true"] .qa-sq{transform:rotate(45deg) scale(1.25)}
.qa-q{font-family:var(--serif);font-size:clamp(1.2rem,2vw,1.6rem);line-height:1.15;letter-spacing:-.015em;text-wrap:pretty}
.qa-ico{position:relative;width:34px;height:34px;border:1px solid var(--line);border-radius:999px;display:inline-block;flex:none}
.qa-ico:before,.qa-ico:after{content:"";position:absolute;top:50%;left:50%;width:11px;height:1.5px;
  background:var(--ink);transform:translate(-50%,-50%)}
.qa-ico:after{transform:translate(-50%,-50%) rotate(90deg);
  transition:transform .4s cubic-bezier(.2,.7,.2,1),opacity .3s}
.qa-btn[aria-expanded="true"] .qa-ico:after{transform:translate(-50%,-50%) rotate(0deg);opacity:0}

/* 0fr→1fr animates height without measuring a pixel value in JS.
   State class is .is-expanded, NOT .is-open: an unscoped `.is-open` rule already
   exists above for the group roster's availability badge, and reusing the name
   painted a green wash across every open panel. */
.qa-panel{display:grid;grid-template-rows:0fr;opacity:0;
  transition:grid-template-rows .5s cubic-bezier(.2,.7,.2,1),opacity .4s cubic-bezier(.2,.7,.2,1)}
.qa-panel.is-expanded{grid-template-rows:1fr;opacity:1}
.qa-panel-in{overflow:hidden}
/* Without JS every answer must still be readable. */
.no-js .qa-panel{grid-template-rows:1fr;opacity:1}


.qa>li.reveal:nth-child(2){transition-delay:.09s}
.qa>li.reveal:nth-child(3){transition-delay:.18s}
.qa>li.reveal:nth-child(4){transition-delay:.27s}
.qa>li.reveal:nth-child(5){transition-delay:.36s}
.qa>li.reveal:nth-child(6){transition-delay:.45s}

/* Reuses the .terms-card shell; only width, inset marks and the two-column
   footer differ. */
.standard-card{max-width:900px;margin:clamp(3rem,6vw,5rem) auto 0}
.standard-card .frame-corner{width:26px;height:26px}
.standard-card .frame-corner.tl{top:14px;left:14px;border-width:2px 0 0 2px}
.standard-card .frame-corner.br{right:14px;bottom:14px;border-width:0 2px 2px 0}
.std-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));
  gap:clamp(1.5rem,4vw,3rem);align-items:end}
.standard-card .mini-kicker{color:var(--muted);margin:0 0 1rem}
.standard-card h3{font-family:var(--serif);font-weight:400;font-size:clamp(1.9rem,2.8vw,2.4rem);
  line-height:1.1;letter-spacing:-.02em;margin:0 0 1rem;max-width:28ch;text-wrap:pretty}
.standard-card h3+p{margin:0;max-width:52ch;color:var(--muted)}
/* Brad, 2026-08-21: the reassurance line centres under the button rather than
   ranging left off its edge. Matches .hero-act, which the hero handoff centres. */
.standard-act{display:flex;flex-direction:column;align-items:center;gap:.9rem}
.standard-act span{font-size:.88rem;color:var(--muted);text-align:center}

@media(max-width:680px){
  .qa-btn{grid-template-columns:auto auto 1fr auto;gap:.7rem;padding:1.15rem .2rem}

  .standard-act .button{width:100%;text-align:center}
  /* .std-note keeps the desktop 3rem right padding: the inset corner mark
     occupies the bottom-right 40px, and 2.4rem cleared it by under 2px. */
}

/* #answers moved onto the sky ground 2026-08-20, once #groups was removed and
   stopped forcing it to paper — this is the ground Brad's artboard specified.
   On sky the house hairline is rgba(9,34,41,.16), not --line (which is drawn
   for paper and nearly vanishes here). Same rule the .z-row / .cta-band use. */
.sky-pass .qa,.sky-pass .qa>li{border-color:rgba(9,34,41,.16)}
.sky-pass .qa-ico,.sky-pass .qa-all{border-color:rgba(9,34,41,.22)}

.sky-pass .qa-btn:hover{background:rgba(253,254,253,.6)}

/* --- 2026-08-20 copy round: hero CTA stack, new sections ------------------- */

.sb-cta .button{margin-left:0}


.not-list b:before{content:"";width:8px;height:8px;border:1.5px solid rgba(9,34,41,.34);flex:none}
.not-list li>:not(b):not(span){grid-column:2}


/* Six-question panels now carry one body of copy, not a two-card comparison.
   .qa-most / .qa-ours CSS above is left live but unused. */
.qa-body{padding:.4rem .25rem 1.8rem clamp(.25rem,6vw,3.9rem)}
.qa-body p{margin:0;max-width:74ch;font-size:1.02rem;line-height:1.62;color:var(--muted)}
@media(max-width:680px){

  .sb-cta .button{width:100%;text-align:center}
  .qa-body{padding-left:.25rem}
}

/* Mobile menu CTA. The header's own .header-cta is a grid sibling of <nav>, so it
   cannot be moved inside the dropdown with CSS alone; this is a second link that
   only ever renders in the open mobile menu. The nav's existing click handler
   closes the menu on any <a>, so tapping it also dismisses the panel. */
.nav-cta{display:none}
@media(max-width:1020px){
  .site-header.open nav .nav-cta{display:inline-flex;justify-content:center;text-align:center;
    border-bottom:0;border-radius:999px;padding:.95rem 1.5rem;margin:1.1rem .4rem .35rem}
}

/* H1 emphasis: bold removed 2026-08-20 at Brad's request, so the phrase is now a
   plain <em> and picks up the shared `h1 em` rule — real Libre Caslon Text italic
   400 at the .94em optical correction. No special case, no synthesized weight
   anywhere on the page, and the house closing-italic signature is restored on the
   H1. Libre Caslon Text 700 was dropped from the font request with it. */


/* --- #websites visual: Willowmere composition (2026-08-21) -----------------
   Replaces the abstract .site-sheet mock. The image column is widened from
   1fr to 1.15fr (Brad's option B) because the source is a 1600px stage — at the
   original 1fr it rendered at 35% and the device screens turned to mush.
   .site-sheet CSS is left live but unused, house practice. */
.ed-row.ed-wide{grid-template-columns:.79fr 1.21fr;align-items:start;gap:clamp(2rem,4vw,4rem)}
.wm-visual{margin:0}
.wm-visual img{width:100%;height:auto;border-radius:var(--rad-img);
  box-shadow:0 28px 64px rgba(0,0,0,.34),0 6px 18px rgba(0,0,0,.22)}
@media(max-width:1020px){
  .ed-row.ed-wide{grid-template-columns:1fr}
}

/* Case-study column: tighter than the standard .ed-text so the copy block and the
   mockup end up close in height. Measured, not guessed — see HANDOVER. */
.ed-wide .ed-text h2{font-size:clamp(2.15rem,3.1vw,2.95rem);line-height:1.04;margin-bottom:1.5rem;max-width:15ch}

.ed-wide .fact-stack li{padding:1.15rem 0}
.ed-wide .fact-stack b{font-size:1.3rem}
.ed-wide .fact-stack span{margin-top:.38rem;font-size:.94rem;line-height:1.55}

/* Real screenshots inside a .slot. Sits over the gradient placeholder and under
   the gold corner marks, which stay on top as brand furniture. */
.slot-shot{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  border-radius:inherit;display:block;z-index:1}
.slot .frame-corner{z-index:2}

/* A .slot that holds a real screenshot becomes the zoom trigger. Placeholder
   slots stay plain <div>s — there is nothing to enlarge. Button reset only;
   .slot keeps its own gradient, radius and aspect-ratio. */
.slot.is-zoomable{border:0;padding:0;margin:0;font:inherit;color:inherit;
  cursor:zoom-in;display:block;width:100%;text-align:inherit;-webkit-appearance:none;appearance:none}
.slot.is-zoomable .slot-shot{transition:transform .35s cubic-bezier(.2,.7,.2,1)}
.slot.is-zoomable:hover .slot-shot,.slot.is-zoomable:focus-visible .slot-shot{transform:scale(1.03)}

/* --- #found: search-journey graphic (design_handoff_seo_section) -----------
   Replaces the old headline + .fact-stack. All values from the handoff, mapped
   onto existing tokens — no new hues. .fact-stack CSS stays; used elsewhere. */
.seo-section{padding:clamp(78px,10vh,116px) clamp(20px,4vw,56px)}
.seo-head{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));
  gap:clamp(24px,4vw,64px);align-items:end;max-width:1240px;margin:0 auto clamp(46px,6vh,72px)}
.seo-head h2{margin:0}
.seo-lead{margin:0;font-size:1.02rem;color:var(--muted-dark);max-width:52ch;text-wrap:pretty}

.seo-searchrow{display:flex;align-items:flex-end;max-width:1240px;margin:0 auto 34px}
.seo-field-wrap{flex:1 1 420px;max-width:52ch}
.seo-minilabel{display:flex;align-items:center;gap:.7rem;margin:0 0 .9rem;font-size:.62rem;
  font-weight:600;text-transform:uppercase;letter-spacing:.2em;color:rgba(159,184,189,.7)}
.seo-minilabel span{width:7px;height:7px;background:var(--gold);flex:none}
/* 10px, deliberately NOT 999px — a pill would read as a button. */
.seo-field{display:flex;align-items:center;gap:.95rem;padding:.95rem 1.15rem;
  border:1px solid rgba(255,255,255,.34);border-radius:10px;background:rgba(255,255,255,.1);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.11),0 14px 34px rgba(0,0,0,.28)}
.seo-mag{position:relative;width:20px;height:20px;flex:none}
.seo-mag span:first-child{position:absolute;inset:0;width:15px;height:15px;
  border:1.5px solid rgba(232,77,56,.85);border-radius:50%}
.seo-mag span:last-child{position:absolute;left:12.5px;top:12.5px;width:9px;height:1.5px;
  background:rgba(232,77,56,.85);transform:rotate(45deg);transform-origin:0 50%}
.seo-query{display:flex;align-items:center;overflow:hidden;min-height:1.7em;
  font-family:var(--serif-i);font-style:italic;font-size:clamp(1.15rem,1.9vw,1.6rem);
  line-height:1.2;letter-spacing:-.02em;white-space:nowrap;color:var(--paper)}
.seo-caret{width:3px;height:1.35em;background:var(--gold);flex:none;
  transform:translateY(.22em);margin-left:.18rem;animation:ffcaret 1s steps(1,end) infinite}
@keyframes ffcaret{0%,45%{opacity:1}55%,100%{opacity:0}}

.seo-path{position:relative;max-width:1240px;margin:0 auto}
.seo-connector{position:absolute;left:0;top:-35px;width:1px;height:35px;background:rgba(255,255,255,.28)}
.seo-rule{position:relative;height:1px;background:rgba(255,255,255,.16)}
/* Full width, revealed by clip-path rather than an animated width. The stage
   targets are calc() expressions with a clamped gap, so scaleX cannot express
   them as a constant — clip-path keeps the exact geometry and is paint-only. */
.seo-fill{position:absolute;left:0;top:0;height:1px;width:100%;background:var(--gold);
  clip-path:inset(0 100% 0 0);
  transition:clip-path .72s cubic-bezier(.2,.7,.2,1)}
/* Fixed 4 tracks, never auto-fit — an auto-fit floor wraps stage 04 and breaks the path. */
.seo-stages{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  column-gap:clamp(16px,2.1vw,32px);row-gap:44px}
.seo-stage{position:relative;border-left:1px solid rgba(255,255,255,.12);padding-top:34px;
  padding-left:clamp(14px,1.5vw,22px);padding-right:clamp(10px,1.4vw,26px)}
.seo-stage:last-child{padding-right:0}
.seo-node{position:absolute;left:-4px;top:-4px;width:9px;height:9px;
  background:rgba(255,255,255,.24);transition:background .5s ease}
.seo-num{margin:0 0 .5rem;font-size:.78rem;font-weight:600;letter-spacing:.14em;
  color:rgba(255,255,255,.22);transition:color .5s ease}
.seo-h{font-family:var(--serif);font-weight:400;font-size:clamp(1.2rem,1.65vw,1.58rem);
  line-height:1.1;letter-spacing:-.025em;margin:0 0 .6rem;color:rgba(159,184,189,.55);
  transition:color .5s ease}
.seo-sub{margin:0;font-size:.86rem;color:var(--muted-dark);text-wrap:pretty;opacity:.34;
  transition:opacity .5s ease}
/* Target is a fixed 62px, so scaleX gives an identical result with no layout. */
.seo-bar{display:block;width:62px;height:2px;background:var(--gold);margin-top:1.1rem;
  transform:scaleX(0);transform-origin:left center;
  transition:transform .6s cubic-bezier(.2,.7,.2,1)}
.seo-stage.is-on .seo-node{background:var(--gold)}
.seo-stage.is-on .seo-num{color:var(--gold)}
.seo-stage.is-on .seo-h{color:var(--paper)}
.seo-stage.is-on .seo-sub{opacity:1}
.seo-stage.is-on[data-stage="3"] .seo-h{color:var(--gold)}
.seo-stage.is-on .seo-bar{transform:scaleX(1)}

@media(max-width:700px){
  /* Path turns vertical: the column hairline plus each node carries it instead. */
  .seo-stages{grid-template-columns:1fr;row-gap:30px}
  .seo-stage{padding-top:4px}
  .seo-rule,.seo-connector{display:none}
  .seo-searchrow{margin-bottom:26px}
}
@media(prefers-reduced-motion:reduce){.seo-caret{animation:none}}

/* --- #behind: the disciplines stepper (design_handoff_disciplines) ---------
   Six states driven by [data-step] on the section. Every layer visibility rule
   below is transcribed from the prototype's own predicates:
     plan = step 0 · words = step>=1 · page = step>=2
     search = step 3 · priv = step 4 · grow = step 5
   ⚠️ The section stays on PAPER and only the stage panel takes the sky ground.
   The handoff put the whole thing on #dbeef2, but #answers above is already sky
   and two sky neighbours breaks the house alternation. */
.dsc-section{padding-bottom:clamp(90px,12vh,150px)}
.dsc-intro{max-width:1240px;margin:0 auto}
.dsc-intro h2{max-width:16ch;margin-bottom:1.3rem}
.dsc-stand{margin:0;font-size:clamp(1.1rem,1.7vw,1.35rem);line-height:1.45;color:#274850;max-width:52ch}

.dsc-stage{display:grid;grid-template-columns:repeat(auto-fit,minmax(330px,1fr));
  gap:clamp(28px,5vw,72px);align-items:center;min-height:min(700px,80vh);
  max-width:1240px;margin:clamp(38px,6vh,64px) auto 0;background:var(--oxwash);
  padding:clamp(22px,3.4vw,44px);border-radius:var(--rad)}
.dsc-copy{display:flex;flex-direction:column;gap:clamp(18px,3.4vh,38px)}
.dsc-meta{display:flex;align-items:center;justify-content:space-between;gap:1rem;margin:0}
.dsc-meta p{margin:0;display:flex;align-items:center;gap:.8rem;font-size:.68rem;font-weight:600;
  text-transform:uppercase;letter-spacing:.16em;color:var(--muted)}
/* rule belongs to the label only — the counter also contains a <span> */
.dsc-meta>p:first-child span{width:28px;height:2px;background:var(--gold)}
.dsc-counter{font-variant-numeric:tabular-nums}
/* one arrow glyph, mirrored for Prev */
[data-dsc-prev] svg{transform:scaleX(-1)}

/* All six titles stack in one box so the column never changes height.
   Stacked with grid, not absolute positioning. The old version made every panel
   `position:absolute; inset:0` and let :first-child size the box — so the column
   was as tall as CARD 01 and any longer card silently overflowed it. Brad's
   2026-08-21 card-06 rewrite ran 22px past the bottom and into the rail. Grid
   sizes the box to the TALLEST panel automatically, at every viewport, so copy
   can change without anyone having to remember this. */
.dsc-titles{display:grid;min-height:clamp(230px,34vh,320px)}
.dsc-title{grid-area:1/1;align-self:start;opacity:0;pointer-events:none;transform:translateY(22px);
  transition:opacity .5s cubic-bezier(.2,.7,.2,1),transform .55s cubic-bezier(.2,.7,.2,1)}
.dsc-num{margin:0 0 .4rem;font-family:var(--serif);font-size:clamp(2.4rem,5vw,4rem);
  line-height:1;color:var(--muted)}
.dsc-title h3{font-family:var(--serif);font-weight:400;font-size:clamp(2.3rem,5.2vw,4.4rem);
  line-height:.96;letter-spacing:-.04em;margin:0 0 1.7rem}
.dsc-body{margin:0;font-size:clamp(1.25rem,2vw,1.7rem);line-height:1.35;color:#274850;max-width:30ch}
.dsc-rail{list-style:none;display:grid;grid-template-columns:repeat(6,minmax(0,1fr));
  gap:.7rem .5rem;margin:0;padding:0}
.dsc-rail button{display:block;width:100%;padding:0;border:0;background:none;cursor:pointer;text-align:left}
.dsc-bar{display:block;width:100%;height:3px;background:rgba(9,34,41,.22);transition:background .45s ease}
.dsc-lab{display:block;margin-top:.5rem;font-family:var(--serif);font-size:clamp(.85rem,1.2vw,1.35rem);
  color:var(--muted);transition:color .45s ease}
.dsc-controls{display:flex;align-items:center;gap:1.1rem}
.dsc-btn{display:grid;place-items:center;width:72px;height:72px;flex:none;border:1.5px solid var(--ink);
  background:none;border-radius:0;color:var(--ink);cursor:pointer;padding:0;
  transition:background .25s ease,color .25s ease}
.dsc-btn[disabled]{opacity:.3;cursor:default}
.dsc-next:not([disabled]){background:var(--gold);border-color:var(--gold);color:#07181d}
.dsc-hint{margin:0;font-size:clamp(.8rem,1.1vw,.95rem);font-weight:600;text-transform:uppercase;
  letter-spacing:.14em;color:var(--muted)}

.dsc-figure{display:flex;justify-content:center}
.dsc-frame{position:relative;width:100%;max-width:620px;background:rgba(253,254,253,.42);
  border:1px solid rgba(9,34,41,.12);padding:clamp(10px,2vw,22px)}
.dsc-frame .frame-corner{width:16px;height:16px;border-color:var(--gold-deep)}
.dsc-frame .frame-corner.tl{top:10px;left:10px;border-width:1.5px 0 0 1.5px}
.dsc-frame .frame-corner.br{right:10px;bottom:10px;border-width:0 1.5px 1.5px 0}
.dsc-cap{margin:0 0 clamp(8px,1.4vw,16px);padding-left:22px;font-size:clamp(.72rem,1vw,.82rem);
  font-weight:600;text-transform:uppercase;letter-spacing:.14em;line-height:1.3;color:var(--muted);
  display:none}
.dsc-art svg{display:block;width:100%;height:auto;aspect-ratio:492/552;overflow:hidden}
.dsc-art [data-l]{opacity:0;
  transition:opacity .55s cubic-bezier(.2,.7,.2,1),transform .65s cubic-bezier(.2,.7,.2,1),
             stroke-dashoffset 1s cubic-bezier(.2,.7,.2,1)}

/* ---- per-step state ---- */
.dsc-section[data-step="0"] .dsc-title[data-t="0"],
.dsc-section[data-step="1"] .dsc-title[data-t="1"],
.dsc-section[data-step="2"] .dsc-title[data-t="2"],
.dsc-section[data-step="3"] .dsc-title[data-t="3"],
.dsc-section[data-step="4"] .dsc-title[data-t="4"],
.dsc-section[data-step="5"] .dsc-title[data-t="5"]{opacity:1;transform:none;pointer-events:auto}
.dsc-section[data-step="1"] .dsc-title[data-t="0"],
.dsc-section[data-step="2"] .dsc-title[data-t="0"],.dsc-section[data-step="2"] .dsc-title[data-t="1"],
.dsc-section[data-step="3"] .dsc-title[data-t="0"],.dsc-section[data-step="3"] .dsc-title[data-t="1"],.dsc-section[data-step="3"] .dsc-title[data-t="2"],
.dsc-section[data-step="4"] .dsc-title[data-t="0"],.dsc-section[data-step="4"] .dsc-title[data-t="1"],.dsc-section[data-step="4"] .dsc-title[data-t="2"],.dsc-section[data-step="4"] .dsc-title[data-t="3"],
.dsc-section[data-step="5"] .dsc-title[data-t="0"],.dsc-section[data-step="5"] .dsc-title[data-t="1"],.dsc-section[data-step="5"] .dsc-title[data-t="2"],.dsc-section[data-step="5"] .dsc-title[data-t="3"],.dsc-section[data-step="5"] .dsc-title[data-t="4"]{transform:translateY(-22px)}
.dsc-section[data-step="0"] .dsc-cap[data-c="0"],
.dsc-section[data-step="1"] .dsc-cap[data-c="1"],
.dsc-section[data-step="2"] .dsc-cap[data-c="2"],
.dsc-section[data-step="3"] .dsc-cap[data-c="3"],
.dsc-section[data-step="4"] .dsc-cap[data-c="4"],
.dsc-section[data-step="5"] .dsc-cap[data-c="5"]{display:block}
.dsc-rail li.is-on .dsc-bar{background:var(--gold)}
.dsc-rail li.is-on .dsc-lab{color:var(--ink)}
.dsc-rail li.is-done .dsc-bar{background:var(--gold-deep)}
.dsc-rail li.is-done .dsc-lab{color:#3d5b63}

/* Layer visibility, straight from the prototype's predicates. */
.dsc-section[data-step="0"] [data-l="L0"],
.dsc-section[data-step="0"] [data-l="L0b"],
.dsc-section[data-step="0"] [data-l="L0c"],
.dsc-section[data-step="0"] [data-l="L0m"]{opacity:1;stroke-dashoffset:0}
.dsc-section[data-step="1"] [data-l="L1"]{opacity:1;stroke-dashoffset:0}
.dsc-section[data-step="2"] [data-l="L1"],
.dsc-section[data-step="3"] [data-l="L1"],
.dsc-section[data-step="4"] [data-l="L1"],
.dsc-section[data-step="5"] [data-l="L1"]{opacity:.12;stroke-dashoffset:0}
.dsc-section[data-step="1"] [data-l="L2m"]{opacity:1}
.dsc-section[data-step="1"] [data-l="L2fill"],
.dsc-section[data-step="2"] [data-l="L2fill"],
.dsc-section[data-step="3"] [data-l="L2fill"],
.dsc-section[data-step="4"] [data-l="L2fill"],
.dsc-section[data-step="5"] [data-l="L2fill"]{opacity:1;transform:scale(1);transform-origin:280px 280px}
.dsc-section[data-step="2"] [data-l="L2"],.dsc-section[data-step="3"] [data-l="L2"],
.dsc-section[data-step="4"] [data-l="L2"],.dsc-section[data-step="5"] [data-l="L2"],
.dsc-section[data-step="2"] [data-l="L2p"],.dsc-section[data-step="3"] [data-l="L2p"],
.dsc-section[data-step="4"] [data-l="L2p"],.dsc-section[data-step="5"] [data-l="L2p"],
.dsc-section[data-step="2"] [data-l="L2c"],.dsc-section[data-step="3"] [data-l="L2c"],
.dsc-section[data-step="4"] [data-l="L2c"],.dsc-section[data-step="5"] [data-l="L2c"]{opacity:1;transform:none}
/* README: L3m is step 03 only. The prototype's own expression also shows it on
   05 and 06 — that is a bug in the reference, not the intent. */
.dsc-section[data-step="2"] [data-l="L3m"]{opacity:1;transform:none}
.dsc-section[data-step="3"] [data-l="L3"],
.dsc-section[data-step="3"] [data-l="L3c"]{opacity:1;stroke-dashoffset:0}
.dsc-section[data-step="3"] [data-l="L3bar"],
.dsc-section[data-step="3"] [data-l="L3n"]{opacity:1;transform:none}
.dsc-section[data-step="4"] [data-l="L4"]{opacity:1;transform:scale(1);transform-origin:280px 280px}
.dsc-section[data-step="4"] [data-l="L4lock"]{opacity:1;transform:none}
.dsc-section[data-step="5"] [data-l="L5"]{opacity:1;transform:scale(1);transform-origin:280px 300px}
.dsc-section[data-step="5"] [data-l="L5r"]{opacity:1;transform:scale(1);transform-origin:280px 300px}
.dsc-section[data-step="5"] [data-l="L5b"]{opacity:1;transform:none}
/* inactive entry offsets */
[data-l="L0m"],[data-l="L2m"],[data-l="L3m"]{transform:translateX(-8px)}
[data-l="L2fill"]{transform:scale(.9);transform-origin:280px 280px}
[data-l="L2"]{transform:scale(.9) translateY(12px);transform-origin:280px 280px}
[data-l="L2p"]{transform:scale(.86);transform-origin:381px 206px}
[data-l="L2c"]{transform:translateY(26px)}
[data-l="L3bar"]{transform:translateY(30px)}
[data-l="L4"]{transform:scale(1.07);transform-origin:280px 280px}
[data-l="L4lock"]{transform:translateY(-14px)}
[data-l="L5"]{transform:scale(.74);transform-origin:280px 300px}
[data-l="L5r"]{transform:scale(.82);transform-origin:280px 300px}
[data-l="L5b"]{transform:translateY(40px)}
[data-l="L0"],[data-l="L1"],[data-l="L3"],[data-l="L3c"]{stroke-dashoffset:1}

/* the three looping motions, all slow and small */
.ff-lock{animation:ffLock 3.8s cubic-bezier(.4,0,.2,1) infinite;transform-box:view-box}
.ff-radiate{animation:ffRad 3.2s cubic-bezier(.4,0,.2,1) infinite;transform-box:view-box;transform-origin:280px 300px}
.ff-ring{animation:ffRing 4.6s cubic-bezier(.4,0,.2,1) infinite;transform-box:view-box;transform-origin:280px 300px}
@keyframes ffLock{0%,100%{transform:translateY(0)}50%{transform:translateY(-3px)}}
@keyframes ffRad{0%,100%{transform:scale(1)}50%{transform:scale(1.07)}}
@keyframes ffRing{0%,100%{transform:scale(1);opacity:.8}50%{transform:scale(1.05);opacity:1}}

@media(max-width:750px){
  .dsc-stage{grid-template-columns:1fr}
  .dsc-titles{min-height:clamp(210px,32vh,280px)}
  .dsc-btn{width:60px;height:60px}
}
@media(prefers-reduced-motion:reduce){
  .dsc-title,.dsc-art [data-l],.dsc-bar,.dsc-lab,.dsc-btn{transition:none!important}
  .ff-lock,.ff-radiate,.ff-ring{animation:none!important}
}

/* Featured slot holds the Meg Simmons composition. Re-rendered 2026-08-21 at
   1440x984 — the canvas was grown 64px so the tablet is not flush against the
   bottom edge. Overriding the ratio shows it whole instead of cropping with
   object-fit. Bump both this and the img width/height together if it changes. */
.slot-meg{aspect-ratio:1440/984}


/* Intro callout above the case body — larger than body, quieter than the head. */
.case-callout{font-size:clamp(1.08rem,1.5vw,1.28rem);line-height:1.45;color:var(--ink);
  max-width:44ch;margin:0 0 1.4rem}
.case-side .mini-kicker{color:var(--muted)}

/* --- #services: "What we make" (design_handoff_services_section) ------------
   Three service cards, each opening on a miniature "artifact" built from divs.

   THE SCALING PROBLEM, and why `--u` exists. The handoff sizes every mock
   internal in `rem` (.24rem–.8rem) and its own README flags the consequence:
   the 16/11 frame grows and shrinks with the card, but fixed rem type does not,
   so the miniature falls apart away from the desktop 3-up width. A single-column
   card at 640px gets a mock twice the reference size with 4px type still in it.
   So the frame is a container and `--u` is "one rem AT the reference width" —
   every internal length is `calc(N * var(--u))`, i.e. the handoff's own rem
   numbers, and the whole miniature scales as one. Calibrated so 1u = 16px when
   the mock is 324px wide, which is what the 1240px container yields at 3-up.
   Browsers without container queries keep the literal rem values.

   The five mock-chrome hexes below are NOT brand tokens and must not be promoted
   to :root — they are browser/UI furniture inside the miniatures, and the handoff
   was wrong that they already existed in this sheet. --------------------------- */
.svc-section{--m-chrome:#f7faf9;--m-hair:#e9f0ef;--m-hair-2:#eef3f2;--m-line:#e3ebea;--m-bar:#1e3d45}
/* The measure is capped at 64ch, but `.section>.lead` (§95) also sets
   margin-inline:auto — which centred that narrow box inside the 1240px
   container instead of leaving it on the container's left edge, so the lead sat
   indented from the h2 above it. Pin the left margin to the same offset the
   1240px box resolves to and both edges line up at every width. Same idiom the
   footer uses. */
.svc-section>.lead{max-width:64ch;margin-bottom:clamp(3rem,6vh,4.5rem);
  margin-left:max(0px,calc((100% - 1240px) / 2));margin-right:auto}
.svc-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:1.4rem;
  max-width:1240px;margin:0 auto}

.svc{background:var(--white);color:var(--ink);border-radius:28px;padding:clamp(.9rem,1.4vw,1.4rem)}
.svc h3{font-family:var(--serif);font-weight:400;font-size:clamp(1.7rem,2.3vw,2.2rem);
  letter-spacing:-.02em;margin:1.6rem 0 .8rem;padding-left:.2rem}
.svc>p{font-size:1rem;line-height:1.6;color:var(--muted);margin:0 0 1.4rem;padding-left:.2rem}
/* The handoff wants two columns, one when the card is narrow — never three. But the
   labels are white-space:nowrap by design, so a two-column grid that does not fit
   does not wrap: it pushes the card wider and overflows the page. Measured, the
   widest label ("Strategy & message") is 9.6rem, so two columns need 9.6+9.6+1.2 =
   20.4rem (326px) of card content. Re-measure if a label is ever lengthened.
   The card is the thing to ask, not the viewport — `auto-fit` on .svc-row means the
   two are different questions (a 700px viewport gives ONE 644px card; a 768px
   viewport gives two 342px ones). Hence the container query.
   The auto-fit base is the fallback for browsers without @container: it can reach
   three columns on a very wide card, which is untidy but never overflows. */
.svc-list{list-style:none;margin:0;padding:0 0 .4rem .2rem;display:grid;
  grid-template-columns:repeat(auto-fit,minmax(9.6rem,1fr));gap:.8rem 1.2rem}
@supports (container-type:inline-size){
  .svc{container:svc / inline-size}
  .svc-list{grid-template-columns:1fr}
  @container svc (min-width:330px){
    .svc-list{grid-template-columns:1fr 1fr}
  }
}
.svc-list li{display:flex;align-items:center;gap:.65rem;font-size:.95rem;font-weight:500;white-space:nowrap}
/* Square, not a dot — the marker echoes the .kicker rule, not a bullet. */
.svc-list li:before{content:"";width:8px;height:8px;background:var(--gold);flex:none}
.svc-well{background:var(--paper);border:1px solid var(--line);border-radius:18px;padding:clamp(.7rem,1.1vw,1.1rem)}

/* line-height:normal is load-bearing. The handoff's prototype page sets no body
   line-height, so every unstyled span in the mocks inherits `normal` (~1.2). This
   sheet sets body{line-height:1.55}, which silently grew every nav item, chip and
   footer cell and squeezed the mock's own photo — the crop visibly changed. Rows
   that set their own line-height keep it. */
.svc-mock{--u:1rem;line-height:normal;aspect-ratio:16/11;border-radius:10px;overflow:hidden;display:flex;flex-direction:column}
@supports (container-type:inline-size){
  .svc-mock{container-type:inline-size;--u:4.932cqw}
}
.svc-mock img{width:100%;height:100%;object-fit:cover}

/* ---- mock 1: a practice homepage ---- */
.svc-mock-site{background:var(--white);border:1px solid var(--m-line)}
.svc-mock-site .m-bar{display:flex;align-items:center;gap:calc(.5*var(--u));
  padding:calc(.5*var(--u)) calc(.6*var(--u));background:var(--m-chrome);border-bottom:1px solid var(--m-hair)}
.m-wordmark{font-family:var(--serif);font-size:calc(.42*var(--u));letter-spacing:.02em;color:var(--ink)}
.m-wordmark em{font-family:var(--serif-i);font-style:italic}
.m-nav{display:flex;gap:calc(.42*var(--u));margin-left:auto;font-size:calc(.3*var(--u));color:var(--muted);font-weight:500}
.m-tel{font-size:calc(.3*var(--u));color:var(--gold-deep);font-weight:600}
.m-btn{background:var(--m-bar);color:var(--white);font-size:calc(.28*var(--u));font-weight:600;
  padding:calc(.22*var(--u)) calc(.38*var(--u));border-radius:calc(.19*var(--u))}
.svc-mock-site .m-body{display:grid;grid-template-columns:1.15fr 1fr;gap:calc(.55*var(--u));padding:calc(.6*var(--u));flex:1;min-height:0}
.m-copy{display:flex;flex-direction:column;justify-content:center;gap:calc(.28*var(--u))}
.m-kicker{font-size:calc(.28*var(--u));font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--gold-deep)}
.m-head{font-family:var(--serif);font-size:calc(.72*var(--u));line-height:1.02;letter-spacing:-.02em}
.m-head em{font-family:var(--serif-i);font-style:italic}
.m-sub{font-size:calc(.3*var(--u));line-height:1.5;color:var(--muted)}
.m-cta{display:flex;align-items:center;gap:calc(.35*var(--u));margin-top:calc(.15*var(--u))}
.m-pill{background:var(--gold);color:#07181d;font-size:calc(.28*var(--u));font-weight:600;
  padding:calc(.28*var(--u)) calc(.45*var(--u));border-radius:99px;white-space:nowrap}
.m-note{font-size:calc(.26*var(--u));color:var(--muted);white-space:nowrap}
.m-shot{border-radius:calc(.38*var(--u));overflow:hidden;background:var(--oxwash)}
.m-shot img{object-position:76% 32%}
.m-strip{display:grid;grid-template-columns:repeat(3,1fr);background:var(--m-bar);color:var(--oxwash)}
.m-strip span{padding:calc(.34*var(--u)) calc(.4*var(--u));font-size:calc(.28*var(--u));
  font-weight:600;letter-spacing:.06em;text-transform:uppercase}
.m-strip span+span{border-left:1px solid var(--line-dark)}

/* ---- mock 2: a short-form video frame ---- */
.svc-mock-reel{background:var(--green);display:block}
.svc-mock-reel>video{display:block;width:100%;height:100%;object-fit:contain;background:var(--green)}


.m-caption-tag:before{content:"";width:calc(.31*var(--u));height:calc(.31*var(--u));background:var(--gold);flex:none}


.m-eyebrow:before{content:"";width:calc(1.37*var(--u));height:calc(.09*var(--u));background:var(--gold);flex:none}


.m-tags span:before{content:"";width:calc(.31*var(--u));height:calc(.31*var(--u));background:var(--gold);flex:none}

/* ---- mock 3: a search-results screen ------------------------------------
   THE FOCAL MOMENT. The other two cards are alive by nature — one is a rich
   page mock, one is a playing film — so this one read as the weak sibling:
   pale, flat, and hard to parse at card size. Two changes, and they are
   different jobs:

   VIBRANCY. The AI panel and the map both sat on --oxwash, so half the mock was
   one wash of the same pale blue with grey hairlines on top. They now carry
   their own tints, the results column is faintly tinted so the white result card
   has something to sit ON, and the skeletons are dark enough to actually read as
   competing results rather than as noise.

   MOTION. The service is "get found", and the sequence performs exactly that:
   the query is typed, results load, the practice RISES into the top slot, its
   rating fills, and the map pin drops. It is keyed off `.svc.visible`, which the
   existing IntersectionObserver already sets, so it costs no new JS and cannot
   run before the card is on screen. Once, never looped — a looping animation in
   a small card next to two other cards is noise, not authorship. ---------- */
.svc-mock-serp{background:var(--white);border:1px solid var(--m-line)}
.m-chrome{display:flex;align-items:center;gap:calc(.45*var(--u));padding:calc(.5*var(--u)) calc(.55*var(--u));
  background:var(--m-chrome);border-bottom:1px solid var(--m-hair)}
.m-dots{display:flex;gap:calc(.14*var(--u))}
.m-dots i{width:calc(.25*var(--u));height:calc(.25*var(--u));border-radius:50%;background:var(--line)}
.m-omni{position:relative;display:flex;align-items:center;gap:calc(.3*var(--u));flex:1;background:var(--white);
  border:1px solid var(--m-line);border-radius:99px;padding:calc(.22*var(--u)) calc(.45*var(--u));
  font-size:calc(.32*var(--u));color:var(--ink)}
/* content-box on purpose: the handoff draws a 6px circle with a 1.2px ring AROUND
   it. This sheet's global border-box would eat the ring into the 6px instead. */
.m-omni i{box-sizing:content-box;width:calc(.38*var(--u));height:calc(.38*var(--u));
  border:calc(.075*var(--u)) solid var(--ox);border-radius:50%;flex:none}
.m-caret{width:calc(.06*var(--u));height:calc(.42*var(--u));background:var(--gold);opacity:0;flex:none}
.m-serp{flex:1;display:grid;grid-template-columns:1.35fr 1fr;min-height:0}
.m-results{padding:calc(.55*var(--u));display:flex;flex-direction:column;gap:calc(.4*var(--u));
  border-right:1px solid var(--m-hair-2);background:#f7fafa}

.m-ai{background:#cfe6ef;border-radius:calc(.31*var(--u));padding:calc(.4*var(--u)) calc(.45*var(--u));
  display:flex;flex-direction:column;gap:calc(.2*var(--u))}
.m-ai-label{display:flex;align-items:center;gap:calc(.3*var(--u));font-size:calc(.24*var(--u));
  font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:#1d4550}
.m-ai-label:before{content:"";width:calc(.875*var(--u));height:calc(.075*var(--u));background:var(--gold);flex:none}
.m-ai-text{font-size:calc(.3*var(--u));line-height:1.45;color:#1d4550}

/* The winning result: white on the tinted column, with a weight the skeletons
   below it do not have. That contrast IS the point of the mock. */
.m-result{position:relative;background:var(--white);border:1px solid var(--line);
  border-radius:calc(.31*var(--u));padding:calc(.42*var(--u)) calc(.45*var(--u));
  display:flex;flex-direction:column;gap:calc(.22*var(--u));
  box-shadow:0 calc(.06*var(--u)) calc(.19*var(--u)) rgba(9,34,41,.07)}
.m-result-title{font-size:calc(.4*var(--u));font-weight:600;color:var(--ink);letter-spacing:-.01em}
.m-result-url{font-size:calc(.28*var(--u));color:var(--gold-deep)}
.m-result-meta{display:flex;align-items:center;gap:calc(.28*var(--u));font-size:calc(.28*var(--u));color:var(--muted);white-space:nowrap}
/* Stars fill left to right via a clipped overlay, so the row never reflows. */
.m-stars{position:relative;color:rgba(9,34,41,.16);font-size:calc(.3*var(--u));letter-spacing:.06em}
.m-stars:after{content:"★★★★★";position:absolute;inset:0;color:var(--gold);
  overflow:hidden;white-space:nowrap;width:0}

.m-skel{position:relative;display:flex;flex-direction:column;gap:calc(.22*var(--u));opacity:.75}
.m-skel i{height:calc(.19*var(--u));border-radius:99px;background:#dfe6e6}
.m-skel i:first-child{background:#cfd9d9}

.m-local{display:flex;flex-direction:column}
.m-map{flex:1;position:relative;overflow:hidden;min-height:0;
  background:linear-gradient(150deg,#dcecef 0%,#cfe4e8 100%)}
.m-map i{position:absolute;display:block}
.m-block{left:8%;top:12%;width:34%;height:26%;border-radius:calc(.12*var(--u));background:rgba(255,255,255,.42)}
.m-map-h1,.m-map-h2,.m-map-h3{left:-10%;width:120%;height:calc(.1*var(--u));background:rgba(16,45,53,.19)}
.m-map-h1{top:34%;transform:rotate(-9deg)}
.m-map-h2{top:66%;transform:rotate(6deg)}
.m-map-h3{top:12%;transform:rotate(-4deg);background:rgba(16,45,53,.11)}
.m-map-v1,.m-map-v2,.m-map-v3{top:-10%;width:calc(.1*var(--u));height:120%;background:rgba(16,45,53,.17)}
.m-map-v1{left:28%}
.m-map-v2{left:68%;background:rgba(16,45,53,.13)}
.m-map-v3{left:88%;background:rgba(16,45,53,.09)}
.m-ring{left:44%;top:38%;width:calc(.56*var(--u));height:calc(.56*var(--u));border-radius:50%;
  border:calc(.06*var(--u)) solid var(--gold);opacity:0;
  transform-origin:center;margin:calc(-.28*var(--u)) 0 0 calc(-.28*var(--u));
  left:calc(44% + .28*var(--u));top:calc(38% + .28*var(--u))}
.m-pin{left:44%;top:38%;width:calc(.56*var(--u));height:calc(.56*var(--u));background:var(--gold);
  border-radius:50% 50% 50% 0;transform:rotate(-45deg);box-shadow:0 2px 6px rgba(9,34,41,.3)}
.m-dot{width:calc(.31*var(--u));height:calc(.31*var(--u));border-radius:50%;background:rgba(16,45,53,.32)}
.m-dot1{left:22%;top:62%}
.m-dot2{left:74%;top:24%}
.m-card{padding:calc(.45*var(--u)) calc(.5*var(--u));display:flex;flex-direction:column;
  gap:calc(.28*var(--u));border-top:1px solid var(--m-hair-2)}
.m-card-name{font-size:calc(.34*var(--u));font-weight:600}
.m-card-meta{font-size:calc(.28*var(--u));color:var(--muted)}
.m-card-pills{display:flex;gap:calc(.25*var(--u));flex-wrap:wrap}
.m-card-pills span{background:#cfe6ef;color:var(--ink);font-size:calc(.26*var(--u));font-weight:600;
  padding:calc(.22*var(--u)) calc(.4*var(--u));border-radius:99px;white-space:nowrap}
.m-card-pills .is-call{background:var(--gold);color:#07181d}

/* ---- the sequence: query -> load -> rise -> rate -> locate ---------------
   Total 2.1s. Every step is transform/opacity/clip only, inside a 324px box. */
@keyframes mCaret{0%,45%{opacity:1}46%,100%{opacity:0}}
@keyframes mSweep{from{transform:translateX(-120%)}to{transform:translateX(240%)}}
@keyframes mRise{from{opacity:0;transform:translateY(calc(.5*var(--u)))}to{opacity:1;transform:none}}
/* ends at .75, not 1: these are the results that did NOT win. Sharing mRise
   pushed them to full opacity and they started competing with the card above. */
@keyframes mRiseDim{from{opacity:0;transform:translateY(calc(.5*var(--u)))}to{opacity:.75;transform:none}}
@keyframes mLand{0%{opacity:0;transform:translateY(calc(1.1*var(--u))) scale(.985)}
                 60%{opacity:1}100%{opacity:1;transform:none}}
@keyframes mEdge{0%,100%{box-shadow:0 calc(.06*var(--u)) calc(.19*var(--u)) rgba(9,34,41,.07)}
                 40%{box-shadow:0 0 0 calc(.09*var(--u)) rgba(232,77,56,.5)}}
@keyframes mStars{from{width:0}to{width:100%}}
@keyframes mDrop{0%{opacity:0;transform:rotate(-45deg) translate(calc(-.9*var(--u)),calc(-.9*var(--u)))}
                 70%{opacity:1}100%{opacity:1;transform:rotate(-45deg)}}
@keyframes mPing{0%{opacity:.9;transform:scale(.3)}70%{opacity:0}100%{opacity:0;transform:scale(2.6)}}

.svc-mock-serp .m-ai,.svc-mock-serp .m-result,.svc-mock-serp .m-skel,
.svc-mock-serp .m-pin,.svc-mock-serp .m-card-pills span{opacity:0}
/* Retimed to land at ~1.55s. The first cut ran 2.4s and a normal scroll speed
   carried the card past the payoff — the pin and the rating are the whole point,
   so they cannot be last in a two-and-a-half second queue. */
.svc.visible .m-caret{animation:mCaret .34s steps(1) 3 both}
.svc.visible .m-skel{animation:mRiseDim .34s cubic-bezier(.16,1,.3,1) .12s both}
/* a light sweep across the placeholder rows reads as "still loading" */
.svc.visible .m-skel:after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(100deg,transparent 20%,rgba(255,255,255,.85) 50%,transparent 80%);
  animation:mSweep .72s ease-in-out .24s 1 both}
.svc.visible .m-ai{animation:mRise .4s cubic-bezier(.16,1,.3,1) .32s both}
.svc.visible .m-result{animation:mLand .52s cubic-bezier(.16,1,.3,1) .66s both,
                                 mEdge .6s ease .9s both}
.svc.visible .m-stars:after{animation:mStars .4s cubic-bezier(.16,1,.3,1) 1.04s both}
.svc.visible .m-pin{animation:mDrop .5s cubic-bezier(.16,1,.3,1) .98s both}
.svc.visible .m-ring{animation:mPing .7s ease-out 1.32s both}
.svc.visible .m-card-pills span{animation:mRise .32s cubic-bezier(.16,1,.3,1) both}
.svc.visible .m-card-pills span:nth-child(1){animation-delay:1.20s}
.svc.visible .m-card-pills span:nth-child(2){animation-delay:1.28s}
.svc.visible .m-card-pills span:nth-child(3){animation-delay:1.36s}

/* Reduced motion: the mock still ARRIVES at the finished state — the result card
   on top, stars filled, pin placed — it just does not perform getting there. */
@media (prefers-reduced-motion:reduce){
  .svc-mock-serp .m-ai,.svc-mock-serp .m-result,.svc-mock-serp .m-skel,
  .svc-mock-serp .m-pin,.svc-mock-serp .m-card-pills span{opacity:1}
  .svc.visible .m-caret,.svc.visible .m-skel:after,.svc.visible .m-ring{animation:none;opacity:0}
  .svc.visible .m-ai,.svc.visible .m-result,
  .svc.visible .m-pin,.svc.visible .m-card-pills span{animation:none;opacity:1;transform:none}
  .svc.visible .m-skel{animation:none;opacity:.75;transform:none}
  .svc.visible .m-pin{transform:rotate(-45deg)}
  .svc.visible .m-stars:after{animation:none;width:100%}
}


/* --- Hero, v2 (design_handoff_homepage_hero) --------------------------------
   Ambient video bleeding in from the right behind a horizontal mask, text on
   ink in the left 65%, then a hard paper cut carrying the message and the CTA.

   TWO DELIBERATE DEPARTURES from the handoff, both because it was drawn as a
   standalone page and this is a page with eight sections under it:

   1. GUTTER. The handoff pads the hero with clamp(22px,5.55vw,80px) of its own.
      Here the band is full-bleed and the text sits in the SAME 1240px container
      every .section uses, so the H1 lines up with the kicker of #services below
      it. A private gutter would have put the hero 20-45px out of step with the
      whole rest of the page.

   2. H1 SIZE, re-derived — the handoff insists you do this rather than eyeball
      a cap, and changing the container changed the input. Its clamp assumed the
      column was 0.65*(viewport - 2*gutter), growing forever. Ours stops at
      0.65*1240 = 806px. Using its clamp(34px, 6.8vw - 11px, 104px) the longest
      line ("Build a Therapy Practice", measured at 8.87x the font-size in Libre
      Caslon Display at this tracking) would need 8.87*104 = 922px in an 806px
      column, and overflow at every width above ~1350px.
      Re-derived by MEASURING the rendered line at every width rather than by
      algebra — an early attempt did the algebra, got 6.2vw, and wrapped the
      headline at every width from 760 to 1280 because the column model was wrong.

      ⚠️ RE-MEASURED 2026-08-22 for the current copy: "You Deserve a Brand" /
      "Worthy of your" / "Therapy Practice", three hard-broken lines. The longest
      line is line 1 and the width ratio is now **7.558x** (it has been 8.879 and
      9.144 on earlier copy — the ratio is a property of the WORDS, so it moves
      every time the headline does). Largest font-size keeping the longest line at
      92% of the column, measured across 17 widths:
        vw   760   900  1100  1280  1350  1440+
        max 55.3  65.5  80.1  93.2  98.1   98.1
      7vw stays under that line the whole way and 94px caps it with ~4% to spare.
      At the previous 78px cap this copy filled only 73% of the column and read
      undersized. Nothing wraps now, even at 360px.
      If the headline copy changes AGAIN, re-run scripts against the rendered line
      and re-derive. Do not eyeball it. --- */
/* Resets the inherited .hero above the THERAPISTS marker, which is still the
   law-firms hero: its top padding left a strip of paper between the header and
   the ink band, and its text-align:center fought .hero-inner. Both are undone
   here rather than edited up there — that block is shared with law-firms. */
.hero{position:relative;padding:0;text-align:left}
.hero-band{position:relative;overflow:hidden;background:var(--green);color:#fff;padding:0 var(--pad)}
/* Brad, 2026-08-21: tighter top and bottom than the handoff's
   clamp(88px,11.5vw,186px) / clamp(80px,9.5vw,150px) — about a third off, so the
   band sits flush under the nav and does not float. */
.hero-inner{position:relative;z-index:2;max-width:1240px;margin:0 auto;
  width:100%;padding:clamp(58px,7.4vw,120px) 0 clamp(52px,6.2vw,98px);text-align:left}
.hero-inner>*{width:65%;max-width:65%}

.hero-eyebrow{display:flex;align-items:center;gap:12px;margin:0;
  font-size:clamp(10.5px,.95vw,13.5px);font-weight:600;letter-spacing:.15em;text-transform:uppercase;color:#fff}
.hero-eyebrow .dot{width:9px;height:9px;border-radius:50%;background:var(--gold);flex:none}
.hero h1{margin:26px 0 0;font-family:var(--serif);font-weight:400;
  font-size:clamp(34px,7vw,94px);line-height:1.04;letter-spacing:-.012em;color:#fff;text-wrap:pretty}
.hero h1 span{display:block}
.hero h1 span+span{margin-top:clamp(4px,.5vw,8px)}

.hero-trio{display:flex;align-items:stretch;gap:clamp(20px,2.6vw,40px);margin-top:clamp(34px,4.2vw,62px)}
.hero-trio>div{display:flex;flex-direction:column;gap:6px}
.hero-trio>div+div{border-left:1px solid rgba(255,255,255,.2);padding-left:clamp(20px,2.6vw,40px)}
.hero-trio b{font-family:var(--serif);font-weight:400;font-size:clamp(20px,2vw,30px);line-height:1.1;color:#fff}
/* .92 white and the 13px floor are the handoff's AA findings, not preferences:
   the third column sits where the video mask is only 0.3-0.5 alpha, and anything
   lighter or smaller measured below AA against moving footage. Do not "tidy". */
.hero-trio span{font-size:clamp(13px,1.05vw,15px);letter-spacing:.02em;color:rgba(255,255,255,.92)}

/* Video layer. The mask is the whole effect — the footage is all but invisible at
   the left edge and full strength from 90% rightward, so it emerges out of the ink
   instead of sitting in a box. The ink gradient on top reinforces the same ramp. */
.hero-video{position:absolute;inset:0;z-index:0;overflow:hidden;pointer-events:none;
  -webkit-mask-image:linear-gradient(to right,rgba(0,0,0,.05) 0%,rgba(0,0,0,.12) 40%,rgba(0,0,0,.3) 62%,rgba(0,0,0,.72) 78%,#000 90%);
  mask-image:linear-gradient(to right,rgba(0,0,0,.05) 0%,rgba(0,0,0,.12) 40%,rgba(0,0,0,.3) 62%,rgba(0,0,0,.72) 78%,#000 90%);
  animation:ffFade 3200ms ease 400ms both}
.hero-clip{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  filter:saturate(.72) contrast(1.02) brightness(.98);opacity:0;
  transition:opacity 4200ms cubic-bezier(.4,0,.3,1);will-change:transform,opacity}
.hero-clip.is-on{opacity:1}
/* Clip 1 is mirrored to put the subject on the RIGHT, inside the full-resolution
   zone. It is baked into its own keyframe because a plain transform would be
   overwritten by the breathe animation. */
/* One clip now — the dissolves are baked into the file. The mirror that used to
   live in ffBreatheFlip is baked in too (build-hero-reel.sh hflips clip 1), so
   this is the plain breathe.
   ⚠️ object-position is a GLOBAL framing for all five scenes. Do NOT retune it to
   fix one scene — that silently reframes the other four. Per-scene framing belongs
   in _tools/build-hero-reel.sh (zoom / panX / panY / shiftY), which is per clip. */
.hero-clip-1{object-position:50% 40%;animation:ffBreathe 52s ease-in-out infinite;opacity:1}
.hero-ink{position:absolute;inset:0;display:block;
  background:linear-gradient(to right,rgba(9,34,41,.6) 0%,rgba(9,34,41,.5) 45%,rgba(9,34,41,.22) 70%,rgba(9,34,41,0) 88%)}

/* Decorative geometry. Nothing here is synchronized — that is the point. */
.hero-orbs{position:absolute;inset:0;z-index:1;pointer-events:none}
.ho{position:absolute;display:block;border-style:solid;border-width:1px}
.ho-c1,.ho-c2,.ho-c3{border-radius:50%}
.ho-c1{right:-330px;top:-40px;width:760px;height:760px;border-color:rgba(255,255,255,.1);
  animation:ffFade 3000ms ease 500ms both,ffDriftC 38s ease-in-out 1s infinite}
.ho-c2{right:-410px;top:-140px;width:960px;height:960px;border-color:rgba(255,255,255,.08);
  animation:ffFade 3000ms ease 750ms both,ffDriftA 44s ease-in-out 1s infinite}
.ho-c3{right:-520px;top:-250px;width:1180px;height:1180px;border-color:rgba(255,255,255,.06);
  animation:ffFade 3000ms ease 1000ms both,ffDriftB 52s ease-in-out 1s infinite}

/* Message bar. A solid paper cut, full-bleed — legibility here comes from the hard
   edge, not from a scrim over the video. */
.hero-bar{background:var(--paper);border-top:1px solid rgba(255,255,255,.14);border-bottom:1px solid var(--line);padding:0 var(--pad)}
.hero-bar-in{max-width:1240px;margin:0 auto;display:grid;grid-template-columns:minmax(0,1fr) auto;
  align-items:center;gap:0;padding:clamp(22px,2.8vw,40px) 0 clamp(24px,3vw,44px)}
/* The ember rule is a border, NOT a flex child with a :before. Making the <p> a
   flex row turns its own sentences into flex ITEMS — the statement rendered as
   three narrow columns. A border-left stretches to full height for free and the
   text stays inline. */
.hero-statement{margin:0;
  border-left:4px solid var(--gold);padding-left:clamp(16px,2vw,28px);padding-right:clamp(24px,4vw,64px);
  font-family:var(--serif);font-weight:400;font-size:clamp(20px,2.35vw,34px);
  line-height:1.28;letter-spacing:-.008em;color:var(--ink);text-wrap:pretty}
.hero-statement span{color:var(--muted)}
/* --gold-deep, not --gold. The brand ember measured 3.53:1 on paper at this size;
   --gold-deep measures 4.99:1. The bright value stays correct for the rule and the
   button, where it is not text. */
/* The three lines are already metrically even — measured 43.3px between each. This
   is an OPTICAL adjustment, not a fix: line 2 ends on "practice." with no
   descender and line 3 opens on a tall italic "W", which reads tight even though
   the boxes are identical. inline-block so the margin applies after the <br>. */
.hero-statement em{font-family:var(--serif-i);font-style:italic;font-weight:400;color:var(--gold-deep);
  display:inline-block;margin-top:.11em}
.hero-act{display:flex;flex-direction:column;align-items:center;gap:14px;
  padding-left:clamp(16px,2.6vw,40px);border-left:1px solid var(--line)}
.hero-note{font-size:clamp(12px,1.05vw,15px);color:var(--muted);white-space:nowrap}

@keyframes ffRise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:translateY(0)}}
@keyframes ffFade{from{opacity:0}to{opacity:1}}
@keyframes ffDriftA{0%,100%{transform:translate3d(0,0,0)}50%{transform:translate3d(12px,-9px,0)}}
@keyframes ffDriftB{0%,100%{transform:translate3d(0,0,0)}50%{transform:translate3d(-10px,14px,0)}}
@keyframes ffDriftC{0%,100%{transform:translate3d(0,0,0) rotate(0)}50%{transform:translate3d(-14px,10px,0) rotate(1.2deg)}}
@keyframes ffBreathe{0%,100%{transform:scale(1.02) translate3d(0,0,0)}50%{transform:scale(1.09) translate3d(-1.2%,-.8%,0)}}

.hero-eyebrow[data-anim]{animation:ffRise 1100ms cubic-bezier(.22,.7,.2,1) 120ms both}
.hero h1 span[data-anim]{animation:ffRise 1400ms cubic-bezier(.22,.7,.2,1) 320ms both}
.hero h1 span+span[data-anim]{animation-delay:440ms}
.hero h1 span+span+span[data-anim]{animation-delay:520ms}
.hero-trio[data-anim]{animation:ffRise 1400ms cubic-bezier(.22,.7,.2,1) 900ms both}
.hero-bar-in[data-anim]{animation:ffRise 1400ms cubic-bezier(.22,.7,.2,1) 1080ms both}

/* Both halves are required. CSS alone stops the reveals but leaves the footage
   playing; script.js pauses each clip and seeks it to 0.8s so the hero reads as a
   still photograph, and never arms the rotation. */
@media (prefers-reduced-motion:reduce){
  [data-anim],.hero-clip{animation:none!important;opacity:1!important;transform:none!important}
}

/* Below ~700px the 65% column and the two-cell bar both stop earning their keep. */
@media (max-width:700px){
  .hero-inner>*{width:100%;max-width:100%}
  /* Dividers come off once the trio wraps: a border-left on every item but the
     first leaves an orphaned rule hanging at the start of the second row. */
  .hero-trio{flex-wrap:wrap;gap:1.1rem 1.6rem}
  .hero-trio>div+div{border-left:0;padding-left:0}
  .hero-bar-in{grid-template-columns:1fr;gap:1.6rem}
  .hero-statement{padding-right:0}
  .hero-act{align-items:flex-start;padding-left:0;border-left:0}
}

/* Brad, 2026-08-21: kill the trailing hairline under the last fact. The rule reads
   as "another item is coming" when nothing is. Top border of the ul stays. */
.fact-stack li:last-child{border-bottom:0}
/* This section's lead sits between the h2 and the stack, so it needs the tighter
   space of a bridging line, not the 2.2rem a standalone .lead carries. */
.ed-text .lead{margin-bottom:1.6rem}

/* --- Footer: the root homepage's layout and style, therapist links ----------
   Brad, 2026-08-21. Overrides the green footer inherited from law-firms above the
   THERAPISTS marker; same specificity, later in the file, so it simply wins.
   Sky, not green, for the same reason the homepage is: `#contact` directly above
   is a dark pass, and a green footer merges into it as one continuous dark mass
   with only a hairline between. The brand mark draws with currentColor, so it
   flips to ink on its own. ------------------------------------------------- */
footer{padding:clamp(3.5rem,7vh,5rem) max(var(--pad),calc((100% - 1240px) / 2)) 1.6rem;
  background:var(--oxwash);color:var(--ink);
  display:grid;grid-template-columns:1fr 1.1fr;gap:clamp(2.5rem,6vw,6rem);
  align-items:start;border-top:1px solid var(--line)}
.footer-cols{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(1.5rem,3vw,2.5rem);
  padding-left:24px}
.footer-cols>:first-child{padding-left:20px}
.footer-intro{max-width:34ch}
.footer-brand{font-size:1.25rem}
.footer-intro p{margin:1.1rem 0 0;color:var(--muted);font-size:.95rem;line-height:1.55}
.footer-cta{margin-top:1.5rem}
.footer-label{margin:0 0 1rem;font-family:var(--sans);font-size:.7rem;font-weight:600;
  text-transform:uppercase;letter-spacing:.16em;color:var(--ink)}
.footer-col ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.15rem}
/* .55rem of vertical padding takes every row past the 24px target minimum. */
.footer-col a,.footer-plain{display:inline-block;padding:.55rem 0;font-size:.92rem;line-height:1.3}
.footer-col a{border-bottom:1px solid transparent;transition:border-color .2s}
.footer-col a:hover,.footer-col a:focus-visible{border-color:currentColor}
.footer-plain{color:var(--muted)}
.footer-bottom{grid-column:1/-1;display:flex;justify-content:space-between;align-items:center;
  gap:.6rem 1.5rem;flex-wrap:wrap;margin-top:clamp(1.5rem,3vh,2.5rem);
  border-top:1px solid var(--line);padding-top:1.2rem;
  color:var(--muted);font-size:.72rem;text-transform:uppercase;letter-spacing:.1em}
.footer-legal{list-style:none;display:flex;flex-wrap:wrap;gap:0 1.5rem;margin:0;padding:0}
/* The inherited rule draws these white for the dark footer. */
.footer-bottom a{display:inline-block;padding:.35rem 0;border-bottom:1px solid rgba(16,45,53,.32)}
.footer-bottom a:hover,.footer-bottom a:focus-visible{border-bottom-color:currentColor}
@media(max-width:900px){
  footer{grid-template-columns:1fr;gap:2.5rem}
  /* The offsets exist only to line the columns up in the two-column layout.
     Stacked, they just indent one group further than the other. */
  .footer-cols,.footer-cols>:first-child{padding-left:0}
}
@media(max-width:520px){
  .footer-cols{grid-template-columns:1fr;gap:1.75rem}
  .footer-cta{width:100%;text-align:center}
}

/* The six new phrases make the strip ~3x longer than the two it replaced, and the
   shared 28s duration is a distance/time, not a speed — so the ticker suddenly ran
   at 117px/s, far too fast to read. 80s puts it back to ~41px/s, the pace it had
   with the old copy. Re-time this if the phrase list changes length again. */
.ticker div{animation-duration:80s}

/* Brad, 2026-08-21: no compact-on-scroll shrink. The header holds 76px at every
   scroll position. The inherited rule above the THERAPISTS marker drops it to
   62px, which is shared with law-firms, so it is neutralised here rather than
   edited there.
   This also removes the CAUSE of the jitter rather than just its symptom: the
   header is sticky but in normal flow, so changing its height moved every pixel
   below it and knocked scrollY by 14px. With the height fixed there is no kick,
   no content jump, and nothing for the scroll listener to fight.
   The background lift and shadow on scroll are kept — they separate the header
   from the content underneath without moving anything. */
.site-header.compact{min-height:76px}

/* --- Motion pass, 2026-08-22 -----------------------------------------------
   Three additions, each answering a specific gap rather than decorating.

   1. PRESS FEEDBACK. `:active` appeared ZERO times in this stylesheet. Every
      control lifted on hover and then did nothing at all on press, so on touch —
      where there is no hover — a tap produced no acknowledgement whatsoever until
      the page moved. 90ms, and it undoes the hover lift rather than inventing a
      new gesture, so press reads as the opposite of hover.
   2. LIGHTBOX CONTINUITY. `showModal()` hard-cut a full-screen panel into
      existence. It now scales up from just under full size while the backdrop
      blur ramps, so the enlarged image reads as the same object as the card.
   3. ACCORDION AFFORDANCE. The +/- crossbar had no transition, so the icon
      teleported between states while the panel it controls animates open.
   ------------------------------------------------------------------------- */
.button:active{transform:translateY(0) scale(.985);box-shadow:none;transition-duration:90ms}
.slot.is-zoomable:active .slot-shot{transform:scale(1.01);transition-duration:90ms}
.qa-btn:active .qa-ico,.dsc-rail button:active .dsc-lab,.dsc-btn:active{transform:scale(.94)}
.dsc-btn,.qa-ico,.dsc-lab{transition:transform .18s cubic-bezier(.16,1,.3,1)}
.footer-col a:active,.site-header nav a:active{opacity:.6;transition-duration:90ms}

/* The crossbar becomes a minus by rotating out, in step with the panel opening. */
.qa-ico:before,.qa-ico:after{transition:transform .32s cubic-bezier(.16,1,.3,1),opacity .32s ease}
.qa-btn[aria-expanded="true"] .qa-ico:after{transform:translate(-50%,-50%) rotate(0deg);opacity:0}

@keyframes lbIn{from{opacity:0;transform:scale(.94)}to{opacity:1;transform:none}}
@keyframes lbBackdrop{from{opacity:0}to{opacity:1}}
.lightbox[open]{animation:lbIn .34s cubic-bezier(.16,1,.3,1) both}
.lightbox[open]::backdrop{animation:lbBackdrop .34s ease both}

@media (prefers-reduced-motion:reduce){
  /* Press feedback SURVIVES — it confirms an action, and removing it would make
     the site feel broken on touch. Only the spatial entrance is dropped. */
  .lightbox[open],.lightbox[open]::backdrop{animation:none}
  .qa-ico:before,.qa-ico:after{transition:opacity .2s ease}
  .dsc-btn,.qa-ico,.dsc-lab{transition:none}
}
