/* ═══════════════════════════════════════════════════════════════
   DoubleDown AI — TEST SITE design system
   Direction sourced from 7 Envato After Effects templates.
   Three tones only: OLED black · mint field · off-white paper.
   NO GOLD. Solid type only. Transitions are the spine.
   ═══════════════════════════════════════════════════════════════ */

@font-face{font-family:'Satoshi';src:url('/assets/fonts/th/satoshi-400.woff2') format('woff2');font-weight:400;font-display:swap}
@font-face{font-family:'Satoshi';src:url('/assets/fonts/th/satoshi-500.woff2') format('woff2');font-weight:500;font-display:swap}
@font-face{font-family:'Satoshi';src:url('/assets/fonts/th/satoshi-700.woff2') format('woff2');font-weight:700;font-display:swap}
@font-face{font-family:'Satoshi';src:url('/assets/fonts/th/satoshi-900.woff2') format('woff2');font-weight:900;font-display:swap}
@font-face{font-family:'Switzer';src:url('/assets/fonts/th/switzer-400.woff2') format('woff2');font-weight:400;font-display:swap}
@font-face{font-family:'Switzer';src:url('/assets/fonts/th/switzer-500.woff2') format('woff2');font-weight:500;font-display:swap}
@font-face{font-family:'Switzer';src:url('/assets/fonts/th/switzer-600.woff2') format('woff2');font-weight:600;font-display:swap}
@font-face{font-family:'Cabinet';src:url('/assets/fonts/th/cabinet-800.woff2') format('woff2');font-weight:800;font-display:swap}
@font-face{font-family:'Cabinet';src:url('/assets/fonts/th/cabinet-900.woff2') format('woff2');font-weight:900;font-display:swap}

@layer th-scene;

/* ══════════ 01 · TOKENS ══════════ */
:root{
  /* tone 1 — void */
  --void:#000;
  --ink:#050807;
  --ink-2:#0A0E0C;
  --ink-3:#0F1613;
  /* tone 2 — mint field */
  --mint:#4FD8A6;
  --mint-hi:#66E9B9;
  --mint-lo:#37C08C;
  --glow:#34F5AD;
  --emerald:#10B981;
  --deep:#063D2B;
  --deep-2:#02180F;
  --on-mint:#02241A;
  /* tone 3 — paper */
  --paper:#F2F7F4;
  --paper-2:#E4EEE9;
  --on-paper:#04241A;
  --paper-soft:rgba(4,36,25,.58);

  --line:rgba(255,255,255,.085);
  --line-2:rgba(255,255,255,.15);
  --line-ink:rgba(2,36,25,.14);
  --line-ink-2:rgba(2,36,25,.26);

  --e-out:cubic-bezier(.16,1,.3,1);
  --e-soft:cubic-bezier(.32,.72,0,1);
  --e-io:cubic-bezier(.62,.05,.29,1);
  --e-back:cubic-bezier(.34,1.56,.64,1);

  --pad:clamp(20px,5vw,80px);
  --maxw:1520px;
  --rad:26px;
}

