/* ============================================================
   NAWF — charcoal / minimal / lime · premium
   ============================================================ */
:root{
  --bg:#18191C;            /* near-black charcoal */
  --ink:#E2E2DE;           /* soft warm white */
  --mut:#72747A;           /* muted mid-grey */
  --line:#2E3035;          /* subtle hairlines */
  --panel:#22252A;         /* raised card surface */
  /* Accent system: a single lime everywhere. No blue —
     deliberately, brand-wide. Anything cool-cast reads as the old palette. */
  --accent:#C1FF72;        /* the only lime: electric lime */
  --accent-deep:#A9EE4C;   /* pressed / hover state */
  --accent-2:#9FC131;      /* secondary: sage-lime, for card/badge background variation only — never for heading text */
  --accent-3:#FFD75E;      /* tertiary: warm amber, third in any rotation (not lime) */
  /* Lime is a light colour: anything sitting ON it must use --on-accent,
     never white, or the contrast collapses. */
  --on-accent:#14160F;
  /* Boot card that fills the screen at 100% and opens onto the page —
     matches the site's primary lime accent. */
  --intro-bg:#C1FF72;
  /* Two faces, one pairing, site-wide: Bricolage Grotesque carries every
     word of body copy, UI and numerals; Boldonse carries titles only.
     --font-body is the ONLY body token. Paragraphs, sub-copy, eyebrow
     labels, numerals, form fields and buttons all resolve to it, so the
     running text never changes face mid-page. */
  --font-body:'Bricolage Grotesque',system-ui,-apple-system,'Segoe UI',sans-serif;
  /* Boldonse — expressive display face used for section headings only.
     Single weight (400); never request bold from it, the browser fakes it. */
  --font-head:'Boldonse','Bricolage Grotesque',system-ui,sans-serif;
  /* One canonical metric for every Boldonse heading. Boldonse's ascenders
     and descenders overflow a 1.0 line box, so anything tighter than this
     collides between lines or gets sheared by a clip/mask ancestor. */
  --head-lh:1.25;
  --head-ls:-0.005em;
  --pad:clamp(20px,5vw,72px);
}
*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:auto}
html.lenis,html.lenis body{height:auto}
.lenis.lenis-smooth{scroll-behavior:auto!important}
body{
  background:var(--bg);
  color:var(--ink);
  font-family:var(--font-body);
  font-size:16px;
  font-weight:400;
  line-height:1.6;
  /* Bricolage sets wider than Geist did; it only needs a hair of tracking */
  letter-spacing:-0.005em;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  overflow-x:hidden;
}
::selection{background:var(--accent);color:var(--on-accent)}
a{color:inherit;text-decoration:none}
em{font-style:italic}
.label{
  font-family:var(--font-body);
  font-size:11px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--mut);font-weight:400;
}
/* section eyebrow that carries real weight rather than fine print */
.label-lead{
  font-size:clamp(14px,1.45vw,21px);
  letter-spacing:.2em;
  color:#9a9c95;
}
.label-lead .lime{color:var(--accent)}
.display{
  font-family:var(--font-head);
  font-weight:400;
  font-size:clamp(26px,4vw,54px);
  line-height:1.18;
  letter-spacing:-0.01em;
}
/* upright colored accents: blue primary, yellow on alternate sections */
.display em,.hero-title em,.infra-card h3 em{font-style:normal;color:var(--accent)}
.wycd .display em,.aithat .display em,.roi .display em,.ideas .display em,.connect .display em{color:var(--accent)}
/* The xl headings are two-liners set very large, where 1.18 is not enough
   leading: the comma of "Influence," lands on the cap-height of
   "reimagined." underneath. Leading is proportional, so this has to be
   looser than the base .display size, not the same. */
.display.xl{font-size:clamp(38px,7vw,100px);line-height:1.34}
/* Use the same Bricolage Grotesque weight as “Production without production.”
   Only the page's primary section headings are affected. */
.page .hero-title,.page .display{font-family:var(--font-head);font-weight:400}
.btn{
  display:inline-block;
  padding:14px 28px;
  border-radius:999px;
  font-weight:400;font-size:14px;
  transition:background .3s,color .3s;
  will-change:transform;
}
.btn-accent{background:var(--accent);color:var(--on-accent);font-weight:500}
.btn-accent:hover{background:var(--accent-deep)}
.btn.big{padding:20px 44px;font-size:16px}

/* ============ INTRO / BOOT ============ */
.intro{
  position:fixed;inset:0;z-index:100;
  background:var(--bg);
  color:var(--ink);
  display:flex;align-items:center;justify-content:center;
}
.intro-frame.cover{background:var(--intro-bg)}
.intro-head{
  position:absolute;top:0;left:0;right:0;
  display:flex;justify-content:space-between;align-items:center;
  padding:22px var(--pad);
}
.intro-logo{
  font-family:var(--font-body);font-weight:400;
  font-size:22px;letter-spacing:.04em;
}
.intro-label{font-size:11px;letter-spacing:.16em;text-transform:uppercase;opacity:.7}
.intro-frame{
  width:min(30vh,300px);
  aspect-ratio:3/4;
  overflow:hidden;
  background:var(--line);
  will-change:width,height;
  transition:background .25s;
}
.intro-img{width:100%;height:100%;object-fit:cover;display:block;will-change:transform}
.intro-foot{
  position:absolute;bottom:0;left:0;right:0;
  display:flex;justify-content:space-between;align-items:flex-end;
  padding:22px var(--pad);
}
.intro-counter{
  font-family:var(--font-body);
  font-size:clamp(40px,7vw,84px);
  font-weight:300;line-height:1;
  font-variant-numeric:tabular-nums;
}
.intro-scroll{
  font-size:11px;letter-spacing:.18em;text-transform:uppercase;
  opacity:0;transition:opacity .6s;
  animation:none;
}
.intro-scroll.on{opacity:.85;animation:bob 1.8s ease-in-out infinite}
@keyframes bob{0%,100%{transform:translateY(0)}50%{transform:translateY(6px)}}

/* ============ SCROLL LINE (home only) ============ */
.scroll-line{
  position:fixed;right:26px;top:50%;transform:translateY(-50%);
  width:1px;height:38vh;z-index:60;
  background:rgba(255,255,255,.10);
  opacity:0;transition:opacity .6s;
  pointer-events:none;
}
.scroll-line.on{opacity:1}
.scroll-line i{
  display:block;width:100%;height:100%;
  background:rgba(255,255,255,.55);
  transform:scaleY(0);transform-origin:top;
  will-change:transform;
}

/* ============ NAV ============ */
.nav{
  position:fixed;top:0;left:0;right:0;z-index:50;
  display:flex;align-items:center;justify-content:space-between;
  padding:18px var(--pad);
  background:color-mix(in srgb,var(--bg) 82%,transparent);
  backdrop-filter:blur(14px);
  border-bottom:1px solid transparent;
  opacity:0;pointer-events:none;
  transition:opacity .5s,transform .45s cubic-bezier(.22,1,.36,1);
}
.nav.on{opacity:1;pointer-events:auto;border-bottom-color:var(--line)}
/* tucked away over a full-screen artboard hero until the page is scrolled */
.nav.nav--tucked{transform:translateY(-105%);opacity:0;pointer-events:none}
.nav-logo{font-family:var(--font-body);font-weight:400;font-size:20px}
.nav-links{
  position:relative;
  display:flex;gap:6px;font-size:15px;font-weight:400;
}
.nav-links a{
  position:relative;z-index:2;
  color:var(--mut);transition:color .3s,background .3s;
  padding:9px 17px;border-radius:999px;
  /* gentle bob — each link drifts on its own phase, like floating on water */
  animation:navFloat 4.6s ease-in-out infinite;
  will-change:transform;
}
/* staggered, non-matching phases so they never bob in unison */
.nav-links a:nth-child(1){animation-delay:-.2s;animation-duration:4.6s}
.nav-links a:nth-child(2){animation-delay:-1.5s;animation-duration:5.3s}
.nav-links a:nth-child(3){animation-delay:-2.9s;animation-duration:4.1s}
.nav-links a:nth-child(4){animation-delay:-.9s;animation-duration:5.8s}
.nav-links a:nth-child(5){animation-delay:-3.6s;animation-duration:4.9s}
@keyframes navFloat{
  0%,100%{transform:translateY(0) rotate(0deg)}
  30%{transform:translateY(-3px) rotate(-.5deg)}
  65%{transform:translateY(2px) rotate(.4deg)}
}
.nav-links a:hover{color:var(--bg);background:var(--ink)}
.nav-links a.active{color:var(--ink)}
.nav-pill{
  position:absolute;top:0;left:0;z-index:1;
  height:100%;width:0;
  background:rgba(255,255,255,.08);
  border:1px solid rgba(255,255,255,.06);
  border-radius:999px;
  opacity:0;
  pointer-events:none;
  will-change:transform,width;
}
.nav-cta{
  font-size:15px;font-weight:400;
  padding:10px 22px;border-radius:999px;
  border:1px solid var(--ink);
  transition:background .3s,color .3s;
}
.nav-cta:hover{background:var(--ink);color:var(--bg)}

/* ============ PAGE / SECTIONS ============ */
.page{position:relative;z-index:1;background:transparent}
section{padding:clamp(80px,12vh,160px) var(--pad)}
/* ── mobile: tighten the rhythm between every section ──
   That padding lands on both sides of each seam, so on a phone two
   adjacent sections contribute ~96px each and the join reads as ~190px of
   nothing. The vertical space desktop needs to separate large compositions
   is simply too much when the same sections are a fraction of the width.
   Sections that set their own padding (.reality, .steps, .connect, .cyl,
   .hero, .xfade, .services, .trusted, .ideas, .usecases) use class
   selectors, which outrank this element selector — so their tuned values,
   including the seam trims added earlier, are unaffected. */
@media (max-width:700px){
  section{padding:clamp(44px,7vh,80px) var(--pad)}
}

/* ============ 360 CYLINDER LANDING ============ */
.cyl{height:100vh;padding:0;position:relative;overflow:hidden}
.cyl-stage{
  position:absolute;inset:0;
  display:flex;align-items:center;justify-content:center;
  perspective:1900px;
}
.cyl-tilt{
  transform-style:preserve-3d;
  will-change:transform;
}
.cyl-ring{
  position:relative;width:0;height:0;
  transform-style:preserve-3d;
  will-change:transform;
}
.cyl-panel{
  position:absolute;
  width:calc(clamp(160px,18vw,300px) * var(--s,1));
  aspect-ratio:3/4;
  transform:
    translate(-50%,calc(-50% + var(--y,0vh)))
    rotateY(calc(var(--i) * 45deg))
    translateZ(min(46vw,620px))
    rotate(var(--t,0deg));
  overflow:hidden;border-radius:4px;
  box-shadow:0 30px 80px -30px rgba(0,0,0,.7);
  background:var(--panel);
}
.cyl-panel img{
  width:100%;height:100%;object-fit:cover;display:block;
}
.cyl-center{
  position:absolute;left:0;right:0;bottom:11vh;z-index:2;
  display:flex;flex-direction:column;align-items:center;gap:10px;
  text-align:center;pointer-events:none;
}
.cyl-title{
  font-family:var(--font-head);font-weight:400;
  font-size:clamp(42px,7vw,108px);line-height:1.1;letter-spacing:0;
}
.cyl-sub{
  font-family:var(--font-body);
  font-size:12px;letter-spacing:.2em;text-transform:uppercase;color:var(--mut);font-weight:400;
}
.cyl-hint{
  margin-top:26px;
  font-size:10px;letter-spacing:.22em;text-transform:uppercase;color:var(--mut);
  animation:bob 1.8s ease-in-out infinite;
}
@media (max-width:700px){
  .cyl-panel{width:calc(38vw * var(--s,1));transform:
    translate(-50%,calc(-50% + var(--y,0vh)))
    rotateY(calc(var(--i) * 45deg))
    translateZ(82vw)
    rotate(var(--t,0deg));}
}

/* hero - ambient drifting glow */
.hero{min-height:100vh;display:flex;flex-direction:column;justify-content:center;gap:28px;padding-top:120px;position:relative;overflow:hidden}
/* soft falloff comes from the gradient itself — a 90px blur on elements
   this large is extremely expensive to paint and caused scroll jank */
