/* =====================================================================
   GRID.PE — tokens
   ===================================================================== */
:root{
  --ground:#f2f2f2;
  --paper:#f7f7f7;
  --white:#fff;
  --ink:#0a0a0a;
  --ink-2:#141414;
  --mute:#6b6b6b;
  --hair:rgba(0,0,0,.10);

  --indigo:#5a5bf3;
  --indigo-d:#3d3ecf;
  --violet:#8b5cf6;
  --magenta:#ff4fd8;
  --cyan:#02bbff;
  --green:#20c368;
  --cream:#fff4e0;
  --lav:#dfcfff;

  /* chrome: light -> shadow, for the lit metal edge on the nav CTA */
  --chrome-hi:#ffffff;
  --chrome-1:#dfe2e7;
  --chrome-2:#a8adb6;
  --chrome-3:#767c86;
  --chrome-4:#4e535c;

  /* vivid */
  --lime:#d4ff3d;
  --lime-d:#b6ef12;
  --hot:#ff00e5;
  --hot-s:#ff6ae8;
  --grape:#7b2bff;
  --sky:#57d9ff;
  --noise:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='g'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='4'/></filter><rect width='180' height='180' filter='url(%23g)' opacity='.5'/></svg>");

  --shell: clamp(20px, 5vw, 72px);
  --maxw: 1400px;
  --r-lg: 34px;
  --r-md: 22px;
  --r-sm: 14px;

  --ease: cubic-bezier(.22,1,.36,1);
  --ease-io: cubic-bezier(.65,0,.35,1);
  /* Mondragon's process grid runs one symmetric in-out for every element.
     Calm and mechanical on purpose: the steps read as a sequence, not a bounce. */
  --ease-step: cubic-bezier(.44,0,.56,1);

  --nav-h: 62px;
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%; scroll-behavior:smooth; overflow-x:clip}
section[id],main[id]{scroll-margin-top:calc(var(--nav-h) + 34px)}
html{
  /* the page runs light at the top and black at the footer, so no single
     canvas colour is right for a rubber-band overscroll - kill the bounce
     instead of letting the body ground flash under the footer */
  overscroll-behavior-y:none;
  /* iOS Safari ignores overscroll-behavior, so the canvas has to match the
     footer instead. body's --ground covers the light sections above. */
  background:var(--ink);
}
body{
  margin:0;
  overscroll-behavior-y:none;
  background:var(--ground);
  color:var(--ink);
  font-family:Manrope,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
  font-size:16px; line-height:1.55;
  -webkit-font-smoothing:antialiased;
  /* clip, not hidden: clip never makes body a scroll container, so sticky
     children keep working and there is nothing left for touch to drag. */
  overflow-x:clip;
}
img{max-width:100%; display:block}
a{color:inherit; text-decoration:none}
button,input{font:inherit; color:inherit}
::selection{background:var(--ink); color:var(--cream)}

/* skip-to-content — accessible off-screen until focused --------------- */
.skip-link{
  position:absolute;
  left:-9999px;
  top:0;
  z-index:9999;
  padding:12px 22px;
  border-radius:999px;
  background:var(--ink);
  color:var(--lime);
  font-size:14px;
  font-weight:600;
  letter-spacing:-.01em;
  text-decoration:none;
}
.skip-link:focus,
.skip-link:focus-visible{
  left:1rem;
  top:1rem;
  outline:2px solid var(--lime);
  outline-offset:2px;
}

/* focus-visible baseline: every interactive element ---------- */
a:focus-visible{outline:2px solid var(--hot); outline-offset:3px; border-radius:4px}
button:focus-visible{outline:2px solid var(--hot); outline-offset:3px}
input:focus-visible{outline:2px solid var(--hot); outline-offset:2px}


.display,.h2,.hero__title,.cta__title,.band__text{
  font-family:Archivo,"Arial Narrow",system-ui,sans-serif;
  font-variation-settings:"wdth" 76,"wght" 500;
  font-weight:500;
  text-transform:uppercase;
  line-height:.84;
  letter-spacing:-.022em;
  margin:0;
}
.eyebrow{
  font-family:"Fragment Mono",ui-monospace,monospace;
  font-size:11px; letter-spacing:.18em; text-transform:uppercase;
  color:var(--mute); display:block; margin-bottom:18px;
}
.eyebrow--light{color:rgba(255,255,255,.72)}

/* film grain ------------------------------------------------------- */
.grain{
  /* inset:0, never oversized: a fixed box is laid out against the viewport, so
     body{overflow-x:clip} cannot clip it and any bleed past 100vw becomes real
     horizontal drag on touch. The jitter moves the repeating tile via
     background-position instead of the box via transform - same shimmer, zero
     overflow. */
  position:fixed; inset:0; z-index:9999; pointer-events:none;
  opacity:.028; mix-blend-mode:multiply;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3'/></filter><rect width='140' height='140' filter='url(%23n)'/></svg>");
  animation:grain 1.1s steps(3) infinite;
}
@keyframes grain{
  0%{background-position:0 0} 33%{background-position:-37px 28px} 66%{background-position:28px -37px} 100%{background-position:0 0}
}

/* =====================================================================
   NAV
   ===================================================================== */
.nav{
  position:fixed; top:14px; left:0; right:0; z-index:900;
  display:flex; justify-content:center; padding:0 16px;
}

/* The hero line, parked under the nav once it scrolls past. Same words as
   .hero__sub but set in the sans at medium instead of the serif italic, so the
   two crossfade rather than morph.

   No chip behind it: the text is painted white and differenced against whatever
   is underneath, so each glyph inverts against its own backdrop - near-black on
   the paper sections, near-white over the ink ones - with no per-section
   overrides to keep in sync. */
.nav__tagline{
  position:fixed; z-index:880; left:0; right:0;
  top:var(--tagTop,86px);
  margin:0; padding:0 16px;
  font-family:Manrope,system-ui,sans-serif; font-style:normal; font-weight:700;
  font-size:clamp(12px,1vw,15px); line-height:1.25;
  text-transform:uppercase; letter-spacing:.04em;   /* caps want positive tracking */
  text-align:center; white-space:nowrap;
  color:#fff; mix-blend-mode:difference;
  opacity:0; transform:translateY(-8px); pointer-events:none;
  transition:opacity .35s var(--ease), transform .35s var(--ease);
}
.nav__tagline.is-pinned{opacity:1; transform:none}
.nav__pill{
  display:flex; align-items:center; gap:10px;
  height:var(--nav-h); padding:6px 6px 6px 18px;
  border-radius:999px;
  background:rgba(232,230,230,.62);
  border:1px solid rgba(255,255,255,.5);
  backdrop-filter:blur(18px) saturate(160%);
  -webkit-backdrop-filter:blur(18px) saturate(160%);
  box-shadow:0 10px 30px -14px rgba(0,0,0,.35);
  transition:background .4s var(--ease), box-shadow .4s var(--ease);
}
.nav.is-stuck .nav__pill{background:rgba(226,224,224,.82); box-shadow:0 16px 40px -18px rgba(0,0,0,.45)}

.nav__logo{display:flex; align-items:center}
/* the wordmark ships as flat black art on transparent, so dark surfaces just
   invert it rather than needing a second file */
.logo{display:block; width:auto; height:20px}
.logo--onDark{filter:invert(1)}

/* wordmark set inline in a display heading. Measured off the art: baseline sits
   at .713 of the ink height, descender runs to 1.0, so height 1.02em lines the
   logo ascenders up with Archivo's cap height and -.29em puts its baseline on
   the text baseline. The tall inline-block grows the .84 line box, which is what
   keeps the g/p tails off the line below - do not claw that space back with a
   negative margin, the descenders land straight on the next line's caps. */
.logo-in{display:inline-block; width:auto; height:1.02em; vertical-align:-.29em}
.line--logo:not(:last-child){margin-bottom:.04em}
.coverage .logo-in{filter:invert(1)}   /* dark section */

