/* ============================================================================
   MARKETING ENGINE — "RINGS WITHIN RINGS" GYROSPHERE  (prototype v6)
   Standalone stylesheet for public/marketing.html only.
   v6: the cone rebuild (WIDER, soft feathered sides, no drawn edge lines, no base
   seam) is entirely in marketing-engine-gyro.webgl.js — this stylesheet is
   unchanged from v5. The ring-styled carousel arrows are still JS-pinned to the
   projection each frame (now to the wider cone's sides); DOM tiles remain the real
   photos + captions with feathered edges, no border.
   Layers on top of /styles.css + /glass.css + /site-glass.css (colors, type,
   .btn/.container/.nav/.footer/.calc-*/.ctaband come from there).
   Nothing here touches or overrides site-wide selectors used by real pages.
   ============================================================================ */

/* ---------- prototype strip (unmistakable — never confuse with the live site) ---------- */
.proto-strip{position:sticky;top:74px;z-index:55;text-align:center;font:600 12.5px/1 var(--body);
  color:#08090c;background:linear-gradient(90deg,#5ee4ff,#00d2ff);padding:7px 14px;letter-spacing:.01em}
.proto-strip b{font-weight:800}

/* =========================================================================
   GYROSPHERE STAGE — pinned scroll choreography (WebGL) / static poster
   ========================================================================= */
/* 2026-07-25 VERTICAL FIX: .gyro-stage is a <section>, which site-wide gets
   `padding:120px 0` (styles.css). For every other section that 120px top
   pad is the right breathing room — but here it just pushed the whole
   pinned stage (and the ring vertically centered inside it) another 120px
   further from the hero above it, on top of the ring already sitting at
   the MIDDLE of a 100vh box (see .gyro-viewport below). Zeroed here;
   restored for the mobile/.no-scrub stacked layout below (unchanged there). */
.gyro-stage{position:relative;min-height:100vh;overflow:clip;padding-top:0}
.gyro-progress{position:absolute;top:0;left:0;height:3px;width:0%;z-index:6;
  background:linear-gradient(90deg,var(--blue),var(--blue-2));box-shadow:0 0 14px var(--glow)}

/* .gyro-sticky is what ScrollTrigger pins (desktop). The gyrosphere is a
   full-bleed, vertically-centered stage. On mobile/reduced-motion (.no-scrub)
   it becomes a normal stacked block. 2026-07-24: the hero copy that used to
   overlay the top of this stage was MOVED OUT into its own .gyro-hero
   section above (see HTML) — replicates HOME's gyro-hero pattern exactly —
   because at the bigger hero-name size the 3-line titles (Communication/
   Marketing) were colliding with the gyrosphere's top ring. ScrollTrigger's
   pin trigger is this element (.gyro-sticky) itself, not .gyro-copy, so
   moving the copy out of the DOM subtree above it does not affect the
   pin/travel/multiply choreography — verified via headless screenshot
   (marketing-engine-gyro.webgl.js `trigger: sticky`). */
.gyro-sticky{position:relative;height:100vh;min-height:560px;overflow:hidden}

/* ENGINE HERO — headline + subhead live ABOVE the gyro stage, in normal
   document flow (stacked, not overlaid on the rings) — moved 2026-07-24 per
   owner request, mirroring home-engine-gyro.css's .gyro-hero exactly.
   .gyro-hero is a plain block section directly before .gyro-stage; kept
   tight against the gyro below (small bottom padding) to match home's
   tightened spacing pass. No scroll cue here (the gyro's own .gyro-hint
   still lives inside .gyro-sticky, untouched). */
.gyro-hero{padding:16px 24px 12px;text-align:center}
.gyro-copy{position:relative;z-index:1;text-align:center;width:min(58ch,90vw,100%);margin:0 auto}
.gyro-copy .eyebrow{justify-content:center}
/* HERO HEADLINE — the engine NAME. Sizing/spacing only here; the aqua
   gradient fill + inner (inset) shadow on the glyphs is the shared
   .aqua-fx treatment in aqua-headline-fx.css (2026-07-24 — replaces the
   old .accent flat-gradient + outer filter:drop-shadow, which is GONE from
   this rule now). line-height/padding-bottom kept (descender-safe) so the
   "g" in "Engine"/"Growth" never clips — the inner .aqua-fx span inherits
   this line-height. Matches the LIVE SITE's hero h1 ceiling
   (clamp(2.7rem,7.2vw,6rem), styles.css) and home's hero name, so every
   hero name on the site reads as the same size. Now sitting ABOVE the gyro
   in normal flow (2026-07-24), so the ring-overlap concern from the old
   overlay position no longer applies. */
.gyro-copy h1.gyro-hero-title{font-size:clamp(2.7rem,7.2vw,6rem);letter-spacing:-.03em;
  line-height:1.15;margin:.2em 0 .14em;padding-bottom:.05em}
/* SUBHEAD — 2026-07-24: was inheriting the site's small/grey default .lead
   (~1rem, ~#c7cfdb) which read as "tiny in comparison and grey" against the
   much bigger aqua hero name above it. Enlarged to scale with the hero and
   lifted off dull grey onto a bright near-white so it reads clearly. */
.gyro-copy .lead{margin:0 auto;max-width:44ch;
  font-size:clamp(1.15rem,2.2vw,1.6rem);line-height:1.5;color:#fff}

/* the gyrosphere fills the pinned frame, rings centred */
/* 2026-07-25 VERTICAL FIX (cont.): the WebGL camera always looks straight at
   its target, which projects to the exact vertical CENTER of this element's
   own render box (see this page's *.webgl.js `camAt`/`proj` — no y-offset in
   the projection math, untouched here) — so with .gyro-viewport filling the
   full 100vh .gyro-sticky, the ring lands at 50vh, ~a whole viewport below
   the hero. translateY nudges the ENTIRE rendered box (canvas ring + the
   .engine-links/.gyro-labels overlay, which are children of THIS element
   and position themselves each frame using ITS OWN clientWidth/clientHeight
   — untouched, so overlays stay perfectly locked to the ring) up as one
   rigid unit, purely at paint time. Nothing the WebGL module reads
   (viewport.clientWidth/clientHeight, used for camera aspect + renderer
   size + card/label projection) changes — a transform never affects layout
   box size — so the pin choreography, camera math and projection are all
   untouched. Reset to none for the mobile/.no-scrub poster layout below
   (different, compact, non-pinned flow with no gap problem to fix). */
.gyro-viewport{position:absolute;inset:0;width:100%;height:100%;z-index:2;
  display:flex;align-items:center;justify-content:center;transform:translateY(-20vh)}

.gyro-canvas{position:absolute;inset:0;width:100%;height:100%;display:block;
  opacity:0;transition:opacity .6s ease}
.gyro-canvas.ready{opacity:1}

/* ---------- STATIC POSTER (pre-WebGL flash-guard + full mobile/reduced-motion look) ----
   Concentric glowing rings = a frozen gyrosphere. Premium, no motion required. */
.gyro-static{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  transition:opacity .6s ease}
.gyro-static.hidden{opacity:0;pointer-events:none}
.gs-core{position:absolute;width:82px;height:82px;border-radius:50%;
  background:radial-gradient(circle,#fff 0%,#8ff2ff 36%,rgba(0,210,255,.6) 62%,transparent 78%);
  filter:blur(1px);box-shadow:0 0 80px 18px var(--glow)}
.gs-ring{position:absolute;border-radius:50%;border:2.5px solid rgba(150,242,255,.85);
  box-shadow:0 0 34px var(--glow),inset 0 0 30px rgba(0,210,255,.35)}
.gs-r1{width:120px;height:120px;transform:rotate(12deg) scaleY(.42)}
.gs-r2{width:210px;height:210px;border-color:rgba(0,210,255,.78);transform:rotate(-24deg) scaleY(.5)}
.gs-r3{width:308px;height:308px;border-color:rgba(93,168,255,.66);transform:rotate(40deg) scaleY(.38)}
.gs-r4{width:404px;height:404px;border-color:rgba(124,240,255,.58);transform:rotate(-64deg) scaleY(.55)}
@media(prefers-reduced-motion:no-preference){
  .gs-r1{animation:gsSpin1 26s linear infinite}
  .gs-r2{animation:gsSpin2 34s linear infinite}
  .gs-r3{animation:gsSpin3 44s linear infinite}
  .gs-r4{animation:gsSpin4 56s linear infinite}
}
@keyframes gsSpin1{from{transform:rotate(0deg) scaleY(.42)}to{transform:rotate(360deg) scaleY(.42)}}
@keyframes gsSpin2{from{transform:rotate(0deg) scaleY(.5)}to{transform:rotate(-360deg) scaleY(.5)}}
@keyframes gsSpin3{from{transform:rotate(0deg) scaleY(.38)}to{transform:rotate(360deg) scaleY(.38)}}
@keyframes gsSpin4{from{transform:rotate(0deg) scaleY(.55)}to{transform:rotate(-360deg) scaleY(.55)}}

/* ---------- projected ring labels (WebGL mode positions these each frame) ---------- */
.gyro-labels{position:absolute;inset:0;pointer-events:none;z-index:5}
.gyro-label{position:absolute;top:0;left:0;transform:translate(-50%,-50%);
  display:inline-flex;align-items:center;gap:7px;white-space:nowrap;
  padding:6px 12px 6px 9px;border-radius:var(--pill);
  background:rgba(9,12,17,.66);border:1px solid rgba(255,255,255,.16);backdrop-filter:blur(9px);
  font:600 .8rem/1 var(--body);color:#fff;text-decoration:none;
  opacity:0;pointer-events:none;transition:border-color .2s,background .2s,opacity .25s}
.gyro-label .gl-dot{width:8px;height:8px;border-radius:50%;background:var(--blue);box-shadow:0 0 9px var(--glow);flex:0 0 auto}
.gyro-labels.show .gyro-label{pointer-events:auto}
.gyro-label:hover{border-color:rgba(0,210,255,.55);background:rgba(0,210,255,.16)}

.gyro-hint{position:absolute;bottom:5vh;left:0;right:0;z-index:4;
  font:600 .82rem/1 var(--mono);letter-spacing:.08em;
  text-transform:uppercase;color:#fff;text-align:center;
  text-shadow:0 2px 5px rgba(0,0,0,.5);transition:opacity .3s var(--ease)}

/* ---------- "now showing" HUD (WebGL projection) — a projected caption, NO box ----
   Real DOM text (accessible + indexable) that names the disc currently projecting.
   No panel/frame: just a soft radial legibility scrim under glowing text, so it
   reads like part of the projection rather than a UI chrome element. */
.gyro-hud{position:absolute;bottom:11vh;left:50%;transform:translate(-50%,10px);z-index:5;
  display:flex;align-items:center;gap:12px;pointer-events:none;
  opacity:0;transition:opacity .45s var(--ease),transform .45s var(--ease)}
.gyro-hud::before{content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:150%;height:340%;z-index:-1;pointer-events:none;
  background:radial-gradient(60% 60% at 50% 50%,rgba(5,8,12,.66),rgba(5,8,12,.22) 60%,transparent 80%)}
.gyro-hud.show{opacity:1;transform:translate(-50%,0)}
.gyro-hud .gh-num{font:800 .82rem/1 var(--mono);letter-spacing:.16em;color:#04121a;
  padding:6px 9px;border-radius:8px;background:linear-gradient(135deg,#8ff2ff,#00d2ff);
  box-shadow:0 0 20px var(--glow)}
.gyro-hud .gh-name{font-family:var(--disp);font-weight:600;font-size:clamp(1.05rem,2.4vw,1.5rem);
  color:#fff;letter-spacing:-.01em;text-shadow:0 0 22px rgba(0,210,255,.55),0 2px 16px rgba(0,0,0,.7)}
.gyro-hud .gh-dots{display:inline-flex;gap:6px;margin-left:4px}
.gyro-hud .gh-dot{width:6px;height:6px;border-radius:50%;background:rgba(255,255,255,.28);
  transition:background .3s,width .3s,box-shadow .3s}
.gyro-hud .gh-dot.on{background:var(--blue);width:18px;border-radius:4px;box-shadow:0 0 10px var(--glow)}

/* ---------- v9: the presenting tool's NAME, UNDER the ring (WebGL hero) ----------
   Real DOM text carrying the site's signature aqua-gradient heading treatment via the
   shared .accent class (linear-gradient + background-clip:text). Because clipped text
   can't take a text-shadow, we lift it off the scene with the site's exact drop-shadow
   (matches styles.css .page-solutions .hero h1). The WebGL module sets left/top inline
   each frame to pin it centred beneath the flat presenting ring; translate() re-centres
   the text on that anchor point. Hidden in the no-WebGL fallback (the DOM disc stages
   carry their own .disc-head titles there). */
.gyro-toolname{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:5;
  pointer-events:none;white-space:nowrap;
  font-family:var(--disp);font-weight:600;font-size:clamp(1.15rem,2.7vw,1.75rem);letter-spacing:-.02em;
  filter:drop-shadow(0 2px 14px rgba(2,6,16,.6));
  opacity:0;transition:opacity .4s var(--ease)}
.gyro-toolname.show{opacity:1}
.no-scrub .gyro-toolname{display:none}

/* ---------- carousel selector (WebGL hero) — visible left/right arrows ----------
   Most users have no side-scroll (Magic Mouse), so the arrows are the primary way
   to move through the projected slides. The WebGL module fades these in while a
   ring is projecting and drives + disables them at the ends. Keyboard: real
   <button>s (Enter/Space) plus ArrowLeft / ArrowRight, wired in the WebGL module. */
.gyro-carousel{position:absolute;inset:0;z-index:6;pointer-events:none;
  opacity:0;transition:opacity .4s var(--ease)}
.gyro-carousel.show{opacity:1}
/* v5: the arrows are PART OF THE PROJECTION — the WebGL module pins them to the
   cone's left/right side edges each frame (left/top set inline), and they're
   styled like the RINGS: a glowing cyan emissive ring, same energy/light. */
.gcar-btn{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);pointer-events:auto;
  width:54px;height:54px;border-radius:50%;cursor:pointer;padding:0;
  border:1.5px solid rgba(140,242,255,.85);
  background:radial-gradient(circle at 50% 42%,rgba(11,20,30,.62),rgba(8,13,20,.40));
  color:#eaffff;font-size:27px;line-height:1;display:flex;align-items:center;justify-content:center;
  text-shadow:0 0 12px rgba(0,220,255,.9),0 0 4px rgba(180,246,255,.95);
  box-shadow:0 0 22px rgba(0,210,255,.55),0 0 42px rgba(0,210,255,.24),inset 0 0 16px rgba(0,210,255,.34);
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
  transition:box-shadow .25s,border-color .2s,transform .12s,opacity .25s}
.gcar-btn::before{content:"";position:absolute;inset:-5px;border-radius:50%;pointer-events:none;
  border:1px solid rgba(0,210,255,.26)}
.gcar-btn:hover{border-color:#c6f7ff;
  box-shadow:0 0 30px rgba(0,220,255,.82),0 0 62px rgba(0,210,255,.4),inset 0 0 20px rgba(0,210,255,.5)}
.gcar-btn:active{transform:translate(-50%,-50%) scale(.92)}
.gcar-btn:focus-visible{outline:2px solid var(--blue);outline-offset:4px}
.gcar-btn:disabled{opacity:.26;cursor:default;box-shadow:0 0 10px rgba(0,210,255,.14)}
.gcar-dots{position:absolute;left:0;right:0;bottom:calc(11vh + 48px);z-index:6;
  display:flex;gap:7px;justify-content:center;pointer-events:none}
.gcar-dots i{width:7px;height:7px;border-radius:50%;background:rgba(255,255,255,.28);transition:background .25s,width .25s}
.gcar-dots i.on{background:var(--blue);width:18px;border-radius:4px;box-shadow:0 0 10px var(--glow)}
.no-scrub .gyro-carousel{display:none}   /* fallback uses the DOM .proj-nav arrows instead */
@media(max-width:760px){.gcar-btn{width:46px;height:46px;font-size:23px}}

/* =========================================================================
   MOBILE / REDUCED-MOTION FALLBACK
   Same gating convention as the rest of the site: phones + prefers-reduced-motion
   never get the pinned WebGL scrub. The gyrosphere shows as the static poster,
   the rings render already-separated (flat) and every slideshow is tap-to-open
   from first paint. This is the "already un-nested" fallback.
   ========================================================================= */
.no-scrub .gyro-stage{min-height:auto;padding-top:120px}
.no-scrub .gyro-sticky{height:auto;min-height:0;padding:20px 0 30px;
  display:flex;flex-direction:column;align-items:center;overflow:visible}
.no-scrub .gyro-viewport{position:relative;inset:auto;width:min(92vw,520px);
  height:min(46vh,380px);margin:20px auto 0;transform:none}
.no-scrub .gyro-canvas{display:none}
.no-scrub .gyro-static{opacity:1}
.no-scrub .gyro-labels{display:none}
.no-scrub .gyro-hint{position:static;bottom:auto;margin-top:16px}

/* ---------- GYRO-IDLE v3 (2026-07-26, THIRD PASS — real scroll length, not
   another smoothstep window) — v1 fixed a DEAD gyro (scrollP stuck at 0). v2
   fixed it reading as tiny/dead-space (grew the box, pulled the camera in).
   Both times the owner came back with the SAME complaint: "it all happens in
   a fraction of a swipe." Widening *-engine-gyro.webgl.js's IDLE_ENTER/EXIT
   smoothstep window (attempt 2) only re-windowed the SAME small pool of raw
   scroll — the section's entire on/off-screen lifetime, MOSTLY off-screen at
   either end — and smoothstep's ease then ate a chunk of even that window. A
   window can't manufacture scroll distance that isn't there; the section was
   just too SHORT. Fixing pacing needed a length fix, not another window.
   FIX: `.gyro-idle .gyro-stage` is now TALL (280vh/280dvh — real, dedicated
   scroll length) while `.gyro-idle .gyro-sticky` holds the canvas viewport-
   sized and visually still using NATIVE CSS `position:sticky;top:0` — NOT a
   GSAP ScrollTrigger pin. Native sticky is safe here in a way the GSAP pin
   was not: GSAP's pin measures innerHeight once (per pin/refresh) and holds
   the stage at a JS-computed position:fixed offset — THAT measurement is
   what goes stale when iOS Safari's address bar collapses mid-scroll, not 3D
   rendering itself. `position:sticky` is native to the browser's own
   compositor, with no JS measurement to go stale; paired with `dvh` (kept
   below) it tracks the real visible viewport cleanly through an address-bar
   collapse. Scroll is never intercepted — the user scrolls completely
   normally throughout; the sticky child just holds its place inside its own
   (now tall) `.gyro-stage`, the same way a sticky table header would.
   `.gyro-idle .gyro-viewport` goes back to the SAME full-bleed geometry the
   desktop/tablet scrub layout already uses (defined earlier in this file,
   unscoped) — still restated explicitly here (not simply deleted) because an
   existing, unscoped `@media(max-width:760px){.gyro-viewport{height:min(42vh
   ,340px)}}` rule further down this file has EQUAL selector specificity to
   the base `.gyro-viewport` rule and would otherwise win by source order on
   every phone-width screen. Restating it under the 2-class `.gyro-idle
   .gyro-viewport` selector pins it to full-bleed regardless of that rule's
   position in the file. Same reasoning for zeroing padding on `.gyro-idle
   .gyro-sticky` (an unscoped same-breakpoint rule sets `padding-top:64px`).
   See the matching idleProgress() rewrite in *-engine-gyro.webgl.js: it now
   reads `.gyro-stage`'s own scroll travel, not `.gyro-sticky`'s — the STICKY
   CHILD's own rect is constant (top≈0) for the whole time it's stuck, so the
   old sticky-rect formula would read a frozen value and go dead on this
   layout. */
/* ---------- v4 CORRECTION (2026-07-26) — native `position:sticky` verified
   BROKEN here, in both Chromium and WebKit: styles.css sets `overflow-x:hidden`
   on <html> AND <body> (site-wide, out of scope to change) — per the CSS
   Overflow spec, setting overflow-x alone forces the UA to also compute
   overflow-y to a scrolling value, which makes <html>/<body> a scroll
   container and the sticky containing-block reference instead of the true
   viewport. Measured: `.gyro-sticky`'s own rect.top tracked window.scrollY in
   exact 1:1 lockstep at every depth tested — it never stuck at all, so the
   canvas physically scrolled off-screen (and the whole gyro along with it)
   well before the scroll-mapped timeline below even finished, independent of
   TIMELINE_END. This is almost certainly the real, whole-saga explanation for
   "it cuts off and scrolls to the next section." `.gyro-sticky` is now
   `position:absolute;top:0` inside `.gyro-stage` (a plain, non-transformed
   positioned ancestor) and JS (idleProgress() in the matching .webgl.js)
   applies `transform:translateY(...)` every scroll to cancel out its natural
   upward drift — clamped to [0, total] so it engages/releases at exactly the
   points a working native sticky would. Same "read fresh every call, never
   cache innerHeight" discipline as the rest of this block, so it carries none
   of the old GSAP-pin staleness risk either. */
/* ---------- v5 CORRECTION (2026-07-26) — root cause fixed upstream, JS
   positioning removed. Owner: "much better but it jitters when scrolling" —
   the v4 JS transform (recomputed in a scroll handler) is inherently a frame
   behind the browser's scroll compositor; iOS momentum scrolling makes that
   lag visible as jitter. No throttling tuning fixes that — it's structural.
   Root cause of v4's "sticky never engages" finding was styles.css's
   `overflow-x:hidden` on <html>/<body> (site-wide) turning them into a
   scroll container per spec, stealing sticky's containing-block reference.
   Fixed at the source: styles.css now uses `overflow-x:clip` (@supports-
   guarded) instead, which blocks horizontal scroll without creating a scroll
   container. `.gyro-idle .gyro-sticky` is back to plain, native
   `position:sticky;top:0` below — no JS transform, nothing fighting the
   compositor, zero jitter by construction. The matching *-engine-gyro.webgl.js
   idleProgress() no longer writes to `.gyro-sticky`'s transform; it only
   reads `.gyro-stage`'s rect for the progress calc, same as before. */
.gyro-idle .gyro-stage{min-height:auto;padding-top:32px;height:280vh}
@supports (height:100dvh){.gyro-idle .gyro-stage{height:280dvh}}
.gyro-idle .gyro-sticky{position:sticky;top:0;width:100%;height:100vh;min-height:560px;
  overflow:hidden;padding:0;margin:0}
@supports (height:100dvh){.gyro-idle .gyro-sticky{height:100dvh}}
.gyro-idle .gyro-viewport{position:absolute;inset:0;width:100%;height:100%;
  margin:0;transform:translateY(-20vh)}
@media(max-width:760px){
  /* 2026-07-24 pass 2: the desktop hero-name clamp's 2.7rem floor (bumped to
     match the live site) is too wide for long words inside the narrow
     mobile .gyro-copy container (min(56ch,90vw)) — verified via headless
     screenshot on the Communication Engine page ("Communication" clipped
     off the right edge at ~430px and below). This mobile-only fluid
     override (no hard floor until it naturally meets the desktop clamp's
     2.7rem right at this breakpoint) keeps hero words on-screen at every
     phone width on all 4 engine pages — applied identically for consistency. */
  .gyro-copy h1.gyro-hero-title{font-size:clamp(2rem,9vw,2.7rem)}
  .gyro-sticky{padding-top:64px}
  .gyro-viewport{height:min(42vh,340px)}
  .gs-r4{width:300px;height:300px}
  .gs-r3{width:238px;height:238px}
  .gs-r2{width:170px;height:170px}
  .gs-r1{width:100px;height:100px}
}

/* ---------- ROI section (numbers reuse .calc-* from styles.css) ---------- */
.roi-section{padding-top:10px}
/* GLASS TILE — same material as .humanity-tile/.hcard: frosted --glass panel
   + canonical edge/curve/rim + the mouse-reactive glint (--lx/--ly/--l-angle,
   driven by the already-loaded glass.js), instead of a flat opaque --bg-1
   card. .calc-inputs/.calc-out (styles.css) get the matching frosted-glass
   treatment too so the whole calculator reads as one glass surface. */
.roi-card{position:relative;overflow:hidden;
  background:var(--glass,rgba(16,24,40,.30));
  backdrop-filter:blur(var(--blur,13px)) saturate(150%) brightness(1.04);
  -webkit-backdrop-filter:blur(var(--blur,13px)) saturate(150%) brightness(1.04);
  border:1px solid var(--glass-border,rgba(255,255,255,.14));border-radius:var(--r-xl);padding:38px 34px;margin-top:8px;
  box-shadow:var(--e2),var(--edge),var(--curve),var(--rim),inset 0 9px 22px var(--inner-top,rgba(255,255,255,.05))}
.roi-card::after{
  content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;z-index:0;
  background:
    radial-gradient(24% 2px at calc(50% + var(--lx,.5)*50%) 1px,rgba(255,255,255,.95),rgba(255,255,255,0) 72%),
    radial-gradient(42% 9px at calc(50% + var(--lx,.5)*50%) 1px,rgba(150,225,255,.4),rgba(150,225,255,0) 74%),
    radial-gradient(2px 24% at calc(100% - 1px) calc(50% - var(--ly,.72)*50%),rgba(255,255,255,.95),rgba(255,255,255,0) 72%),
    radial-gradient(9px 40% at calc(100% - 1px) calc(50% - var(--ly,.72)*50%),rgba(150,225,255,.4),rgba(150,225,255,0) 74%),
    linear-gradient(var(--l-angle,217deg),rgba(255,255,255,.09),rgba(255,255,255,0) 15%);
}
.roi-card>*{position:relative;z-index:1}
@media(max-width:640px){.roi-card{padding:26px 20px}}
.roi-card .calc-inputs{background:var(--glass-2,rgba(16,24,40,.4));
  backdrop-filter:blur(var(--blur,13px)) saturate(150%);-webkit-backdrop-filter:blur(var(--blur,13px)) saturate(150%);
  border:1px solid var(--glass-border,rgba(255,255,255,.14));box-shadow:var(--curve-sm),var(--rim-sm)}
.roi-card .calc-out{background:linear-gradient(150deg,rgba(0,210,255,.16),var(--glass-2,rgba(16,24,40,.4)) 60%);
  backdrop-filter:blur(var(--blur,13px)) saturate(150%);-webkit-backdrop-filter:blur(var(--blur,13px)) saturate(150%);
  border:1px solid rgba(0,210,255,.3);box-shadow:var(--curve-sm),var(--rim-sm)}
/* WHITE LETTERING — 2026-07-24: ROI labels/notes + the accordion subhead +
   Book-a-Call sub-copy/fine-print inherited the site's default grey .lead/
   .dim/.fine/.calc-* (styles.css --ink-2/--muted). Scoped overrides (this
   file only loads on this page — no live-site impact) lift them to white. */
.humanity-head .lead{color:#fff}
.roi-section .center .lead{color:#fff}
.roi-card .calc-field>span{color:#fff}
.roi-card .calc-inwrap i{color:#fff}
.roi-card .calc-out-cell .calc-lbl{color:#fff}
.ctaband .lead{color:#fff}
.ctaband .dim{color:#fff}
.footer .fine{color:#fff}

/* ---------- CTA band: room for the embedded calendar iframe ---------- */
.book-section{padding-top:10px}

/* 2026-07-25 MOBILE BOOKING-WIDGET CLIP FIX — see home-engine-gyro.css for the
   full writeup (byte-identical fix, rolled out to every page that embeds the
   calendar). styles.css's site-wide .ctaband padding+margin squeeze the
   LeadConnector iframe to ~240-270px at phone widths, clipping the Saturday
   column + next-month arrow. styles.css is NOT edited — this file loads after
   it with equal specificity, so this wins. Verified via CDP at 360x800/390x844. */
@media(max-width:560px){
  .ctaband{padding:56px 8px;margin:0 8px}
}

/* BOOK-A-CALL HEADLINE — same shared .aqua-fx gradient + inner-shadow
   treatment as the hero (aqua-headline-fx.css). Sizing/spacing only here;
   the old .accent flat-gradient + outer filter:drop-shadow is GONE
   (2026-07-24 — see aqua-headline-fx.css for why + the tunable values). */
.ctaband h2.book-title{font-size:clamp(2.2rem,5.2vw,4rem);letter-spacing:-.02em;
  line-height:1.15;margin:0 0 .14em;padding-bottom:.05em}
.book-sub{margin:0 auto 6px;max-width:44ch;font-size:1.22rem}

/* NAV LINKS WHITE — 2026-07-25 (owner decision, approved): the plain nav
   links ("Live site" / "The engine" / etc.) inherited the site's grey nav
   convention (styles.css: .nav .links a:not(.btn){color:var(--ink-2)}).
   Everything else on this page was already white; the nav was the one open
   item (see website-build-STATE doc). Scoped to this page only — global
   styles.css untouched, live production unaffected. This file loads after
   styles.css so it wins at equal selector specificity (same load-order
   pattern as the WHITE LETTERING block above). Hover/focus goes aqua
   (--aqua-2) instead of the global's plain #fff-on-hover, which would be
   invisible now that the resting state is already white. The "Book a call"
   pill (.btn/.btn-primary) is untouched — it keeps its own existing styling. */
.nav .links a:not(.btn),
.nav-mobile a:not(.btn){color:#fff}
.nav .links a:not(.btn):hover,
.nav-mobile a:not(.btn):hover,
.nav-mobile a:not(.btn):focus{color:var(--aqua-2)}