.hero::before,.hero::after{
  content:"";position:absolute;z-index:-1;border-radius:50%;
  pointer-events:none;will-change:transform;
}
.hero::before{
  width:52vw;height:52vw;top:-14vw;right:-12vw;
  background:radial-gradient(circle,rgba(193,255,114,.055),rgba(193,255,114,.02) 40%,transparent 68%);
  animation:drift1 16s ease-in-out infinite alternate;
}
.hero::after{
  width:38vw;height:38vw;bottom:-10vw;left:-8vw;
  background:radial-gradient(circle,rgba(255,215,94,.035),rgba(255,215,94,.01) 40%,transparent 68%);
  animation:drift2 20s ease-in-out infinite alternate;
}
@keyframes drift1{to{transform:translate(-9vw,7vw) scale(1.15)}}
@keyframes drift2{to{transform:translate(7vw,-6vw) scale(1.1)}}
/* warning-tape marquee strip */
.tag-strip{
  margin-inline:calc(var(--pad) * -1);
  background:var(--accent);
  border-top:3px solid #0A0A0C;
  border-bottom:3px solid #0A0A0C;
  overflow:hidden;
  padding:12px 0;
}
.tag-track{
  display:inline-flex;align-items:center;gap:26px;
  white-space:nowrap;
  font-family:var(--font-body);
  font-size:13px;letter-spacing:.14em;text-transform:uppercase;font-weight:500;
  color:#0A0A0C;
  padding-right:26px;
  animation:tagscroll 22s linear infinite;
  will-change:transform;
}
.tag-track i{font-style:normal;font-size:9px}
@keyframes tagscroll{
  from{transform:translateX(0)}
  to{transform:translateX(-50%)}
}
/* Set in caps in the markup, not with text-transform, so the line breaks
   are authored: THE INFRASTRUCTURE BEHIND / NEXT-GEN MARKETING.
   Boldonse is a wide face and line one is 25 characters, so the size is
   capped by what fits that line in the copy column — not by how big the
   headline could be. Push the size up and line one wraps, which is the
   thing these breaks exist to prevent.
   text-wrap:balance is the safety net at widths where it stops fitting. */
.hero-title{
  font-family:var(--font-head);font-weight:400;
  font-size:clamp(22px,2.9vw,48px);
  line-height:1.3;letter-spacing:-0.015em;
  padding-top:.1em;
  text-wrap:balance;
}
.hero-title em{color:var(--accent)}
/* The positioning statement — sits directly under the headline, set in
   the same display font as the headline so it reads as its continuation,
   with a lime rule down the left tying it to the accent system. */
.hero-sub{
  max-width:600px;color:var(--ink);
  font-family:var(--font-body);font-weight:600;
  font-size:clamp(19px,1.5vw,24px);line-height:1.4;
  letter-spacing:-0.01em;
  padding-left:clamp(16px,1.4vw,22px);
  border-left:2px solid var(--accent);
}
.hero-sub em{font-style:normal;color:var(--ink)}
.hero-actions{display:flex;align-items:center;gap:28px}

/* ── mobile: close the dead band between the cylinder and the hero ──
   Three things stack up on a phone and none of them show on desktop:
   100vh counts the area behind the collapsing address bar, so both
   sections render taller than the screen actually is; the mark sits
   11vh off the cylinder's bottom; and the hero adds a 120px top pad
   sized for the desktop nav. svh measures the genuinely visible
   viewport — on desktop it equals vh, and browsers without it simply
   keep the 100vh above, so this block cannot affect the desktop view.
   Placed after the .hero rule on purpose: media queries add no
   specificity, so an earlier block would lose to it. */
@media (max-width:700px){
  .cyl{height:100svh}
  .cyl-center{bottom:7vh}
  .hero{min-height:100svh;padding-top:76px;gap:20px}
}

/* wycd / infra */
.infra-cards{display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-top:56px}
.infra-card{
  --acc:var(--accent);
  border:1px solid var(--line);border-radius:20px;
  padding:40px;display:flex;flex-direction:column;gap:14px;
  background:var(--panel);position:relative;overflow:hidden;
  transition:border-color .3s,transform .5s cubic-bezier(.22,1,.36,1),box-shadow .5s;
}
.infra-card:nth-child(2){--acc:var(--accent-2)}
.infra-card .card-bg{
  position:absolute;inset:0;z-index:0;
  background-size:cover;background-position:center 20%;
  opacity:0;transform:scale(1.08);
  transition:opacity .55s ease,transform 1.1s cubic-bezier(.22,1,.36,1);
}
.infra-card::after{
  content:"";position:absolute;inset:0;z-index:1;
  background:linear-gradient(to top,rgba(10,10,12,.9) 20%,rgba(10,10,12,.35));
  opacity:0;transition:opacity .55s ease;
}
.infra-card>.label,.infra-card>h3{position:relative;z-index:2}
.infra-card:hover{border-color:var(--acc);transform:translateY(-8px) scale(1.012);box-shadow:0 30px 70px -30px color-mix(in srgb,var(--acc) 45%,transparent)}
.infra-card:hover .card-bg{opacity:.55;transform:scale(1)}
.infra-card:hover::after{opacity:1}
.infra-card:hover h3 em{color:var(--acc)}
.infra-card h3{font-family:var(--font-head);font-size:clamp(19px,2.1vw,29px);font-weight:400;line-height:1.2}
.infra-card h3 em{color:var(--accent)}

/* reality — pinned orb-merge scene */
.reality{
  position:relative;
  text-align:center;
  height:100vh;
  display:flex;flex-direction:column;
  justify-content:center;
  align-items:center;
  padding:6vh var(--pad) 5vh;
  gap:0;
  overflow:hidden;
}
.reality > .display{position:relative;z-index:3;font-size:clamp(13px,1.85vw,26px);letter-spacing:-0.01em;line-height:1.3;white-space:nowrap}
.merge-stage{
  position:relative;
  z-index:2;              /* orbs + logo sit ABOVE the giant tagline */
  width:100%;
  height:38vh;margin:3vh 0 4vh;
  flex-shrink:0;
}
.orb{
  position:absolute;top:50%;left:50%;
  width:clamp(170px,23vw,320px);aspect-ratio:1;
  margin:calc(clamp(170px,23vw,320px) / -2) 0 0 calc(clamp(170px,23vw,320px) / -2);
  border-radius:50%;
  mix-blend-mode:screen;
  display:flex;align-items:center;justify-content:center;
  will-change:transform;
  z-index:1;
}
.orb-l{background:radial-gradient(circle,rgba(230,230,226,.30) 0%,rgba(230,230,226,.10) 45%,transparent 70%)}
.orb-r{background:radial-gradient(circle,rgba(193,255,114,.34) 0%,rgba(193,255,114,.12) 45%,transparent 70%)}
.orb-label{
  font-family:var(--font-body);
  font-size:clamp(14px,1.3vw,17px);letter-spacing:.22em;text-transform:uppercase;
  color:var(--ink);font-weight:400;
}
.merge-burst{
  position:absolute;top:50%;left:50%;
  width:clamp(280px,38vw,540px);aspect-ratio:1;
  transform:translate(-50%,-50%) scale(0);
  border-radius:50%;
  background:radial-gradient(circle,rgba(255,215,94,.30) 0%,rgba(193,255,114,.18) 40%,transparent 70%);
  mix-blend-mode:screen;
  opacity:0;
  will-change:transform,opacity;
}
.merge-center{
  position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  display:flex;flex-direction:column;align-items:center;gap:10px;
  pointer-events:none;
}
/* ── OVERLAP word — vertical stacked letters at intersection ── */
.overlap-word{
  position:absolute;top:50%;left:50%;
  transform:translate(-50%,-50%);
  display:flex;flex-direction:column;align-items:center;
  gap:0;
  z-index:3;
  pointer-events:none;
  opacity:0;
  will-change:opacity;
  /* pill border wrapping the letters, like the reference */
  border:1px solid rgba(255,255,255,0.18);
  border-radius:999px;
  padding:12px 10px;
}
.overlap-word span{
  display:block;
  font-family:var(--font-body);
  font-size:clamp(9px,1vw,13px);
  font-weight:400;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:rgba(255,255,255,0.75);
  line-height:1.55;
}
.merge-nawf{
  font-family:var(--font-head);font-weight:400;
  font-size:clamp(34px,5.6vw,86px);line-height:1.08;letter-spacing:0;
  color:#fff;
  text-shadow:0 0 40px rgba(193,255,114,.5),0 0 90px rgba(255,215,94,.25);
  opacity:0;
  will-change:transform,opacity;
}
.merge-sub{
  /* anchored to the section, not the logo. It used to sit under the whole
     tagline block at 91vh, which read as a stray line rather than a caption
     for the mark. It sits under the tagline's closing line rather than beside
     the mark: the tagline is padded 47vh from the top of the section and sets
     two lines. Working the geometry through rather than eyeballing it: the
     47vh pad plus a flex-centred block of 2 x 1.12 x clamp(29px,5.9vw,144px)
     puts the last line's ink at roughly 87-88vh on every common screen, and
     the vh padding and vw type track each other so that barely moves. 87vh
     therefore sat right on it. 92vh clears the descenders with a few vh to
     spare and still leaves the label inside the section, which is
     overflow:hidden. */
  position:absolute;
  top:92vh;left:50%;
  transform:translateX(-50%);
  z-index:4;
  white-space:nowrap;
  font-family:var(--font-body);
  font-size:clamp(14px,1.3vw,18px);letter-spacing:.26em;text-transform:uppercase;
  color:var(--accent-2);
  opacity:0;
}

/* ── "We make AI emotional / not plastic." — post-merge tagline ── */
.emotion-tagline{
  /* full-screen layer sitting BEHIND the merge circle */
  position:absolute;
  inset:0;
  z-index:1;
  display:flex;align-items:center;justify-content:center;
  margin:0;
  /* dropped just far enough that the star's base kisses the top of line
     one — any higher and the star covers "AI" */
  padding:47vh 2vw 0;
  pointer-events:none;

  font-family:var(--font-head);
  font-weight:400;
  /* huge — line one spans nearly the full viewport width */
  font-size:clamp(29px,5.9vw,144px);
  /* tight — "not plastic." reads as the next line of the same sentence */
  line-height:1.12;
  letter-spacing:-0.015em;
  text-align:center;
  white-space:nowrap;

  /* transparent bold grey — reads through/behind the glow */
  color:rgba(158,161,158,0.26);

  opacity:0;
  filter:blur(24px);
  will-change:opacity,filter;
}

/* aithat */
.aithat{
  text-align:center;
  /* tall enough that the whole scene is on screen when it auto-plays, but
     no longer a full viewport: with the closing CTA gone it is a headline
     and one row of cards, and 100vh left a dead band under them. */
  min-height:clamp(520px,76vh,880px);
  display:flex;flex-direction:column;justify-content:center;align-items:center;
  overflow:hidden;          /* cards start off-screen — don't widen the page */
}
.aithat > *{width:100%}
.aithat-list{
  list-style:none;
  /* no gap: the hairline lives inside each step's own padding */
  display:grid;grid-template-columns:repeat(5,1fr);gap:0;
  /* nothing follows the row now, so the trailing margin would only push the
     centred block off true — the section's own padding is the bottom space */
  margin:56px auto 0;max-width:1320px;
}
/* No containers. The steps are separated by a single hairline in the gutter,
   drawn as a gradient so it fades out at both ends instead of stopping dead,
   with a soft bloom either side of it. Nothing is boxed, nothing is filled:
   the numeral and the white space do the grouping. */
.ai-card{
  position:relative;
  display:flex;flex-direction:column;gap:clamp(28px,4vh,58px);
  padding:clamp(10px,1.4vw,20px) clamp(16px,1.9vw,32px);
  min-height:clamp(190px,20vw,270px);
  text-align:left;
  background:none;border:0;border-radius:0;box-shadow:none;
  will-change:transform,opacity;
  /* NO transform transition here. GSAP flies these in from up to 620px below
     and 520px to the side; a CSS transition on transform interpolates toward
     every frame GSAP writes, so the card chases a moving target and is left
     stranded outside .aithat's overflow:hidden. The hover lift therefore
     lives on the children, which GSAP never touches. */
}
/* the hairline sits in the gutter before every step except the first */
.ai-card + .ai-card::before{
  content:"";
  position:absolute;left:0;top:6%;bottom:6%;
  width:1px;
  background:linear-gradient(to bottom,
    transparent 0%,
    color-mix(in srgb,var(--accent) 26%,transparent) 22%,
    color-mix(in srgb,var(--accent) 26%,transparent) 78%,
    transparent 100%);
  box-shadow:0 0 10px 0 color-mix(in srgb,var(--accent) 22%,transparent);
  transition:background .45s ease,box-shadow .45s ease;
}
.ai-card:hover + .ai-card::before,
.ai-card:hover::before{
  background:linear-gradient(to bottom,
    transparent 0%,
    color-mix(in srgb,var(--accent) 60%,transparent) 18%,
    color-mix(in srgb,var(--accent) 60%,transparent) 82%,
    transparent 100%);
  box-shadow:0 0 16px 0 color-mix(in srgb,var(--accent) 42%,transparent);
}
.ai-num{
  font-family:var(--font-head);font-weight:400;
  font-size:clamp(30px,3.1vw,50px);line-height:.9;
  letter-spacing:-.03em;
  padding-top:.1em;                      /* Boldonse paints above its line box */
  color:color-mix(in srgb,var(--accent) 52%,transparent);
  transition:color .4s ease;
}
.ai-card:hover .ai-num{color:var(--accent)}
.ai-copy{display:flex;flex-direction:column;gap:.55em;margin-top:auto}
.ai-card > .ai-copy > b{
  font-weight:300;text-transform:uppercase;
  font-size:clamp(14px,1.16vw,18px);
  letter-spacing:.05em;line-height:1.34;
  color:var(--ink);
}
.ai-copy p{font-size:clamp(12px,.92vw,14px);line-height:1.5;color:var(--mut)}
.ai-num,.ai-copy{transition:transform .45s cubic-bezier(.22,1,.36,1)}
.ai-card:hover .ai-num,
.ai-card:hover .ai-copy{transform:translateY(-6px)}
@media (prefers-reduced-motion:reduce){
  .ai-num,.ai-copy{transition:none}
  .ai-card:hover .ai-num,
  .ai-card:hover .ai-copy{transform:none}
}
@media (max-width:900px){
  .aithat-list{grid-template-columns:repeat(2,1fr)}
  /* two columns: the vertical rule only works between row neighbours, so
     the third and fifth steps start a new row and drop theirs */
  .ai-card{min-height:0}
  .ai-card:nth-child(odd)::before{display:none}
  .aithat-list li:last-child{grid-column:1/-1;aspect-ratio:16/6}
}