.nav__links{display:flex; gap:4px; margin:0 6px}
.nav__links a{
  position:relative; padding:8px 12px; border-radius:999px;
  font-size:13.5px; font-weight:600; color:#2b2b2b;
  transition:color .25s, background .25s;
}
.nav__links a::after{
  content:""; position:absolute; left:12px; right:12px; bottom:5px; height:1.5px;
  background:currentColor; transform:scaleX(0); transform-origin:left;
  transition:transform .45s var(--ease);
}
.nav__links a:hover{color:#000}
.nav__links a:hover::after{transform:scaleX(1)}
.nav__links a:focus-visible{outline:2px solid var(--hot); outline-offset:3px; border-radius:999px}
.nav__links a:focus-visible::after{transform:none}

/* The one nav item that leaves the page. A small outbound arrow separates it
   from the in-page anchors either side of it. */
.nav__links-out{display:inline-flex; align-items:center; gap:5px}
.nav__links-out::before{
  content:""; width:5px; height:5px; flex:none; border-radius:50%;
  background:var(--hot); opacity:.75;
}

.nav__cta{
  position:relative; isolation:isolate;
  display:flex; align-items:center; gap:11px;
  height:49px; padding:0 18px 0 8px; border-radius:999px;   /* pill, like .nav__pill */
  background:var(--ground); color:var(--ink);
  font-size:15px; font-weight:500; letter-spacing:-.01em;
  transition:transform .35s var(--ease);
}
.nav__cta:hover{transform:translateY(-1px)}
/* animated conic glow ring, like a lit-up chrome edge */
.nav__cta-ring{
  position:absolute; inset:-1.7px; z-index:-1; border-radius:999px; padding:1.7px;
  background:linear-gradient(135deg,
    var(--chrome-hi) 0%,  var(--chrome-3) 11%, var(--chrome-hi) 24%,
    var(--chrome-1) 34%,  var(--chrome-4) 47%, var(--chrome-hi) 60%,
    var(--chrome-2) 72%,  var(--chrome-hi) 85%, var(--chrome-3) 100%);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor; mask-composite:exclude;
}
.nav__cta::before{
  content:""; position:absolute; inset:-5px; z-index:-2; border-radius:999px;
  background:linear-gradient(135deg,var(--chrome-3),var(--chrome-1) 50%,var(--chrome-4));
  filter:blur(9px); opacity:.42;
  animation:ctabreathe 3.6s ease-in-out infinite;
}
@keyframes ctabreathe{0%,100%{opacity:.34}50%{opacity:.56}}
.nav__cta-tile{
  width:37px; height:37px; border-radius:999px; flex:none;
  display:grid; place-items:center; background:var(--ink); color:var(--lime);
}
.nav__cta-tile svg{width:17px; height:17px}
.nav__cta-label{white-space:nowrap}

.nav__burger{
  display:none; width:44px; height:44px; border:0; border-radius:999px;
  background:transparent; cursor:pointer; padding:0;
}
.nav__burger span{
  display:block; width:20px; height:2px; margin:4px auto; background:#000; border-radius:2px;
  transition:transform .4s var(--ease), opacity .3s;
}
.nav__burger[aria-expanded="true"] span:first-child{transform:translateY(3px) rotate(45deg)}
.nav__burger[aria-expanded="true"] span:last-child{transform:translateY(-3px) rotate(-45deg)}

.drawer{
  position:fixed; inset:0; z-index:880;
  background:var(--ground);
  display:flex; flex-direction:column; justify-content:center; gap:6px;
  padding:0 var(--shell);
  clip-path:inset(0 0 100% 0);
  transition:clip-path .7s var(--ease);
  pointer-events:none;
}
.drawer.is-open{clip-path:inset(0 0 0 0); pointer-events:auto}
.drawer a{
  font-family:Archivo,sans-serif; font-variation-settings:"wdth" 80,"wght" 500;
  text-transform:uppercase; font-size:12vw; line-height:1.02; letter-spacing:-.03em;
  opacity:0; transform:translateY(30px);
  transition:opacity .5s var(--ease), transform .6s var(--ease);
}
.drawer.is-open a{opacity:1; transform:none}
.drawer.is-open a:nth-child(1){transition-delay:.10s}
.drawer.is-open a:nth-child(2){transition-delay:.16s}
.drawer.is-open a:nth-child(3){transition-delay:.22s}
.drawer.is-open a:nth-child(4){transition-delay:.28s}
.drawer.is-open a:nth-child(5){transition-delay:.34s}
.drawer__cta{color:var(--hot); transition-delay:.40s !important}
.drawer a:focus-visible{outline:2px solid var(--hot); outline-offset:6px; border-radius:8px}

/* =====================================================================
   HERO
   ===================================================================== */
.hero{
  position:relative; padding:calc(var(--nav-h) + 74px) var(--shell) 0;
  text-align:center; overflow:clip;
}
.hero__title{
  position:relative; z-index:2;
  font-size:clamp(52px,11.4vw,178px);
  font-variation-settings:"wdth" 72,"wght" 500;
  letter-spacing:-.028em;
}
.hero__sub{
  position:relative; z-index:2;
  margin:22px auto 0;
  font-family:"Instrument Serif",Georgia,serif; font-style:italic; font-weight:400;
  font-size:clamp(18px,2vw,30px); color:#2c2c2c; line-height:1.3;
  white-space:nowrap;            /* the line is the point - never wrap it */
  transition:opacity .3s var(--ease);
}
/* handed off to .nav__tagline - otherwise both are on screen at once, since
   the nav pill is narrower than the line and leaves it visible either side */
.hero__sub.is-parked{opacity:0}

.hero__act{
  position:relative; z-index:2;
  display:flex; flex-wrap:wrap; align-items:center; justify-content:center; gap:14px 20px;
  margin:26px auto 0;
}
.btn--go{
  display:inline-flex; align-items:center; gap:9px;
  height:52px; padding:0 24px; border-radius:999px;
  background:var(--ink); color:#fff; text-decoration:none;
  font-size:15.5px; font-weight:600; letter-spacing:-.01em;
  transition:transform .4s var(--ease), box-shadow .4s var(--ease);
}
.btn--go:hover{transform:translateY(-2px); box-shadow:0 18px 34px -18px rgba(0,0,0,.55)}
.btn--go:focus-visible{outline:2px solid var(--hot); outline-offset:3px}
.hero__where{
  display:inline-flex; align-items:center; gap:8px;
  font-family:"Fragment Mono",monospace; font-size:11px; letter-spacing:.1em;
  text-transform:uppercase; color:var(--mute);
}
.hero__where i{
  width:7px; height:7px; border-radius:50%; background:var(--lime);
  box-shadow:0 0 0 3px rgba(212,255,61,.28);
}

.hero__stage{position:relative; z-index:2; margin:38px auto 0; width:min(330px,72vw); will-change:transform}
.hero__device{width:100%; height:auto; display:block}
.hero__foot{
  position:relative; z-index:2;
  margin:56px auto 0; padding-bottom:86px; max-width:34ch;
  font-family:"Fragment Mono",monospace; font-size:12px; line-height:1.7;
  text-transform:uppercase; letter-spacing:.06em; color:var(--mute);
}

.trail{position:absolute; inset:0; z-index:3; pointer-events:none; overflow:hidden}
.sticker{
  position:absolute; top:0; left:0;   /* width is set per note in main.js */
  transform-origin:50% 50%;
  will-change:transform,opacity;
  opacity:0;
  backface-visibility:hidden;
}
.sticker img{
  display:block; width:100%; height:auto;
  border-radius:7px;
}


/* =====================================================================
   TICKER
   ===================================================================== */
/* =====================================================================
   STRAP — kinetic editorial band (replaces the old .ticker)
   Direction and speed come from main.js; everything here is static styling.
   ===================================================================== */
.strap{
  /* no colour slab: the band is defined by two hairlines on the page ground,
     which keeps it editorial rather than neon */
  background:var(--ground); color:var(--ink);
  border-block:1px solid var(--ink);
  padding:clamp(26px,4vw,58px) 0;
  overflow:hidden;                 /* clips the track: no page-level h-scroll */
}
.strap__track{display:flex; width:max-content; will-change:transform}
.strap__row{
  flex:none; display:flex; align-items:center; white-space:nowrap;
  gap:clamp(24px,4.4vw,72px); padding-right:clamp(24px,4.4vw,72px);
}
.strap__word,.strap__glyph,.strap__arrow{
  font-family:Archivo,sans-serif; font-variation-settings:"wdth" 68,"wght" 700;
  text-transform:uppercase; letter-spacing:-.04em; line-height:.8;
}
.strap__word{font-size:clamp(52px,11vw,168px)}
.strap__glyph{font-size:clamp(70px,13.5vw,208px); letter-spacing:-.06em}
.strap__arrow{font-size:clamp(38px,6.6vw,104px); transform:translateY(.06em)}
.strap__serif{
  font-family:"Instrument Serif",Georgia,serif; font-style:italic; font-weight:400;
  font-size:clamp(50px,10.4vw,158px); letter-spacing:-.015em; line-height:.86;
  font-variation-settings:normal;
}
.strap__mark{height:clamp(30px,5.4vw,84px); width:auto; flex:none}

/* outlined words read as drawn objects rather than more copy */
.strap__word--out,.strap__glyph{color:var(--ink)}
@supports (-webkit-text-stroke:1px black){
  .strap__word--out,.strap__glyph{
    color:transparent; -webkit-text-stroke:clamp(1.2px,.16vw,2.6px) var(--ink);
  }
}


/* =====================================================================
   FLOW — the money story (one amount, three states)
   ===================================================================== */
.flow{
  background:var(--ink); color:#fff;
  padding:clamp(56px,7vw,104px) var(--shell) clamp(62px,8vw,112px);
}
.flow__inner{max-width:var(--maxw); margin:0 auto}
.flow .h2{font-size:clamp(32px,5.2vw,78px)}
.flow__note{margin:22px 0 0; color:rgba(255,255,255,.68); font-size:15px; line-height:1.65; max-width:54ch}
.flow__note b{color:#fff; font-weight:500}
.flow__note--end{margin-top:clamp(24px,2.8vw,36px)}

.ledger{
  margin:clamp(32px,4.4vw,56px) 0 0;
  display:grid; gap:14px; grid-template-columns:repeat(auto-fit,minmax(270px,1fr));
}
.ledger__card{
  display:flex; flex-direction:column; gap:14px;
  padding:26px 26px 28px; border-radius:var(--r-lg);
  background:rgba(255,255,255,.045); border:1px solid rgba(255,255,255,.13);
  transition:transform .55s var(--ease);
}
.ledger__card:hover{transform:translateY(-5px)}
.ledger__step{
  font-family:"Fragment Mono",monospace; font-size:10.5px;
  letter-spacing:.14em; text-transform:uppercase; color:rgba(255,255,255,.5);
}
.ledger__amt{
  margin:0; font-family:Archivo,sans-serif;
  font-variation-settings:"wdth" 84,"wght" 500;
  font-size:clamp(40px,4.6vw,62px); letter-spacing:-.035em; line-height:.9;
}
.ledger__amt em{
  display:block; margin-top:13px;
  font-style:normal; font-family:"Fragment Mono",monospace;
  font-variation-settings:normal; font-size:10.5px; letter-spacing:.12em;
  text-transform:uppercase; line-height:1.5; color:rgba(255,255,255,.55);
}
.ledger__say{margin:auto 0 0; font-size:14px; line-height:1.55; color:rgba(255,255,255,.7)}

/* held — the state nobody expects, so it gets the loud treatment */
.ledger__card--key{background:var(--lime); border-color:transparent; color:var(--ink)}
.ledger__card--key .ledger__step,
.ledger__card--key .ledger__amt em{color:rgba(0,0,0,.55)}
.ledger__card--key .ledger__say{color:rgba(0,0,0,.72)}

/* debited — same rupees, resolved: marked, not shouting */
.ledger__card--fin{border-color:rgba(212,255,61,.45)}
.ledger__card--fin .ledger__step{color:var(--lime)}
.ledger__card--fin .ledger__amt em{color:rgba(212,255,61,.72)}

/* the six beats, as a spine rather than six more boxes */

/* =====================================================================
   WORKS
   ===================================================================== */
.works{background:var(--paper); padding:clamp(70px,9vw,130px) var(--shell) clamp(60px,8vw,110px)}
.works__head{max-width:var(--maxw); margin:0 auto clamp(40px,5vw,70px)}
.h2{font-size:clamp(34px,5.6vw,86px)}
.h2--center{text-align:center}

.works__grid{
  max-width:var(--maxw); margin:0 auto;
  display:grid; gap:18px; grid-template-columns:repeat(3,1fr);
}
.work{
  position:relative; background:var(--white); border-radius:var(--r-lg);
  padding:30px 30px 0; overflow:hidden; min-height:450px;
  display:flex; flex-direction:column;
  border:1px solid var(--hair);
  transition:transform .55s var(--ease), box-shadow .55s var(--ease);
}
.work:hover{transform:translateY(-6px); box-shadow:0 30px 60px -34px rgba(0,0,0,.4)}
.work__num{
  font-family:"Fragment Mono",monospace; font-size:11px; color:var(--hot);
  letter-spacing:.14em; margin-bottom:14px; display:block;
}
.work h3{
  font-family:Archivo,sans-serif; font-variation-settings:"wdth" 84,"wght" 500;
  text-transform:uppercase; font-size:clamp(24px,2.6vw,36px); letter-spacing:-.02em;
  margin:0 0 10px; line-height:.95;
}
.work p{margin:0; color:var(--mute); font-size:14.5px; max-width:32ch}
.work__art{position:relative; flex:1; margin:26px -30px 0; min-height:190px; overflow:hidden}

.work__art--order{
  display:flex; flex-direction:column; justify-content:flex-end; gap:14px;
  padding:0 30px 26px;
}
.amt{display:grid; gap:5px}
.amt__label{
  font-family:"Fragment Mono",monospace; font-size:10px; letter-spacing:.16em;
  text-transform:uppercase; color:var(--mute);
}
.amt__value{
  display:flex; align-items:baseline; gap:3px; line-height:1;
  font-family:Archivo,sans-serif; font-variation-settings:"wdth" 84,"wght" 500;
  font-size:clamp(30px,3.4vw,42px); letter-spacing:-.02em;
}
.amt__value b{font-size:.55em; font-weight:inherit; color:var(--mute)}
.amt__caret{
  width:2px; height:.82em; margin-left:3px; background:var(--hot); border-radius:1px;
  animation:caret 1s steps(1) infinite;
}
@keyframes caret{50%{opacity:0}}
.amt__fee{
  font-family:"Fragment Mono",monospace; font-size:10px; letter-spacing:.06em;
  text-transform:uppercase; color:var(--mute);
  transition:color .3s var(--ease);
}
.amt__fee.is-set{color:var(--ink)}

.pad{display:grid; grid-template-columns:repeat(3,1fr); gap:7px}
.pad span{
  height:38px; display:grid; place-items:center; border-radius:11px;
  background:var(--ink); color:#fff; font-size:15px; font-weight:600;
  /* settled state lives here, not in the keyframe: .hit swaps the animation
     out, and a `to`-only padin would drop the key back to invisible */
  animation:padin .5s var(--ease) both;
  transition:background .18s var(--ease), color .18s var(--ease);
}
@keyframes padin{from{transform:translateY(12px); opacity:0} to{transform:none; opacity:1}}
.pad span:nth-child(n){animation-delay:calc(var(--i,0)*40ms)}
/* key strike while the amount types itself */
.pad span.hit{animation:padhit .28s var(--ease)}
@keyframes padhit{
  0%{background:var(--lime); color:var(--ink); transform:scale(.94)}
  100%{background:var(--ink); color:#fff; transform:none}
}

.work__art--track{background:linear-gradient(150deg,#eaff7a,var(--lime))}

/* collapsed panel -> expands on card hover/focus (port of the expand-map interaction) */
.map{
  /* absolutely centred so the % widths below resolve against the art box,
     not against a content-sized grid track */
  position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);
  overflow:hidden; cursor:pointer; text-align:left;
  width:min(84%,230px); height:136px; border-radius:18px;
  background:var(--ink); color:#fff; border:1px solid rgba(255,255,255,.1);
  padding:14px 16px 16px; display:flex; flex-direction:column; justify-content:space-between;
  box-shadow:0 18px 40px -26px rgba(0,0,0,.65);
  transition:width .6s var(--ease), height .6s var(--ease), border-radius .6s var(--ease),
             padding .6s var(--ease), box-shadow .6s var(--ease);
}
.map:focus-visible{outline:2px solid var(--hot); outline-offset:3px}
.work:is(:hover,:focus-within,.is-demo) .map{
  width:calc(100% - 26px); height:calc(100% - 26px); border-radius:16px;
  padding:16px 18px 26px;
  box-shadow:0 26px 60px -28px rgba(0,0,0,.75);
}
.map__grid{
  position:absolute; inset:0; opacity:.07; transition:opacity .4s var(--ease);
  background-image:linear-gradient(rgba(255,255,255,.9) 1px,transparent 1px),
                   linear-gradient(90deg,rgba(255,255,255,.9) 1px,transparent 1px);
  background-size:24px 24px;
}
.work:is(:hover,:focus-within,.is-demo) .map .map__grid{opacity:0}
/* legibility scrim under the label block */
.map::after{
  content:""; position:absolute; left:0; right:0; bottom:0; height:52%; z-index:1;
  background:linear-gradient(to top,rgba(0,0,0,.92) 0%,rgba(0,0,0,.72) 42%,transparent 100%);
  pointer-events:none;
}

.map__view{position:absolute; inset:0; opacity:0; transition:opacity .45s var(--ease) .12s}
.work:is(:hover,:focus-within,.is-demo) .map .map__view{opacity:1}
.map__view svg{position:absolute; inset:0; width:100%; height:100%}
.map__view .streets line{stroke:rgba(255,255,255,.09); stroke-width:1.5}
.map__view .blocks rect{fill:rgba(255,255,255,.07)}
.map__view .road{fill:none; stroke:rgba(255,255,255,.14); stroke-width:9; stroke-linecap:round; stroke-linejoin:round}
/* faint full route + a gradient pulse tracing it (gradient-tracing port) */
.map__view .route{
  fill:none; stroke:var(--lime); stroke-opacity:.22; stroke-width:4;
  stroke-linecap:round; stroke-linejoin:round;
}
.map__view .trace{
  fill:none; stroke-width:4; stroke-linecap:round; stroke-linejoin:round;
}
.map__view .rider{fill:#fff; stroke:var(--ink); stroke-width:2.5}
.pin{position:absolute; width:12px; height:12px; border-radius:50%; background:var(--lime); box-shadow:0 0 0 4px rgba(216,255,74,.16)}
.pin--a{left:8%; bottom:14%}
.pin--b{right:7%; top:20%; background:var(--hot); box-shadow:0 0 0 0 rgba(255,0,229,.55)}
.work:is(:hover,:focus-within,.is-demo) .map .pin--b{animation:ping 2s ease-out infinite}
@keyframes ping{to{box-shadow:0 0 0 22px rgba(255,0,229,0)}}

.map__top{position:relative; z-index:2; display:flex; align-items:center; justify-content:space-between}
.map__icon{
  width:18px; height:18px; color:var(--lime);
  filter:drop-shadow(0 0 4px rgba(216,255,74,.35));
  transition:opacity .3s var(--ease);
}
.map:hover .map__icon{filter:drop-shadow(0 0 9px rgba(216,255,74,.6))}
.work:is(:hover,:focus-within,.is-demo) .map .map__icon{opacity:0}
.map__live{
  display:inline-flex; align-items:center; gap:6px; padding:4px 9px; border-radius:999px;
  background:rgba(255,255,255,.07); font-family:"Fragment Mono",monospace; font-size:9.5px;
  letter-spacing:.12em; text-transform:uppercase; color:rgba(255,255,255,.72);
}
.map__live i{width:5px; height:5px; border-radius:50%; background:var(--lime); animation:blink 1.4s ease-in-out infinite}
@keyframes blink{50%{opacity:.25}}

.map__foot{position:relative; z-index:2; display:block}
.map__foot b{
  display:block; font-size:14px; font-weight:500; letter-spacing:-.01em;
  transition:transform .4s var(--ease);
}
.map:hover .map__foot b{transform:translateX(4px)}
.map__foot em{
  display:block; font-style:normal; font-family:"Fragment Mono",monospace;
  font-size:11px; letter-spacing:.06em; color:rgba(255,255,255,.78);
  max-height:0; opacity:0; overflow:hidden;
  transition:max-height .35s var(--ease), opacity .35s var(--ease), margin .35s var(--ease);
}
.work:is(:hover,:focus-within,.is-demo) .map .map__foot em{max-height:16px; opacity:1; margin-top:4px}
.map__rule{
  display:block; height:1px; margin-top:7px;
  background:linear-gradient(90deg,rgba(216,255,74,.55),rgba(216,255,74,.25),transparent);
  transform:scaleX(.3); transform-origin:0 50%; transition:transform .4s var(--ease);
}
.map:hover .map__rule,.work:is(:hover,:focus-within,.is-demo) .map .map__rule{transform:none}


.work__art--otp{
  display:grid; place-content:center; justify-items:center; gap:16px;
  background:var(--ink); color:var(--lime);
}
.otpf{display:grid; justify-items:center; gap:12px}
.otpf__label{
  font-family:"Fragment Mono",monospace; font-size:11px; letter-spacing:.16em;
  text-transform:uppercase; color:rgba(255,255,255,.72);
}
.otpf__slots{display:flex; gap:8px}
.otpf__slot{
  width:42px; height:54px; border-radius:11px;
  display:grid; place-items:center;              /* spans now, not inputs */
  background:#1c1c1c; border:1px solid rgba(255,255,255,.08); color:var(--lime);
  font-family:Manrope,sans-serif; font-size:22px; font-weight:500;
  transition:border-color .25s var(--ease), background .25s var(--ease);
}
/* digit landing */
.otpf__slot.in{animation:otpflip .34s var(--ease) both}
@keyframes otpflip{0%{transform:rotateX(90deg); opacity:0}100%{transform:none; opacity:1}}

.otpf[data-state=checking] .otpf__slot{border-color:rgba(216,255,74,.3); animation:otpwait 1s ease-in-out infinite}
.otpf[data-state=checking] .otpf__slot:nth-child(2){animation-delay:.08s}
.otpf[data-state=checking] .otpf__slot:nth-child(3){animation-delay:.16s}
.otpf[data-state=checking] .otpf__slot:nth-child(4){animation-delay:.24s}
.otpf[data-state=checking] .otpf__slot:nth-child(5){animation-delay:.32s}
.otpf[data-state=checking] .otpf__slot:nth-child(6){animation-delay:.4s}
@keyframes otpwait{50%{background:#232323; border-color:rgba(216,255,74,.6)}}

.otpf[data-state=ok] .otpf__slot{border-color:rgba(216,255,74,.7); background:rgba(216,255,74,.08)}
.otpf[data-state=bad] .otpf__slot{border-color:rgba(255,0,229,.6); color:var(--hot)}
.otpf[data-state=bad] .otpf__slots{animation:otpshake .32s var(--ease)}
@keyframes otpshake{25%{transform:translateX(-5px)}75%{transform:translateX(5px)}}

.otpf__msg{
  margin:0; min-height:14px; text-align:center;
  font-family:"Fragment Mono",monospace; font-size:10.5px; letter-spacing:.08em;
  text-transform:uppercase; color:rgba(255,255,255,.72);
}
.otpf[data-state=checking] .otpf__msg{color:rgba(216,255,74,.75); animation:blink 1s ease-in-out infinite}
.otpf[data-state=ok] .otpf__msg{color:var(--lime)}
.otpf[data-state=bad] .otpf__msg{color:var(--hot)}

/* =====================================================================
   STACKING CARDS
   ===================================================================== */
.enables{background:var(--paper); padding:clamp(60px,8vw,110px) var(--shell) clamp(70px,10vw,150px)}
.enables__kicker{
  max-width:var(--maxw); margin:0 auto 26px; text-align:center;
  font-size:clamp(15px,1.4vw,19px); font-weight:500; line-height:1.4;
}
.enables__h2{max-width:var(--maxw); margin:0 auto clamp(34px,4.5vw,64px); font-size:clamp(32px,5.4vw,80px); text-align:center}

/* ---- the pinboard: polaroid frames, scattered notes, sticker labels ---- */
.pile{max-width:var(--maxw); margin:0 auto; position:relative}
.pile__row{
  position:relative;
  display:grid; grid-template-columns:1fr; gap:clamp(22px,3vw,44px);
  align-items:center;
}
.pile__art{position:relative; display:flex; justify-content:center; will-change:transform}

/* Pure rotation wrapper - no frame, no fill, no shadow. The device art is a
   transparent cutout that already carries its own bezel, so anything drawn
   behind it reads as a box around the phone. Rotation lives here and never in
   the JS transform on .pile__art. */
.snap{
  position:relative; z-index:2; margin:0; padding:0;
  background:none; border:0; box-shadow:none;
  transform:rotate(var(--rot,0deg));
  transition:transform .65s var(--ease);
}
.snap .shot{display:block; width:100%; height:auto; box-shadow:none; filter:none}
.snap--tall{width:min(248px,62vw)}
/* straightens up when you reach for it */
.pile__art:hover .snap{transform:rotate(0deg) translateY(-4px)}

.pile__label{
  position:absolute; z-index:4; white-space:nowrap;
  font-family:"Permanent Marker","Bradley Hand",Chalkboard,cursive;
  font-size:clamp(13px,1.4vw,19px); line-height:1; letter-spacing:.005em;
  color:var(--ink);                      /* marker ink, always dark */
  padding:11px 24px 12px;
  border:0; border-radius:0; box-shadow:none;
  /* tape: warm, slightly translucent, with a sheen down the middle */
  background:
    linear-gradient(176deg, rgba(255,255,255,.42) 0%, rgba(255,255,255,0) 46%, rgba(0,0,0,.05) 100%),
    rgba(231,216,180,.94);
  /* torn ends - straight top and bottom, ragged left and right */
  clip-path:polygon(0 7%, 4% 0, 96% 3%, 100% 9%, 100% 91%, 96% 100%, 4% 97%, 0 93%);
}

.pile__copy{position:relative; z-index:3}
.pile__no{
  display:block; margin-bottom:11px;
  font-family:"Fragment Mono",monospace; font-size:11px;
  letter-spacing:.14em; color:var(--ink); opacity:.42;
}
.pile__aside{
  display:block; margin-bottom:13px;
  font-family:"Fragment Mono",monospace; font-size:10.5px;
  letter-spacing:.16em; text-transform:uppercase; color:var(--mute);
}
.pile__copy h3{
  font-family:Archivo,sans-serif; font-variation-settings:"wdth" 80,"wght" 500;
  text-transform:uppercase; font-size:clamp(26px,3.3vw,50px); line-height:.9;
  letter-spacing:-.025em; margin:0 0 18px;
}
.pile__copy p{margin:0 0 22px; max-width:40ch; font-size:15.5px; color:var(--mute); line-height:1.6}
.pile__list{list-style:none; margin:0; padding:0; display:flex; flex-wrap:wrap; gap:8px}
.pile__list li{
  font-size:12.5px; font-weight:600; padding:7px 13px; border-radius:999px;
  border:1px solid var(--hair); color:var(--mute);
}

/* --- 3D image belt (Mondragon's process rotor, our screens) ------------ */
/* Geometry is the reference's, to the number: cards hinge on their top edge,
   four of them a quarter-cycle apart, the whole scene turned on its side and
   tilted. --imgrot counter-rotates the artwork inside because .ffg-scene is
   rotated 90deg - without it every screen would ride the belt sideways. */
/* Sticky exactly as the reference has it: the belt is the first item in the
   same track the rows scroll through, so it pins for the whole length of the
   pile while the copy and the polaroids ride up past it. Mondragon pins at
   top:350px in a 900px viewport - a little under half - so 30vh here. It sits
   above the rows on z but takes no pointer events, or it would eat the hover
   on the art underneath. */
.ffg{
  --card:clamp(170px,15vw,200px); --dur:15.25s; --imgrot:-90deg;
  display:grid; place-items:center; overflow:visible;
  perspective:1350px;
  height:calc(var(--card) * 1.35);
  margin:0 auto calc(var(--card) * -.35);
  position:sticky; top:30vh; z-index:5; pointer-events:none;
}
.ffg-scene{
  position:relative; transform-style:preserve-3d;
  width:var(--card); height:var(--card);
  transform:translate3d(4px, calc(var(--card) * .44), 0)
            rotateX(90deg) rotateY(90deg) rotateZ(-67deg);
}
.ffg-ul{
  position:relative; transform-style:preserve-3d;
  width:100%; height:100%; list-style:none; margin:0; padding:0;
}
.ffg-li{
  position:absolute; inset:0; transform-style:preserve-3d;
  transform-origin:center top; will-change:transform;
  animation:ffgTurn var(--dur) linear infinite;
}
/* quarter-cycle apart. Negative delays start each card mid-orbit rather than
   making the first three wait, so the belt is already full on the first frame. */
.ffg-li:nth-child(2){animation-delay:calc(var(--dur) / -4)}
.ffg-li:nth-child(3){animation-delay:calc(var(--dur) / -2)}
.ffg-li:nth-child(4){animation-delay:calc(var(--dur) / -1.3333)}

/* The face box stays square, as the reference has it, because ::before is
   inset:0 and then rotated - a non-square box would stop covering itself the
   moment it turned. The note sits inside it with `contain`, so the whole bill
   reads and nothing is cropped. --imgrot cancels the scene's own 90deg turn:
   at -90deg the note lands horizontal on screen. Flip it to 0deg if it comes
   out standing on its end. Subtle 3D drop-shadow gives realistic folding depth. */
.ffg-li::before,.ffg-li::after{
  content:""; position:absolute; inset:0; overflow:hidden;
  backface-visibility:hidden;
  background-image:var(--bg-img);
  background-position:center center; background-size:contain; background-repeat:no-repeat;
  transform:rotate(var(--imgrot));
  filter:drop-shadow(0 12px 22px rgba(0,0,0,.16)) drop-shadow(0 2px 6px rgba(0,0,0,.10));
}
.ffg-li::after{transform:rotateX(180deg) rotate(var(--imgrot))}

@keyframes ffgTurn{
  0%  {transform:rotateZ(90deg) rotateX(1turn)}
  100%{transform:rotateZ(90deg) rotateX(0turn)}
}

@media (max-width:820px){
  .ffg{
    --card:140px;
    position:relative;
    top:auto;
    height:calc(var(--card) * 1.35);
    margin:12px auto 36px;
    z-index:2;
  }
}

/* --- the scatter itself: angles, offsets and column placement ---------- */
.pile__row--a .snap{--rot:-7deg}
.pile__row--b .snap{--rot:9deg}
.pile__row--c .snap{--rot:-12.5deg}
.pile__row--d .snap{--rot:5.5deg}

.pile__row--a .pile__label{top:2%;    right:4%; transform:rotate(-8deg)}
.pile__row--b .pile__label{bottom:12%; right:2%; transform:rotate(7deg)}
.pile__row--c .pile__label{top:5%;     left:0%;  transform:rotate(-11deg)}
.pile__row--d .pile__label{bottom:8%;  left:0%;  transform:rotate(6deg)}

@media (min-width:821px){
  .pile__row{grid-template-columns:repeat(12,1fr)}
  /* Copy alternates sides, and each cluster sits a little further right than
     the one two rows above it - so the pinboard drifts across the section
     instead of bouncing between two fixed columns. */
  .pile__row--a .pile__art {grid-column:1/6}    /* left,  outer  */
  .pile__row--a .pile__copy{grid-column:7/13}
  .pile__row--b .pile__copy{grid-column:1/7}
  .pile__row--b .pile__art {grid-column:8/13}   /* right, inner  */
  .pile__row--c .pile__art {grid-column:2/7}    /* left,  +1 col */
  .pile__row--c .pile__copy{grid-column:8/13}
  .pile__row--d .pile__copy{grid-column:1/6}
  .pile__row--d .pile__art {grid-column:9/13}   /* right, +1 col */
  /* no art: let the copy breathe across the middle instead of hugging one edge */
  .pile__row--solo .pile__copy{grid-column:2/10}
  /* rows interleave so the pile reads as one pinboard, not four blocks */
  .pile__row + .pile__row{margin-top:calc(clamp(18px,3.4vw,54px) * -1)}
}
@media (max-width:820px){
  /* image first in every row, so the sticker names the feature before you read it */
  .pile__art{order:-1}
  .pile__row + .pile__row{margin-top:clamp(46px,9vw,74px)}
  .snap--tall{width:min(206px,54vw)}
  .pile__label{font-size:13px; padding:9px 18px 10px}
}

/* =====================================================================
   TRUST
   ===================================================================== */
.trust{
  /* full-bleed: capping the width here would stop the paper panel short and
     leak the darker body ground down both edges as vertical bands */
  background:var(--paper);
  padding-block:clamp(70px,9vw,130px);
  padding-inline:max(var(--shell), (100% - var(--maxw)) / 2);
  display:grid; grid-template-columns:.9fr 1.1fr; gap:clamp(30px,5vw,90px);
  align-items:start;
}
.trust__l{align-self:stretch}
.trust__lin{position:sticky; top:calc(var(--nav-h) + 50px)}
.trust__cta{grid-column:1/-1; margin-top:clamp(34px,4vw,56px); display:flex; flex-wrap:wrap; align-items:center; gap:18px 26px}
.trust__cta p{margin:0; font-size:15px; color:var(--mute); max-width:40ch}
.trust__note{margin:22px 0 0; color:var(--mute); font-size:15px; max-width:34ch}

/* Answers are open and side by side. An accordion made the trust argument
   look like something we would rather you did not read. */
.trust__r{
  display:grid; grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(24px,2.6vw,38px) clamp(24px,3vw,48px);
}
.qa{border-top:1px solid var(--hair); padding-top:clamp(14px,1.5vw,20px)}
.qa h3{
  margin:0 0 10px;
  font-family:Archivo,sans-serif; font-variation-settings:"wdth" 88,"wght" 500;
  font-weight:500; font-size:clamp(15px,1.35vw,19px); letter-spacing:-.015em;
  line-height:1.2;
}
.qa p{margin:0; color:var(--mute); font-size:14.5px; line-height:1.62}
.qa em{font-style:normal; color:var(--ink); font-weight:500}

@media (max-width:900px){
  .trust__r{grid-template-columns:1fr; gap:clamp(20px,3vw,28px)}
}

/* =====================================================================
   BAND
   ===================================================================== */
.band{background:var(--paper); padding:clamp(58px,9vw,132px) var(--shell); overflow:hidden}
.band__inner{
  position:relative; isolation:isolate;
  max-width:var(--maxw); margin:0 auto;
  border-top:1px solid var(--ink); padding-top:clamp(22px,2.6vw,38px);
}
.band__label{
  margin:0 0 clamp(18px,2.4vw,34px); display:flex; align-items:center; gap:11px;
  font-family:"Fragment Mono",monospace; font-size:10.5px;
  letter-spacing:.18em; text-transform:uppercase; color:var(--mute);
}
.band__label i{width:28px; height:1px; background:var(--ink); flex:none}
.band__text{
  position:relative; z-index:1;
  max-width:19ch; margin:0; text-align:left;
  font-size:clamp(38px,8.4vw,148px);
  font-variation-settings:"wdth" 70,"wght" 600;
  letter-spacing:-.035em; line-height:.9;
}
/* the reveal clips each word box, so descenders need a little room back */
.band__text .w{
  display:inline-block; overflow:hidden; vertical-align:bottom;
  padding-bottom:.08em; margin-bottom:-.08em;
}
.band__text .w > i{
  display:inline-block; font-style:normal;
  transform:translateY(105%);
  transition:transform .8s var(--ease);
}
.band__text.is-in .w > i{transform:none}
/* oversized currency glyph, bled off the band's bottom-right - decorative only.
   Archivo's condensed rupee is far narrower than the system fallback this was
   first eyeballed against, so the inset is tuned to the real glyph. */
.band__mark{
  position:absolute; z-index:0; right:0; bottom:-.06em;
  font-family:Archivo,sans-serif; font-variation-settings:"wdth" 80,"wght" 700;
  font-size:clamp(160px,26vw,430px); line-height:.7;
  color:transparent; pointer-events:none; user-select:none;
}
@supports (-webkit-text-stroke:1px black){
  .band__mark{-webkit-text-stroke:1px rgba(0,0,0,.17)}
}

/* =====================================================================
   FIELD
   ===================================================================== */
.field{background:var(--paper); padding:clamp(50px,7vw,100px) 0 clamp(70px,9vw,130px)}
.field__head{
  margin:0 0 clamp(34px,4vw,58px);
  padding-inline:max(var(--shell), (100% - var(--maxw)) / 2);
  display:grid; grid-template-columns:minmax(0,1fr) minmax(0,.82fr) auto;
  gap:26px clamp(30px,5vw,80px); align-items:end;
}
.field__lede{margin:0 0 6px; max-width:44ch; font-size:15.5px; line-height:1.6; color:var(--mute)}
.field__nav{display:flex; gap:8px}
.rnd{
  width:48px; height:48px; border-radius:50%; border:1px solid var(--hair);
  background:transparent; cursor:pointer;
  display:grid; place-items:center;
  transition:background .3s, color .3s, transform .3s var(--ease);
}
.rnd:hover{background:var(--ink); color:#fff; transform:scale(1.06)}
.rnd:focus-visible{outline:2px solid var(--hot); outline-offset:3px}

.field__rail{
  display:flex; gap:18px; overflow-x:auto; scroll-snap-type:x mandatory;
  padding-block:6px 26px; scrollbar-width:none;
  padding-inline:max(var(--shell), (100% - var(--maxw)) / 2);
  /* Without this the snapport starts at the border edge, so the browser snaps
     scrollLeft to padding-left on load and the first card sits flush against
     the viewport instead of lining up with the headline above it. */
  scroll-padding-inline:max(var(--shell), (100% - var(--maxw)) / 2);
  cursor:grab;
}
.field__rail::-webkit-scrollbar{display:none}
.field__rail.is-dragging{cursor:grabbing; scroll-snap-type:none}

.quote{
  flex:0 0 min(400px,82vw); scroll-snap-align:start; margin:0;
  background:var(--white); border:1px solid var(--hair); border-radius:var(--r-md);
  padding:28px 30px 30px;
  display:flex; flex-direction:column; gap:22px;
  min-height:392px;
  transition:transform .5s var(--ease);
}
.quote:hover{transform:translateY(-5px)}
.quote--alt{background:var(--lime); border-color:transparent}
.quote--dark{background:var(--ink); color:var(--lime); border-color:transparent}

/* mark + name, where the reference puts a logo and a brand */
.quote__top{display:flex; align-items:center; gap:12px}
.quote__num{
  flex:none; width:38px; height:38px; border-radius:11px;
  display:grid; place-items:center;
  font-family:Archivo,sans-serif; font-variation-settings:"wdth" 78,"wght" 600;
  font-size:15px; letter-spacing:-.02em;
  background:rgba(0,0,0,.07);
}
.quote--dark .quote__num{background:rgba(212,255,61,.15)}
.quote__top b{font-size:16px; font-weight:600; letter-spacing:-.01em}

.quote blockquote,.quote__line{
  margin:0 0 auto; font-family:"Instrument Serif",Georgia,serif; font-weight:400;
  font-size:clamp(20px,2.1vw,27px); line-height:1.22; letter-spacing:-.01em;
}
.quote figcaption{padding-top:17px; border-top:1px solid var(--hair)}
.quote--alt figcaption{border-top-color:rgba(0,0,0,.16)}
.quote--dark figcaption{border-top-color:rgba(212,255,61,.22)}
.quote figcaption span{
  font-family:"Fragment Mono",monospace; font-size:11px; letter-spacing:.1em;
  text-transform:uppercase; opacity:.74;
}


@media (max-width:820px){
  .field__head{grid-template-columns:1fr auto}
  .field__title{grid-column:1/-1}
  .field__lede{grid-column:1}
  .field__nav{grid-column:2}
  .quote{min-height:344px; padding:24px 24px 26px}
}

/* =====================================================================
   MISSION / FOUNDER NOTE
   ===================================================================== */
/* Light section now: the dark run starts at the map below, so .coverage
   carries the slab's top rounding. Black envelope on white, white letter. */
.mission{background:var(--paper); color:var(--ink); padding:clamp(40px,5vh,72px) var(--shell)}
.mission__inner{max-width:980px; margin:0 auto}
.mission__grid{
  margin-top:clamp(18px,2.4vh,32px);
  display:grid; grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(34px,5vw,64px); align-items:center; justify-items:center;
}

/* --- the letter in the envelope ------------------------------------------
   .env__paper is a normal block; the envelope is pulled up over its bottom
   with a percentage margin, so the overlap scales with width and nothing
   needs a fixed aspect ratio. .env clips, so the paper can tuck right down
   inside without ever showing below the envelope's bottom edge.            */
.env{position:relative; width:100%; max-width:420px; overflow:hidden}

.env__paper{
  position:relative; z-index:1;
  width:74%; margin-inline:auto;
  text-align:left;
  padding:clamp(16px,2.4vh,28px) clamp(18px,2.4vw,28px) max(24%, 88px);
  border-radius:var(--r-sm) var(--r-sm) 4px 4px;
  border:1px solid var(--hair); border-bottom-color:transparent;
  background:linear-gradient(180deg,#fff 0%, #fbfbfb 100%);
  box-shadow:0 24px 44px rgba(0,0,0,.14);
  /* tucked at rest, slides out when the section reveals */
  transform:translateY(var(--tuck,48%)) rotate(-2deg);
  transition:transform 1.15s var(--ease) .18s, box-shadow .45s var(--ease);
}
.env.is-in .env__paper{transform:translateY(0) rotate(-2deg)}
.env.is-in:hover .env__paper{
  transform:translateY(-8px) rotate(-2deg);
  box-shadow:0 34px 60px rgba(0,0,0,.2);
}

.env__lede{
  margin:0 0 clamp(11px,1.8vh,16px);
  font-size:clamp(15px,2.1vh,19px); font-weight:600;
  font-variation-settings:"wdth" 100,"wght" 600;
  line-height:1.26; letter-spacing:-.018em; text-transform:none; color:var(--ink);
}
.env__paper p{
  margin:0 0 clamp(8px,1.3vh,11px); max-width:44ch;
  font-size:clamp(11.5px,1.45vh,13px); line-height:1.65;
  color:var(--mute);
}
.env__paper p:last-of-type{margin-bottom:0}

.env__paper .env__signoff{margin-top:clamp(12px,2vh,18px); color:var(--ink)}
.env__paper .env__sign{
  margin:6px 0 0;
  font-family:"Caveat","Segoe Script","Bradley Hand",cursive;
  font-size:clamp(22px,3.4vh,30px); font-weight:600; line-height:1.05;
  letter-spacing:.005em; color:var(--ink);
}
.env__paper .env__role{
  margin:8px 0 0;
  font-family:"Fragment Mono",monospace;
  font-size:9.5px; letter-spacing:.11em; line-height:1.4;
  text-transform:uppercase; color:var(--mute);
}

/* the envelope: two SVGs sandwiching the paper. .env__front stays in flow and
   sets the box; .env__back is pinned to the same rect from behind. Both share
   one viewBox, so every seam lines up at any width. */
.env__front,
.env__back{display:block; width:100%; height:auto; pointer-events:none}
.env__front{position:relative; z-index:2; margin-top:-80%}
.env__back{position:absolute; left:0; bottom:0; z-index:0}
.env__back path,
.env__front path{shape-rendering:geometricPrecision}

/* --- founder portrait ---------------------------------------------------- */
.fnd{margin:0; width:100%; max-width:380px; display:flex; flex-direction:column}
.fnd__frame{
  position:relative; flex:0 0 auto; aspect-ratio:4/5; max-height:56vh; overflow:hidden;
  border-radius:var(--r-md); border:1px solid var(--hair);
  background:var(--paper);
}
.fnd__frame img{width:100%; height:100%; object-fit:cover; display:block}
.fnd__cap{margin:14px 0 0}
.fnd__cap b{display:block; font-size:15px; letter-spacing:-.01em}
.fnd__cap span{
  display:block; margin-top:5px;
  font-family:"Fragment Mono",monospace; font-size:10px; letter-spacing:.11em;
  text-transform:uppercase; color:var(--mute);
}

@media (max-width:820px){
  .mission__grid{grid-template-columns:1fr; gap:clamp(30px,6vw,44px); align-items:stretch}
  .env{width:100%; max-width:440px; margin-inline:auto}
  .fnd{width:100%; max-width:380px; margin-inline:auto}
  .fnd__frame{flex:0 0 auto; aspect-ratio:4/5; min-height:0}
}
@media (max-width:640px){
  .env__paper{width:82%}
  .env__lede{font-size:17px}
  .env__paper p{font-size:13px}
  .env__paper .env__sign{font-size:28px}
}
@media (prefers-reduced-motion:reduce){
  .env__paper{transform:rotate(-2deg) !important; transition:none}
}

/* =====================================================================
   COVERAGE
   ===================================================================== */
.coverage{
  background:var(--ink); color:#fff;
  border-radius:34px 34px 0 0;
  padding-inline:max(var(--shell), (100% - var(--maxw)) / 2);
  padding-top:clamp(60px,8vw,110px);
  padding-bottom:clamp(48px,6vw,86px);
  display:grid; grid-template-columns:1fr 1fr; gap:clamp(30px,5vw,80px);
  align-items:center;
}
.coverage .h2{font-size:clamp(28px,4vw,62px)}
.coverage__list{list-style:none; margin:36px 0 0; padding:0}
.coverage__list li{
  display:flex; justify-content:space-between; align-items:center;
  padding:15px 0; border-bottom:1px solid rgba(255,255,255,.12);
  font-size:15px; font-weight:600;
  transition:padding-left .4s var(--ease), color .3s;
}
.coverage__list li:hover{padding-left:10px}
.coverage__list i{
  font-style:normal; font-family:"Fragment Mono",monospace; font-size:10.5px;
  letter-spacing:.12em; text-transform:uppercase; color:rgba(255,255,255,.72);
}
.coverage__list li:first-child i{color:var(--green)}
.coverage__note{margin:26px 0 0; font-size:14.5px; line-height:1.6; color:rgba(255,255,255,.7); max-width:42ch}
.coverage__note a{color:var(--lime); text-decoration:underline; text-underline-offset:3px}
.coverage a:focus-visible,.coverage button:focus-visible{outline-color:var(--lime)}
.coverage__map{
  position:relative; aspect-ratio:1/1; border-radius:var(--r-lg);
  background:rgba(255,255,255,.03); border:1px solid rgba(255,255,255,.1);
  overflow:hidden;
}
/* --- MapLibre basemap theming (dark section) ----------------------- */
.coverage__map .maplibregl-map{width:100%; height:100%; font:inherit}
.coverage__map canvas{outline:none}
.coverage__map .maplibregl-ctrl-group{
  background:rgba(16,16,16,.86); border:1px solid rgba(255,255,255,.12);
  border-radius:10px; box-shadow:none; overflow:hidden;
}
.coverage__map .maplibregl-ctrl-group button+button{border-top:1px solid rgba(255,255,255,.1)}
.coverage__map .maplibregl-ctrl-group button .maplibregl-ctrl-icon{filter:invert(1) opacity(.7)}
.coverage__map .maplibregl-ctrl-group button:hover{background:rgba(255,255,255,.08)}
.coverage__map .maplibregl-ctrl-attrib{
  background:rgba(0,0,0,.55); border-radius:8px 0 0 0; padding:2px 6px;
  font-family:"Fragment Mono",monospace; font-size:9px;
}
.coverage__map .maplibregl-ctrl-attrib a{color:rgba(255,255,255,.72)}
/* MapLibre's stylesheet is appended to <head> by main.js, so it lands after
   this file. Its `.maplibregl-ctrl-attrib.maplibregl-compact` rule ties the
   rule above on specificity (0,2,0) and wins on source order, repainting the
   pill white - which put the white link colour on a white box and made the
   CARTO / OpenStreetMap credit invisible. One extra class takes the tie back.
   Colours only: MapLibre keeps its own compact padding, which reserves room
   for the toggle button. */
.coverage__map .maplibregl-ctrl-attrib.maplibregl-compact{
  background:rgba(0,0,0,.55); color:rgba(255,255,255,.72);
}
.coverage__map .maplibregl-ctrl-attrib-button{filter:invert(1) opacity(.6)}

/* city markers */
.mk{
  display:block; width:9px; height:9px; border-radius:50%; cursor:pointer;
  background:rgba(255,255,255,.8); box-shadow:0 0 0 3px rgba(0,0,0,.55);
}
.mk--live{
  width:11px; height:11px; background:var(--lime);
  box-shadow:0 0 0 3px rgba(0,0,0,.55), 0 0 0 0 rgba(212,255,61,.6);
  animation:ping 2.4s ease-out infinite;
}
.coverage__map .maplibregl-popup-content{
  background:var(--ink); border:1px solid rgba(255,255,255,.14); border-radius:10px;
  padding:8px 12px; box-shadow:0 18px 40px -22px rgba(0,0,0,.8);
}
.coverage__map .maplibregl-popup-content b{
  display:block; font-size:13px; font-weight:500; color:#fff; letter-spacing:-.01em;
}
.coverage__map .maplibregl-popup-content i{
  display:block; margin-top:2px; font-style:normal;
  font-family:"Fragment Mono",monospace; font-size:9px; letter-spacing:.12em;
  text-transform:uppercase; color:var(--lime);
}
.coverage__map .maplibregl-popup-tip{border-top-color:var(--ink); border-bottom-color:var(--ink)}

.coverage__map .dot{
  position:absolute; width:3px; height:3px; border-radius:50%;
  background:rgba(255,255,255,.22);
}
.coverage__map .dot.hot{
  background:var(--lime); width:7px; height:7px;
  box-shadow:0 0 0 0 rgba(212,255,61,.6); animation:ping 2.4s ease-out infinite;
}

/* =====================================================================
   CTA
   ===================================================================== */
.cta{background:var(--ink); color:#fff; padding:0 var(--shell) clamp(80px,10vw,150px); text-align:center}
.cta__title{font-size:clamp(38px,9.4vw,148px); font-variation-settings:"wdth" 72,"wght" 500}
/* confetti draws over everything and never eats a click */
#confetti{position:fixed; inset:0; width:100%; height:100%; pointer-events:none; z-index:9998}

/* honeypot - offscreen rather than display:none, which some bots skip */
.hp{position:absolute!important; left:-9999px; width:1px; height:1px; opacity:0; pointer-events:none}

.cta__form{
  display:flex; gap:8px; margin:44px auto 0; max-width:560px;
  padding:7px; border-radius:999px;
  background:rgba(255,255,255,.07); border:1px solid rgba(255,255,255,.14);
  transition:border-color .4s, background .4s;
}
.cta__form:focus-within{border-color:rgba(255,255,255,.4); background:rgba(255,255,255,.1)}
.cta__form input{
  flex:1; min-width:0; border:0; background:transparent; padding:0 20px;
  font-size:15px; color:#fff; outline:none;
}
.cta__form input::placeholder{color:rgba(255,255,255,.58)}
.cta__form button{
  border:0; cursor:pointer; border-radius:999px; padding:15px 26px;
  background:#fff; color:var(--ink); font-size:14.5px; font-weight:500;
  display:flex; align-items:center; gap:7px;
  transition:transform .35s var(--ease), background .3s;
}
.cta__form button:hover{transform:scale(1.03); background:var(--lime)}
.cta__form button:focus-visible{outline:2px solid var(--lime); outline-offset:3px}
.cta__form input:focus-visible{outline:2px solid var(--lime); outline-offset:1px}
.cta__msg{
  margin:18px 0 0; min-height:20px;
  font-family:"Fragment Mono",monospace; font-size:12px; letter-spacing:.06em;
  text-transform:uppercase; color:var(--green);
}
.cta__msg.err{color:var(--magenta)}
.cta__next{
  margin:20px auto 0; max-width:min(640px,100%); text-align:center;
  font-size:14.5px; line-height:1.6; color:rgba(255,255,255,.88);
}
.cta__consent{
  margin:16px auto 0; max-width:min(500px,100%); text-align:center;
  font-size:12.5px; line-height:1.65; color:rgba(255,255,255,.72);
}
.cta__consent a{color:#fff; text-decoration:underline; text-underline-offset:2px}

/* =====================================================================
   FOOTER
   The footer is not scrolled to, it is revealed: it pins to the viewport
   bottom at z-index 0 and MAIN slides over it on a curved bottom edge.
   The curve is not a radius on the last section - it is an ink-coloured
   strip hanging off MAIN, so the seam reads at every scroll position and
   does not pop in only once main has cleared it.
   ===================================================================== */
:root{--f-curve:60px; --f-curve-r:52px}

/* scoped to the page that actually has a footer - privacy.html and terms.html
   share this stylesheet and would otherwise grow a stray black curved strip */
main:has(~ .foot){position:relative; z-index:1; background:var(--ground)}
main:has(~ .foot)::after{
  content:""; position:absolute; left:0; right:0; top:100%;
  height:var(--f-curve); pointer-events:none;
  background:var(--ink);                 /* matches .cta, the last section */
  border-radius:0 0 var(--f-curve-r) var(--f-curve-r);
  /* main and the footer are both near-black, so the corners alone would not
     read as two planes - the cast shadow is what sells the layering */
  box-shadow:0 26px 54px rgba(0,0,0,.75);
  /* the rounded border traces the seam - on black-over-black the shadow alone
     is too soft to tell you where one plane ends */
  border-bottom:1px solid rgba(255,255,255,.11);
}

.foot{
  position:sticky; bottom:0; z-index:0;
  background:#000; color:#fff; overflow:hidden;
  padding:calc(var(--f-curve) + clamp(26px,3vw,42px)) var(--shell) 0;
}
/* one cold wash so the ground is not a flat black rectangle */
.foot::before{
  /* Was inset -10% left and right, making the glow box 120% of the footer.
     It is absolutely positioned, so that bleed was real scrollable overflow -
     ~38px of sideways drag on a 375px viewport. Pulled back to the footer's
     own width; the gradient's horizontal radius goes 46% -> 55.2% (46 x 1.2)
     so the glow is drawn at exactly the same size as before. */
  content:""; position:absolute; inset:auto 0 -30% 0; height:70%;
  pointer-events:none;
  background:radial-gradient(55.2% 58% at 50% 100%,rgba(212,255,61,.10) 0%,rgba(212,255,61,.03) 46%,transparent 72%);
}
.foot > *{position:relative; z-index:1}

.foot__stage{
  max-width:var(--maxw); margin:0 auto;
  display:grid; grid-template-columns:minmax(0,1.4fr) minmax(0,1.35fr) minmax(0,1fr);
  gap:clamp(24px,3.4vw,56px); align-items:start;
}

/* ---- left ---- */
.foot__eyebrow{
  margin:0 0 clamp(14px,1.8vw,22px); display:flex; align-items:center; gap:11px;
  font-family:"Fragment Mono",monospace; font-size:10.5px;
  letter-spacing:.18em; text-transform:uppercase; color:rgba(255,255,255,.6);
}
.foot__eyebrow i{width:28px; height:1px; background:var(--lime); flex:none}
.foot__say{
  margin:0 0 clamp(20px,2.6vw,34px);
  font-family:Archivo,sans-serif; font-variation-settings:"wdth" 76,"wght" 600;
  font-size:clamp(34px,3.6vw,58px); line-height:.94; letter-spacing:-.03em;
  text-transform:uppercase;
}
.foot__legal{display:grid; gap:12px; max-width:46ch}
.foot__legal p{margin:0; font-size:12.5px; line-height:1.7; color:rgba(255,255,255,.6)}
.foot__legal b{color:#fff; font-weight:600}
.foot__card{
  margin-top:clamp(22px,2.8vw,36px); max-width:400px;
  display:flex; align-items:center; justify-content:space-between; gap:18px;
  padding:16px 18px; border:1px solid rgba(255,255,255,.16); border-radius:14px;
}
.foot__card b{display:block; font-size:14.5px; font-weight:600}
.foot__card span{display:block; margin-top:4px; font-size:12.5px; line-height:1.55; color:rgba(255,255,255,.6)}
.foot__book{
  flex:none; padding:10px 16px; border-radius:999px;
  background:var(--lime); color:var(--ink); font-size:13px; font-weight:600;
  transition:transform .3s var(--ease);
}
.foot__book:hover{transform:scale(1.05)}

/* ---- centre carousel: a spiral staircase of cards on a vertical axis ----
   Ported 1:1 off the reference footer, which is a three.js scene. Its numbers
   are in world units; --u is the px-per-unit, fixed by the camera it used
   (40deg fov at z=52), so the whole thing is one multiplication away from the
   original: reel height = 2 * 52 * tan(20deg) * --u = 480px.
     count 8 - gap .2 - card 6x8 - corner .38 - yStep -3.1 - yWave 1.3
     speed .222 rad/s (= 28.3s a turn) - direction reverse
   Ring radius is the reference's own formula, (card + gap) / (2 sin(pi/8)). */
.foot__reel{
  --u:12.7px;                       /* world unit -> px */
  --card-w:calc(6 * var(--u));
  --card-h:calc(8 * var(--u));
  --ring:calc(8.1013 * var(--u));   /* 6.2 / (2 * sin(22.5deg)) */
  position:relative; height:480px; align-self:center;
  /* the reference clips at the sides and leaves the top and bottom alone -
     tiles exit by turning edge-on, not by sliding out of frame */
  overflow:hidden;
}
/* camera distance, 52 units, is exactly CSS perspective */
.foot__swirl{position:absolute; inset:0; perspective:calc(52 * var(--u))}
.foot__helix{
  position:absolute; left:50%; top:50%;
  transform-style:preserve-3d; will-change:transform;
  /* negative, so the near face travels left - the direction the original turns */
  animation:footTurn 28.3s linear infinite;
}
@keyframes footTurn{from{transform:rotateY(0deg)} to{transform:rotateY(-360deg)}}

/* rotateY(a) translateZ(R) reproduces the reference's mesh exactly: it both
   places the card at (sin a * R, cos a * R) and turns it to face outwards,
   which is what setting position + rotation.y to the same angle did there.
   CSS y points down where three's points up, hence the flipped signs. */
.foot__cell{
  position:absolute; left:0; top:0; transform-style:preserve-3d;
  transform:
    rotateY(calc(var(--i) * 45deg))
    translateZ(var(--ring))
    translateY(calc((3.1 * (var(--i) - 3.5) - 1.3 * sin(var(--i) * 45deg)) * var(--u)));
}
.foot__chip{
  display:block; width:var(--card-w); height:var(--card-h); max-width:none;
  margin:calc(var(--card-h) / -2) 0 0 calc(var(--card-w) / -2);
  /* cropped to the top of each screen, where the one big thing on it lives -
     a whole shrunken screenshot reads as noise at this size */
  object-fit:cover; object-position:50% 15%;
  border-radius:38%/28.5%;          /* cornerRadius .38 of the card width */
  /* these screens are dark UI on a black ground; without a lift they sink */
  filter:brightness(1.18) saturate(1.08);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.07);
  /* the original material is double-sided, so the far half of the ring shows
     the same art mirrored - which is what a plain backface gives us free */
}
.foot__reel:hover .foot__helix{animation-play-state:paused}

/* 3D transforms only - without them every tile stacks on the centre point */
@supports not (transform-style:preserve-3d){
  .foot__reel{display:none}
}
/* sin() is what places the cards; no trig means no spiral, only a flat ring */
@supports not (top:calc(1px * sin(45deg))){
  .foot__reel{display:none}
}

/* ---- right ---- */
.foot__menu{display:flex; flex-direction:column; gap:2px; margin-bottom:clamp(24px,3vw,40px)}
.foot__menu a{
  width:fit-content;
  font-family:Archivo,sans-serif; font-variation-settings:"wdth" 82,"wght" 500;
  font-size:clamp(20px,1.9vw,30px); line-height:1.24; letter-spacing:-.02em;
  text-transform:uppercase; color:rgba(255,255,255,.82);
  transition:color .25s, transform .35s var(--ease);
}
.foot__menu a:hover{color:var(--lime); transform:translateX(6px)}
.foot__block{margin-bottom:clamp(16px,2vw,24px)}
.foot__block b{
  display:block; margin-bottom:9px;
  font-family:"Fragment Mono",monospace; font-size:10.5px; font-weight:400;
  letter-spacing:.14em; text-transform:uppercase; color:rgba(255,255,255,.55);
}
.foot__block a,.foot__block span{
  display:block; width:fit-content; font-size:14px; color:rgba(255,255,255,.78);
  transition:color .25s, transform .35s var(--ease);
}
.foot__block a:hover{color:#fff; transform:translateX(4px)}
.foot__block a.foot__top{
  display:inline-flex; align-items:center; gap:6px;
  width:fit-content; white-space:nowrap;
  font-family:Manrope,sans-serif; font-size:13.5px; font-weight:500;
  color:rgba(255,255,255,.75); text-decoration:none;
  cursor:pointer;
  transition:color .25s;
}
.foot__block a.foot__top svg{
  display:inline-block;
  transition:transform .25s var(--ease);
}
.foot__block a.foot__top:hover{
  color:#fff; transform:none;
}
.foot__block a.foot__top:hover svg{
  transform:translateY(-2px);
}
.foot a:focus-visible,.foot button:focus-visible{outline-color:var(--lime)}

.foot__bar{
  max-width:var(--maxw); margin:clamp(22px,2.6vw,38px) auto 0; padding:18px 0;
  display:flex; justify-content:space-between; align-items:center; gap:16px; flex-wrap:wrap;
  border-top:1px solid rgba(255,255,255,.12);
  font-family:"Fragment Mono",monospace; font-size:10.5px;
  letter-spacing:.12em; text-transform:uppercase; color:rgba(255,255,255,.6);
}
.foot__bar-links{display:flex; gap:18px}
.foot__bar a:hover{color:#fff}

/* The mark bleeds off the page bottom rather than fitting on it. The crop is
   also the height budget: the footer has to stay inside one viewport or the
   sticky reveal has nothing to pin to. */
.foot__wordmark{
  margin:clamp(6px,1.2vw,16px) calc(var(--shell) * -1) 0; padding:0 4vw;
  height:clamp(72px,15vw,215px); overflow:hidden;
  user-select:none; pointer-events:none;
}
.foot__wordmark img{
  display:block; width:100%; height:auto;
  filter:invert(1); opacity:.07;
}

@media (prefers-reduced-motion:reduce){
  /* paused rather than none: each card's place on the spiral comes from --i,
     not from the animation, so the composition survives - it just stops moving */
  .foot__helix{animation-play-state:paused}
}

/* =====================================================================
   BUTTERFLY CURSOR  (CTA + footer)
   Two mirrored wings clipped out of the 500 note, hinged on a body and
   flapped with rotateY. Follows the cursor on a CSS transition rather than
   rAF, so it stays smooth without a per-frame loop.
   ===================================================================== */
.fly{
  position:fixed; left:0; top:0; z-index:60; pointer-events:none;
  width:150px; height:112px; margin:-56px 0 0 -75px;
  opacity:0; transform:translate3d(-400px,-400px,0);
  transition:opacity .3s ease, transform .34s cubic-bezier(.22,.8,.3,1);
  perspective:520px; will-change:transform,opacity;
}
.fly.is-on{opacity:1}
.fly__side{position:absolute; left:50%; top:0; width:75px; height:112px}
.fly__side--l{transform:scaleX(-1); transform-origin:left center}
.fly__up,.fly__lo{
  position:absolute; left:0; display:block;
  background-repeat:no-repeat;
  transform-origin:left center;
  transform:rotateY(16deg);          /* fixed origami tilt - wings do not flap */
  filter:drop-shadow(0 4px 7px rgba(0,0,0,.4));
}
/* Wings are cut from the CORNERS of the note - the numerals and guilloche
   borders - not the middle, so no portrait lands on a wing. Paths carry
   rounded joins so the folds read as creased paper, not cut glass. */
.fly__up{
  top:4px; width:70px; height:58px;
  background-size:330% auto; background-position:100% 0%;
  clip-path:path("M6.9 49.0 Q2.0 50.0 2.8 45.1 L8.2 10.9 Q9.0 6.0 14.0 5.7 L62.0 3.3 Q67.0 3.0 64.3 7.2 L44.7 37.8 Q42.0 42.0 37.1 43.0 Z");
}
.fly__lo{
  top:54px; width:58px; height:52px;
  background-size:360% auto; background-position:100% 100%;
  clip-path:path("M3.1 9.9 Q2.0 5.0 7.0 4.7 L31.0 3.3 Q36.0 3.0 38.6 7.3 L52.4 29.7 Q55.0 34.0 50.2 35.5 L16.8 46.5 Q12.0 48.0 10.9 43.1 Z");
}
/* body is a rolled sliver of the note itself, not a drawn stroke */
.fly__body{
  position:absolute; left:50%; top:26%; width:9px; height:46px;
  margin-left:-4.5px; border-radius:5px/7px;
  background:6% 50%/auto 460% no-repeat;
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.35), 0 3px 6px rgba(0,0,0,.4);
}
body.fly-armed :is(.fly__up,.fly__lo,.fly__body){background-image:url("assets/notes/500.webp")}

/* the butterfly IS the cursor over the map - pointer stays on things you click */
body.is-fly{cursor:none}
body.is-fly a,body.is-fly button,body.is-fly input,body.is-fly summary{cursor:pointer}

/* =====================================================================
   REVEALS
   ===================================================================== */
[data-reveal]{opacity:0; transform:translateY(26px); transition:opacity .8s var(--ease), transform .9s var(--ease)}
[data-reveal].is-in{opacity:1; transform:none}

/* The wrapper carries opacity only and each child carries the lift, so the
   number, the headline, the paragraph and the chips land in reading order
   instead of arriving as one slab. */
[data-reveal-stagger]{opacity:0; transition:opacity .5s var(--ease-step)}
[data-reveal-stagger].is-in{opacity:1}
[data-reveal-stagger] > *{
  opacity:0; transform:translateY(22px);
  transition:opacity .55s var(--ease-step), transform .55s var(--ease-step);
}
[data-reveal-stagger].is-in > *{opacity:1; transform:none}
[data-reveal-stagger].is-in > :nth-child(2){transition-delay:.07s}
[data-reveal-stagger].is-in > :nth-child(3){transition-delay:.14s}
[data-reveal-stagger].is-in > :nth-child(4){transition-delay:.21s}
[data-reveal-stagger].is-in > :nth-child(5){transition-delay:.28s}

[data-reveal-lines] .line{display:block; overflow:hidden}
[data-reveal-lines] .line > span{
  display:block; transform:translateY(104%);
  transition:transform .95s var(--ease);
}
[data-reveal-lines].is-in .line > span{transform:none}
[data-reveal-lines].is-in .line:nth-child(2) > span{transition-delay:.08s}
[data-reveal-lines].is-in .line:nth-child(3) > span{transition-delay:.16s}

/* =====================================================================
   RESPONSIVE
   ===================================================================== */
@media (max-width:1080px){
  .works__grid{grid-template-columns:1fr 1fr}
  .work:last-child{grid-column:span 2}
  .trust{grid-template-columns:1fr}
  .trust__l{align-self:auto}
  .trust__lin{position:static}
  .coverage{grid-template-columns:1fr}
  .coverage__map{max-width:520px}
  /* the reel is the first thing to go: the two text columns need the width */
  .foot__stage{grid-template-columns:minmax(0,1.1fr) minmax(0,.8fr)}
  .foot__reel{display:none}
}
/* A footer taller than the viewport cannot pin sensibly - below this the
   reveal is dropped and it is an ordinary block at the end of the page. */
@media (max-width:900px){
  main:has(~ .foot)::after{display:none}
  .foot{position:static; padding-top:clamp(46px,9vw,70px)}
  .foot__stage{grid-template-columns:1fr; gap:34px}
  .foot__card{max-width:none}
}
/* A footer taller than the viewport cannot pin sensibly - below this the
   reveal is dropped and it is an ordinary block at the end of the page. */
@media (max-width:900px){
  main:has(~ .foot)::after{display:none}
  .foot{position:static; padding-top:clamp(46px,9vw,70px)}
  .foot__stage{grid-template-columns:1fr; gap:34px}
  .foot__card{max-width:none}
}
@media (max-width:820px){
  .nav__links{display:none}
  .nav__burger{display:block}
  .nav__cta span:last-child{display:none}
  .nav__cta{padding:0 8px}
}
@media (max-width:760px){
  .nav__tagline{display:none}          /* too long to park legibly this narrow */
}
@media (max-width:640px){
  .works__grid{grid-template-columns:1fr}
  .work:last-child{grid-column:auto}
  .field__head{align-items:flex-start}
}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms !important; animation-iteration-count:1 !important; transition-duration:.001ms !important}
  html{scroll-behavior:auto}
  .ffg-li{animation:none}
  .ffg-li:not(:first-child){display:none}
  .ffg-scene{transform:none}
  .ffg-li::before{transform:none}
  .ffg-li::after{display:none}
  [data-reveal],[data-reveal-stagger],[data-reveal-stagger] > *,
  [data-reveal-lines] .line > span,.band__text .w > i{opacity:1 !important; transform:none !important}
  .grain{display:none}
  /* SMIL ignores prefers-reduced-motion, so drop the moving bits by hand */
  .map__view .rider,.map__view .trace{display:none}
  .map__view .route{stroke-opacity:1}
}

/* =====================================================================
   LEGAL PAGES  (privacy.html, terms.html)
   ===================================================================== */
/* Three columns: the middle one holds the document, the left gutter holds a
   sticky back button so it stays reachable down a long page. Both gutters
   collapse to 0 on narrow screens, where the button goes inline instead. */
.legal{
  --back-d:clamp(26px,2.6vw,34px);   /* == .legal__logo height */
  background:var(--paper); min-height:100vh;
  padding:clamp(24px,4vw,48px) var(--shell) clamp(60px,8vw,110px);
  display:grid; align-items:start;
  grid-template-columns:1fr min(72ch,100%) 1fr;
  column-gap:clamp(20px,5vw,96px);
}
.legal__inner{grid-column:2; min-width:0}

.legal__back{
  grid-column:1; justify-self:end;
  position:relative; position:sticky; top:clamp(24px,4vw,48px);
  width:var(--back-d); aspect-ratio:1; border-radius:50%;
  display:grid; place-items:center; flex:none;
  color:var(--ink); text-decoration:none;
  border:1.2px solid var(--ink); background:transparent;
  transition:background .28s var(--ease), color .28s var(--ease), transform .28s var(--ease);
}
/* the circle matches the logo, but a 34px tap target does not meet the 44px
   minimum, so an invisible overlay carries the hit area */
.legal__back::after{
  content:""; position:absolute; inset:50% auto auto 50%;
  width:max(44px, 100%); height:max(44px, 100%); transform:translate(-50%,-50%);
  border-radius:50%;
}
.legal__back svg{width:46%; height:auto; display:block}
.legal__back:hover{background:var(--ink); color:var(--paper); transform:translateX(-3px)}
.legal__back:focus-visible{outline:2px solid var(--ink); outline-offset:4px}

/* The logo sticks with the back button. It needs an opaque strip behind it,
   fading out at the bottom, or the body text scrolls visibly through it. */
.legal__brand{
  position:sticky; top:0; z-index:2;
  padding:clamp(24px,4vw,48px) 0 16px;
  margin:calc(clamp(24px,4vw,48px) * -1) 0 clamp(16px,2.4vw,26px);
  background:linear-gradient(var(--paper) 0%, var(--paper) 74%, transparent 100%);
}
.legal__logo{height:var(--back-d); width:auto; display:block}

.legal h1{
  font-family:Archivo,sans-serif; font-variation-settings:"wdth" 78,"wght" 500;
  text-transform:uppercase; font-size:clamp(32px,5vw,60px); line-height:.92;
  letter-spacing:-.02em; margin:0 0 10px; color:var(--ink);
}
.legal__meta{
  font-family:"Fragment Mono",monospace; font-size:11px; letter-spacing:.1em;
  text-transform:uppercase; color:var(--mute); margin:0 0 40px;
}
.legal h2{
  font-family:Archivo,sans-serif; font-variation-settings:"wdth" 88,"wght" 500;
  text-transform:uppercase; font-size:17px; letter-spacing:.005em;
  margin:42px 0 12px; color:var(--ink);
}
.legal p,.legal li{color:var(--mute); font-size:15.5px; line-height:1.7; margin:0 0 14px}
.legal strong{color:var(--ink); font-weight:600}
.legal ul{margin:0 0 14px; padding-left:22px}
.legal li{margin-bottom:8px}
.legal a{color:var(--ink); text-decoration:underline; text-underline-offset:2px}

/* what applies to this website specifically, as opposed to the app */
.legal__site{
  margin:0 0 8px; padding:clamp(18px,2.4vw,26px) clamp(18px,2.4vw,28px);
  border:1px solid var(--hair); border-radius:var(--r-md); background:var(--white);
}
.legal__site h2{margin-top:0}
.legal__site p:last-child{margin-bottom:0}

.legal__foot{
  margin-top:clamp(44px,6vw,72px); padding-top:22px; border-top:1px solid var(--hair);
  font-family:"Fragment Mono",monospace; font-size:11px; letter-spacing:.1em;
  text-transform:uppercase;
}

@media (max-width:900px){
  .legal{grid-template-columns:1fr; row-gap:0}
  .legal__inner,.legal__back{grid-column:1}
  .legal__back{position:static; justify-self:start; margin-bottom:26px}
  .legal__back:hover{transform:none}
}


/* =====================================================================
   PROGRESSIVE BOTTOM BLUR  (neiden.framer.media parity)
   Eight stacked backdrop-filter layers, each masked to start where the
   previous one ended. One flat blur reads as a hard band; the ramp of
   0.3 -> 20px behind a staircase of gradient masks is what makes the
   bottom edge pull and smear as content scrolls under it.
   Values lifted verbatim from the reference (8 steps, 8.75% apart).

   Mask and backdrop-filter must sit on the SAME box. Moving the mask to a
   parent wrapper looks like the tidier fix but kills the effect outright:
   a masked element is a Backdrop Root, so a blurred child inside it has an
   empty backdrop and renders nothing.
   ===================================================================== */
.pblur{
  position:fixed; left:0; bottom:0; width:100%;
  /* the ramp stays 120px; the safe-area pad carries it under the home
     indicator so the strip still reaches the physical bottom edge */
  height:calc(120px + env(safe-area-inset-bottom, 0px));
  z-index:500; pointer-events:none; user-select:none; -webkit-user-select:none;
  /* No transform and no overflow here on purpose. A transform makes an element
     a Backdrop Root, which leaves the layers inside it with an empty backdrop
     to sample - Chrome tolerates it, WebKit does not, and a blurred empty
     backdrop paints as a flat white wash on iOS. Neither property earned its
     place: the layers are inset:0 so there is nothing to clip, and the
     translateZ was only a compositing hint. */
}
.pblur i{position:absolute; inset:0; display:block; pointer-events:none}
.pblur i:nth-child(1){
  backdrop-filter:blur(0.3px) saturate(120%); -webkit-backdrop-filter:blur(0.3px) saturate(120%);
  mask-image:linear-gradient(to bottom, transparent 0%, transparent 0%, black 8.75%, black 100%);
  -webkit-mask-image:linear-gradient(to bottom, transparent 0%, transparent 0%, black 8.75%, black 100%);
}
.pblur i:nth-child(2){
  backdrop-filter:blur(1.3px) saturate(120%); -webkit-backdrop-filter:blur(1.3px) saturate(120%);
  mask-image:linear-gradient(to bottom, transparent 0%, transparent 8.75%, black 17.5%, black 100%);
  -webkit-mask-image:linear-gradient(to bottom, transparent 0%, transparent 8.75%, black 17.5%, black 100%);
}
.pblur i:nth-child(3){
  backdrop-filter:blur(2.8px) saturate(120%); -webkit-backdrop-filter:blur(2.8px) saturate(120%);
  mask-image:linear-gradient(to bottom, transparent 0%, transparent 17.5%, black 26.25%, black 100%);
  -webkit-mask-image:linear-gradient(to bottom, transparent 0%, transparent 17.5%, black 26.25%, black 100%);
}
.pblur i:nth-child(4){
  backdrop-filter:blur(5px) saturate(120%); -webkit-backdrop-filter:blur(5px) saturate(120%);
  mask-image:linear-gradient(to bottom, transparent 0%, transparent 26.25%, black 35%, black 100%);
  -webkit-mask-image:linear-gradient(to bottom, transparent 0%, transparent 26.25%, black 35%, black 100%);
}
.pblur i:nth-child(5){
  backdrop-filter:blur(7.8px) saturate(120%); -webkit-backdrop-filter:blur(7.8px) saturate(120%);
  mask-image:linear-gradient(to bottom, transparent 0%, transparent 35%, black 43.75%, black 100%);
  -webkit-mask-image:linear-gradient(to bottom, transparent 0%, transparent 35%, black 43.75%, black 100%);
}
.pblur i:nth-child(6){
  backdrop-filter:blur(11.3px) saturate(120%); -webkit-backdrop-filter:blur(11.3px) saturate(120%);
  mask-image:linear-gradient(to bottom, transparent 0%, transparent 43.75%, black 52.5%, black 100%);
  -webkit-mask-image:linear-gradient(to bottom, transparent 0%, transparent 43.75%, black 52.5%, black 100%);
}
.pblur i:nth-child(7){
  backdrop-filter:blur(15.3px) saturate(120%); -webkit-backdrop-filter:blur(15.3px) saturate(120%);
  mask-image:linear-gradient(to bottom, transparent 0%, transparent 52.5%, black 61.25%, black 100%);
  -webkit-mask-image:linear-gradient(to bottom, transparent 0%, transparent 52.5%, black 61.25%, black 100%);
}
.pblur i:nth-child(8){
  backdrop-filter:blur(20px) saturate(120%); -webkit-backdrop-filter:blur(20px) saturate(120%);
  mask-image:linear-gradient(to bottom, transparent 0%, transparent 61.25%, black 70%, black 100%);
  -webkit-mask-image:linear-gradient(to bottom, transparent 0%, transparent 61.25%, black 70%, black 100%);
}

/* ============ COOKIE BANNER ============
   Injected by consent.js. One low pill floating clear of the viewport edges -
   icon, a single line, then the two choices. Light, like the nav pill, so it
   reads as part of the furniture rather than a black slab dropped on the page.
   Sits above .pblur (z-index 500) so the bottom blur never washes over it. */
.cbar{
  --cbar-gap: clamp(14px, 2.2vw, 26px);
  position:fixed; z-index:9990;
  left:var(--cbar-gap); right:var(--cbar-gap);
  bottom:calc(var(--cbar-gap) + env(safe-area-inset-bottom, 0px));
  max-width:min(var(--maxw), 920px); margin-inline:auto;
  display:flex; align-items:center; gap:14px;
  padding:10px 10px 10px 18px;
  background:var(--white); color:var(--ink);
  border:1px solid var(--hair);
  border-radius:999px;
  box-shadow:0 18px 44px rgba(0,0,0,.13), 0 2px 8px rgba(0,0,0,.06);
  transform:translateY(calc(100% + var(--cbar-gap))); opacity:0;
  transition:transform .55s var(--ease), opacity .4s var(--ease);
}
.cbar.is-in{transform:none; opacity:1}

.cbar__ico{flex:none; display:block; color:var(--ink)}
.cbar__t{
  flex:1 1 auto; min-width:0; margin:0;
  font-size:14px; line-height:1.45; color:var(--ink);
}
.cbar__t a{color:var(--mute); text-decoration:underline; text-underline-offset:3px}
.cbar__t a:hover{color:var(--ink)}

.cbar__b{display:flex; align-items:center; gap:8px; margin-left:auto; flex:none}
.cbar button{
  font:inherit; font-size:14px; font-weight:500; cursor:pointer;
  padding:11px 22px; border-radius:999px; border:0;
  white-space:nowrap;
  transition:transform .35s var(--ease), background .3s var(--ease), color .3s var(--ease);
}
.cbar__no{background:rgba(0,0,0,.05); color:var(--ink)}
.cbar__no:hover{background:rgba(0,0,0,.09)}
.cbar__ok{background:var(--ink); color:#fff}
.cbar__ok:hover{background:var(--lime); color:var(--ink); transform:scale(1.03)}
.cbar :focus-visible{outline:2px solid var(--ink); outline-offset:3px}

/* Narrow: one line plus two pills will not sit in a row, so the pill becomes
   a small card - the icon stays on the sentence, the buttons take their own. */
@media (max-width:760px){
  .cbar{
    flex-wrap:wrap; gap:12px 12px;
    padding:16px; border-radius:var(--r-md);
  }
  /* icon stays on the sentence - giving it a row of its own wastes a line */
  .cbar__t{flex:1 1 200px; font-size:13.5px}
  .cbar__b{flex:1 1 100%; margin-left:0}
  .cbar__b button{flex:1; padding:12px 18px}
}
@media (prefers-reduced-motion:reduce){
  .cbar{transition:none; transform:none; opacity:1}
  .cbar__ok:hover{transform:none}
}
