/* motion.css - Gulf Grins motion layer (v3, DESIGN-V3-SPEC.md section 9). Loaded after the page <style> and brand.css.
   The finished page is the default: nothing is hidden unless motion.js adds html.motion (IntersectionObserver, no reduced motion).
   Scroll-linked effects are CSS animation-timeline only (static page elsewhere). One wow (the sunrise), one gesture (the tide).
   No selector here touches .btn, .tel, .mbar, .form, .waitlist, .emg, .cbox or .phero-act. */

/* --hdr: 76px at the default 16px font; grows with a larger browser font (like the header itself) */
:root{--hdr:max(76px,4.75rem)}

/* ---------- 0. Overrides of the base layer (same specificity, later wins) ---------- */
/* metric-matched local fallbacks, so the late Nunito swap does not rewrap text the parent is already reading. */
@font-face{font-family:'Nunito Fallback';src:local('Arial'),local('ArialMT'),local('Helvetica'),local('Segoe UI');font-weight:1 549;size-adjust:101.2%;ascent-override:99.9%;descent-override:34.9%;line-gap-override:0%}
@font-face{font-family:'Nunito Fallback';src:local('Arial Bold'),local('Arial-BoldMT'),local('Helvetica Bold'),local('Segoe UI Bold');font-weight:550 1000;size-adjust:96.4%;ascent-override:104.9%;descent-override:36.6%;line-gap-override:0%}
@font-face{font-family:'Nunito Sans Fallback';src:local('Arial'),local('ArialMT'),local('Helvetica'),local('Segoe UI');font-weight:1 549;size-adjust:101.2%;ascent-override:99.9%;descent-override:34.9%;line-gap-override:0%}
@font-face{font-family:'Nunito Sans Fallback';src:local('Arial Bold'),local('Arial-BoldMT'),local('Helvetica Bold'),local('Segoe UI Bold');font-weight:550 1000;size-adjust:95%;ascent-override:106.4%;descent-override:37.2%;line-gap-override:0%}
/* no one-word last lines in headings; pretty only touches the last lines of the longer ledes */
h1,h2,h3{text-wrap:balance}.lede{text-wrap:pretty}
/* scroll landings: focus() and #fragment jumps stop below the sticky header with the field's label in view, and at <=1080px nothing is scrolled in */
html{scroll-behavior:auto;scroll-padding-top:calc(var(--hdr) + 1rem)}
@media (max-width:1080px),(max-width:67.5em){html{scroll-padding-bottom:calc(96px + env(safe-area-inset-bottom))}}
/* the sticky header is always in view: its controls cancel the padding, so focus() on the logo, nav or menu toggle never scrolls the page */
.hdr *{scroll-margin-top:calc(-1 * (var(--hdr) + 1rem))}
input,select,textarea{scroll-margin-top:2.5rem}
#waitlist{scroll-margin-top:0}
/* overflow:clip, never hidden, around anything scroll-animated: hidden makes a scroll container and view() attaches to it */
.phero,.crest,.phero-sea,.photo-band,.ft{overflow:clip}
/* eyebrow rule: drawn by default; the reveal below draws it in once */
.eyebrow::after{content:"";position:absolute;left:0;bottom:0;height:2px;width:56px;background:var(--blue);transition:width .8s var(--ease) .15s}

