/* ---------- 1. tokens ---------- */
:root{
  /* softer ambient grid (was .07) */
  --grid-line:rgba(0,0,0,.032);
  --gutter:clamp(18px,4vw,40px);
  --shadow-1:0 1px 2px rgba(18,16,12,.04),0 4px 12px rgba(18,16,12,.05);
  --shadow-2:0 2px 6px rgba(18,16,12,.05),0 14px 32px rgba(18,16,12,.09);
  --shadow-3:0 4px 12px rgba(18,16,12,.07),0 24px 54px rgba(18,16,12,.13);
  --focus-ring:var(--accent-2);
}
html.dark{
  --grid-line:rgba(255,255,255,.038);
  --shadow-1:0 1px 2px rgba(0,0,0,.32),0 4px 12px rgba(0,0,0,.28);
  --shadow-2:0 2px 6px rgba(0,0,0,.36),0 14px 32px rgba(0,0,0,.42);
  --shadow-3:0 4px 12px rgba(0,0,0,.42),0 24px 54px rgba(0,0,0,.52);
  --focus-ring:var(--accent);
}

/* ---------- 2. viewport plumbing ---------- */
html{scroll-padding-top:clamp(82px,13vw,110px);-webkit-text-size-adjust:100%;text-size-adjust:100%;}
/* on <html> so it propagates to the viewport — on <body> alone it does not,
   and absolutely-positioned decoration still dragged a scrollbar in */
html,body{overflow-x:clip;}
@supports not (overflow-x:clip){html,body{overflow-x:hidden;}}

/* .lw-rule sits at calc(100% + 26px) outside the container, so it only fits
   once the container stops touching the gutters */
@media(max-width:1419px){.lw-rule{display:none;}}

