/* ============================================================
   VTDO — The Green Thread
   ------------------------------------------------------------
   Two green treatments, chosen by plate tone:
     ink   -> Signal Lime #B9F23B, plus-lighter (adds light)
     cream -> Deep Lime  #7FA828, multiply (behaves like pigment)
   Emitting cores stay near-white on both, because a lit filament
   reads the same way on any ground.

   Type is Archivo variable. The width axis does the work here —
   62% condensed at display sizes, back to ~90% for reading. That
   width shift is the house voice; it is not decoration.
   ============================================================ */

:root{
  --ink:#111111; --cream:#F6F4EF; --alt:#EAE7DF;
  --muted:#585751; --rule:#CFCBC0;
  --lime:#B9F23B; --lime-deep:#7FA828; --core:#EFFFC4;

  --rail:1720px;
  --pad:clamp(20px,4.2vw,84px);
}

*{box-sizing:border-box}
html{scroll-behavior:auto}
body{
  margin:0; background:var(--ink); color:var(--cream);
  font-family:"Archivo","Helvetica Neue",Arial,sans-serif;
  font-size:17px; line-height:1.5; font-stretch:100%;
  -webkit-font-smoothing:antialiased; overflow-x:hidden;
}

/* ============================================================
   THE OVERLAY — one continuous object for the whole document
   ============================================================ */
.thread{position:fixed;inset:0;width:100vw;height:100svh;pointer-events:none;z-index:40;
  mix-blend-mode:plus-lighter}