/* ---------- 1. TRIGGERED: reveal on entry (motion.js adds html.motion, then .in, then hands the element back) ---------- */
/* screen only: prefers-reduced-motion also matches print, and a printout must never carry the hidden states below */
@media screen and (prefers-reduced-motion:no-preference){
  /* hidden only until .in arrives; then each element settles to its OWN stylesheet values. */
  .motion [data-reveal].in{transition:opacity .6s var(--ease),translate .8s var(--ease);
    transition-delay:calc(min(var(--i,0),6)*70ms)}
  .motion [data-reveal]:not(.in):not([data-reveal=wipe]):not([data-reveal=words]):not([data-reveal=seq]){opacity:0;translate:0 var(--motion-distance,16px)}

  /* one-shot image wipe. The clip goes on the <img>, never on the observed frame. */
  .motion [data-reveal=wipe]>img{clip-path:inset(0 0 100% 0);scale:1.14;
    transition:clip-path .9s var(--ease),scale 1.4s var(--ease);transition-delay:calc(min(var(--i,0),6)*90ms)}
  .motion [data-reveal=wipe].in>img{clip-path:inset(0 0 0 0);scale:1}

  /* section headline, word by word (markup written by apply_motion.py / v3_migrate.py; the hero h1 has its own entrance, section 3) */
  .motion [data-reveal=words] .w>span{translate:0 110%;transition:translate .7s var(--ease);transition-delay:calc(var(--i,0)*45ms)}
  .motion [data-reveal=words].in .w>span{translate:0 0}

  /* the eyebrow rule draws in with its reveal and stays drawn after the hand-back */
  .motion .eyebrow[data-reveal]::after{width:0}
  .motion .eyebrow[data-reveal].in::after{width:56px}
  /* the special-needs statement: its three sentences arrive one after another (300 ms apart) */
  .motion [data-reveal=seq] .s{opacity:0;translate:0 12px}
  .motion [data-reveal=seq].in .s{opacity:1;translate:0 0;transition:opacity .6s var(--ease),translate .7s var(--ease)}
  .motion [data-reveal=seq].in .s:nth-child(2){transition-delay:.3s}
  .motion [data-reveal=seq].in .s:nth-child(3){transition-delay:.6s}
}
/* clip only vertically: the headings use negative letter-spacing, so a full clip would shave the last glyph of each word */
.w{display:inline-block;overflow-x:visible;overflow-y:clip;vertical-align:top;padding-bottom:.14em;margin-bottom:-.14em}
.w>span{display:inline-block}
[data-reveal=wipe]{overflow:clip}