/* grid backdrop: gentler falloff, tighter cells on small screens */
body::before{
  -webkit-mask-image:radial-gradient(ellipse 112% 72% at 50% 0%,#000 16%,transparent 74%);
  mask-image:radial-gradient(ellipse 112% 72% at 50% 0%,#000 16%,transparent 74%);
}
@media(max-width:690px){body::before{background-size:26px 26px;}}

/* safe-area aware gutters (notched phones, landscape especially) */
.container,.hero-cards{
  padding-left:max(var(--gutter),env(safe-area-inset-left));
  padding-right:max(var(--gutter),env(safe-area-inset-right));
}

/* ---------- 3. fluid type scale (readable at 320px, generous at 1600px) ---------- */
.display{font-size:clamp(30px,6.4vw,76px);}
.section-display{font-size:clamp(25px,4.4vw,44px);}
h2.feature-title{font-size:clamp(22px,3.4vw,29px);}
.page-hero h1{font-size:clamp(30px,6.8vw,80px);}
.sd-hero h1{font-size:clamp(29px,6.6vw,76px);}
.faq-head h2{font-size:clamp(27px,5.6vw,64px);}
.ri-layer h2{font-size:clamp(29px,7vw,86px);}
.lw-title{font-size:clamp(34px,9.6vw,112px);}
.tm-quote{font-size:clamp(19px,3.6vw,38px);}
.foot-newsletter h2{font-size:clamp(21px,2.6vw,30px);}
.body-copy{font-size:clamp(15px,1.4vw,16px);}
.hero .body-copy{font-size:clamp(15.5px,1.7vw,18px);}
@media(max-width:400px){
  /* letter-spacing costs more width than font-size here, so trim that first
     and keep 12px as the legibility floor */
  .eyebrow{font-size:12px;letter-spacing:.06em;}
  .display{letter-spacing:-.01em;}
}

/* ---------- 4. vertical rhythm ---------- */
@media(max-width:690px){
  section{padding-block:clamp(34px,7vw,50px);}
  section.hero,section.final-cta{padding-block:clamp(44px,9vw,64px);}
  section.hero{padding-top:calc(100px + env(safe-area-inset-top));padding-bottom:clamp(30px,6vw,44px);}
  .page-hero,.sd-hero,.contact-page{padding-top:calc(108px + env(safe-area-inset-top));}
}

/* ---------- 5. floating nav ---------- */
.floatnav{top:clamp(10px,1.8vw,22px);box-shadow:var(--shadow-1);}
.floatnav.scrolled{box-shadow:var(--shadow-2);}
.brand-dot{box-shadow:0 2px 10px rgba(226,154,10,.32);}
@media(min-width:1000px) and (max-width:1130px){
  .navlinks a{padding:0 13px;font-size:14.5px;}
  .floatnav .btn{padding:0 20px;font-size:14.5px;}
}
@media(max-width:999px){
  .floatnav{
    left:max(10px,env(safe-area-inset-left));
    right:max(10px,env(safe-area-inset-right));
    top:max(10px,env(safe-area-inset-top));
    height:60px;
  }
}
@media(max-width:400px){
  .floatnav{padding:8px 8px 8px 14px;height:58px;}
  .floatnav .brand{font-size:16px;gap:9px;}
  .brand-dot{width:30px;height:30px;}
}

/* ---------- 6. mobile menu: real viewport height, scrollable, safe area ---------- */
@supports (height:100dvh){.mobile-menu{bottom:auto;height:100dvh;}}
.mobile-menu{
  overflow-y:auto;overscroll-behavior:contain;
  padding-top:max(24px,env(safe-area-inset-top));
  padding-bottom:max(24px,env(safe-area-inset-bottom));
}
.mobile-close{top:max(18px,env(safe-area-inset-top));right:max(18px,env(safe-area-inset-right));}
/* landscape phone: the centred 32px stack does not fit — compact it */
@media(max-height:560px){
  .mobile-menu{justify-content:flex-start;padding-top:72px;}
  .mobile-menu a{font-size:21px;line-height:1.35;}
  .mobile-menu__cta{margin-top:14px;padding:12px 28px;}
}

/* ---------- 7. pinned service stack ---------- */
/* type only — all layout/pinning now lives in section 19, which runs the
   pinned stack on phone and tablet too (see the note there). */
.stack-panel .panel-copy h3{font-family:var(--font-display);font-size:clamp(19px,2.2vw,27px);line-height:1.22;margin-bottom:12px;}
.stack-panel .panel-copy p{font-size:clamp(13.5px,1.25vw,15.5px);line-height:1.6;}
.stack-panel .panel-copy p + p{margin-top:11px;}

/* ---------- 8. website-redesign morph: tuned per screen, never disabled ---------- */
/* see section 20 — the morph now runs at every size instead of degrading to cards */

/* ---------- 9. grids that work at every width (no dead breakpoints) ---------- */
.svc-grid{grid-template-columns:repeat(auto-fit,minmax(min(100%,230px),1fr));}
.process-grid{grid-template-columns:repeat(auto-fit,minmax(min(100%,238px),1fr));}
.trust-grid{grid-template-columns:repeat(auto-fit,minmax(min(100%,258px),1fr));}
.matrix-grid{grid-template-columns:repeat(auto-fit,minmax(min(100%,208px),1fr));}
.inc-grid{grid-template-columns:repeat(auto-fit,minmax(min(100%,248px),1fr));}
.post-grid{grid-template-columns:repeat(auto-fit,minmax(min(100%,288px),1fr));}
.why-grid{grid-template-columns:repeat(auto-fit,minmax(min(100%,218px),1fr));}
.care-grid{grid-template-columns:repeat(auto-fit,minmax(min(100%,268px),1fr));}
.tier-grid{grid-template-columns:repeat(auto-fit,minmax(min(100%,238px),1fr));}
/* .trust-bento: explicit tracks per range, see section 22 */
.price-grid{grid-template-columns:repeat(auto-fit,minmax(min(100%,232px),1fr));}
.price-grid--4{grid-template-columns:repeat(auto-fit,minmax(min(100%,232px),1fr));}
@media(max-width:900px){
  .price-grid{grid-template-columns:1fr;max-width:440px;}
  .price-grid--4{grid-template-columns:repeat(auto-fit,minmax(min(100%,232px),1fr));max-width:560px;}
  .price-card.featured{margin-top:0;order:-1;padding-top:32px;padding-bottom:32px;}
}
@media(max-width:600px){.price-grid--4{grid-template-columns:1fr;max-width:440px;}}

/* ---------- 10. hero ---------- */
@media(max-width:690px){
  /* was: hide "Explore Services" entirely. stack it instead. */
  .hero-ctas{flex-direction:column;align-items:stretch;gap:10px;max-width:320px;margin-inline:auto;}
  .hero-ctas .btn--light{display:inline-flex;}
  .hero-ctas .btn{justify-content:center;}
  .founders-row{gap:10px;}
}
@media(max-width:400px){
  .hcard{padding:20px;min-height:172px;}
  .hcard--dark .stmt{font-size:18px;margin-bottom:16px;}
  .hcard--accent .ladder-mini{gap:7px;}
}

/* ---------- 11. touch devices: no sticky hover, no phantom lift ---------- */
@media(hover:none){
  .btn:hover,.commit-card:hover,.bento-card:hover,.price-card:hover,.price-card.featured:hover,
  .care-card:hover,.svc-card:hover,.process-step:hover,.trust-item:hover,.matrix-item:hover,
  .post-card:hover,.tb:hover,.inc-card:hover,.tier:hover,.faq-item:hover,.chip:hover,
  .social-row a:hover,.newsletter-submit:hover,.tm-nav button:hover,.fav:hover,
  .ct-method:hover .ct-ico,.lw-link:hover .lw-arrow::before{transform:none;}
  .commit-card:hover,.bento-card:hover,.price-card:hover,.price-card.featured:hover,
  .care-card:hover,.svc-card:hover,.post-card:hover,.tb:hover,.matrix-item:hover,
  .faq-item:hover,.btn:hover{box-shadow:none;}
  .svc-card:hover,.process-step:hover,.trust-item:hover,.matrix-item:hover,.post-card:hover,
  .tb:hover,.inc-card:hover,.tier:hover,.price-card:hover{border-color:var(--muted);}
  .chip:hover{background:var(--surface);color:var(--text);border-color:var(--muted);}
  .why-row:hover{padding-left:10px;background:transparent;}
  .svc-item:hover{padding-left:12px;background:transparent;}
  .why-row:hover::before,.svc-item:hover::before{transform:scaleY(0);}
  .social-row a::after{display:none;}
  a:hover .reveal__text,button:hover .reveal__text{transform:none;}
  a:hover .reveal__text::after,button:hover .reveal__text::after{transform:none;}
  .faq-item:hover::before{opacity:0;}
}

/* ---------- 12. tap targets ≥44px on touch ---------- */
@media(pointer:coarse){
  .foot-link{padding-block:10px;}
  .foot-bottom nav a{padding-block:9px;}
  .foot-bottom nav{gap:16px;flex-wrap:wrap;}
  .fav{height:40px;}
  .fav__mark{width:32px;height:32px;font-size:13px;}
  .chip{padding:12px 20px;}
  .outline-pill{padding:14px 24px;}
  .tm-nav button{width:52px;height:52px;}
  .social-row a{width:48px;height:48px;}
  .sd-next a,.post-more{padding-block:8px;}
  /* these two were the only remaining sub-36px targets in the audit */
  .floatnav .brand{min-height:44px;}
  .lw-mail{display:inline-block;padding-block:12px;}
  /* contact.html's mailto sat at 201x17. Padding grows the hit area and the
     matching negative margin gives the space back, so nothing moves. */
  .ct-method a{display:inline-block;padding-block:12px;margin-block:-12px;}
}

/* ---------- 13. forms: no iOS auto-zoom, comfortable targets ---------- */
.newsletter-input{height:52px;}
.newsletter-submit{top:6px;right:6px;}
@media(max-width:860px){
  .newsletter-input,.ct-input,.ct-textarea{font-size:16px;}
  .newsletter-form{max-width:100%;}
}

/* ---------- 14. wide screens ---------- */
@media(min-width:1600px){
  :root{--container:1480px;--gutter:56px;}
  body::before{background-size:40px 40px;}
}

/* ---------- 15. testimonial block on small screens ---------- */
@media(max-width:560px){
  .tm-number{font-size:clamp(92px,30vw,150px);left:-6px;top:30%;opacity:.038;}
  .tm-quote{min-height:0;margin-bottom:26px;}
  .tm-foot{gap:16px;}
  .tm-content{padding-block:20px;}
}

/* ---------- 16. FAQ / footer small-screen tidy ---------- */
/* both sat under the 12px legibility floor; 11.5 still did, so they clear it */
.faq-meta{font-size:12px;}
.post-meta{font-size:12px;letter-spacing:.09em;}
@media(max-width:420px){
  .faq-item{padding:0 8px;border-radius:20px;}
  .faq-item summary{padding:20px 12px;gap:12px;font-size:15.5px;}
  .faq-icon{width:38px;height:38px;}
  .faq-item .a{padding:0 12px 22px 62px;}
  .quote-banner{padding:22px 20px;}
  .lw-arrow{width:56px;height:56px;}
}
@media(max-width:600px){
  .foot-top{gap:30px;}
  footer{padding-block:48px 24px;}
  .foot-bottom{gap:12px;}
}

/* ---------- 17. polish: focus, shadows, eyebrow rule ---------- */
:focus-visible{outline:2px solid var(--focus-ring);outline-offset:3px;box-shadow:0 0 0 5px var(--accent-soft);}
.switch-toggle input:focus-visible ~ .switch-track{outline:2px solid var(--focus-ring);outline-offset:3px;}
.commit-card:hover,.bento-card:hover,.svc-card:hover,.post-card:hover,.tb:hover,
.matrix-item:hover,.inc-card:hover,.tier:hover,.faq-item:hover{box-shadow:var(--shadow-2);}
.price-card:hover{box-shadow:var(--shadow-3);}
.care-card:hover,.trust-item:hover{box-shadow:var(--shadow-1);}

/* inline (not flex) so the rule sits with the first word and centres with it */
.eyebrow::before{content:'';display:inline-block;vertical-align:middle;width:20px;height:1px;background:var(--accent-2);margin-right:10px;margin-bottom:2px;}
.panel-4 .eyebrow::before,.hcard--accent .eyebrow::before,.tb--accent .eyebrow::before,
.ri-light .eyebrow::before,.panel-6 .eyebrow::before{background:currentColor;opacity:.6;}
@media(max-width:400px){.eyebrow::before{width:14px;margin-right:8px;}}

/* ---------- 18. reduced motion belt-and-braces ---------- */
@media(prefers-reduced-motion:reduce){
  .ri-track,.ri-track.ri-on{height:auto;}
  .ri-ball{display:none!important;}
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;}
}

/* ---------- PART 2 — richer visuals + desktop scroll effects everywhere ---------- */

/* ---------- 19. service stack 01–06: pinned on EVERY screen ---------- */
/* The pin is the signature interaction, so it now runs on phone and tablet too.
   Panels are sized to fit the viewport instead of being dropped. */
/* --stack-step is 0: every panel pins at the *same* top as the one before it,
   so each card lands exactly on top of its predecessor and covers it whole —
   no sliver of the previous card's top edge left showing. The staircase used
   to be the depth cue; the ghost index and the shadow carry that now. */
:root{--stack-top:18vh;--stack-step:0px;}
.stack-track{height:calc(6 * 88vh);display:block;}
.stack-panel{
  position:sticky;
  height:clamp(300px,66vh,680px);
  min-height:0;
  overflow:hidden;
  border:1px solid transparent;
  box-shadow:var(--shadow-2);
  z-index:auto;
}
.panel-1{top:calc(var(--stack-top) + 0*var(--stack-step) - 30px);z-index:1;}
.panel-2{top:calc(var(--stack-top) + 1*var(--stack-step) - 30px);z-index:2;}
.panel-3{top:calc(var(--stack-top) + 2*var(--stack-step) - 30px);z-index:3;}
.panel-4{top:calc(var(--stack-top) + 3*var(--stack-step) - 30px);z-index:4;}
.panel-5{top:calc(var(--stack-top) + 4*var(--stack-step) - 30px);z-index:5;}
.panel-6{top:calc(var(--stack-top) + 5*var(--stack-step) - 30px);z-index:6;}

/* a hairline sheen along the top edge gives the stack real depth */
.stack-panel::after{
  content:'';position:absolute;left:0;right:0;top:0;height:1px;z-index:2;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.55),transparent);
  opacity:.5;pointer-events:none;
}
.panel-4::after,.panel-6::after{background:linear-gradient(90deg,transparent,rgba(255,255,255,.3),transparent);}
html.dark .stack-panel::after{background:linear-gradient(90deg,transparent,rgba(255,255,255,.16),transparent);}