/* steps — a pinned deck: three near-fullscreen cards shuffle in one at a time */
.steps{
  min-height:100vh;
  display:flex;flex-direction:column;
  padding-top:clamp(110px,15vh,160px);
  padding-bottom:clamp(26px,5vh,60px);
  overflow:hidden;              /* cards start below the fold */
}
/* room above the stack for the pushed-back cards to peek into */
.steps-intro{margin-bottom:clamp(28px,5vh,58px);flex:none;white-space:nowrap;font-size:clamp(16px,4vw,54px)}
.step-stack{
  position:relative;
  flex:1 1 auto;min-height:0;
}
.step{
  --acc:var(--accent);
  position:absolute;inset:0;
  border-radius:clamp(16px,1.9vw,28px);
  background:var(--acc);
  color:var(--bg);
  padding:clamp(24px,3.8vw,64px);
  display:flex;flex-direction:column;
  overflow:hidden;
  will-change:transform;
  box-shadow:0 44px 92px -46px rgba(0,0,0,.85);
}
.step:nth-of-type(2){--acc:var(--accent-2)}
.step:nth-of-type(3){--acc:var(--accent-3)}
/* the mark fills the card's empty half as a tonal watermark */
.step-mark{
  position:absolute;right:-4%;bottom:-12%;
  width:clamp(210px,33vw,520px);height:auto;
  opacity:.13;filter:brightness(0);
  pointer-events:none;user-select:none;
}
.step-head{
  display:flex;align-items:baseline;justify-content:space-between;
  gap:16px;
}
.step-title{
  font-family:var(--font-head);font-weight:400;
  font-size:clamp(26px,3.4vw,52px);
  color:var(--bg);
}
/* small ordinal so the card reads as a step without a heavy label */
.step-index{
  font-family:var(--font-body);
  font-size:clamp(11px,.95vw,14px);letter-spacing:.16em;
  color:rgba(24,25,28,.42);
}
/* the service lines are the point of the card — they get the display size,
   one per row, separated by hairlines that run the full card width */
.step-lines{
  list-style:none;
  margin-top:clamp(14px,2.4vh,30px);
  border-top:1px solid rgba(24,25,28,.22);
}
.step-lines li{
  color:var(--bg);font-weight:400;
  font-size:clamp(21px,3.1vw,46px);
  line-height:1.2;letter-spacing:-0.018em;
  padding:clamp(12px,1.9vh,24px) 0;
  border-bottom:1px solid rgba(24,25,28,.22);
  max-width:22ch;
}
.step-desc{
  color:rgba(24,25,28,.7);
  font-size:clamp(14px,1.2vw,18px);max-width:46ch;
  margin-top:auto;padding-top:clamp(16px,2.6vh,32px);
}
@media (max-width:900px){
  /* Cards already on the table settle to yPercent:-5*depth with a matching
     scale-down. transformOrigin is 50% 50%, so shrinking pulls the top edge
     back down by half the height it loses and the strip left showing is
     roughly half the offset. Desktop's large padding keeps that strip empty,
     so it reads as a card edge; at 24px the strip cut through the title and
     sliced it in half. Hold the title below the peek band instead. */
  .step{padding:46px 20px 26px}
  .step-lines li{max-width:none;font-size:clamp(20px,5.4vw,30px)}
  .step-desc{max-width:none}
  .step-mark{width:clamp(160px,52vw,300px);opacity:.11}
}

/* ── mobile: shrink the pinned step boards ──
   .step is absolute inset:0 inside .step-stack, and the stack is
   flex:1 1 auto — so each card grew to whatever height the pinned
   100vh section had left over, i.e. nearly the whole phone screen.
   Because .step-desc is pushed down by margin-top:auto, that surplus
   showed up as a large empty band in the middle of the card. Giving
   the stack a fixed, smaller height sizes the cards down with it;
   the deck's yPercent animation is relative to card height, so the
   shuffle still lines up. Desktop (>700px) keeps flex:1 1 auto. */
@media (max-width:700px){
  /* the deck is a fixed 470px inside a full-screen pinned section, so the
     leftover height collects under it — trim the tail it adds to the seam */
  .steps{min-height:100svh;padding-top:clamp(88px,12vh,120px);
         padding-bottom:clamp(14px,3vh,34px)}
  .step-stack{flex:0 0 auto;height:min(60vh,470px)}
  /* the deck already leaves room above itself for the pushed-back cards to
     peek into, so the headline does not need a large margin of its own */
  /* Two problems met here. The line wrapped because 4vw resolves to ~16.5px
     on a 412px screen and 37 characters of Boldonse at that size overrun
     the ~90vw available. And the cards already on the table settle to
     yPercent -5*depth, climbing up to ~47px above the stack, which a
     ~19px margin could not keep clear of — so the deck covered the
     second line. Smaller type holds it to one line; the larger margin
     keeps the risen cards off it. */
  .steps-intro{margin-bottom:clamp(26px,4.5vh,46px);
               white-space:nowrap;font-size:clamp(12px,3.5vw,54px)}
}

/* influence */
.influence{
  text-align:center;
  /* full-height so the pinned fill scene fills the screen */
  min-height:100vh;
  display:flex;flex-direction:column;justify-content:center;align-items:center;
}
.influence > *{width:100%}

/* ── "reimagined." fills with lime like water rising in a bottle ── */
.display em.fillword{
  position:relative;display:inline-block;
  color:var(--ink);          /* starts identical to "Influence," */
  font-style:normal;
  /* Boldonse overflows its line box; .fw-fill clips to this element, so pad
     the box out to the real glyph extent and cancel the layout cost. */
  padding-block:.20em .30em;
  margin-block:-.20em -.30em;
}
.fw-fill,
.stats-fill{
  position:absolute;left:0;bottom:0;
  width:100%;height:0;       /* GSAP drives this 0% → 100% on scroll */
  overflow:hidden;
  pointer-events:none;
  /* two mask layers: a rippling wave crest on top, solid body beneath —
     gives the fill a moving waterline instead of a flat cut */
  -webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 24' preserveAspectRatio='none'%3E%3Cpath d='M0,12 C15,2 25,22 40,12 C55,2 65,22 80,12 C95,2 105,22 120,12 L120,24 L0,24 Z' fill='%23000'/%3E%3C/svg%3E"),linear-gradient(#000 0 0);
  mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 24' preserveAspectRatio='none'%3E%3Cpath d='M0,12 C15,2 25,22 40,12 C55,2 65,22 80,12 C95,2 105,22 120,12 L120,24 L0,24 Z' fill='%23000'/%3E%3C/svg%3E"),linear-gradient(#000 0 0);
  -webkit-mask-size:240px 18px,100% calc(100% - 17px);
  mask-size:240px 18px,100% calc(100% - 17px);
  -webkit-mask-repeat:repeat-x,no-repeat;
  mask-repeat:repeat-x,no-repeat;
  -webkit-mask-position:0 0,0 100%;
  mask-position:0 0,0 100%;
  animation:fwRipple 6s linear infinite;
  animation-play-state:paused;   /* resumed by ScrollTrigger when in view */
}
.fw-fill > span{
  position:absolute;left:0;bottom:.30em;   /* matches .fillword padding-bottom */
  display:block;white-space:nowrap;
  color:var(--accent);           /* electric lime, matching the marker circle */
}
.fw-fill.live,
.stats-fill.live{animation-play-state:running}
@keyframes statsRipple{
  from{-webkit-mask-position:0 0,0 100%;mask-position:0 0,0 100%}
  to{-webkit-mask-position:520px 0,0 100%;mask-position:520px 0,0 100%}
}
@keyframes fwRipple{
  from{-webkit-mask-position:0 0,0 100%;mask-position:0 0,0 100%}
  to{-webkit-mask-position:240px 0,0 100%;mask-position:240px 0,0 100%}
}

/* hand-drawn red pen strike */
/* production tagline — this is the section's headline, so it carries weight */
.aithat-head{
  font-weight:400;
  font-size:clamp(13px,3.4vw,50px);
  letter-spacing:-.005em;
  text-transform:uppercase;
  white-space:nowrap;
  /* Boldonse overflows a 1.0 line box; the reveal mask is sized to this
     element's box, so anything outside it gets sheared flat. Keep it roomy. */
  line-height:1.28;
  padding-block:.06em;
  color:var(--ink);
}
.aithat-head em{font-weight:400}
.aithat .aithat-head em{color:var(--accent)}

/* hand-drawn marker circle */
.circled{position:relative;display:inline-block;padding:0 .34em}
.circled svg{
  position:absolute;
  /* Boldonse is wider and taller in its box than the face this was drawn
     for, so the ellipse needs noticeably more clearance to stay off the caps. */
  left:-0.48em;top:-0.40em;
  width:calc(100% + 0.96em);height:calc(100% + 0.80em);
  overflow:visible;pointer-events:none;
}
.circled svg path{
  fill:none;
  stroke:#8B5CF6;
  stroke-width:5.5;
  stroke-linecap:round;
  stroke-linejoin:round;
  stroke-dasharray:1;
  stroke-dashoffset:1;
  opacity:.9;
}
/* the banner's circle rides on dark footage, so it takes the lime rather
   than the violet the light sections use */
.circled--lime svg path{stroke:var(--accent);opacity:1}
/* the parenthetical in the influence tagline, carried over from the banner */
.influence-body p span{color:var(--accent)}

.influence-body{margin-top:56px;display:flex;flex-direction:column;gap:14px;align-items:center}
.influence-body h3{font-family:var(--font-head);font-size:clamp(21px,2.6vw,35px);font-weight:400;line-height:1.2}
.influence-body p{max-width:480px;color:var(--mut)}

/* ── mobile: let the influence scene fill its screen ──
   The section is pinned for the waterline fill, so it has to stay a full
   screen tall, and its content is centred inside that screen. The copy was
   only ~250px of an ~800px viewport, so centring split the remainder into
   two large voids. Shifting the group with padding only moved the void from
   below the copy to above it; the fix is to give the type enough size to
   carry the screen. svh also stops the section over-measuring itself
   against the address bar. */
@media (max-width:700px){
  /* the phone build pins this scene too (see js/main.js), so it has to hold
     a full screen — a pinned box shorter than the viewport would let the
     gate video show underneath while it is held. svh measures the screen
     actually available, and the enlarged type below fills it. */
  /* No longer pinned here (see js/main.js), so the section does not have to
     hold a screen it cannot fill. The copy is about half a phone viewport,
     and while this was pinned that remainder had to go somewhere — above
     the copy, below it, or between its two halves — and read as a gap in
     every arrangement. Sized to its content there is no remainder at all. */
  .influence{min-height:auto;justify-content:flex-start;
             padding:clamp(58px,10vh,110px) var(--pad) clamp(52px,9vh,100px)}
  /* .display.xl bottoms out at its 38px floor on a phone (7vw is only
     ~29px there), so the whole composition came to ~250px inside a
     full-screen section and centring split the ~70vh remainder into two
     voids. Letting the headline scale with the viewport fills the screen
     rather than moving the emptiness around. */
  .influence .display.xl{font-size:clamp(44px,13vw,74px);line-height:1.16}
  .influence-body{margin-top:clamp(26px,5vh,46px)}
  .influence-body h3{font-size:clamp(23px,6vw,32px)}
  .influence-body p{max-width:34ch}
}

/* stats */
.stats{
  position:relative;overflow:hidden;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  display:flex;flex-wrap:wrap;align-items:center;gap:48px;justify-content:space-between;
}
.stats > *:not(.stats-fill){position:relative;z-index:2}
/* lime water rising inside the band — translucent so the copy stays legible
   at every fill level (a solid wash would swallow the numbers) */