/* ---------- 2. THE SUNRISE (home hero only) + the header hairline. Zero JS. ---------- */
/* 2a-i. her five rays fan in around the smile on load (skipped after the preloader); reduced motion: the static mark */
@media (prefers-reduced-motion:no-preference){
  .sun-rays .ray,.nf-mark .ray{transform-box:view-box;transform-origin:380.362px 380.201px;animation:ray-fan .28s cubic-bezier(.2,.7,.3,1) calc(var(--intro-delay,0s) + 0s) both}
  .sun-rays .ray:nth-child(2),.nf-mark .ray:nth-child(2){animation-delay:calc(var(--intro-delay,0s) + 80ms)}
  .sun-rays .ray:nth-child(3),.nf-mark .ray:nth-child(3){animation-delay:calc(var(--intro-delay,0s) + 160ms)}
  .sun-rays .ray:nth-child(4),.nf-mark .ray:nth-child(4){animation-delay:calc(var(--intro-delay,0s) + 240ms)}
  .sun-rays .ray:nth-child(5),.nf-mark .ray:nth-child(5){animation-delay:calc(var(--intro-delay,0s) + 320ms)}
  @keyframes ray-fan{from{opacity:0;transform:rotate(-18deg) scale(.78)}}
}
@media (prefers-reduced-motion:no-preference){
@supports (animation-timeline:view()){
  /* 2a-ii. as the hero scrolls away: the sun lifts, the rays lengthen, the dawn glow brightens, the sea veil lifts and a morning light comes up */
  .phero{view-timeline:--hero block}
  .phero-sun,.sun-rays,.dawn,.phero-sea::before,.phero-sea::after{animation:1ms linear both;animation-timeline:--hero;animation-range:exit 0% exit 65%}
  .phero-sun{animation-name:sun-lift}
  .sun-rays{animation-name:sun-rays}
  .dawn{animation-name:sun-dawn}
  .phero-sea::before{animation-name:sea-morning}
  .phero-sea::after{animation-name:sea-veil}
  @keyframes sun-lift{to{transform:translate3d(0,-9%,0)}}
  @keyframes sun-rays{to{transform:scale(1.2)}}
  @keyframes sun-dawn{from{opacity:.6;transform:scale(1)}to{opacity:.95;transform:scale(1.16)}}
  @keyframes sea-veil{to{opacity:0}}
  @keyframes sea-morning{to{opacity:1}}
  /* phones: the sun sits close under the fold, so tie the sunrise to the first 420px of page scroll instead */
  @media (max-width:1080px){
    .phero-sun,.sun-rays,.dawn,.phero-sea::before,.phero-sea::after{animation-timeline:scroll(root block);animation-range:0 420px}
  }

  /* 2b. the home photo band: the photo drifts gently inside its clipped frame while the band crosses the screen */
  .px img{animation:px-y 1ms linear both;animation-timeline:view();animation-range:cover 0% cover 100%}
  @keyframes px-y{from{transform:translate3d(0,-5%,0) scale(1.12)}to{transform:translate3d(0,5%,0) scale(1.12)}}

  /* 2c. header: hairline shadow fades in over the first 120px of page scroll (.hdr is sticky, so ::after positions against it) */
  .hdr::after{content:"";position:absolute;left:0;right:0;bottom:-10px;height:10px;pointer-events:none;
    background:linear-gradient(rgba(45,76,88,.10),transparent);opacity:0;
    animation:hdr-shadow 1ms linear both;animation-timeline:scroll(root block);animation-range:0 120px}
  @keyframes hdr-shadow{to{opacity:1}}

  /* 2d. footer: the giant wordmark rises into place as the footer enters */
  .ft-mark{animation:ft-rise 1ms linear both;animation-timeline:view(block 0px);animation-range:entry 0% entry 100%}   /* inset 0: the phone's scroll-padding-bottom must not stop the rise short */
  @keyframes ft-rise{from{transform:translate3d(0,42%,0)}}

  /* 2e. first visit: the step rail fills in --blue as you read */
  .steps{view-timeline:--steps block}
  .steps::after{content:"";position:absolute;left:0;top:.5rem;width:2px;height:calc(100% - 1rem);background:var(--blue);transform-origin:top;
    animation:rail-fill 1ms linear both;animation-timeline:--steps;animation-range:cover 15% cover 85%}
  @keyframes rail-fill{from{transform:scaleY(0)}}
  /* 2f. privacy: a 2px reading-progress line under the header */
  html:has(#npp) .hdr::before{content:"";position:absolute;left:0;right:0;bottom:0;height:2px;background:var(--blue);transform-origin:left;
    animation:read-prog 1ms linear both;animation-timeline:scroll(root block)}
  @keyframes read-prog{from{transform:scaleX(0)}}
  /* 2g. services (desktop): the sticky photo column crossfades Prevention -> Treatment -> Specialist Care; the incoming layer fades in
         as its block enters, the outgoing crest fades out (two elements, so the two fades never fight over one opacity) */
  @media (min-width:1024px){
    .svc-layout{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));column-gap:var(--col-gap);align-items:start;timeline-scope:--b2,--b3}
    .svc-media{display:grid;grid-column:1/6;position:sticky;top:calc(var(--hdr) + 2rem);max-width:min(100%,calc((100svh - var(--hdr) - 4rem) * .8))}
    .svc-blocks{grid-column:7/13}
    .svc-inline{display:none}
    .svc-layer{grid-area:1/1}
    .svc-layer .crest{max-width:none;width:100%}
    #svc-2{view-timeline:--b2 block}#svc-3{view-timeline:--b3 block}
    .svc-layer.l2,.svc-layer.l3,.svc-layer.l1 .crest,.svc-layer.l2 .crest{animation:1ms linear both}
    .svc-layer.l2{animation-name:svc-in;animation-timeline:--b2}
    .svc-layer.l3{animation-name:svc-in;animation-timeline:--b3}
    .svc-layer.l1 .crest{animation-name:svc-out;animation-timeline:--b2}
    .svc-layer.l2 .crest{animation-name:svc-out;animation-timeline:--b3}
    .svc-layer.l2,.svc-layer.l3,.svc-layer.l1 .crest,.svc-layer.l2 .crest{animation-range:entry 0% entry 60%}
    @keyframes svc-in{from{opacity:0}}
    @keyframes svc-out{to{opacity:0}}
  }
}}

/* ---------- 3. SEQUENCED ENTRANCES on every page load (CSS only, html.js + no-preference; */
@media (prefers-reduced-motion:no-preference){
  @keyframes gg-rule{from{transform:scaleX(0)}}
  @keyframes gg-word{from{opacity:.15;translate:0 .3em}}
  @keyframes gg-rise{from{opacity:0;translate:0 16px}}
  @keyframes gg-settle{from{scale:1.06}}
  html.js .page-hero .eyebrow::after,html.js .nf .eyebrow::after{animation:gg-rule .6s var(--ease) var(--intro-delay,0s) both}
  html.js .page-hero h1 .w>span,html.js .phero h1 .w>span,html.js .nf h1 .w>span{animation:gg-word .52s var(--ease) both;
    animation-delay:calc(var(--intro-delay,0s) + 120ms + min(var(--i,0),10) * 40ms)}
  html.js .page-hero .lede,html.js .nf .lede{animation:gg-rise .38s var(--ease) calc(var(--intro-delay,0s) + 300ms) both}
  html.js .phero .badge{animation:gg-rise .4s var(--ease) var(--intro-delay,0s) both}
  html.js .phero .lede{animation:gg-rise .38s var(--ease) calc(var(--intro-delay,0s) + 420ms) both}
  html.js .hero-crest img,html.js .phero-sea img{animation:gg-settle 1.1s var(--ease) var(--intro-delay,0s) both}
}