/* oversized ghost index — depth without extra markup */
/* The copy centres itself in the panel at every size. The base sheet's
   align-items:start sized this item to its content, so a 594-680px panel had
   250-400px of dead space under the chips — at desktop as much as on a phone. */
.stack-panel .panel-copy{
  position:relative;align-self:stretch;
  display:flex;flex-direction:column;justify-content:center;
}
.stack-panel .panel-copy::before{
  content:attr(data-n);
  position:absolute;right:0;top:50%;transform:translateY(-52%);z-index:-1;
  font-family:var(--font-display);font-size:clamp(90px,13vw,190px);line-height:.8;
  color:currentColor;opacity:.045;pointer-events:none;letter-spacing:-.04em;
}
.panel-4 .panel-copy::before{opacity:.09;}
.panel-6 .panel-copy::before{opacity:.075;}

/* the meta line reads much better as chips */
/* colour:inherit, not the muted .meta default — the chips draw their own
   background from currentColor, so a muted currentColor washes them out */
.stack-panel .meta{
  display:flex;flex-wrap:wrap;gap:7px;margin-top:16px;
  color:inherit;
}
.stack-panel .meta > span{
  /* floor is 12px, not 11.5 — these chips name real capabilities, so they read
     as content rather than as a micro-label, and 1vw only reaches 12.5px past
     a 1250px viewport, which would have left every phone and tablet under it */
  font-size:clamp(12px,1vw,12.5px);line-height:1;letter-spacing:.01em;font-weight:500;
  padding:7px 12px;border-radius:var(--r-pill);
  background:color-mix(in srgb,currentColor 8%,transparent);
  border:1px solid color-mix(in srgb,currentColor 16%,transparent);
  color:currentColor;opacity:.82;
}
@supports not (background:color-mix(in srgb,red 8%,transparent)){
  .stack-panel .meta > span{background:rgba(128,128,128,.12);border-color:rgba(128,128,128,.26);}
}
.panel-6 .meta > span,.panel-4 .meta > span{opacity:.9;}

/* media: scrim + slow drift so the image feels alive while pinned */
.panel-media{
  min-height:0;
  background-size:cover!important;background-position:center!important;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.07);
}
.panel-media::after{
  content:'';position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  background:linear-gradient(160deg,rgba(255,255,255,.09),transparent 42%,rgba(20,18,16,.2));
}
@media(min-width:861px) and (prefers-reduced-motion:no-preference){
  .panel-media{transition:transform 1.1s var(--ease-out);}
  .stack-panel:hover .panel-media{transform:scale(1.028);}
}

/* tablet: tighter two-column */
@media(min-width:691px) and (max-width:900px){
  :root{--stack-top:max(112px,15vh);}
  .stack-panel{padding:24px 22px;}
  .stack-panel .panel-inner{gap:22px;grid-template-columns:1fr 1fr;}
  /* The copy centres itself (shared rule above). What's left here is the photo:
     at 316x626 it was a 0.5 sliver, so equal columns plus a height cap make it
     a 0.75 portrait sitting on the panel's centre line, and the two halves
     read as a deliberate spread instead of text pinned to a corner. */
  .panel-media{align-self:center;height:100%;max-height:470px;}
}