.stats-fill{
  z-index:1;
  /* wider, taller crest + slower drift: on a full-width band a small fast
     wave reads as sideways travel rather than a rising waterline */
  -webkit-mask-size:520px 30px,100% calc(100% - 28px);
  mask-size:520px 30px,100% calc(100% - 28px);
  animation:statsRipple 9s linear infinite;   /* tile width must match the shift */
  animation-play-state:paused;
  background:linear-gradient(to top,
    rgba(159,193,49,.34) 0%,
    rgba(159,193,49,.20) 55%,
    rgba(159,193,49,.10) 100%);
}
.stats-note{
  max-width:520px;
  font-size:clamp(19px,2vw,27px);line-height:1.5;
  color:var(--ink);font-weight:400;
}
.stats-row{display:flex;gap:clamp(48px,7vw,104px)}
.stat-num{
  font-family:var(--font-head);font-weight:400;
  font-size:clamp(40px,5.4vw,74px);line-height:1.08;color:var(--ink);
  font-variant-numeric:tabular-nums;
}
.stat:nth-child(1) .stat-num{color:var(--accent)}
.stat:nth-child(2) .stat-num{color:var(--ink)}
.stat-label{display:block;margin-top:10px;font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:#b9bcb2}

/* services — pinned horizontal slide deck */
/* This section pins with its top flush to the viewport, so its top padding is
   the ONLY thing between the headline and the screen edge — and it has to
   clear the fixed nav too. 10vh was not enough at laptop heights and the caps
   ran into the edge. */
.services{padding-top:clamp(104px,17vh,200px);padding-bottom:6vh}
/* The 760px cap and the nowrap fought each other: the line was forbidden to
   wrap, so once it outgrew the gutters it ran off the page and body's
   overflow-x:hidden clipped the tail silently — no scrollbar, just a cut
   word. Let it wrap instead; text-wrap:balance keeps the two lines even
   when it does, and a wide screen still holds it on one. */
.services>.display{
  max-width:min(1100px,100%);text-wrap:balance;
  /* headroom for Boldonse's ascenders, which sit above the line box */
  padding-top:.12em;
}
.slide-viewport{
  width:min(100%,1440px);
  margin:clamp(52px,7.5vh,104px) auto 0;   /* sits lower, clear of the headline */
  overflow:hidden;
  border:1px solid rgba(255,255,255,.14);
  border-radius:24px;
  background:#111114;
  box-shadow:0 32px 90px -48px rgba(0,0,0,.9);
}
.slide-track{
  display:flex;
  width:400%;
  will-change:transform;
}
.slide{
  --acc:var(--accent);
  position:relative;
  flex:0 0 25%;
  min-height:clamp(430px,56vh,680px);
  display:flex;align-items:flex-end;
  padding:clamp(26px,3vw,48px);
  overflow:hidden;
  isolation:isolate;
  border-right:1px solid rgba(255,255,255,.12);
  background:
    linear-gradient(135deg,rgba(255,255,255,.06),transparent 34%),
    var(--panel);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.08);
}
.slide:nth-child(2){--acc:var(--accent-2)}
.slide:nth-child(3){--acc:var(--accent-3)}
.slide:nth-child(4){--acc:var(--accent-2)}
.slide{background:var(--panel)}
.slide-net{
  position:absolute;inset:0;z-index:0;
  width:100%;height:100%;
  opacity:.7;
}
.slide::before{
  content:"";position:absolute;inset:0;z-index:1;
  background:linear-gradient(180deg,rgba(10,10,12,.12) 0%,rgba(10,10,12,.08) 34%,rgba(10,10,12,.92) 100%);
}
.slide::after{
  content:"";position:absolute;z-index:1;
  width:clamp(220px,32vw,520px);height:clamp(220px,32vw,520px);
  right:-14%;top:-20%;
  border-radius:50%;
  background:radial-gradient(circle,color-mix(in srgb,var(--acc) 28%,transparent),transparent 68%);
  filter:blur(12px);
  opacity:.8;
  pointer-events:none;
}
.slide-body{
  position:relative;z-index:2;
  width:100%;
  display:grid;grid-template-columns:1.15fr 1fr;
  gap:clamp(28px,4vw,64px);
  align-items:end;
}
.slide-left{display:flex;flex-direction:column;gap:14px}
.slide-right{
  display:flex;flex-direction:column;gap:18px;
  border-left:1px solid color-mix(in srgb,var(--acc) 70%,rgba(255,255,255,.2));
  padding-left:clamp(24px,3vw,48px);
  padding-bottom:6px;
}
@media (max-width:800px){
  .slide-body{grid-template-columns:1fr;align-items:start}
  .slide-right{border-left:none;padding-left:0;border-top:1px solid rgba(255,255,255,.18);padding-top:18px}
}
.slide-body .label{color:var(--acc);font-size:14px;letter-spacing:.18em}
.slide-body h3{
  font-family:var(--font-head);font-weight:400;
  max-width:620px;
  font-size:clamp(27px,3.3vw,47px);line-height:1.3;
  letter-spacing:-.005em;
  color:#fff;
}
.slide-body p{
  color:#E4E4E6;
  font-size:clamp(18px,1.6vw,24px);line-height:1.5;
  max-width:520px;
}
.slide-body a{
  align-self:flex-start;
  color:var(--acc);font-weight:400;font-size:16px;
  border-bottom:1px solid color-mix(in srgb,var(--acc) 65%,transparent);
  padding-bottom:4px;
  transition:border-color .3s,color .3s;
}
.slide-body a:hover{color:#fff;border-bottom-color:#fff}
.slide-num{
  position:absolute;top:clamp(24px,3vw,44px);right:clamp(24px,3vw,44px);z-index:2;
  font-family:var(--font-body);
  font-size:13px;letter-spacing:.16em;color:rgba(255,255,255,.78);
  padding:8px 10px;
  border:1px solid rgba(255,255,255,.16);
  border-radius:999px;
  background:rgba(10,10,12,.28);
  backdrop-filter:blur(8px);
}

/* math — flip-tile columns with computing figures */
.math-grid{
  display:grid;grid-template-columns:repeat(4,1fr);gap:18px;
  margin-top:64px;
  perspective:1200px;
}
.math-card{
  --acc:var(--accent);
  border:1px solid var(--line);border-radius:20px;
  background:var(--panel);
  padding:38px 28px;
  display:flex;flex-direction:column;gap:14px;
  transform-style:preserve-3d;
  will-change:transform,opacity;
  transition:border-color .3s,box-shadow .5s;
}
.math-card:nth-child(2){--acc:var(--accent-2)}
.math-card:nth-child(3){--acc:var(--accent-3)}
.math-card:nth-child(4){--acc:var(--accent-2)}
.math-card:hover{
  border-color:var(--acc);
  box-shadow:0 24px 56px -28px color-mix(in srgb,var(--acc) 45%,transparent);
}
.math-fig{
  font-family:var(--font-head);font-weight:400;
  font-size:clamp(24px,2.6vw,42px);line-height:1.1;
  color:var(--acc);
  font-variant-numeric:tabular-nums;
  min-height:1em;
}
.math-label{
  font-size:15px;color:var(--mut);font-weight:400;
}
@media (max-width:900px){
  .math-grid{grid-template-columns:1fr 1fr}
}
@media (max-width:560px){
  /* One-line headlines that had no escape hatch. body{overflow-x:hidden}
     means an overflowing line is silently sheared off, with no scrollbar to
     hint at it, so both are released to wrap on small screens. */
  .emotion-tagline{white-space:normal}
  .math-grid{grid-template-columns:1fr}
}
/* This one needs releasing earlier than the rest. The line runs to 70
   characters and its font-size sits on the 13px floor anywhere below ~700px,
   so between roughly 560 and 620 it still overran the column while nowrap
   was in force. body{overflow-x:hidden} shears an overrunning nowrap line
   and leaves no scrollbar to show for it, so it failed silently on larger
   phones and small tablets. */
@media (max-width:700px){
  .reality > .display{white-space:normal;text-wrap:balance}
}

/* roi — full-screen, scroll-driven */
.roi{
  min-height:100vh;
  display:grid;grid-template-columns:.95fr 1.4fr;
  gap:clamp(32px,5vw,80px);
  align-items:center;
}
.roi-left{display:flex;flex-direction:column;gap:clamp(24px,3.4vh,38px)}
.roi-right{display:flex;flex-direction:column;justify-content:center;width:100%}
.roi-note{max-width:46ch;color:var(--mut);margin:0;font-size:clamp(15px,1.1vw,17px);line-height:1.6}
.roi-graph{margin:0;display:flex;flex-direction:column;gap:clamp(42px,7.4vh,86px);width:100%}
/* velocity formula — fraction, operator, term, then the result it defines */
.roi-formula{display:flex;flex-direction:column;gap:clamp(14px,2vh,22px);margin-top:clamp(18px,3vh,34px)}
.rf-eq{
  display:flex;align-items:center;gap:clamp(20px,2.6vw,38px);
  font-family:var(--font-head);
}
.rf-frac{display:flex;flex-direction:column;align-items:center;gap:12px}
.rf-frac b{
  font-size:clamp(15px,1.35vw,21px);
  color:var(--ink);
}
.rf-frac i{display:block;width:100%;height:2px;background:var(--ink);border-radius:2px}
.rf-op{
  font-size:clamp(20px,2.1vw,30px);font-weight:400;
  color:var(--ink);
}
.rf-term{
  font-size:clamp(15px,1.35vw,21px);
  color:var(--ink);
}
.rf-label{
  font-family:var(--font-body);
  font-size:12px;letter-spacing:.2em;text-transform:uppercase;
  color:var(--accent-2);
}
/* scale beneath the bars */
.roi-axis{
  display:flex;justify-content:space-between;
  /* offset to sit under the bar track, matching the grid above */
  margin-left:calc(clamp(128px,12vw,190px) + clamp(14px,1.6vw,26px));
  margin-right:calc(clamp(52px,5vw,84px) + clamp(14px,1.6vw,26px));
  margin-top:clamp(22px,3.4vh,38px);
  padding-top:16px;border-top:1px solid var(--line);
  font-family:var(--font-body);
  font-size:11px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--mut);
}

.roi-bar{
  display:grid;grid-template-columns:clamp(128px,12vw,190px) 1fr clamp(52px,5vw,84px);
  align-items:center;gap:clamp(14px,1.6vw,26px);
  --p:0;
}
.roi-name{font-size:clamp(14px,1.1vw,17px);color:var(--mut);font-weight:400;line-height:1.3}
.roi-bar i{
  display:block;height:clamp(24px,3.6vh,42px);border-radius:999px;background:var(--line);
  position:relative;overflow:hidden;
}
.roi-bar i::after{
  content:"";position:absolute;inset:0;
  width:calc(var(--w) * var(--p));
  background:var(--mut);border-radius:999px;
}
.roi-nawf i::after{background:var(--accent)}
.roi-bar b{
  font-family:var(--font-head);font-weight:400;
  font-size:clamp(18px,1.9vw,30px);line-height:1.1;
  font-variant-numeric:tabular-nums;text-align:right;
}
.roi-nawf b{color:var(--accent)}

/* usecases */
/* the divider hands over a full viewport of clearance already, so the
   grid's own top padding on top of it read as a gap, not as rhythm */
.usecases{padding-top:clamp(28px,5vh,64px)}
.usecase-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--line);border:1px solid var(--line);border-radius:20px;overflow:hidden;margin-top:56px}
.usecase-grid article{
  --acc:var(--accent);
  position:relative;overflow:hidden;
  background:var(--bg);padding:32px 28px;min-height:230px;
  transition:transform .45s cubic-bezier(.22,1,.36,1),box-shadow .45s,background .3s;
}
.usecase-grid article:nth-child(3n+2){--acc:var(--accent-2)}
.usecase-grid article:nth-child(3n){--acc:var(--accent-3)}
/* the still carries the card now that the hover clips are gone: it is on
   from the start, held back by the tint below so the copy stays legible,
   and lifts a little on hover instead of appearing out of nowhere */