/* ---------- 4. PAGE TRANSITION: THE TIDE + the card-photo -> hero morph. */
@media (prefers-reduced-motion:no-preference){
  @view-transition{navigation:auto}
}
.hdr{view-transition-name:site-header}
.mbar{view-transition-name:mbar}
#gg-preview-bar{view-transition-name:preview-bar}   /* injected by the worker while the site is gated */
::view-transition-group(site-header),::view-transition-group(mbar),::view-transition-group(preview-bar){animation:none}
::view-transition-group(site-header),::view-transition-group(preview-bar){z-index:10}
::view-transition-group(mbar){z-index:12}
::view-transition-old(site-header),::view-transition-old(mbar),::view-transition-old(preview-bar){display:none}
::view-transition-new(site-header),::view-transition-new(mbar),::view-transition-new(preview-bar){animation:none}
::view-transition-old(root),::view-transition-new(root){mix-blend-mode:normal}
::view-transition-old(root){animation:none}
::view-transition-new(root){animation:tide-rise .5s cubic-bezier(.3,.55,.35,1) 40ms both}
@keyframes tide-rise{
  from{clip-path:inset(100% 0 0 0 round 50% 50% 0 0 / 24% 24% 0 0)}
  to{clip-path:inset(0 0 0 0 round 0 0 0 0 / 0 0 0 0)}
}
/* the card-photo -> hero morph rules live in the page's first <style> (with the tide opt-in); motion.js lends the name at pageswap */
/* the mobile menu must never be caught mid-close in the outgoing snapshot (class set at pageswap by motion.js, cleared on pageshow) */
.vt-swap .mnav,.vt-swap .mnav-scrim{transition:none!important;visibility:hidden!important;opacity:0!important}

/* ---------- 5. FULL-SCREEN MENU: two columns from 700px (pages | phone, email, address, hours, Join), staggered links ---------- Shows at <=1080px with .navtoggle; */
.mnav-scrim{display:none}
.mnav{position:fixed;inset:0;z-index:130;display:grid;gap:2rem 3rem;align-content:start;overflow-y:auto;visibility:hidden;
  padding:calc(var(--hdr) + 1.25rem) var(--gutter) calc(82px + 1.5rem);background:var(--deep);color:#fff;
  opacity:0;translate:0 -10px;transition:opacity .3s var(--ease),translate .3s var(--ease),visibility 0s .3s}
.mnav[data-open="true"]{visibility:visible;opacity:1;translate:0 0;transition-delay:0s}
.mnav-pages{display:grid;counter-reset:mn;border-top:1px solid var(--rule-dark)}
.mnav-pages a{counter-increment:mn;display:flex;align-items:baseline;gap:1rem;padding:.65rem 0;border-bottom:1px solid var(--rule-dark);
  font-family:var(--f-display);font-weight:400;font-size:var(--t-h2);line-height:1.1;letter-spacing:-.018em;color:#fff;text-decoration:none;
  background:linear-gradient(var(--blue),var(--blue)) 0 calc(100% - .55rem)/0 2px no-repeat;transition:background-size .4s var(--ease)}