/* phone portrait: media becomes a band on top, copy below — still pinned */
@media(max-width:690px){
  :root{--stack-top:max(104px,13vh);}
  .stack-track{height:calc(6 * 84vh);display:block;}
  .stack-panel{
    position:sticky;height:clamp(300px,64vh,560px);
    padding:0;border-radius:var(--r-card);
  }
  .stack-panel .panel-inner{
    display:grid;grid-template-columns:1fr;grid-template-rows:40% 1fr;
    gap:0;height:100%;max-width:none;
  }
  .panel-media{order:-1;border-radius:0;min-height:0;height:100%;padding:0;max-height:none;}
  .stack-panel .panel-copy{padding:18px 20px 20px;overflow:hidden;}
  .stack-panel .panel-copy h3{font-size:clamp(18px,5.2vw,23px);margin-bottom:9px;}
  .stack-panel .panel-copy p{font-size:13.5px;line-height:1.55;}
  .stack-panel .meta{margin-top:12px;gap:6px;}
  .stack-panel .meta > span{padding:5px 10px;}
  /* a phone panel is ~40% shorter, so the watermark scales down with it */
  .stack-panel .panel-copy::before{font-size:76px;right:4px;}
}

/* short viewports: compress the stagger and the panel, keep the pin */
@media(max-height:619px){
  :root{--stack-top:max(88px,12vh);}
  .stack-track{height:calc(6 * 92vh);display:block;}
  .stack-panel{
    position:sticky;height:min(calc(100dvh - 128px),420px);padding:0;
  }
  .stack-panel .panel-copy h3{font-size:clamp(16px,2.6vh,20px);margin-bottom:7px;}
  .stack-panel .panel-copy p{font-size:12.5px;line-height:1.5;}
  .stack-panel .panel-copy p.meta{margin-top:9px;}
  .stack-panel .meta > span{padding:4px 9px;font-size:10.5px;}
  .stack-panel .panel-copy::before{display:none;}
}
/* short AND wide (landscape phone, short desktop window): copy beside media.
   Below 600px the column would be ~180px, so the narrow rule above keeps
   its media-band-on-top layout and only inherits the height compression. */
@media(max-height:619px) and (min-width:601px){
  .stack-panel .panel-inner{
    grid-template-columns:1.15fr .85fr;grid-template-rows:1fr;gap:0;height:100%;
  }
  .panel-media{order:2;border-radius:0;height:100%;max-height:none;}
  .stack-panel .panel-copy{padding:16px 18px;order:1;overflow:hidden;}
}
@media(max-height:619px) and (max-width:600px){
  /* less room, so the image band gives up height to the copy */
  .stack-panel .panel-inner{grid-template-rows:27% 1fr;}
  .stack-panel .panel-copy{padding:14px 16px;}
}

/* ---------- 20. website-redesign morph: runs on phone + tablet too ---------- */
/* Only the geometry changes per screen. The JS reads these heights, so the
   effect finishes inside the track at every size. */
/* the JS derives its phase lengths from these, and needs > 3x the sticky
   height for both phases plus a hold to fit inside the pin */
.ri-track.ri-on{height:420vh;}
@media(max-width:1100px){.ri-track.ri-on{height:390vh;}}
@media(max-width:860px){.ri-track.ri-on{height:360vh;}}
/* The copy is centred in the pinned panel, so the empty space above the eyebrow
   and below the button IS (panelHeight - contentHeight) / 2 — the only way to
   take it back is to make the panel shorter.
   A pure vh height is the wrong tool for that, because the copy is only 283-436px
   tall at every size while the panel grows with the screen: the slack was 176px
   at 1440x900, 285px on a portrait tablet and 302px on a 1200px-tall monitor, so
   the taller the display the more dead space it invented. The min() caps the
   panel in px, which pins the slack to roughly 80-110px everywhere instead of
   letting it scale; vh still wins on short screens, where 84/88vh is already
   smaller than the cap and the space is tight rather than excessive.
   The top offset stays deliberately small. It is not framing — it is subtracted
   from the pinned scroll range, and the morph needs the tail end of that range
   to finish before the band unsticks, so every px here is a px the circle
   doesn't get. min(64px, 7vh) keeps a sliver of page background above the band
   (the floating nav sits on it, not on the black) and still leaves more tail
   than the section had before this change. */
.ri-on .ri-sticky{height:min(84vh,620px);top:min(64px,7vh);}
@supports (height:100dvh){.ri-on .ri-sticky{height:min(84dvh,620px);top:min(64px,7dvh);}}
/* Tablet and phone carry the *worst* of it — a portrait tablet had 285px of
   slack against 341px of copy — and their copy is the shortest, so they take
   the tighter cap. */
@media(max-width:860px){
  .ri-on .ri-sticky{height:min(88vh,500px);top:min(52px,6vh);}
}
@supports (height:100dvh){
  @media(max-width:860px){.ri-on .ri-sticky{height:min(88dvh,500px);top:min(52px,6dvh);}}
}
.ri-ball{background:var(--ink);}
.ri-on .ri-light{will-change:clip-path;}

/* the layers are absolutely stacked, so both need the same optical centre */
.ri-on .ri-layer{justify-content:center;}
.ri-layer h2{margin-bottom:clamp(18px,3vw,34px);}
.ri-layer .ri-list{margin-bottom:clamp(16px,2.4vw,26px);}
@media(max-width:860px){
  .ri-layer{padding-inline:max(26px,env(safe-area-inset-left));}
  .ri-layer h2{font-size:clamp(27px,7.4vw,42px);max-width:13ch;line-height:1.08;}
  .ri-layer .ri-list{font-size:14px;line-height:1.65;max-width:30ch;}
  /* the reveal circle is small here — a tight column keeps every line inside it */
  .ri-layer .eyebrow{margin-bottom:10px;}
}
@media(max-height:620px) and (max-width:860px){
  .ri-layer h2{font-size:clamp(22px,4.4vh,30px);margin-bottom:12px;}
  .ri-layer .ri-list{font-size:12.5px;margin-bottom:12px;max-width:38ch;}
  .ri-layer .btn{padding:10px 20px;font-size:13px;}
}
/* a soft rim keeps the ball from looking like a hard paste-up */
.ri-on .ri-ball{box-shadow:0 30px 90px rgba(0,0,0,.28);}
html.dark .ri-on .ri-ball{box-shadow:0 30px 90px rgba(0,0,0,.6);}

/* reduced motion / unusably short viewport: two honest static cards */
@media(prefers-reduced-motion:reduce),(max-height:319px){
  .ri-track,.ri-track.ri-on{height:auto;}
  .ri-sticky,.ri-on .ri-sticky{position:static;top:auto;height:auto;display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,300px),1fr));gap:16px;align-items:stretch;padding-block:clamp(34px,7vw,56px);padding-inline:max(var(--gutter),env(safe-area-inset-left));}
  .ri-layer,.ri-on .ri-layer{position:static;inset:auto;pointer-events:auto;display:flex;align-items:flex-start;justify-content:flex-start;text-align:left;padding:clamp(24px,5vw,38px);border-radius:var(--r-card);opacity:1!important;}
  .ri-layer h2{font-size:clamp(26px,5.6vw,40px);max-width:24ch;margin-bottom:16px;}
  .ri-dark{background:var(--surface);border:1px solid var(--muted);}
  .ri-light,.ri-on .ri-light{display:flex;background:var(--ink);clip-path:none!important;}
  .ri-ball,.ri-on .ri-ball{display:none!important;}
  .ri-layer .ri-list{max-width:52ch;}
  .ri-layer .btn{align-self:flex-start;}
}

