:root{
  --soft-grey:#F8F8F4; --warm-grey:#F1F1E7; --stone:#4B4947; --dark:#1C1C1C;
  /* The hero clips play back through the GPU's limited-range video path,
     which lifts their black to ~rgb(16,16,16) — while the pages/art sit on
     true near-zero blacks, so scrolling out of the hero visibly DROPPED the
     floor. Everything after the hero now shares this lifted floor (lighten
     overlay on the page stack + FAQ canvas bg). Tune the match by eye here;
     the FAQ canvas needs the same value in its data-anm-bg attribute. */
  --hero-black:#101010;
  --soft-orange:#FBAA85; --orange:#FE7233; --soft-purple:#C9CDF7; --soft-green:#95CCA2;
  --ink:var(--soft-grey);
  --rail:1440px;          /* shared by the layout and the mascot placement */
  --neon:#fd8bad;         /* sampled from the visor ring on frame 64 */
}
*{margin:0;padding:0;box-sizing:border-box}
/* deliberately no overflow-x:hidden on the root: it is a known way to break
   position:fixed in some engines, and the hero is entirely pinned */
html,body{min-height:100%;background:var(--dark);color:var(--ink);
  font-family:'Clash Grotesk',ui-sans-serif,system-ui,sans-serif;
  -webkit-font-smoothing:antialiased}
/* Scroll snap is permanently OFF. Every use of it here broke something real:
   a snap point on the card screen swallowed the last third of the hero push,
   and one on the FAQ sat above the page's end on short viewports and bounced
   the bottom back up. Arrivals are geometric instead — the runway's height
   equals the card screen's offset, so the strip lands flush unassisted. */
html{scroll-snap-type:none}
/* The hero is pinned, so this spacer is the only thing that scrolls and its
   height is what sets the sequence length. Height comes from JS (see TRAVEL) so
   the spacer and the progress maths cannot drift apart. */
.runway{height:0;pointer-events:none}
/* The canvas draws the mascot on BLACK and the browser does the lighten against
   the page background, so --dark is painted in exactly one place. Doing the
   lighten inside the shader meant the canvas painted its own copy of the
   background, and the two only matched while their colour pipelines agreed —
   which is how the left and right halves ended up different blacks. */
#stage{position:fixed;inset:0;width:100vw;height:100vh;display:block;z-index:0;
  mix-blend-mode:lighten}
.scrim{position:fixed;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(to right,rgba(28,28,28,.86) 0%,rgba(28,28,28,.6) 38%,rgba(28,28,28,.06) 68%,rgba(28,28,28,0) 100%)}
/* nav, copy and stats all ride the same centred rails — without this the copy
   stays pinned to the left edge while the figure drifts right on wide screens */
.shell{position:fixed;inset:0;z-index:2;display:flex;flex-direction:column;
  width:100%;max-width:var(--rail);margin:0 auto}