/* ══════════ 02 · BASE ══════════ */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:auto}
body{
  margin:0;background:var(--void);color:#fff;
  font-family:'Switzer',ui-sans-serif,system-ui,-apple-system,sans-serif;
  font-weight:400;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
  /* clip, NOT hidden — hidden makes this a scroll container and kills every position:sticky */
  overflow-x:clip;
}
main{overflow-x:clip;width:100%;max-width:100%}
body.is-locked{overflow:hidden}
img,svg{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
ul{margin:0;padding:0;list-style:none}
p{margin:0}
::selection{background:var(--mint);color:#00110a}
:focus-visible{outline:2px solid var(--mint);outline-offset:3px;border-radius:6px}

h1,h2,h3,h4{margin:0;font-family:'Satoshi',ui-sans-serif,system-ui,sans-serif;font-weight:900;line-height:.92;letter-spacing:-.045em}
.h-hero{font-size:clamp(2.5rem,6.1vw,6.9rem)}
.h-giant{font-size:clamp(2.9rem,9.4vw,10.2rem);letter-spacing:-.055em}
.h-sec{font-size:clamp(2.2rem,5.7vw,5.4rem);letter-spacing:-.05em}
.h-mid{font-size:clamp(1.75rem,3.7vw,3.4rem);letter-spacing:-.045em}
.h-sm{font-size:clamp(1.25rem,2vw,1.7rem);letter-spacing:-.04em}
.kinetic{font-family:'Cabinet',ui-sans-serif,sans-serif;font-weight:900;letter-spacing:-.055em;line-height:.86}
.lede{font-size:clamp(1rem,1.5vw,1.22rem);line-height:1.5;color:rgba(255,255,255,.58);letter-spacing:-.012em;max-width:62ch}
.lede--ink{color:var(--paper-soft)}
.lede--mint{color:rgba(2,36,25,.66)}
@layer th-scene{
.wrap{position:relative;z-index:2;max-width:var(--maxw);margin:0 auto}
.wrap--nar{max-width:1180px}
}

/* ══════════ 03 · ATMOSPHERICS ══════════ */
.grain{
  position:fixed;inset:0;z-index:70;pointer-events:none;opacity:.05;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
.dust{
  position:absolute;inset:0;pointer-events:none;opacity:.45;
  background-image:
    radial-gradient(1.3px 1.3px at 18% 24%,rgba(255,255,255,.5),transparent),
    radial-gradient(1px 1px at 74% 12%,rgba(255,255,255,.4),transparent),
    radial-gradient(1.5px 1.5px at 42% 78%,rgba(255,255,255,.34),transparent),
    radial-gradient(1px 1px at 88% 62%,rgba(255,255,255,.44),transparent),
    radial-gradient(1.2px 1.2px at 8% 68%,rgba(255,255,255,.3),transparent),
    radial-gradient(1px 1px at 61% 41%,rgba(255,255,255,.36),transparent),
    radial-gradient(1.1px 1.1px at 31% 8%,rgba(255,255,255,.26),transparent),
    radial-gradient(1px 1px at 95% 32%,rgba(255,255,255,.3),transparent);
}
.blob{position:absolute;border-radius:50%;filter:blur(80px);will-change:transform;pointer-events:none}
.blob--a{width:52vw;height:52vw;background:radial-gradient(circle at 35% 35%,rgba(52,245,173,.5),rgba(16,185,129,.14) 55%,transparent 72%)}
.blob--b{width:46vw;height:46vw;background:radial-gradient(circle at 60% 40%,rgba(79,216,166,.36),rgba(6,61,43,.24) 58%,transparent 74%)}
.blob--c{width:40vw;height:40vw;background:radial-gradient(circle at 50% 50%,rgba(2,24,15,.95),rgba(2,24,15,.3) 60%,transparent 75%)}
/* the second dark orb — a mesh needs a dark body crossing the bright ones, not just
   two greens sitting still next to each other (AE-01/AE-03 both run bright + dark) */
.blob--d{width:44vw;height:44vw;background:radial-gradient(circle at 44% 46%,rgba(2,16,10,.9),rgba(2,20,13,.28) 58%,transparent 76%)}
/* the dark blob that sits ON a mint field (AE: mint frame with a deep-green bloom behind the card) */
.blob--shade{width:64vw;height:64vw;filter:blur(92px);background:radial-gradient(circle at 45% 40%,rgba(3,58,40,.52),rgba(3,58,40,.14) 58%,transparent 74%)}
/* soft green organic bloom for the paper tone */
.blob--paper{width:56vw;height:56vw;filter:blur(78px);background:radial-gradient(circle at 42% 38%,rgba(16,185,129,.34),rgba(79,216,166,.13) 56%,transparent 74%)}

/* ── the mesh: the orbs DRIFT ──────────────────────────────────────────────
   The AE templates never hold a static gradient — bright and dark orbs cross
   each other slowly and the field never repeats. Four orbs on four different
   periods (37/43/53/61s — coprime, so the pattern does not visibly loop) is
   the whole effect. Transform + opacity only, so it stays on the compositor
   and never triggers layout. blur() is already committed by .blob; animating
   the transform of an already-blurred layer is cheap, animating the blur is
   not — never put filter in these keyframes. */
@keyframes meshA{0%,100%{transform:translate3d(0,0,0) scale(1)}
  33%{transform:translate3d(6vw,4vh,0) scale(1.12)}
  66%{transform:translate3d(-3vw,7vh,0) scale(.94)}}
@keyframes meshB{0%,100%{transform:translate3d(0,0,0) scale(1)}
  30%{transform:translate3d(-7vw,-5vh,0) scale(1.08)}
  70%{transform:translate3d(4vw,-2vh,0) scale(.9)}}
@keyframes meshC{0%,100%{transform:translate3d(0,0,0) scale(1);opacity:1}
  40%{transform:translate3d(9vw,6vh,0) scale(1.18);opacity:.82}
  75%{transform:translate3d(-5vw,-4vh,0) scale(.88);opacity:1}}
@keyframes meshD{0%,100%{transform:translate3d(0,0,0) scale(1.04);opacity:.9}
  45%{transform:translate3d(-8vw,9vh,0) scale(.86);opacity:1}
  80%{transform:translate3d(5vw,3vh,0) scale(1.15);opacity:.78}}
.blob--a{animation:meshA 37s ease-in-out infinite}
.blob--b{animation:meshB 43s ease-in-out infinite;animation-delay:-9s}
.blob--c{animation:meshC 53s ease-in-out infinite;animation-delay:-21s}
.blob--d{animation:meshD 61s ease-in-out infinite;animation-delay:-14s}
.blob--shade{animation:meshB 47s ease-in-out infinite}
.blob--paper{animation:meshA 59s ease-in-out infinite}
.s-paper__fx .blob--paper:nth-child(2){animation:meshC 67s ease-in-out infinite;animation-delay:-30s}

.lit{position:relative}
.lit::after{
  content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  background:radial-gradient(340px circle at var(--mx,50%) var(--my,50%),rgba(52,245,173,.16),transparent 62%);
  opacity:0;transition:opacity .6s var(--e-soft);
}
.lit:hover::after{opacity:1}

/* ══════════ 04 · TRANSITIONS (the spine) ══════════
   Six named entries. The baker refuses two of the same in a row.
   The 4-point star "sparkle" was cut — Duval disliked it wherever it appeared.
   .rise and .split replace it. */
.wipe{clip-path:inset(36% 24% 36% 24% round 999px);will-change:clip-path}
.iris{clip-path:circle(16% at 50% 58%);will-change:clip-path}
/* curtain lifting off the bottom edge */
.rise{clip-path:inset(100% 0 0 0);will-change:clip-path}
/* a horizontal slit opening vertically */
.split{clip-path:inset(50% 0 50% 0);will-change:clip-path}
/* horizontal reveal */
@layer th-scene{
.band{clip-path:inset(0 100% 0 0);will-change:clip-path}
}
/* ── four more, studied off the AE renders 2026-07-28 ──
   .goo     organic blob opening      (AE-01 SaaS Fluid — liquid mesh)
   .swell   a pill growing into a field (AE-03 — the stadium that becomes the scene)
   .defocus racks focus, does not move  (AE-03 — the blur-out beat)
   .streak  words arrive with motion blur (AE-05 — "Bot" flying past)
   The no-two-in-a-row guard now rotates through ten, not six. */
.goo{clip-path:ellipse(22% 18% at 46% 56%);will-change:clip-path}
.swell{clip-path:inset(34% 18% 34% 18% round 999px);will-change:clip-path,transform}
.defocus{filter:blur(22px);opacity:.3;will-change:filter,opacity}
.streak .rwl>i{will-change:transform,filter,opacity}
/* .streak drives its own words, so the base .rw lift must not also run on it */
.streak.is-in .rwl>i{transition:none}
/* band curtain — mint bars that sweep off to expose the scene beneath */
.bandfx{position:absolute;inset:0;z-index:6;pointer-events:none;display:flex;flex-direction:column}
.bandfx i{display:block;flex:1;background:var(--mint);transform-origin:0 50%;will-change:transform}
.bandfx i:nth-child(even){transform-origin:100% 50%;background:var(--mint-lo)}
/* push-through: scales up out of a blur */
.dolly{will-change:transform,filter,opacity}
/* colour-field hard cut is driven from JS (kinetic scene) */

/* ══════════ 05 · PRIMITIVES ══════════ */
/* double bezel — outer shell + inner core, never a single flat card */
.shell{padding:6px;border-radius:calc(var(--rad) + 6px);
  background:linear-gradient(160deg,rgba(255,255,255,.07),rgba(255,255,255,.015));
  border:1px solid var(--line)}
.core{border-radius:var(--rad);background:linear-gradient(165deg,#0B100E,#050706 60%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.09);overflow:hidden}
.shell--ink{background:linear-gradient(160deg,rgba(2,36,25,.14),rgba(2,36,25,.03));border-color:var(--line-ink)}
.core--ink{background:linear-gradient(165deg,#fff,var(--paper-2));box-shadow:inset 0 1px 0 rgba(255,255,255,.9);color:var(--on-paper)}

/* button-in-button — the arrow always lives in its own circular chip */
.btn{
  --h:58px;position:relative;display:inline-flex;align-items:center;gap:.9rem;
  height:var(--h);padding:0 8px 0 26px;border-radius:999px;
  font-family:'Switzer';font-weight:600;font-size:1rem;letter-spacing:-.012em;white-space:nowrap;
  transition:transform .55s var(--e-soft),background .5s var(--e-soft),color .4s var(--e-soft),border-color .5s var(--e-soft),box-shadow .55s var(--e-soft);
}
.btn:active{transform:scale(.978)}
.btn__chip{width:calc(var(--h) - 16px);height:calc(var(--h) - 16px);flex:none;border-radius:50%;
  display:grid;place-items:center;transition:transform .55s var(--e-soft),background .5s var(--e-soft)}
.btn__chip svg{width:16px;height:16px}
.btn:hover .btn__chip{transform:translate(3px,-3px) scale(1.06)}
.btn--mint{background:var(--mint);color:#00170E;box-shadow:inset 0 1px 0 rgba(255,255,255,.5),0 12px 34px -20px rgba(0,0,0,.9)}
.btn--mint .btn__chip{background:rgba(0,23,14,.1)}
.btn--mint:hover{background:var(--mint-hi)}
.btn--mint:hover .btn__chip{background:rgba(0,23,14,.16)}
.btn--line{border:1px solid var(--line-2);color:rgba(255,255,255,.92)}
.btn--line .btn__chip{background:rgba(255,255,255,.07)}
.btn--line:hover{border-color:rgba(52,245,173,.5);color:#fff}
.btn--line:hover .btn__chip{background:rgba(52,245,173,.18)}
.btn--ink{background:#03130D;color:#EAFBF3;box-shadow:inset 0 1px 0 rgba(255,255,255,.12),0 16px 40px -24px rgba(0,0,0,.9)}
.btn--ink .btn__chip{background:rgba(255,255,255,.1)}
.btn--ink:hover{background:#02241A}
.btn--ink-line{border:1px solid var(--line-ink-2);color:var(--on-mint)}
.btn--ink-line .btn__chip{background:rgba(1,40,27,.09)}
.btn--ink-line:hover{border-color:rgba(1,40,27,.6)}
.btn--sm{--h:44px;padding:0 6px 0 18px;font-size:.9rem;gap:.7rem}
.btn--sm .btn__chip svg{width:13px;height:13px}
.cta-row{display:flex;flex-wrap:wrap;gap:.7rem}
.cta-row--c{justify-content:center}

/* stadium glass card — AE's outlined pill holding the headline */
.stadium{
  position:relative;margin:0 auto;
  padding:clamp(2.4rem,5.2vw,4rem) clamp(1.5rem,5vw,4.5rem) clamp(2.8rem,5.6vw,4.2rem);
  border:1px solid rgba(255,255,255,.19);border-radius:clamp(52px,10vw,999px);
  background:linear-gradient(180deg,rgba(255,255,255,.045),rgba(255,255,255,.008));
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.13);
}
.stadium--mint{border-color:rgba(2,36,25,.2);background:linear-gradient(180deg,rgba(255,255,255,.3),rgba(255,255,255,.06));box-shadow:inset 0 1px 0 rgba(255,255,255,.5)}

/* white prompt pill + sparkle badge + bloom — the single most-repeated AE object */
.prompt{position:relative;display:inline-flex;justify-content:center;width:min(100%,560px)}
.prompt__bloom{position:absolute;inset:-40px -28px;border-radius:999px;
  background:radial-gradient(60% 120% at 50% 50%,rgba(52,245,173,.6),rgba(16,185,129,.2) 55%,transparent 76%);
  filter:blur(28px);animation:bloom 5s ease-in-out infinite}
@keyframes bloom{0%,100%{opacity:.7;transform:scale(1)}50%{opacity:1;transform:scale(1.06)}}
.prompt__bar{position:relative;display:flex;align-items:center;gap:.9rem;width:100%;height:62px;
  padding:0 .55rem;border-radius:999px;background:#fff;color:#06120D;
  box-shadow:0 22px 54px -26px rgba(0,0,0,.75),inset 0 0 0 1px rgba(0,0,0,.05)}
.prompt__badge{width:40px;height:40px;flex:none;border-radius:50%;display:grid;place-items:center;
  background:linear-gradient(150deg,var(--glow),var(--emerald));color:#032218}
.prompt__badge svg{width:18px;height:18px}
.prompt__text{flex:1;text-align:left;font-weight:500;font-size:clamp(.95rem,2.1vw,1.14rem);letter-spacing:-.015em;white-space:nowrap;overflow:hidden}
.caret{display:inline-block;width:2px;height:1.05em;translate:0 .18em;background:currentColor;animation:blink 1.05s steps(2) infinite}
@keyframes blink{50%{opacity:0}}
.prompt__go{width:42px;height:42px;flex:none;border-radius:50%;display:grid;place-items:center;background:#06120D;color:#fff;
  transition:transform .5s var(--e-soft),background .4s}
.prompt__go svg{width:15px;height:15px}
.prompt:hover .prompt__go{transform:translate(2px,-2px) scale(1.06);background:var(--emerald)}

/* floating frosted chip */
.chip{position:absolute;display:flex;align-items:center;gap:.55rem;padding:.72rem 1.05rem;border-radius:18px;
  background:linear-gradient(140deg,rgba(3,58,40,.4),rgba(255,255,255,.55));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.4),0 26px 54px -34px rgba(0,40,26,.9);
  font-size:.9rem;font-weight:500;color:#fff;white-space:nowrap;will-change:transform}
.chip--light{background:linear-gradient(140deg,rgba(255,255,255,.82),rgba(255,255,255,.36));color:#03291C}
.chip--dark{background:linear-gradient(140deg,rgba(2,32,22,.8),rgba(2,32,22,.36));color:#EAFBF3}
.chip--stat{flex-direction:column;gap:.1rem;align-items:flex-start;padding:.78rem 1.15rem}
.chip--stat b{font-family:'Satoshi';font-weight:900;font-size:1.55rem;letter-spacing:-.045em;line-height:1}
.chip--stat span{font-size:.68rem;font-weight:600;letter-spacing:.09em;text-transform:uppercase;opacity:.62}
.chip svg{width:16px;height:16px;flex:none}

/* white circular icon badge (rides the wave, sits in the orbit) */
.badge{width:clamp(46px,6vw,72px);height:clamp(46px,6vw,72px);border-radius:50%;display:grid;place-items:center;background:#fff;
  box-shadow:0 22px 44px -20px rgba(0,0,0,.9),inset 0 0 0 1px rgba(255,255,255,.6)}
.badge svg{width:44%;height:44%;color:var(--emerald)}

/* section head */
@layer th-scene{
.sec{position:relative;padding:clamp(104px,15vh,190px) var(--pad)}
.sec--tight{padding:clamp(72px,10vh,130px) var(--pad)}
.sec__head{display:flex;align-items:flex-end;justify-content:space-between;gap:2rem;flex-wrap:wrap;margin-bottom:clamp(2.4rem,5vw,3.6rem)}
.sec__head--c{justify-content:center;text-align:center}
}

/* ══════════ 06 · TYPE MOTION (solid only — no ghost text) ══════════ */
/* .rw = word-by-word mask reveal. Words are fully opaque, they wipe up from a clipped line. */
.rw{display:block}
/* padding+negative margin so the glyph INK clears the mask without opening layout gaps.
   The right pad is not cosmetic: these headings carry -.045em to -.055em letter-spacing,
   which is subtracted after the last glyph, so the inline box ends up NARROWER than the
   ink. Measured overflow was 5.5px on .h-giant — overflow:hidden sliced the final letter
   of every word vertically ("Neve|r", "mis|s"). Every margin cancels its padding, so
   layout is unchanged; only the clipping box grows.
   NEVER put a text-shadow on a .rw heading — the per-word mask clips it into
   visible rectangles behind every word. */
.rw .rwl{display:inline-block;overflow:hidden;vertical-align:bottom;
  padding-bottom:.13em;margin-bottom:-.13em;
  padding-right:.10em;margin-right:-.10em;
  padding-left:.04em;margin-left:-.04em;
  padding-top:.12em;margin-top:-.12em}
/* 128%, not 112%: the mask box is line-height (.86–1.04em) tall but padding-bottom adds
   .13em, so a 112% push left the word's ascenders peeking below the mask before reveal. */
.rw .rwl>i{display:inline-block;font-style:normal;transform:translateY(128%);will-change:transform}
.rw.is-in .rwl>i{transform:none;transition:transform 1.05s var(--e-out)}
.rw.is-in .rwl:nth-child(1)>i{transition-delay:.02s}
.rw.is-in .rwl:nth-child(2)>i{transition-delay:.08s}
.rw.is-in .rwl:nth-child(3)>i{transition-delay:.14s}
.rw.is-in .rwl:nth-child(4)>i{transition-delay:.2s}
.rw.is-in .rwl:nth-child(5)>i{transition-delay:.26s}
.rw.is-in .rwl:nth-child(6)>i{transition-delay:.32s}
.rw.is-in .rwl:nth-child(7)>i{transition-delay:.38s}
.rw.is-in .rwl:nth-child(8)>i{transition-delay:.44s}
.rw.is-in .rwl:nth-child(n+9)>i{transition-delay:.5s}

/* .tt = two-tone sentence: alternating words shift to mint as they land (AE "that answers, books clients") */
.tt em{font-style:normal;color:inherit;transition:color .8s var(--e-soft)}
.tt.is-in em{color:var(--emerald)}
.tt--onvoid.is-in em{color:var(--mint)}

.t-mint{color:var(--mint)}
.t-em{color:var(--emerald)}
.t-white{color:#fff}
.t-onmint{color:#fff}
.t-onpaper{color:var(--on-paper)}
@layer th-scene{
.eyebrow{font-size:.72rem;font-weight:600;letter-spacing:.26em;text-transform:uppercase;color:rgba(255,255,255,.34);margin-bottom:1.1rem}
.eyebrow--ink{color:rgba(2,36,25,.42)}
}

/* ══════════ 07 · NAV ══════════ */
.prog{position:fixed;top:0;left:0;right:0;height:1px;z-index:60;background:rgba(255,255,255,.06)}
.prog i{display:block;height:100%;width:100%;transform:scaleX(0);transform-origin:0 50%;
  background:linear-gradient(90deg,var(--emerald),var(--mint),var(--glow))}
.nav{position:fixed;top:0;left:0;right:0;z-index:55;display:flex;align-items:center;justify-content:space-between;
  padding:clamp(14px,2vw,26px) var(--pad);pointer-events:none}
.nav>*{pointer-events:auto}
.nav .brand{display:flex;align-items:center;gap:.65rem}
/* THE MARK — new logo 2026-07-29. Two mint D's with the arrow driven through them.
   It is 1.6615:1, not square like the old disc, so it is sized by HEIGHT and lets
   aspect-ratio find the width; a square box would letterbox it to 60% scale.
   The D's read --markd so a mint field can flip them to ink — mint-on-mint is
   invisible, and the supplied artwork only covers a light and a dark ground. */
.brand__mark{height:36px;width:auto;aspect-ratio:1000/602;flex:none;display:block;
  transition:transform .6s var(--e-soft)}
.brand__mark svg{width:100%;height:100%;display:block}
.nav .brand:hover .brand__mark{transform:translateX(3px) scale(1.04)}
.brand__name{font-family:'Satoshi';font-weight:700;font-size:1.14rem;letter-spacing:-.04em;transition:color .4s}
/* THE FOOTER — Duval, round 11: "use the white logo in the footer, the arrow is the
   same colour as the background." It was: ink D's with the arrow knocked out in the
   field colour, so on the mint field the arrow read as nothing. Now the mark is
   WHITE and the arrow is the knockout, which is the dark-ground artwork inverted and
   the arrow is legible again. The wordmark stays ink — white text on --mint-lo is
   about 2.3:1 and would fail to read. */
footer.foot .brand__mark{--markd:#fff;color:#04241A}

/* THE NAV MARK — Duval, round 11: "the logo in the top left needs a background,
   round, add its background back." The old disc mark carried its own white circle;
   the new artwork is a bare 1.66:1 lockup, so the plate goes back as CSS. The mark
   is inset to ~72% so it has the optical breathing room a circle needs. */
.nav .brand__mark{
  height:46px;width:46px;aspect-ratio:1;border-radius:50%;
  display:grid;place-items:center;background:#fff;color:#0d201a;
  box-shadow:0 10px 26px -10px rgba(0,0,0,.7),inset 0 0 0 1px rgba(2,36,25,.08);
}
.nav .brand__mark svg{width:78%;height:auto;aspect-ratio:1000/602}
.nav.is-light .brand__mark{box-shadow:0 8px 20px -10px rgba(2,36,25,.45),inset 0 0 0 1px rgba(2,36,25,.12)}
.island{display:flex;align-items:center;gap:6px;padding:6px;border-radius:999px;
  background:rgba(255,255,255,.045);border:1px solid var(--line);
  backdrop-filter:blur(18px) saturate(150%);-webkit-backdrop-filter:blur(18px) saturate(150%);
  transition:background .6s var(--e-soft),border-color .6s var(--e-soft)}
.island__links{display:flex;align-items:center;gap:2px;padding:0 6px}
.ilink{position:relative;display:inline-flex;align-items:center;gap:.45rem;padding:.5rem .8rem;border-radius:999px;
  font-size:.88rem;font-weight:500;color:rgba(255,255,255,.55);transition:color .45s var(--e-soft)}
.ilink::before{content:"";width:4px;height:4px;border-radius:50%;background:var(--mint);transform:scale(0);transition:transform .5s var(--e-soft)}
.ilink:hover{color:#fff}
.ilink.is-on{color:#fff}
.ilink.is-on::before{transform:scale(1)}
.ilink__car{width:9px;height:9px;transition:transform .5s var(--e-soft)}
.ilink.is-open .ilink__car{transform:rotate(180deg)}
.nav.is-light .brand__name{color:#052419}
.nav.is-light .island{background:rgba(255,255,255,.4);border-color:rgba(1,40,27,.13)}
.nav.is-light .ilink{color:rgba(3,40,28,.62)}
.nav.is-light .ilink:hover,.nav.is-light .ilink.is-on{color:#042419}
.nav.is-light .btn--mint{background:#03130D;color:#EAFBF3}
.nav.is-light .btn--mint .btn__chip{background:rgba(255,255,255,.12)}
/* the burger's glyph now sits on a MINT chip in both themes, so its bars stay --on-mint
   and need no light-theme override. The old `.burger span` selector would additionally
   have painted the new label and the chip itself dark — it matched every descendant span. */
.nav.is-light .burger__g span{background:var(--on-mint)}

/* ── Solutions mega-dropdown ── */
.mega{position:fixed;left:var(--pad);right:var(--pad);top:calc(clamp(14px,2vw,26px) + 58px);z-index:54;
  opacity:0;visibility:hidden;transform:translateY(-12px);pointer-events:none;
  transition:opacity .5s var(--e-soft),transform .5s var(--e-soft),visibility .5s}
.mega.is-open{opacity:1;visibility:visible;transform:none;pointer-events:auto}
.mega__shell{padding:6px;border-radius:32px;border:1px solid var(--line);
  background:linear-gradient(160deg,rgba(255,255,255,.09),rgba(255,255,255,.02));
  backdrop-filter:blur(26px) saturate(160%);-webkit-backdrop-filter:blur(26px) saturate(160%)}
.mega__core{border-radius:26px;background:linear-gradient(165deg,rgba(8,14,12,.95),rgba(4,7,6,.97));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.09);padding:clamp(1.3rem,2vw,1.9rem) clamp(1.3rem,2vw,1.9rem) 0}
/* four columns split by hairlines, editorial — no promo card, no gradient panel */
.mega__cols{display:grid;grid-template-columns:repeat(3,minmax(0,1fr)) minmax(0,.78fr);gap:0}
.mega__col{padding:0 clamp(.8rem,1.5vw,1.6rem)}
.mega__col+.mega__col{border-left:1px solid var(--line)}
.mega__col:first-child{padding-left:0}
.mega__col:last-child{padding-right:0}
.mega__col>h4{font-size:.63rem;font-weight:700;letter-spacing:.24em;text-transform:uppercase;
  color:rgba(255,255,255,.32);margin:0 0 .5rem;padding:0 .5rem .55rem;border-bottom:1px solid var(--line)}
.mrow{display:flex;align-items:center;gap:.7rem;padding:.55rem .5rem;border-radius:12px;
  opacity:0;transform:translateY(10px);transition:background .4s var(--e-soft),opacity .6s var(--e-out),transform .6s var(--e-out)}
.mega.is-open .mrow,.mega.is-open .mlink{opacity:1;transform:none}
.mrow:hover{background:rgba(255,255,255,.05)}
.mrow__ic{width:26px;height:26px;flex:none;display:grid;place-items:center;
  color:rgba(255,255,255,.38);transition:color .4s var(--e-soft),transform .5s var(--e-soft)}
.mrow__ic svg{width:100%;height:100%}
.mrow:hover .mrow__ic{color:var(--mint);transform:translateX(1px)}
.mrow__n{font-family:'Satoshi';font-weight:700;font-size:.93rem;letter-spacing:-.032em;
  color:rgba(255,255,255,.86);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .35s}
.mrow:hover .mrow__n{color:#fff}
.mrow__k{margin-left:auto;flex:none;font-size:.6rem;font-weight:700;letter-spacing:.13em;text-transform:uppercase;
  color:rgba(255,255,255,.24);transition:color .35s}
.mrow:hover .mrow__k{color:var(--mint)}
/* the fourth column is a plain link list, deliberately not a card */
.mlink{display:flex;align-items:center;padding:.55rem .5rem;font-size:.9rem;font-weight:500;
  color:rgba(255,255,255,.55);border-radius:12px;opacity:0;transform:translateY(10px);
  transition:color .35s,background .4s var(--e-soft),opacity .6s var(--e-out),transform .6s var(--e-out)}
.mlink svg{width:13px;height:13px;margin-left:auto;opacity:0;transform:translateX(-5px);
  transition:opacity .4s var(--e-soft),transform .4s var(--e-soft)}
.mlink:hover{color:#fff;background:rgba(255,255,255,.05)}
.mlink:hover svg{opacity:1;transform:none;color:var(--mint)}
.mega__foot{margin-top:clamp(.9rem,1.6vw,1.4rem);padding:.95rem 0;border-top:1px solid var(--line);
  display:flex;align-items:center;justify-content:space-between;gap:1.2rem;flex-wrap:wrap}
.mega__foot>span{font-size:.76rem;color:rgba(255,255,255,.3);letter-spacing:-.005em}
.mega__all{display:inline-flex;align-items:center;gap:.5rem;font-size:.82rem;font-weight:600;color:var(--mint)}
.mega__all svg{width:14px;height:14px;transition:transform .5s var(--e-soft)}
.mega__all:hover svg{transform:translateX(4px)}
@media(max-width:1080px){.mega{display:none}}

/* burger + mobile menu */
/* THE MOBILE MENU BUTTON — rebuilt 2026-07-31 on Duval's note ("the mobile button could
   be made better"). It was a 44px circle holding two 1.5px hairlines: a thin, low-contrast
   mark that disappeared against a busy hero and gave no clue what it did. This is the
   brand's own button-in-button language instead — a 48px stadium carrying the word Menu
   and the glyph in its own chip, so it reads as a control, states its purpose, and clears
   the 44px tap-target floor with room to spare. Under 380px the label drops and it
   returns to a circle, because at that width the wordmark needs the space. */
.burger{display:none;align-items:center;gap:.5rem;height:48px;padding:0 .38rem 0 .95rem;
  border-radius:999px;border:1px solid var(--line-2);background:rgba(255,255,255,.05);
  -webkit-tap-highlight-color:transparent;transition:background .3s,border-color .3s}
.burger__l{font-family:'Switzer';font-weight:600;font-size:.9rem;letter-spacing:-.01em;color:#fff}
.burger__g{display:grid;place-items:center;width:36px;height:36px;border-radius:50%;
  background:var(--mint);transition:background .35s var(--e-soft),transform .45s var(--e-back)}
.burger__g span{display:block;width:15px;height:2px;border-radius:2px;background:var(--on-mint);
  transition:transform .45s var(--e-soft),opacity .3s}
.burger__g span+span{margin-top:4px}
.burger.is-x .burger__g{transform:rotate(90deg)}
.burger.is-x .burger__g span:first-child{transform:translateY(3px) rotate(45deg)}
.burger.is-x .burger__g span:last-child{transform:translateY(-3px) rotate(-45deg)}
.burger:hover{background:rgba(255,255,255,.09);border-color:var(--line-2)}
.nav.is-light .burger{border-color:rgba(1,40,27,.18);background:rgba(2,36,25,.04)}
.nav.is-light .burger__l{color:var(--on-paper)}
@media(max-width:1080px){.island__links{display:none}.burger{display:inline-flex}.island .btn{display:none}}
@media(max-width:379px){.burger{padding:0;width:48px;justify-content:center}.burger__l{display:none}}
.menu{position:fixed;inset:0;z-index:56;display:flex;flex-direction:column;justify-content:center;
  padding:calc(var(--pad) + 60px) var(--pad) var(--pad);background:rgba(3,6,5,.9);
  backdrop-filter:blur(26px);-webkit-backdrop-filter:blur(26px);overflow-y:auto;
  opacity:0;visibility:hidden;transition:opacity .6s var(--e-soft),visibility .6s}
.menu.is-open{opacity:1;visibility:visible}
.menu__top{display:flex;flex-direction:column;gap:.1rem;margin-bottom:1.6rem}
.menu__top a{font-family:'Satoshi';font-weight:900;font-size:clamp(1.9rem,8vw,3.4rem);letter-spacing:-.05em;
  color:rgba(255,255,255,.92);opacity:0;transform:translateY(30px);
  transition:opacity .7s var(--e-out),transform .7s var(--e-out),color .3s}
.menu.is-open .menu__top a{opacity:1;transform:none}
.menu.is-open .menu__top a:nth-child(1){transition-delay:.06s}
.menu.is-open .menu__top a:nth-child(2){transition-delay:.11s}
.menu.is-open .menu__top a:nth-child(3){transition-delay:.16s}
.menu.is-open .menu__top a:nth-child(4){transition-delay:.21s}
.menu.is-open .menu__top a:nth-child(5){transition-delay:.26s}
.menu__top a:hover{color:var(--mint)}
.macc{border-top:1px solid var(--line);opacity:0;transform:translateY(20px);transition:opacity .6s var(--e-out) .3s,transform .6s var(--e-out) .3s}
.menu.is-open .macc{opacity:1;transform:none}
.macc__h{width:100%;display:flex;align-items:center;justify-content:space-between;padding:1rem 0;
  font-family:'Satoshi';font-weight:700;font-size:1.05rem;letter-spacing:-.03em;color:rgba(255,255,255,.62)}
.macc__h svg{width:14px;height:14px;transition:transform .45s var(--e-soft)}
.macc.is-on .macc__h{color:#fff}
.macc.is-on .macc__h svg{transform:rotate(45deg)}
.macc__b{display:grid;grid-template-rows:0fr;transition:grid-template-rows .55s var(--e-soft)}
.macc.is-on .macc__b{grid-template-rows:1fr}
.macc__i{overflow:hidden}
.macc__i a{display:block;padding:.5rem 0 .5rem 1rem;font-size:1rem;color:rgba(255,255,255,.55);border-left:1px solid var(--line)}
.macc__i a:hover{color:var(--mint)}
.menu__cta{margin-top:1.8rem;display:flex;gap:.6rem;flex-wrap:wrap}
/* THUMB REACH. The panel was justify-content:center, so with six product groups open the
   two CTAs — the only things in here that make money — floated somewhere around the middle
   of the screen or below the fold. Push the content to the top and pin the CTAs to the
   bottom, where a thumb actually rests. safe-area-inset keeps them clear of the gesture bar. */
@media(max-width:1080px){
  .menu{justify-content:flex-start;padding-bottom:calc(var(--pad) + env(safe-area-inset-bottom,0px))}
  .menu__top{margin-bottom:1.1rem}
  .menu__cta{margin-top:auto;padding-top:1.6rem;flex-wrap:nowrap}
  .menu__cta .btn{flex:1;min-width:0;justify-content:space-between}
}

/* ═══════════════════════════════════════════════════════════════
   09 · SCENE MODULES
   ═══════════════════════════════════════════════════════════════ */

/* ── s-hero ── */
.s-hero{position:relative;min-height:100svh;display:flex;flex-direction:column;align-items:center;justify-content:center;
  text-align:center;padding:clamp(130px,17vh,190px) var(--pad) clamp(110px,15vh,160px);overflow:hidden;
  background:radial-gradient(120% 92% at 50% 4%,#0C1512 0%,#040706 46%,#000 100%)}
.s-hero__fx{position:absolute;inset:0;pointer-events:none}
.spot{position:absolute;width:70vw;height:70vw;left:0;top:0;margin:-35vw 0 0 -35vw;border-radius:50%;
  background:radial-gradient(circle,rgba(52,245,173,.2),rgba(16,185,129,.05) 45%,transparent 68%);filter:blur(60px);will-change:transform}
.s-hero__in{position:relative;z-index:2;width:100%;max-width:1320px}
.s-hero h1{margin-bottom:clamp(1.4rem,3vw,2.2rem)}
.s-hero--sub{min-height:auto;padding:clamp(160px,22vh,240px) var(--pad) clamp(80px,11vh,130px)}
.s-hero__meta{display:flex;gap:.5rem;flex-wrap:wrap;justify-content:center;margin-top:1.6rem}
.metapill{display:inline-flex;align-items:center;gap:.45rem;height:36px;padding:0 .95rem;border-radius:999px;
  border:1px solid var(--line-2);font-size:.8rem;font-weight:500;color:rgba(255,255,255,.6)}
.metapill svg{width:13px;height:13px;color:var(--mint)}
.scrollcue{position:absolute;left:0;right:0;margin-inline:auto;width:max-content;bottom:26px;z-index:1;
  display:flex;flex-direction:column;align-items:center;gap:.6rem;
  font-size:.64rem;letter-spacing:.28em;text-transform:uppercase;color:rgba(255,255,255,.3)}
.scrollcue__rail{width:1px;height:46px;background:linear-gradient(rgba(255,255,255,.28),transparent);position:relative;overflow:hidden}
.scrollcue__rail::after{content:"";position:absolute;top:-50%;left:0;width:1px;height:50%;background:var(--mint);animation:cue 2.1s var(--e-io) infinite}
@keyframes cue{to{transform:translateY(300%)}}

/* ── s-kin — kinetic words on hard colour-field cuts ── */
.s-kin{position:relative;background:var(--void)}
.s-kin__vp{position:sticky;top:0;height:100dvh;display:grid;place-items:center;overflow:hidden}
.s-kin__bg{position:absolute;inset:0;background:var(--void)}
.s-kin__wrap{position:relative;z-index:2;width:100%;text-align:center;padding:0 var(--pad)}
.kw{position:absolute;left:0;right:0;top:50%;translate:0 -50%;font-size:clamp(3.4rem,20vw,16.5rem);opacity:0;will-change:transform,opacity}
.kw--fill{color:#fff}
.kw--mint{color:var(--mint)}
.kw--dark{color:#03251A}
.kw--paper{color:var(--on-paper)}

/* ── s-field — the mint colour-field flip ── */
.s-field{position:relative;background:var(--void)}
.s-field__panel{position:relative;min-height:104svh;display:flex;align-items:center;justify-content:center;
  padding:clamp(90px,14vh,150px) var(--pad);overflow:hidden;color:var(--on-mint);
  background:linear-gradient(165deg,var(--mint-hi) 0%,var(--mint) 42%,var(--mint-lo) 100%)}
.s-field__in{position:relative;z-index:2;width:100%;max-width:1240px;text-align:center}
.chips{position:absolute;inset:0;z-index:1;pointer-events:none}
/* CORNERS ONLY. The h-giant headline in this scene wraps to 3–4 full-width lines, so
   any chip at mid-height lands behind the type — a frosted box sat directly behind the
   "B" of "Built in Vanderbijlpark". Four chips, hard into the corners, is the whole set.
   Held off the very edge too: the field is clipped to a stadium on arrival and anything
   at 5% gets sliced by the rounded corner. */
.chip{max-width:min(30vw,230px)}
.chip.c1{left:7%;top:9%}
.chip.c2{right:7%;top:7%}
.chip.c3{left:8%;bottom:9%}
.chip.c4{right:8%;bottom:7%}
.chip.c5,.chip.c6,.chip.c7{display:none}
@media(max-width:820px){.chip{font-size:.78rem;padding:.55rem .8rem;max-width:42vw}
  .chip.c1{left:4%;top:5%}.chip.c2{right:4%;top:4%}.chip.c3{left:4%;bottom:5%}.chip.c4{right:4%;bottom:4%}}
@media(max-width:560px){.chip.c2,.chip.c3{display:none}}

/* ── s-paper — the third tone ── */
.s-paper{position:relative;background:var(--paper);color:var(--on-paper);overflow:hidden;
  padding:clamp(110px,16vh,200px) var(--pad)}
.s-paper .lede{color:var(--paper-soft)}
.s-paper__fx{position:absolute;inset:0;pointer-events:none;opacity:.9}
.s-paper--full{min-height:92svh;display:flex;align-items:center}

/* ── s-pillflow — Answer instantly → Capture leads → Book meetings ── */
.s-pillflow{position:relative;overflow:hidden;padding:clamp(80px,12vh,150px) var(--pad);
  background:linear-gradient(160deg,var(--mint) 0%,var(--mint-lo) 100%);color:var(--on-mint)}
.pflow{display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:.7rem;position:relative;z-index:2}
.pf{display:inline-flex;align-items:center;gap:.6rem;height:60px;padding:0 1.7rem;border-radius:999px;background:#fff;
  font-family:'Satoshi';font-weight:700;font-size:clamp(.92rem,1.5vw,1.14rem);letter-spacing:-.03em;color:var(--on-mint);
  box-shadow:0 18px 40px -26px rgba(0,40,26,.9),inset 0 1px 0 rgba(255,255,255,.8);white-space:nowrap;
  opacity:0;transform:translateY(16px) scale(.96)}
.pf.is-in{opacity:1;transform:none;transition:opacity .7s var(--e-out),transform .8s var(--e-back)}
.pf svg{width:16px;height:16px;color:var(--emerald)}
.pfa{display:grid;place-items:center;width:30px;height:30px;flex:none;color:rgba(2,42,29,.4);opacity:0;transform:scale(.6)}
.pfa.is-in{opacity:1;transform:none;transition:opacity .5s var(--e-out),transform .6s var(--e-back)}
.pfa svg{width:20px;height:20px}
@media(max-width:700px){.pflow{flex-direction:column}.pfa{transform:rotate(90deg) scale(.6)}.pfa.is-in{transform:rotate(90deg)}}

/* ── s-numeral — the giant number moment ── */
.s-num{position:relative;overflow:hidden;padding:clamp(96px,15vh,180px) var(--pad);text-align:center}
.s-num--mint{background:linear-gradient(170deg,var(--mint-hi),var(--mint) 46%,var(--mint-lo));color:var(--on-mint)}
.s-num--paper{background:var(--paper);color:var(--on-paper)}
.s-num--void{background:var(--void);color:#fff}
.num{font-family:'Cabinet';font-weight:900;font-size:clamp(4.2rem,17vw,15rem);letter-spacing:-.06em;line-height:.82;
  display:block;position:relative;z-index:2}
.num--white{color:#fff}
.num__lbl{position:relative;z-index:2;font-size:clamp(.9rem,1.5vw,1.15rem);font-weight:600;letter-spacing:-.01em;opacity:.62;margin-bottom:1rem}
.num__sub{position:relative;z-index:2;margin-top:1.4rem;font-size:.92rem;opacity:.55;letter-spacing:-.01em}

/* ── s-wall — the chat wall ── */
.s-wall{position:relative;background:var(--void);overflow:hidden;padding:clamp(110px,16vh,190px) 0}
.wall__grid{display:flex;gap:clamp(10px,1.4vw,20px);justify-content:center;
  -webkit-mask-image:radial-gradient(120% 78% at 50% 50%,#000 34%,transparent 78%);
  mask-image:radial-gradient(120% 78% at 50% 50%,#000 34%,transparent 78%)}
.wcol{display:flex;flex-direction:column;gap:clamp(10px,1.4vw,20px);width:clamp(180px,20vw,280px);flex:none;will-change:transform}
.bub{padding:.85rem 1.1rem;border-radius:20px;font-size:.9rem;font-weight:500;line-height:1.35;
  border:1px solid var(--line);background:linear-gradient(160deg,rgba(255,255,255,.05),rgba(255,255,255,.012));color:rgba(255,255,255,.62)}
.bub--mint{background:linear-gradient(140deg,var(--glow),var(--mint-lo));border-color:transparent;color:var(--on-mint);font-weight:600;
  box-shadow:0 18px 40px -26px rgba(52,245,173,.8)}
.bub--r{border-bottom-right-radius:6px}
.bub--l{border-bottom-left-radius:6px}
.wall__over{position:absolute;inset:0;z-index:3;display:grid;place-items:center;text-align:center;padding:0 var(--pad);pointer-events:none}
.wall__over>*{pointer-events:auto;position:relative;z-index:2}
.wall__over::before{content:"";position:absolute;left:50%;top:50%;translate:-50% -50%;width:min(1100px,92vw);height:min(620px,70vh);
  background:radial-gradient(closest-side,rgba(0,0,0,.94),rgba(0,0,0,.72) 52%,transparent 78%);filter:blur(6px);pointer-events:none}
@media(max-width:900px){.wcol:nth-child(n+4){display:none}}
@media(max-width:600px){.wcol:nth-child(n+3){display:none}}

/* ── s-wave — mint ribbon with badges riding it ── */
.s-wave{position:relative;background:var(--void);overflow:hidden;padding:clamp(96px,15vh,170px) var(--pad) clamp(60px,8vh,110px)}
.wave__head{position:relative;z-index:3;max-width:1240px;margin:0 auto;text-align:center}
.wave__stage{position:relative;height:clamp(280px,32vw,400px);margin-top:clamp(1.4rem,3.4vw,2.6rem)}
/* max-width:none is mandatory — the global img,svg{max-width:100%} crushes this 400%-wide svg */
.wave__svg{position:absolute;left:-100%;top:0;width:400%;max-width:none;height:100%;overflow:visible;will-change:transform}
.wave__svg--back{opacity:.42;filter:blur(26px)}
.badges{position:absolute;inset:0;z-index:3}
.badges .badge{position:absolute;top:40%;left:0;will-change:transform,top,left}
@media(max-width:760px){.badges .badge:nth-child(4),.badges .badge:nth-child(6){display:none}}

/* ── s-marquee ── */
.s-marq{position:relative;padding:clamp(22px,4vw,44px) 0;overflow:hidden;
  background:linear-gradient(180deg,var(--mint) 0%,var(--mint-lo) 100%);
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent)}
.s-marq--void{background:var(--void);border-block:1px solid var(--line)}
.marq__row{display:flex;align-items:center;gap:.85rem;width:max-content;will-change:transform}
.mpill{display:inline-flex;align-items:center;height:56px;padding:0 1.6rem;border-radius:999px;background:#fff;color:#04241A;
  font-weight:600;font-size:1rem;letter-spacing:-.015em;white-space:nowrap;
  box-shadow:0 16px 34px -24px rgba(0,40,26,.9),inset 0 1px 0 rgba(255,255,255,.7)}
.mpill--line{background:transparent;color:rgba(2,42,29,.72);border:1px solid rgba(2,42,29,.24);box-shadow:none}
.mpill--dark{background:#03241A;color:#EAFBF3;box-shadow:0 16px 34px -24px rgba(0,20,13,.9)}
.s-marq--void .mpill{background:rgba(255,255,255,.06);color:rgba(255,255,255,.8);box-shadow:none;border:1px solid var(--line)}
.s-marq--void .mpill--dark{background:var(--mint);color:var(--on-mint);border-color:transparent}
.marr{display:grid;place-items:center;width:26px;height:26px;flex:none;color:rgba(2,42,29,.42)}
.s-marq--void .marr{color:rgba(255,255,255,.24)}
.marr svg{width:18px;height:18px}

/* ── s-cmd — command centre glass panels ── */
.s-cmd{position:relative;background:var(--void);overflow:hidden;padding:clamp(110px,16vh,190px) var(--pad) clamp(120px,18vh,210px)}
.cmd__bloom{position:absolute;left:50%;bottom:-46%;translate:-50% 0;width:130vw;height:110vw;border-radius:50%;
  background:radial-gradient(circle at 50% 46%,rgba(52,245,173,.42),rgba(16,185,129,.12) 42%,transparent 66%);filter:blur(70px);pointer-events:none}
.cmd__head{position:relative;z-index:3;text-align:center;max-width:1180px;margin:0 auto}
.cmd__stage{position:relative;z-index:2;max-width:1240px;margin:clamp(2.6rem,6vw,4.6rem) auto 0;height:clamp(360px,42vw,520px)}
.pan{position:absolute;will-change:transform}
.pan .core{padding:1.15rem 1.25rem}
.pan__t{font-size:.7rem;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:rgba(255,255,255,.36)}
.pan__v{font-family:'Satoshi';font-weight:900;font-size:clamp(1.5rem,2.6vw,2.3rem);letter-spacing:-.05em;margin-top:.35rem;
  background:linear-gradient(180deg,#fff 20%,rgba(255,255,255,.38));-webkit-background-clip:text;background-clip:text;color:transparent}
.pan--a{left:0;top:6%;width:clamp(200px,23vw,290px)}
.pan--b{right:0;top:0;width:clamp(210px,25vw,320px)}
.pan--c{left:50%;top:34%;translate:-50% 0;width:clamp(280px,40vw,520px)}
.pan--d{left:4%;bottom:0;width:clamp(190px,22vw,280px)}
.pan--e{right:5%;bottom:6%;width:clamp(180px,21vw,260px)}
.spark{width:100%;height:52px;margin-top:.6rem}
.spark path{fill:none;stroke:var(--mint);stroke-width:2;vector-effect:non-scaling-stroke}
.rowline{display:flex;align-items:center;gap:.6rem;padding:.45rem 0;border-top:1px solid var(--line);font-size:.84rem;color:rgba(255,255,255,.6)}
.rowline:first-of-type{border-top:0}
.rowline b{margin-left:auto;color:var(--mint);font-weight:600}
.tick{width:18px;height:18px;border-radius:50%;display:grid;place-items:center;background:rgba(52,245,173,.16);color:var(--mint);flex:none}
.tick svg{width:10px;height:10px}
@media(max-width:900px){.cmd__stage{height:auto;display:grid;gap:14px}.pan{position:static;width:100%!important;translate:none!important}.pan--c{order:-1}}

/* ── s-acc — horizontal product accordion ── */
.s-acc{position:relative;background:var(--void);padding:clamp(120px,18vh,210px) var(--pad) clamp(96px,14vh,170px)}
.pacc{display:flex;gap:8px;height:clamp(360px,42vw,520px)}
.pacc__i{position:relative;flex:1;min-width:0;border-radius:26px;overflow:hidden;isolation:isolate;
  border:1px solid var(--line);background:linear-gradient(170deg,rgba(255,255,255,.055),rgba(255,255,255,.012));
  transition:flex .85s var(--e-soft),border-color .6s var(--e-soft)}
.pacc__i::before{content:"";position:absolute;inset:0;z-index:-1;opacity:0;transition:opacity .7s var(--e-soft);
  background:radial-gradient(85% 62% at 50% 118%,rgba(52,245,173,.34),transparent 68%)}
.pacc__i:hover,.pacc__i.is-on{flex:3.6;border-color:rgba(52,245,173,.34)}
.pacc__i:hover::before,.pacc__i.is-on::before{opacity:1}
.pacc__in{position:absolute;inset:0;padding:1.4rem;display:flex;flex-direction:column;justify-content:flex-end}
.pacc__n{position:absolute;left:1.4rem;bottom:1.4rem;transform-origin:0 100%;transform:rotate(-90deg);
  font-family:'Satoshi';font-weight:700;font-size:1.05rem;letter-spacing:-.03em;white-space:nowrap;
  transition:transform .85s var(--e-soft),opacity .5s var(--e-soft)}
.pacc__i:hover .pacc__n,.pacc__i.is-on .pacc__n{transform:rotate(0deg);opacity:0}
.pacc__open{opacity:0;transform:translateY(14px);transition:opacity .7s var(--e-soft) .12s,transform .7s var(--e-soft) .12s}
.pacc__i:hover .pacc__open,.pacc__i.is-on .pacc__open{opacity:1;transform:none}
.pacc__ttl{display:block;font-family:'Satoshi';font-weight:900;font-size:clamp(1.4rem,2.4vw,2.2rem);letter-spacing:-.045em;line-height:1}
.pacc__p{display:block;margin-top:.55rem;font-size:.86rem;color:rgba(255,255,255,.5);max-width:32ch}
.pacc__go{display:inline-flex;align-items:center;gap:.6rem;margin-top:1rem;font-size:.9rem;font-weight:600;color:var(--mint)}
.pacc__go span{width:32px;height:32px;border-radius:50%;display:grid;place-items:center;background:rgba(52,245,173,.14)}
.pacc__go svg{width:13px;height:13px}
.pacc__ico{position:absolute;top:1.4rem;left:1.4rem;width:34px;height:34px;color:rgba(255,255,255,.28);
  transition:color .7s var(--e-soft),width .8s var(--e-soft),height .8s var(--e-soft),opacity .7s}
.pacc__i:hover .pacc__ico,.pacc__i.is-on .pacc__ico{color:var(--mint);width:78px;height:78px;opacity:.9}
@media(max-width:900px){
  .pacc{flex-direction:column;height:auto;gap:8px}
  .pacc__i{flex:none;height:88px;transition:height .8s var(--e-soft)}
  .pacc__i:hover,.pacc__i.is-on{flex:none;height:230px}
  .pacc__n{transform:none;left:auto;right:1.4rem;bottom:auto;top:1.55rem;font-size:1.15rem}
  .pacc__i:hover .pacc__n,.pacc__i.is-on .pacc__n{transform:none;opacity:0}
  .pacc__ico{top:1.3rem}
}

/* ── s-conv — the phone that types itself ── */
.s-conv{position:relative;overflow:hidden;padding:clamp(96px,14vh,170px) var(--pad);
  background:radial-gradient(110% 80% at 18% 42%,rgba(6,61,43,.55),transparent 62%),var(--void)}
.conv__in{max-width:var(--maxw);margin:0 auto;display:grid;grid-template-columns:1fr minmax(320px,400px);gap:clamp(2.5rem,6vw,6rem);align-items:center}
@media(max-width:1000px){.conv__in{grid-template-columns:1fr;justify-items:center;text-align:center}}
@layer th-scene{
.phone{width:min(100%,380px);border-radius:46px;padding:8px;
  background:linear-gradient(160deg,rgba(255,255,255,.12),rgba(255,255,255,.02));border:1px solid var(--line-2)}
.phone__s{border-radius:38px;background:linear-gradient(180deg,#0A0F0D,#040605);padding:1.5rem 1.1rem;min-height:clamp(430px,54vw,520px);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.1);display:flex;flex-direction:column;gap:.7rem}
.phone__bar{display:flex;align-items:center;justify-content:space-between;font-size:.7rem;color:rgba(255,255,255,.4);margin-bottom:.4rem}
}
.msg{max-width:82%;padding:.72rem .95rem;border-radius:18px;font-size:.88rem;line-height:1.4;opacity:0;will-change:opacity,transform}
.msg--in{align-self:flex-start;background:rgba(255,255,255,.07);border:1px solid var(--line);color:rgba(255,255,255,.72);border-bottom-left-radius:6px}
.msg--out{align-self:flex-end;background:linear-gradient(140deg,var(--glow),var(--mint-lo));color:var(--on-mint);font-weight:500;border-bottom-right-radius:6px}
.conv__list{display:flex;flex-direction:column;gap:.2rem;margin-top:clamp(1.6rem,3vw,2.4rem)}
.cli{display:flex;align-items:center;gap:1rem;padding:1rem 0;border-top:1px solid var(--line);
  font-family:'Satoshi';font-weight:700;font-size:clamp(1.05rem,1.7vw,1.45rem);letter-spacing:-.035em;color:rgba(255,255,255,.5);
  transition:color .5s var(--e-soft),padding-left .6s var(--e-soft)}
.cli:hover{color:#fff;padding-left:.6rem}
.cli em{font-style:normal;margin-left:auto;font-family:'Switzer';font-weight:500;font-size:.82rem;color:var(--mint);opacity:.85}

/* ── s-collage — frosted glass proof collage ── */
.s-collage{position:relative;overflow:hidden;padding:clamp(96px,14vh,180px) var(--pad);
  background:linear-gradient(165deg,var(--mint-hi),var(--mint) 50%,var(--mint-lo));color:var(--on-mint)}
.coll{position:relative;max-width:1180px;margin:clamp(2rem,4vw,3.4rem) auto 0;height:clamp(420px,48vw,560px)}
/* These panels were empty glass rectangles — pretty, but they read as unfinished.
   They now carry the actual numbers behind "the proof is in the pipeline". */
.gl{position:absolute;border-radius:22px;background:linear-gradient(150deg,rgba(255,255,255,.5),rgba(255,255,255,.14));
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);box-shadow:0 30px 60px -40px rgba(0,40,26,.8);
  will-change:transform;display:flex;flex-direction:column;justify-content:center;
  padding:.7rem .95rem;color:var(--on-paper);overflow:hidden}
.gl b{display:block;font-family:'Satoshi';font-weight:900;font-size:clamp(.95rem,1.5vw,1.28rem);
  letter-spacing:-.04em;line-height:1.05}
.gl span{display:block;margin-top:.18rem;font-size:clamp(.56rem,.78vw,.68rem);font-weight:600;
  letter-spacing:.1em;text-transform:uppercase;color:rgba(2,36,25,.58);line-height:1.25}
.gl--a{left:2%;top:6%;width:24%;height:14%}
.gl--b{right:4%;top:2%;width:20%;height:12%}
.gl--c{left:8%;bottom:10%;width:22%;height:13%}
.gl--d{right:2%;bottom:16%;width:25%;height:15%}
.gl--e{left:35%;top:0;width:19%;height:11%}
@media(max-width:640px){.gl span{display:none}.gl{padding:.5rem .6rem}}
.coll__card{position:absolute;left:50%;top:50%;translate:-50% -50%;width:min(440px,72%);border-radius:26px;padding:1.6rem 1.8rem;
  background:linear-gradient(150deg,rgba(255,255,255,.72),rgba(255,255,255,.38));
  backdrop-filter:blur(18px);-webkit-backdrop-filter:blur(18px);
  box-shadow:0 48px 90px -50px rgba(0,40,26,.9),inset 0 1px 0 rgba(255,255,255,.8);text-align:center}
.coll__card small{font-size:.74rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;opacity:.5}
.coll__card b{display:block;font-family:'Satoshi';font-weight:900;font-size:clamp(2rem,4.4vw,3.4rem);letter-spacing:-.05em;line-height:1;margin-top:.4rem}
.coll__stat{position:absolute;right:6%;top:38%;border-radius:18px;padding:.85rem 1.15rem;background:#fff;text-align:center;
  box-shadow:0 30px 60px -40px rgba(0,40,26,.9)}
.coll__stat b{display:block;font-family:'Satoshi';font-weight:900;font-size:1.6rem;letter-spacing:-.05em;line-height:1}
.coll__stat span{font-size:.66rem;font-weight:600;letter-spacing:.09em;text-transform:uppercase;opacity:.5}
.coll__ico{position:absolute;left:6%;top:40%;display:flex;gap:.9rem;color:rgba(2,36,25,.6)}
.coll__ico svg{width:20px;height:20px}
.coll__pill{position:absolute;left:50%;bottom:6%;translate:-50% 0}
@media(max-width:760px){.gl--e,.coll__ico{display:none}.coll{height:clamp(380px,90vw,460px)}.coll__stat{right:2%;top:22%}}

/* ── s-dock — the channels, iOS-style bevelled dock ── */
.s-dock{position:relative;overflow:hidden;background:var(--void);padding:clamp(100px,15vh,180px) var(--pad)}
.dock{position:relative;z-index:2;margin:clamp(2.2rem,4vw,3.4rem) auto 0;width:max-content;max-width:100%;
  display:flex;gap:clamp(.7rem,1.4vw,1.3rem);padding:clamp(.8rem,1.4vw,1.2rem);border-radius:32px;
  background:linear-gradient(160deg,rgba(255,255,255,.08),rgba(255,255,255,.015));border:1px solid var(--line);
  backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);box-shadow:0 50px 90px -60px #000}
.dapp{width:clamp(64px,9vw,96px);text-align:center;transition:transform .55s var(--e-back)}
.dapp:hover{transform:translateY(-10px)}
.dapp__t{width:100%;aspect-ratio:1;border-radius:23%;display:grid;place-items:center;position:relative;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 20px 34px -22px #000}
.dapp__t svg{width:46%;height:46%}
.dapp--web .dapp__t{background:linear-gradient(160deg,#12312A,#081813);color:var(--mint)}
.dapp--wa .dapp__t{background:linear-gradient(160deg,#2BD46E,#128A45);color:#042313}
.dapp--em .dapp__t{background:linear-gradient(160deg,#EDF4F0,#BFD4C9);color:#0A2A1F}
.dapp--tg .dapp__t{background:linear-gradient(160deg,#3FC7F5,#1682B8);color:#03242F}
.dapp--ai .dapp__t{background:linear-gradient(160deg,#0C0F0E,#000);color:#fff;box-shadow:inset 0 0 0 1px rgba(255,255,255,.14),0 20px 34px -22px #000}
.dapp__n{display:block;margin-top:.6rem;font-size:.74rem;font-weight:500;color:rgba(255,255,255,.5);letter-spacing:-.01em}
.dock__rail{width:34%;height:4px;border-radius:99px;background:rgba(255,255,255,.24);margin:1.4rem auto 0}
@media(max-width:620px){.dock{flex-wrap:wrap;justify-content:center;border-radius:28px}}

/* ── s-orbit — concentric rings, badge in the middle ── */
.s-orbit{position:relative;overflow:hidden;background:var(--void);padding:clamp(100px,15vh,180px) var(--pad);text-align:center}
.orbit{position:relative;width:min(720px,86vw);aspect-ratio:1;margin:clamp(1.6rem,3vw,2.6rem) auto 0}
.orbit__r{position:absolute;left:50%;top:50%;translate:-50% -50%;border-radius:50%;border:1px solid rgba(255,255,255,.09)}
.orbit__r--1{width:38%;height:38%}
.orbit__r--2{width:62%;height:62%}
.orbit__r--3{width:86%;height:86%}
.orbit__r--4{width:100%;height:100%;border-color:rgba(255,255,255,.05)}
.orbit__c{position:absolute;left:50%;top:50%;translate:-50% -50%;width:22%;height:22%;border-radius:50%;display:grid;place-items:center;
  background:linear-gradient(150deg,var(--glow),var(--emerald));color:#022A1D;
  box-shadow:0 0 90px 12px rgba(52,245,173,.28),inset 0 1px 0 rgba(255,255,255,.5)}
.orbit__c svg{width:44%;height:44%}
.orbit__sat{position:absolute;left:50%;top:50%;width:0;height:0}
.osat{position:absolute;display:inline-flex;align-items:center;gap:.45rem;height:34px;padding:0 .85rem;border-radius:999px;
  translate:-50% -50%;white-space:nowrap;font-size:.78rem;font-weight:600;letter-spacing:-.01em;
  background:rgba(255,255,255,.07);border:1px solid var(--line-2);color:rgba(255,255,255,.82);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}
.osat--mint{background:var(--mint);border-color:transparent;color:var(--on-mint)}
.osat__d{width:5px;height:5px;border-radius:50%;background:var(--mint)}
.osat--mint .osat__d{background:var(--on-mint)}
@media(max-width:640px){.osat{font-size:.7rem;height:30px;padding:0 .7rem}}

/* ── s-typebox — outlined box with a live caret ── */
.tbox{display:inline-flex;align-items:center;gap:.2rem;padding:.5rem 1rem .6rem;border:1px solid var(--line-2);border-radius:14px;
  font-family:'Cabinet';font-weight:800;letter-spacing:-.04em;line-height:1;background:rgba(255,255,255,.02)}
.tbox--ink{border-color:var(--line-ink-2);background:rgba(255,255,255,.4)}
.tbox .caret{width:3px;background:var(--mint);height:.9em;translate:0 .04em}

/* ── s-blobstat — a liquid shape holding a number ── */
.s-blob{position:relative;overflow:hidden;background:var(--paper);color:var(--on-paper);padding:clamp(100px,15vh,180px) var(--pad)}
.bstage{position:relative;display:grid;place-items:center;min-height:clamp(320px,40vw,460px)}
.bshape{position:absolute;left:50%;top:50%;translate:-50% -50%;width:min(680px,88vw);aspect-ratio:1.32;
  background:linear-gradient(150deg,var(--glow),var(--emerald) 55%,var(--deep));
  border-radius:58% 42% 47% 53%/47% 55% 45% 53%;
  box-shadow:0 60px 110px -60px rgba(3,58,40,.7);
  animation:bmorph 16s ease-in-out infinite}
@keyframes bmorph{
  0%,100%{border-radius:58% 42% 47% 53%/47% 55% 45% 53%;transform:rotate(0deg)}
  33%{border-radius:44% 56% 62% 38%/56% 44% 56% 44%;transform:rotate(3deg)}
  66%{border-radius:63% 37% 39% 61%/41% 62% 38% 59%;transform:rotate(-3deg)}
}
.bstage__t{position:relative;z-index:2;text-align:center;color:#fff;padding:0 1.5rem}
.bstage__t b{display:block;font-family:'Cabinet';font-weight:900;font-size:clamp(2.6rem,8vw,6.4rem);letter-spacing:-.055em;line-height:.9}
.bstage__t span{display:block;margin-top:.6rem;font-size:clamp(.9rem,1.6vw,1.15rem);font-weight:500;opacity:.82}

/* ── s-bubbles3d — tilted chat bubbles drifting ── */
/* min-height, not just padding: the bubbles are absolutely positioned by percentage,
   so without a floor the scene collapses to the height of its heading and they stack */
.s-b3d{position:relative;overflow:hidden;background:var(--void);min-height:88svh;
  display:flex;align-items:center;padding:clamp(110px,16vh,200px) var(--pad);perspective:1100px}
.b3d{position:absolute;inset:0;transform-style:preserve-3d;pointer-events:none}
@layer th-scene{
.b3{position:absolute;padding:.85rem 1.25rem;border-radius:20px 20px 20px 6px;font-size:clamp(.82rem,1.4vw,1.05rem);font-weight:600;
  background:linear-gradient(140deg,var(--glow),var(--mint-lo));color:var(--on-mint);white-space:nowrap;
  box-shadow:0 30px 60px -34px rgba(52,245,173,.7);will-change:transform}
.b3--ghost{background:rgba(255,255,255,.055);border:1px solid var(--line);color:rgba(255,255,255,.6);box-shadow:none;font-weight:500}
}
.s-b3d__in{position:relative;z-index:3;text-align:center;max-width:1180px;margin:0 auto;width:100%}
@media(max-width:760px){.b3:nth-child(n+6){display:none}}

/* ── s-cmdchips — floating capability chips ── */
.s-chips{position:relative;overflow:hidden;background:var(--void);padding:clamp(100px,15vh,180px) var(--pad)}
.cchips{position:relative;z-index:2;display:flex;flex-wrap:wrap;justify-content:center;gap:.65rem;max-width:960px;margin:clamp(2rem,4vw,3rem) auto 0}
.cchip{display:inline-flex;align-items:center;gap:.55rem;height:46px;padding:0 1.15rem;border-radius:999px;
  background:linear-gradient(150deg,rgba(255,255,255,.075),rgba(255,255,255,.02));border:1px solid var(--line);
  font-size:.9rem;font-weight:500;color:rgba(255,255,255,.78);white-space:nowrap;
  transition:border-color .5s var(--e-soft),color .4s,transform .6s var(--e-soft)}
.cchip:hover{border-color:rgba(52,245,173,.42);color:#fff;transform:translateY(-3px)}
.cchip svg{width:15px;height:15px;color:var(--mint)}

/* ── s-sticker — rotated brand plate ── */
.s-sticker{position:relative;overflow:hidden;background:var(--paper);padding:clamp(96px,14vh,170px) var(--pad);text-align:center}
.sticker{display:inline-block;transform:rotate(-4.5deg);background:#fff;color:var(--emerald);
  font-family:'Satoshi';font-weight:900;font-size:clamp(2rem,7.4vw,6rem);letter-spacing:-.055em;line-height:1;
  padding:.34em .5em;border-radius:.22em;box-shadow:.14em .16em 0 var(--on-paper);position:relative;z-index:2}
.sticker--mint{background:var(--mint);color:var(--on-paper);box-shadow:.14em .16em 0 var(--deep)}

/* ── s-tiers — plan cards ── */
.s-tiers{position:relative;background:var(--void);padding:clamp(110px,16vh,190px) var(--pad)}
.tiers{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px}
/* The seven productised products moved to THREE tiers on 2026-07-30 (pricing.py's
   Minimum/Growth/Scale). Three cards in a four-column grid leave a hole on the right.
   Scoped to min-width so it cannot outrank the narrow breakpoints below — an
   attribute selector is 0-2-0 and would otherwise beat every 0-1-0 media query at
   every width, which is the specificity trap that once shipped 38px footer columns. */
@media(min-width:1081px){.tiers[data-n="3"]{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media(max-width:1080px){.tiers{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:600px){.tiers{grid-template-columns:1fr}}
.tier .core{padding:clamp(1.4rem,2.2vw,2rem);height:100%;display:flex;flex-direction:column}
.tier{transition:transform .6s var(--e-soft)}
.tier:hover{transform:translateY(-6px)}
.tier--best .shell{background:linear-gradient(160deg,rgba(52,245,173,.34),rgba(52,245,173,.06));border-color:rgba(52,245,173,.4)}
.tier__tag{display:inline-flex;align-items:center;height:24px;padding:0 .6rem;border-radius:999px;background:var(--mint);color:var(--on-mint);
  font-size:.64rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;margin-bottom:.9rem}
.tier__n{font-family:'Satoshi';font-weight:900;font-size:1.35rem;letter-spacing:-.04em}
.tier__p{font-family:'Satoshi';font-weight:900;font-size:clamp(2rem,3.2vw,2.8rem);letter-spacing:-.055em;line-height:1;margin-top:.9rem}
.tier__p sup{font-size:.44em;font-weight:700;top:-.85em;position:relative;letter-spacing:0}
.tier__per{font-size:.82rem;color:rgba(255,255,255,.42);margin-top:.35rem}
.tier__setup{margin-top:1rem;padding:.7rem .85rem;border-radius:14px;background:rgba(52,245,173,.08);border:1px solid rgba(52,245,173,.16);
  font-size:.8rem;color:rgba(255,255,255,.72);line-height:1.4}
.tier__setup b{color:var(--mint);font-weight:700}
.tier__f{margin-top:1.2rem;display:flex;flex-direction:column;gap:.55rem;flex:1}
.tier__f li{display:flex;gap:.6rem;font-size:.86rem;color:rgba(255,255,255,.62);line-height:1.4}
.tier__f .tick{margin-top:.15rem}
.tier .btn{margin-top:1.4rem;width:100%;justify-content:space-between}
.tier--soon .core{opacity:.72}
.soonpill{display:inline-flex;align-items:center;height:26px;padding:0 .75rem;border-radius:999px;
  border:1px solid rgba(52,245,173,.32);color:var(--mint);font-size:.7rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase}

/* ── s-pipe — the three-step brief. Mocked end to end; it never touches the network ── */
.s-pipe{position:relative;overflow:hidden;background:var(--void);padding:clamp(100px,15vh,180px) var(--pad)}
.pipe{position:relative;z-index:2;max-width:820px;margin:0 auto;
  padding:clamp(1.5rem,3vw,2.6rem);border:1px solid var(--line);border-radius:var(--rad);
  background:linear-gradient(168deg,#0A0F0D,#040706 62%);box-shadow:inset 0 1px 0 rgba(255,255,255,.07)}
.pipe__rail{display:grid;grid-template-columns:repeat(3,1fr);gap:6px}
.pipe__seg{height:2px;border-radius:99px;background:rgba(255,255,255,.08);overflow:hidden;position:relative}
.pipe__seg::after{content:"";position:absolute;inset:0;transform:scaleX(0);transform-origin:0 50%;
  background:linear-gradient(90deg,var(--emerald),var(--mint),var(--glow));transition:transform .7s var(--e-out)}
.pipe__seg.is-on::after{transform:none}
.pipe__meta{display:flex;align-items:baseline;justify-content:space-between;gap:1rem;margin-top:1rem}
.pipe__step{font-size:.68rem;font-weight:700;letter-spacing:.18em;text-transform:uppercase;color:rgba(255,255,255,.34)}
.pipe__step b{color:var(--mint)}
.pipe__lbl{font-family:'Satoshi';font-weight:700;font-size:.9rem;letter-spacing:-.03em;color:rgba(255,255,255,.6)}
.pstep{display:none;margin-top:clamp(1.5rem,2.6vw,2.2rem)}
.pstep.is-on{display:block}
.pipe__q{margin:0;font-family:'Satoshi';font-weight:900;font-size:clamp(1.2rem,2vw,1.6rem);letter-spacing:-.04em}
.pipe__q--sm{margin-top:1.6rem;font-size:clamp(1rem,1.5vw,1.15rem)}
.pipe__hint{margin:.5rem 0 0;font-size:.88rem;line-height:1.5;color:rgba(255,255,255,.44)}
.pchips{display:flex;flex-wrap:wrap;gap:.5rem;margin-top:1.1rem}
/* ── typed budget with a fixed R ──
   The R lives in the chrome, not the value, so what comes back is always a number. */
/* wide enough that even a nine-figure number never runs out of room — there is no cap
   on what a customer can type, so the field must not imply one */
.pmoney{position:relative;display:flex;align-items:center;margin-top:1.1rem;max-width:440px}
.pmoney__r{position:absolute;left:1rem;font-family:'Satoshi';font-weight:900;font-size:1.15rem;
  color:var(--mint);pointer-events:none;letter-spacing:-.03em}
.pmoney__i{padding-left:2.3rem!important;font-family:'Satoshi';font-weight:700;font-size:1.15rem;
  letter-spacing:-.02em}

/* ── two-up ownership choice ── */
.pcards{display:grid;grid-template-columns:1fr 1fr;gap:1rem;margin-top:1.1rem}
@media(max-width:720px){.pcards{grid-template-columns:1fr}}
.pcard{position:relative;display:flex;flex-direction:column;align-items:flex-start;gap:.45rem;
  padding:1.25rem 1.3rem 1.15rem;border-radius:18px;text-align:left;
  border:1px solid var(--line-2);background:rgba(255,255,255,.02);
  transition:border-color .4s var(--e-soft),background .4s var(--e-soft),transform .5s var(--e-soft)}
.pcard:hover{border-color:rgba(52,245,173,.42);transform:translateY(-2px)}
.pcard.is-on{border-color:var(--mint);background:rgba(52,245,173,.07)}
.pcard__t{font-family:'Satoshi';font-weight:900;font-size:1.02rem;letter-spacing:-.035em;color:#fff}
.pcard__d{font-size:.86rem;line-height:1.5;color:rgba(255,255,255,.5)}
.pcard__tag{margin-top:.35rem;display:inline-flex;align-items:center;height:24px;padding:0 .7rem;
  border-radius:999px;font-size:.62rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  border:1px solid var(--line-2);color:rgba(255,255,255,.5)}
.pcard.is-on .pcard__tag{background:var(--mint);border-color:transparent;color:#00170E}

.pchip{display:inline-flex;align-items:center;height:42px;padding:0 1.05rem;border-radius:999px;
  border:1px solid var(--line-2);font-size:.88rem;font-weight:500;color:rgba(255,255,255,.72);
  transition:border-color .4s var(--e-soft),background .4s var(--e-soft),color .35s,transform .5s var(--e-soft)}
.pchip:hover{border-color:rgba(52,245,173,.42);color:#fff}
.pchip.is-on{background:var(--mint);border-color:transparent;color:#00170E;font-weight:600}
.pchip:active{transform:scale(.97)}
.pgrid{display:grid;grid-template-columns:1fr 1fr;gap:.9rem;margin-top:1.2rem}
@media(max-width:620px){.pgrid{grid-template-columns:1fr}}
.pfield{display:block}
.pfield>span{display:block;font-size:.7rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:rgba(255,255,255,.36);margin-bottom:.45rem}
.pinput{display:block;width:100%;padding:.85rem 1rem;border-radius:14px;font:inherit;font-size:.95rem;
  color:#fff;background:rgba(255,255,255,.035);border:1px solid var(--line-2);
  transition:border-color .4s var(--e-soft),background .4s var(--e-soft),box-shadow .4s}
.pinput--area{margin-top:1.1rem;resize:vertical;min-height:130px;line-height:1.55}
.pinput:focus{outline:none;border-color:var(--mint);background:rgba(255,255,255,.06);box-shadow:0 0 0 4px rgba(52,245,173,.1)}
.pinput::placeholder{color:rgba(255,255,255,.26)}
.pipe__err{margin:1.1rem 0 0;padding:.7rem .9rem;border-radius:12px;font-size:.86rem;
  background:rgba(255,110,110,.1);border:1px solid rgba(255,110,110,.28);color:#FFC9C9}
.pipe__nav{display:flex;justify-content:space-between;gap:.7rem;margin-top:clamp(1.6rem,2.6vw,2.2rem);
  padding-top:clamp(1.2rem,2vw,1.6rem);border-top:1px solid var(--line)}
.pipe__nav .btn[hidden]{display:none}
.pipe__nav .btn:only-child{margin-left:auto}
/* success — deliberately says nothing was sent */
.pdone{position:relative;z-index:2;max-width:820px;margin:0 auto;text-align:center;
  padding:clamp(2rem,4vw,3.2rem) clamp(1.4rem,3vw,2.6rem);border-radius:var(--rad);
  border:1px solid rgba(52,245,173,.28);background:linear-gradient(168deg,rgba(52,245,173,.09),rgba(4,7,6,.9) 62%)}
.pdone[hidden]{display:none}
.pdone__tick{width:60px;height:60px;margin:0 auto;border-radius:50%;display:grid;place-items:center;
  background:var(--mint);color:#00170E}
.pdone__tick svg{width:26px;height:26px}
.pdone__h{margin:1.3rem 0 0;font-family:'Satoshi';font-weight:900;font-size:clamp(1.5rem,2.6vw,2.2rem);letter-spacing:-.045em}
.pdone__p{margin:.9rem auto 0;max-width:56ch;font-size:.95rem;line-height:1.6;color:rgba(255,255,255,.58)}
.pdone__p b{color:var(--mint)}
.pdone__sum{margin-top:1.6rem;text-align:left;border-top:1px solid var(--line)}
.pdone__sum div{display:flex;gap:1.2rem;padding:.75rem .2rem;border-bottom:1px solid var(--line);font-size:.88rem}
.pdone__sum b{flex:none;width:120px;font-size:.66rem;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;color:rgba(255,255,255,.34);padding-top:.16rem}
.pdone__sum span{color:rgba(255,255,255,.72);line-height:1.5}

/* ── s-pick — choose a product, its prices arrive underneath ── */
.s-pick{position:relative;background:var(--void);padding:clamp(110px,16vh,190px) var(--pad)}
.pick{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1px;
  background:var(--line);border:1px solid var(--line);border-radius:2px;overflow:hidden}
@media(max-width:900px){.pick{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:520px){.pick{grid-template-columns:1fr}}
.pick__i{position:relative;display:flex;align-items:center;gap:.8rem;width:100%;text-align:left;
  padding:clamp(.85rem,1.4vw,1.1rem) clamp(.9rem,1.5vw,1.25rem);background:var(--void);
  transition:background .45s var(--e-soft)}
.pick__i:hover{background:rgba(255,255,255,.035)}
.pick__i.is-on{background:linear-gradient(150deg,rgba(52,245,173,.13),rgba(16,185,129,.02))}
.pick__i.is-on::after{content:"";position:absolute;left:0;top:0;bottom:0;width:2px;background:var(--mint)}
.pick__ic{width:24px;height:24px;flex:none;color:rgba(255,255,255,.34);transition:color .4s}
.pick__ic svg{width:100%;height:100%}
.pick__i:hover .pick__ic,.pick__i.is-on .pick__ic{color:var(--mint)}
.pick__n{font-family:'Satoshi';font-weight:700;font-size:.94rem;letter-spacing:-.032em;
  color:rgba(255,255,255,.76);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .4s}
.pick__i.is-on .pick__n{color:#fff}
.pick__m{margin-left:auto;flex:none;font-size:.63rem;font-weight:700;letter-spacing:.13em;
  text-transform:uppercase;color:rgba(255,255,255,.24)}
.pick__i.is-on .pick__m{color:var(--mint)}
.pickpane{position:relative;margin-top:clamp(1.8rem,3.4vw,3rem)}
.pkp[hidden]{display:none}
/* the panes are already in the DOM, so nothing is fetched on select */
.pkp .sec__head{margin-bottom:clamp(1.6rem,3vw,2.4rem)}
.pkp .lede{max-width:70ch}

/* ── s-faq — accordion ── */
.s-faq{position:relative;background:var(--void);padding:clamp(110px,16vh,190px) var(--pad)}
.faq{max-width:940px;margin:0 auto}
.fq{border-top:1px solid var(--line)}
.fq:last-child{border-bottom:1px solid var(--line)}
.fq__h{width:100%;display:flex;align-items:flex-start;gap:1.2rem;padding:1.5rem 0;text-align:left;
  font-family:'Satoshi';font-weight:700;font-size:clamp(1.02rem,1.7vw,1.35rem);letter-spacing:-.035em;color:rgba(255,255,255,.72);
  transition:color .45s var(--e-soft)}
.fq.is-on .fq__h,.fq__h:hover{color:#fff}
.fq__pm{margin-left:auto;flex:none;width:30px;height:30px;border-radius:50%;display:grid;place-items:center;
  background:rgba(255,255,255,.06);color:var(--mint);transition:transform .5s var(--e-soft),background .4s}
.fq__pm svg{width:13px;height:13px}
.fq.is-on .fq__pm{transform:rotate(45deg);background:rgba(52,245,173,.18)}
.fq__b{display:grid;grid-template-rows:0fr;transition:grid-template-rows .6s var(--e-soft)}
.fq.is-on .fq__b{grid-template-rows:1fr}
.fq__i{overflow:hidden}
.fq__i p{padding:0 3rem 1.6rem 0;font-size:.98rem;line-height:1.6;color:rgba(255,255,255,.55)}

/* ── s-founders ── */
.founders{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}
@media(max-width:820px){.founders{grid-template-columns:1fr}}
.fdr .core{padding:clamp(1.6rem,2.6vw,2.4rem);height:100%}
.fdr__av{width:76px;height:76px;border-radius:24px;display:grid;place-items:center;
  background:linear-gradient(150deg,var(--mint),var(--emerald));color:#00170E;
  font-family:'Satoshi';font-weight:900;font-size:1.5rem;letter-spacing:-.06em;box-shadow:inset 0 1px 0 rgba(255,255,255,.4)}
.fdr__n{margin-top:1.4rem;font-family:'Satoshi';font-weight:900;font-size:clamp(1.5rem,2.4vw,2.1rem);letter-spacing:-.045em}
.fdr__r{margin-top:.4rem;font-size:.84rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--mint)}
.fdr__q{margin-top:1.4rem;font-size:clamp(1rem,1.5vw,1.18rem);line-height:1.5;color:rgba(255,255,255,.66);letter-spacing:-.015em}

/* ── s-cover — the country as a province board, on paper ── */
.s-cover{position:relative;overflow:hidden;background:var(--paper);color:var(--on-paper);
  padding:clamp(100px,15vh,180px) var(--pad)}
.s-cover .lede{color:var(--paper-soft)}
.cover__head{position:relative;z-index:2;display:flex;align-items:flex-end;justify-content:space-between;
  gap:2rem;flex-wrap:wrap;margin-bottom:clamp(2.2rem,4vw,3.2rem)}
.cover__n{display:flex;align-items:flex-end;gap:.9rem}
.cover__n>span{font-family:'Cabinet';font-weight:900;font-size:clamp(4rem,9vw,8.5rem);letter-spacing:-.07em;
  line-height:.8;color:var(--emerald)}
.cover__n small{font-size:.72rem;font-weight:700;letter-spacing:.18em;text-transform:uppercase;
  color:var(--paper-soft);line-height:1.5;padding-bottom:.5rem}
/* ── the South Africa map ──
   The outline draws itself, then the nine pins land one after another. This replaced a
   grid of province cards: the cards were accurate but they were a list, and a list of
   provinces does not say "we cover the country" the way the country's own shape does. */
.cover__map{position:relative;max-width:min(680px,92%);margin:clamp(2.4rem,5vw,4rem) auto 0}
.samap{display:block;width:100%;height:auto;overflow:visible}
/* was rgba(2,36,25,.055) — a grey wash that barely separated the country from the
   paper, so the shape read as a smudge. A mint tint makes it a landmass. */
.samap__fill{fill:rgba(79,216,166,.16)}
.samap__line{fill:none;stroke:var(--emerald);stroke-width:3;stroke-linejoin:round;
  stroke-dasharray:1;stroke-dashoffset:1}
.samap__glow{fill:none;stroke:var(--mint);stroke-width:12;opacity:.18;filter:blur(9px);
  stroke-linejoin:round;stroke-dasharray:1;stroke-dashoffset:1}

.samap__pins{position:absolute;inset:0;pointer-events:none}
/* THE DOT IS THE ANCHOR. The pin is a zero-size point at the city's real coordinate;
   the dot is centred on it and the label block is placed AROUND it via data-p. It used
   to be a flex column centred on the coordinate, which meant the dot drifted off the
   city as soon as the label was long — and with the real Natural Earth outline that
   put pins visibly in the wrong place. */
.sapin{position:absolute;translate:-50% -50%;width:0;height:0;
  display:block;line-height:0;

  opacity:0;transform:translateY(7px) scale(.85);
  transition:opacity .55s var(--e-out),transform .6s var(--e-back)}
.sapin.is-in{opacity:1;transform:none}
.sapin i{position:absolute;left:0;top:0;translate:-50% -50%;
  width:11px;height:11px;border-radius:50%;background:var(--emerald);
  box-shadow:0 0 0 4px rgba(16,185,129,.16),0 4px 12px -3px rgba(0,40,26,.6)}
/* default: the label hangs under the dot */
.sapin__t{position:absolute;left:0;top:11px;translate:-50% 0;text-align:center;line-height:1}
/* data-p places it beside instead, for the pins whose cities really are close together */
.sapin[data-p="l"] .sapin__t{left:-13px;top:0;translate:-100% -50%;text-align:right}
.sapin[data-p="r"] .sapin__t{left:13px;top:0;translate:0 -50%;text-align:left}
.sapin b{display:block;font-family:'Satoshi';font-weight:900;font-size:.76rem;
  letter-spacing:-.025em;color:var(--on-paper);white-space:nowrap;line-height:1.1}
.sapin small{display:block;margin-top:.12rem;font-size:.6rem;font-weight:600;letter-spacing:.05em;
  color:rgba(2,36,25,.5);white-space:nowrap;line-height:1.1}
/* Vanderbijlpark — the one pin that is us */
.sapin--hq i{width:15px;height:15px;background:var(--on-paper);
  box-shadow:0 0 0 5px rgba(52,216,166,.35),0 6px 16px -4px rgba(0,40,26,.7)}
.sapin--hq b{font-size:.86rem}
.sapin--hq .sapin__t{top:14px}
.sapin--hq[data-p="l"] .sapin__t{left:-16px;top:0}
.sapin--hq[data-p="r"] .sapin__t{left:16px;top:0}
@media(max-width:620px){
  .sapin b{font-size:.62rem}
  .sapin small{display:none}
  .sapin i{width:9px;height:9px}
}
@media(prefers-reduced-motion:reduce){
  .sapin{opacity:1;transform:none}
  .samap__line,.samap__glow{stroke-dashoffset:0}
}
/* ── s-steps — a process RAIL, not four boxes.
   Each step draws its own segment of the rule and its own node, so the rail runs
   continuously across the gaps and re-forms correctly at every breakpoint. */
.steps{--sgap:clamp(1.2rem,2.4vw,2.6rem);display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--sgap)}
@media(max-width:1000px){.steps{grid-template-columns:repeat(2,minmax(0,1fr));row-gap:clamp(2.4rem,4vw,3.2rem)}}
@media(max-width:560px){.steps{grid-template-columns:1fr;row-gap:2.4rem}}
.step{position:relative;padding-top:clamp(1.5rem,2.4vw,2rem)}
.step::before{content:"";position:absolute;left:0;right:calc(-1 * var(--sgap));top:0;height:1px;background:var(--line)}
.step:last-child::before{right:0}
@media(max-width:1000px){.step:nth-child(2n)::before{right:0}}
@media(max-width:560px){.step::before{right:0}}
/* the node sits on the rail and lights when its step enters */
.step::after{content:"";position:absolute;left:0;top:-4.5px;width:9px;height:9px;border-radius:50%;
  background:var(--ink);box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.24);
  transition:background .7s var(--e-soft),box-shadow .7s var(--e-soft)}
.step.is-in::after{background:var(--mint);box-shadow:0 0 0 5px rgba(52,245,173,.13)}
.step__num{display:block;font-family:'Cabinet';font-weight:900;font-size:clamp(2.3rem,3.6vw,3.5rem);
  letter-spacing:-.07em;line-height:.86;color:rgba(255,255,255,.17);transition:color .8s var(--e-soft)}
.step.is-in .step__num{color:var(--mint)}
.step__w{margin-top:1rem;display:inline-flex;align-items:center;height:26px;padding:0 .72rem;border-radius:999px;
  border:1px solid var(--line-2);color:rgba(255,255,255,.52);
  font-size:.66rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase}
.step__t{margin:.95rem 0 0;font-family:'Satoshi';font-weight:900;font-size:1.14rem;letter-spacing:-.04em}
.step__d{margin:.5rem 0 0;font-size:.88rem;line-height:1.55;color:rgba(255,255,255,.46);max-width:34ch}

/* ── s-ledger — an editorial run-sheet of outcomes across the whole roster ── */
.s-ledger{position:relative;overflow:hidden;background:var(--void);padding:clamp(100px,15vh,180px) var(--pad)}
.ledger{position:relative;z-index:2;border-top:1px solid var(--line)}
.ldg{display:grid;grid-template-columns:minmax(132px,.85fr) minmax(0,2.7fr) minmax(84px,auto);
  align-items:center;gap:1.4rem;padding:clamp(1rem,1.7vw,1.35rem) .3rem;border-bottom:1px solid var(--line);
  transition:background .55s var(--e-soft),padding-left .6s var(--e-soft)}
.ldg:hover{background:rgba(255,255,255,.028);padding-left:1.1rem}
.ldg__k{font-size:.67rem;font-weight:700;letter-spacing:.16em;text-transform:uppercase;
  color:rgba(255,255,255,.34);transition:color .45s}
.ldg:hover .ldg__k{color:var(--mint)}
.ldg__t{font-family:'Satoshi';font-weight:700;font-size:clamp(1rem,1.55vw,1.3rem);letter-spacing:-.035em;
  color:rgba(255,255,255,.8);transition:color .45s}
.ldg:hover .ldg__t{color:#fff}
.ldg__v{margin-left:auto;font-family:'Cabinet';font-weight:900;font-size:clamp(1.3rem,2.1vw,1.95rem);
  letter-spacing:-.055em;line-height:1;color:var(--mint);white-space:nowrap}
@media(max-width:820px){
  .ldg{grid-template-columns:1fr auto;gap:.35rem 1rem;padding:1.1rem .3rem}
  .ldg__k{grid-column:1/-1}
  .ldg__t{font-size:1rem}
}

/* ── s-proof — stat row ── */
.s-proof{position:relative;background:var(--void);padding:clamp(70px,10vh,130px) var(--pad) clamp(100px,14vh,160px)}
.rule{height:1px;background:linear-gradient(90deg,transparent,rgba(52,245,173,.25) 18%,var(--mint) 50%,rgba(52,245,173,.25) 82%,transparent);
  margin-bottom:clamp(2.6rem,5vw,4rem)}
.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(1.2rem,3vw,2rem)}
@media(max-width:760px){.stats{grid-template-columns:repeat(2,1fr)}}
.stat__n{font-family:'Satoshi';font-weight:900;font-size:clamp(2.6rem,5.6vw,5rem);letter-spacing:-.055em;line-height:.9;
  background:linear-gradient(180deg,#fff 22%,rgba(255,255,255,.28));-webkit-background-clip:text;background-clip:text;color:transparent}
.stat__l{margin-top:.75rem;font-size:.8rem;font-weight:500;color:rgba(255,255,255,.42);letter-spacing:-.01em}

/* ── s-cards — indexed spec grid.
   The separators are the 1px grid GAP showing the container colour through, so the
   hairlines stay perfect at 3 columns, 2 columns, or any wrap, with no nth-child maths. */
@layer th-scene{
.cards{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1px;
  background:var(--line);border:1px solid var(--line);border-radius:2px}
@media(max-width:1000px){.cards{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:640px){.cards{grid-template-columns:1fr}}
.cards--2{grid-template-columns:repeat(2,minmax(0,1fr))}
@media(max-width:820px){.cards--2{grid-template-columns:1fr}}
.card{position:relative;overflow:hidden;background:var(--void);
  padding:clamp(1.5rem,2.3vw,2.1rem) clamp(1.3rem,2vw,1.9rem) clamp(1.9rem,2.8vw,2.5rem)}
/* the oversized ghost index — the AE "feature plate" cue, and what replaces the icon tile */
.card__ix{position:absolute;right:.45rem;top:-.35rem;font-family:'Cabinet';font-weight:900;
  font-size:clamp(3.6rem,5.4vw,5.6rem);letter-spacing:-.07em;line-height:1;pointer-events:none;
  color:rgba(255,255,255,.05);transition:color .7s var(--e-soft),transform .8s var(--e-soft)}
.card:hover .card__ix{color:rgba(52,245,173,.16);transform:translateY(-5px)}
.card__g{display:block;width:22px;height:22px;color:var(--mint)}
.card__g svg{width:100%;height:100%}
.card__t{position:relative;margin:1.15rem 0 0;font-family:'Satoshi';font-weight:900;font-size:1.14rem;letter-spacing:-.04em}
.card__d{margin:.55rem 0 0;font-size:.9rem;line-height:1.55;color:rgba(255,255,255,.48);max-width:36ch}
/* a mint rule grows along the foot on hover — the only movement in the grid */
.card::after{content:"";position:absolute;left:0;bottom:0;height:2px;width:0;
  background:linear-gradient(90deg,var(--glow),var(--mint-lo));transition:width .75s var(--e-soft)}
.card:hover::after{width:100%}
}

/* ═══════════════════════════════════════════════════════════════
   09b · EDITORIAL — blog index, articles, city pages
   These carry the ported copy. Nothing here writes content; it only paints
   the structures th_article.js maps the legacy markup onto.
   ═══════════════════════════════════════════════════════════════ */
/* layered: the wizard has its own .sr-only, and unlayered CSS would beat it */
@layer th-scene{
.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}
}

/* ── blog index ── */
.s-blog{position:relative;background:var(--void);padding:clamp(70px,10vh,120px) var(--pad) clamp(110px,16vh,180px)}
.bsearch{width:min(100%,330px)}
.bsearch .pinput{padding:.72rem 1rem;border-radius:999px;font-size:.9rem}
.bfilter{display:flex;flex-wrap:wrap;gap:.45rem;margin-bottom:clamp(1.8rem,3vw,2.6rem);
  padding-bottom:clamp(1.4rem,2.4vw,2rem);border-bottom:1px solid var(--line)}
.bchip{display:inline-flex;align-items:center;gap:.5rem;height:38px;padding:0 .95rem;border-radius:999px;
  border:1px solid var(--line-2);font-size:.85rem;font-weight:500;color:rgba(255,255,255,.62);
  transition:border-color .4s var(--e-soft),background .4s var(--e-soft),color .35s}
.bchip span{font-size:.66rem;font-weight:700;color:rgba(255,255,255,.3)}
.bchip:hover{border-color:rgba(52,245,173,.42);color:#fff}
.bchip.is-on{background:var(--mint);border-color:transparent;color:#00170E;font-weight:600}
.bchip.is-on span{color:rgba(0,23,14,.55)}
.bgrid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1px;
  background:var(--line);border:1px solid var(--line);border-radius:2px}
@media(max-width:1000px){.bgrid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:640px){.bgrid{grid-template-columns:1fr}}
.bcard{display:flex;flex-direction:column;background:var(--void);overflow:hidden;
  transition:background .5s var(--e-soft)}
.bcard[hidden]{display:none}
.bcard:hover{background:rgba(255,255,255,.03)}
.bcard__thumb{display:block;aspect-ratio:16/9;overflow:hidden;background:var(--ink-2)}
.bcard__thumb img{width:100%;height:100%;object-fit:cover;
  transition:transform 1.1s var(--e-soft),filter .7s var(--e-soft);filter:grayscale(.35) contrast(1.05)}
.bcard:hover .bcard__thumb img{transform:scale(1.05);filter:none}
.bcard__in{display:flex;flex-direction:column;flex:1;padding:clamp(1.2rem,1.9vw,1.6rem)}
.bcard__meta{display:flex;align-items:center;gap:.7rem;margin-bottom:.9rem}
.bcard__meta b{font-size:.62rem;font-weight:700;letter-spacing:.15em;text-transform:uppercase;color:var(--mint)}
.bcard__meta i{margin-left:auto;font-style:normal;font-size:.72rem;color:rgba(255,255,255,.3)}
.bcard__t{font-family:'Satoshi';font-weight:900;font-size:1.14rem;letter-spacing:-.04em;line-height:1.14;color:#fff}
.bcard__d{margin-top:.6rem;font-size:.88rem;line-height:1.55;color:rgba(255,255,255,.46)}
.bcard__go{display:inline-flex;align-items:center;gap:.5rem;margin-top:auto;padding-top:1.1rem;
  font-size:.84rem;font-weight:600;color:var(--mint)}
.bcard__go svg{width:12px;height:12px;transition:transform .5s var(--e-soft)}
.bcard:hover .bcard__go svg{transform:translate(3px,-3px)}
.bempty{margin-top:2.4rem;text-align:center;color:rgba(255,255,255,.45);font-size:.95rem}
.bempty[hidden]{display:none}

/* ── article ── */
.s-art{position:relative;overflow:hidden;background:radial-gradient(120% 90% at 50% 0%,#0C1512 0%,#040706 48%,#000 100%);
  padding:clamp(150px,20vh,220px) var(--pad) clamp(50px,7vh,80px);text-align:center}
.s-art .wrap{position:relative;z-index:2}
.s-art h1{max-width:20ch;margin-inline:auto}
.artmeta{display:flex;justify-content:center;align-items:center;gap:.7rem;flex-wrap:wrap;margin-top:1.6rem}
.artmeta__tag{display:inline-flex;align-items:center;height:28px;padding:0 .8rem;border-radius:999px;
  background:rgba(52,245,173,.13);color:var(--mint);font-size:.68rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase}
.artmeta__d{font-size:.82rem;color:rgba(255,255,255,.38)}
.artshot{margin-top:clamp(2rem,4vw,3.2rem);border-radius:var(--rad);overflow:hidden;border:1px solid var(--line)}
.artshot img{width:100%;height:auto;aspect-ratio:21/9;object-fit:cover;display:block}

.s-prose{position:relative;background:var(--void);padding:clamp(50px,7vh,80px) var(--pad) clamp(90px,13vh,150px)}
/* the typographic system the ported article copy lands in */
.prose{font-size:clamp(1.02rem,1.35vw,1.14rem);line-height:1.75;color:rgba(255,255,255,.72);letter-spacing:-.006em}
.prose>*:first-child{margin-top:0}
.prose p{margin:1.35em 0}
.prose h2,.prose h3,.prose h4{margin:2.1em 0 .7em;line-height:1.1;color:#fff}
.prose h2{font-size:clamp(1.6rem,2.8vw,2.3rem);letter-spacing:-.045em}
.prose h3{font-size:clamp(1.28rem,2vw,1.65rem);letter-spacing:-.04em}
.prose h4{font-size:1.14rem;letter-spacing:-.035em}
/* a mint tick in the margin marks each section — the AE "spec sheet" cue */
.prose h3::before{content:"";display:inline-block;width:14px;height:2px;border-radius:99px;
  background:var(--mint);vertical-align:middle;margin-right:.65rem;translate:0 -.18em}
.prose strong{color:#fff;font-weight:700}
.prose em{color:var(--mint);font-style:normal}
.prose a{color:var(--mint);text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1px}
.prose a:hover{color:var(--glow)}
.prose ul,.prose ol{margin:1.35em 0;padding-left:0;display:flex;flex-direction:column;gap:.7em}
.prose li{position:relative;padding-left:2rem;list-style:none}
.prose ul>li::before{content:"";position:absolute;left:.35rem;top:.72em;width:6px;height:6px;border-radius:50%;background:var(--mint)}
.prose ol{counter-reset:pl}
.prose ol>li{counter-increment:pl}
.prose ol>li::before{content:counter(pl,decimal-leading-zero);position:absolute;left:0;top:.06em;
  font-family:'Cabinet';font-weight:900;font-size:.9em;color:var(--mint);letter-spacing:-.04em}
.prose blockquote{margin:2em 0;padding:1.4rem 1.6rem;border-left:2px solid var(--mint);border-radius:0 16px 16px 0;
  background:linear-gradient(100deg,rgba(52,245,173,.07),transparent 70%);
  font-family:'Satoshi';font-weight:700;font-size:clamp(1.1rem,1.7vw,1.35rem);line-height:1.45;
  letter-spacing:-.03em;color:rgba(255,255,255,.88)}
.prose img{width:100%;height:auto;border-radius:var(--rad);margin:2em 0;border:1px solid var(--line)}
/* A table cannot reflow without destroying its own meaning, so it scrolls inside its
   own box instead of pushing the page sideways. The mint edge fade is the affordance
   that says "there is more to the right" — on a phone there is no scrollbar to see. */
.tblwrap{position:relative;max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;
  margin:2em 0;border-radius:14px}
.tblwrap:focus-visible{outline:2px solid var(--mint);outline-offset:2px}
.tblwrap table{margin:0}
.tblwrap::-webkit-scrollbar{height:5px}
.tblwrap::-webkit-scrollbar-thumb{background:rgba(52,245,173,.4);border-radius:99px}
.prose table{width:100%;border-collapse:collapse;margin:2em 0;font-size:.94rem}
.prose th,.prose td{padding:.8rem .9rem;border-bottom:1px solid var(--line);text-align:left}
.prose th{font-family:'Satoshi';font-weight:700;color:#fff;font-size:.78rem;letter-spacing:.1em;text-transform:uppercase}
.prose hr{border:0;height:1px;background:var(--line);margin:2.6em 0}

.relrow{display:flex;flex-wrap:wrap;gap:.6rem;margin-top:1.2rem}
.relrow__i{display:inline-flex;align-items:center;gap:.6rem;height:46px;padding:0 1.2rem;border-radius:999px;
  border:1px solid var(--line-2);font-size:.92rem;font-weight:600;color:rgba(255,255,255,.78);
  transition:border-color .45s var(--e-soft),color .35s,transform .5s var(--e-soft)}
.relrow__i svg{width:12px;height:12px;color:var(--mint)}
.relrow__i:hover{border-color:rgba(52,245,173,.5);color:#fff;transform:translateY(-2px)}

/* ── city pages: the ported local copy, repainted ── */
.cityx{position:relative;background:var(--void)}
.cityx .sec--alt{background:var(--ink)}
.cityx .sec{padding:clamp(72px,11vh,130px) var(--pad)}
.cityx .eyebrow{margin-bottom:.9rem}
.cityx .h-sec{max-width:24ch}
.cityx .lede{margin-top:1.3rem}
.cityx .cards,.cityx .cchips,.cityx .areas,.cityx .faqx{margin-top:clamp(1.8rem,3vw,2.6rem)}
.cityx .card--plain{display:flex;align-items:flex-start;gap:.9rem;font-size:.95rem;line-height:1.6;color:rgba(255,255,255,.6)}
.cityx .card--plain::before{content:"";flex:none;width:7px;height:7px;border-radius:50%;background:var(--mint);margin-top:.55rem}
.card--plain{background:var(--void)}
.card>h3{margin:0;font-family:'Satoshi';font-weight:900;font-size:1.14rem;letter-spacing:-.04em;color:#fff}
.card>p{margin:.6rem 0 0;font-size:.9rem;line-height:1.6;color:rgba(255,255,255,.48)}
.card__m{margin-top:.5rem;font-size:.86rem;line-height:1.5;color:var(--mint)}
.card__pr{display:flex;gap:1.4rem;margin-top:1rem;padding-top:.9rem;border-top:1px solid var(--line)}
.card__pr strong{display:block;font-family:'Satoshi';font-weight:900;font-size:1.05rem;letter-spacing:-.04em;color:#fff}
.card__pr span{display:block;margin-top:.15rem;font-size:.64rem;font-weight:700;letter-spacing:.13em;
  text-transform:uppercase;color:rgba(255,255,255,.3)}
.citystats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:1px;background:var(--line);
  border:1px solid var(--line);border-radius:2px;margin-top:clamp(2.2rem,4vw,3.2rem)}
@media(max-width:760px){.citystats{grid-template-columns:repeat(2,minmax(0,1fr))}}
.citystats>div{background:var(--void);padding:1.05rem 1.1rem;text-align:left}
.citystats b{display:block;font-family:'Satoshi';font-weight:900;font-size:clamp(1.3rem,2.2vw,1.9rem);
  letter-spacing:-.05em;line-height:1;color:var(--mint)}
.citystats span{display:block;margin-top:.4rem;font-size:.76rem;color:rgba(255,255,255,.42);line-height:1.35}
/* the answer-first block (targets AI Overviews / voice search) */
.answer{padding:1.3rem 1.5rem;border-radius:var(--rad);border:1px solid rgba(52,245,173,.24);
  background:linear-gradient(160deg,rgba(52,245,173,.08),rgba(4,7,6,.6) 70%);
  font-size:1rem;line-height:1.7;color:rgba(255,255,255,.74)}
.answer strong{color:#fff}
/* the suburb boards */
.areas{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1px;background:var(--line);
  border:1px solid var(--line);border-radius:2px}
@media(max-width:820px){.areas{grid-template-columns:1fr}}
.abox{background:var(--void);padding:clamp(1.3rem,2.1vw,1.9rem)}
.abox h3{margin:0;font-family:'Satoshi';font-weight:900;font-size:1.14rem;letter-spacing:-.04em;color:#fff}
.abox p{margin:.55rem 0 0;font-size:.9rem;line-height:1.55;color:rgba(255,255,255,.46)}
.atags{display:flex;flex-wrap:wrap;gap:.4rem;margin-top:1.1rem}
.atag{display:inline-flex;align-items:center;height:32px;padding:0 .8rem;border-radius:999px;
  border:1px solid var(--line);font-size:.78rem;color:rgba(255,255,255,.6);
  transition:border-color .4s,color .35s}
.atag:hover{border-color:rgba(52,245,173,.4);color:#fff}
/* native <details> FAQ — the city pages use details/summary, not the site accordion */
.faqx{max-width:960px}
.fqx{border-top:1px solid var(--line)}
.fqx:last-child{border-bottom:1px solid var(--line)}
.fqx__q{list-style:none;cursor:pointer;display:flex;align-items:flex-start;gap:1.2rem;padding:1.35rem 0;
  font-family:'Satoshi';font-weight:700;font-size:clamp(1rem,1.5vw,1.2rem);letter-spacing:-.035em;
  color:rgba(255,255,255,.74);transition:color .4s var(--e-soft)}
.fqx__q::-webkit-details-marker{display:none}
.fqx__q::after{content:"";flex:none;margin-left:auto;width:28px;height:28px;border-radius:50%;
  background:rgba(255,255,255,.06) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%234FD8A6' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M12 5v14M5 12h14'/%3E%3C/svg%3E") center/12px no-repeat;
  transition:transform .5s var(--e-soft),background-color .4s}
.fqx[open] .fqx__q{color:#fff}
.fqx[open] .fqx__q::after{transform:rotate(45deg);background-color:rgba(52,245,173,.18)}
.fqx__a{padding:0 3rem 1.5rem 0;font-size:.97rem;line-height:1.65;color:rgba(255,255,255,.55)}

/* ── s-final — the closing mint field ── */
.s-final{position:relative;min-height:80svh;display:flex;align-items:center;justify-content:center;text-align:center;
  padding:clamp(96px,14vh,160px) var(--pad);overflow:hidden;color:var(--on-mint);
  background:linear-gradient(200deg,var(--mint-hi),var(--mint) 46%,var(--mint-lo))}
.s-final__in{position:relative;z-index:2;max-width:1180px}

/* Document + 404 heading spacing lives OUTSIDE @layer th-scene deliberately.
   The base rule `h1,h2,h3,h4{margin:0}` is unlayered, and unlayered CSS beats
   layered CSS no matter the specificity — a layered `.s-e404 .h-sec{margin-bottom}`
   loses to it and the lede collides with the heading's descenders. */
.s-doc__top .h-sec,.s-e404 .h-sec{margin-bottom:.42em}

/* ═══════════════════════════════════════════════════════════════
   09b1 · LIGHT SWEEP — from AE-04 "AI SaaS Promo"
   In the template a bright mint flare travels across a list and the row it crosses
   flares white. Here it rakes the spec-row grid as the section scrolls in, so the
   cards arrive as one lit pass instead of a staggered fade — that stagger was most of
   what made the grid read as generic.
   Driven by --sweep (0→1) written by th.js from a ScrollTrigger.
   ═══════════════════════════════════════════════════════════════ */
@layer th-scene{
.cards{--sweep:0;position:relative;isolation:isolate}
.cards::after{
  content:"";position:absolute;top:0;bottom:0;z-index:3;pointer-events:none;
  width:34%;left:calc(var(--sweep) * 134% - 34%);
  background:linear-gradient(90deg,transparent,rgba(52,245,173,.16) 45%,rgba(52,245,173,.05) 70%,transparent);
  filter:blur(22px);opacity:calc(1 - max(0, var(--sweep) * 2 - 1.35))}
/* the card the beam is over lifts its rule and its numeral */
.card{transition:background .6s var(--e-soft)}
.card.is-lit{background:#070C0A}
.card.is-lit .card__ix{color:rgba(52,245,173,.2)}
.card.is-lit::after{width:100%}
@media(prefers-reduced-motion:reduce){.cards::after{display:none}}
}

/* ═══════════════════════════════════════════════════════════════
   09b2 · PROCESS RIBBON — replaces the .step card row
   From AE-03: a glowing mint ribbon with white icon badges riding the curve.
   Nodes are placed with --at (a percentage along the width) and lifted/dropped
   alternately so they sit near the curve rather than on a straight line.
   ═══════════════════════════════════════════════════════════════ */
@layer th-scene{
.s-ribbon{overflow:hidden}
/* The band reserves room above and below the curve for the cards. --pad and --svgh are
   named because the badge positions are derived from them arithmetically: the viewBox
   puts crests at y=40 and troughs at y=220 of 260, i.e. 15.4% and 84.6% of the SVG's
   rendered height. No JS measures anything. */
.ribbon{--rbpad:clamp(140px,14vw,200px);--svgh:clamp(150px,17vw,230px);
  position:relative;margin-top:clamp(2rem,4vw,3.4rem);padding:var(--rbpad) 0}
.ribbon__svg{display:block;width:100%;height:var(--svgh);overflow:visible}
.rnode--hi{--y:calc(var(--rbpad) + 0.1538 * var(--svgh))}
.rnode--lo{--y:calc(var(--rbpad) + 0.8462 * var(--svgh))}
/* a crest has empty space above it, a trough has empty space below */
.rnode--hi .rnode__card{bottom:calc(100% - var(--y) + clamp(38px,4.4vw,54px));top:auto}
.rnode--lo .rnode__card{top:calc(var(--y) + clamp(38px,4.4vw,54px));bottom:auto}
/* NO vector-effect:non-scaling-stroke here. With preserveAspectRatio="none" it makes
   the browser compute dashes in SCREEN space while getTotalLength() reports USER
   space — the line then stops short of the right edge by exactly the scale factor. */
.ribbon__line,.ribbon__glow{fill:none;stroke:url(#rbg);stroke-linecap:round}
.ribbon__line{stroke-width:10}
.ribbon__glow{stroke-width:26;opacity:.28;filter:blur(14px)}

.ribbon__nodes{position:absolute;inset:0;list-style:none;margin:0;padding:0}
/* --at is the x position along the width; --y is written by JS from the real path
   point, so a badge always sits exactly ON the curve however the SVG has stretched. */
.rnode{position:absolute;left:var(--at);top:0;height:100%;width:min(240px,23vw);
  transform:translateX(-50%)}
.rnode__dot{position:absolute;left:50%;top:var(--y,50%);translate:-50% -50%;
  width:clamp(38px,4.4vw,54px);height:clamp(38px,4.4vw,54px);border-radius:50%;
  display:grid;place-items:center;background:#fff;color:var(--emerald);
  box-shadow:0 18px 38px -16px rgba(0,0,0,.9),0 0 0 0 rgba(52,245,173,.3);
  opacity:0;transform:scale(.5);
  transition:opacity .6s var(--e-out),transform .7s var(--e-back),box-shadow .7s var(--e-soft)}
.rnode__dot svg{width:44%;height:44%}
.rnode.is-in .rnode__dot{opacity:1;transform:none;box-shadow:0 18px 38px -16px rgba(0,0,0,.9),0 0 0 9px rgba(52,245,173,.11)}

/* the card clears the badge by its own radius plus a gap, measured from --y —
   so it can never overlap the curve no matter where the peak falls */
.rnode__card{position:absolute;left:0;right:0;text-align:center;
  opacity:0;transform:translateY(14px);
  transition:opacity .7s var(--e-out) .12s,transform .8s var(--e-out) .12s}
.rnode--down .rnode__card{top:calc(var(--y,50%) + clamp(40px,4.6vw,56px))}
.rnode--up .rnode__card{bottom:calc(100% - var(--y,50%) + clamp(40px,4.6vw,56px))}
.rnode.is-in .rnode__card{opacity:1;transform:none}
.rnode__n{display:block;font-family:'Cabinet';font-weight:900;font-size:clamp(1.5rem,2.2vw,2.1rem);
  letter-spacing:-.06em;line-height:1;color:rgba(255,255,255,.18);transition:color .7s var(--e-soft)}
.rnode.is-in .rnode__n{color:var(--mint)}
.rnode__w{display:inline-flex;align-items:center;height:24px;margin-top:.5rem;padding:0 .68rem;
  border-radius:999px;border:1px solid var(--line-2);color:rgba(255,255,255,.5);
  font-size:.62rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase}
.rnode__t{margin:.7rem 0 0;font-family:'Satoshi';font-weight:900;font-size:1.02rem;letter-spacing:-.04em}
.rnode__d{margin:.4rem 0 0;font-size:.84rem;line-height:1.5;color:rgba(255,255,255,.46)}

/* Under 860px a snaking horizontal ribbon is unreadable — become a vertical rail.
   Same nodes, same classes; only the geometry changes. */
@media(max-width:860px){
  .ribbon__svg{display:none}
  /* --rbpad is 140–200px of vertical room for a curve that is no longer drawn */
  .ribbon{padding:0;--rbpad:0px}
  .ribbon__nodes{position:static;display:grid;gap:2.1rem;padding-left:2.6rem;
    border-left:2px solid rgba(52,245,173,.22)}
  .rnode,.rnode:nth-child(odd),.rnode:nth-child(even){position:relative;left:auto;top:auto;
    height:auto;width:auto;transform:none;text-align:left}
  .rnode__dot,.rnode:nth-child(odd) .rnode__dot,.rnode:nth-child(even) .rnode__dot{
    position:absolute;left:calc(-2.6rem - 1px);top:.1rem;bottom:auto;translate:-50% 0;
    width:38px;height:38px}
  /* THE BUG, 2026-07-29: the card stayed `position:absolute` and .rnode--hi/--lo kept
     pushing it with bottom:calc(100% - var(--y)…). Every card was lifted out of flow,
     so the grid rows collapsed, all four dots stacked in the top-left corner and the
     cards printed on top of each other. Resetting `position` is the whole fix — the
     top/bottom overrides need matching specificity (0,2,0) to land. */
  .rnode__card,
  .rnode--hi .rnode__card,.rnode--lo .rnode__card,
  .rnode--up .rnode__card,.rnode--down .rnode__card,
  .rnode:nth-child(even) .rnode__card{
    position:static;top:auto;bottom:auto;left:auto;right:auto;
    padding:0;text-align:left}
  .rnode__n{font-size:1.35rem}
  .rnode__t{font-size:1.06rem;margin-top:.55rem}
  .rnode__d{max-width:46ch}
}
@media(prefers-reduced-motion:reduce){
  .rnode__dot,.rnode__card{opacity:1;transform:none}
}
}

/* ═══════════════════════════════════════════════════════════════
   09c · DOCUMENTS — privacy, terms, security, data-rights, 404
   These carry legal copy lifted verbatim from the live pages. The job here is
   readability at 25,000 characters, not decoration: one narrow column, generous
   leading, and the section rules doing the structural work.
   ═══════════════════════════════════════════════════════════════ */
@layer th-scene{
.s-doc__top{padding-bottom:0}
.s-doc__meta{margin-top:1.4rem;display:inline-flex;align-items:center;height:30px;padding:0 .85rem;
  border-radius:999px;border:1px solid var(--line-2);
  font-size:.68rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.5)}
.s-doc .prose{max-width:74ch}
/* legal documents are numbered top to bottom; a hairline before each h2 turns a
   wall of clauses into a scannable spine */
.s-doc .prose h2{padding-top:1.5em;border-top:1px solid var(--line)}
.s-doc .prose h2:first-child{padding-top:0;border-top:0}
.s-doc .prose hr{margin:2.6em 0;border:0;border-top:1px solid var(--line)}
.s-doc .prose li{margin:.5em 0}
.s-doc .prose a{color:var(--mint);text-decoration:underline;text-underline-offset:3px;
  text-decoration-color:rgba(52,245,173,.35);transition:text-decoration-color .35s}
.s-doc .prose a:hover{text-decoration-color:var(--mint)}
/* the live docs use tables for the retention schedule and the sub-processor list */
.s-doc .prose table{width:100%;border-collapse:collapse;margin:1.6em 0;font-size:.92rem}
.s-doc .prose th,.s-doc .prose td{padding:.7rem .8rem;border:1px solid var(--line);text-align:left;vertical-align:top}
.s-doc .prose th{background:rgba(255,255,255,.03);color:#fff;font-weight:700}

/* ── POPIA request form (mocked) ── */
.dsar{margin:1.8rem 0 0;padding:clamp(1.3rem,2.4vw,2rem);border-radius:var(--rad);
  border:1px solid var(--line);background:linear-gradient(165deg,#0B100E,#050706 60%)}
.dsar__g{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1.1rem;margin-bottom:1.1rem}
@media(max-width:700px){.dsar__g{grid-template-columns:1fr}}
.dsar .btn{margin-top:1.4rem}
.dsar__fine{margin:1.1rem 0 0;font-size:.82rem;line-height:1.55;color:rgba(255,255,255,.4)}
.dsar__ok{margin:1.8rem 0 0;padding:clamp(1.3rem,2.4vw,2rem);border-radius:var(--rad);
  border:1px solid rgba(52,245,173,.3);background:rgba(52,245,173,.05)}
.dsar__okt{font-family:'Satoshi';font-weight:900;font-size:1.05rem;letter-spacing:-.03em;
  color:var(--mint);margin-bottom:.5rem}
.dsar__ok p{margin:0;font-size:.95rem;line-height:1.6;color:rgba(255,255,255,.6)}

/* ── 404 ── */
.s-e404{min-height:82svh;display:flex;align-items:center;text-align:center}
.s-e404 .wrap{width:100%}
.s-e404 .lede{margin-left:auto;margin-right:auto}
.e404__n{font-size:clamp(7rem,26vw,20rem);line-height:.8;color:rgba(255,255,255,.05);
  margin-bottom:-.06em;pointer-events:none;user-select:none}
.e404__links{display:flex;flex-wrap:wrap;justify-content:center;gap:1px;margin-top:clamp(2.2rem,4vw,3.2rem);
  background:var(--line);border:1px solid var(--line);border-radius:2px;overflow:hidden}
.e404__l{display:flex;align-items:center;justify-content:space-between;gap:1.2rem;
  flex:1 1 220px;padding:1.15rem 1.3rem;background:var(--void);text-align:left;
  font-family:'Satoshi';font-weight:700;font-size:1rem;letter-spacing:-.03em;
  transition:background .5s var(--e-soft),color .4s}
.e404__l:hover{background:#080D0B;color:var(--mint)}
.e404__x{display:grid;place-items:center;width:30px;height:30px;flex:none;border-radius:50%;
  background:rgba(255,255,255,.06);transition:background .45s var(--e-soft),transform .5s var(--e-soft)}
.e404__x svg{width:13px;height:13px}
.e404__l:hover .e404__x{background:rgba(52,245,173,.18);transform:translate(3px,-3px)}
}

/* ══════════ 10 · OUTRO (every page) — Innovate. Automate. Dominate. ══════════ */
/* the height IS the scrub track: a sticky viewport with no scroll room above it
   never sticks, and the scene renders as a dead black screen.
   Cut 260svh → 150svh (50svh per word) so the run to the footer is quick — the words
   still get a full beat each because the scrub was tightened to match. */
.s-outro{position:relative;background:var(--void);height:150svh}
/* dvh, not svh. svh is the SMALL viewport — the height with the URL bar VISIBLE. When
   Android Chrome collapses its bar the visible screen grows ~64px but this sticky box
   does not, so .s-outro__bg (inset:0 inside it) stopped short and a black strip of
   .s-outro showed under the mint field on every page. dvh tracks the live viewport.
   Chrome 108+ / Safari 15.4+ — every phone in the field. */
.s-outro__vp{position:sticky;top:0;height:100dvh;display:grid;place-items:center;overflow:hidden}
.s-outro__bg{position:absolute;inset:0;background:var(--void)}
.s-outro__wrap{position:relative;z-index:2;width:100%;text-align:center;padding:0 var(--pad)}
.s-outro .kw{font-size:clamp(3rem,17vw,14rem)}
.s-outro__cta{position:absolute;left:0;right:0;bottom:clamp(30px,7vh,80px);z-index:3;display:flex;justify-content:center;gap:.7rem;flex-wrap:wrap;
  opacity:0;transition:opacity .8s var(--e-soft)}
.s-outro__cta.is-in{opacity:1}
/* the outro field cycles black -> mint -> paper, so the buttons must invert with it
   or they vanish into whichever tone they were designed for */
.s-outro.on-light .btn--mint{background:#03130D;color:#EAFBF3}
.s-outro.on-light .btn--mint .btn__chip{background:rgba(255,255,255,.14)}
.s-outro.on-light .btn--line{border-color:rgba(2,36,25,.32);color:#042419}
.s-outro.on-light .btn--line .btn__chip{background:rgba(1,40,27,.1)}
.s-outro.on-light .btn--line:hover{border-color:rgba(1,40,27,.62)}

/* ══════════ 11 · FOOTER ══════════ */
footer.foot{position:relative;background:var(--mint-lo);color:var(--on-mint);padding:clamp(56px,8vh,90px) var(--pad) 0;overflow:hidden}
footer.foot .foot__grid{max-width:var(--maxw);margin:0 auto;display:grid;grid-template-columns:1.5fr repeat(3,minmax(0,1fr));gap:clamp(1.6rem,3vw,3rem)}
@media(max-width:940px){.foot__grid{grid-template-columns:1fr 1fr}}
@media(max-width:560px){.foot__grid{grid-template-columns:1fr}}
.foot__lede{font-size:.95rem;line-height:1.55;color:rgba(2,36,25,.66);max-width:34ch;margin-top:1rem}
footer.foot h4{font-size:.7rem;font-weight:700;letter-spacing:.18em;text-transform:uppercase;color:rgba(2,36,25,.5);margin-bottom:1rem}
.foot__col a{display:block;padding:.3rem 0;font-size:.92rem;color:rgba(2,36,25,.72);transition:color .35s,padding-left .4s var(--e-soft)}
.foot__col a:hover{color:var(--on-mint);padding-left:.35rem}
.foot__in{max-width:var(--maxw);margin:clamp(2rem,4vw,3rem) auto 0;display:flex;align-items:center;justify-content:space-between;
  gap:1.4rem;flex-wrap:wrap;padding:clamp(20px,3vw,30px) 0;border-top:1px solid rgba(2,36,25,.16)}
.foot__c{font-size:.8rem;color:rgba(2,36,25,.5)}
.foot__legal{display:flex;gap:1.2rem;flex-wrap:wrap}
.foot__legal a{font-size:.8rem;color:rgba(2,36,25,.5)}
.foot__legal a:hover{color:var(--on-mint)}
.foot__mark{font-family:'Cabinet';font-weight:900;font-size:clamp(2.4rem,14.1vw,13.6rem);letter-spacing:-.06em;line-height:.78;
  color:#03291D;text-align:center;margin:clamp(.6rem,2vw,1.4rem) 0 -.17em;user-select:none;white-space:nowrap}
.foot__brand{display:flex;align-items:center;gap:.65rem}
.foot__brand .brand__mark{width:40px;height:40px;filter:drop-shadow(0 8px 18px rgba(0,40,26,.35))}
.foot__brand .brand__name{color:var(--on-mint)}

/* ══════════ 11b · FILM — the small in-page player ══════════
   Capped hard at 660px on purpose: Duval asked for something that does NOT take over
   the screen. Everything else is the same double-bezel object as a tier card. */
@layer th-scene{
  .s-film .sec__head{margin-bottom:clamp(1.8rem,3.4vw,2.6rem)}
  .film{max-width:660px;margin:0 auto;position:relative}
  .film__shell{position:relative}
  .film__core{position:relative;overflow:hidden;line-height:0;isolation:isolate}
  .film__el{display:block;width:100%;height:auto;aspect-ratio:16/9;object-fit:cover;background:#050807}
  /* the two controls share a chip so they read as one family */
  .film__snd,.film__play{
    position:absolute;display:grid;place-items:center;cursor:pointer;z-index:2;
    border:1px solid rgba(255,255,255,.22);border-radius:999px;color:#fff;
    background:rgba(6,12,10,.58);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
    transition:background .35s var(--e-soft),border-color .35s,transform .4s var(--e-back),opacity .4s}
  .film__snd{right:12px;bottom:14px;width:42px;height:42px}
  .film__snd svg{width:17px;height:17px}
  .film__snd:hover,.film__play:hover{background:var(--mint);border-color:var(--mint);color:var(--on-mint);transform:scale(1.07)}
  .film__snd:focus-visible,.film__play:focus-visible{outline:2px solid var(--mint);outline-offset:3px}
  /* only one of the two speaker glyphs is ever shown */
  .film__sndi{display:none;line-height:0}
  .film__snd [data-film-i="off"]{display:block}
  .film__snd.is-on [data-film-i="off"]{display:none}
  .film__snd.is-on [data-film-i="on"]{display:block}
  .film__play{left:50%;top:50%;translate:-50% -50%;width:74px;height:74px;opacity:0;pointer-events:none}
  .film__play svg{width:26px;height:26px;margin-left:3px}
  .film.is-paused .film__play{opacity:1;pointer-events:auto}
  .film.is-paused .film__el{filter:saturate(.75) brightness(.72)}
  .film__el{transition:filter .5s var(--e-soft)}
  /* playhead — a mint hairline, the only chrome the player gets */
  .film__bar{position:absolute;left:0;right:0;bottom:0;height:2px;background:rgba(255,255,255,.14);z-index:2}
  .film__bar i{display:block;height:100%;width:0;background:var(--glow);
    box-shadow:0 0 12px rgba(52,245,173,.65)}
  .film__cap{margin-top:1rem;text-align:center;font-size:.82rem;color:rgba(255,255,255,.42)}
  @media(max-width:560px){
    .film__snd{right:9px;bottom:10px;width:38px;height:38px}
    .film__play{width:60px;height:60px}
    .film__cap{font-size:.76rem}
  }
}

/* ══════════ 12 · BREADCRUMB + PAGE FURNITURE ══════════ */
.crumb{display:flex;align-items:center;gap:.5rem;font-size:.8rem;color:rgba(255,255,255,.36);justify-content:center;margin-bottom:1.4rem}
.crumb a:hover{color:var(--mint)}
.crumb svg{width:11px;height:11px;opacity:.5}
.testbar{position:fixed;left:50%;bottom:16px;translate:-50% 0;z-index:80;display:inline-flex;align-items:center;gap:.5rem;
  height:32px;padding:0 .85rem;border-radius:999px;background:rgba(6,10,9,.82);border:1px solid rgba(52,245,173,.28);
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  font-size:.7rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--mint);pointer-events:none}
.testbar i{width:6px;height:6px;border-radius:50%;background:var(--mint);animation:bloom 2.4s ease-in-out infinite}

/* ══════════ 13 · ENTRANCES ══════════ */
.up{opacity:0;transform:translateY(30px)}
.up.is-in{opacity:1;transform:none;transition:opacity .95s var(--e-out),transform .95s var(--e-out)}
.up-1.is-in{transition-delay:.06s}.up-2.is-in{transition-delay:.12s}.up-3.is-in{transition-delay:.18s}
.up-4.is-in{transition-delay:.24s}.up-5.is-in{transition-delay:.3s}.up-6.is-in{transition-delay:.36s}

/* ══════════ 14 · REDUCED MOTION ══════════ */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}
  /* initTransitions() returns early under reduced motion, so whatever clip-path or
     filter the class sets as its STARTING state is where the scene stays forever.
     .goo/.swell/.defocus/.streak were added later and never got added here — three
     scenes on the home, about and product pages sat permanently clipped or blurred
     for anyone with "reduce motion" on. All ten are listed now; adding a transition
     without adding it here is the trap. */
  .wipe,.iris,.rise,.split,.band,.goo,.swell{clip-path:none!important}
  .defocus{filter:none!important;opacity:1!important}
  /* .bandfx is a full-section mint curtain made of <i> bars that initTransitions sweeps
     off with scaleX:0. Under reduced motion that scene never runs, so the curtain stays
     shut over the whole section. It was added after this block was written — the same
     trap as .goo/.swell/.defocus/.streak before it. */
  .bandfx i{transform:scaleX(0)!important}
  /* COLOUR, not just layout. kineticScene() returns early under reduced motion, so the
     data-bg cycling never paints .s-outro__bg and it stays VOID — but .kw--dark (#03251A)
     and .kw--paper (#04241A) are coloured for the mint/paper fields that never arrive.
     Measured 1.1:1 on live: "Automate." and "Dominate." were invisible on all 107 pages.
     Scoped to :not(.kw--fill) so the next colour variant cannot reintroduce this. */
  .s-outro .kw:not(.kw--fill),.s-kin .kw:not(.kw--fill){color:#fff!important}
  .s-outro .kw--mint,.s-kin .kw--mint{color:var(--mint)!important}
  .dolly,.streak{transform:none!important;filter:none!important;opacity:1!important}
  .rw .rwl>i{transform:none!important}
  .tt em{color:var(--emerald)!important}
  .msg,.pf,.pfa{opacity:1!important;transform:none!important}
  .up{opacity:1!important;transform:none!important}
  .s-kin,.s-outro{height:auto!important}
  .s-kin__vp,.s-outro__vp{position:relative;height:auto;padding:16vh 0}
  .kw{position:relative;opacity:1;translate:0 0;margin:.16em 0}
  .s-outro__cta{position:relative;bottom:auto;opacity:1;margin-top:2rem}
  .b3d,.chips{display:none}
}

/* ══════════════════════════════════════════════════════════════════════════════
   15 · MOBILE
   Duval, 2026-07-29: "make the entire website mobile friendly… every page… even if
   you have to ditch paragraphs below current headings of sections, I want everything
   minimal… everything should look nice and fit on the screen."

   THIS BLOCK IS DELIBERATELY UNLAYERED AND LAST. Several desktop rules are written
   with element-qualified selectors (`footer.foot .foot__grid`, 0-2-1) that a plain
   `.foot__grid` media query loses to no matter what breakpoint it sits at — which is
   exactly why the footer never collapsed and its columns rendered 38px wide. Being
   unlayered puts these rules in the top cascade layer; matching the specificity where
   it matters does the rest. Do not move this block into @layer th-scene.

   Nothing here is !important. If a rule stops winning, the fix is specificity.
   ══════════════════════════════════════════════════════════════════════════════ */

/* ── 15.1 · tablet / large phone ── */
@media (max-width:900px){
  /* the desktop rhythm is built for a 900px-tall viewport with a mouse. On a phone the
     same padding reads as three empty screens between every idea. */
  .sec{padding:clamp(76px,10vh,120px) var(--pad)}
  .sec__head{flex-direction:column;align-items:flex-start;gap:1.4rem;margin-bottom:clamp(1.8rem,4.4vw,2.6rem)}
  .sec__head--c{align-items:center}
  .s-num{padding:clamp(76px,11vh,130px) var(--pad)}
  .s-cmd{padding:clamp(80px,11vh,130px) var(--pad) clamp(84px,12vh,140px)}
  /* min-height on a phone is what produces the empty half-screens */
  .s-field__panel{min-height:auto;padding:clamp(84px,13vh,130px) var(--pad)}
  .s-paper--full{min-height:auto;padding-block:clamp(84px,13vh,130px)}
  .s-b3d{min-height:auto;padding-block:clamp(80px,12vh,120px)}
  .s-final{min-height:auto;padding-block:clamp(90px,14vh,140px)}
  .s-e404{min-height:auto;padding-block:clamp(90px,14vh,140px)}
  .s-hero{min-height:auto;padding:clamp(122px,17vh,170px) var(--pad) clamp(86px,12vh,120px)}
  .s-hero--sub{padding:clamp(126px,18vh,180px) var(--pad) clamp(64px,9vh,100px)}

  /* On desktop the nav links sit inside a frosted island, which is its own backdrop.
     On mobile the island is hidden and only the wordmark and the burger remain — so
     body copy scrolled straight through them and "DoubleDown AI" landed on top of a
     card heading. A scrim behind the bar, fading out downward so it never reads as a
     solid header bar. z-index:-1 keeps it behind the wordmark but inside .nav's own
     stacking context, and pointer-events stays none so it cannot eat a tap. */
  .nav::before{
    content:"";position:absolute;inset:-1px 0 auto;height:calc(100% + 14px);z-index:-1;
    pointer-events:none;
    background:linear-gradient(180deg,rgba(0,0,0,.9) 0%,rgba(0,0,0,.62) 52%,transparent 100%);
    -webkit-backdrop-filter:blur(9px);backdrop-filter:blur(9px);
    -webkit-mask-image:linear-gradient(180deg,#000 58%,transparent);
    mask-image:linear-gradient(180deg,#000 58%,transparent);
  }
  .nav.is-light::before{
    background:linear-gradient(180deg,rgba(242,247,244,.92) 0%,rgba(242,247,244,.6) 52%,transparent 100%);
  }
}

/* ── 15.2 · phone ── */
@media (max-width:640px){
  :root{--rad:22px}

  /* TYPE — the desktop floors (2.2rem/2.9rem) leave a 390px screen with a two-word
     line touching both edges. These floors are set from the measured 360px case. */
  h1,h2,h3,h4{overflow-wrap:break-word}
  .h-hero{font-size:clamp(2rem,10.4vw,3.15rem);letter-spacing:-.038em;line-height:.95}
  .h-giant{font-size:clamp(2.3rem,12.6vw,3.9rem);letter-spacing:-.045em;line-height:.93}
  .h-sec{font-size:clamp(1.85rem,8.4vw,2.85rem);letter-spacing:-.038em;line-height:.96}
  .h-mid{font-size:clamp(1.45rem,6.2vw,2.05rem);letter-spacing:-.035em;line-height:1}
  .h-sm{font-size:1.06rem;letter-spacing:-.03em}
  .kinetic{letter-spacing:-.045em}
  .lede{font-size:.98rem;line-height:1.58;max-width:none}

  /* SMALL TYPE FLOOR — nothing on a phone may render under 12px. Every one of these
     was measured at 9.9–11.2px in the audit. Letter-spacing comes down so the same
     label still fits the same box at the larger size. */
  .eyebrow{font-size:.75rem;letter-spacing:.19em;margin-bottom:.85rem}
  .pan__t,.pipe__step,.pick__m,.tier__tag,.soonpill,.rnode__w,.osat,
  .metapill,.film__cap,.crumb,.foot__c,.foot__legal a,footer.foot h4,
  .coll__stat span,.samap__pins .sapin b,.s-doc__meta,.artmeta__tag,.artmeta__d,
  .blogcard__k,.relrow__i,.bchip span,.bcard__meta b,.pfield>span,.pcard__tag,
  .card__pr span,.phone__bar span,.atag,.testbar{font-size:.76rem}
  .pick__m,.pipe__step,.pan__t{letter-spacing:.1em}
  .rnode__w{letter-spacing:.09em;height:26px}
  .scrollcue{font-size:.68rem;letter-spacing:.22em}
  .card__d,.step__d{font-size:.93rem;line-height:1.55}

  /* TAP TARGETS — 29px and 17px links measured in the footer and breadcrumb. The
     negative margin keeps the visual rhythm while the hit box grows to ~42px. */
  .foot__col a{padding:.62rem 0}
  .foot__legal{gap:1rem}
  .foot__legal a{display:inline-block;padding:.5rem 0}
  .crumb{gap:.55rem}
  .crumb a{display:inline-block;padding:.6rem .2rem;margin:-.6rem -.2rem}
  .btn{height:52px}
  .btn--sm{height:44px}
  .atag{height:40px;padding:0 .95rem}          /* 41 city pages, 32px was untappable */
  .atags{gap:.5rem}
  /* the /cities/ hub page uses a different template — bare <a> in a card and a long
     province link list, both measured 20px tall */
  .svc-card a,.city-links a{display:inline-block;min-height:40px;line-height:40px}
  .city-links a{margin-right:.6rem}

  /* the orbit satellites are pinned by percentage from the centre, so at 335px the
     outer ring pushed its pills 24px past the box. Pulling the ring in is the fix —
     shrinking the pills only made them unreadable. */
  .orbit{width:min(720px,74vw)}

  /* ONE COLUMN, EVERYWHERE. Written with the same element qualifier the desktop rule
     uses so it actually wins — see the header note. */
  /* Two columns, not one. A single column of four link lists with 42px tap targets
     measured 1,285px of footer on a 390px screen — longer than the hero. The brand
     block spans both so the wordmark and lede keep their line length. */
  footer.foot .foot__grid{grid-template-columns:1fr 1fr;gap:1.7rem 1.2rem}
  footer.foot .foot__grid>:first-child{grid-column:1/-1}
  .foot__lede{max-width:none;font-size:.9rem}
  .foot__mark{font-size:clamp(2rem,13.4vw,4.4rem)}
  .foot__in{gap:1rem;padding-block:18px}

  /* the TEST MODE badge wrapped to two lines and sat over the wizard's Continue button */
  .testbar{height:30px;letter-spacing:.05em;bottom:10px;padding:0 .7rem;white-space:nowrap}
  .cards,.cards--2,.steps,.bgrid,.pick,.pgrid,.pcards,.areas,.tiers,.founders{grid-template-columns:1fr}
  .stats,.citystats{grid-template-columns:repeat(2,minmax(0,1fr))}

  /* THE PROMPT PILL — the one component that was visibly broken: `white-space:nowrap`
     truncated the typed line mid-word ("answer every lead in one s"). On a phone it
     wraps and the bar grows instead. */
  .prompt__bar{height:auto;min-height:58px;padding:.5rem .5rem;gap:.6rem;align-items:center}
  .prompt__text{white-space:normal;font-size:.94rem;line-height:1.3;padding-block:.15rem}
  .prompt__badge{width:34px;height:34px}
  .prompt__badge svg{width:15px;height:15px}
  .prompt__go{width:38px;height:38px}
  .prompt__bloom{inset:-26px -18px}
  .stadium{padding:clamp(1.9rem,7vw,2.6rem) clamp(1.1rem,4.4vw,1.6rem) clamp(2.1rem,7.4vw,2.8rem);
    border-radius:clamp(34px,9vw,46px)}

  /* MINIMAL — Duval asked for less, not smaller. These are the pieces that carry no
     information on a phone: they are atmosphere sized for a 1440px canvas. */
  .chips{display:none}                       /* frosted corner chips land on the type */
  .dust{opacity:.28}
  .scrollcue{display:none}                   /* a phone user already knows to scroll */
  .s-hero__meta{margin-top:1.15rem;gap:.4rem}
  .metapill{height:32px;padding:0 .8rem}
  .card__ix{opacity:.045}
  .film{max-width:100%}

  /* the wave stage is a 1400px SVG on a 350px screen — clip it rather than let it
     define the scroll width */
  .wave__stage{overflow:hidden;height:clamp(200px,52vw,280px)}

  /* The outro is three words — but 118svh against a 100svh sticky viewport leaves an
     18svh TRACK, i.e. ~153px of scroll for three words and two background cross-fades.
     A normal thumb flick is 800-1500px, so the whole finale fired and finished inside
     one flick and what the eye actually saw was a black screen. Scroll distance is the
     one thing that costs nothing here. 200svh = ~66svh per word, which reads. */
  .s-outro{height:200svh}

  /* PROSE — the 40 blog posts, 41 city pages and the five legal documents.
     A four-column table squeezed into 358px is unreadable; it keeps real column
     widths and scrolls inside .tblwrap instead. */
  .tblwrap table{min-width:540px}
  .prose{font-size:1rem;line-height:1.68}
  .prose h2{font-size:1.55rem}
  .prose h3{font-size:1.22rem}
  .prose pre{overflow-x:auto}
  .prose table,.s-doc .prose table{font-size:.88rem}
  .prose th,.prose td,.s-doc .prose th,.s-doc .prose td{padding:.6rem .7rem}
}

/* ── 15.3 · small phone (360px and under) ── */
@media (max-width:400px){
  :root{--pad:16px}
  .h-sec{font-size:clamp(1.7rem,8.2vw,2.2rem)}
  .h-hero{font-size:clamp(1.9rem,10vw,2.6rem)}
  .h-giant{font-size:clamp(2.1rem,12vw,3rem)}
  .stats,.citystats{grid-template-columns:1fr}
  .btn{height:50px;padding-left:1.1rem}
}

/* ══════════════════════════════════════════════════════════════════════════════
   16 · MOBILE — LESS COPY
   Duval, 2026-07-29: "on mobile we can ditch some of the paragraphs below headings
   that people don't really read… this is critical."

   THE RULE, and it is a rule, not a taste: a supporting paragraph is hidden ONLY
   where the section has other content underneath it. A scene whose entire body is
   a heading + a paragraph + a button keeps its paragraph — hiding it there leaves a
   bare headline and reads as a bug, not as restraint.

   Hidden  → section heads that are followed by cards, steps, a grid or a picker.
   Kept    → the mint field, the paper scenes, the final CTA, the hero, all prose,
             every form label, hint and legal line.

   `display:none` and not `visibility` on purpose: these are decorative on a phone,
   and the space they take is the actual problem.
   ══════════════════════════════════════════════════════════════════════════════ */
@media (max-width:640px){
  /* a section head whose body is a card grid, a rail or a picker */
  .sec__head .lede,
  .s-ribbon .lede,
  .s-cmd .lede,
  .s-pick .lede,
  .s-blog .lede,
  .s-orbit .lede,
  .s-wave .lede,
  .s-ledger .lede,
  .s-cover .lede,
  .s-founders .lede{display:none}

  /* the small line under a giant numeral — the numeral is the whole message */
  .s-num__sub{display:none}

  /* the dock scene is a heading plus a strip of logos; the paragraph adds nothing */
  .s-dock__in>p{display:none}

  /* the heading no longer needs the gap it was leaving for the paragraph */
  .sec__head{margin-bottom:clamp(1.5rem,4vw,2.1rem)}
}

/* ══════════════════════════════════════════════════════════════════════════════
   17 · MESH GUARDS — unlayered and last, same reasoning as sections 15 and 16.
   The drifting orbs are a desktop luxury. On a phone four 40vw+ blurred layers
   repainting forever is a battery and jank cost the hero does not earn, so the
   mesh holds still and the fourth orb is dropped entirely.
   ══════════════════════════════════════════════════════════════════════════ */
@media(max-width:860px){
  .blob--d{display:none}
  .blob--a,.blob--b,.blob--c,.blob--d,.blob--shade,.blob--paper,
  .s-paper__fx .blob--paper:nth-child(2){animation:none}
}

/* ══════════════════════════════════════════════════════════════════════════════
   17b · THE PHONE GPU BUDGET — added 2026-07-31 after Duval's Android report
   ("when you scroll down its just black").

   Measured on the LIVE homepage at 412px / DPR 2.6: ~224 MB of blurred, composited
   layers across 34 elements, and 75 elements resolving will-change != auto. Android
   Chrome does not degrade gracefully when it runs out of layer memory — it EVICTS
   the layer and paints it BLACK. That is the reported symptom, exactly.

   Two compounding mistakes, both fixed here:
     1. blur radii are fixed px while the elements are sized in vw, so at 412px a
        .blob--a is 214px of content inside a 694px layer — 92% of the memory is blur
        padding rendering as a featureless smudge nobody can see.
     2. will-change:transform stayed on all 7 blobs, .spot and .wave__svg even though
        the block above already froze their animation at 860px — so they were pinned
        to their own GPU layer forever, for nothing.

   Everything here is a phone-only downgrade. Nothing above 860px changes.
   ══════════════════════════════════════════════════════════════════════════ */
@media(max-width:860px){
  /* 1 · stop promoting layers. will-change is a HINT with a cost: every element carrying
     it gets its own composited layer for the whole life of the page, not just while it
     animates. 75 of them on one phone screen is the opposite of what it is for. The
     .rwl>i case is the worst — 36 word-spans promoted forever for a one-shot reveal that
     GSAP and the CSS transition both promote on their own for the duration anyway. */
  .blob,.spot,.wave__svg,.pan,.badges .badge,.wcol,.marq__row,
  .rw .rwl>i,.streak .rwl>i,.kw,.msg,.chip,.gl,.bandfx i,
  .wipe,.iris,.rise,.split,.band,.goo,.swell,.dolly,.defocus{will-change:auto}

  /* 2 · scale the blur with the element instead of holding a desktop radius.
     Visually identical at this size — these are 5-40% opacity glows. */
  .blob{filter:blur(clamp(22px,7vw,80px))}
  .blob--shade{filter:blur(clamp(26px,8vw,92px))}
  .blob--paper{filter:blur(clamp(24px,7.5vw,78px))}
  .spot{filter:blur(clamp(22px,7vw,60px))}
  .cmd__bloom{filter:blur(clamp(26px,8vw,70px))}
  .wave__svg--back{filter:blur(clamp(10px,3vw,26px))}

  /* 3 · the single most expensive decision on the page. A position:fixed, full-viewport
     mix-blend-mode:overlay layer forces the ENTIRE scroll content into a blend group on
     Android Chrome. At 5% opacity on a 412px screen the grain is not perceptible — it is
     paying full compositing price for something invisible. */
  .grain{display:none}

  /* 4 · decorative backdrop-filters. Each one re-reads the buffer behind it every frame.
     The collage panels and the card sit on solid dark art; a flat translucent fill is
     indistinguishable at this size. The nav island keeps its blur — it sits over live
     scrolling content and the effect is load-bearing there. */
  .gl,.coll__card{backdrop-filter:none;-webkit-backdrop-filter:none;background:rgba(10,16,14,.82)}
  .stadium,.dock{backdrop-filter:none;-webkit-backdrop-filter:none}
  .dock{background:rgba(10,16,14,.82)}

  /* 5 · .defocus is the AE "rack focus" beat — a FULL SECTION painted through a 22px
     blur that scrubs with the scroll, plus will-change:filter, which is the single most
     expensive hint there is (it forces a filter-capable layer for the page's whole life).
     10 MB for a beat nobody can perceive on a 412px screen. The scene still arrives; it
     just arrives sharp. th.js also has to skip the tween — see initTransitions. */
  .defocus{filter:none;opacity:1}

  /* 6 · .wave__svg--back is a 400%-wide BLURRED DUPLICATE of the wave, sitting behind the
     sharp one at 42% opacity. On a phone it is 11.6 MB of imperceptible smudge. */
  .wave__svg--back{display:none}

  /* 7 · the two remaining decorative blooms, sized down rather than removed — they are
     the mint glow that makes the hero and the command centre read as lit. */
  .cmd__bloom{width:150vw;height:80vw;filter:blur(clamp(20px,6vw,70px))}
  .prompt__bloom{filter:blur(clamp(14px,4vw,28px))}
}

/* 5 · CLOSED overlays must not hold a full-viewport backdrop-filter.
   .menu and .ddw close with opacity:0 + visibility:hidden — NOT display:none — so their
   blur stayed in the layer tree on every page, on every device, permanently. That is
   ~377k css px² of live backdrop-filter each, for two things nobody is looking at.
   Gating the blur on the open state costs nothing: it is applied in the same frame the
   overlay becomes visible, and both already animate opacity over 400-600ms. */
.menu:not(.is-open),.ddw:not(.is-open){backdrop-filter:none;-webkit-backdrop-filter:none}
/* trap 20: a transition or animation added without a reduced-motion entry keeps
   running for everyone who asked it not to. These are (0,1,0), the same as the
   rules above, and later in the file — so they win. */
@media(prefers-reduced-motion:reduce){
  .blob--a,.blob--b,.blob--c,.blob--d,.blob--shade,.blob--paper,
  .s-paper__fx .blob--paper:nth-child(2){animation:none}
}

/* ══════════════════════════════════════════════════════════════════════════════
   18 · MOBILE, ROUND 10 — the footer and the pill flow
   Duval, 2026-07-29: "the footer can also be more mobile friendly" and "this 'what
   you are actually agreeing to' section on the pricing page — a lot of the pages
   have it — I need it more mobile friendly."
   Unlayered and last, same reasoning as 15, 16 and 17.
   ══════════════════════════════════════════════════════════════════════════ */
@media(max-width:700px){

  /* ── THE PILL FLOW ────────────────────────────────────────────────────────
     Measured at 390px: 680px tall — a screen and a half for four short facts —
     and the four pills were 195/213/173/190px wide, centred, so they zig-zagged
     down the page and read as a mistake rather than a list. Equal width fixes
     the rag; the rest is padding that a phone does not need. */
  .s-pillflow{padding-block:clamp(48px,9vh,72px)}
  .pflow{gap:.45rem;width:100%;max-width:420px;margin-inline:auto}
  .pf{width:100%;justify-content:flex-start;height:52px;padding:0 1.15rem;font-size:.95rem}
  /* the arrow still says "then", it just stops costing 30px of dead height each */
  .pfa{width:100%;height:16px}
  .pfa svg{width:15px;height:15px}
  /* "What you are actually agreeing / to." — an orphaned "to." on its own line.
     balance splits the heading evenly instead of filling line 1 first. */
  .s-pillflow h2{text-wrap:balance;margin-bottom:clamp(1.4rem,5vw,2rem)!important}

  /* ── THE FOOTER ───────────────────────────────────────────────────────────
     Measured at 390px: 949px — 1.12 screens of footer. It carries 17 real
     navigation links and those stay; what goes is the supporting paragraph and
     the desktop breathing room. */
  footer.foot{padding-top:clamp(38px,6vh,56px)}
  /* the tagline is a supporting paragraph with a whole footer underneath it —
     exactly the case section 16 already hides everywhere else */
  .foot__lede{display:none}
  footer.foot h4{margin-bottom:.45rem}
  footer.foot .foot__grid{gap:1.5rem 1.1rem}
  .foot__col a{padding:.5rem 0;font-size:.9rem}     /* still a 40px tap target */
  /* the meta row stacked into ragged lines with "Terms" orphaned on its own */
  .foot__in{flex-direction:column;align-items:flex-start;gap:.5rem;
    margin-top:1.4rem;padding-block:14px}
  /* email · phone · Privacy · Terms wrapped 3 + 1 at 390px and 360px. A 2×2 grid
     is even at every width instead of depending on how long the phone number is. */
  .foot__legal{display:grid;grid-template-columns:1fr 1fr;gap:.1rem 1rem;width:100%}
  .foot__mark{margin-top:.4rem}
  /* NOTE: the wordmark is NOT clipped — measured at 390/360/414 it is 331/306/352px
     of ink inside 358/328/373px of content box. What covers its last letter at full
     scroll is the fixed chat launcher, which sits over the bottom-right of every page
     on every breakpoint. Padding the footer to clear it would add back most of the
     height this section just removed, so it is left alone deliberately. */

  /* ── THE SOUTH AFRICA MAP ─────────────────────────────────────────────────
     Duval: "the South Africa can be made better there." At 390px the map is only
     329px wide but the nine labels stay at a fixed size, so they collided into
     each other and off the right edge — "Mpumalanga" sat on top of the Gauteng
     pin, "KwaZulu-Natal" ran off the page, "North West" and "Gauteng" overlapped.
     No amount of nudging fixes nine labels inside 329px.

     So on a phone the labels come OFF the map and the SAME elements reflow as a
     two-column chip list underneath it — identical DOM, no duplicated content,
     zero collisions, and the silhouette is left clean. */
  .cover__map{max-width:100%;margin-top:clamp(1.6rem,5vw,2.4rem)}
  .samap__pins{position:static;display:grid;grid-template-columns:1fr 1fr;
    gap:.7rem .9rem;margin-top:1.5rem;pointer-events:auto}
  /* the pin stops being a zero-size anchor and becomes a chip: dot beside the label */
  .sapin{position:static;translate:none;opacity:1;transform:none;
    width:auto;height:auto;line-height:normal;
    display:grid;grid-template-columns:auto 1fr;column-gap:.55rem;
    align-items:center;text-align:left}
  .sapin i{position:static;translate:none;grid-column:1}
  .sapin__t,.sapin[data-p="l"] .sapin__t,.sapin[data-p="r"] .sapin__t{
    position:static;translate:none;left:auto;top:auto;text-align:left;grid-column:2}
  .sapin b{margin-top:0;font-size:.82rem;line-height:1.15}
  /* the city line is hidden on the MAP below 560px because it has nowhere to go;
     in a chip it is the useful half of the label, so it comes back */
  /* .62rem = 9.9px, under the 12px mobile floor section 15 set — thmobile caught it */
  .sapin small{display:block;margin-top:.05rem;font-size:.76rem;letter-spacing:.02em;line-height:1.25}
  .sapin--hq b{font-size:.82rem}
  .sapin--hq i{width:13px;height:13px}
}

/* ══════════════════════════════════════════════════════════════════════════════
   19 · THE NEW MARK IN CONTEXT (2026-07-29)
   The mark replaced a square disc, so the few places that assumed a square box
   need the real 1.6615:1 ratio. Unlayered and last, like 15–18.
   ══════════════════════════════════════════════════════════════════════════ */
/* the hero prompt pill — the tiny star is now the mark (Duval's ask). The pill is
   white, so the D's stay mint and the arrow goes ink. */
.prompt__badge{background:none!important;width:auto!important;height:26px;border-radius:0!important;
  color:#04241A}
.prompt__mark{display:block;height:26px;width:auto;aspect-ratio:1000/602}
.prompt__mark svg{width:100%;height:100%;display:block}
@media(max-width:700px){.prompt__badge,.prompt__mark{height:21px}}

/* the footer lockup — mark over wordmark, the second file Duval supplied */
.foot__brand{flex-direction:column;align-items:flex-start;gap:.7rem}
footer.foot .foot__brand .brand__mark{height:54px;width:auto}
.foot__brand .brand__name{font-size:1.45rem}
@media(max-width:700px){
  footer.foot .foot__brand .brand__mark{height:42px}
  .foot__brand .brand__name{font-size:1.2rem}
}

/* ── the honeypot + the brief's Turnstile (go-live 2026-07-30) ──────────────
   Off-screen, not display:none — a hidden-by-display field is the first thing a
   competent bot skips, and the whole point is that it gets filled in. */
.pipe__hp{position:absolute;left:-9999px;top:auto;width:1px;height:1px;overflow:hidden}
.pipe__ts{margin:1.1rem 0 .2rem;min-height:65px}
.pipe__ts[hidden]{display:none}
.dsar__err{margin-top:.9rem;font-size:.92rem;line-height:1.5;color:#ffb4b4;
  background:rgba(239,68,68,.09);border:1px solid rgba(239,68,68,.28);
  border-radius:14px;padding:.75rem .9rem}
.dsar__err[hidden]{display:none}