/* ---------- 21. "How we work": full-bleed inverted section, no accent ---------- */
/* --ink is #000000 in light and #FFFFFF in dark, and --text-invert is exactly
   its opposite, so this pair gives black-on-light / white-on-dark with nothing
   in between. The colour now sits on the section itself rather than on an inset
   ::before slab, so it really is the *whole* section: edge to edge, no radius,
   no shadow, no outer margin, no page background showing around it.
   Net height still drops — the old block spent 38px of margin plus 74px of
   padding at each end, this spends 84px. */
#process{
  position:relative;z-index:1;isolation:isolate;
  margin-block:0;padding-block:clamp(48px,6vw,84px);
  background:var(--ink);color:var(--text-invert);
}
/* the container's extra inset existed to clear the old slab's gutter; with a
   full-bleed background the copy lines up with every other section again */
#process > .container{padding-inline:max(var(--gutter),env(safe-area-inset-left));}
#process .eyebrow{color:var(--text-invert);opacity:.72;}
/* was the gold dash — solid black and white only in here now */
#process .eyebrow::before{background:var(--text-invert);opacity:.5;}
#process h2.feature-title{color:var(--text-invert);}

/* Six steps only ever divide evenly by 3, 2 or 1. The generic auto-fit rule in
   section 9 sized tracks to the space instead: it fitted 4 at 1440 and orphaned
   two, and once the container lost its extra inset above it fitted 5 and
   orphaned one. Explicit tracks, so the last row is never a stub. */
#process .process-grid{
  grid-template-columns:repeat(3,1fr);
  gap:clamp(10px,1.4vw,16px);margin-top:clamp(24px,3.4vw,42px);
}
@media(max-width:900px){#process .process-grid{grid-template-columns:repeat(2,1fr);}}
@media(max-width:560px){#process .process-grid{grid-template-columns:1fr;}}
#process .process-step{
  background:color-mix(in srgb,var(--text-invert) 7%,transparent);
  border:1px solid color-mix(in srgb,var(--text-invert) 14%,transparent);
  color:var(--text-invert);
  padding:clamp(20px,2.4vw,28px) clamp(18px,2.2vw,26px);
  border-radius:var(--r-card);
  overflow:hidden;
}
@supports not (background:color-mix(in srgb,red 7%,transparent)){
  #process .process-step{background:rgba(128,128,128,.16);border-color:rgba(128,128,128,.3);}
  #process .process-step:hover{border-color:rgba(128,128,128,.6);}
}
#process .process-step h3,.process-step h4{color:var(--text-invert);font-size:clamp(17px,1.6vw,20px);}
#process .process-step p{color:var(--text-invert-muted);font-size:clamp(13.5px,1.2vw,14.5px);line-height:1.6;}
/* the step index carried the only gold left in the section; at full-strength
   invert it still reads as the loudest thing in the card, which is the point */
#process .process-step .step-n{
  color:var(--text-invert);font-size:12px;letter-spacing:.14em;margin-bottom:14px;
  display:inline-flex;align-items:center;gap:9px;
}
/* a short rule after the index doubles as the step connector */
#process .process-step .step-n::after{
  content:'';width:26px;height:1px;background:currentColor;opacity:.4;
}
/* the wash that slides in from the number's corner on hover — same geometry as
   before, just drawn in the invert colour instead of the accent */
#process .process-step::before{
  content:'';position:absolute;inset:0;pointer-events:none;border-radius:inherit;
  background:radial-gradient(120% 90% at 0% 0%,var(--text-invert) 0%,transparent 62%);
  opacity:0;transition:opacity .45s var(--ease-out);
}
#process .process-step > *{position:relative;}
#process .process-step:hover{border-color:color-mix(in srgb,var(--text-invert) 55%,transparent);transform:translateY(-5px);}
#process .process-step:hover::before{opacity:.1;}
@media(max-width:520px){
  #process .process-grid{gap:9px;}
  #process .process-step{padding:17px 18px;}
  #process .process-step .step-n{margin-bottom:9px;}
}

/* ---------- 22. "How we work with you": a bento that actually works ---------- */
/* auto-fit gave 3 ragged columns at tablet with .tb--wide spanning 2 of them,
   which left holes. Explicit tracks per range instead. */
.trust-bento{
  grid-template-columns:repeat(4,1fr);
  grid-auto-rows:minmax(clamp(128px,15vw,158px),auto);
  gap:clamp(10px,1.2vw,16px);
}
.tb{
  padding:clamp(19px,2.2vw,26px);
  border-radius:var(--r-card);
  position:relative;overflow:hidden;
}
.tb h3,.tb h4{font-size:clamp(14.5px,1.3vw,16px);line-height:1.35;}
.tb p{font-size:clamp(12.5px,1.1vw,13.5px);line-height:1.5;}
.tb-num{
  font-size:clamp(30px,3.6vw,52px);margin-bottom:8px;
  color:var(--accent-2);letter-spacing:-.03em;
}
.tb--dark .tb-num,.tb--accent .tb-num{color:currentColor;}
/* chips were hard-coded to white alpha, so they only read on the dark tile */
.tb-steps{gap:7px;margin-top:clamp(10px,1.4vw,16px);}
.tb-steps span{
  font-size:12px;padding:6px 11px;white-space:nowrap;
  background:color-mix(in srgb,currentColor 12%,transparent);
  border:1px solid color-mix(in srgb,currentColor 24%,transparent);
}
@supports not (background:color-mix(in srgb,red 12%,transparent)){
  .tb-steps span{background:rgba(255,255,255,.1);border-color:rgba(255,255,255,.2);}
}
/* corner sheen, same language as the stack panels */
.tb::after{
  content:'';position:absolute;left:0;right:0;top:0;height:1px;pointer-events:none;
  background:linear-gradient(90deg,transparent,color-mix(in srgb,currentColor 28%,transparent),transparent);
  opacity:.6;
}
.tb > *{position:relative;}