.mnav-pages a::before{content:"0" counter(mn);min-width:2.2ch;font-family:var(--f-ui);font-weight:800;font-size:var(--t-label);letter-spacing:.12em;color:var(--blue)}
.mnav-pages a[aria-current="page"]{color:var(--blue-soft);background-size:100% 2px}
.mnav-aside{display:grid;gap:1rem;align-content:start}
.mnav-aside a.mtel{display:flex;align-items:center;min-height:48px;font-family:var(--f-display);font-weight:400;font-size:var(--t-h2-sm);line-height:1.1;letter-spacing:-.012em;color:var(--ice);text-decoration:none}
.mnav-aside a.mmail{display:inline-flex;align-items:center;min-height:44px;font-size:1.0625rem;color:var(--ice);text-underline-offset:4px}
.mnav-aside .maddr,.mnav-aside .mhours li{margin:0;font-size:1.0625rem;line-height:1.55;color:var(--ice)}
.mnav-aside .mhours{list-style:none;margin:0;padding:0;display:grid;gap:.15rem}
.mnav-aside .btn{width:100%;margin-top:.5rem}
.mnav :focus-visible{outline-color:var(--peach)}
.nav-open .hdr{z-index:135}      /* logo and the close button stay above the open panel (html.nav-open set by motion.js) */
.hdr:has(.navtoggle[aria-expanded="true"]){z-index:135}   /* same, without motion.js (own rule: an unknown :has() must not drop the line above) */
.mbar{z-index:140}               /* Call / Join waitlist stay one tap away with the menu open */
.mnav{scroll-padding:calc(var(--hdr) + .5rem) 0 calc(82px + .5rem + env(safe-area-inset-bottom))}   /* the panel is its own scroller: Tab keeps each link clear of the header and the Call / Join bar */
@media (min-width:700px){.mnav{grid-template-columns:minmax(0,1.35fr) minmax(0,1fr)}.mnav-aside .btn{width:auto;justify-self:start}}
@media (hover:hover) and (pointer:fine){
  .mnav-pages:hover a:not(:hover){opacity:.45}
  .mnav-pages a:hover{background-size:100% 2px}
}
@media (prefers-reduced-motion:no-preference){
  .motion .mnav a{opacity:0;translate:0 14px;transition:opacity .45s var(--ease),translate .5s var(--ease),background-size .4s var(--ease);transition-delay:calc(60ms + var(--i,0)*45ms),calc(60ms + var(--i,0)*45ms),0s}
  .motion .mnav[data-open="true"] a{opacity:1;translate:0 0}
  .motion .mnav .btn{transition-delay:calc(60ms + 8*45ms),calc(60ms + 8*45ms),0s}
  @media (hover:hover) and (pointer:fine){.motion .mnav[data-open="true"] .mnav-pages:hover a:not(:hover){opacity:.45;transition-delay:0s}}
}
@media (prefers-reduced-motion:reduce){.mnav{transition:none}}
/* larger browser font (Chrome Large 20px / Very large 24px): */
@media (min-width:1081px) and (max-width:67.5em){.nav,.hdr-cta{display:none}.navtoggle{display:flex}.mbar{display:flex}body{padding-bottom:82px}}
/* without motion.js (blocked or 404) nothing closes the open menu past the breakpoint: */
@media (min-width:1081px) and (min-width:67.5em){
  html:not(.nav-open) .mnav,html:not(.nav-open) .mnav-scrim{visibility:hidden!important;opacity:0!important;pointer-events:none!important}
  html:not(.nav-open) body:has(.mnav[data-open="true"]){overflow-x:hidden!important;overflow-y:auto!important}
}

/* ---------- 6. STATIC ACCESSIBILITY FIXES (no motion) ---------- */
/* footer taps: 44px-tall bottom-bar links, 44x44 social icons; padding plus negative margin leaves the drawn layout unchanged */
.ft-bot a{padding-block:0}
/* short viewports (landscape phones, 200-400% zoom): the bar stops covering the page; it stays fixed and on top only while the menu is open */
@media (max-width:1080px) and (max-height:500px),(max-width:67.5em) and (max-height:500px){
  html{scroll-padding-bottom:0}
  .mbar{position:static;view-transition-name:none}
  body{padding-bottom:0}
  .nav-open .mbar{position:fixed}
  body:has(.navtoggle[aria-expanded="true"]) .mbar{position:fixed}
}
/* very short viewports (400% zoom at 1280x720/800): header + bar leave no room for one link, so the bar steps aside while the menu is open */
@media (max-width:1080px) and (max-height:250px),(max-width:67.5em) and (max-height:250px){
  .mnav{scroll-padding-bottom:.5rem;padding-bottom:1.5rem}
  .nav-open .mbar{position:static;visibility:hidden}
}
@media (max-width:1080px) and (max-height:250px),(max-width:67.5em) and (max-height:250px){
  body:has(.navtoggle[aria-expanded="true"]) .mbar{position:static;visibility:hidden}
}
/* print: no fixed bar, menu or sticky header on paper; closed answers print open */
@media print{.mbar,.navtoggle,.mnav,.mnav-scrim,.skip{display:none!important}body{padding-bottom:0!important}.hdr{position:static!important}details .ans{transition:none!important}}
@media print{details::details-content{content-visibility:visible}details .ans{grid-template-rows:1fr!important}}