nav{display:flex;align-items:center;justify-content:space-between;padding:20px 24px}
/* full lockup (mark + outlined wordmark), 909x229 — height-driven, width auto */
.brand{display:flex;align-items:center}
.brand svg{height:30px;width:auto;color:var(--soft-grey)}
.navlinks{display:none;gap:34px}
.navlinks a{color:rgba(248,248,244,.75);font-size:13px;letter-spacing:.02em;text-decoration:none;transition:color .2s}
.navlinks a:hover{color:#fff}
.cta-ghost{display:none;align-items:center;gap:8px;padding:11px 22px;border:1px solid rgba(248,248,244,.3);
  color:var(--ink);text-decoration:none;font-size:12px;letter-spacing:.02em;transition:background .2s,border-color .2s}
.cta-ghost:hover{background:rgba(248,248,244,.1);border-color:rgba(248,248,244,.6)}
.burger{display:flex;flex-direction:column;gap:6px;background:none;border:0;cursor:pointer;padding:6px}
.burger i{display:block;height:2px;background:var(--ink)}
.burger i:nth-child(1),.burger i:nth-child(2){width:24px}.burger i:nth-child(3){width:16px}

main{flex:1;display:flex;flex-direction:column;justify-content:center;padding:0 24px 28px;width:100%;min-height:0}
/* the copy tracks the container: 50% of the rail, floored so it never gets
   narrower than it was, capped so the measure stays readable */
.copy{width:100%;max-width:clamp(34rem,50vw,44rem)}
/* brand: Heading 1 is Clash Grotesk Bold at 90% leading, sentence case */
h1{line-height:.9;letter-spacing:-.025em;font-weight:700;font-size:clamp(2.6rem,8vw,7rem)}
h1 span{display:block}
h1 .accent{color:var(--orange)}
.sub{margin-top:22px;max-width:36rem;color:rgba(248,248,244,.7);font-size:16px;font-weight:400;line-height:1.45}
.sub b{color:#fff;font-weight:500}
.ctarow{margin-top:32px;display:flex;flex-wrap:wrap;align-items:center;gap:20px}
.btn{display:inline-flex;align-items:center;gap:10px;background:var(--orange);color:var(--dark);
  padding:14px 26px;font-size:13px;font-weight:600;letter-spacing:.01em;text-decoration:none;transition:background .2s}
.btn:hover{background:var(--soft-orange)}
.btn svg{width:15px;height:15px;transition:transform .25s}
.btn:hover svg{transform:translate(2px,-2px)}
.btn-quiet{display:inline-flex;align-items:center;gap:9px;color:rgba(248,248,244,.75);
  padding:14px 0;font-size:13px;font-weight:400;text-decoration:none;
  border-bottom:1px solid rgba(248,248,244,.28);transition:color .2s,border-color .2s}
.btn-quiet:hover{color:#fff;border-color:rgba(248,248,244,.7)}
.btn-quiet svg{width:14px;height:14px;transition:transform .25s}
.btn-quiet:hover svg{transform:translate(2px,-2px)}
/* the only affordance that the hero goes anywhere; fades out as soon as the
   scroll is under way, so it never competes with the turn itself */
/* centred with flex, not translateX — the .fu entrance animates transform, and a
   translateY keyframe would wipe out a centring translateX */
.scrollcue{position:fixed;left:0;right:0;bottom:26px;z-index:3;
  display:flex;flex-direction:column;align-items:center;gap:9px;pointer-events:none;
  color:rgba(248,248,244,.5);font-size:13px;font-weight:400;letter-spacing:.01em;
  transition:opacity .25s linear}
.scrollcue i{display:block;width:1px;height:34px;background:linear-gradient(
  to bottom,rgba(248,248,244,.45),rgba(248,248,244,0));overflow:hidden;position:relative}
.scrollcue i::after{content:'';position:absolute;left:0;top:-34px;width:1px;height:34px;
  background:linear-gradient(to bottom,rgba(254,114,51,0),var(--orange));
  animation:cue 2.1s cubic-bezier(.4,0,.2,1) infinite}
@keyframes cue{0%{transform:translateY(0)}60%,100%{transform:translateY(68px)}}
@media(prefers-reduced-motion:reduce){.scrollcue{display:none}}

/* the page on the other side of the glass — a placeholder second section on
   the brand's light wash, faded in by the last stretch of the push. Sits above
   the shell/scrim but below the HUD, so tuning stays reachable. */
/* Full bleed: the light runs edge to edge so no screen space is lost to a
   margin, and the neon sits ON the viewport edge. Nothing is visible beyond it
   because there is no beyond — which means the bloom has to go INWARD. Square,
   not rounded: at inset 0 a radius would cut corners out of the light and show
   the layer underneath, which is exactly the black-past-the-neon we are killing.
   Ring colour sampled off frame 64 (#fd8bad); the white-hot core #feeff9 is
   dropped because a near-white line cannot read on a light field. */
/* Once through the glass this stays for the rest of the site: the light screen
   and its neon edge are the surface every following section sits on, so the
   whole page reads as being INSIDE the visor. Fixed, so the frame stays welded
   to the viewport while the real content scrolls over it. */
/* Was var(--soft-grey) — the "light screen" concept died when the FAQ went
   dark (2026-08-12): the cream backdrop's only remaining sighting was the
   overscroll rubber-band below the footer flashing white. Site black now. */
.next{position:fixed;inset:0;z-index:5;background:var(--hero-black);opacity:0;pointer-events:none}
/* The bezel rides ABOVE the scrolling content (the light screen sits below it),
   so the neon stays welded to the viewport edge and frames whatever is passing
   through — including the dark strip — instead of being covered by it. */
.bezel{position:fixed;inset:0;z-index:7;opacity:0;pointer-events:none;
  /* Full intensity at the edge, but a MUCH shorter reach. The wide layer was
     150px blur + 34px spread (~184px of travel), which washed pink across the
     whole page rather than reading as an edge glow. Cutting reach to ~70px
     keeps the neon bright where the light actually is and leaves the page
     clean; dropping alpha instead only made it dimmer AND still tinted. */
  border:2px solid var(--neon);
  box-shadow:
    inset 0 0 10px 1px rgba(253,139,173,.92),
    inset 0 0 26px 4px rgba(253,139,173,.46),
    inset 0 0 60px 10px rgba(253,139,173,.16)}

/* ---- the scrolling site, from step 2 on -------------------------------- */
/* Normal flow, above the fixed light screen and below the bezel. The runway is
   exactly TRAVEL viewports tall, so this block's top lands at the top of the
   viewport at the very frame the push completes: the cards ARE the arrival,
   not something you scroll to find. Hidden until then, or it would show
   through the lower half of the screen during the hero. */
/* .pages is a <main>, so it was silently inheriting the HERO's main rule
   (flex centring, 64px side gutters, 34px bottom padding) — which is why the
   strip could never reach the viewport edge no matter what its own width said.
   Reset it: this main is a plain scrolling block, not the hero's flex column. */
.pages{position:relative;z-index:6;color:var(--dark);opacity:0;
  display:block;flex:none;padding:0;min-height:0}
.section{max-width:var(--rail);margin:0 auto;padding:clamp(80px,12vh,150px) 24px}
@media(min-width:768px){.section{padding-left:44px;padding-right:44px}}
@media(min-width:1024px){.section{padding-left:64px;padding-right:64px}}

/* .s-title / .blocks / .reach lived on the intro section that used to precede
   the cards; removed with it so the dead rules do not outlive the markup. */

/* ---- Expanding strip (step 2 cards) ------------------------------------
   A viewport-filling row of tall panels, edge to edge. Hovering one grows it
   while every neighbour compresses on a gaussian falloff, so the row reads as
   one organism. Title + label rise from a mask once a panel passes an
   expansion threshold; collapsed panels show a vertical sliver word.
   Retheme of the supplied component: Clash Grotesk, brand palette, and the
   image layer is a COLOUR PLACEHOLDER until the art arrives. */
/* ---- Idea pages (replaced the card strip; archive in
   hero-glitch-cards-version.html) ----------------------------------------
   One full-viewport page per idea: huge background visual, subject on one
   side, text on the other. Page 1 is the arrival — pinned through push +
   dwell. Text is light over near-black art (page 1's text zone measured
   19:1 for the title with no scrim). The raster carries over from the
   cards: 2px trough + 1px emission line, the site's texture. */
.idea{position:relative;height:100vh;height:100dvh;overflow:hidden;
  display:flex;align-items:center;background:#050505}
/* THE "APPEAR" STACK: pages don't scroll past — they hold the frame while the
   scroll position crossfades them (out through near-black, next page appears
   with a 3.5% settle-scale). .ideastack keeps the exact 400vh of document the
   four in-flow pages occupied, so the runway math and the FAQ arrival are
   untouched; the sticky hold owns the viewport while the stack has height
   left. Driven per-frame from scroll in the stack script — a pure function
   of scroll like the bezel and the FAQ cover. No wheel interception. */
.ideastack{position:relative;height:400vh}
.ideastack_hold{position:sticky;top:0;height:100vh;height:100dvh;
  overflow:hidden;background:#050505}
/* black-floor match with the hero (see --hero-black): lighten = per-channel
   max, so it raises only pixels darker than the floor — art shadows, the
   page bg, the video's true black — and passes text/orange through intact */
.ideastack_hold::after{content:'';position:absolute;inset:0;z-index:10;
  background:var(--hero-black);mix-blend-mode:lighten;pointer-events:none}

/* ---- ROADMAP overlay ---------------------------------------------------- */
/* PrecisionSection skeleton (chip -> falling line -> items, pillars rising
   left to right), reskinned: lifted-black ground, dark chips, orange
   pinwheel + numerals, one-hue orange gradient line. NOT part of the scroll
   journey (user, 2026-08-12): it opens full-screen from the nav's "Roadmap"
   link and closes on Esc / the X — reference material, not a narrative beat. */
/* SPLIT COMPOSITION (user, 2026-08-13): the text never fights the vista.
   Top ~54vh: solid black band with the title and the whole staircase.
   Bottom ~46vh: the vista as a panorama strip (duo + clouds featured).
   The gradient lines fall out of the band INTO the scene, and a gradient
   horizon softens the seam. */
.roadmap{position:fixed;inset:0;z-index:60;background:var(--hero-black);
  overflow:hidden;display:none}
.roadmap.open{display:flex;flex-direction:column}
/* posY 73%: the duo's feet sit at 77.9% of the source — this window ends at
   ~86%, giving them ground to stand on (58% cut them at the ankles) */
.rd_vista{position:fixed;left:0;right:0;bottom:0;top:auto;width:100%;height:46vh;
  object-fit:cover;object-position:center 73%;z-index:0;pointer-events:none}
/* soft horizon where the band meets the vista — no hard cut line */
.rd_scrim{position:fixed;left:0;right:0;bottom:36vh;top:auto;height:10vh;z-index:0;
  pointer-events:none;
  background:linear-gradient(var(--hero-black),rgba(16,16,16,0))}
.rd_reveal{position:relative;z-index:1;height:54vh;display:flex;flex-direction:column;
  padding:clamp(28px,4.5vh,56px) clamp(20px,4vw,60px) 0}
.rd_stair .rd_items{text-shadow:0 1px 8px rgba(0,0,0,.85)}
/* the ember clouds churn under zones 1 and 4, so a static scrim can never
   guarantee the item text — each row gets its own glass plate instead
   (measured: worst cloud pixel 205 -> ~57 behind a .6 plate, text at 158) */
.roadmap .rd_items div{background:rgba(10,8,6,.6);
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
  padding:.3vw .55vw;border-radius:9px}
.roadmap .rd_items{color:rgba(255,255,255,.72)}
@media(max-width:767px){.roadmap .rd_items div{padding:5px 10px}}
.rd_close{position:fixed;top:22px;right:26px;z-index:61;width:40px;height:40px;
  display:flex;align-items:center;justify-content:center;border:none;cursor:pointer;
  border-radius:999px;background:var(--dark);color:rgba(255,250,242,.85);
  font-size:18px;line-height:1;transition:color .2s,background .2s}
.rd_close:hover{color:var(--orange);background:#2a2a28}
.rd_close:focus-visible{outline:2px solid var(--orange);outline-offset:2px}
.rd_reveal{opacity:0;transform:translateY(28px);
  transition:opacity .8s cubic-bezier(0,0,.58,1),transform .8s cubic-bezier(0,0,.58,1)}
.rd_reveal.in{opacity:1;transform:none}
@media(prefers-reduced-motion:reduce){.rd_reveal{opacity:1;transform:none;transition:none}}
.rd_head{display:flex;flex-direction:column;align-items:center;text-align:center;
  gap:12px;margin-bottom:0}
.rd_title{color:rgba(255,250,242,.94);font-weight:700;letter-spacing:-.025em;
  line-height:1.08;font-size:clamp(1.8rem,3.3vw,2.9rem);margin:0}
.rd_title .accent{color:var(--orange)}
.rd_sub{margin:0;font-size:clamp(15px,1.245vw,23.9px);font-weight:500;
  color:rgba(255,255,255,.66)}
.rd_sub .accent{color:var(--orange)}

.rd_chip{display:flex;align-items:center;gap:10px;background:var(--dark);
  border-radius:18px;padding:clamp(10px,.95vw,16px) clamp(14px,1.4vw,24px);
  font-size:clamp(14px,1vw,18px);font-weight:500;white-space:nowrap;
  color:rgba(255,250,242,.94)}
.rd_chip svg{height:clamp(14px,1vw,18px);width:auto;flex-shrink:0;color:var(--orange)}
.rd_num{color:var(--orange);font-size:.85em;font-weight:500}
.rd_line{width:1px;background:linear-gradient(rgba(254,114,51,.9),
  rgba(251,170,133,.55) 55%,rgba(254,114,51,0))}
.rd_items{display:flex;flex-direction:column;align-items:flex-start;text-align:left;
  font-size:clamp(11px,.85vw,15px);color:rgba(255,255,255,.62)}

/* desktop staircase: absolute pillars, geometry inline per pillar. The stair
   hugs the bottom of the black band (margin-top:auto), and its lines run out
   of the container into the vista strip below. */
.rd_stair{position:relative;width:90vw;height:min(24vw,38vh);
  margin:auto auto 0;max-width:1800px}
.rd_pillar{position:absolute;display:flex;flex-direction:column;align-items:center}
.rd_stair .rd_drop{position:relative;display:flex;flex-direction:column;align-items:center}
.rd_stair .rd_line{height:12vw}
.rd_stair .rd_items{position:absolute;top:.6vw;left:.8vw;gap:.55vw;white-space:nowrap}

/* mobile: alternating single column */
.rd_flow{display:none}
@media(max-width:767px){
  .roadmap{overflow:auto}
  .roadmap.open{display:block}
  .rd_reveal{height:auto;min-height:60vh;padding-bottom:36vh}
  .rd_vista{height:32vh}
  .rd_scrim{bottom:22vh;height:10vh}
  .rd_stair{display:none}
  .rd_flow{display:flex;flex-direction:column;width:100%}
  .rd_step{display:flex;flex-direction:column;align-items:flex-start;width:100%;
    padding-bottom:8px}
  .rd_step--right{align-items:flex-end}
  .rd_step .rd_chip{display:inline-flex;font-size:15px;padding:10px 18px;gap:7px}
  .rd_steprow{display:flex;align-items:stretch;width:100%}
  .rd_step--right .rd_steprow{flex-direction:row-reverse}
  .rd_steprow .rd_line{flex-shrink:0;min-height:120px;margin-left:22px}
  .rd_step--right .rd_steprow .rd_line{margin-left:0;margin-right:22px}
  .rd_steprow .rd_items{padding:8px 0 8px 20px;gap:10px;font-size:14px}
  .rd_step--right .rd_steprow .rd_items{padding:8px 20px 8px 0;align-items:flex-end;text-align:right}
}
.ideastack .idea{position:absolute;inset:0;height:100%;
  will-change:opacity,transform}
.idea_bg{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:center;user-select:none;
  -webkit-user-drag:none;pointer-events:none}
/* TV treatment OFF for comparison (was: scanline raster + phosphor vignette
   at z3, over the text). To bring it back, restore on .idea::after —
   content:''; position:absolute; inset:0; z-index:3; pointer-events:none;
   background:
     radial-gradient(125% 125% at 50% 50%,
       rgba(0,0,0,0) 55%, rgba(0,0,0,.14) 82%, rgba(0,0,0,.35) 100%),
     repeating-linear-gradient(to bottom,
       rgba(0,0,0,.16) 0px, rgba(0,0,0,.16) 1px,
       rgba(255,255,255,.035) 1px, rgba(255,255,255,.035) 2px); */
.idea::after{content:none}
/* Pulled toward the subject: at 7vw inset there was ~290px of dead black
   between the text and the bot at 1920. 13vw closes it to ~180px — but no
   further, because cover-fit crops the image's SIDES as the window narrows,
   which slides the subject inward: at 1440 the bot's body edge is at ~784px
   and the text must stay clear of it. Measured, not eyeballed. */
/* hidden until its first decoded frame is actually painting ('playing'
   event), so a slow fetch can never flash black over the still */
.idea_vid{opacity:0;transition:opacity .4s linear}
.idea_vid.live{opacity:1}
.idea_text{position:relative;z-index:2;max-width:560px;
  margin-left:clamp(28px,13vw,270px);
  opacity:0;transform:translateY(28px);
  transition:opacity .8s cubic-bezier(0,0,.58,1),transform .8s cubic-bezier(0,0,.58,1)}
.idea_text.in{opacity:1;transform:none}
.idea--right .idea_text{margin-left:auto;margin-right:clamp(28px,13vw,270px);text-align:left}
.idea_eyebrow{font-size:13px;font-weight:500;letter-spacing:.14em;
  text-transform:uppercase;color:rgba(255,255,255,.52);margin:0 0 14px}
.idea_title{color:rgba(255,250,242,.94);font-weight:700;letter-spacing:-.025em;
  line-height:1.08;font-size:clamp(1.8rem,3.3vw,2.9rem);margin:0 0 16px}
.idea_title .accent{color:var(--orange)}
/* Title + subtitle pair (page 1): both single-line, sized so their rendered
   widths MATCH — the ratio is vw-linked (2.2vw : 1.05vw ≈ the 26-char bold
   title against the 60-char medium subtitle), so the match holds as the
   viewport scales rather than only at one width. */
.idea_title--one{font-size:clamp(29px,2.45vw,47px);white-space:nowrap;margin:0 0 12px}
.idea_sub{color:rgba(255,250,242,.88);font-weight:500;letter-spacing:-.01em;
  /* 1.245vw: measured against the title's INK (not its block box — flex items
     stretch children, which faked a perfect match once). Caps proportional
     (47/23.9 = the same ratio) so the match survives the clamp boundary. */
  font-size:clamp(15px,1.245vw,23.9px);line-height:1.4;white-space:nowrap;
  margin:0 0 18px}
.idea_sub .accent{color:var(--orange)}
@media(max-width:767px){
  .idea_title--one,.idea_sub{white-space:normal}}
.idea_body{color:rgba(255,255,255,.78);font-size:clamp(15px,1.15vw,17px);
  line-height:1.6;margin:0;max-width:46ch}
.idea--right .idea_body{margin-left:0}
/* the bigger body follows the title+subtitle structure (pages 1 and 2) */
#idea-control .idea_body,#idea-commerce .idea_body,#idea-compound .idea_body,#idea-expand .idea_body{font-size:clamp(16px,1.35vw,20px)}
/* page 3's swarm reaches further left (x .41) than the single bots (.53), so
   its paragraph takes a narrower measure to stay off the kneeling row */
#idea-compound .idea_body{max-width:33ch}
/* page 4: the rover's right wheel reaches x .473, so the paragraph stays
   narrower than the title to keep clear of it */
#idea-expand .idea_body{max-width:32ch}
@media(prefers-reduced-motion:reduce){
  .idea_text{opacity:1;transform:none;transition:none}}
@media(max-width:767px){
  .idea{align-items:flex-end}
  .idea_text,.idea--right .idea_text{margin:0 0 9vh;text-align:left;
    padding-inline:22px;max-width:100%}
  /* portrait screens show a narrow slice of a wide image — aim it at the
     subject side declared per-image via object-position */
}

/* retired with the strip (kept for the archived version): */
.cardstage{height:100vh;height:100dvh;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:clamp(18px,3vh,32px);
  padding:clamp(26px,4vh,52px) clamp(20px,3.5vw,56px)}

/* PLACEHOLDER copy — swap when the real line lands. Dark ink on the light
   screen, hero accent grammar (the orange full stop). */
.cs_head{text-align:center;color:var(--dark)}
.cs_eyebrow{font-size:13px;font-weight:500;letter-spacing:.14em;
  text-transform:uppercase;color:var(--stone);margin:0 0 10px}
.cs_title{font-weight:700;letter-spacing:-.03em;line-height:1;margin:0;
  font-size:clamp(1.7rem,3.2vw,2.6rem)}
.cs_title .accent{color:var(--orange)}

.exs_wrap{
  --exs-fg:rgba(255,250,242,.94);
  --exs-fg-soft:rgba(255,255,255,.82);
  --exs-margin:clamp(18px,1.8vw,30px);
  position:relative;display:flex;align-items:stretch;
  /* a component on the page, not the page: capped both ways so the light
     screen breathes around it and the heading reads as part of one slide */
  width:100%;max-width:min(1180px,90vw);flex:1 1 auto;min-height:0;
  max-height:min(62vh,660px);
  border-radius:clamp(10px,1.1vw,18px);
  overflow:hidden;background:#141210;
  -webkit-font-smoothing:antialiased;outline:none;touch-action:pan-y}
.exs_wrap:focus-visible{outline:2px solid var(--orange);outline-offset:-2px}

.exs_panel{position:relative;flex:1 1 0;min-width:0;height:100%;
  overflow:hidden;cursor:pointer}
.exs_panel:focus-visible{outline:2px solid var(--orange);outline-offset:-2px;z-index:5}

/* Scale + pan are GSAP-owned; no static transform here or the channels fight.
   PLACEHOLDER: a dark field with one accent light from upper left, matching
   the art direction the real renders are being made to. Swap this div for an
   <img class="exs_img"> and nothing else changes. */
.exs_img{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:center;transform-origin:center;
  will-change:transform;user-select:none;-webkit-user-drag:none;pointer-events:none;
  background:
    radial-gradient(120% 88% at 26% 16%, rgb(var(--c) / .55), transparent 62%),
    radial-gradient(88% 68% at 78% 90%, rgb(var(--c) / .16), transparent 72%),
    #141210}
/* Real art: --c is gone with the placeholder, which makes the gradient above
   invalid at computed-value time and takes the #141210 fallback down with it.
   Restate the ground so there is dark under the picture while it loads. */
img.exs_img{background:#141210}

/* Focus-pull on non-active panels. The element's own opacity must STAY 1:
   fading an element carrying a backdrop-filter composites the blurred result
   over the SHARP original at that alpha, so the blur reads as nothing. JS
   tweens the blur radius var and the tint alpha instead. */
.exs_shade{position:absolute;inset:0;z-index:1;background:rgba(10,10,10,0);
  -webkit-backdrop-filter:blur(var(--exs-blur-live,0px));
  backdrop-filter:blur(var(--exs-blur-live,0px));pointer-events:none}

.exs_scrim{position:absolute;inset:0;z-index:1;opacity:0;pointer-events:none;
  background:linear-gradient(to top,rgba(10,10,10,.62) 0%,rgba(10,10,10,.05) 45%,rgba(10,10,10,.2) 100%)}

/* ---- CRT raster --------------------------------------------------------- */
/* Taken from the supplied image-glitch shader's REST state, which is where its
   TV look actually lives — everything else in that component is driven by
   uIntensity, i.e. the glitch. The raster is these two lines:
     float scan = 0.5 + 0.5 * sin(uv.y * uResolution.y * 3.14159);
     col *= 1.0 - uScanlines * 0.22 * scan;
   sin(y·π) gives a 2px period, and at the shipped uScanlines of 0.45 the
   trough takes 0.45 × 0.22 = 9.9% of the light. That is the whole effect and
   it never animates, so it needs no WebGL, no texture and no render loop —
   which also means it works NOW, on the colour placeholders. A shader would
   render black until the real art lands, because it has nothing to sample.
   z-index 1 puts it over the picture and over the dim/blur, but under the
   type — matching the demo, where .ig_label sits outside the canvas. */
/* .099 was the shader's own trough — mathematically faithful and invisible
   here: this art is 40-60% near-black, and a multiplicative raster darkens
   a 9/255 pixel to 8/255. Real CRTs read as lined on dark screens because
   the lit rows EMIT, so the raster gained a faint glow phase (--exs-glow)
   and a deeper trough. Compared at .099/.16/.22 over the real art. */
.exs_wrap{--exs-scan:.16;--exs-glow:.035;--exs-vig:0}
.exs_panel::after{content:'';position:absolute;inset:0;z-index:1;
  pointer-events:none;
  background:
    /* phosphor vignette, from the same rest state: col *= mix(1, vig, 0.35).
       pow(vg,0.28) is near-flat across the middle and falls away only in the
       last fifth, so the stops sit late. OFF by default — you asked for the
       lines; set --exs-vig:.35 for the shader's full rest look. */
    radial-gradient(125% 125% at 50% 50%,
      rgba(0,0,0,0) 55%,
      rgba(0,0,0,calc(var(--exs-vig) * .4)) 82%,
      rgba(0,0,0,var(--exs-vig)) 100%),
    /* the raster: 2px period — a 1px trough, then a 1px emission line, so
       the lines survive on near-black art where darkening alone vanishes */
    repeating-linear-gradient(to bottom,
      rgba(0,0,0,var(--exs-scan)) 0px,
      rgba(0,0,0,var(--exs-scan)) 1px,
      rgba(255,255,255,var(--exs-glow)) 1px,
      rgba(255,255,255,var(--exs-glow)) 2px)}

.exs_text{position:absolute;left:var(--exs-margin);right:var(--exs-margin);
  bottom:var(--exs-margin);z-index:2;display:flex;flex-direction:column;gap:8px;
  pointer-events:none}
.exs_title{position:relative;display:block;margin:0;overflow-y:hidden;overflow-x:visible;
  padding-bottom:.18em;margin-bottom:-.18em;
  font-size:clamp(24px,2.6vw,42px);font-weight:700;letter-spacing:-.03em;line-height:1;
  color:var(--exs-fg);white-space:nowrap}
.exs_title_inner{display:block;transform:translateY(110%)}
.exs_label{position:relative;display:block;overflow-y:hidden;overflow-x:visible;
  padding-bottom:.2em;margin-bottom:-.2em;
  font-size:15px;font-weight:500;letter-spacing:.01em;color:var(--exs-fg-soft);
  white-space:nowrap}
.exs_label_inner{display:block;transform:translateY(110%)}

/* Body copy, same masked-reveal grammar as the title but allowed to WRAP, so
   no white-space:nowrap here. The mask is the <p>; the inner block slides up
   through it, however many lines it runs to. */
.exs_body{position:relative;display:block;overflow-y:hidden;overflow-x:visible;
  padding-bottom:.3em;margin:10px 0 -.3em;
  /* 14px at 60% white was legible in isolation but not over a photograph;
     both size and contrast were the problem, so both moved. */
  font-size:17px;font-weight:400;line-height:1.55;
  color:rgba(255,255,255,.80);max-width:40ch}
.exs_body_inner{display:block;transform:translateY(110%)}

/* Collapsed panel's word, reading bottom-up. The outer element is the MASK
   (static rotation, never tweened); the inner span slides through it. */
.exs_vlabel{position:absolute;left:var(--exs-margin);bottom:var(--exs-margin);z-index:2;
  transform:rotate(180deg);writing-mode:vertical-rl;overflow:hidden;pointer-events:none}
/* The sliver word is the ONLY label a closed card shows, and at a flat 18px it
   read as a caption on a 1080px-tall panel — "Settle" occupied 4.4% of the
   card. Scales with the viewport now; the floor keeps it legible on a laptop,
   the ceiling stops it dominating the art on a large screen. */
.exs_vlabel_inner{display:block;font-size:clamp(26px,2vw,40px);font-weight:500;
  letter-spacing:.005em;color:var(--exs-fg-soft);white-space:nowrap}

/* ---- Morphing accordion (step 3, FAQ) ----------------------------------
   Two stacked shapes share an SVG goo filter so the panel pours out of the
   pill. Text is never inside the filtered layer (the threshold matrix
   destroys type), so each filtered shape has a crisp twin that owns the
   visible edge. Retheme of the supplied component: brand ink, Clash Grotesk,
   transparent page so the fixed light screen shows through. */
.macc_wrap{
  --ga-ink:var(--dark);
  --ga-fg:rgba(255,250,242,.94);
  --ga-fg-soft:rgba(255,255,255,.80);
  --ga-fg-dim:rgba(255,255,255,.55);
  --ga-margin:clamp(20px,4vw,40px);
  /* NOT align-items:center. Centring meant every height change slid the whole
     component by half the delta — opening row 3 moved question 1 by 79.5px.
     The stage's top is placed by faq.js instead (see placeStage) and never
     moves; rows grow downward into the space below it.
     Content-height, NOT a forced viewport: 100vh wrapped a 419px component in
     ~660px of dead screen. placeStage degrades cleanly here — with no spare
     height its centring maths lands on marginTop 0 and the padding rules. */
  /* NO snap-align. The snap point sat ~100px above the page's end on real
     screens (browser chrome shortens the viewport), so resting at the bottom
     made proximity snap yank the page back up — the "small bump". The FAQ is
     the final screen; there is nothing below it to align to. */
  position:relative;display:flex;align-items:flex-start;justify-content:center;
  width:100%;
  /* generous but not a forced viewport — and sized so that sitting on the FAQ
     puts the WHOLE footer inside the same screen: FAQ wrap + footer stage must
     stay within ~100vh (at 1080p: 689 + 387 = 1076). The bottom padding leans
     smaller than the top because the footer band brings its own dark air. */
  padding:clamp(110px,14vh,170px) var(--ga-margin) clamp(90px,11vh,140px);
  background:transparent;
  -webkit-font-smoothing:antialiased}
/* Cards -> FAQ: the scroll-driven FADE (the keeper — the static gradient
   bands were the ugly part, and they are gone for good; the bottom seam into
   the footer stays a clean cut). The cover is the strip's own dark laid over
   the whole FAQ, opacity a pure function of scrollY: hold dark deep into the
   arrival, then clear in a short throw — an aggressive pop, not a long
   dissolve. Scrolling back re-darkens it exactly. z2 keeps it ABOVE the
   questions; a fade the pills float on top of isn't a fade. */
.macc_fade{position:absolute;inset:0;z-index:2;background:#141210;
  opacity:1;pointer-events:none;will-change:opacity}

/* Reactive Lines live behind the accordion. z-index 1 on the stage keeps every
   pill, panel and click above the canvas; the canvas itself never takes
   pointer events. */
.macc_lines{position:absolute;inset:0;z-index:0;pointer-events:none}
.macc_lines canvas{width:100%;height:100%;display:block}
.macc_stage{position:relative;z-index:1;width:100%;max-width:620px}
/* light ink on the dark screen — same register as the idea-page titles */
.macc_title{color:rgba(255,250,242,.94);font-weight:700;letter-spacing:-.03em;line-height:1;
  font-size:clamp(1.9rem,3.6vw,2.8rem);margin-bottom:clamp(24px,3vh,38px)}
/* hero accent grammar carried over: the headline's orange full stop, the index
   numerals as the accent ink, and the open state answering in orange */
.macc_title .accent{color:var(--orange)}
.macc_filter_svg{position:absolute;width:0;height:0;overflow:hidden;pointer-events:none}
.macc_list{display:flex;flex-direction:column;gap:8px}
.macc_row{position:relative}

/* filtered layer: solid ink shapes only, never text */
.macc_goo{position:absolute;inset:0;z-index:0;pointer-events:none}
.macc_goo_trigger,.macc_goo_panel{position:absolute;top:0;left:0;width:100%;
  background-color:var(--ga-ink);will-change:transform}
.macc_goo_panel{border-radius:16px}

/* crisp twins, OUTSIDE the filter: while the blur is live the threshold
   reshapes every filtered edge, so these own the visible outline and the
   filtered originals only supply goo mass */
.macc_trigger_crisp{position:absolute;top:0;left:0;right:0;z-index:3;
  background-color:var(--ga-ink);pointer-events:none;
  transition:background-color .3s cubic-bezier(.7,0,.16,1)}
.macc_trigger:hover + .macc_trigger_crisp{background-color:#2a2a28}
.macc_panel_crisp{position:absolute;top:0;left:0;z-index:1;
  background-color:var(--ga-ink);border-radius:16px;pointer-events:none;
  will-change:transform}

.macc_trigger{position:relative;z-index:4;display:flex;align-items:center;gap:16px;
  width:100%;min-height:62px;padding:18px 24px;background:transparent;border:none;
  cursor:pointer;text-align:left;color:var(--ga-fg);font-family:inherit}
.macc_trigger:focus{outline:none}
.macc_trigger:focus-visible{outline:2px solid var(--orange);outline-offset:2px;border-radius:999px}
.macc_index{flex-shrink:0;min-width:24px;font-size:14px;font-weight:500;
  color:var(--orange);transition:color .3s}
.macc_trigger:hover .macc_index{color:var(--soft-orange)}
.macc_question{flex:1;font-size:17px;font-weight:500;letter-spacing:-.015em;
  line-height:1.35;color:var(--ga-fg)}
.macc_icon{width:17px;height:17px;flex-shrink:0;color:var(--ga-fg-soft);
  transform-origin:50% 50%;will-change:transform;transition:color .3s}
/* the plus rotates to an x when open — it turns orange as it does, the same
   "active = orange" rule as the hero CTA */
.macc_trigger[aria-expanded="true"] .macc_icon{color:var(--orange)}

.macc_panel{position:relative;z-index:2;height:0;overflow:hidden;will-change:height}
/* margin-top must match PANEL_GAP in faq.js: it is the rest gap the goo
   bridges during the pour */
.macc_panel_inner{margin-top:10px;padding:18px 24px 22px}
.macc_answer{margin:0;font-size:16px;font-weight:400;line-height:1.6;
  letter-spacing:-.005em;color:var(--ga-fg-soft)}
.macc_answer_line{overflow-x:visible;overflow-y:clip;
  padding-bottom:.18em;margin-bottom:-.18em}

@media(max-width:767px){
  .macc_trigger{padding:16px 18px;gap:12px;min-height:56px}
  .macc_question{font-size:16px}
  .macc_panel_inner{padding:14px 18px 18px}
  .macc_answer{font-size:15px}
}
@media(max-width:479px){ .macc_index{display:none} }

/* ---- STEP 4 — footer ---------------------------------------------------- */
/* The liquid-glass recipe below is used EXACTLY as supplied. It is built for a
   dark backdrop: the fill is a 1% white wash and the entire edge treatment is
   white, so over the light screen both the border and the copy would vanish.
   The band therefore brings its own dark ground — which also closes the site
   on the same ink it opened with. */
/* flow-root, or the footer's mt-32/md:mt-64 collapses straight out through the
   band and becomes a gap of LIGHT screen above it — leaving the glass panel
   welded to the top edge of the dark with no ground around it. */
.footerstage{position:relative;background:var(--dark);display:flow-root;
  padding:0 clamp(20px,3.5vw,56px) clamp(14px,2vh,24px);
  content-visibility:auto;contain-intrinsic-size:auto 420px}
.footerstage .ft_inner{max-width:80rem;margin:0 auto}      /* max-w-7xl */

/* Glass panel RETIRED (user, 2026-08-12): the white gradient edge read as a
   frame and made the footer a bombastic object. The footer now sits flat on
   the dark ground — content, a hairline divider, done. The class stays in the
   markup so the old recipe can be restored from git/archives if wanted. */
.liquid-glass{position:relative}

/* motion.footer: {opacity:0,y:40} -> {opacity:1,y:0}, duration 1, delay .4,
   ease "easeOut". Framer's named easeOut IS cubic-bezier(0,0,.58,1), so this is
   the same curve rather than an approximation. React would fire it on MOUNT;
   here the footer is three screens below the fold at load, so it would be over
   long before anyone saw it — it runs on first sight instead. */
/* NOT the spec's mt-32/md:mt-64. Those 128/256px existed to clear the CTA the
   spec put above the footer; with nothing there it was 256px of dead black
   against 43px below the panel — a 6:1 band. This is breathing room, not a gap. */
.site-footer{width:100%;padding:16px 0 0;
  color:rgba(255,255,255,.7);margin-top:clamp(12px,2vh,20px);
  opacity:0;transform:translateY(40px);
  transition:opacity 1s cubic-bezier(0,0,.58,1) .4s,
             transform 1s cubic-bezier(0,0,.58,1) .4s}
.site-footer.in{opacity:1;transform:none}
@media(min-width:768px){.site-footer{padding:20px 0 0;margin-top:clamp(14px,2vh,24px)}}
@media(prefers-reduced-motion:reduce){
  .site-footer{opacity:1;transform:none;transition:none}}

.ft_top{display:grid;grid-template-columns:1fr;gap:28px;margin-bottom:26px}
@media(min-width:768px){
  .ft_top{grid-template-columns:repeat(12,minmax(0,1fr));gap:36px}
  .ft_brand{grid-column:span 5/span 5}
  .ft_linkgrid{grid-column:span 7/span 7}}

.ft_mark{display:flex;align-items:center;gap:10px;color:#fff}
/* the pinwheel in brand orange — the footer's one solid accent, mirroring the
   hero where orange belongs to the brand moments (Settle., the CTA) */
.ft_mark svg{height:24px;width:auto;flex-shrink:0;color:var(--orange)}
.ft_name{font-size:1.25rem;font-weight:500;letter-spacing:-.01em;line-height:1}
.ft_desc{font-size:.875rem;line-height:1.55;max-width:24rem;margin:10px 0 0}

.ft_linkgrid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:28px}
@media(max-width:600px){.ft_linkgrid{grid-template-columns:repeat(2,1fr)}}
/* items with no destination yet: click pops the coming-soon chip */
.ft_soon{cursor:pointer;position:relative}
.ft_soon::after{content:'COMING SOON';position:absolute;left:50%;bottom:calc(100% + 7px);
  transform:translateX(-50%) translateY(4px);background:#1C1C1C;color:var(--orange);
  font-size:10px;font-weight:500;letter-spacing:.09em;padding:6px 10px;border-radius:8px;
  white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .25s,transform .25s}
.ft_soon:focus{outline:none}
.ft_soon:hover::after,.ft_soon:focus::after,.ft_soon.show::after{opacity:1;transform:translateX(-50%) translateY(0)}
.ft_col h3{font-size:.875rem;text-transform:uppercase;letter-spacing:.05em;
  color:#fff;font-weight:500;margin:0 0 10px}
.ft_col ul{list-style:none;margin:0;padding:0;
  display:flex;flex-direction:column;gap:6px;font-size:.75rem}
.ft_col a{color:inherit;text-decoration:none;transition:color .2s}
.ft_col a:hover{color:var(--soft-orange)}
.ft_col a:focus-visible{outline:2px solid var(--orange);outline-offset:2px;border-radius:2px}

.ft_bottom{padding-top:14px;border-top:1px solid rgba(255,255,255,.1);
  display:flex;flex-direction:column;align-items:center;
  justify-content:space-between;gap:14px;padding-bottom:2px}
@media(min-width:768px){.ft_bottom{flex-direction:row;gap:16px}}
.ft_fine{font-size:10px;text-transform:uppercase;letter-spacing:.1em;
  opacity:.5;margin:0}
.ft_socialwrap{display:flex;align-items:center;gap:16px}
.ft_social{display:flex;align-items:center;gap:16px}
.ft_social a{color:inherit;opacity:.7;display:inline-flex;
  transition:opacity .2s,color .2s}
.ft_social a:hover{opacity:1;color:var(--orange)}
.ft_social a:focus-visible{outline:2px solid var(--orange);outline-offset:3px;border-radius:4px}
.ft_social svg{width:16px;height:16px}
@media(max-width:479px){.ft_linkgrid{gap:20px}.ft_col ul{font-size:.7rem}}

@media(max-width:767px){
  .exs_wrap{flex-direction:column;--exs-margin:18px}
  /* rows are wide and short here, so a vertical word has no axis to run on */
  .exs_vlabel{display:none}
  .exs_panel{min-height:0}
  .exs_title{font-size:clamp(22px,7vw,34px)}
  /* rows are short here; the paragraph has to stay inside one */
  .exs_body{font-size:15px;line-height:1.5;max-width:46ch}
  .exs_label{font-size:14px}
}
.next p{font-size:13px;color:var(--stone);margin-bottom:16px}
.next h2{font-weight:700;letter-spacing:-.025em;line-height:.95;font-size:clamp(2.2rem,5.5vw,4.5rem)}
.next h2 em{font-style:normal;color:var(--orange)}

@keyframes fade-up{from{opacity:0;transform:translateY(30px)}to{opacity:1;transform:translateY(0)}}
.fu{opacity:0;animation:fade-up .8s ease-out forwards}
.fu1{animation-delay:.2s}.fu2{animation-delay:.4s}.fu3{animation-delay:.6s}.fu4{animation-delay:.8s}
@media(prefers-reduced-motion:reduce){.fu{animation:none;opacity:1}}

@media(min-width:768px){nav{padding:26px 44px}main{padding:0 44px 34px}.navlinks,.cta-ghost{display:flex}.burger{display:none}}
@media(min-width:1024px){nav{padding:28px 64px}main{padding:0 64px 34px}}

/* portrait: the figure sits low and small, so the scrim has to run top-to-bottom
   rather than left-to-right, and the stats need a tighter track */
@media(max-width:767px){
  /* the bloom is in absolute px, so at 375 wide it swallowed far more of the
     screen than it does at 1280 — scaled back to stay proportional */
  .bezel{box-shadow:
    inset 0 0 8px 1px rgba(253,139,173,.92),
    inset 0 0 20px 3px rgba(253,139,173,.44),
    inset 0 0 44px 8px rgba(253,139,173,.14)}
  .scrim{background:linear-gradient(to bottom,
    rgba(28,28,28,.95) 0%,rgba(28,28,28,.9) 40%,rgba(28,28,28,.55) 62%,
    rgba(28,28,28,.82) 84%,rgba(28,28,28,.95) 100%)}
  .toggle{top:78px;bottom:auto;right:12px;padding:8px 14px;font-size:11px}
}

/* ---- Ecosystem dropdown + nav coming-soon chip -------------------------- */
nav{position:relative;z-index:20}
.navdrop{position:relative;display:flex}
.navdrop_t{cursor:pointer}
.navdrop_p{position:absolute;top:calc(100% + 12px);left:50%;
  transform:translateX(-50%) translateY(-4px);min-width:150px;
  display:flex;flex-direction:column;gap:2px;padding:8px;background:#1C1C1C;
  border-radius:12px;opacity:0;pointer-events:none;
  transition:opacity .2s,transform .2s;z-index:30}
.navdrop:hover .navdrop_p,.navdrop:focus-within .navdrop_p{opacity:1;
  pointer-events:auto;transform:translateX(-50%) translateY(0)}
.navlinks .navdrop_p a{padding:9px 14px;border-radius:8px;font-size:13px}
.navlinks .navdrop_p a:hover{background:#2a2a28;color:#fff}
/* the bar sits at the viewport top, so its chip drops BELOW the item */
.navlinks .ft_soon::after{bottom:auto;top:calc(100% + 9px);
  transform:translateX(-50%) translateY(-4px)}
.navlinks .ft_soon:hover::after,.navlinks .ft_soon:focus::after,
.navlinks .ft_soon.show::after{transform:translateX(-50%) translateY(0)}

/* ---- No scrollbar -------------------------------------------------------
   The native scrollbar was the last piece of unstyled OS chrome on the site:
   a light-grey slab down the edge of a #101010 page, the same leak the .next
   rule already went black to stop. No indicator replaces it — the edge is
   meant to be empty; the hero's .scrollcue is the only affordance.
   Vertical only, so a horizontal overflow bug still shows its bar — the root
   deliberately has no overflow-x:hidden and hiding both axes would mask that.
   Side effect worth keeping: #stage is width:100vw, which included the
   scrollbar gutter while the client area did not, so the canvas was ~15px
   wider than the page. With no gutter the two finally agree. */
html{scrollbar-width:none}
html::-webkit-scrollbar:vertical{width:0}