@media(min-width:701px) and (max-width:1040px){
  /* 2 up. Both wide tiles as full-width bands still leaves holes: the tiles run
     wide,1,1,1,wide,1 — so the second band starts mid-row and strands the cell
     beside it, plus the cell after it. Sending that one band to the end makes
     the fill exact: band / 1+1 / 1+1 / band. */
  .trust-bento{grid-template-columns:repeat(2,1fr);grid-auto-rows:minmax(140px,auto);}
  .tb--wide{grid-column:span 2;}
  .tb--wide:not(.tb--dark){order:1;}
}
@media(max-width:700px){
  .trust-bento{grid-template-columns:1fr;grid-auto-rows:auto;gap:10px;margin-top:26px;}
  .tb--wide{grid-column:auto;}
  .tb{min-height:0;padding:18px 19px;}
  /* "0 Surprise invoices" / "1 Team, not five vendors" are single phrases, so
     the numeral belongs on the heading's line. .tb is display:flex, which
     ignores float — a 2-column grid on just the numbered tiles instead, so the
     unnumbered ones keep their plain stack rather than gaining an empty column. */
  .tb:has(> .tb-num){
    display:grid;grid-template-columns:auto 1fr;column-gap:6px;align-content:start;
  }
  .tb:has(> .tb-num) > .tb-num{grid-area:1 / 1;align-self:center;}
  .tb:has(> .tb-num) > h4{grid-area:1 / 2;align-self:center;}
  .tb:has(> .tb-num) > p,.tb:has(> .tb-num) > .tb-steps{grid-column:1 / -1;}
  .tb-num{font-size:34px;margin-bottom:0;line-height:.9;}
  /* no :has() (older Safari): the numeral just stacks above, still legible */
  @supports not selector(:has(*)){
    .tb-num{margin-bottom:2px;}
  }
  .tb h3,.tb h4{font-size:15px;}
  .tb p{font-size:13px;}
  .tb--dark h3,.tb--dark h4{font-size:16.5px;}
  .tb-steps{margin-top:13px;gap:6px;}
  /* the six steps are the only place that sequence is written out on this
     section, so they hold the 12px floor and take the extra wrap instead */
  .tb-steps span{font-size:12px;padding:5px 10px;}
}
@media(max-width:420px){
  .tb-num{font-size:29px;margin-right:10px;}
  .tb-steps span{padding:5px 9px;}
}

