/* ═══════════════════════════════════════════════════════════════════
   BALLARD SERVICES — site design system
   d-drift (FILM) character, extended for the full 19-page site.

   Sections:
   1. Tokens + base            (unchanged from v1 core)
   2. Type, eyebrow, button    (unchanged)
   3. Photo guardrail, reveal, odometer (unchanged)
   4. Nav + mobile drawer      (drawer is new — the mock had no mobile nav)
   5. Bands, map, plate, footer
   6. d-drift section styles   (lifted from d-drift.html verbatim)
   7. Interior-page components (pageband, prose, FAQ, form, tiles, confirm)
   8. Motion                   (d-drift @supports block + f-stack .rise)
   9. Responsive + reduced motion

   SMOOTHNESS RULE: scroll-driven animation may only touch transform and
   opacity. Initial states live in keyframes, never base rules, so
   killing animation leaves content visible.
   ═══════════════════════════════════════════════════════════════════ */

:root{
  --white:#FFFFFF;
  --paper:#FAFAFC;
  --indigo:#101A3D;
  --indigo-2:#1A2554;
  --brand:#0454FC;
  --brand-lit:#5C8FFF;
  --tint:#DCE6FF;
  --ink:#1A1A22;
  --ink-2:#5A5E70;      /* body text, 6.4:1 on white */
  --ink-3:#696F83;      /* labels and eyebrows, 5.0:1 on white — WCAG AA at 11px */
  --rule:#E4E6EE;       /* hairlines and grid gaps (decorative) */
  --rule-2:#CFD3DF;     /* heavier decorative rules */
  --rule-3:#8A90A2;     /* borders on interactive controls, 3.2:1 — WCAG 1.4.11 */

  --f:'Titillium Web',ui-sans-serif,sans-serif;
  --gut:clamp(20px,5.2vw,76px);
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{
  margin:0;background:var(--white);color:var(--ink);
  font-family:var(--f);font-weight:400;-webkit-font-smoothing:antialiased;overflow-x:hidden;
}
img{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
strong,b{font-weight:600}   /* the scale tops out at 600; no 700 is loaded */
::selection{background:var(--brand);color:#fff}

/* ── keyboard focus ───────────────────────────────────────────────
   One ring for every interactive element. Brand blue is 5.7:1 on white
   but only 3.0:1 on the indigo ground, so dark surfaces take the lit
   tint instead. Components with their own ring keep it.            */
a:focus-visible,button:focus-visible,summary:focus-visible,
input:focus-visible,textarea:focus-visible{
  outline:2px solid var(--brand);outline-offset:3px;
}
.dark a:focus-visible,.pageband a:focus-visible,footer a:focus-visible,
.plate-img a:focus-visible,.shufcap a:focus-visible,
.nav:not(.solid) a:focus-visible{outline-color:var(--brand-lit)}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.skip{position:fixed;left:var(--gut);top:-60px;z-index:99;background:var(--brand);color:#fff;padding:10px 18px;font-size:12.5px;font-weight:600;letter-spacing:.03em;text-transform:uppercase;transition:top .2s}
.skip:focus-visible{top:12px;outline:2px solid #fff;outline-offset:2px}

/* ── type scale: thin, sentence case, tight negative tracking ─────── */
h1,h2,h3{margin:0;font-weight:300;letter-spacing:-.025em;line-height:1.08}
.h-hero{font-size:clamp(2.7rem,min(8.4vw,12.6vh),7rem);line-height:1.0;letter-spacing:-.032em}
.h-1{font-size:clamp(1.9rem,4.3vw,4rem);line-height:1.12}
.h-2{font-size:clamp(1.5rem,2.7vw,2.35rem);line-height:1.16}
.state{font-size:clamp(1.45rem,3.1vw,2.9rem);font-weight:300;line-height:1.22;letter-spacing:-.022em;margin:0}

/* square-bullet eyebrow */
.eb{
  display:flex;align-items:center;gap:14px;margin:0 0 26px;
  font-size:11px;font-weight:600;letter-spacing:.22em;text-transform:uppercase;color:var(--ink-3);
}
.eb::before{content:'';width:7px;height:7px;background:var(--brand);flex:none}
.eb--on-dark{color:rgba(255,255,255,.62)}
.eb--on-dark::before{background:var(--brand-lit)}

.p{font-size:clamp(.98rem,1.06vw,1.08rem);line-height:1.62;color:var(--ink-2);margin:0;max-width:46ch}
.p--dark{color:rgba(255,255,255,.76)}
/* the opening answer block: a clear step above body, not a nudge */
.p--lead{font-size:clamp(1.22rem,1.72vw,1.58rem);line-height:1.5;max-width:62ch}
/* the quiet register: footnotes, attributions, trust lines */
.p--fine{font-size:13px;line-height:1.6}

/* ── split button ─────────────────────────────────────────────────── */
.btn{display:inline-flex;align-items:stretch;gap:6px}
.btn a,.btn button{display:flex;align-items:center;justify-content:center;border:0;cursor:pointer;font-family:var(--f)}
.btn .lab{
  background:var(--brand);color:#fff;padding:15px 24px;
  font-size:12.5px;font-weight:600;letter-spacing:.03em;text-transform:uppercase;
  transition:background .2s;
}
.btn .chev{background:var(--ink);color:#fff;width:46px;font-size:14px;transition:background .2s}
.btn:hover .lab{background:#2A6DFF}
.btn:hover .chev{background:var(--brand)}
.btn--light .lab{background:#fff;color:var(--ink)}
.btn--light:hover .lab{background:var(--tint)}
.btn--lg .lab{padding:19px 30px;font-size:13.5px}
.btn--lg .chev{width:54px;font-size:16px}
.btn a:focus-visible,.btn button:focus-visible{outline:2px solid var(--brand-lit);outline-offset:2px}

/* ── photo guardrail ──────────────────────────────────────────────
   Every photo goes through the same grain tile — one static 170px tile,
   no blend mode, so it costs nothing under scroll.                  */
.proc{position:relative;overflow:hidden}
.proc>img{width:100%;height:100%;object-fit:cover}
.proc::after{
  content:'';position:absolute;inset:0;pointer-events:none;opacity:.30;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='170' height='170'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='170' height='170' filter='url(%23n)' opacity='.42'/%3E%3C/svg%3E");
  background-size:170px 170px;
}

/* ── scroll-linked zoom ─────────────────────────────────────────── */
.zoom>img{will-change:transform;backface-visibility:hidden}
@supports (animation-timeline: view()){
  .zoom>img{
    animation:zoombreathe linear both;animation-timeline:view();
    animation-range:cover 0% cover 100%;animation-duration:1s;
  }
  @keyframes zoombreathe{
    0%  {transform:translate3d(0,0,0) scale(1.26)}
    50% {transform:translate3d(0,0,0) scale(1.03)}
    100%{transform:translate3d(0,0,0) scale(1.26)}
  }
}

/* ── masked line reveal ───────────────────────────────────────────
     <span class="rv"><i>line one</i></span>                          */
.rv{display:block;overflow:hidden;padding-bottom:.16em;margin-bottom:-.16em}
.rv>i{display:block;font-style:normal;transform-origin:0 100%}

/* ── odometer (digits ordered TARGET FIRST — resting state is true) ─ */
.od{
  --h:1.08em;
  display:inline-block;overflow:hidden;vertical-align:baseline;
  height:var(--h);width:1ch;font-variant-numeric:tabular-nums;
}
.od>i{display:block;font-style:normal;will-change:transform}
.od b{display:block;height:var(--h);line-height:var(--h);font-weight:inherit}

@supports (animation-timeline: view()){
  .rv>i{
    animation:rvline cubic-bezier(.19,.9,.26,1) both;animation-timeline:view();
    animation-range:entry 4% cover 34%;animation-duration:1s;
  }
  @keyframes rvline{from{transform:translate3d(0,112%,0)}to{transform:translate3d(0,0,0)}}
  .rv:nth-of-type(2)>i{animation-range:entry 9% cover 39%}
  .rv:nth-of-type(3)>i{animation-range:entry 14% cover 44%}
  .rv:nth-of-type(4)>i{animation-range:entry 19% cover 49%}

  .od>i{
    animation:roll cubic-bezier(.2,.85,.25,1) both;animation-timeline:view();
    animation-range:entry 10% cover 46%;animation-duration:1s;
  }
  .od:nth-of-type(2)>i{animation-range:entry 13% cover 49%}
  .od:nth-of-type(3)>i{animation-range:entry 16% cover 52%}
  .od:nth-of-type(4)>i{animation-range:entry 19% cover 55%}
  .od:nth-of-type(5)>i{animation-range:entry 22% cover 58%}
  @keyframes roll{
    from{transform:translate3d(0,calc(var(--d) * var(--h) * -1),0)}
    to  {transform:translate3d(0,0,0)}
  }
}

/* ── nav ──────────────────────────────────────────────────────────── */
.nav{position:fixed;inset:0 0 auto 0;z-index:60;display:flex;align-items:center;gap:var(--gut);padding:16px var(--gut);transition:.3s;isolation:isolate}
.nav::before{
  content:'';position:absolute;inset:0;z-index:-2;pointer-events:none;
  background:linear-gradient(to bottom,rgba(11,16,48,.68) 0%,rgba(11,16,48,.34) 54%,transparent 100%);
  transition:opacity .3s;
}
.nav.solid::before{opacity:0}
/* opaque, NOT backdrop-filter — a fixed backdrop-filter re-blurs on every
   frame of every scroll */
.nav.solid{background:#fff;border-bottom:1px solid var(--rule)}
.logo{display:flex;align-items:center;gap:10px}
.logo .bsl{height:32px;width:auto;flex:none;filter:invert(1)}
.nav.solid .logo .bsl{filter:none}
.nav-links{display:flex;gap:26px;margin-left:auto;align-items:center}
.nav-links a{font-size:12.5px;font-weight:600;letter-spacing:.02em;text-transform:uppercase;color:rgba(255,255,255,.92);padding-bottom:4px;border-bottom:1px solid transparent}
.nav-links a:hover{border-color:currentColor}
.nav.solid .nav-links a{color:var(--ink)}

/* Tap to call, secondary to the quote button: outlined, not filled, so the
   two never compete. Collapses to the handset alone on phones. */
.nav-tel{
  flex:none;display:inline-flex;align-items:center;gap:9px;min-height:44px;padding:0 16px;
  border:1px solid rgba(255,255,255,.5);color:#fff;
  font-size:12.5px;font-weight:600;letter-spacing:.03em;
  transition:background .2s,border-color .2s,color .2s;
}
.nav-tel svg{width:16px;height:16px;flex:none}
.nav-tel:hover{background:rgba(255,255,255,.14);border-color:#fff}
.nav.solid .nav-tel{border-color:var(--rule-3);color:var(--ink)}
.nav.solid .nav-tel:hover{background:var(--paper);border-color:var(--ink)}

/* the one thing the nav is asking for. It sits outside .nav-links so it stays
   in the bar at every width instead of hiding inside the mobile drawer. */
.nav-cta{
  flex:none;white-space:nowrap;background:var(--brand);color:#fff;padding:0 20px;
  display:inline-flex;align-items:center;min-height:44px;   /* full tap target */
  font-size:12.5px;font-weight:600;letter-spacing:.03em;text-transform:uppercase;
  transition:background .2s;
}
.nav-cta:hover,.nav.solid .nav-cta:hover{background:#2A6DFF;color:#fff}
.nav.solid .nav-cta{color:#fff}
/* the menu button exists only where it does something: below 680px, where
   the inline links are replaced by the drawer */
.nav-sq{display:none;width:44px;height:44px;background:var(--brand);place-items:center;flex:none;position:relative;border:0;cursor:pointer}
.nav-sq i{display:block;width:16px;height:1.5px;background:#fff;box-shadow:0 5px 0 #fff,0 -5px 0 #fff}

/* mobile drawer — checkbox-driven, no JS. The mock hid nav links below
   680px with nothing in their place; a 19-page site needs a real menu. */
.navtoggle{position:absolute;opacity:0;width:1px;height:1px;pointer-events:none}
@media (max-width:680px){
  .nav{gap:12px}
  .nav-sq{display:grid}
  /* the drawer is out of flow here, so the first in-flow button after the
     logo absorbs the free space and the pair sits right */
  .nav-tel{margin-left:auto;width:44px;padding:0;justify-content:center}
  .nav-tel .nav-tel-n{display:none}
  .nav-cta{padding:0 16px;font-size:11.5px}
  .navtoggle{pointer-events:auto}
  .navtoggle:focus-visible ~ .nav-sq{outline:2px solid var(--brand-lit);outline-offset:2px}
  .nav-links{
    position:fixed;inset:0;z-index:-1;
    background:var(--indigo);
    display:flex;flex-direction:column;justify-content:center;align-items:flex-start;gap:4px;
    padding:96px var(--gut) 48px;margin:0;
    transform:translateY(-102%);visibility:hidden;
    transition:transform .35s cubic-bezier(.2,.7,.3,1),visibility 0s .35s;
  }
  .navtoggle:checked ~ .nav-links{transform:none;visibility:visible;transition:transform .35s cubic-bezier(.2,.7,.3,1)}
  .nav-links a{display:block;font-size:clamp(1.55rem,7vw,2.1rem);font-weight:300;text-transform:none;letter-spacing:-.02em;color:#fff;border:0;padding:9px 0}
  .nav.solid .nav-links a{color:#fff}
  /* while the drawer is open the bar reads as part of the drawer */
  .nav:has(.navtoggle:checked){background:transparent;border-color:transparent}
  .nav:has(.navtoggle:checked) .logo .bsl{filter:invert(1)}
  /* hamburger becomes an X */
  .navtoggle:checked ~ .nav-sq i{background:transparent;box-shadow:none}
  .navtoggle:checked ~ .nav-sq::before,
  .navtoggle:checked ~ .nav-sq::after{
    content:'';position:absolute;left:50%;top:50%;width:18px;height:1.5px;background:#fff;margin:-1px 0 0 -9px;
  }
  .navtoggle:checked ~ .nav-sq::before{transform:rotate(45deg)}
  .navtoggle:checked ~ .nav-sq::after{transform:rotate(-45deg)}
}

/* ═══ BANDS ════════════════════════════════════════════════════════ */
section{position:relative}
[id]{scroll-margin-top:clamp(70px,9vh,96px)}
.wrap{padding:clamp(72px,9vw,140px) var(--gut)}
.dark{background:var(--indigo);color:#fff}
.dark h1,.dark h2,.dark h3,.dark .state{color:#fff}
.cut-t{clip-path:polygon(0 3.2vw,100% 0,100% 100%,0 100%)}
.cut-b{clip-path:polygon(0 0,100% 0,100% calc(100% - 3.2vw),0 100%)}
.glow{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden}
.glow i{
  position:absolute;right:-6%;top:8%;width:58%;height:86%;display:block;
  background:linear-gradient(122deg,rgba(4,84,252,.42) 0%,rgba(4,84,252,.06) 46%,transparent 72%);
  clip-path:polygon(28% 0,100% 12%,100% 88%,10% 100%);
}
.dark .wrap{position:relative;z-index:2}

/* ── coverage map ────────────────────────────────────────────────
   Suburbs are plotted from real OpenStreetMap coordinates. The dot field
   behind them is a coordinate grid, not a coastline: the previous version
   drew an invented landmass, which is the one thing a map must not do. */
.map{position:relative;display:grid;place-items:center;padding:clamp(20px,4vw,60px) 0}
.map-svg{width:100%;max-width:620px;height:auto;display:block;overflow:visible}
.map-lbl{font-family:var(--f);font-size:13px;fill:var(--ink-2)}
.map-lbl--base{fill:var(--ink);font-weight:600}
.map-leader{stroke:var(--rule-2);stroke-width:1}
.map-svg a{cursor:pointer}
.map-svg a:hover .map-lbl{fill:var(--brand)}
.map-svg a:hover circle{r:6}
.map-svg a:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
@media (max-width:680px){
  .map-lbl{font-size:17px}   /* the svg scales down; keep labels legible */
}

/* ── brand plate (supplied wordmark asset) ───────────────────────── */
.plate{background:var(--brand);padding:clamp(26px,3.6vw,60px) var(--gut)}
.plate img{width:100%;max-width:1000px;height:auto}

/* ── footer ──────────────────────────────────────────────────────── */
footer{background:var(--indigo);color:rgba(255,255,255,.66);padding:clamp(48px,6vw,88px) var(--gut) 34px;position:relative;overflow:hidden}
footer .glow i{opacity:.5}
.foot-grid{position:relative;z-index:2;display:grid;grid-template-columns:1.2fr 1fr 1fr 1fr;gap:clamp(20px,3vw,48px)}
.foot-grid h4{font-weight:300;font-size:20px;color:#fff;margin:0 0 12px}
.foot-grid .big{font-size:22px;font-weight:300;color:#fff;margin:0 0 10px}
.foot-grid .big a:hover{color:var(--brand-lit)}
.foot-grid p{font-size:13px;line-height:1.6;margin:0}
.foot-grid address{font-style:normal;font-size:13px;line-height:1.6;margin:16px 0}
.foot-grid p a:hover{color:var(--brand-lit)}
.foot-links a{display:block;font-size:12px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:rgba(255,255,255,.8);padding:9px 0}
.foot-links a:hover{color:var(--brand-lit)}
.foot-dot{position:relative;z-index:2;height:1px;margin:clamp(32px,4vw,56px) 0;background-image:radial-gradient(circle,rgba(255,255,255,.34) 1px,transparent 1px);background-size:7px 1px}
.foot-btm{position:relative;z-index:2;display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap;font-size:12px}

/* ═══ d-DRIFT SECTIONS (lifted from d-drift.html) ═════════════════ */
.band{padding:clamp(84px,11vw,170px) var(--gut)}
.mid{max-width:840px;margin:0 auto;text-align:center}
.mid .eb{justify-content:center}
.mid .p{max-width:60ch;margin-inline:auto}

/* hero */
.heroD{position:relative;min-height:100svh;overflow:hidden;color:#fff;display:flex;flex-direction:column}
.heroD .proc{position:absolute;inset:0;z-index:0}
.heroD .proc>img{width:100%;height:100%;object-fit:cover;object-position:50% 60%}
.heroD-scrim{
  position:absolute;inset:0;z-index:1;
  background:
    linear-gradient(to bottom,rgba(16,26,61,.62) 0%,rgba(16,26,61,.22) 34%,transparent 60%),
    linear-gradient(to right,rgba(16,26,61,.58) 0%,rgba(16,26,61,.14) 52%,transparent 78%);
}
.heroD-body{position:relative;z-index:3;flex:1;display:flex;flex-direction:column;padding:clamp(112px,15vh,170px) var(--gut) clamp(30px,5vh,56px)}
.heroD h1{max-width:13ch;font-size:clamp(2.7rem,min(8vw,12vh),6.6rem);line-height:1.0;letter-spacing:-.034em}
.heroD-foot{margin-top:auto;display:flex;justify-content:space-between;align-items:flex-end;gap:var(--gut);flex-wrap:wrap}
.heroD-foot .p{color:rgba(255,255,255,.9);max-width:34ch}
.cue{font-size:10px;font-weight:600;letter-spacing:.5em;text-transform:uppercase;color:rgba(255,255,255,.75);display:flex;flex-direction:column;align-items:center;gap:12px;writing-mode:vertical-rl}
.cue i{width:1px;height:46px;background:rgba(255,255,255,.42);display:block}

/* ── hero place-word cycle ────────────────────────────────────────
   The rotating suburbs live in CSS content, not in the DOM, so the H1's
   text stays exactly "Keeping the Shore powered" for crawlers and AI
   agents while humans see the cycle. ::before reserves the width of the
   longest word so the line never reflows mid-swap, and the resting word
   is visible by default: with no animation support, and for
   reduced-motion visitors, the headline simply reads "the Shore".     */
.swap{
  position:relative;display:inline-block;overflow:hidden;vertical-align:top;
  padding-bottom:.16em;margin-bottom:-.16em;
}
.swap::before{content:'Cheltenham';display:block;visibility:hidden}
.swap i{
  position:absolute;left:0;top:0;display:block;
  font-style:normal;white-space:nowrap;opacity:0;
}
.swap i:last-child{opacity:1}
.swap i:nth-child(1)::before{content:'Devonport'}
.swap i:nth-child(2)::before{content:'Cheltenham'}
.swap i:nth-child(3)::before{content:'Bayswater'}
.swap i:nth-child(4)::before{content:'Takapuna'}
.swap i:nth-child(5)::before{content:'Milford'}
.swap i:nth-child(6)::before{content:'Birkenhead'}
.swap i:nth-child(7)::before{content:'the Shore'}

/* full-bleed image band with type over it */
.plate-img{position:relative;min-height:clamp(420px,72svh,760px);display:grid;align-items:end;color:#fff}
.frame{position:absolute;inset:0;z-index:0;overflow:hidden}
.frame::after{content:'';position:absolute;inset:0;z-index:1;background:linear-gradient(to top,rgba(16,26,61,.78) 0%,rgba(16,26,61,.24) 46%,transparent 78%)}
.plate-img .proc{position:absolute;inset:0}
.plate-img .proc>img{width:100%;height:100%;object-fit:cover}
.plate-img .inner{position:relative;z-index:2;padding:clamp(34px,5vw,74px) var(--gut)}

/* numbers */
.figs{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:clamp(28px,4vw,64px);max-width:1180px;margin:0 auto}
.figs .f{font-size:clamp(2.6rem,6vw,4.6rem);font-weight:200;letter-spacing:-.055em;line-height:.9;margin:0 0 16px;color:var(--brand);font-variant-numeric:tabular-nums}
.figs .f em{font-style:normal;font-size:.28em;letter-spacing:0;padding-left:.12em;color:var(--ink-3)}
.figs p{margin:0;font-size:14.5px;line-height:1.55;color:var(--ink-2)}

/* the shuffle: four frames cross-dissolving through a pinned panel */
.shufsec{height:380svh;position:relative}
.shufstick{position:sticky;top:0;height:100svh;overflow:hidden;background:var(--indigo)}
.shuf{position:absolute;inset:0}
.shuf figure{position:absolute;inset:0;margin:0}
.shuf figure .proc{position:absolute;inset:0}
.shuf figure .proc>img{width:100%;height:100%;object-fit:cover}
.shufcap{
  position:absolute;z-index:4;left:var(--gut);bottom:clamp(34px,6vh,74px);right:var(--gut);
  color:#fff;display:flex;justify-content:space-between;align-items:flex-end;gap:24px;flex-wrap:wrap;
}
.shufcap h2{max-width:16ch}
.shufstick::after{content:'';position:absolute;inset:0;z-index:2;background:linear-gradient(to top,rgba(16,26,61,.76),transparent 58%)}
.shufdots{display:flex;gap:7px}
.shufdots i{width:26px;height:2px;background:rgba(255,255,255,.34);display:block}

/* services list with icons that draw on */
.svcD{max-width:1180px;margin:0 auto;border-top:1px solid var(--rule)}
.svcD a{display:grid;grid-template-columns:56px minmax(0,1fr);gap:clamp(18px,3vw,40px);align-items:start;padding:clamp(26px,3.2vw,44px) 0;border-bottom:1px solid var(--rule)}
.svcD a>*{transition:transform .3s cubic-bezier(.2,.7,.3,1)}
.svcD a:hover>*{transform:translateX(10px)}
.svcD h3{font-size:clamp(1.2rem,2.1vw,1.75rem);transition:color .3s}
.svcD a:hover h3{color:var(--brand)}
.svcD p{margin:10px 0 0;font-size:14.5px;line-height:1.6;color:var(--ink-2);max-width:56ch}
.ico{width:44px;height:44px;stroke:var(--brand);fill:none;stroke-width:1.3;stroke-linecap:round;stroke-linejoin:round}

/* hairline tile grid (from f-stack) — services hub + suburb grids */
.svcF{max-width:1180px;margin:0 auto;display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:1px;background:var(--rule);border:1px solid var(--rule)}
.svcF a{background:var(--white);padding:clamp(24px,2.8vw,38px);display:flex;flex-direction:column;transition:background .25s}
.svcF a:hover{background:var(--paper)}
.svcF h3{font-size:clamp(1.15rem,1.7vw,1.45rem);margin:20px 0 0;transition:color .25s}
.svcF h3:first-child{margin-top:0}
.svcF a:hover h3{color:var(--brand)}
.svcF p{margin:10px 0 0;font-size:14px;line-height:1.58;color:var(--ink-2)}
.svcF .ico{width:38px;height:38px}

/* ═══ INTERIOR-PAGE COMPONENTS ═════════════════════════════════════ */

/* compact dark header band — interior pages open here, not a full hero */
.pageband{position:relative;overflow:hidden;background:var(--indigo);color:#fff;padding:clamp(122px,17vh,196px) var(--gut) clamp(52px,7vw,96px)}
.pageband>*{position:relative;z-index:2}
.pageband .glow{z-index:0}
.pageband h1{font-size:clamp(2.3rem,5.2vw,4.8rem);line-height:1.04;letter-spacing:-.03em;max-width:17ch}
.pageband .lede{margin:clamp(22px,3vw,38px) 0 0;max-width:68ch;font-size:clamp(1.02rem,1.18vw,1.16rem);line-height:1.62;color:rgba(255,255,255,.78)}
.pageband .lede strong{color:#fff;font-weight:400}

/* editorial prose column for body sections */
.prose{max-width:760px;margin:0 auto}
.prose h2{font-size:clamp(1.5rem,2.7vw,2.35rem);line-height:1.16;margin:clamp(44px,6vw,76px) 0 18px}
.prose h2:first-child{margin-top:0}
.prose h3{font-size:clamp(1.15rem,1.7vw,1.45rem);margin:clamp(28px,4vw,44px) 0 12px}
.prose p{font-size:clamp(.98rem,1.06vw,1.08rem);line-height:1.66;color:var(--ink-2);margin:0 0 16px;max-width:66ch}
.prose ul{margin:0 0 16px;padding-left:20px}
.prose li{font-size:clamp(.98rem,1.06vw,1.08rem);line-height:1.66;color:var(--ink-2);margin-bottom:8px}
.prose a{color:var(--brand);border-bottom:1px solid var(--tint);transition:border-color .2s}
.prose a:hover{border-color:var(--brand)}

/* flagged callout — the honesty blocks (no 24/7 line etc.)
   accent is the brand square from .eb, on a hairline border: the design
   system's own marks, not a colored side bar */
.callout{position:relative;border:1px solid var(--rule-2);background:var(--paper);padding:20px 24px 20px 46px;margin:clamp(24px,3vw,40px) 0}
.callout::before{content:'';position:absolute;left:24px;top:28px;width:7px;height:7px;background:var(--brand)}
.callout p{margin:0;font-size:15px;line-height:1.6;color:var(--ink-2)}

/* FAQ — native details/summary, no JS */
.faq{max-width:840px;margin:0 auto;border-top:1px solid var(--rule)}
.faq details{border-bottom:1px solid var(--rule)}
.faq summary{
  cursor:pointer;list-style:none;display:flex;justify-content:space-between;align-items:center;gap:20px;
  padding:clamp(18px,2.4vw,26px) 0;font-size:clamp(1.05rem,1.5vw,1.3rem);font-weight:400;color:var(--ink);
}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:'+';font-weight:300;font-size:1.6em;line-height:1;color:var(--brand);flex:none}
.faq details[open] summary::after{content:'\2212'}
.faq summary:focus-visible{outline:2px solid var(--brand);outline-offset:4px}
.faq details p{margin:0 0 clamp(18px,2.4vw,26px);font-size:15.5px;line-height:1.66;color:var(--ink-2);max-width:64ch}
.faq details a{color:var(--brand)}

/* contact form */
.form{display:grid;gap:20px;max-width:600px}
.form .fld label{display:block;font-size:11px;font-weight:600;letter-spacing:.22em;text-transform:uppercase;color:var(--ink-3);margin-bottom:8px}
.form input,.form textarea{
  width:100%;border:1px solid var(--rule-3);background:#fff;color:var(--ink);
  font-family:var(--f);font-size:15px;line-height:1.5;padding:13px 14px;border-radius:0;
}
.form input::placeholder,.form textarea::placeholder{color:var(--ink-3)}
.form textarea{min-height:130px;resize:vertical}
.form input:focus-visible,.form textarea:focus-visible{outline:2px solid var(--brand);outline-offset:0;border-color:var(--brand)}
.form .duo{display:grid;grid-template-columns:1fr 1fr;gap:20px}
@media (max-width:560px){.form .duo{grid-template-columns:1fr}}

/* testimonial cards — live inside the .svcF hairline grid */
.rev{margin:0;background:var(--white);padding:clamp(24px,2.8vw,38px);display:flex;flex-direction:column}
/* drawn, not typed: the unicode star renders as an emoji on some
   platforms and as a hairline glyph on others */
.rev .stars{display:block;width:86px;height:auto;fill:var(--brand);margin:0 0 20px}
.rev blockquote{margin:0;font-size:15.5px;line-height:1.66;color:var(--ink-2)}
.rev .who{margin:auto 0 0;padding-top:20px;font-size:14px;font-weight:600;color:var(--ink)}
.rev .who span{display:block;margin-top:4px;font-size:11px;font-weight:600;letter-spacing:.18em;text-transform:uppercase;color:var(--ink-3)}

/* unverified content flag — must not survive to production */
.confirm{outline:2px dashed #C77700;outline-offset:3px;background:rgba(199,119,0,.08)}

/* contact form success note — shown when the worker redirects to /contact/#sent */
#sent{display:none}
#sent:target{display:block}

/* two-column fact grid used on interior pages */
.split{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:clamp(28px,4vw,64px);max-width:1180px;margin:0 auto}

/* ═══ MOTION (d-drift @supports block) ═════════════════════════════ */
@supports (animation-timeline: view()){

  /* the signature: drift up, hold, drift on and dissolve — homepage */
  .dr{
    animation:drift linear both;animation-timeline:view();
    animation-range:entry 2% exit 98%;animation-duration:1s;
  }
  @keyframes drift{
    0%  {opacity:0;transform:translate3d(0,58px,0) scale(.978)}
    24% {opacity:1;transform:translate3d(0,0,0) scale(1)}
    76% {opacity:1;transform:translate3d(0,0,0) scale(1)}
    100%{opacity:0;transform:translate3d(0,-58px,0) scale(.978)}
  }
  .dr-2{animation-range:entry 8% exit 94%}
  .dr-3{animation-range:entry 14% exit 90%}

  /* interior pages rise without the recede (from f-stack) — copy being
     read must not dissolve out from under the reader */
  .rise{
    animation:rise linear both;animation-timeline:view();
    animation-range:entry 8% cover 26%;animation-duration:1s;
  }
  @keyframes rise{from{opacity:0;transform:translateY(34px) scale(.985)}to{opacity:1;transform:none}}

  /* media parallaxes AND zooms: in at the edges, out through centre */
  .px>img{
    will-change:transform;backface-visibility:hidden;
    animation:px linear both;animation-timeline:view();
    animation-range:cover 0% cover 100%;animation-duration:1s;
  }
  @keyframes px{
    0%  {transform:translate3d(0,-4.5%,0) scale(1.30)}
    50% {transform:translate3d(0,0,0)     scale(1.08)}
    100%{transform:translate3d(0,4.5%,0)  scale(1.30)}
  }

  /* hero plays once, on load — animation-timeline:auto overrides the
     view() binding, which is already part-way through at page top */
  .heroD h1 .rv>i{
    animation:rvload 1.2s cubic-bezier(.19,.9,.26,1) both;animation-timeline:auto;
  }
  .heroD h1 .hl-a>i{animation-delay:.12s}
  .heroD h1 .hl-b>i{animation-delay:.26s}
  @keyframes rvload{from{transform:translate3d(0,112%,0)}to{transform:translate3d(0,0,0)}}

  /* The place word rides the same masked slide as the headline lines, so the
     cycle reads as part of the type rather than a ticker bolted on top.
     Word one arrives with the load stagger and holds while the fixed lines
     finish, then the swap runs on a 1.2s step and stops for good on "the
     Shore". Each word's exit and the next word's entrance share the same
     0.4s window, so the slot is never empty. */
  .swap i{
    will-change:transform;
    animation:swapword 1.6s cubic-bezier(.19,.9,.26,1) both;
  }
  .swap i:nth-child(1){animation-name:swapfirst;animation-duration:2s;animation-delay:.26s}
  .swap i:nth-child(2){animation-delay:1.86s}
  .swap i:nth-child(3){animation-delay:3.06s}
  .swap i:nth-child(4){animation-delay:4.26s}
  .swap i:nth-child(5){animation-delay:5.46s}
  .swap i:nth-child(6){animation-delay:6.66s}
  .swap i:nth-child(7){animation-name:swaprest;animation-duration:.5s;animation-delay:7.86s}

  /* holds longer: it waits for "Keeping" and "powered" to land */
  @keyframes swapfirst{
    0%   {opacity:1;transform:translate3d(0,112%,0)}
    22.5%{opacity:1;transform:translate3d(0,0,0)}
    80%  {opacity:1;transform:translate3d(0,0,0)}
    99%  {opacity:1;transform:translate3d(0,-112%,0)}
    100% {opacity:0;transform:translate3d(0,-112%,0)}
  }
  @keyframes swapword{
    0%  {opacity:1;transform:translate3d(0,112%,0)}
    28% {opacity:1;transform:translate3d(0,0,0)}
    75% {opacity:1;transform:translate3d(0,0,0)}
    99% {opacity:1;transform:translate3d(0,-112%,0)}
    100%{opacity:0;transform:translate3d(0,-112%,0)}
  }
  /* arrives and stays: no exit keyframe, so the cycle ends here */
  @keyframes swaprest{
    from{opacity:1;transform:translate3d(0,112%,0)}
    to  {opacity:1;transform:translate3d(0,0,0)}
  }

  .heroD .eb,.heroD-foot{animation:settle 1.1s cubic-bezier(.16,.8,.24,1) both}
  .heroD .eb{animation-delay:.05s}
  .heroD-foot{animation-delay:.44s}
  @keyframes settle{from{opacity:0;transform:translate3d(0,26px,0)}to{opacity:1;transform:none}}

  /* pageband header settles on load the same way */
  .pageband .eb,.pageband h1,.pageband .lede{animation:settle 1.1s cubic-bezier(.16,.8,.24,1) both}
  .pageband .eb{animation-delay:.05s}
  .pageband h1{animation-delay:.16s}
  .pageband .lede{animation-delay:.3s}

  /* the framed plate: inset on the ground, opens to full bleed at centre */
  .frame{
    animation:openframe linear both;animation-timeline:view();
    animation-range:cover 0% cover 100%;animation-duration:1s;
    will-change:transform;backface-visibility:hidden;
  }
  @keyframes openframe{
    0%  {transform:scale(.90)}
    50% {transform:scale(1)}
    100%{transform:scale(.90)}
  }

  /* four frames cross-dissolving — opposing pairs exactly complementary */
  .shufsec{view-timeline-name:--shuf;view-timeline-axis:block}
  .shuf figure{
    animation-timing-function:linear;animation-fill-mode:both;animation-duration:1s;
    animation-timeline:--shuf;animation-range:contain 0% contain 100%;
  }
  .shuf figure:nth-child(1){animation-name:sh1}
  .shuf figure:nth-child(2){animation-name:sh2}
  .shuf figure:nth-child(3){animation-name:sh3}
  .shuf figure:nth-child(4){animation-name:sh4}
  @keyframes sh1{0%,14%{opacity:1}32%,100%{opacity:0}}
  @keyframes sh2{0%,14%{opacity:0}32%,40%{opacity:1}57%,100%{opacity:0}}
  @keyframes sh3{0%,40%{opacity:0}57%,65%{opacity:1}82%,100%{opacity:0}}
  @keyframes sh4{0%,65%{opacity:0}82%,100%{opacity:1}}

  .shuf .proc>img{
    will-change:transform;backface-visibility:hidden;
    animation-timing-function:linear;animation-fill-mode:both;animation-duration:1s;
    animation-timeline:--shuf;animation-range:contain 0% contain 100%;
  }
  .shuf figure:nth-child(1) .proc>img{animation-name:sz1}
  .shuf figure:nth-child(2) .proc>img{animation-name:sz2}
  .shuf figure:nth-child(3) .proc>img{animation-name:sz3}
  .shuf figure:nth-child(4) .proc>img{animation-name:sz4}
  @keyframes sz1{0%{transform:scale(1.03)}32%,100%{transform:scale(1.20)}}
  @keyframes sz2{0%,14%{transform:scale(1.03)}57%,100%{transform:scale(1.20)}}
  @keyframes sz3{0%,40%{transform:scale(1.03)}82%,100%{transform:scale(1.20)}}
  @keyframes sz4{0%,65%{transform:scale(1.03)}100%{transform:scale(1.20)}}

  .shufdots i{
    animation-timing-function:linear;animation-fill-mode:both;animation-duration:1s;
    animation-timeline:--shuf;animation-range:contain 0% contain 100%;
  }
  .shufdots i:nth-child(1){animation-name:d1}
  .shufdots i:nth-child(2){animation-name:d2}
  .shufdots i:nth-child(3){animation-name:d3}
  .shufdots i:nth-child(4){animation-name:d4}
  /* boundaries must match sh1-sh4 exactly, or the read-out lies */
  @keyframes d1{0%,14%{background:#fff}32%,100%{background:rgba(255,255,255,.34)}}
  @keyframes d2{0%,14%{background:rgba(255,255,255,.34)}32%,40%{background:#fff}57%,100%{background:rgba(255,255,255,.34)}}
  @keyframes d3{0%,40%{background:rgba(255,255,255,.34)}57%,65%{background:#fff}82%,100%{background:rgba(255,255,255,.34)}}
  @keyframes d4{0%,65%{background:rgba(255,255,255,.34)}82%,100%{background:#fff}}

  /* icons draw themselves as the row arrives (pathLength=1 on every path) */
  .ico *{
    stroke-dasharray:1;stroke-dashoffset:1;
    animation:drawico linear both;animation-timeline:view();
    animation-range:entry 24% cover 22%;animation-duration:1s;
  }
  @keyframes drawico{to{stroke-dashoffset:0}}
}

/* ── responsive ──────────────────────────────────────────────────── */
@media (max-width:1000px){
  .foot-grid{grid-template-columns:1fr 1fr}
}
@media (max-width:680px){
  .foot-grid{grid-template-columns:1fr}
  .cut-t,.cut-b{clip-path:none}
  .heroD-foot{flex-direction:column;align-items:flex-start;gap:24px}
  .cue{display:none}
  .shufsec{height:210svh}
  .svcD a{grid-template-columns:40px minmax(0,1fr);gap:16px}
  .ico{width:34px;height:34px}
}
@media (prefers-reduced-motion:reduce){
  *{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}
  /* scroll-driven animations ignore animation-duration — killing the
     timeline and the name is what actually stops them. Resting states are
     the finished states, so this leaves content visible. */
  *{animation-timeline:none!important;animation-name:none!important}
}