.usecase-grid .uc-bg{
  position:absolute;inset:0;z-index:0;
  background-size:cover;background-position:center 15%;
  opacity:.34;transform:scale(1.02);
  transition:opacity .5s ease,transform 1.1s cubic-bezier(.22,1,.36,1);
}
.usecase-grid article::before{
  content:"";position:absolute;inset:0;z-index:1;
  background:linear-gradient(to top,rgba(10,10,12,.92) 30%,rgba(10,10,12,.45));
  opacity:1;transition:opacity .5s ease;
}
.usecase-grid h3,.usecase-grid p,.usecase-grid .uc-arrow{position:relative;z-index:2}
.usecase-grid article:hover{
  transform:translateY(-8px) scale(1.02);
  box-shadow:0 26px 60px -24px color-mix(in srgb,var(--acc) 40%,transparent);
  z-index:3;
}
.usecase-grid article:hover .uc-bg{opacity:.62;transform:scale(1.06)}
.usecase-grid article:hover h3{color:var(--acc)}
.usecase-grid h3{font-family:var(--font-head);font-size:17px;font-weight:400;line-height:1.25;margin-bottom:10px;transition:color .35s}
.usecase-grid p{font-size:13.5px;color:var(--mut);transition:color .35s}
.usecase-grid article:hover p{color:#c9c9ce}
.uc-arrow{
  position:absolute;top:24px;right:24px;
  font-size:18px;color:var(--acc);
  opacity:0;transform:translate(-6px,6px);
  transition:opacity .35s,transform .45s cubic-bezier(.22,1,.36,1);
}
.usecase-grid article:hover .uc-arrow{opacity:1;transform:translate(0,0)}

/* ============ TECH GRID BACKDROP — canvas driven ============ */
.tail-wrap{position:relative}
.tail-wrap > section{position:relative;z-index:1}
.tech-grid{
  position:fixed;inset:0;z-index:0;
  pointer-events:none;
  overflow:hidden;
}
.tech-grid canvas{
  position:absolute;inset:0;
  width:100%;height:100%;
  display:block;
}

/* trusted / ideas / connect */
.trusted{text-align:center;border-top:1px solid var(--line)}

/* ── sponsor marquee ──
   The marks are white artwork on transparency, so they sit straight on the
   page's own ground rather than on a white band — a white strip would both
   cut a bright block into a dark page and, since the artwork is white,
   erase most of the logos. They run quiet at .42 and come up to full on
   hover, so the row reads as texture until you look at it.
   Same technique as .tag-track: the set is laid down twice and the track
   travels exactly -50%, so the loop closes on itself with no seam. */
.sponsors{
  margin-top:clamp(34px,6vh,72px);
  margin-inline:calc(var(--pad) * -1);
  overflow:hidden;
  /* a narrow softening at each end. A wider fade dimmed whole logos on the
     way in and out, which read as them being cut rather than the row easing
     into the page. */
  -webkit-mask-image:linear-gradient(to right,transparent,#000 4%,#000 96%,transparent);
  mask-image:linear-gradient(to right,transparent,#000 4%,#000 96%,transparent);
}
.sponsor-track{
  display:inline-flex;align-items:center;
  gap:clamp(30px,5vw,74px);
  padding-right:clamp(30px,5vw,74px);
  white-space:nowrap;
  animation:sponsorscroll 54s linear infinite;
  will-change:transform;
}
.sponsors:hover .sponsor-track{animation-play-state:paused}
/* a fixed slot per logo: these marks run from 5.5:1 wordmarks to nearly
   square, so sizing on height alone would leave the wide ones towering over
   the compact ones. The box is constant and each mark is fitted inside it. */
.sponsor{
  flex:none;
  display:grid;place-items:center;
  width:clamp(82px,10vw,120px);
  /* the set runs from 5.5:1 wordmarks to 1.2:1, so the slot keeps some
     height or the squarer marks shrink to nothing beside the wide ones */
  height:clamp(30px,3.5vw,42px);
  /* Inset on all four sides. Horizontal keeps the wordmarks off their
     neighbours; vertical matters more than it looks — the marks are trimmed
     to their own bounds, so a tall one like NINE WATT fills the slot's full
     height and the tail of its "House" script lands on the very bottom edge,
     which reads as clipped even though object-fit is not cropping anything.
     A few pixels of air and it clearly ends inside the box. */
  padding:6px 6px;
}
.sponsor img{
  /* fill the slot and let object-fit do the fitting. Sizing by max-width and
     max-height instead left the taller marks scaling to the slot's WIDTH —
     NINE WATT came out 121px tall in a 46px box and overflow:hidden cut the
     rest off. contain can never overflow, whatever the mark's ratio. */
  width:100%;height:100%;
  object-fit:contain;object-position:center;
}
@keyframes sponsorscroll{
  from{transform:translateX(0)}
  to{transform:translateX(-50%)}
}
@media (max-width:700px){
  .sponsors{margin-top:clamp(26px,4.5vh,48px)}
  /* fewer logos fit, so the same speed reads as faster — lengthen the cycle */
  .sponsor-track{animation-duration:38s;gap:34px;padding-right:34px}
  .sponsor{width:88px;height:34px;padding:4px 5px}
}
@media (prefers-reduced-motion:reduce){
  .sponsor-track{animation:none}
  /* with no travel the track would sit at its start; let it wrap instead so
     every logo is reachable rather than half the set hanging off-screen */
  .sponsors{overflow-x:auto;-webkit-mask-image:none;mask-image:none}
  .sponsor-track{flex-wrap:wrap;justify-content:center;white-space:normal}
}
.ideas{
  min-height:100vh;
  display:flex;align-items:center;
  overflow:hidden;              /* entrances start off-screen */
}
.ideas-grid{
  width:100%;
  display:grid;grid-template-columns:1fr 1fr;
  gap:clamp(18px,2.4vw,40px);   /* halves sit closer together */
  align-items:center;
}
.ideas-copy{text-align:left}
.ideas-copy .display{margin:0}
/* right-hand media card — same video + tint treatment as the other cards */
.ideas-media{
  position:relative;overflow:hidden;
  aspect-ratio:4/3.4;
  border:1px solid var(--line);border-radius:22px;
  background:#07070a;
  display:flex;align-items:flex-end;
  will-change:transform;
}
.ideas-vid{
  position:absolute;inset:0;z-index:0;
  width:100%;height:100%;object-fit:cover;
  opacity:.42;transform:scale(1.05);
  transition:opacity .6s,transform 1.1s cubic-bezier(.22,1,.36,1);
}
.ideas-tint{
  position:absolute;inset:0;z-index:1;
  background:linear-gradient(180deg,
    rgba(6,6,9,.42) 0%,
    rgba(6,6,9,.70) 48%,
    rgba(6,6,9,.93) 100%);
}
.ideas-media:hover .ideas-vid{opacity:.66;transform:scale(1)}
/* copy sits over the footage */
.ideas-note{
  position:relative;z-index:2;
  padding:clamp(24px,3vw,44px);
  display:flex;flex-direction:column;
  gap:clamp(10px,1.4vh,16px);
  text-align:left;
}
.ideas-lead{
  font-size:clamp(18px,1.8vw,27px);
  line-height:1.34;letter-spacing:-.015em;
  color:var(--ink);
  text-wrap:balance;
}
.ideas-sub{
  font-size:clamp(14px,1.05vw,17px);
  line-height:1.6;color:#a7a9a2;
  text-wrap:pretty;
}
/* "ideas" stays white — only "real." carries the lime */
.ideas .display em{color:var(--ink)}
@media (max-width:900px){
  /* the two headlines sit either side of a section seam, so the space
     between them is .trusted's bottom padding plus .ideas' top padding —
     both from the global clamp(80px,12vh,160px), which stacks to roughly
     190px on a phone. Trim just the two edges that meet; the outer edges
     of each section keep the normal rhythm. */
  .trusted{padding-bottom:clamp(28px,5vh,54px)}
  .ideas{min-height:auto;padding-top:clamp(28px,5vh,54px)}
  .ideas-grid{grid-template-columns:1fr;gap:34px}
  .ideas-copy{text-align:center}
  .ideas-media{aspect-ratio:4/3}
}
/* "real." lands like a slot-machine reel, then breathes */
.real-wrap{
  position:relative;display:inline-block;
  /* the reel is heading text, so it takes the primary lime like every other
     accented word on the page — accent-2 is background-only by contract */
  color:var(--accent);
  /* clip-path, not overflow:hidden — overflow would move the inline-block's
     baseline to its bottom edge and drop the word off the headline's line */
  clip-path:inset(0);
  will-change:transform;
}
/* invisible copy holds the width, height and baseline while the reel spins */
.real-ghost{visibility:hidden}
.real-reel{
  position:absolute;top:0;left:0;width:100%;
  will-change:transform;
}
.real-reel span{display:block}
/* breathing only starts once the reel has settled */
.real-wrap.spun{animation:word-breathe 2.4s ease-in-out infinite}
@keyframes word-breathe{
  0%,100%{transform:scale(1)}
  50%{transform:scale(1.07)}
}
.connect{
  text-align:center;
  min-height:100vh;
  display:flex;flex-direction:column;align-items:center;
  padding-top:14vh;padding-bottom:0;
}
.connect-note{
  font-family:var(--font-body);
  font-size:11px;letter-spacing:.2em;text-transform:uppercase;
  color:var(--accent-2);margin-top:22px;
}
.connect .btn{margin-top:26px}
.connect-strip{
  margin-top:auto;
  width:calc(100% + var(--pad) * 2);
  margin-inline:calc(var(--pad) * -1);
  display:flex;justify-content:center;align-items:flex-end;
  gap:clamp(12px,2vw,28px);
  padding-top:8vh;
}
.cn-img{
  position:relative;overflow:hidden;
  width:clamp(140px,20vw,320px);
  height:var(--h,40vh);
  border-radius:8px 8px 0 0;
  transition:transform .5s cubic-bezier(.22,1,.36,1);
}
.cn-img img{
  width:100%;height:100%;object-fit:cover;object-position:center top;display:block;
  filter:grayscale(1) contrast(1.2) brightness(.92);
  transition:filter .6s ease;
}
/* halftone dots + fade into the page background */
.cn-img::before{
  content:"";position:absolute;inset:0;z-index:1;
  background-image:radial-gradient(rgba(0,0,0,.4) 1px,transparent 1.4px);
  background-size:4px 4px;
  pointer-events:none;
}
.cn-img::after{
  content:"";position:absolute;inset:0;z-index:2;
  background:linear-gradient(to top,transparent 55%,var(--bg));
  pointer-events:none;
}
.cn-img:hover{transform:translateY(-10px)}
.cn-img:hover img{filter:grayscale(0) contrast(1.05) brightness(1)}
@media (max-width:700px){
  /* .connect is a 100vh flex column and the strip carries margin-top:auto,
     so it is pinned to the bottom edge and every bit of unused height opens
     up between the button and the images. The copy is short on a phone and
     the tiles are scaled to 60% below, so that space was most of a screen.
     Sizing the section to its content and swapping the auto margin for a
     real one closes it; padding-bottom stays 0 so the tiles still sit flush
     on the section's bottom edge. */
  .connect{min-height:auto;padding-top:clamp(54px,9vh,108px)}
  .connect-strip{flex-wrap:nowrap;margin-top:clamp(26px,5vh,56px);padding-top:0}
  .cn-img{width:24vw;height:calc(var(--h,40vh) * .6)}
}

/* footer */
.footer{
  border-top:1px solid var(--line);
  padding:clamp(56px,9vh,110px) var(--pad) 0;
  overflow:hidden;                 /* the wordmark is cropped by this */
}
.footer-top{
  display:grid;grid-template-columns:1.1fr 1.9fr;
  gap:clamp(36px,6vw,90px);
}
.footer-brand{display:flex;flex-direction:column;gap:22px;max-width:380px}
/* same mark + wordmark lockup as the navbar.
   align-self matters: .footer-brand is a column flex container, so its
   cross axis is horizontal and items stretch to full width by default —
   that was flattening the square mark into a 380px-wide smear. */
.footer-brand .footer-logo{
  display:flex;align-items:center;gap:12px;
  align-self:flex-start;
}
.footer-brand .logo-mark{height:34px;width:auto;display:block}
.footer-brand .logo-word{height:18px;width:auto;display:block}
.footer-brand p{color:var(--mut);font-size:15px;line-height:1.6}
.footer-cols{
  display:grid;grid-template-columns:repeat(3,1fr);
  gap:clamp(24px,4vw,56px);
}
.footer-cols ul{list-style:none;margin-top:20px;display:flex;flex-direction:column;gap:13px}
.footer-cols a{
  font-size:15px;color:var(--ink);
  transition:color .25s;
}
.footer-cols a:hover{color:var(--accent-2)}
.footer-legal{
  display:flex;align-items:center;justify-content:space-between;
  flex-wrap:wrap;gap:14px;
  margin-top:clamp(48px,7vh,90px);
  padding-top:22px;border-top:1px solid var(--line);
  font-family:var(--font-body);
  font-size:11px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--mut);
}
.footer-legal-links{display:flex;gap:22px}
.footer-legal a{transition:color .25s}
.footer-legal a:hover{color:var(--accent-2)}
/* oversized wordmark bled off the bottom edge — only the top half shows.
   3604x1237 art; the ratio below crops it just past the midline. */
.footer-word{
  margin-top:clamp(34px,6vh,72px);
  aspect-ratio:3604 / 760;
  overflow:hidden;
  line-height:0;
}
.footer-word img{
  /* cover + top anchoring crops from the bottom while guaranteeing the
     wordmark keeps its aspect ratio — height:auto was letting it squash */
  width:100%;height:100%;display:block;
  object-fit:cover;object-position:center top;
  opacity:.92;
}
.contact-footer{
  width:100vw;
  margin-left:calc((100% - 100vw) / 2);
}
@media (max-width:900px){
  .footer-top{grid-template-columns:1fr;gap:44px}
  .footer-cols{grid-template-columns:repeat(2,1fr);gap:32px}
  .footer-word{aspect-ratio:3604 / 760}
}

/* ============ MEN / WOMEN GATE (62management-style split) ============ */
.gate-section{
  display:block;                 /* one full-width panel, no split */
  min-height:82vh;padding:0;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);
}
.gate{
  position:relative;overflow:hidden;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:22px;
  padding:80px var(--pad);
}
.gate.solo{min-height:82vh;text-align:center;color:inherit}
.gate-bg{
  position:absolute;inset:0;
  background-size:cover;background-position:center top;
  opacity:0;transform:scale(1.06);
  transition:opacity .6s ease,transform 1.2s cubic-bezier(.22,1,.36,1);
}
.gate::after{
  content:"";position:absolute;inset:0;
  background:linear-gradient(to top,rgba(10,10,12,.82),rgba(10,10,12,.25));
  opacity:0;transition:opacity .6s ease;
}
.gate-vid{
  position:absolute;inset:0;
  width:100%;height:100%;object-fit:cover;
  opacity:0;transform:scale(1.05);
  transition:opacity .6s ease,transform 1.2s cubic-bezier(.22,1,.36,1);
  pointer-events:none;
}
.gate:hover .gate-vid.on{opacity:1;transform:scale(1)}
.gate:hover .gate-bg{opacity:1;transform:scale(1)}
.gate:hover::after{opacity:1}

/* ── ambient gate: the banner film runs behind the panel at rest, not on
   hover. It only fades up once frames are actually playing (.on), so the
   still underneath covers the gap instead of a black rectangle. The scrim
   is always on here — white type over moving footage needs it — and it
   deepens on hover so the CTA still has somewhere to land. */
.gate--ambient .gate-vid.on{opacity:1;transform:scale(1)}
.gate--ambient::after{
  opacity:1;
  background:linear-gradient(to top,rgba(10,10,12,.86),rgba(10,10,12,.5));
}
.gate--ambient:hover::after{
  background:linear-gradient(to top,rgba(10,10,12,.92),rgba(10,10,12,.62));
}
.gate--ambient .gate-cta{color:#fff;border-color:rgba(255,255,255,.42)}
.gate--ambient:hover .gate-cta{color:var(--bg);background:#fff;border-color:#fff}
/* The banner carries only its button, and it rides the bottom of the frame
   rather than the middle: centred over the footage it covers the subject's
   face, and the scrim is at its darkest along the bottom edge, which is
   where an outlined white pill reads cleanest. Horizontal centring still
   comes from the parent's align-items. */
.gate--ambient{justify-content:flex-end}
.gate--ambient .gate-cta{margin-top:0;margin-bottom:clamp(8px,3vh,40px)}
.gate-cta{
  position:relative;z-index:2;
  margin-top:clamp(26px,3.4vw,44px);
  display:inline-flex;align-items:center;gap:10px;
  font-family:var(--font-body);
  font-size:13px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--mut);
  padding:11px 24px;border-radius:999px;
  border:1px solid var(--line);
  transition:color .35s,border-color .35s,background .35s;
}
.gate-cta i{font-style:normal;transition:transform .35s cubic-bezier(.22,1,.36,1)}
.gate:hover .gate-cta{color:var(--bg);background:var(--ink);border-color:var(--ink)}
.gate:hover .gate-cta i{transform:translateX(4px)}
@media (max-width:900px){
  .gate,.gate.solo{min-height:62vh}
}

/* ============ SUBPAGES (models listing + detail) ============ */
.subpage{
  min-height:100vh;
  padding:140px var(--pad) 100px;
  background:transparent;
  position:relative;z-index:1;
}
.models-head{
  display:flex;align-items:flex-end;justify-content:space-between;
  flex-wrap:wrap;gap:24px;
  border-bottom:1px solid var(--line);
  padding-bottom:32px;margin-bottom:48px;
}
/* both filter rows ride the right edge, stacked */
.models-tools{
  margin-left:auto;
  display:flex;flex-direction:column;align-items:flex-end;
  gap:10px;
}
.models-tools .models-filters{justify-content:flex-end}
.models-title{
  font-family:var(--font-head);font-weight:400;
  font-size:clamp(24px,3.5vw,50px);line-height:1.14;letter-spacing:0;
  white-space:nowrap;
}
/* "GEN AI" carries the lime so the qualifier reads first */
.models-title .title-accent{color:var(--accent-2)}
.models-filters{display:flex;gap:10px;flex-wrap:wrap}
.models-filters button{
  font-family:var(--font-body);font-size:13px;font-weight:400;
  padding:9px 20px;border-radius:999px;cursor:pointer;
  border:1px solid var(--line);background:var(--panel);color:var(--mut);
  transition:border-color .25s,color .25s,background .25s;
}
.models-filters button:hover{border-color:var(--accent);color:var(--ink)}
.models-filters button.on{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
/* gender is a two-state switch, not a filter list — the segments sit flush
   inside one track so it reads as a toggle rather than another button row */
.gender-switch[hidden]{display:none}
.gender-switch{
  display:inline-flex;
  padding:3px;border-radius:999px;
  border:1px solid var(--line);background:var(--panel);
}
.gender-switch button{
  font-family:var(--font-body);font-size:13px;font-weight:400;
  padding:7px 20px;border-radius:999px;cursor:pointer;
  border:0;background:transparent;color:var(--mut);
  transition:color .25s,background .25s;
}
.gender-switch button:hover{color:var(--ink)}
.gender-switch button.on{background:var(--accent-2);color:var(--bg)}
.models-grid{
  display:grid;grid-template-columns:repeat(4,1fr);gap:20px;
}
.model-card{display:flex;flex-direction:column;gap:12px;group:card}
.model-card .mc-img{
  position:relative;
  aspect-ratio:3/4;overflow:hidden;border-radius:14px;background:var(--line);
}
/* creator-type badge — ribbon seal: a ring with a banner struck across it,
   the banner ends notched into swallowtails. `currentColor` on the wrapper
   drives ring, rule and text together, so a variant is one declaration. */
.mc-badge{
  position:absolute;top:9px;right:9px;z-index:2;
  display:flex;align-items:center;justify-content:center;
  height:30px;
  font-style:normal;
  pointer-events:none;
  filter:drop-shadow(0 2px 6px rgba(0,0,0,.45));
}
.mcb-ring{
  position:absolute;left:50%;top:50%;
  transform:translate(-50%,-50%);
  width:28px;height:28px;border-radius:50%;
  border:1.5px solid currentColor;
  background:rgba(10,10,12,.72);
}
.mcb-band{
  position:relative;z-index:2;
  padding:4px 11px;
  background:rgba(10,10,12,.94);
  border-top:1px solid currentColor;
  border-bottom:1px solid currentColor;
  font-family:var(--font-body);font-weight:400;
  font-size:9px;letter-spacing:.13em;text-transform:uppercase;
  line-height:1;white-space:nowrap;
  /* swallowtail notch at each end */
  clip-path:polygon(0 0,100% 0,calc(100% - 6px) 50%,100% 100%,0 100%,6px 50%);
}
.mc-badge--gen{color:var(--accent-2)}
.mc-badge--real{color:#e2e2de}
.model-card img{
  width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .6s cubic-bezier(.22,1,.36,1);
}
.model-card:hover img{transform:scale(1.05)}
.model-card > span{
  font-family:var(--font-body);font-weight:500;font-size:18px;
  letter-spacing:.02em;text-transform:uppercase;
}
/* empty board — the same panel the work page uses, so a filter with nobody
   behind it yet reads as a deliberate state rather than a dead end. It is a
   grid child, so it has to span every column or it would sit in one cell. */
.models-empty{
  grid-column:1/-1;
  min-height:46vh;
  display:flex;flex-direction:column;align-items:flex-start;justify-content:center;
  gap:clamp(14px,2vw,26px);
  padding:clamp(24px,4vh,48px) 0;
}
.models-empty-head{
  font-family:var(--font-head);font-weight:400;
  /* same guard as .work-head: Boldonse paints outside its line box, so the
     descender on "g" would otherwise fall through onto the line below */
  font-size:clamp(34px,7vw,96px);line-height:1.12;letter-spacing:-.02em;
  padding-block:.12em .18em;
  color:var(--ink);
}
.models-empty-head em{font-style:normal;color:var(--accent)}
.models-empty-sub{
  max-width:44ch;color:var(--mut);
  font-size:clamp(14px,1.3vw,18px);line-height:1.6;
}

.detail-crumb{margin-bottom:32px;font-size:13px;color:var(--mut)}
.detail-crumb a{color:var(--accent);font-weight:600}
.detail-hero{margin-bottom:32px;border-radius:24px;overflow:hidden;background:#f2f2f2;border:1px solid var(--line)}
.detail-hero-frame{position:relative;display:grid;place-items:center;min-height:72vh;max-height:88vh;background:#f2f2f2;overflow:hidden}
.detail-hero-name{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center;align-items:center;pointer-events:none;z-index:1;line-height:.78;letter-spacing:-0.04em}
.detail-hero-name span{display:block;width:100%;color:rgba(38,38,38,.33);font-family:var(--font-head);font-size:clamp(8rem,18vw,31rem);font-weight:900;text-transform:uppercase;transform:translateY(0.05em)}
.detail-hero-name span:last-child{margin-top:-0.1em;transform:translateX(.12em)}
.detail-hero-media{position:relative;z-index:2;display:flex;align-items:center;justify-content:center;width:min(92%,1200px);height:min(78vh,860px);margin-inline:auto}
.detail-hero-media img{display:block;width:100%;height:100%;object-fit:contain;filter:contrast(1.05) saturate(1.08)}

/* ---- artboard hero: finished composition, opens on its own full screen ---- */
/* :not([hidden]) — a class-level display would otherwise beat the UA hidden rule */
.model-page--art:not([hidden]){display:flex;flex-direction:column;padding-top:0}
.model-page--art .detail-crumb{order:2;margin-top:44px}
.model-page--art .detail-body{order:3}
.detail-hero--art{
  order:1;position:relative;display:grid;place-items:center;
  /* breaks out of the subpage gutter without touching 100vw (scrollbar-safe) */
  margin:0 calc(-1 * var(--pad));
  border:0;border-radius:0;background:#fff;overflow:hidden;
}
.detail-hero--art .detail-hero-art{
  display:block;width:100%;height:100vh;height:100svh;
  object-fit:contain;object-position:center;
}
.detail-hero-scroll{
  position:absolute;left:50%;bottom:clamp(16px,4vh,44px);transform:translateX(-50%);
  display:flex;flex-direction:column;align-items:center;gap:10px;
  background:none;border:0;padding:6px 12px;cursor:pointer;color:var(--ink);
  font-family:var(--font-body);font-size:10px;letter-spacing:.22em;
  opacity:.5;transition:opacity .3s;
}
.detail-hero-scroll:hover{opacity:1}
.detail-hero-scroll i{
  width:1px;height:38px;background:currentColor;transform-origin:top;
  animation:heroScrollLine 1.9s ease-in-out infinite;
}
@keyframes heroScrollLine{
  0%,100%{transform:scaleY(.18);opacity:.25}
  50%{transform:scaleY(1);opacity:1}
}
/* portrait screens: a 16:9 artboard held at full height is mostly white bands,
   so it sits under the nav at its own ratio instead */
@media (max-width:900px){
  .model-page--art{padding-top:96px}
  .model-page--art .detail-crumb{margin-top:28px}
  .detail-hero--art .detail-hero-art{height:auto;aspect-ratio:2752/1536}
}
.detail-body{display:grid;grid-template-columns:1.6fr 1fr;gap:56px;align-items:start}
/* masonry: two columns, images keep their own varied heights */
.detail-gallery{columns:2;column-gap:16px}
.detail-gallery .g-item{
  margin-bottom:16px;border-radius:14px;overflow:hidden;
  background:var(--line);break-inside:avoid;
}
.detail-gallery img{
  width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .8s cubic-bezier(.22,1,.36,1);
}
/* breathing zoom while hovering — one slow 4s cycle, repeats while held */
.detail-gallery .g-item:hover img{
  animation:breathe 4s ease-in-out infinite;
}
@keyframes breathe{
  0%,100%{transform:scale(1)}
  50%{transform:scale(1.07)}
}
.detail-side{
  position:sticky;top:120px;
  /* clips the spec rows while they're parked off-panel, so they read as
     emerging from behind the gallery instead of floating in */
  overflow:hidden;
}
.detail-name{
  font-family:var(--font-head);font-weight:400;
  font-size:clamp(31px,3.9vw,56px);line-height:1.1;text-transform:uppercase;
}
.detail-tabs{display:flex;gap:20px;margin:24px 0}
.detail-tabs button{
  font-family:var(--font-body);font-size:12px;letter-spacing:.14em;font-weight:400;
  color:var(--mut);background:none;border:0;padding:0 0 4px;cursor:pointer;
  border-bottom:2px solid transparent;
  transition:color .25s,border-color .25s;
}
.detail-tabs button:hover{color:var(--ink)}
.detail-tabs button.on{color:var(--accent);border-bottom-color:var(--accent)}
.detail-stats{
  display:grid;grid-template-columns:auto 1fr;gap:10px 24px;
  border-top:1px solid var(--line);padding-top:24px;
  font-size:13px;
}
.detail-stats dt{color:var(--mut);letter-spacing:.1em;font-weight:400}
.detail-stats dd{font-weight:400}
.detail-actions{display:flex;flex-direction:column;gap:12px;margin-top:32px}
.detail-actions a{
  border:1px solid var(--line);border-radius:999px;
  padding:12px 24px;text-align:center;font-size:13px;font-weight:400;
  transition:border-color .25s,background .25s,color .25s;
}
.detail-actions a:hover{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}

@media (max-width:900px){
  .models-grid{grid-template-columns:1fr 1fr}
  /* one column, so the source order takes over and the spec panel — which
     sits beside the gallery on desktop, level with its top — fell to the
     very bottom, past every photo. Order it back above the gallery so the
     page still opens on the name, tabs and stats. */
  .detail-body{grid-template-columns:1fr;gap:28px}
  .detail-side{position:static;order:-1}
  .detail-gallery{order:0}
}

/* text-roll hover (label rolls out, duplicate rolls in from below) */
.roll{position:relative;display:inline-block;overflow:hidden;vertical-align:top}
.roll span{display:block;transition:transform .45s cubic-bezier(.65,0,.35,1)}
.roll .roll-b{position:absolute;left:0;top:100%;width:100%}
.has-roll:hover .roll-a{transform:translateY(-100%)}
.has-roll:hover .roll-b{transform:translateY(-100%)}

/* split-text headline reveal */
/* Each word is its own mask so it can slide up out of nothing — but the mask
   clips, and Boldonse paints well above its line box, so a .08em pad on the
   bottom alone sheared the caps and ascenders flat across the top. The box is
   now padded on BOTH edges out to the real glyph extent, with matching
   negative margins so the headline still sits exactly where it did. */
.split .w{
  display:inline-block;overflow:hidden;vertical-align:top;
  padding:.24em 0 .10em;
  margin:-.24em 0 -.10em;
}
.split .wi{display:inline-block;transform:translateY(115%)}

/* reveal */
[data-reveal]{opacity:0;transform:translateY(28px)}

/* responsive */
@media (max-width:900px){
  .infra-cards{grid-template-columns:1fr}
  .usecase-grid{grid-template-columns:1fr 1fr}
  .stats{flex-direction:column;align-items:flex-start}
  /* stacked and top-aligned, the content is well short of a screen, so the
     forced 100vh left dead space under the graph before the next section */
  .roi{grid-template-columns:1fr;gap:40px;align-items:start;min-height:auto}
  .roi-note{margin-left:0}
  .roi-bar{grid-template-columns:110px 1fr 64px}
  /* the axis is offset by hand to sit under the bar track, so it has to
     follow the columns whenever they change or it drifts out from under
     the bars and reads as a stray row of numbers */
  .roi-axis{
    margin-left:calc(110px + clamp(14px,1.6vw,26px));
    margin-right:calc(64px + clamp(14px,1.6vw,26px));
  }
  .nav{padding:12px 14px;gap:8px}
  .nav-links{
    gap:2px;font-size:13px;
    overflow-x:auto;scrollbar-width:none;
    max-width:60vw;
  }
  .nav-links::-webkit-scrollbar{display:none}
  .nav-links a{padding:7px 10px;white-space:nowrap}
  .nav-cta{padding:7px 13px;font-size:13px;white-space:nowrap}
  .merge-stage{height:36vh}
  .emotion-tagline{font-size:clamp(22px,6.7vw,56px);letter-spacing:-0.01em;line-height:1.18;padding-top:44vh;color:rgba(158,161,158,0.32)}
  .scroll-line{right:12px;height:30vh}
}

/* ── mobile: close the dead band in the reality scene ──
   The section is pinned at height:100vh, which on a phone measures the
   address-bar-inclusive viewport, so the pinned scene is taller than the
   screen. On top of that the flow content is only the headline plus a
   36vh stage, and it is vertically centred — so the leftover height is
   split into two empty bands, one of which reads as a big gap under the
   infra cards. svh sizes the section to what is actually visible, and a
   taller stage lets the composition fill it instead of the padding.
   Must sit after the 900px block above: media queries carry no extra
   specificity, so an earlier .merge-stage override would lose to it. */
@media (max-width:700px){
  .reality{height:100svh;padding:4vh var(--pad)}
  /* Same placement as desktop — under the tagline's closing line — but the
     tagline is padded 44vh here, so its second line finishes nearer 80svh.
     Note the unit: .reality is sized in svh on a phone and svh is the
     smaller of the two, so a vh offset this far down would resolve past the
     bottom of the box and overflow:hidden would clip the label away. */
  .merge-sub{top:85svh}
  .merge-stage{height:54vh;margin:2vh 0}
}
@media (max-width:560px){
  .usecase-grid{grid-template-columns:1fr}
  .roi-bar{grid-template-columns:88px 1fr 56px;gap:10px}
  .roi-axis{margin-left:98px;margin-right:66px;letter-spacing:.1em}
  .roi-bar b{font-size:19px}
  .models-head{flex-direction:column;align-items:flex-start}
  .models-tools{margin-left:0;align-items:flex-start}
  .models-tools .models-filters{justify-content:flex-start}
  .models-title{white-space:normal}
  .detail-gallery{columns:1}
  .tag-track{font-size:11px;gap:18px}
  .services>.display{white-space:normal}
}

/* ── mobile: stand the ROI scale on end ──
   Five labels across a phone-width track leaves "UNLIMITED" crowding its
   neighbours. writing-mode is used rather than a rotate(): rotate paints
   the glyphs sideways but leaves the box its original horizontal width, so
   the labels would keep reserving the space they no longer occupy and drift
   out of line with the bars. writing-mode reflows each span to tall and
   narrow, so justify-content:space-between goes on spacing them correctly.
   The 180deg turn sets them bottom-to-top, the usual axis reading order.
   Placed after the 560px block so the per-tier margins above still stand. */
@media (max-width:700px){
  .roi-axis{align-items:flex-start}
  .roi-axis span{
    writing-mode:vertical-rl;
    transform:rotate(180deg);
    line-height:1;
  }
}

/* touch devices: no hover exists, so imagery and video show on their own */
@media (hover:none){
  .gate-bg{opacity:.5;transform:scale(1)}
  .gate::after{opacity:1}
  .usecase-grid .uc-bg{transform:scale(1)}
  .infra-card .card-bg{opacity:.35;transform:scale(1)}
  .infra-card::after{opacity:1}
  .gate-vid.on{opacity:.85;transform:scale(1)}
  .cn-img img{filter:grayscale(1) contrast(1.2) brightness(.92)}
}

/* ============ LOGO IMAGE (replaces NAWF wordmark text) ============ */
.intro-logo img{height:20px;width:auto;display:block}
.nav-logo{display:flex;align-items:center;gap:10px}
.nav-logo .logo-mark{height:28px;width:auto;display:block}
.nav-logo .logo-word{height:15px;width:auto;display:block}
.cyl-title img{height:clamp(46px,7.2vw,112px);width:auto;display:block}
.merge-nawf img{
  height:clamp(36px,5.5vw,86px);width:auto;display:block;
  filter:drop-shadow(0 0 24px rgba(193,255,114,.5)) drop-shadow(0 0 55px rgba(255,215,94,.25));
}

/* ============ CONTACT PAGE ============ */
/* ── WORK (placeholder) ─────────────────────────────────────
   Same shell as the contact page: centred column, footer bleeding off the
   bottom edge the way it does on the home page. */
.work-page{
  max-width:1320px;margin:0 auto;
  padding-bottom:0;
}
.work-body{
  min-height:56vh;
  display:flex;flex-direction:column;align-items:flex-start;justify-content:center;
  gap:clamp(18px,2.4vw,30px);
}
.work-head{
  font-family:var(--font-head);font-weight:400;
  /* Boldonse paints well outside its line box, so at this size a 1.05
     line-height let the 'g' descender fall straight through the gap and onto
     the paragraph. Loosen the leading and pad the box out to the real glyph
     extent — the flex gap then measures from the ink, not the em box. */
  font-size:clamp(38px,8vw,120px);line-height:1.12;letter-spacing:-.02em;
  padding-block:.12em .18em;
  color:var(--ink);
}
.work-head em{font-style:normal;color:var(--accent)}
.work-sub{max-width:44ch;color:var(--mut);font-size:clamp(14px,1.3vw,18px);line-height:1.6}

.contact-page{
  /* Page accent is the electric lime the rest of the site leads with. It was
     --accent-2, the sage-lime, which the palette reserves for card and badge
     backgrounds — "never for heading text" — yet it was colouring both
     "reach out to us!" and #TOWARDSNAWF, and backing a submit button while
     every other CTA on the site uses .btn-accent's electric lime. */
  --ct:var(--accent);
  max-width:1320px;margin:0 auto;
  /* the footer wordmark bleeds off the bottom edge exactly like the home
     page, so the subpage's 100px bottom padding has to go */
  padding-bottom:0;
}
.ct-head{
  font-family:var(--font-head);
  font-weight:400;text-transform:none;
  font-size:clamp(24px,4.2vw,60px);
  line-height:1.24;letter-spacing:-.008em;
  color:var(--ink);
  max-width:20ch;
}
.ct-head em{font-style:normal;color:var(--ct);display:block;margin-top:.18em}
.ct-tag{
  display:block;margin-top:clamp(20px,3.4vw,44px);
  font-family:var(--font-head);font-weight:400;text-transform:uppercase;
  font-size:clamp(17px,2.3vw,33px);letter-spacing:0;
  color:var(--ct);
}

.ct-form{
  margin-top:clamp(48px,8vh,110px);
  margin-bottom:clamp(40px,7vh,90px);
  display:flex;flex-direction:column;
  gap:clamp(34px,5.5vh,60px);
}
.ct-row{
  display:grid;grid-template-columns:1fr 1fr;
  gap:clamp(28px,5vw,72px);
}
.ct-field{display:flex;flex-direction:column;gap:14px}
.ct-label{
  font-family:var(--font-body);
  font-size:11px;letter-spacing:.2em;text-transform:uppercase;
  color:var(--mut);
}
.ct-label i{font-style:normal;color:var(--ct)}
/* underline inputs — big uppercase display type, like the reference */
.ct-field input,
.ct-field textarea,
.ct-select select{
  width:100%;
  font-family:var(--font-body);font-weight:400;text-transform:uppercase;
  font-size:clamp(17px,1.7vw,25px);letter-spacing:-.01em;
  color:var(--ink);
  background:transparent;
  border:0;border-bottom:1px solid var(--line);
  border-radius:0;
  padding:0 0 14px;
  transition:border-color .3s,color .3s;
}
.ct-field textarea{resize:vertical;min-height:96px;line-height:1.35;text-transform:none}
.ct-field input::placeholder,
.ct-field textarea::placeholder{color:#5c5e64}
.ct-field input:focus,
.ct-field textarea:focus,
.ct-select select:focus{outline:none;border-bottom-color:var(--ct)}
/* select keeps the same underline treatment plus its own chevron */
.ct-select{position:relative}
.ct-select select{
  appearance:none;-webkit-appearance:none;
  cursor:pointer;padding-right:38px;
}
.ct-select select option{
  background:#111214;color:var(--ink);
  font-family:var(--font-body);font-size:15px;text-transform:none;font-weight:400;
}
.ct-select svg{
  position:absolute;right:2px;top:6px;
  width:22px;height:22px;color:var(--mut);
  pointer-events:none;transition:color .3s;
}
.ct-select:hover svg{color:var(--ct)}

/* The spam trap. Off-screen rather than display:none — a bot that reads
   computed styles skips anything hidden, and the point is that it fills
   this in. Kept out of the tab order and off the accessibility tree by
   the markup itself. */
.ct-hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

.ct-foot{display:flex;align-items:center;gap:24px;flex-wrap:wrap;line-height:1}
.ct-submit{
  /* inline-flex + line-height:1 so the label sits optically centred in the
     pill — the mono font's default leading was pushing it low */
  display:inline-flex;align-items:center;justify-content:center;
  line-height:1;
  font-family:var(--font-body);
  font-size:12px;letter-spacing:.2em;text-transform:uppercase;
  color:var(--bg);background:var(--ct);
  border:1px solid var(--ct);border-radius:999px;
  padding:17px 34px 17px 36px;   /* extra left pad balances the tracking */
  cursor:pointer;
  transition:background .3s,color .3s;
}
.ct-submit:hover{background:transparent;color:var(--ct)}
.ct-status{
  font-family:var(--font-body);font-size:12px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--mut);
}
.ct-status.ok{color:var(--ct)}
.ct-status.err{color:#E5484D}
@media (max-width:760px){
  .ct-row{grid-template-columns:1fr}
  .ct-head{max-width:none}
}

/* registering --s as a number lets it interpolate smoothly instead of
   being treated as an opaque string */
@property --s{syntax:'<number>';inherits:false;initial-value:0}
/* scratch-card reveal — the headline is masked by a cluster of soft blobs
   that grow in sequence as the section scrolls, so it uncovers in irregular
   patches rather than wiping cleanly. GSAP drives --s from 0 to 1. */
.aithat-head{
  --s:0;
  -webkit-mask-image:radial-gradient(closest-side, #000 58%, rgba(0,0,0,.6) 80%, transparent 100%),
    radial-gradient(closest-side, #000 58%, rgba(0,0,0,.6) 80%, transparent 100%),
    radial-gradient(closest-side, #000 58%, rgba(0,0,0,.6) 80%, transparent 100%),
    radial-gradient(closest-side, #000 58%, rgba(0,0,0,.6) 80%, transparent 100%),
    radial-gradient(closest-side, #000 58%, rgba(0,0,0,.6) 80%, transparent 100%),
    radial-gradient(closest-side, #000 58%, rgba(0,0,0,.6) 80%, transparent 100%),
    radial-gradient(closest-side, #000 58%, rgba(0,0,0,.6) 80%, transparent 100%),
    radial-gradient(closest-side, #000 58%, rgba(0,0,0,.6) 80%, transparent 100%),
    radial-gradient(closest-side, #000 58%, rgba(0,0,0,.6) 80%, transparent 100%),
    radial-gradient(closest-side, #000 58%, rgba(0,0,0,.6) 80%, transparent 100%),
    radial-gradient(closest-side, #000 58%, rgba(0,0,0,.6) 80%, transparent 100%),
    radial-gradient(closest-side, #000 58%, rgba(0,0,0,.6) 80%, transparent 100%);
  -webkit-mask-size:calc(max(0, var(--s) * 1.75 - 0.0) * 150%) calc(max(0, var(--s) * 1.75 - 0.0) * 210%),
    calc(max(0, var(--s) * 1.75 - 0.055) * 150%) calc(max(0, var(--s) * 1.75 - 0.055) * 210%),
    calc(max(0, var(--s) * 1.75 - 0.11) * 150%) calc(max(0, var(--s) * 1.75 - 0.11) * 210%),
    calc(max(0, var(--s) * 1.75 - 0.165) * 150%) calc(max(0, var(--s) * 1.75 - 0.165) * 210%),
    calc(max(0, var(--s) * 1.75 - 0.22) * 150%) calc(max(0, var(--s) * 1.75 - 0.22) * 210%),
    calc(max(0, var(--s) * 1.75 - 0.275) * 150%) calc(max(0, var(--s) * 1.75 - 0.275) * 210%),
    calc(max(0, var(--s) * 1.75 - 0.33) * 150%) calc(max(0, var(--s) * 1.75 - 0.33) * 210%),
    calc(max(0, var(--s) * 1.75 - 0.385) * 150%) calc(max(0, var(--s) * 1.75 - 0.385) * 210%),
    calc(max(0, var(--s) * 1.75 - 0.44) * 150%) calc(max(0, var(--s) * 1.75 - 0.44) * 210%),
    calc(max(0, var(--s) * 1.75 - 0.495) * 150%) calc(max(0, var(--s) * 1.75 - 0.495) * 210%),
    calc(max(0, var(--s) * 1.75 - 0.55) * 150%) calc(max(0, var(--s) * 1.75 - 0.55) * 210%),
    calc(max(0, var(--s) * 1.75 - 0.605) * 150%) calc(max(0, var(--s) * 1.75 - 0.605) * 210%);
  -webkit-mask-position:8% 42%,21% 66%,33% 31%,45% 72%,56% 38%,67% 64%,78% 33%,88% 68%,50% 50%,15% 30%,72% 50%,94% 44%;
  -webkit-mask-repeat:no-repeat,no-repeat,no-repeat,no-repeat,no-repeat,no-repeat,no-repeat,no-repeat,no-repeat,no-repeat,no-repeat,no-repeat;
  mask-image:radial-gradient(closest-side, #000 58%, rgba(0,0,0,.6) 80%, transparent 100%),
    radial-gradient(closest-side, #000 58%, rgba(0,0,0,.6) 80%, transparent 100%),
    radial-gradient(closest-side, #000 58%, rgba(0,0,0,.6) 80%, transparent 100%),
    radial-gradient(closest-side, #000 58%, rgba(0,0,0,.6) 80%, transparent 100%),
    radial-gradient(closest-side, #000 58%, rgba(0,0,0,.6) 80%, transparent 100%),
    radial-gradient(closest-side, #000 58%, rgba(0,0,0,.6) 80%, transparent 100%),
    radial-gradient(closest-side, #000 58%, rgba(0,0,0,.6) 80%, transparent 100%),
    radial-gradient(closest-side, #000 58%, rgba(0,0,0,.6) 80%, transparent 100%),
    radial-gradient(closest-side, #000 58%, rgba(0,0,0,.6) 80%, transparent 100%),
    radial-gradient(closest-side, #000 58%, rgba(0,0,0,.6) 80%, transparent 100%),
    radial-gradient(closest-side, #000 58%, rgba(0,0,0,.6) 80%, transparent 100%),
    radial-gradient(closest-side, #000 58%, rgba(0,0,0,.6) 80%, transparent 100%);
  mask-size:calc(max(0, var(--s) * 1.75 - 0.0) * 150%) calc(max(0, var(--s) * 1.75 - 0.0) * 210%),
    calc(max(0, var(--s) * 1.75 - 0.055) * 150%) calc(max(0, var(--s) * 1.75 - 0.055) * 210%),
    calc(max(0, var(--s) * 1.75 - 0.11) * 150%) calc(max(0, var(--s) * 1.75 - 0.11) * 210%),
    calc(max(0, var(--s) * 1.75 - 0.165) * 150%) calc(max(0, var(--s) * 1.75 - 0.165) * 210%),
    calc(max(0, var(--s) * 1.75 - 0.22) * 150%) calc(max(0, var(--s) * 1.75 - 0.22) * 210%),
    calc(max(0, var(--s) * 1.75 - 0.275) * 150%) calc(max(0, var(--s) * 1.75 - 0.275) * 210%),
    calc(max(0, var(--s) * 1.75 - 0.33) * 150%) calc(max(0, var(--s) * 1.75 - 0.33) * 210%),
    calc(max(0, var(--s) * 1.75 - 0.385) * 150%) calc(max(0, var(--s) * 1.75 - 0.385) * 210%),
    calc(max(0, var(--s) * 1.75 - 0.44) * 150%) calc(max(0, var(--s) * 1.75 - 0.44) * 210%),
    calc(max(0, var(--s) * 1.75 - 0.495) * 150%) calc(max(0, var(--s) * 1.75 - 0.495) * 210%),
    calc(max(0, var(--s) * 1.75 - 0.55) * 150%) calc(max(0, var(--s) * 1.75 - 0.55) * 210%),
    calc(max(0, var(--s) * 1.75 - 0.605) * 150%) calc(max(0, var(--s) * 1.75 - 0.605) * 210%);
  mask-position:8% 42%,21% 66%,33% 31%,45% 72%,56% 38%,67% 64%,78% 33%,88% 68%,50% 50%,15% 30%,72% 50%,94% 44%;
  mask-repeat:no-repeat,no-repeat,no-repeat,no-repeat,no-repeat,no-repeat,no-repeat,no-repeat,no-repeat,no-repeat,no-repeat,no-repeat;
}


/* ============================================================
   Boldonse heading normalisation
   Single source of truth for heading weight, leading and tracking.
   Boldonse ships one weight (400) — asking for 700 makes the browser
   synthesise it, which smears the outlines. Size stays per-selector.
   ============================================================ */
.display,.page .display,
.hero-title,.page .hero-title,
.cyl-title,.merge-nawf,.emotion-tagline,
.aithat-head,.step-title,.stat-num,
.slide-body h3,.math-fig,.roi-bar b,.rf-eq,.rf-op,
.models-title,.detail-name,
.ct-head,.ct-tag,
.rf-frac b,.rf-term,
.infra-card h3,.influence-body h3,.usecase-grid h3{
  font-weight:400;
  line-height:var(--head-lh);
  letter-spacing:var(--head-ls);
}

/* connect headline is the only two-line display on the page — the shared
   1.25 leading packs the lime line right under the white one. A small bump,
   scoped here so no other heading moves. Declared after the Boldonse
   normalisation block because the specificity ties. */
.connect .display,
.page .connect .display{line-height:1.6}
/* contact headline wraps to 3 lines at most widths — same Boldonse
   overlap as the connect headline, same fix: more leading. */
.ct-head{line-height:1.5}


/* ============================================================
   SECTION DIVIDER — "signal sweep" (ROI → use cases)
   A standalone pinned scene. Everything starts collapsed and is
   driven by the scrollbar from js/main.js, so the CSS only owns
   the resting geometry and colour; nothing animates on its own.
   ============================================================ */
.xfade{
  position:relative;
  height:100vh;
  /* the scene fills the viewport on its own — the global section padding
     was squeezing the band and adding a screen of dead space on exit */
  padding:0;
  display:flex;align-items:center;
  overflow:hidden;
  /* a faint lime bloom behind the band so the strip separates from
     the flat charcoal above and below it */
  background:radial-gradient(120% 46% at 50% 50%,rgba(193,255,114,.055),transparent 70%);
}
.xfade-stage{
  position:relative;
  width:100%;
  display:flex;flex-direction:column;align-items:center;
  gap:clamp(14px,2vw,26px);
}

/* ── slat stacks: thin bars that rake in from alternating edges ── */
.xfade-slats{
  width:100%;
  display:flex;flex-direction:column;
  gap:clamp(5px,.7vw,9px);
}
.xfade-slats i{
  display:block;
  width:var(--w,60%);
  height:2px;
  background:var(--line);
  border-radius:2px;
  will-change:transform;
}
.xfade-slats i.is-lime{background:var(--accent);opacity:.55}
/* the stacks fan away from the centre line */
.xfade-slats--top{margin-bottom:clamp(6px,1vw,14px)}
.xfade-slats--bot{margin-top:clamp(6px,1vw,14px)}

/* ── core: two hairlines sandwiching the counter-running marquees ── */
.xfade-core{
  position:relative;
  width:100%;
  display:flex;flex-direction:column;
  gap:clamp(8px,1.2vw,16px);
}
.xfade-rule{
  display:block;height:1px;width:100%;
  background:linear-gradient(90deg,transparent,var(--accent) 12%,var(--accent) 88%,transparent);
  opacity:.5;
  will-change:transform;
}
.xfade-rows{
  display:flex;flex-direction:column;
  gap:clamp(2px,.4vw,8px);
  will-change:opacity,filter;
}
.xfade-row{overflow:hidden;width:100%}
.xfade-track{
  display:inline-flex;align-items:center;
  gap:clamp(14px,2vw,34px);
  white-space:nowrap;
  font-family:var(--font-head);
  font-weight:400;
  font-size:clamp(34px,7.4vw,104px);
  line-height:var(--head-lh);
  letter-spacing:var(--head-ls);
  will-change:transform;
}
.xfade-track b{
  font-family:var(--font-body);
  font-size:.28em;
  color:var(--accent);
  transform:translateY(-.18em);
}
/* top row reads solid, bottom row is the outline echo of it */
.xfade-row--a .xfade-track{color:var(--ink)}
.xfade-row--b .xfade-track{
  color:transparent;
  -webkit-text-stroke:1px var(--mut);
  opacity:.75;
}
.xfade-row--b .xfade-track b{color:var(--accent);-webkit-text-stroke:0}
/* the brand name is the only lime word in the strip, so it reads as the
   signature rather than as one more item in the list */
.xfade-track .is-brand{
  color:var(--accent);
  letter-spacing:.02em;
}
.xfade-row--b .xfade-track .is-brand{
  color:transparent;
  -webkit-text-stroke-color:var(--accent);
  opacity:.9;
}

/* ── vertical scan line that crosses the band mid-hold ── */
.xfade-scan{
  position:absolute;top:-4%;bottom:-4%;left:0;
  width:1px;
  background:linear-gradient(180deg,transparent,var(--accent),transparent);
  opacity:0;
  box-shadow:0 0 22px 3px rgba(193,255,114,.35);
  pointer-events:none;
}

/* ── phones ──
   The scene is no longer pinned here (see js/main.js), so it does not need
   to hold a whole viewport. Pinned, it owned the entire screen while it ran
   and nothing below could show through — a sparse band of slats and two
   marquees, reading as an empty screen with no sign that the page carries
   on. Sized to its own content it scrolls with the page instead, so "Nawf
   in virtual action" rises into view underneath it and the band becomes a
   transition between two things rather than a hole between them. */
@media (max-width:700px){
  .xfade{height:auto;padding:clamp(60px,12vh,124px) 0}
  .xfade-stage{gap:clamp(10px,3vw,16px)}
  .xfade-slats{gap:5px}
  .xfade-slats i{height:1.5px}
  .xfade-core{gap:8px}
  .xfade-track{
    font-size:clamp(30px,10vw,54px);
    gap:16px;
  }
  .xfade-row--b .xfade-track{-webkit-text-stroke-width:.75px}
  .xfade-scan{box-shadow:0 0 14px 2px rgba(193,255,114,.3)}
}
/* very narrow phones */
@media (max-width:380px){
  .xfade-track{font-size:clamp(26px,11vw,40px)}
}
/* short landscape phones — pull the type down so the band still fits
   inside a ~380px-tall viewport */
@media (max-height:480px){
  .xfade-track{font-size:clamp(22px,5vh,38px)}
  .xfade-slats{gap:4px}
}
@media (prefers-reduced-motion:reduce){
  .xfade{height:auto;padding:clamp(60px,10vw,120px) 0}
}