/* ---------- 23. mobile menu, rebuilt ---------- */
.mobile-menu{
  background:
    radial-gradient(120% 78% at 100% 0%,rgba(226,154,10,.20),transparent 58%),
    radial-gradient(90% 60% at 0% 100%,rgba(226,154,10,.10),transparent 60%),
    linear-gradient(168deg,#1d1b19 0%,#131211 62%,#0d0c0b 100%);
  gap:0;justify-content:center;
  padding-inline:max(26px,env(safe-area-inset-left));
  transition:opacity .38s var(--ease-out),backdrop-filter .38s var(--ease-out);
}
/* faint grid echoes the page backdrop so the overlay feels part of the site */
.mobile-menu::before{
  content:'';position:absolute;inset:0;pointer-events:none;opacity:.5;
  background-image:linear-gradient(rgba(255,255,255,.028) 1px,transparent 1px),
                   linear-gradient(90deg,rgba(255,255,255,.028) 1px,transparent 1px);
  background-size:26px 26px;
  -webkit-mask-image:radial-gradient(ellipse 100% 70% at 50% 0%,#000 10%,transparent 78%);
  mask-image:radial-gradient(ellipse 100% 70% at 50% 0%,#000 10%,transparent 78%);
}
/* Send the grid overlay behind instead of lifting every child forward. A
   `.mobile-menu > *` rule would set position on the two absolutely-positioned
   children as well, and :not()-ing them only raises its specificity so it wins
   anyway — the overlay is the thing that should move. */
.mobile-menu::before{z-index:0;}
.mobile-menu__links,.mobile-menu__cta{position:relative;z-index:1;}

.mobile-menu__links{
  counter-reset:mm;width:100%;max-width:420px;
  align-items:stretch;text-align:left;
  border-top:1px solid rgba(255,255,255,.09);
}
.mobile-menu__links a{
  counter-increment:mm;
  display:flex;align-items:center;gap:16px;
  font:400 clamp(24px,7.4vw,34px)/1.15 var(--font-display);
  letter-spacing:-.015em;
  padding:clamp(14px,3.4vw,20px) 4px;
  border-bottom:1px solid rgba(255,255,255,.09);
  transform:translateY(22px);
  transition:opacity .5s var(--ease-out),transform .5s var(--ease-spring),
             color .3s var(--ease-out),padding-left .35s var(--ease-out);
}
/* index numbers with no extra markup */
.mobile-menu__links a::before{
  content:'0' counter(mm);
  font:600 11px/1 var(--font-ui);letter-spacing:.16em;
  color:var(--accent);opacity:.75;flex:none;width:20px;
  transition:opacity .3s var(--ease-out);
}
/* the arrow only appears on the row you touch */
.mobile-menu__links a::after{
  content:'';margin-left:auto;flex:none;
  width:9px;height:9px;border-right:1.5px solid currentColor;border-top:1.5px solid currentColor;
  transform:rotate(45deg) translateX(-4px);opacity:0;
  transition:opacity .3s var(--ease-out),transform .35s var(--ease-spring);
}
.mobile-menu__links a:active,.mobile-menu__links a:focus-visible{
  color:var(--accent);padding-left:10px;
}
.mobile-menu__links a:active::after,.mobile-menu__links a:focus-visible::after{
  opacity:.8;transform:rotate(45deg) translateX(0);
}
@media(hover:hover) and (pointer:fine){
  .mobile-menu__links a:hover{color:var(--accent);padding-left:10px;}
  .mobile-menu__links a:hover::after{opacity:.8;transform:rotate(45deg) translateX(0);}
}
.mobile-menu__cta{
  margin-top:clamp(20px,5vw,30px);width:100%;max-width:420px;
  justify-content:center;padding:16px 30px!important;
  box-shadow:0 16px 40px rgba(226,154,10,.26);
}
/* wordmark top-left, balancing the close button top-right */
.mobile-menu__brand{
  position:absolute;z-index:2;
  top:max(20px,env(safe-area-inset-top));left:max(26px,env(safe-area-inset-left));
  display:flex;align-items:center;gap:9px;
  font-family:var(--font-display);font-size:17px;letter-spacing:-.01em;
  color:var(--text-on-dark);opacity:0;transform:translateY(-8px);
  transition:opacity .5s var(--ease-out) .12s,transform .5s var(--ease-out) .12s;
  pointer-events:none;
}
.mobile-menu.open .mobile-menu__brand{opacity:.92;transform:none;}
.mobile-menu__brand .brand-dot{width:26px;height:26px;box-shadow:0 2px 12px rgba(226,154,10,.4);}
.mobile-close{
  width:44px;height:44px;font-size:0;
  background:rgba(255,255,255,.07);border-color:rgba(255,255,255,.16);
  backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
}
/* draw the × so it is optically centred at any font size */
.mobile-close::before,.mobile-close::after{
  content:'';position:absolute;top:50%;left:50%;width:15px;height:1.5px;
  background:currentColor;border-radius:1px;
}
.mobile-close::before{transform:translate(-50%,-50%) rotate(45deg);}
.mobile-close::after{transform:translate(-50%,-50%) rotate(-45deg);}
@supports (backdrop-filter:blur(2px)){
  .mobile-menu{background-color:rgba(13,12,11,.94);backdrop-filter:blur(16px) saturate(140%);-webkit-backdrop-filter:blur(16px) saturate(140%);}
}
@media(max-height:560px){
  .mobile-menu{justify-content:flex-start;padding-top:max(66px,env(safe-area-inset-top));}
  .mobile-menu__links a{font-size:20px;padding-block:10px;}
  .mobile-menu__cta{margin-top:14px;padding:12px 26px!important;}
  .mobile-menu::before{display:none;}
}

/* ---------- 24. footer: deliberate tablet + phone layouts ---------- */
.foot-top{gap:clamp(24px,3vw,40px);}
.foot-col h5{color:var(--text-muted);}
.social-row a{border:1px solid var(--muted);}

/* tablet: newsletter band, two link columns, follow as a band of its own.
   Three even columns looked wrong here for a content reason, not a sizing one:
   Services has 8 links and Follow Us has two controls, so the third column ran
   dry ~130px before the others and left a hole in the corner of the page. */
@media(min-width:481px) and (max-width:1040px){
  .foot-top{grid-template-columns:1fr 1fr;gap:26px 30px;}
  .foot-newsletter{grid-column:1 / -1;}
  .foot-newsletter .body-copy{max-width:440px;}
  .newsletter-form{max-width:440px;}
  /* the two long lists sit side by side — 8 and 7 items, so they end level */
  .foot-services,.foot-company{grid-row:2;}
  /* and the short one becomes a full-width strip instead of a stub column */
  .foot-follow{
    grid-column:1 / -1;flex-direction:row;align-items:center;flex-wrap:wrap;
    gap:14px 20px;padding-top:20px;margin-top:4px;border-top:1px solid var(--muted);
  }
  .foot-follow h5{margin-bottom:0;}
  /* the strip is align-items:center, but centring is measured on the *outer*
     box — the UA's 1.67em h5 margin-top and the social row's 22px bottom
     margin were both still in play, so the three items sat on three baselines. */
  .foot-follow h5,.foot-follow .social-row{margin-block:0;}
  /* toggle to the far edge, so the strip reads as one line with two ends */
  .foot-follow .theme-toggle-row{margin:0 0 0 auto;}
}
/* phone: one column with hairlines so the sections stay legible */
@media(max-width:480px){
  .foot-top{grid-template-columns:1fr;gap:0;margin-bottom:30px;}
  .foot-newsletter{padding-bottom:26px;border-bottom:1px solid var(--muted);}
  .foot-col{padding-block:20px;border-bottom:1px solid var(--muted);}
  .foot-col:last-child{border-bottom:0;padding-bottom:4px;}
  .foot-col h5{margin-bottom:10px;}
  /* two link columns keeps the 8-item lists from running a whole screen tall */
  .foot-col nav,.foot-col > .foot-link:first-of-type{display:block;}
  .foot-services,.foot-company{
    display:grid;grid-template-columns:1fr 1fr;column-gap:14px;align-items:start;
  }
  .foot-services h5,.foot-company h5{grid-column:1 / -1;}
  .foot-follow{display:block;}
  .foot-follow .social-row{margin-top:4px;flex-wrap:wrap;}
}
@media(max-width:700px){
  .foot-bottom{flex-direction:column;align-items:flex-start;gap:16px;padding-top:20px;}
  .foot-bottom nav{gap:14px 18px;flex-wrap:wrap;}
  .foot-bottom > span,.foot-bottom > p{font-size:12.5px;}
  .theme-toggle-row{margin-top:6px;}
}

/* ---------- 25. pointer + touch feedback ---------- */
/* the ring now carries a label for a few element types */
.cursor-ring{
  transition:opacity .3s var(--ease-out),width .32s var(--ease-spring),
             height .32s var(--ease-spring),margin .32s var(--ease-spring),
             background-color .3s var(--ease-out),border-color .3s var(--ease-out);
  display:grid;place-items:center;
}
.cursor-ring__label{
  font:600 10px/1 var(--font-ui);letter-spacing:.12em;text-transform:uppercase;
  color:var(--ink);opacity:0;transform:scale(.7);white-space:nowrap;
  transition:opacity .22s var(--ease-out),transform .28s var(--ease-spring);
}
html.cursor-on .cursor-ring.has-label{width:76px;height:76px;margin:-38px 0 0 -38px;background:var(--accent);border-color:var(--accent);}
html.cursor-on .cursor-ring.has-label .cursor-ring__label{opacity:1;transform:scale(1);}
html.cursor-on .cursor-ring.has-label{mix-blend-mode:normal;}
/* trailing halo, one frame behind the ring — reads as momentum */
.cursor-halo{
  position:fixed;top:0;left:0;z-index:9998;pointer-events:none;border-radius:50%;
  width:150px;height:150px;margin:-75px 0 0 -75px;opacity:0;
  background:radial-gradient(circle,var(--accent-soft) 0%,transparent 68%);
  transition:opacity .5s var(--ease-out);
}
html.cursor-on .cursor-halo{opacity:.75;}
html.cursor-on.cursor-hidden .cursor-halo{opacity:0;}

/* the press ripple that fires under a fingertip, alongside the touch cursor
   in section 28 — it marks the moment of contact, the ring marks the place */
.tap-ripple{
  position:fixed;z-index:9997;pointer-events:none;border-radius:50%;
  width:14px;height:14px;margin:-7px 0 0 -7px;
  background:var(--accent);opacity:.5;
  animation:tapRipple .58s var(--ease-out) forwards;
}
@keyframes tapRipple{
  from{transform:scale(.35);opacity:.42;}
  to{transform:scale(7);opacity:0;}
}
/* and a real pressed state, since :hover never fires */
@media(hover:none){
  .btn,.svc-card,.post-card,.tb,.price-card,.care-card,.commit-card,.bento-card,
  .process-step,.inc-card,.tier,.matrix-item,.chip,.faq-item summary,.stack-panel{
    -webkit-tap-highlight-color:transparent;
    transition:transform .18s var(--ease-out),opacity .18s var(--ease-out);
  }
  .btn:active,.chip:active{transform:scale(.965);}
  .svc-card:active,.post-card:active,.tb:active,.price-card:active,.care-card:active,
  .commit-card:active,.bento-card:active,.process-step:active,.inc-card:active,
  .tier:active,.matrix-item:active{transform:scale(.985);}
}
@media(prefers-reduced-motion:reduce){
  .cursor-halo,.tap-ripple{display:none;}
}

/* ---------- 26. scroll-linked reveals on touch too ---------- */
/* the IntersectionObserver reveal was already global; this just makes the
   motion read on a small screen, where 28px of travel looked like a glitch */
@media(max-width:860px){
  .stagger-el{transform:translateY(20px);}
  .stagger-el.in{transform:none;}
}

/* ---------- 27. tighter section bottoms ---------- */
/* Every section rule in the base sheet uses the padding-block *shorthand*, so
   one edge cannot be touched in place — it has to be re-declared afterwards,
   which is what this layer's cascade position is for. Tops are left alone on
   purpose: a heading keeps its full run-up, the block just stops closer to
   whatever follows it. About a third comes off each bottom, so the gap between
   two sections at 1440 goes 144px -> 118px and still reads as a break. */
section,.stack-section{padding-bottom:clamp(26px,3.2vw,58px);}   /* was 40-90 */
section.hero{padding-bottom:clamp(40px,6vw,88px);}               /* was 64-150 */
/* the last band before the footer, which has 64px of its own top padding —
   this was the widest dead stretch on the page at every size. Written as a
   compound because the base declares it that way too, and a bare .final-cta
   loses to section.final-cta no matter how late it comes. */
section.final-cta,.final-cta{padding-bottom:clamp(48px,7vw,96px);}  /* was 144 */
/* the subpage heros already ran tight, so they only give up a little */
.page-hero{padding-bottom:clamp(22px,2.8vw,38px);}               /* was 30-54 */
.sd-hero{padding-bottom:clamp(18px,2.2vw,30px);}                 /* was 24-40 */
.contact-page{padding-bottom:clamp(44px,5.6vw,76px);}            /* was 70-120 */

/* #process keeps its symmetric padding: that one is the inset of a filled
   block, not whitespace between two, and a short bottom would look lopsided. */

@media(max-width:690px){
  section,.stack-section{padding-bottom:clamp(22px,4.4vw,32px);}  /* was 34-50 */
  section.hero{padding-bottom:clamp(22px,4.4vw,32px);}            /* was 30-44 */
  .final-cta{padding-bottom:clamp(30px,5.8vw,42px);}              /* was 44-64 */
  section.final-cta{padding-bottom:clamp(30px,5.8vw,42px);}
}

/* ---------- 28. the cursor effect on touch, led by a fingertip ---------- */
/* Same three parts as the desktop cursor — the exact dot, the lerped ring, the
   trailing halo — but a fingertip is ~45px across and sits *on top of* the
   point it names, so the 40px desktop ring would spend its whole life hidden
   under a thumb. On touch every part steps up a size and the rim thickens, so
   what you see is a ring around your finger instead of a ring beneath it. */
html.cursor-touch .cursor-ring{width:62px;height:62px;margin:-31px 0 0 -31px;border-width:1.5px;}
html.cursor-touch.cursor-on .cursor-ring.is-hover{width:88px;height:88px;margin:-44px 0 0 -44px;}
html.cursor-touch.cursor-on .cursor-ring.has-label{width:94px;height:94px;margin:-47px 0 0 -47px;}
html.cursor-touch .cursor-ring__label{font-size:11px;letter-spacing:.1em;}
/* The dot lands directly under the fingertip, where nobody can see it, so it
   only earns its keep on a fast drag — the moment the ring falls behind and
   the dot is the one thing still at the finger. Softened so it reads as the
   leading edge of the ring rather than a second object. */
html.cursor-touch .cursor-dot{width:9px;height:9px;margin:-4.5px 0 0 -4.5px;}
html.cursor-touch.cursor-on .cursor-dot{opacity:.5;}
html.cursor-touch.cursor-on.cursor-hidden .cursor-dot{opacity:0;}
/* and it steps aside the moment the ring takes over, exactly as on desktop —
   otherwise a 9px ink dot sits in the middle of the solid gold label disc.
   The touch script also applies is-hover to the dot for a labelled target,
   which the desktop sheet does not: there the dot *is* the pointer, because
   the real cursor is hidden. Here the fingertip is, so the dot has nothing
   left to say once a 94px disc is spelling the action out. */
html.cursor-touch.cursor-on .cursor-dot.is-hover{opacity:0;}
/* the halo grows with the ring so the momentum smear still frames it */
html.cursor-touch .cursor-halo{width:196px;height:196px;margin:-98px 0 0 -98px;}
html.cursor-touch.cursor-on .cursor-halo{opacity:.6;}
html.cursor-touch.cursor-on.cursor-hidden .cursor-halo{opacity:0;}
/* A touch cursor is discontinuous: it has to appear when a finger lands and
   leave when it lifts. A .3s fade is right for arriving and too abrupt for
   leaving, so the hidden state gets a longer, softer exit. */
html.cursor-touch.cursor-on.cursor-hidden .cursor-dot,
html.cursor-touch.cursor-on.cursor-hidden .cursor-ring{transition-duration:.42s;}
/* three elements moving every frame on a phone GPU: promote them once here
   rather than letting the compositor rediscover it on each gesture */
html.cursor-touch .cursor-ring,html.cursor-touch .cursor-dot,html.cursor-touch .cursor-halo{
  will-change:transform;
}

/* ---------- 25. mobile + tablet menu: monochrome pass ---------- */
/* Neutralises every gold/amber value inside the drawer while leaving the
   "Start a Project" CTA on --accent. Colour values only - no layout,
   spacing, type, size or position is touched. Scoped to the widths where
   the drawer is actually reachable (hamburger appears at <=999px). */
@media(max-width:999px){
  /* flat #111111 ground: kills both gold radials, the brown ramp and the
     @supports backdrop-filter background-color override further up */
  .mobile-menu,
  .mobile-menu.open{
    background-image:none;
    background-color:#111111;
  }
  /* wordmark dot: gold gradient -> flat white, gold glow removed */
  .mobile-menu__brand .brand-dot{
    background:#FFFFFF;
    box-shadow:none;
  }
  .mobile-menu__brand{color:#FFFFFF;}
  /* close icon */
  .mobile-close{color:#FFFFFF;}
  /* index numbers 01-04: gold -> subtle grey */
  .mobile-menu__links a::before{
    color:rgba(255,255,255,.55);
  }
  /* link colours incl. pressed / focused states: gold -> white
     (padding-left shift is left untouched so motion is unchanged) */
  .mobile-menu__links a{color:#FFFFFF;}
  .mobile-menu__links a:active,
  .mobile-menu__links a:focus-visible{color:#FFFFFF;}
}
@media(max-width:999px) and (hover:hover) and (pointer:fine){
  .mobile-menu__links a:hover{color:#FFFFFF;}
}