.thread.on-light{mix-blend-mode:normal}
.thread-spine{display:none}
.thread-spine-lit{stroke:var(--lime);stroke-width:2;opacity:0;stroke-linecap:round}
.thread.on-light .thread-spine-lit{stroke:var(--lime-deep)}
.dot-glow{fill:url(#dotglow)}
.thread.on-light .dot-glow{fill:url(#dotglowD)}
.dot-ping{fill:none;stroke:var(--lime);stroke-width:1.4;opacity:0}
.thread.on-light .dot-ping{stroke:var(--lime-deep)}
.dot-core{fill:var(--core)}
.dot-hand{opacity:0}
.dot-car{opacity:0}
.car-p,.car-w{fill:var(--lime)}
.thread.on-light .car-p,.thread.on-light .car-w{fill:var(--lime-deep)}
.hand-p{fill:var(--lime)}
.thread.on-light .hand-p{fill:var(--lime-deep)}
/* a near-white core vanishes on cream, so it takes the pigment green there */
.thread.on-light .dot-core{fill:var(--lime-deep)}

.prog{position:fixed;top:0;left:0;right:0;height:2px;background:rgba(128,128,128,.16);z-index:60}
.prog span{display:block;height:100%;width:0;background:var(--lime)}

/* ============================================================
   SECTIONS
   Every beat is a full-bleed plate. The rail sits inside it and
   its alignment CHANGES per beat — that variation is the point.
   ============================================================ */
.plates{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
.plate{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;
  will-change:transform,opacity}

main{position:relative;z-index:2}

/* Sections are transparent windows onto the fixed plate stack. The scrim is
   what carries the ink/cream tone, so the ground can dissolve between beats
   instead of cutting. */
/* overflow:clip, not hidden — clip does not create a scroll container, so the
   sticky stage inside still works. hidden would make it inert. */
.s{position:relative;min-height:100svh;overflow:clip;padding:0}

/* Each section holds while its foreground sequence plays. The extra height is
   the runway; the sticky rail is what freezes on screen while you spend it. */
/* The runway belongs to the stage, not the section. Sticky is bounded by its
   containing block, so anything else inside the section scrolls THROUGH the
   freeze — which is what put the closing line over the top of the frame. */
.stage{position:relative}
[data-beat="leaks"]    .stage{min-height:205svh}
[data-beat="teardown"] .stage{min-height:420svh}
[data-beat="checks"]   .stage{min-height:170svh}
[data-beat="process"]  .stage{min-height:240svh}
[data-beat="about"]    .stage{min-height:215svh}
[data-beat="contact"]  .stage{min-height:168svh}
.s.dark{color:var(--cream)}
.s.light{color:var(--ink)}

/* Scrim protects the type column only. The remaining frame is left
   as render — that is what stops the page reading as a template with
   a photo behind it. */
.scrim{position:absolute;inset:0;z-index:1;pointer-events:none;
  -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 17%,#000 83%,transparent 100%);
          mask-image:linear-gradient(180deg,transparent 0,#000 17%,#000 83%,transparent 100%)}
.s.dark  .scrim{background:linear-gradient(94deg,rgba(17,17,17,.94) 0%,rgba(17,17,17,.84) 30%,rgba(17,17,17,.44) 56%,rgba(17,17,17,.04) 86%,rgba(17,17,17,0) 100%)}
.s.light .scrim{background:linear-gradient(94deg,rgba(246,244,239,.95) 0%,rgba(246,244,239,.86) 30%,rgba(246,244,239,.46) 56%,rgba(246,244,239,.04) 86%,rgba(246,244,239,0) 100%)}
/* second, softer pass from the bottom so long copy never floats on noise */
.s::after{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 17%,#000 83%,transparent 100%);
          mask-image:linear-gradient(180deg,transparent 0,#000 17%,#000 83%,transparent 100%)}
.s.dark::after{background:linear-gradient(0deg,rgba(17,17,17,.7) 0%,rgba(17,17,17,0) 42%)}
.s.light::after{background:linear-gradient(0deg,rgba(246,244,239,.7) 0%,rgba(246,244,239,0) 42%)}

.grain{position:absolute;inset:0;z-index:2;pointer-events:none;opacity:.055;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/></filter><rect width='160' height='160' filter='url(%23n)'/></svg>")}
.s.light .grain{mix-blend-mode:multiply}

.rail{position:sticky;top:0;z-index:5;width:100%;max-width:var(--rail);margin:0 auto;
  min-height:100svh;display:flex;flex-direction:column;justify-content:center;
  padding:clamp(96px,11svh,150px) var(--pad)}

/* sits on the plate's own glow, which moved when the plate was pushed right */
.orb{position:absolute;z-index:3;left:63.5%;top:66%;width:2px;height:2px;pointer-events:none}

/* line-split reveal: each line rides up out of its own mask */
/* The mask has to be taller than the line box or it slices descenders:
   line-height is .83 but Archivo's g/y/p hang ~.21em below the baseline.
   Padding opens the mask, the negative margin gives the space back to
   layout, so spacing is unchanged and nothing is clipped. */
.ln{display:block;overflow:hidden;padding-bottom:.24em;margin-bottom:-.24em}
.ln > i{display:block;font-style:inherit;will-change:transform}
/* the hinge between the setup and the payoff — h1 only, so the H2s keep their
   uniform leading */
h1 .ln-turn{margin-top:.13em}
.w.is-em{color:var(--lime)}
.s.light .w.is-em{color:var(--lime-deep)}

/* ============================================================
   THE STAMP — oversized outlined beat numeral, bleeding off an
   edge. Repeats across the page for cohesion, moves every time so
   the composition never repeats.
   ============================================================ */
/* The numeral is pinned to the viewport for the whole beat. Anchored to the
   section instead, a bottom-set stamp only shows at the very end of its
   section and a top-set one has already scrolled away. */
/* The numeral is pinned to the viewport, not the section, so it bleeds off
   the screen edge and stays in frame for the whole beat. Anchored to the
   section it leaves as soon as you scroll — and CSS sticky is no use here,
   .s needs overflow:hidden for the bleed and that makes sticky inert. */
.stamp-hold{position:fixed;inset:0;z-index:3;pointer-events:none;opacity:0}
.stamp-vp{position:relative;width:100%;height:100%}

.stamp{position:absolute;pointer-events:none;user-select:none;
  font-size:clamp(200px,32vw,520px);line-height:.66;font-weight:820;font-stretch:62%;
  letter-spacing:-.05em;color:transparent;
  -webkit-text-stroke:1.5px rgba(207,203,192,.15)}
.s.light .stamp{-webkit-text-stroke-color:rgba(17,17,17,.10)}

/* One position, every beat: upper left, behind the copy but in front of the
   plate. Consistency makes it a system mark rather than decoration. */
.stamp{left:-.06em;top:-.10em}
[data-beat="contact"] .stamp{-webkit-text-stroke-color:rgba(185,242,59,.24)}

/* ============================================================
   HEADER — full bar at rest, condenses to a pill on scroll
   ============================================================ */
/* Capped and centred exactly like .rail, or the header and the copy stop
   sharing a left edge on viewports wider than --rail. */
.hdr{position:fixed;top:0;left:0;right:0;margin:0 auto;max-width:var(--rail);
  z-index:70;display:flex;align-items:center;
  justify-content:space-between;gap:24px;padding:clamp(16px,2.2svh,26px) var(--pad);
  transition:padding .45s cubic-bezier(.6,0,.2,1)}
/* the wash behind it stays full-bleed */
.hdr::before{content:"";position:absolute;top:0;bottom:0;left:50%;width:100vw;
  transform:translateX(-50%);z-index:-1;pointer-events:none;
  background:linear-gradient(180deg,rgba(17,17,17,.62),rgba(17,17,17,0));
  opacity:1;transition:opacity .4s ease}
.hdr.cond::before{opacity:0}

.pack{display:flex;align-items:center;gap:12px;order:-1;
  border-radius:999px;padding:0;background:transparent;
  transition:background-color .45s ease,padding .45s ease,box-shadow .45s ease}
.hdr.cond .pack{order:1;padding:7px 7px 7px 16px;
  background:rgba(17,17,17,.72);backdrop-filter:blur(14px) saturate(1.1);
  box-shadow:0 1px 0 rgba(207,203,192,.14) inset}
.hdr.cond{justify-content:flex-end}

.brand{display:inline-flex;align-items:center;text-decoration:none;color:inherit}
/* horizontal lockup at rest, the icon alone once the header condenses */
.lg-full{display:block;height:clamp(28px,2.4vw,38px);width:auto}
.lg-icon{display:none;height:24px;width:auto}
.hdr.cond .lg-full{display:none}
.hdr.cond .lg-icon{display:block}
.ftr .lg-full{height:38px}

.burger{display:none;width:42px;height:42px;flex:none;border:0;border-radius:999px;
  background:var(--lime);cursor:pointer;align-items:center;justify-content:center;
  flex-direction:column;gap:5px;padding:0}
.hdr.cond .burger{display:flex}
.burger span{display:block;width:16px;height:2px;background:var(--ink);border-radius:2px;
  transition:transform .32s cubic-bezier(.6,0,.2,1),opacity .2s ease}
.hdr.open .burger span:first-child{transform:translateY(3.5px) rotate(45deg)}
.hdr.open .burger span:last-child{transform:translateY(-3.5px) rotate(-45deg)}

.nav{display:flex;align-items:center;gap:clamp(16px,1.9vw,32px)}
.nav a{color:var(--rule);text-decoration:none;font-size:14px;font-weight:620;
  font-stretch:92%;letter-spacing:-.005em;transition:color .2s ease}
.nav a:hover{color:var(--cream)}
.nav-cta{color:var(--ink) !important;background:var(--lime);border-radius:999px;
  padding:10px 20px;font-weight:720}

/* condensed -> the nav becomes a full overlay behind the burger */
.hdr.cond .nav{position:fixed;inset:0;z-index:-2;flex-direction:column;align-items:flex-start;
  justify-content:center;gap:clamp(8px,1.6svh,18px);
  padding:0 clamp(28px,9vw,160px);
  background:rgba(12,12,12,.96);backdrop-filter:blur(20px);
  clip-path:inset(0 0 100% 0);transition:clip-path .62s cubic-bezier(.66,0,.2,1);
  pointer-events:none}
.hdr.cond.open .nav{clip-path:inset(0 0 0 0);pointer-events:auto}
.hdr.cond .nav a{font-size:clamp(30px,5.4vw,66px);font-weight:740;font-stretch:68%;
  letter-spacing:-.028em;color:var(--cream);opacity:0;transform:translateY(22px);
  transition:opacity .4s ease,transform .5s cubic-bezier(.5,0,.2,1)}
.hdr.cond.open .nav a{opacity:1;transform:none}
.hdr.cond.open .nav a:nth-child(1){transition-delay:.14s}
.hdr.cond.open .nav a:nth-child(2){transition-delay:.20s}
.hdr.cond.open .nav a:nth-child(3){transition-delay:.26s}
.hdr.cond.open .nav a:nth-child(4){transition-delay:.32s}
.hdr.cond.open .nav a:nth-child(5){transition-delay:.38s}
.hdr.cond.open .nav a:nth-child(6){transition-delay:.44s}
.hdr.cond.open .nav a:nth-child(7){transition-delay:.50s}
/* The overlay has room for every section; the inline desktop bar does not.
   Scoped to the media query, not to :not(.cond) — on a phone the header is
   not condensed at the top of the page and these would vanish there. */
@media (min-width:768px){ .hdr:not(.cond) .nav .nav-more{display:none} }
.hdr.cond .nav-cta{margin-top:clamp(14px,2.4svh,28px);font-size:16px !important;
  padding:15px 30px;color:var(--ink) !important;align-self:flex-start}

/* ============================================================
   FOOTER
   ============================================================ */
.ftr{position:relative;z-index:2;background:var(--ink);color:var(--rule);
  padding:clamp(64px,9svh,110px) 0 clamp(26px,3svh,38px);
  border-top:1px solid rgba(207,203,192,.14)}
.ftr-rail,.ftr-base{width:100%;max-width:var(--rail);margin:0 auto;padding:0 var(--pad)}
.ftr-rail{display:grid;gap:clamp(34px,5vw,80px);
  grid-template-columns:minmax(0,1.4fr) minmax(0,1fr) minmax(0,1fr)}
.ftr h4{margin:0 0 18px;font-size:11px;font-weight:700;font-stretch:90%;
  letter-spacing:.19em;text-transform:uppercase;color:var(--muted)}
.ftr-line{margin:22px 0 0;font-size:15px;line-height:1.55;color:var(--muted);max-width:38ch}
.ftr-social{display:inline-flex;align-items:center;gap:9px}
.ftr-social svg{fill:currentColor;flex:none;opacity:.85}
.ftr-nav,.ftr-meta{display:flex;flex-direction:column;align-items:flex-start;gap:11px}
.ftr a{color:var(--rule);text-decoration:none;font-size:15px;transition:color .2s ease}
.ftr a:hover{color:var(--lime)}
.ftr-meta p{margin:10px 0 0;font-size:15px;line-height:1.55;color:var(--muted)}
.ftr-base{display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap;
  margin-top:clamp(44px,6svh,78px);padding-top:22px;
  border-top:1px solid rgba(207,203,192,.12)}
.ftr-base p{margin:0;font-size:13px;color:var(--muted)}

/* ============================================================
   TYPE
   ============================================================ */
.eye{margin:0 0 clamp(22px,3svh,40px);font-size:12px;font-weight:700;font-stretch:90%;
  letter-spacing:.2em;text-transform:uppercase;color:var(--rule)}
.s.light .eye{color:var(--muted)}
.eye span{position:relative;padding-left:34px;display:inline-block}
.eye span::before{content:"";position:absolute;left:0;top:.62em;width:24px;height:1px;background:var(--lime)}
.s.light .eye span::before{background:var(--lime-deep)}

h1{margin:0;font-size:min(clamp(46px,7.6vw,124px),11.5svh);line-height:.83;font-weight:760;
  font-stretch:64%;letter-spacing:-.036em;max-width:17ch;text-wrap:balance}
h1 em{font-style:normal;color:var(--lime)}
h2{margin:0 0 clamp(34px,5svh,66px);font-size:min(clamp(38px,6.4vw,104px),13svh);line-height:.86;
  font-weight:740;font-stretch:66%;letter-spacing:-.032em;max-width:16ch;text-wrap:balance}
h2 em{font-style:normal;color:var(--lime-deep)}
.s.dark h2 em{color:var(--lime)}

.sub{margin:0;font-size:clamp(16px,1.35vw,20px);line-height:1.5;color:var(--rule);max-width:44ch;
  font-stretch:96%}
.s.light .sub{color:var(--muted)}

/* Sits after the sticky stage, so it arrives as the section lets go rather
   than competing for room inside the frozen frame. */
/* The rail is a viewport-tall sticky stage with its content centred, so there
   is a lot of dead space under the last row. Pull the trailing copy back up
   through it — but not so far that it reaches the frozen rows. */
.after{position:relative;z-index:5;width:100%;max-width:var(--rail);
  margin:clamp(-140px,-10svh,-80px) auto 0;
  padding:clamp(20px,2.6svh,40px) var(--pad) clamp(70px,10svh,130px)}

/* A closing line, set larger than body copy — it is the argument of the
   section, not a footnote to it. */
.close{margin:clamp(34px,5svh,58px) 0 0;max-width:38ch;
  font-size:min(clamp(18px,1.8vw,26px),3.1svh);line-height:1.32;font-weight:400;font-stretch:92%;
  letter-spacing:-.006em;color:var(--ink);text-wrap:pretty}
.s.dark .close{color:var(--cream);border-top:2px solid rgba(246,244,239,.9);
  padding-top:24px;max-width:34ch}

.sub + .sub{margin-top:clamp(11px,1.5svh,18px)}
.sub.strong{color:var(--ink);font-weight:600}
.s.dark .sub.strong{color:var(--cream)}

/* ---------- formal training block ---------- */
.creds{margin-top:clamp(18px,2.4svh,34px);padding-top:16px;
  border-top:1px solid rgba(17,17,17,.16)}
.s.dark .creds{border-top-color:rgba(246,244,239,.18)}
.creds-h{margin:0 0 16px;font-size:11px;font-weight:700;font-stretch:90%;
  letter-spacing:.19em;text-transform:uppercase;color:var(--muted)}
.creds-l{display:flex;flex-wrap:wrap;gap:10px;list-style:none;margin:0;padding:0}
.creds-l li{display:inline-flex;align-items:center;gap:9px;
  padding:9px 16px 9px 12px;border:1px solid rgba(17,17,17,.16);border-radius:999px;
  font-size:14px;font-weight:660;font-stretch:92%;color:var(--ink);
  background:rgba(255,255,255,.5)}
.s.dark .creds-l li{border-color:rgba(246,244,239,.2);color:var(--cream);
  background:rgba(246,244,239,.06)}
/* Official marks, self-hosted. Heights are matched rather than widths —
   these are three different aspect ratios and forcing a square box would
   distort two of them. */
.creds-mark{height:17px;width:auto;max-width:26px;flex:none;display:block}
.creds-mark[src*="openai"]{height:21px}
.creds-n{margin:12px 0 0;font-size:13px;line-height:1.5;color:var(--muted);max-width:46ch}

/* ============================================================
   00 HERO — type sits on the floor of the frame, plate full bleed
   ============================================================ */
/* justify-content:center is inherited from .rail, where it centres a flex
   column vertically. Under display:grid it centres the TRACK instead, and
   with no explicit column the track shrinks to max-content — which is what
   was pushing the hero copy in from the rail's left edge. */
[data-beat="hero"] .rail{display:grid;align-content:end;justify-content:stretch;
  grid-template-columns:minmax(0,1fr);gap:clamp(30px,5svh,58px)}
.hero-foot{display:flex;flex-wrap:wrap;gap:clamp(24px,4vw,72px);align-items:flex-end;
  justify-content:space-between}
.ticks{display:flex;gap:clamp(18px,2.4vw,40px);list-style:none;margin:0;padding:0;
  font-size:12px;font-weight:700;font-stretch:88%;letter-spacing:.16em;text-transform:uppercase;
  color:var(--rule)}
.ticks li{position:relative;padding-top:14px;border-top:1px solid rgba(207,203,192,.28)}
.ticks b{display:block;font-size:clamp(26px,3vw,44px);font-weight:780;font-stretch:66%;
  letter-spacing:-.03em;color:var(--cream);margin-top:6px;line-height:1}

/* ============================================================
   01 LEAKS — the list is the whole section. Big rows, big icons,
   no boxes. Number + icon + line, nothing else.
   ============================================================ */

[data-beat="leaks"] .stamp{right:-.09em;bottom:-.13em}
.rows{display:flex;flex-direction:column;max-width:1240px}
.row{display:grid;
  grid-template-columns:clamp(44px,4.6vw,74px) clamp(52px,6.4vw,96px) 1fr;
  gap:clamp(16px,2.6vw,42px);align-items:center;
  padding:clamp(18px,2.5svh,34px) 0;position:relative}
.row + .row::before{content:"";position:absolute;top:0;left:0;right:0;height:1px;
  background:currentColor;opacity:.16}
.num{font-style:normal;font-size:clamp(14px,1.1vw,17px);font-weight:720;font-stretch:80%;
  letter-spacing:.06em;opacity:.4;font-variant-numeric:tabular-nums}
.slot{display:block;width:clamp(52px,6.4vw,96px);height:clamp(52px,6.4vw,96px);position:relative}
.slot svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
.slot path{fill:none;stroke:var(--lime-deep);stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.s.dark .slot path{stroke:var(--lime)}
.row h3{margin:0;font-size:clamp(21px,3.3vw,50px);line-height:.98;font-weight:720;
  font-stretch:70%;letter-spacing:-.024em}

/* The whole beat has to fit one viewport — the rail freezes on screen, so
   anything past the fold never gets seen while its sequence plays. Measured
   at 913px: heading, five rows and the closer all inside the stage. */
[data-beat="leaks"] .rail{padding-top:clamp(38px,4.4svh,72px);padding-bottom:clamp(38px,4.4svh,72px)}
[data-beat="leaks"] h2{margin-bottom:clamp(14px,2svh,30px);
  font-size:min(clamp(32px,4.9vw,84px),11svh)}
[data-beat="leaks"] .row{padding:clamp(8px,1.1svh,17px) 0;
  grid-template-columns:clamp(38px,3.2vw,54px) clamp(50px,5vw,76px) 1fr;
  gap:clamp(16px,2vw,32px)}
[data-beat="leaks"] .slot{width:min(clamp(46px,4.4vw,66px),7.4svh);height:min(clamp(46px,4.4vw,66px),7.4svh)}
[data-beat="leaks"] .row h3{font-size:min(clamp(19px,2.5vw,38px),4.6svh);
  font-weight:500;font-stretch:78%;letter-spacing:-.012em}

/* Every held beat must fit its own stage, or the tail of it plays below the
   fold while the section is frozen. Measured at 913px. */
[data-beat="teardown"] .rail,
[data-beat="process"] .rail,
[data-beat="about"] .rail,
[data-beat="checks"] .rail,
[data-beat="contact"] .rail{padding-top:clamp(34px,4svh,66px);padding-bottom:clamp(34px,4svh,66px)}
[data-beat="about"] h2{font-size:clamp(30px,4.3vw,70px)}

/* ============================================================
   02 TEARDOWN — the frame goes wide and the heading overlaps it
   ============================================================ */

[data-beat="teardown"] .stamp{left:-.06em;top:-.1em}
/* Stacking a 16:9 figure under the heading forces both to shrink to fit one
   viewport. Side by side, the horizontal room carries the figure and the
   heading keeps display scale. */
[data-beat="teardown"] .rail{display:grid;justify-content:stretch;align-items:center;
  grid-template-columns:minmax(0,.92fr) minmax(0,1.62fr);
  grid-template-rows:auto auto auto;column-gap:clamp(30px,3.4vw,64px);row-gap:0;
  align-content:center}
[data-beat="teardown"] .eye{grid-column:1;grid-row:1;align-self:end}
[data-beat="teardown"] h2{grid-column:1;grid-row:2;align-self:start;position:relative;z-index:6;
  max-width:13ch;margin-bottom:0;font-size:clamp(32px,4.6vw,80px)}
[data-beat="teardown"] .frame{grid-column:2;grid-row:1 / span 3;max-width:none;margin:0;
  max-height:62svh;justify-self:end;align-self:center}
/* the closing line sits under the heading in the left column, not stranded
   far below the frame */
[data-beat="teardown"] .close{grid-column:1;grid-row:3;align-self:start;
  margin:clamp(20px,2.6svh,34px) 0 0;padding-top:clamp(16px,2svh,24px);
  border-top:2px solid rgba(246,244,239,.9);max-width:30ch;
  font-size:min(clamp(17px,1.7vw,25px),3svh)}
.frame{position:relative;width:100%;max-width:1180px;aspect-ratio:16/9;margin-left:auto;
  border:0;background:none;overflow:visible}
.frame svg{position:absolute;inset:0;width:100%;height:100%}

/* --- figures: these are strokes, never fills --- */
#wire .wf{stroke:rgba(207,203,192,.26);stroke-width:1.1;fill:none}
#wire .wf-hard{stroke:rgba(207,203,192,.42);stroke-width:1.3;fill:none}
#wire .wf-dot{fill:rgba(207,203,192,.34)}
#wire .lead{stroke:rgba(185,242,59,.42);stroke-width:1;fill:none}
/* the charge that runs the lines once they are drawn */
#wire .wf-spark{fill:none;stroke:var(--core);stroke-width:2;stroke-linecap:round;opacity:0}
#wire .pulse{fill:none;stroke:var(--lime);stroke-width:1.6;opacity:0}
#wire .pin{stroke:var(--lime);stroke-width:1.5;fill:none}
#wire .pin-c{fill:var(--core)}
#wire .retic{stroke:var(--lime);stroke-width:1.4;fill:none}
#wire .retic-glow{fill:url(#dotglow)}
#wire .retic-core{fill:var(--core)}
#wire .wf-limb{stroke-width:1.6}
#wire .wf-root{fill:var(--lime);stroke:none}
/* the glyph is ground, the ring the crosshair leaves is the signal */
#wire .ico-p{stroke:rgba(207,203,192,.52);stroke-width:2.4;fill:none;
  stroke-linecap:round;stroke-linejoin:round}
/* the lit copy sits exactly on the dim one and is what the punch reveals */
#wire .ico-l{stroke:var(--lime);stroke-width:2.8;fill:none;
  stroke-linecap:round;stroke-linejoin:round}
#wire text{font-family:"Archivo","Helvetica Neue",Arial,sans-serif;font-size:22px;
  font-weight:620;font-stretch:92%;letter-spacing:.005em;fill:var(--lime)}
/* map furniture reads as ground; only the route and the stops carry green */
/* Opacity is the whole hierarchy here, so it is set in one place: the floor
   holds it all together, blocks read as footprint, roads as structure. The
   previous values were tuned against the dark left half of the plate alone,
   which is why the map vanished over the bright half. */
#route .map-ground rect{opacity:.66}
#route .blk{fill:rgba(207,203,192,.075);stroke:rgba(207,203,192,.055);stroke-width:1}
#route .blk-c{fill:rgba(207,203,192,.115)}
#route .park{fill:rgba(185,242,59,.085);stroke:rgba(185,242,59,.14);stroke-width:1}
/* water sits UNDER the roads and stays cool and low — it is ground, not a
   line competing with the route */
#route .water{fill:none;stroke:rgba(126,158,186,.22);stroke-width:13;stroke-linecap:round}
#route .rd-major{stroke:rgba(207,203,192,.30);stroke-width:5;fill:none}
#route .rd-minor{stroke:rgba(207,203,192,.135);stroke-width:2;fill:none}
#route .rt-bed{stroke:rgba(185,242,59,.16);stroke-width:9;fill:none;
  stroke-linecap:round;stroke-linejoin:round}
#route .rt{stroke:var(--lime);stroke-width:3.2;fill:none;
  stroke-linecap:round;stroke-linejoin:round}
/* The overlay car carries the dot's glow with it. Without a matching halo
   here the handoff read as a lit car swapping for a flat one, which is the
   only frame in the beat where you could see the seam. */
#route .car{fill:var(--lime);
  filter:drop-shadow(0 0 6px rgba(185,242,59,.55)) drop-shadow(0 0 17px rgba(185,242,59,.30))}
#route .car-w{fill:var(--lime)}
#route .stop-ring{fill:none;stroke:var(--lime);stroke-width:2}
#route .stop-core{fill:var(--core)}
/* Two of the four labels land over the plate's brightest area. paint-order
   puts a dark stroke behind the glyphs rather than a box around them, so they
   hold on any ground without adding furniture to the map. */
#route .stop-t{font-family:"Archivo","Helvetica Neue",Arial,sans-serif;font-size:19px;
  font-weight:720;font-stretch:80%;letter-spacing:-.01em;fill:var(--cream);
  paint-order:stroke fill;stroke:rgba(10,10,10,.85);stroke-width:4.5;
  stroke-linejoin:round}
#route .evt-box{fill:rgba(17,17,17,.55);stroke:rgba(207,203,192,.4);stroke-width:1.4}
#route .evt-red{fill:#E2673F}
#route .evt-go{fill:var(--lime)}
#route .evt-tree{fill:rgba(185,242,59,.30);stroke:var(--lime);stroke-width:1.2}
#route .evt-tower{fill:rgba(185,242,59,.10);stroke:var(--lime);stroke-width:1.4}
#route .evt-round{fill:none;stroke:var(--lime);stroke-width:2;
  stroke-dasharray:8 7}
#circuit .tr{stroke:var(--lime-deep);stroke-width:1.6;fill:none;stroke-linecap:round}
/* An SVG path with no fill declared defaults to BLACK, so every unclosed
   trace was painting as a filled shape. Stroked geometry must say fill:none. */
#circuit .spark{fill:none;stroke:var(--core);stroke-width:2.4;stroke-linecap:round}
#circuit .via-o{fill:none;stroke:var(--lime-deep);stroke-width:1.5}
#circuit .via-i{fill:var(--lime-deep)}
#circuit .nd{fill:var(--lime-deep)}
/* contact points sit on the dark photo, so they emit instead of printing */
#circuit .nd-hot{fill:var(--core)}

/* ============================================================
   03 CHECKS — the marquee IS the section. Type steps aside.
   ============================================================ */

[data-beat="checks"] h2{margin-bottom:clamp(30px,4svh,52px);font-size:clamp(34px,5.4vw,88px)}
[data-beat="checks"] .sub{max-width:52ch}
/* the chip rows break out of the rail to full bleed without leaving it */
.marq-wrap{margin:clamp(30px,4.4svh,56px) 0 0;
  width:100vw;margin-left:calc(50% - 50vw);margin-right:calc(50% - 50vw)}
.marq{position:relative;z-index:5;overflow:hidden;margin:clamp(8px,1.1svh,14px) 0}
.marq-t{display:flex;gap:12px;width:max-content;will-change:transform}
.marq-t span{flex:none;font-size:clamp(14px,1.35vw,20px);font-weight:620;font-stretch:88%;
  white-space:nowrap;padding:clamp(11px,1.3vw,17px) clamp(18px,2vw,30px);
  border:1px solid rgba(17,17,17,.18);border-radius:999px;
  color:var(--ink);background:rgba(255,255,255,.6);
  transition:background-color 220ms ease,border-color 220ms ease,color 220ms ease}
.marq-t span.lit{background:var(--lime);border-color:var(--lime-deep)}

/* ============================================================
   04 PROCESS — four steps across the full width
   ============================================================ */

[data-beat="process"] .stamp{right:-.07em;top:-.12em}
/* width must be derived from the height explicitly. `width:auto` on a block
   box means "fill the container", which beats aspect-ratio — so the frame was
   1240 wide for a 383-tall map, the SVG letterboxed inside it, and every
   percentage-positioned marker was ~178px out. */
[data-beat="process"] .frame{height:min(42svh,470px);
  width:calc(min(42svh,470px) * 1200 / 520);max-width:100%;
  margin:0;border:0;background:none}
[data-beat="process"] h2{font-size:min(clamp(34px,5vw,86px),10svh);margin-bottom:clamp(16px,2svh,26px)}
[data-beat="process"] .sub{margin-bottom:clamp(14px,1.8svh,22px)}

/* ============================================================
   04 SYSTEMS — the only beat with no photograph under it. Every other
   section is a window onto the plate stack; this one is a schematic on flat
   ink, which is what a section full of diagrams should look like.
   ============================================================ */
/* The ink is a masked layer, not a background colour on the section. As a
   background it cut a hard horizontal edge against the cream beat above it;
   masked, it dissolves into its neighbours the way every other ground here
   does. The fade is a fixed distance, not a percentage — this section is
   250svh tall, so a percentage fade would leave the content sitting on the
   neighbouring plate for the first third of the beat. */
/* Drafting paper: a fine grid with a heavier rule every fifth line. It is the
   only ground on the page that is drawn rather than photographed, which is
   what makes this beat read as the schematic it is. */
.s.flat .scrim{
  background:
    repeating-linear-gradient(0deg,  rgba(207,203,192,.075) 0 1px, transparent 1px 230px),
    repeating-linear-gradient(90deg, rgba(207,203,192,.075) 0 1px, transparent 1px 230px),
    repeating-linear-gradient(0deg,  rgba(207,203,192,.032) 0 1px, transparent 1px 46px),
    repeating-linear-gradient(90deg, rgba(207,203,192,.032) 0 1px, transparent 1px 46px),
    var(--ink);
  /* cream to near-black is the biggest tonal jump on the page, so the fade has
     to be long or it reads as a band rather than a dissolve */
  -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 clamp(150px,20svh,300px),
    #000 calc(100% - clamp(150px,20svh,300px)),transparent 100%);
          mask-image:linear-gradient(180deg,transparent 0,#000 clamp(150px,20svh,300px),
    #000 calc(100% - clamp(150px,20svh,300px)),transparent 100%)}
[data-beat="systems"] .stage{min-height:250svh}
[data-beat="systems"] .stamp{left:-.06em;top:-.10em}
[data-beat="systems"] h2{max-width:18ch;margin-bottom:clamp(12px,1.5svh,20px);font-size:min(clamp(34px,5.2vw,88px),10svh)}
[data-beat="systems"] .sub{max-width:62ch}
/* The figure takes whatever the copy leaves. A vh cap was both a magic number
   and a guarantee it would be smaller than it needed to be — flexing means it
   is always as large as the beat allows and can never overflow the rail. */
[data-beat="systems"] .frame{width:100%;max-width:1180px;margin:clamp(16px,2.4svh,36px) 0 0;
  flex:1 1 auto;min-height:0;height:auto;aspect-ratio:auto;border:0;background:none}
[data-beat="systems"] .frame svg{width:100%;height:100%}

#pipes text{font-family:"Archivo","Helvetica Neue",Arial,sans-serif}
#pipes .pipe-name{font-size:21px;font-weight:730;font-stretch:76%;letter-spacing:.005em;
  fill:var(--cream)}
/* dashed is the machine working; solid is what happens once a person has
   signed off. The line weight carries the argument before anyone reads it. */
#pipes .pipe-auto{stroke:rgba(207,203,192,.30);stroke-width:2;fill:none;stroke-dasharray:9 9}
#pipes .pipe-done{stroke:var(--lime);stroke-width:2.4;fill:none;stroke-linecap:round}
#pipes .pipe-node{fill:none;stroke:rgba(207,203,192,.46);stroke-width:2}
#pipes .gate-bar{stroke:var(--lime);stroke-width:4.4;fill:none;stroke-linecap:round}
#pipes .gate-dot{fill:var(--core)}
#pipes .pd-glow{fill:url(#pipeglow)}
#pipes .pd-core{fill:var(--core)}
.pipe-a{position:absolute;width:2px;height:2px;pointer-events:none}
#pipes .pipe-lab{font-size:18px;font-weight:480;font-stretch:94%;fill:rgba(207,203,192,.62)}
#pipes .pipe-lab.is-gate{fill:var(--lime);font-weight:680;font-stretch:86%}
/* the badge is hidden, so the attribution below the form is not optional */
.grecaptcha-badge{visibility:hidden !important}
.f-legal{margin:clamp(9px,1.2svh,15px) 0 0;font-size:11.5px;line-height:1.45;
  color:rgba(207,203,192,.42);max-width:56ch}
.f-legal a{color:rgba(207,203,192,.72);text-underline-offset:2px}
.f-legal a:hover{color:var(--cream)}

.pipe-say{display:none}
.fig-portrait [data-beat="systems"] .frame{
  flex:0 0 auto;height:min(30svh,300px);width:100%;max-width:none;margin:clamp(14px,2svh,22px) 0 0}
.fig-portrait #pipes .pipe-name{font-size:25px}
.fig-portrait #pipes .pipe-auto{stroke-width:3;stroke-dasharray:11 10}
.fig-portrait #pipes .pipe-done{stroke-width:3.4}
.fig-portrait #pipes .gate-bar{stroke-width:6}
.fig-portrait #pipes .gate-dot{r:6}
.fig-portrait .pipe-say{display:block;margin:clamp(14px,2svh,22px) 0 0;
  font-size:clamp(15px,4vw,17px);line-height:1.45;color:rgba(207,203,192,.66);min-height:4.4em}
.fig-portrait .pipe-say b{color:var(--lime);font-weight:700;font-stretch:88%}
.fig-portrait .pipe-say i{font-style:normal;color:rgba(207,203,192,.34);padding:0 .4em}

/* ============================================================
   05 ABOUT — asymmetric: portrait left, type right
   ============================================================ */
/* Eyebrow and heading run full width on the rail's left edge; the photo and
   the copy sit beneath them as one top-aligned row. */
[data-beat="about"] .rail{display:grid;align-content:center;align-items:start;
  justify-content:stretch;
  grid-template-columns:minmax(0,clamp(230px,24vw,340px)) minmax(0,1fr);
  column-gap:clamp(32px,4.4vw,72px);row-gap:0}
[data-beat="about"] .eye{grid-column:1 / -1;grid-row:1}
[data-beat="about"] h2{grid-column:1 / -1;grid-row:2;max-width:20ch;
  margin-bottom:clamp(18px,2.6svh,44px);font-size:min(clamp(32px,4.6vw,72px),8.5svh)}
[data-beat="about"] .about-copy{grid-column:2;grid-row:3}
[data-beat="about"] .sub{max-width:62ch;font-size:min(clamp(16px,1.35vw,20px),2.25svh);
  line-height:1.44}
.frame.portrait{grid-column:1;grid-row:3;aspect-ratio:3/4;max-width:none;margin:0;
  overflow:visible;max-height:46svh;justify-self:start}
.frame svg{overflow:visible}
/* sits exactly on the map's "Look" stop (60,470 of a 1200x520 viewBox) */
.map-a{position:absolute;left:0;top:0;width:2px;height:2px;pointer-events:none}
/* point B — 1140,70 of the 1200x520 viewBox */
.map-b{position:absolute;left:0;top:0;width:2px;height:2px;pointer-events:none}
/* contact point the board grows out of */
.circ-a{position:absolute;left:0;top:0;width:2px;height:2px;pointer-events:none}
/* sits on the first finding, so the dot arrives where the crosshair starts */
.wire-a{position:absolute;width:2px;height:2px;pointer-events:none}
/* The photo is cropped to keep the head high in frame; the circuit grows out
   of its edges rather than across his face. */
.pf{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  object-position:50% 26%;filter:contrast(1.05) brightness(1.02);display:block;
  /* Eight bands, each opening from the top of its own slice. --rv defaults to
     1 so the photo is fully visible if the script never runs. */
  --rv:1;
  -webkit-mask-image:repeating-linear-gradient(180deg,
    #000 0 calc(var(--rv) * 12.5%), transparent calc(var(--rv) * 12.5%) 12.5%);
          mask-image:repeating-linear-gradient(180deg,
    #000 0 calc(var(--rv) * 12.5%), transparent calc(var(--rv) * 12.5%) 12.5%)}

/* Slow breathing halo, started once the board has woken. Sits behind the
   photo and fades out with the rest of the figure on scroll. */
.pf-glow{position:absolute;inset:-14px;z-index:0;pointer-events:none;opacity:0;
  border-radius:2px;
  box-shadow:0 0 0 1px rgba(185,242,59,.30), 0 0 34px 6px rgba(185,242,59,.34),
             0 0 90px 18px rgba(185,242,59,.16)}

.pf-scan{position:absolute;left:0;right:0;top:0;height:2px;z-index:4;pointer-events:none;
  opacity:0;background:linear-gradient(90deg,transparent,var(--lime) 22%,var(--core) 50%,var(--lime) 78%,transparent);
  box-shadow:0 0 22px 3px rgba(185,242,59,.45)}

/* ============================================================
   06 CONTACT — the question fills the screen
   ============================================================ */

[data-beat="contact"] h2{max-width:27ch;font-size:min(clamp(30px,4.3vw,70px),9svh);
  margin-bottom:clamp(16px,2.2svh,32px)}

.form{display:grid;margin-top:clamp(16px,2.2svh,40px);
  gap:clamp(12px,1.6svh,24px) clamp(18px,2.4vw,34px);max-width:920px;
  grid-template-columns:repeat(3,minmax(0,1fr))}
.f{display:grid;gap:9px}
.f-wide{grid-column:1 / -1}
.f label{font-size:11px;font-weight:700;font-stretch:90%;letter-spacing:.17em;
  text-transform:uppercase;color:var(--rule)}
.f label span{opacity:.5;letter-spacing:.1em}
.f input,.f textarea{font-family:inherit;font-size:17px;font-stretch:96%;color:var(--cream);
  background:transparent;border:0;border-bottom:1px solid rgba(207,203,192,.34);
  padding:11px 2px;border-radius:0;resize:vertical;
  transition:border-color 200ms ease}
.f input:focus,.f textarea:focus{outline:0;border-bottom-color:var(--lime)}
.f input:user-invalid,.f textarea:user-invalid{border-bottom-color:#E2673F}
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

.form .send{grid-column:1 / -1;justify-self:start;margin-top:clamp(6px,1.4svh,16px)}
.send[disabled]{opacity:.55;cursor:default}
.f-note{grid-column:1 / -1;margin:0;font-size:14px;color:var(--rule);min-height:1.2em}
.f-note.bad{color:#F0906B}
.f-note.good{color:var(--lime)}
.send{display:inline-flex;align-items:center;gap:16px;font-family:inherit;
  font-size:clamp(15px,1.3vw,19px);font-weight:700;font-stretch:92%;letter-spacing:-.01em;
  color:var(--ink);background:var(--cream);border:0;border-radius:999px;
  padding:clamp(17px,1.7vw,24px) clamp(30px,3vw,44px);cursor:pointer}
/* an empty socket waiting for the dot, not a decorative bullet */
.send-slot{width:15px;height:15px;border-radius:99px;flex:none;
  background:rgba(17,17,17,0);border:1.5px solid rgba(17,17,17,.30);box-sizing:border-box}

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width:1024px){
  [data-beat="about"] .rail{grid-template-columns:1fr;row-gap:clamp(24px,3svh,38px)}
  [data-beat="about"] .about-copy{grid-column:1;grid-row:4}
  [data-beat="about"] .eye{grid-row:1}
  [data-beat="about"] h2{grid-row:2;margin-bottom:0}
  .frame.portrait{grid-column:1;grid-row:3;max-width:320px}
  [data-beat="teardown"] h2{margin-bottom:clamp(28px,4svh,44px)}
  .frame{margin-left:0}
}
/* ============================================================
   PORTRAIT FIGURES
   Keyed to the class the script stamps on <html>, NOT to a media query: the
   figure that was built is the one whose aspect the frame has to match, and
   rotating the phone must not letterbox it.
   ============================================================ */
.fig-portrait [data-beat="teardown"] .frame{aspect-ratio:420/500}
.fig-portrait #route .car-gl{fill:rgba(10,10,10,.62)}
.fig-portrait [data-beat="process"] .frame{
  /* derived from the height, and the height from whichever of the two limits
     binds first — so the box always matches 560:720 and never letterboxes */
  height:min(52svh, calc((100vw - 2 * var(--pad)) * 720 / 560));
  width:calc(min(52svh, calc((100vw - 2 * var(--pad)) * 720 / 560)) * 560 / 720);
  max-width:100%;margin:clamp(10px,1.4svh,18px) auto 0}
/* labels are viewBox units, so they shrink with the drawing — these are the
   sizes that land at ~16px once a 560-unit map is drawn 340px wide */
.fig-portrait #route .stop-t{font-size:27px}
.fig-portrait #route .rd-major{stroke-width:3.4}
.fig-portrait #route .rd-minor{stroke-width:1.5}
.fig-portrait #route .rt{stroke-width:4}
.fig-portrait #route .rt-bed{stroke-width:11}
.fig-portrait #wire .wf{stroke:rgba(207,203,192,.34);stroke-width:1.4}
.fig-portrait #wire .wf-hard{stroke:rgba(207,203,192,.55);stroke-width:1.8}

/* The five findings, moved out of the SVG. At 350px wide the in-figure
   labels were 4px; here they read, and they still accumulate so the beat
   still lands on "five specific things". */
.wf-list{list-style:none;margin:clamp(14px,2svh,22px) 0 0;padding:0;
  display:flex;flex-direction:column;gap:clamp(6px,.9svh,11px)}
.wf-list li{display:grid;grid-template-columns:26px 1fr;gap:12px;align-items:baseline;
  font-size:clamp(14px,3.9vw,16px);line-height:1.25;opacity:0}
.wf-list li i{font-style:normal;font-weight:700;font-stretch:80%;font-size:.82em;
  letter-spacing:.06em;color:var(--lime)}
.s.light .wf-list li i{color:var(--lime-deep)}

@media (max-width:767px){
  .s{padding:clamp(80px,10svh,110px) 0}
  .rail{padding:clamp(70px,8.4svh,96px) var(--pad)}
  /* 02 was still on the desktop two-column grid, so the heading was ranging
     over four lines in a 230px column and the figure was a 204px stamp */
  /* align-items:center comes from the desktop grid rule and does NOT stop
     applying just because the display changed — in a flex column it shrank
     every child to its content width and centred it, which threw the
     eyebrow to the right edge. */
  [data-beat="teardown"] .rail{display:flex;flex-direction:column;
    justify-content:center;align-items:stretch}
  /* ...and align-self:end from the same grid rule means "right" once the
     cross axis is horizontal. That, not align-items, was throwing the
     eyebrow to the right edge. */
  [data-beat="teardown"] .eye{align-self:start}
  /* the extra room around the findings rule grew the stack, which pushed the
     eyebrow up into the 02 numeral */
  [data-beat="teardown"] .rail{padding-top:clamp(56px,7svh,84px)}
  [data-beat="teardown"] h2{max-width:none;margin-bottom:clamp(10px,1.4svh,18px);
    font-size:min(clamp(30px,8.2vw,44px),6.2svh)}
  [data-beat="teardown"] .frame{max-height:none;justify-self:auto;align-self:center;
    height:min(40svh, calc((100vw - 2 * var(--pad)) * 500 / 420));
    width:calc(min(40svh, calc((100vw - 2 * var(--pad)) * 500 / 420)) * 420 / 500);
    max-width:100%;margin:clamp(8px,1.2svh,16px) auto 0}
  /* the closing line leaves the frozen rail — there is no room for it beside
     a full-height figure, and it reads better as the thing you land on after */
  [data-beat="teardown"] .close{margin:0;padding-top:clamp(14px,1.8svh,20px);
    max-width:none;font-size:clamp(16px,4.4vw,19px);border-top-width:1px}
  [data-beat="process"] h2{font-size:min(clamp(30px,8.2vw,46px),6.4svh);
    margin-bottom:clamp(8px,1.2svh,14px)}
  [data-beat="process"] .sub{margin-bottom:0;font-size:clamp(15px,4vw,17px)}
  /* 07 was already within a few px of the viewport at 360x740; the reCAPTCHA
     attribution tipped it over. Reclaimed from the beat's own padding and the
     gaps between fields rather than by shrinking anything anyone reads. */
  [data-beat="contact"] .rail{padding-top:clamp(20px,2.6svh,34px);
    padding-bottom:clamp(20px,2.6svh,34px)}
  [data-beat="contact"] .sub{font-size:clamp(15px,4vw,17px)}
  [data-beat="contact"] .form{margin-top:clamp(12px,1.6svh,22px);
    gap:clamp(10px,1.3svh,16px) 0}
  [data-beat="contact"] .f{gap:6px}
  .f-legal{font-size:11px;max-width:none}
  /* 05 carries 672px of copy. Frozen behind a 100svh sticky rail on an 844px
     screen that puts 459px of it off the bottom for the whole beat, so on a
     phone this one scrolls instead of freezing. thread.js keys its sequence
     off the section's travel when there is no hold. */
  /* ---- 00 HERO ----
     Desktop stands the type on the floor of the frame. On a phone that put
     390px of nothing above it AND buried the plate's green dot — which, with
     the overlay stripped, is the only thing carrying the dot idea here. Type
     to the top, the stats stay on the floor, and the gap between them is
     where the dot lives. */
  /* .s gets 10svh of padding on mobile; on a full-bleed screen that pushed the
     bottom 84px of a 100svh rail below the fold, taking the stats with it. */
  [data-beat="hero"]{padding:0}
  [data-beat="hero"] .rail{display:flex;flex-direction:column;align-content:normal;
    justify-content:flex-start;gap:clamp(16px,2.4svh,26px);
    padding-top:clamp(120px,15svh,150px);padding-bottom:clamp(26px,3.4svh,40px)}
  [data-beat="hero"] .hero-foot{margin-top:auto;gap:clamp(16px,2.2svh,24px)}
  /* three across, not one under another: the ticks are a footer strip, and
     stacked they ate the space the dot needed */
  /* max-content, not 1fr: equal thirds gave "25+ YRS" a column as wide as
     "HUMAN DRIVEN" and left the gap inside it. Each column hugs its own value
     and the gaps get the slack instead. */
  .ticks{display:grid;grid-template-columns:repeat(3,max-content);
    justify-content:space-between;gap:10px;width:100%;
    font-size:10px;letter-spacing:.11em}
  .ticks b{font-size:clamp(17px,4.6vw,24px);margin-top:5px}
  /* The mobile scrim goes to 93% black at 58% — the dot sits at 66%. This
     one is heavy where the type is and opens where the dot is. */
  /* .s.dark .scrim is three classes; [data-beat="hero"] .scrim is two, so the
     generic mobile scrim outranked this and none of it applied. Match the
     tone classes to win. */
  [data-beat="hero"].s.dark .scrim{background:linear-gradient(180deg,
    rgba(17,17,17,.90) 0%, rgba(17,17,17,.86) 40%, rgba(17,17,17,.30) 52%,
    rgba(17,17,17,.10) 62%, rgba(17,17,17,.10) 72%, rgba(17,17,17,.60) 88%,
    rgba(17,17,17,.72) 100%)}
  /* and the second, bottom-up pass reached 58% too — pull it back under the
     stats strip */
  [data-beat="hero"].s.dark::after{background:linear-gradient(0deg,
    rgba(17,17,17,.78) 0%, rgba(17,17,17,.44) 13%, rgba(17,17,17,0) 26%)}
  /* No added glow. A lime bloom laid over the plate's own dot in plus-lighter
     flattened the core into a green cloud — the thing that reads as a LIT dot
     is the near-white center, and painting over it is what hid it. Taking the
     scrim off it is the whole fix. */
  [data-beat="hero"] .orb{width:0;height:0;left:69.5%;top:65.5%}

  /* ---- 01 ---- content up under the stamp, and the closing line pulled in
     under the rows instead of stranded a screen below them */
  [data-beat="leaks"] .rail{justify-content:flex-start;
    padding-top:clamp(112px,14svh,150px)}
  /* -39svh pulled the closer up THROUGH the rows once the rail released.
     Verified by sweeping the whole exit, not one sample point. */
  .after{margin-top:clamp(-200px,-22svh,-150px)}

  /* ---- 02 ---- the rule under the findings was 10px off the list above it
     and 25px off the copy below */
  [data-beat="teardown"] .close{margin-top:clamp(22px,2.8svh,34px);
    padding-top:clamp(20px,2.6svh,30px)}

  /* ---- 05 ---- the traces hang ~60px below the photo and ran straight into
     the first paragraph */
  [data-beat="about"] .about-copy{margin-top:clamp(54px,7svh,84px)}
  [data-beat="about"] .stage{min-height:auto}
  [data-beat="about"] .rail{position:relative;min-height:auto;
    padding-top:clamp(60px,7svh,90px);padding-bottom:clamp(60px,7svh,90px)}
  .row{grid-template-columns:34px 46px 1fr;gap:14px}
  .slot{width:46px;height:46px}
  .stamp{font-size:46vw;-webkit-text-stroke-width:1px}
  .thread{display:none}
  .s.dark  .scrim{background:linear-gradient(180deg,rgba(17,17,17,.5),rgba(17,17,17,.93) 58%)}
  .s.light .scrim{background:linear-gradient(180deg,rgba(246,244,239,.48),rgba(246,244,239,.94) 58%)}
  .hero-foot{flex-direction:column;align-items:flex-start;gap:26px}
  .form{grid-template-columns:1fr}
  .ftr-rail{grid-template-columns:1fr;gap:40px}
  /* 34ch made the box 292px while the line needed 303 — so it wrapped and
     pushed "One operator." onto a third line. The viewport was never the
     constraint; the max-width was. */
  .ftr-line{max-width:none}
  /* The overlay menu is gated on .hdr.cond, and on a phone the header is NOT
     condensed at the top of the page — so the burger had nothing to open
     there. `.nav{display:none}` then killed it at every scroll position: it is
     one class, so it beat `.hdr.cond .nav{display:flex}` on source order and
     the panel could never show at all. Restated here without the .cond gate. */
  .hdr .nav{display:flex;position:fixed;inset:0;z-index:-2;
    flex-direction:column;align-items:flex-start;justify-content:center;
    gap:clamp(8px,1.6svh,18px);padding:0 clamp(28px,9vw,64px);
    background:rgba(12,12,12,.96);backdrop-filter:blur(20px);
    clip-path:inset(0 0 100% 0);transition:clip-path .62s cubic-bezier(.66,0,.2,1);
    pointer-events:none}
  .hdr.open .nav{clip-path:inset(0 0 0 0);pointer-events:auto}
  .hdr .nav a{font-size:clamp(30px,7.6vw,46px);font-weight:740;font-stretch:68%;
    letter-spacing:-.028em;color:var(--cream);opacity:0;transform:translateY(22px);
    transition:opacity .4s ease,transform .5s cubic-bezier(.5,0,.2,1)}
  .hdr.open .nav a{opacity:1;transform:none}
  .hdr.open .nav a:nth-child(1){transition-delay:.14s}
  .hdr.open .nav a:nth-child(2){transition-delay:.20s}
  .hdr.open .nav a:nth-child(3){transition-delay:.26s}
  .hdr.open .nav a:nth-child(4){transition-delay:.32s}
  .hdr.open .nav a:nth-child(5){transition-delay:.38s}
  .hdr.open .nav a:nth-child(6){transition-delay:.44s}
  .hdr.open .nav a:nth-child(7){transition-delay:.50s}
  /* seven links now, so they have to be a touch tighter */
  .hdr .nav a{font-size:clamp(26px,6.6vw,40px)}
  .hdr .nav-cta{margin-top:clamp(14px,2.4svh,28px);font-size:16px !important;
    padding:15px 30px;color:var(--ink) !important;align-self:flex-start}
  .burger{display:flex}
  .hdr .pack{order:1}
  .hdr{justify-content:flex-end}
}
/* The H1's line breaks are authored, and the clamp floor of 46px is wider
   than a 320px screen's text column — "Don't lose customers" wrapped and the
   composition went to five lines. One step down protects the break. */
@media (max-width:350px){ h1{font-size:40px} }

/* On a very short phone (iPhone SE, 568px) a seven-field form plus its legal
   line cannot fit one screen, and a sticky rail taller than the viewport hides
   the submit button for the length of the freeze. Same treatment as 05: this
   beat stops freezing and simply scrolls. Its one animation is keyed to the
   send button's own position, not to a hold, so nothing else has to change. */
@media (max-width:767px) and (max-height:640px){
  [data-beat="contact"] .stage{min-height:auto}
  [data-beat="contact"] .rail{position:relative;min-height:auto}
}

/* 07 fit its stage exactly at 800px tall before the reCAPTCHA attribution
   existed. Rather than shrink the form, take the difference out of the beat's
   own padding on short desktop viewports. */
@media (min-width:768px) and (max-height:880px){
  [data-beat="contact"] .rail{padding-top:clamp(18px,2.2svh,40px);
    padding-bottom:clamp(18px,2.2svh,40px)}
  [data-beat="contact"] .form{margin-top:clamp(12px,1.7svh,32px)}
}

@keyframes orbBreath{0%,100%{opacity:.72;transform:scale(.94)}50%{opacity:1;transform:scale(1.06)}}

@media (prefers-reduced-motion: reduce){
  .thread{display:none}
  .marq-t{transform:none !important}
  .orb::after{animation:none !important}
}

/* Footer sign-off: "One operator." must hold visual line 2 — a 3-line break
   orphans "and run." The sentence measures 304px at 15px/Archivo, so any
   column narrower than that widows it. Two bands were short: the tablet
   3-column grid (258-302px) and phones at/below ~340px (280px). */
@media (min-width:768px) and (max-width:1023px){
  .ftr-rail{grid-template-columns:repeat(2,minmax(0,1fr))}
  .ftr-brand{grid-column:1 / -1}
}
@media (max-width:359px){
  .ftr-line{font-size:13.5px}
}
