/* ==========================================================================
   Scalesworks — scroll-driven showreel
   One accent (--purple). One light source (above). One decorative device
   (the offset duplicate). The pacing comes from weight contrast, pinned
   surfaces and progressive reveal, and from nothing else.

   Layout model: one very tall .track with a pinned .sticky stage. Every
   animated value is a pure function of the normalised scroll progress p,
   written by js/showreel.js. Nothing here animates on its own except the
   marquee and two hover transitions.
   ========================================================================== */

:root{
  /* ---- palette (fixed, do not extend) ---- */
  --ink:#01050B;
  --ink-2:#020710;
  --card:#03080F;
  --navy:#0B3266;
  --purple:#8B5CF6;
  --purple-dim:#6D3FE8;
  --amber:#EF9F27;   /* a person has to act. nothing else, ever. */
  --paper:#F3F5F9;
  --muted:#6E7E96;
  --line:rgba(255,255,255,.07);
  --line-2:rgba(255,255,255,.13);

  --body-2:#8FA0B8;   /* running prose on ink, 7.7:1 */
  --body-1:#B9C4D6;   /* lede and nav, 11.6:1 */

  --glass:rgba(4,10,20,.55);
  --glass-line:rgba(255,255,255,.16);

  /* ---- type ---- */
  --disp:"Bricolage Grotesque",ui-sans-serif,system-ui,sans-serif;
  --body:"Instrument Sans",ui-sans-serif,system-ui,sans-serif;
  --mono:"Azeret Mono",ui-monospace,monospace;

  /* ---- radii ---- */
  --r-btn:8px;
  --r-card:3vmin;
  --r-pf:2.5vmin;
  --r-surf:1.6vmin;
  --r-tile:12px;
  --r-target:30px;

  /* ---- showreel geometry. Desktop defaults; js/showreel.js swaps these on
         <html> per orientation bucket. Every timeline string reads the vars,
         so a swap never rebuilds an interpolation. ---- */
  --sr-track-vh:2000vh;
  --sr-card-w:42vmin;         /* side-card width  (= hero card HEIGHT) */
  --sr-card-h:62vmin;         /* side-card height (= hero card WIDTH)  */
  --sr-carousel-r:27vmin;     /* carousel radius (card translateZ) */
  --sr-flyback:40vmin;        /* carousel fly-back depth */
  --sr-hero-pad:8vmin;        /* hero full-screen inset (2x stage padding) */
  --sr-heading-1:18vmin;      /* handover top heading */
  --sr-heading-2:24vmin;      /* handover bottom heading */
  --sr-body-w:52vmin;         /* handover supporting-copy max-width */
  --sr-body-text:2.4vmin;     /* handover supporting-copy size */
  --sr-slot-w:min(90vw, 46svh);  /* hero surface, before the card flips */
  --sr-slot-h:62svh;
  /* Landscape docks the surface into the right column so it can never sit on
     the headline or the lede. Portrait centres it horizontally but lifts it: the
     copy above is two lines and the copy below is four plus two buttons, so the
     free band is not centred on the screen. JS eases both to 0 as the card
     flips, because by then the surface IS the card face. */
  --sr-slot-x:0px;
  --sr-slot-y:0px;

  --ease:cubic-bezier(.2,.7,.3,1);
  --gut:clamp(20px,5vw,64px);
  --max:1180px;
}

*,*::before,*::after{box-sizing:border-box}

/* clip, NOT hidden: overflow:hidden on html breaks position:sticky (CLAUDE.md 4.2) */
html{overflow-x:clip;scrollbar-width:none;-ms-overflow-style:none}
html::-webkit-scrollbar,body::-webkit-scrollbar{display:none}

body{
  margin:0;
  background:#000;
  color:var(--paper);
  font-family:var(--body);
  font-size:17px;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
}
/* No `overflow-x` on body. It makes body a scroll container, which silently
   stops the stage from pinning at all — the same trap as overflow:hidden on
   html (CLAUDE.md 4.2), one element down. `html{overflow-x:clip}` above is
   what guards the offset plate's 7px. */

h1,h2,h3,h4,p,dl,dd,ol,ul,figure{margin:0}
ol,ul{padding:0;list-style:none}
a{color:inherit;text-decoration:none}
img,svg,canvas{display:block;max-width:100%}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}

:focus-visible{outline:2px solid var(--purple);outline-offset:3px;border-radius:2px}

.skip{
  position:fixed;top:8px;left:8px;z-index:300;
  transform:translateY(-160%);
  background:var(--paper);color:var(--ink);
  padding:10px 16px;border-radius:var(--r-btn);font-weight:600;
}
.skip:focus-visible{transform:none}

.vh{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap}

/* ---- type primitives ---------------------------------------------------- */

.disp{
  font-family:var(--disp);
  font-variation-settings:"wdth" 92;
  letter-spacing:-.03em;
  line-height:.95;
  font-weight:600;
}
/* The narrative beat: a headline sets up light and pays off heavy.
   One jump per headline, never two. */
.lt{font-weight:200}
.hv{font-weight:700}

.mono{
  font-family:var(--mono);
  font-size:11px;
  line-height:1.2;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--muted);
  font-weight:400;
}

/* ---- the signature: the offset duplicate -------------------------------- */
/* From the logo, where the purple square sits offset behind the dark one.
   Primary actions only. Nowhere else. */
/* Not `isolation:isolate` on the button itself: a stacking context paints its
   own background BEFORE negative-z children, so the plate would land on top of
   the button. It goes on the CONTAINER instead — that context is transparent,
   so the plate paints over the page and under the button, which is the mark. */
.hero-btns,.cta-block,.carousel-cta,.close-cta,#dock{isolation:isolate}
.off{position:relative}
.off::before{
  content:"";position:absolute;inset:0;border-radius:inherit;
  background:var(--purple);z-index:-1;
  transform:translate(7px,7px);
  transition:transform .35s var(--ease);
}
.off:hover::before,.off:focus-visible::before{transform:translate(11px,11px)}

/* ==========================================================================
   Intro loader
   ========================================================================== */

#loader{
  position:fixed;inset:0;z-index:200;
  display:grid;place-items:center;
  overflow:hidden;background:#000;
}
#loader[hidden]{display:none}
.ld-bloom{
  position:absolute;width:78vmin;height:78vmin;border-radius:9999px;
  filter:blur(80px);opacity:0;
  background:radial-gradient(95% 80% at 50% 28%,
    #C6B4FB 0%, #8B5CF6 38%, #4B21A8 68%, #0B1330 100%);
}
.ld-mark{position:relative;width:132px;height:132px;opacity:0}
.ld-plate,.ld-dark{position:absolute;inset:0;border-radius:26px}
.ld-plate{background:var(--purple)}
.ld-dark{
  background:linear-gradient(180deg,#14375F 0%,#061428 46%,#01060E 100%);
  box-shadow:0 0 40px rgba(139,92,246,.34);
}
.ld-s{
  position:absolute;inset:0;background:var(--paper);
  -webkit-mask:url("../assets/svg/s.svg") center/76% no-repeat;
          mask:url("../assets/svg/s.svg") center/76% no-repeat;
}
.ld-word{
  position:absolute;bottom:9vh;left:50%;
  opacity:0;white-space:nowrap;
}

/* ==========================================================================
   Header
   ========================================================================== */

#hdr{
  position:fixed;left:0;top:2vmin;z-index:100;
  display:flex;width:100%;flex-direction:column;align-items:center;
  pointer-events:none;
  opacity:0;transform:translateY(-10px);
  transition:opacity .7s ease-in-out,transform .7s ease-in-out;
}
#hdr.revealed{opacity:1;transform:none}

/* One surface, not six. This was a segmented control: the container's fill
   showed through 1px gaps so every link sat in its own box, and a fixed 104px
   cell gave "Agents" and "Automations" identical rectangles. That is a
   toolbar, and a toolbar dates everything under it. Now it is one dark bar
   with text in it, each label sized to its own word. Same 46px height, so
   nothing below moves. */
.nav{
  pointer-events:auto;
  display:flex;align-items:center;gap:2px;
  height:46px;padding:0 6px;border-radius:var(--r-btn);
  background:rgba(4,9,17,.92);
  border:1px solid var(--line-2);
  box-shadow:0 10px 40px rgba(0,0,0,.5);
}
.nav-tile{
  position:relative;
  display:flex;align-items:center;justify-content:center;
  height:32px;border-radius:6px;
  color:var(--paper);font-size:14.5px;line-height:1;
}
/* The bar is 46px but the items inside it are 32px, so each one carries its
   own 44px hit area (CLAUDE.md 4.4). It fills the bar exactly and does not
   spill past it. */
.nav-tile::before{
  content:"";position:absolute;left:0;right:0;top:50%;
  height:44px;transform:translateY(-50%);
}
/* No overflow:hidden — it clipped the 44px hit area back to the 32px box.
   The mark's rotate stays inside its own bounds anyway. */
.nav-logo{width:32px;margin-right:4px}
.nav-logo::after{
  content:"";position:absolute;inset:0;
  background:var(--paper);
  -webkit-mask:url("../assets/svg/s.svg") center/62% no-repeat;
          mask:url("../assets/svg/s.svg") center/62% no-repeat;
  transition:transform .45s var(--ease);
}
.nav-logo:hover::after{transform:rotate(-8deg) scale(1.06)}
.nav-links{display:flex;align-items:center;gap:2px}
/* Rest state is dimmed and hover brings it up, rather than full white dropping
   to 55% — a link should not have to get harder to read to show it is live. */
.nav-links a{
  padding:0 14px;color:rgba(243,245,249,.68);
  transition:color .25s var(--ease),background .25s var(--ease);
}
.nav-links a:hover{color:var(--paper);background:rgba(255,255,255,.06)}
.nav-cta{
  background:var(--purple);color:#01050B;font-weight:600;
  padding-left:16px;padding-right:16px;
  transition:background .3s var(--ease);
}
.nav-cta:hover{background:#9E77F8}
.nav-toggle{display:none;width:32px}
.nav-toggle span{position:relative;display:block;width:16px;height:1.5px;background:var(--paper)}
.nav-toggle span::before,.nav-toggle span::after{
  content:"";position:absolute;left:0;width:16px;height:1.5px;background:var(--paper);
  transition:transform .3s var(--ease),opacity .2s linear;
}
.nav-toggle span::before{top:-5px}
.nav-toggle span::after{top:5px}
.nav-toggle[aria-expanded="true"] span{background:transparent}
.nav-toggle[aria-expanded="true"] span::before{transform:translateY(5px) rotate(45deg)}
.nav-toggle[aria-expanded="true"] span::after{transform:translateY(-5px) rotate(-45deg)}

/* full-screen menu below 940px (CLAUDE.md 4.4) */
#menu{
  position:fixed;inset:0;z-index:99;
  display:flex;flex-direction:column;justify-content:center;
  padding-left:var(--gut);padding-right:var(--gut);
  background:var(--ink);
  background-image:radial-gradient(120% 62% at 50% -12%,
    #0B2A54 0%, rgba(9,32,66,.42) 30%, rgba(1,5,11,0) 68%);
  opacity:0;visibility:hidden;pointer-events:none;
  transform:translateY(-8px);
  transition:opacity .3s var(--ease),transform .3s var(--ease),visibility .3s;
}
#menu.open{opacity:1;visibility:visible;pointer-events:auto;transform:none}
#menu a{
  display:flex;align-items:center;min-height:56px;
  font-family:var(--disp);font-variation-settings:"wdth" 92;
  font-size:clamp(30px,9vw,52px);font-weight:200;letter-spacing:-.03em;
  border-bottom:1px solid var(--line);
}
#menu a:last-of-type{font-weight:700;border-bottom:0}

/* ==========================================================================
   Track + pinned stage
   ========================================================================== */

.track{position:relative;height:var(--sr-track-vh)}
.sticky{
  position:sticky;top:0;height:100svh;overflow:hidden;
  padding:4vmin;
}

/* Phases 1–4 sit on the site's own surface: ink with the single top-light.
   It extinguishes as the handover scene opens, leaving true black + aurora. */
.stage-bg{
  position:absolute;inset:0;z-index:0;
  background-color:var(--ink);
  background-image:radial-gradient(120% 62% at 50% -12%,
    #0B2A54 0%, rgba(9,32,66,.42) 30%, rgba(1,5,11,0) 68%);
}

/* ---- marquee ------------------------------------------------------------ */
.marquee-wrap{
  position:absolute;left:0;top:50%;z-index:1;
  width:100vw;transform:translateY(-50%);
  pointer-events:none;overflow:hidden;
}
.mq-track{
  display:flex;align-items:center;width:max-content;
  animation:mq 25s linear infinite;
}
/* Faded out, the marquee's infinite loop was still a commit every frame.
   js/showreel.js parks it whenever its opacity is spent. Scoped to showreel
   mode like the other gates, so the static page never inherits a paused rail. */
html[data-mode="showreel"] .marquee-wrap.off{visibility:hidden}
html[data-mode="showreel"] .marquee-wrap.off .mq-track{animation-play-state:paused}
@keyframes mq{from{transform:translateX(0)}to{transform:translateX(-50%)}}
.mq-item{
  display:flex;align-items:center;
  padding-left:3vw;padding-right:3vw;
  font-family:var(--disp);font-variation-settings:"wdth" 92;
  font-size:7vw;font-weight:200;letter-spacing:-.03em;line-height:1;
  color:rgba(243,245,249,.19);
  white-space:nowrap;
}
.mq-dot{
  width:1.5vw;height:1.5vw;border-radius:9999px;
  border:2px solid rgba(243,245,249,.19);
  transform:translateY(.8vw);flex:none;
}

/* ---- 3D scene ----------------------------------------------------------- */
.scene{
  position:relative;z-index:2;
  display:flex;width:100%;height:100%;
  align-items:center;justify-content:center;
  perspective:1500px;
}
.rig{position:absolute;inset:0;transform-style:preserve-3d}
.carousel{
  position:relative;
  display:flex;width:100%;height:100%;
  align-items:center;justify-content:center;
  transform-style:preserve-3d;
}
.card{position:absolute}
.card-2,.card-3,.card-4{width:var(--sr-card-w);height:var(--sr-card-h)}
.card-1{overflow:hidden}
.card-4{display:flex;align-items:center;justify-content:center;overflow:visible}

/* ---- hover on the facing card ------------------------------------------
   The lift and the lean live in the transform (js/showreel.js writes it every
   frame, so CSS cannot own it). What is left here is what the card does with
   its own contents: it comes up out of the dark and its live rows firm up.
   Occlusion shadow, not a glow. */
.pcard,.hcard-face{transition:border-color .4s var(--ease),box-shadow .4s var(--ease)}
.log-d,.log-t,.wire-node,.mf-row{
  transition:color .4s var(--ease),border-color .4s var(--ease);
}
.card.is-hover .pcard,
.card.is-hover .hcard-face{box-shadow:0 3vmin 7vmin rgba(0,0,0,.6)}
.card.is-hover .pcard-dark{border-color:var(--line-2)}
.card.is-hover .log-row .log-d{color:var(--paper)}
.card.is-hover .log-row .log-t{color:var(--purple)}
.card.is-hover .pcard-light{border-color:rgba(1,5,11,.26)}
.card.is-hover .pcard-light .wire-node{border-color:rgba(1,5,11,.3);color:#20293A}

/* ==========================================================================
   Card 1 — hero
   ========================================================================== */

.hero-card{
  position:relative;width:100%;height:100%;
  overflow:hidden;border-radius:var(--r-card);background:#000;
}
#c-hero{position:absolute;inset:0;z-index:1;width:100%;height:100%}
/* Legibility, not decoration: the field is bright in one corner and the copy
   has to hold 4.5:1 everywhere. Invisible when it is doing its job. */
/* Fixed to the card's INITIAL box, not inset:0. While the card flips, an
   inset box shrinks every frame: the gradient re-rasters, the lede re-wraps,
   and that is main-thread work on exactly the frames that carry the flip.
   At the full-screen state these sizes are identical to inset:0; during the
   shrink the card's overflow:hidden clips them just as the smaller box did —
   the text clips instead of re-wrapping, at an opacity where nobody can tell
   the difference, and nothing lays out or paints again. */
.hero-scrim{
  position:absolute;left:0;top:0;z-index:2;pointer-events:none;
  width:calc(100vw - var(--sr-hero-pad));
  height:calc(100svh - var(--sr-hero-pad));
  background:linear-gradient(178deg,
    rgba(1,5,11,.42) 0%, rgba(1,5,11,0) 26%,
    rgba(1,5,11,0) 44%, rgba(1,5,11,.78) 100%);
}

.hero-head{
  position:absolute;left:0;top:0;z-index:3;
  width:calc(100vw - var(--sr-hero-pad));
  display:flex;padding:40px;pointer-events:none;
}
.hero-head h1{
  display:flex;flex-direction:column;align-items:flex-start;
  font-family:var(--disp);font-variation-settings:"wdth" 92;
  font-size:7vw;letter-spacing:-.03em;line-height:.95;
  text-align:left;color:#fff;
}
.hero-head .hv{opacity:.55}

.hero-rot{
  position:absolute;inset:0;z-index:7;
  display:flex;align-items:center;justify-content:center;
  pointer-events:none;
}
.hero-rot h2{
  font-family:var(--disp);font-variation-settings:"wdth" 92;
  font-size:3.6vmin;font-weight:400;letter-spacing:-.02em;line-height:1.1;
  text-align:center;color:#fff;
  /* No fixed angle here. js/showreel.js turns it against the card's flip so it
     stays upright on screen: a caption pinned in space while the card turns
     behind it. A fixed -90deg meant it was only readable at the one moment the
     flip finished, which is exactly when it fades out. */
  filter:drop-shadow(0 6px 18px rgba(0,0,0,.55));
}

@media (orientation:landscape){
  :root{--sr-slot-x:calc(50vw - var(--sr-slot-w) / 2 - 8vmin)}
}
@media (orientation:portrait){
  :root{--sr-slot-y:-6svh}
}

/* the tilting product surface */
.hero-slot{
  position:absolute;inset:0;z-index:6;
  perspective:1400px;pointer-events:none;
}
/* The run log's tabs are real buttons, so the surface opts back in even though
   card 1 is pointer-events:none until the ring has formed. js/showreel.js makes
   the panel inert once the card has tilted away, so a click can never compete
   with the scroll track. */
#heroSurfA{pointer-events:auto}
#heroSurfA[inert]{pointer-events:none}
.hero-slot-in{
  position:absolute;left:50%;top:50%;
  overflow:hidden;border-radius:var(--r-card);
  box-shadow:0 40px 90px rgba(0,0,0,.6);
}
.hero-surf{position:absolute;inset:0;width:100%;height:100%}
/* The second surface waits off to the right and counter-rotates, so it reads
   upright once the card has flipped into the carousel. It clips its own
   rotation; JS gives the inner box the slot's dimensions, swapped.

   What sits inside it is a full card, not a bare surface — the same three
   layers cards 02, 03 and 04 have: a label, a product surface, and a line at
   the bottom that says what to make of it. Without that last layer this was
   the only card on the page with no voice of its own. The slot still ends at
   exactly the card's size, so the flip geometry is untouched. */
.hero-surf-b{left:100%;overflow:hidden}
.hero-turn{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%) rotate(-90deg)}
.hero-turn > .surf,.hero-turn > .daycard{width:100%;height:100%}

/* The foot spans the full width at z-6, the same layer as the slot. It must not
   swallow pointer events over the surface docked beside it, so only the things
   you can actually press opt back in. */
.hero-foot{
  position:absolute;left:0;bottom:0;z-index:6;
  display:flex;flex-direction:column;gap:24px;
  width:calc(100vw - var(--sr-hero-pad));  /* fixed: see .hero-scrim */
  padding:40px;color:#fff;
  pointer-events:none;
}
.hero-foot .btn{pointer-events:auto}
.hero-foot .lede{
  max-width:30rem;font-size:16px;line-height:1.6;
  color:rgba(255,255,255,.92);
}
.hero-btns{display:flex;align-items:center;gap:16px}
.btn{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:48px;padding:14px 32px;border-radius:var(--r-btn);
  font-size:17px;font-weight:600;line-height:1;
  transition:background .3s var(--ease),border-color .3s var(--ease);
}
.btn-primary{background:var(--paper);color:var(--ink)}
.btn-primary:hover{background:#fff}
.btn-ghost{
  background:rgba(255,255,255,.10);color:#fff;font-weight:500;
  border:1px solid rgba(255,255,255,.22);
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
}
.btn-ghost:hover{background:rgba(255,255,255,.16)}
.hero-rule{width:100%;height:1px;background:rgba(255,255,255,.28);margin:8px 0}
.hero-meta{display:flex;align-items:center;justify-content:space-between;gap:24px}
.chips{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.chip{
  display:inline-flex;align-items:center;gap:8px;
  padding:9px 14px;border-radius:9999px;
  background:rgba(255,255,255,.10);border:1px solid rgba(255,255,255,.22);
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
  font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;
  text-transform:uppercase;color:rgba(255,255,255,.94);
}
.chip::before{
  content:"";width:5px;height:5px;border-radius:1px;
  background:var(--purple);flex:none;
}
.hero-meta p{
  max-width:32rem;text-align:right;font-size:15px;
  color:rgba(255,255,255,.88);
}

/* ==========================================================================
   Product surfaces — these are the product, so they stay in markup.
   No photography, no stock, no render standing in for a screen.
   ========================================================================== */

.surf{
  display:flex;flex-direction:column;
  background:rgba(2,7,16,.72);
  -webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);
  border:1px solid var(--line-2);
  overflow:hidden;
}
.surf-head{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:1.5vmin 1.9vmin;border-bottom:1px solid var(--line);
  flex:none;
}
.surf-head .mono{font-size:10.5px;color:var(--muted)}
.dot{
  display:inline-flex;align-items:center;gap:7px;
  font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--body-2);
}
.dot::before{
  content:"";width:6px;height:6px;border-radius:9999px;background:var(--purple);
  box-shadow:0 0 0 3px rgba(139,92,246,.18);
}
/* The agents card's only motion. It reads as live rather than as a screenshot,
   and costs nothing. Ambient, so it runs on a CSS loop; it ends on the resting
   state, which is what reduced motion collapses to. */
.dot-live::before{animation:dotPulse 2.2s ease-in-out infinite}
@keyframes dotPulse{0%,100%{opacity:1}50%{opacity:.35}}

/* Ambient loops stop while the carousel is not the subject. Gated from
   sceneVisibility(p) — one class toggle, not a second observer. Scoped to
   showreel mode: without JS the class never arrives, and an ungated rule would
   leave the static page permanently paused. */
html[data-mode="showreel"] .carousel:not(.anim) .dot-live::before,
html[data-mode="showreel"] .carousel:not(.anim) .wire-rail i,
html[data-mode="showreel"] .carousel:not(.anim) .wire-node::before,
html[data-mode="showreel"] .carousel:not(.anim) .wire-node .mono{
  animation-play-state:paused;
}
/* overflow:hidden, so a surface that runs out of room clips instead of
   painting its rows over the footer below it. */
.surf-body{display:flex;flex-direction:column;min-height:0;flex:1;overflow:hidden}
.surf-foot{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  margin-top:auto;flex:none;
  padding:1.5vmin 1.9vmin;border-top:1px solid var(--line);
}
.surf-foot .mono{font-size:10px}

/* run log */
/* Every row reserves the 2px rail, so marking one shifts nothing. The rail is
   where a human touchpoint is flagged: it is present at every width, unlike
   the status column on the right, which is dropped below 720px. */
.log-row{
  display:grid;grid-template-columns:auto 1fr auto;
  align-items:center;gap:1.4vmin;
  padding:1.25vmin 1.9vmin;border-bottom:1px solid var(--line);
  border-left:2px solid transparent;
}
.log-row:last-child{border-bottom:0}
.log-t{font-family:var(--mono);font-size:10.5px;letter-spacing:.06em;color:var(--muted)}
.log-d{font-size:13px;line-height:1.35;color:var(--body-1)}
.log-m{font-family:var(--mono);font-size:10.5px;letter-spacing:.06em;color:var(--muted)}
.log-row.on .log-d{color:var(--paper)}
.log-row.on .log-t{color:var(--purple)}

/* The one exception to the single accent. Marks a step that is waiting on a
   person, and appears nowhere else. The row already says so in words — this
   only makes the touchpoints countable at a glance. */
.log-row.human{border-left-color:var(--amber)}
.log-row.human .log-m{color:var(--amber)}

/* ---- the hero run log --------------------------------------------------
   Three tabs over one shape: header strip, phase strip, seven rows, three
   outcomes, footer strip. Every tab has the same count, so switching one for
   another never changes the panel's height. Flat fills and hairlines only —
   no gradient, no glow, no shadow inside a surface. */
.runlog{position:relative}
.rl-head{padding-top:1vmin;padding-bottom:1vmin}
.rl-tabs{display:flex;align-items:center;gap:.6vmin;min-width:0}
.rl-tab{
  position:relative;
  padding:.65vmin 1.3vmin;border-radius:9999px;
  border:1px solid var(--line-2);background:transparent;
  font-family:var(--mono);font-size:9.5px;line-height:1.2;
  letter-spacing:.12em;text-transform:uppercase;
  color:var(--body-2);white-space:nowrap;
  transition:color .25s var(--ease),background .25s var(--ease),border-color .25s var(--ease);
}
/* The pill stays small — a 44px pill would eat a third of the panel on a phone
   — but the thing you press is 44px tall. Nothing below it is interactive. */
.rl-tab::before{
  content:"";position:absolute;left:0;right:0;top:50%;
  height:44px;transform:translateY(-50%);
}
.rl-tab:hover{color:var(--paper)}
.rl-tab[aria-selected="true"]{background:var(--paper);border-color:var(--paper);color:var(--ink)}
.rl-tab[aria-selected="true"]:hover{color:var(--ink)}
.rl-label{font-size:10px;flex:none;margin-left:auto;padding-left:1.2vmin}

.rl-panel{display:flex;flex-direction:column;flex:1;min-height:0}
/* A display declaration beats the UA's [hidden]{display:none}, so the inactive
   panels have to be told again. Without this all three stack inside one surface
   and every one of them collapses. */
.rl-panel[hidden]{display:none}
.rl-panel:focus-visible{outline-offset:-3px}

.rl-phases{
  display:flex;align-items:center;gap:.6vmin;flex:none;
  padding:.9vmin 1.9vmin;border-bottom:1px solid var(--line);
}
.rl-phase{
  padding:.3vmin .95vmin;border-radius:9999px;
  border:1px solid var(--line);
  font-family:var(--mono);font-size:9px;line-height:1.3;
  letter-spacing:.12em;text-transform:uppercase;color:var(--muted);
  transition:color .25s var(--ease),background .25s var(--ease),border-color .25s var(--ease);
}
.rl-phase.done{color:var(--purple);border-color:rgba(139,92,246,.5)}
.rl-phase.on{background:var(--purple);border-color:var(--purple);color:var(--ink)}
.rl-ref{margin-left:auto;font-size:10px;flex:none;padding-left:1.2vmin}

/* The rows share the body evenly, so the panel compresses smoothly as the card
   flips instead of clipping its last rows off the bottom. Scoped to showreel
   mode: on the static page the surface has no fixed height, and a flex-basis of
   0 would collapse every row to nothing. */
.rl-body{display:flex;flex-direction:column;flex:1;min-height:0;overflow:hidden}
html[data-mode="showreel"] .rl-body .log-row{
  flex:1 1 0;min-height:0;padding-top:.6vmin;padding-bottom:.6vmin;
}
/* The reveal is carried by the row's contents, not by the row. Its rule stays
   at full strength either way, so a panel with three of seven rows filled reads
   as a log part-way through a run rather than as a panel four sevenths empty. */
.rl-body .log-row > *{
  opacity:var(--rv,1);
  transform:translateY(calc((1 - var(--rv,1)) * -4px));
}
/* The neutral hairline stays; the amber rail does not. A rail on a row that has
   not arrived yet is a human touchpoint with no words beside it, which is the
   one thing amber must never be. Channels are --amber written out, because CSS
   cannot take an alpha channel from a hex custom property. */
html[data-mode="showreel"] .rl-body .log-row.human{
  border-left-color:rgba(239,159,39,var(--rv,1));
}
/* A log line is one line. It scales with the surface — which is itself sized
   from the viewport — and truncates rather than wrapping into the row below. */
.rl-body .log-d{
  font-size:clamp(10px,1.55vmin,13px);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.rl-body .log-t,.rl-body .log-m{font-size:clamp(9px,1.2vmin,10.5px)}
.rl-body .log-row{gap:1.1vmin}

.rl-out{
  display:flex;flex-direction:column;gap:.45vmin;flex:none;
  padding:1.1vmin 1.9vmin;border-top:1px solid var(--line-2);
}
.rl-task{
  display:flex;align-items:center;gap:1.2vmin;min-width:0;
  padding:.45vmin 0 .45vmin 1.1vmin;
  border-left:2px solid var(--purple);
  font-size:12.5px;line-height:1.3;color:var(--body-1);
}
.rl-task > span:first-child{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rl-task .mono{margin-left:auto;flex:none;font-size:10px;color:var(--purple)}
/* Same rule as the log rail: amber is a person, and only a person. */
.rl-task.person{border-left-color:var(--amber)}
.rl-task.person .mono{color:var(--amber)}
.rl-foot{border-top:1px solid var(--line)}

/* ---- what is left for you ----------------------------------------------
   Three rails and nothing else. Everywhere else on the page amber is a mark in
   a margin; here it is the entire contents, because everything on this surface
   is a thing a person still has to do. That is the pay-off for spending the
   colour nowhere else. */
.waiting{
  display:flex;flex-direction:column;justify-content:space-between;
  padding:1.6vmin 1.9vmin;gap:1.1vmin;flex:1;min-height:0;overflow:hidden;
}
/* space-between only distributes FREE space; once the rows are taller than the
   box it hands out none and they spill straight through the footer. Letting
   them shrink is what keeps that from happening on a short landscape window. */
.wait-row{
  border-left:2px solid var(--amber);padding-left:1.4vmin;
  min-width:0;min-height:0;flex:0 1 auto;
}
/* Cards 02 and 03 carry a fragment; this one carries a full sentence, so it
   sets one step smaller to stay on two lines at both ends of the range. Three
   lines here squeezed the surface until the rows fell out of it. */
.daycard h2{font-size:4.1vmin}
/* Both halves stay on one line at every card size. A wrapped mono strip reads
   as a mistake rather than as a caption. */
.daycard .surf-foot .mono{white-space:nowrap;font-size:9.5px}
.wait-row b{
  display:block;font-size:clamp(12px,1.65vmin,15px);font-weight:600;
  line-height:1.3;color:var(--paper);
}
.wait-row span{
  display:block;margin-top:.35vmin;
  font-size:clamp(10.5px,1.4vmin,13px);line-height:1.35;color:var(--body-2);
}

/* wiring surface */
/* One continuous connector on the left with a single pulse travelling down it.
   Ambient, not narrative: it has no beginning or end, so it runs on a CSS loop
   rather than on p — a sequence tied to scroll would freeze the moment the
   visitor stopped, and a card that freezes reads as broken. */
.wire{
  position:relative;
  display:flex;flex-direction:column;justify-content:space-between;gap:1.1vmin;
  padding:1.4vmin 1.4vmin 1.4vmin 3.6vmin;flex:1;min-height:0;
}
.wire-rail{
  position:absolute;left:1.8vmin;top:1.4vmin;bottom:1.4vmin;
  width:1px;background:rgba(1,5,11,.16);
}
.wire-rail i{
  position:absolute;left:-2.5px;top:0;
  width:6px;height:6px;border-radius:9999px;background:var(--purple);
  opacity:0;
  animation:wirePulse 4.5s linear infinite;
}
@keyframes wirePulse{
  0%  {top:0;opacity:0}
  3%  {opacity:1}
  55% {top:100%;opacity:1}
  61% {top:100%;opacity:0}
  100%{top:100%;opacity:0}
}
/* One step, one line. The step reads left to right — bold word, then what it
   does, then its type — so wrapping it into two lines breaks the grammar and
   pushes the fourth step off the bottom of the card. */
.wire-node{
  position:relative;
  display:flex;align-items:center;gap:1.1vmin;flex:none;
  padding:1.05vmin 1.2vmin;border-radius:10px;
  border:1px solid var(--line-2);background:rgba(255,255,255,.035);
  font-size:clamp(10.5px,1.5vmin,13px);color:var(--body-1);
}
.wire-node > span:first-child{
  min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
/* The fill rides on a pseudo-element rather than on the node's own border and
   background. An animation beats a normal declaration, so animating those
   directly would have silently killed the card's hover state. z-index:-1 puts
   it above the node's background and below its text. */
.wire-node::before{
  content:"";position:absolute;inset:-1px;z-index:-1;
  border-radius:inherit;border:1px solid var(--purple);
  background:rgba(139,92,246,.12);
  opacity:0;
  animation:wireNode 4.5s linear var(--wd,0s) infinite;
}
.wire-node b{font-weight:600;color:var(--paper)}
.wire-node .mono{
  --tag-rest:var(--muted);
  font-size:clamp(8.5px,1.15vmin,10px);flex:none;margin-left:auto;
  color:var(--tag-rest);
  animation:wireTag 4.5s linear var(--wd,0s) infinite;
}
/* The pulse reaches each node at roughly these points down the rail. Held for
   400ms, then settled — the node lights, it does not throb. */
.wire-node:nth-of-type(1){--wd:.25s}
.wire-node:nth-of-type(2){--wd:.92s}
.wire-node:nth-of-type(3){--wd:1.56s}
.wire-node:nth-of-type(4){--wd:2.23s}
@keyframes wireNode{
  0%,9%   {opacity:1}
  24%,100%{opacity:0}
}
@keyframes wireTag{
  0%,9%   {color:var(--purple-dim)}
  24%,100%{color:var(--tag-rest)}
}

/* handover manifest */
.manifest{display:flex;flex-direction:column;padding:.6vmin 0;flex:1}
.mf-row{
  display:flex;align-items:center;gap:1.2vmin;
  padding:1.05vmin 1.9vmin;
  font-size:13px;color:var(--body-1);
}
.mf-row::before{
  content:"";width:9px;height:9px;border-radius:2px;flex:none;
  border:1px solid var(--purple);background:var(--purple);
}
.mf-row .mono{margin-left:auto;font-size:10px;color:var(--muted)}

/* scope sheet */
/* space-between, so the lines breathe across a tall card face instead of
   bunching at the top with the total stranded at the bottom. */
.scope{
  display:flex;flex-direction:column;justify-content:space-between;
  padding:1.6vmin 1.9vmin;gap:1.2vmin;flex:1;min-height:0;
}
.scope-line{display:flex;align-items:baseline;justify-content:space-between;gap:1.4vmin}
.scope-line span:first-child{font-size:13px;color:var(--body-1)}
.scope-line span:last-child{
  font-family:var(--mono);font-size:10.5px;letter-spacing:.06em;color:var(--muted);
}
/* No margin-top:auto here: an auto margin absorbs the free space before
   justify-content gets a look in, which is what kept the lines bunched. */
.scope-total{
  display:flex;align-items:baseline;justify-content:space-between;
  padding-top:1.2vmin;border-top:1px solid var(--line-2);
}
.scope-total b{font-family:var(--disp);font-size:2.6vmin;font-weight:700;letter-spacing:-.02em}

/* ==========================================================================
   Cards 2 & 3 — agents, automations
   ========================================================================== */

.pcard{
  position:relative;width:100%;height:100%;
  overflow:hidden;border-radius:var(--r-card);
  display:flex;flex-direction:column;padding:3.2vmin;
  background:var(--card);border:1px solid var(--line);
}
.pcard-dark{
  background:
    radial-gradient(120% 70% at 50% -10%, rgba(11,50,102,.55) 0%, rgba(1,5,11,0) 62%),
    var(--card);
  color:var(--paper);
}
/* The one light surface on the page: automations arrive as a document.
   Monochrome, so the single-accent rule holds. */
.pcard-light{
  background:var(--paper);color:#0B1220;border-color:rgba(1,5,11,.12);
}
.pcard-top{display:flex;align-items:center;justify-content:space-between;gap:12px;flex:none}
.pcard-mark{
  display:grid;place-items:center;
  width:3.4vmin;height:3.4vmin;min-width:26px;min-height:26px;
  border-radius:.9vmin;background:var(--paper);
}
.pcard-mark::after{
  content:"";width:70%;height:70%;background:#01050B;
  -webkit-mask:url("../assets/svg/s.svg") center/contain no-repeat;
          mask:url("../assets/svg/s.svg") center/contain no-repeat;
}
.pcard-light .pcard-mark{background:#0B1220}
.pcard-light .pcard-mark::after{background:var(--paper)}
.pcard-top .mono,.hcard-top .mono{font-size:10.5px}
.pcard-light .mono{color:#5B6779}

.pcard-mid{margin-top:2.6vmin;flex:none}
.pcard-pill{
  display:flex;align-items:center;justify-content:space-between;gap:1.5vmin;
  border-radius:4vmin;padding:1.8vmin 2vmin;
  border:1px solid var(--glass-line);background:var(--glass);
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
}
.pcard-pill .k{display:block;font-size:1.4vmin;opacity:.62;line-height:1.3}
.pcard-pill .v{display:block;font-size:2.2vmin;line-height:1.2}
.pcard-badge{
  display:grid;place-items:center;flex:none;
  width:3vmin;height:3vmin;min-width:24px;min-height:24px;
  border-radius:9999px;background:var(--glass-line);
  font-size:1.6vmin;line-height:1;color:var(--paper);
}
.pcard-light .pcard-pill{
  background:#0B1220;border-color:#0B1220;color:var(--paper);border-radius:5vmin;
}
.pcard-light .pcard-badge{background:rgba(255,255,255,.18)}
.pcard-q{
  flex:1;min-width:0;font-size:1.7vmin;opacity:.85;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}

.pcard-surface{flex:1;min-height:0;margin-top:2.4vmin;border-radius:var(--r-surf)}
.pcard-light .pcard-surface{
  background:rgba(11,18,32,.04);border-color:rgba(1,5,11,.12);
  -webkit-backdrop-filter:none;backdrop-filter:none;
}
.pcard-light .log-d,.pcard-light .wire-node{color:#39455A}
.pcard-light .log-t,.pcard-light .log-m,.pcard-light .surf-head .mono{color:#5B6779}
.pcard-light .log-row,.pcard-light .surf-head{border-color:rgba(1,5,11,.10)}
.pcard-light .wire-node{border-color:rgba(1,5,11,.14);background:rgba(255,255,255,.7)}
.pcard-light .wire-node b{color:#0B1220}
.pcard-light .wire-node .mono{--tag-rest:#5B6779}
.pcard-light .dot{color:#39455A}

.pcard-bottom{margin-top:2.6vmin;flex:none}
.pcard h2{
  font-family:var(--disp);font-variation-settings:"wdth" 92;
  font-size:4.6vmin;letter-spacing:-.03em;line-height:1.05;font-weight:200;
}
.pcard h2 strong{font-weight:700;color:#fff}
.pcard-light h2{font-size:3.4vmin}
.pcard-light h2 strong{color:#0B1220}

/* ==========================================================================
   Card 4 — handover, and the scene it opens into
   ========================================================================== */

.hcard-face{
  position:absolute;inset:0;overflow:hidden;border-radius:var(--r-card);
  background:radial-gradient(95% 80% at 50% 28%,
    #CDBCFB 0%, #8B5CF6 38%, #5B24C9 68%, #180A3C 100%);
}
.hcard-in{
  display:flex;flex-direction:column;width:100%;height:100%;
  padding:3.2vmin;color:#fff;
}
.hcard-top{display:flex;align-items:center;justify-content:space-between;gap:12px;white-space:nowrap}
/* The label carries the same size as the other three cards. Its own colour,
   though: --muted is a dark-background value and this card is purple. */
.hcard-top .mono{color:rgba(255,255,255,.86)}
.hcard-in h2{
  margin-top:auto;max-width:88%;
  font-family:var(--disp);font-variation-settings:"wdth" 92;
  font-size:4.4vmin;letter-spacing:-.03em;line-height:1.05;font-weight:200;
}
.hcard-in h2 strong{font-weight:700}

/* the panel the mark opens into */
.reveal{
  position:absolute;left:50%;top:50%;
  width:300vw;height:300vh;
}
/* The portal, in two layers. The mask never changes size: .rv-clip scales up
   and .rv-anti scales down by the exact inverse, so the window grows on the
   compositor while the scene inside holds still. 150vmin base, so the raster
   is sharp both scaled down to the 8vmin badge and up past the screen. The
   default transforms are the p=0 state (8/150 and its inverse); JS and the
   compiled keyframes take over from there. */
.rv-clip{
  position:absolute;inset:0;
  -webkit-mask:url("../assets/svg/mark-mask.svg") center/150vmin no-repeat;
          mask:url("../assets/svg/mark-mask.svg") center/150vmin no-repeat;
  transform:scale(.05333);
}
.rv-anti{position:absolute;inset:0;background:#000;transform:scale(18.75)}
/* js/showreel.js lifts the mask once the window has outgrown every viewport
   and everything behind the plane is black anyway. It returns on scroll-up. */
.reveal.open .rv-clip{-webkit-mask:none;mask:none}
.reveal-in{position:absolute;left:50%;top:50%;width:100vw;height:100svh}
#c-sphere{position:absolute;left:50%;top:50%;z-index:2;width:100%;height:100%}
.reveal-mark{
  position:absolute;left:50%;top:50%;z-index:3;
  width:12vh;height:12vh;background:#fff;
  -webkit-mask:url("../assets/svg/s.svg") center/contain no-repeat;
          mask:url("../assets/svg/s.svg") center/contain no-repeat;
}
.rv-h1,.rv-h2{
  position:absolute;z-index:4;color:#fff;
  font-family:var(--disp);font-variation-settings:"wdth" 92;
  letter-spacing:-.03em;line-height:.85;
}
.rv-h1{left:4vmin;top:4vmin;font-size:var(--sr-heading-1);font-weight:200}
.rv-h2{
  right:4vmin;bottom:4vmin;
  display:flex;flex-direction:column;align-items:flex-end;text-align:right;
  font-size:var(--sr-heading-2);font-weight:700;
}
.rv-body{
  position:absolute;left:4vmin;bottom:5vmin;z-index:4;
  display:flex;flex-direction:column;gap:1.8vmin;
  max-width:var(--sr-body-w);
  font-size:var(--sr-body-text);font-weight:300;line-height:1.45;color:#fff;
}
/* The copy sits directly on a moving field of particles. A shadow, not a panel:
   it holds contrast without putting a box around the words. */
.rv-h1,.rv-h2,.rv-body{text-shadow:0 2px 16px rgba(0,0,0,.9)}

/* Portrait has a fixed nav at the top and an action bar at the bottom. The
   three lines move into the upper half and the copy sits clear of both. */
@media (orientation:portrait){
  .rv-h1{top:15vmin;left:5vmin}
  .rv-h2{top:30vmin;bottom:auto;right:5vmin}
  .rv-body{
    left:5vmin;right:5vmin;max-width:none;
    bottom:calc(84px + env(safe-area-inset-bottom));
  }
}

/* ==========================================================================
   Parallax tiles — fragments of the week, flying past
   ========================================================================== */

/* Each tile is scaled down to a third by its depth, so type is sized to survive
   that: they must still read as surfaces from the far end of the field. */
/* Opacity and visibility are written per tile by js/showreel.js, never as a
   custom property on the rig: an inherited property there recalculates the
   style of everything on the stage every frame it changes. Hidden as well as
   dark, so twenty invisible layers do not ride along in every commit. */
.tile{
  position:absolute;left:50%;top:50%;z-index:-1;
  overflow:hidden;opacity:0;visibility:hidden;
  background:
    radial-gradient(130% 80% at 50% -14%, rgba(11,50,102,.55) 0%, rgba(1,5,11,0) 62%),
    rgba(5,12,22,.97);
  border:1px solid var(--line-2);
  contain:paint;
}
.tile-in{
  display:flex;flex-direction:column;gap:2vmin;
  width:100%;height:100%;padding:3.4vmin 3.6vmin;
}
.tile-in .mono{font-size:2.4vmin;letter-spacing:.14em}
.tile-line{
  display:flex;align-items:center;justify-content:space-between;gap:2vmin;
  padding-bottom:2vmin;border-bottom:1px solid var(--line);
  font-size:3.2vmin;line-height:1.25;color:var(--body-1);
}
.tile-line:last-child{border-bottom:0}
.tile-line span:last-child{font-family:var(--mono);font-size:2.2vmin;color:var(--muted);flex:none}
.tile-line.on{color:var(--paper)}
.tile-line.on span:last-child{color:var(--purple)}
/* Same rule as everywhere else: a person has to act. Two of the twelve agents
   are holding for one, which is the whole point of flying through the rest. */
.tile-line.you{color:var(--paper)}
.tile-line.you span:last-child{color:var(--amber)}

/* Each tile works through its three lines on a shared loop, offset per tile by
   a negative delay so every one of them is already mid-job when the field
   appears. Ambient — a floor of agents has no beginning or end — so it runs in
   CSS rather than off the scroll, and stops dead when the field is not on
   screen. */
.tile-line{animation:tileRun 6.4s linear var(--td,0s) infinite}
.tile-in .tile-line:nth-of-type(2){animation-delay:calc(var(--td,0s) + .5s)}
.tile-in .tile-line:nth-of-type(3){animation-delay:calc(var(--td,0s) + 1s)}
@keyframes tileRun{
  0%       {opacity:.22}
  9%,74%   {opacity:1}
  86%,100% {opacity:.22}
}
html[data-mode="showreel"] .rig:not(.anim) .tile-line{animation-play-state:paused}
.tile-big{
  margin-top:auto;
  font-family:var(--disp);font-variation-settings:"wdth" 92;
  font-size:9.5vmin;font-weight:200;letter-spacing:-.03em;line-height:.95;
  color:var(--paper);
}
.tile-big strong{font-weight:700;display:block}

/* ==========================================================================
   Target block — the landing
   ========================================================================== */

/* Parked at the far end of the flight path. Constant, so it lives here: the
   camera rig travels exactly this far and the two cancel out on arrival. */
.target{
  position:absolute;left:50%;top:50%;z-index:-1;
  width:100vw;height:100svh;overflow:hidden;background:var(--ink);
  transform:translate(calc(-50% + 250vw), calc(-50% + 100vh)) translateZ(-2250px);
}
#c-target{position:absolute;inset:0;width:100%;height:100%}
/* The page reasserting itself: the block is matted back down to the site's
   own surface as the flight settles. */
.target-frame{
  position:absolute;inset:-4vmin;z-index:3;pointer-events:none;
  border-radius:11vmin;border:8vmin solid var(--ink);
}
.cta-block{
  position:absolute;inset:0;z-index:2;
  display:flex;flex-direction:column;align-items:flex-start;justify-content:center;
  gap:2.5vmin;padding:9vmin;pointer-events:none;
}
.cta-block h2{
  display:flex;flex-direction:column;align-items:flex-start;
  max-width:60vw;
  font-family:var(--disp);font-variation-settings:"wdth" 92;
  font-size:7vw;letter-spacing:-.03em;line-height:.95;color:var(--paper);
}
.cta-block h2 .hv{opacity:.55}
.cta-block p{max-width:26vw;font-size:2.2vmin;line-height:1.45;color:rgba(243,245,249,.8)}
.cta-block .btn{pointer-events:auto;margin-top:1.5vmin;font-size:2.1vmin;padding:2.2vmin 4.6vmin;min-height:0}

/* ---- the field's own headline ------------------------------------------
   Sits in screen space in front of the flight, so it names what you are moving
   through. Nothing else on the page occupies this stretch of the scroll. */
/* Sits high rather than centred: the landing block is parked to the right and
   drifts to the middle as the camera comes round, so a centred headline ends
   up on top of it just as it arrives. */
.field-head{
  position:absolute;left:0;right:0;top:29%;z-index:4;
  display:flex;flex-direction:column;align-items:center;gap:2vmin;
  padding-left:8vmin;padding-right:8vmin;
  transform:translateY(-50%);text-align:center;pointer-events:none;
}
.field-head h2{
  max-width:22ch;
  font-family:var(--disp);font-variation-settings:"wdth" 92;
  font-size:clamp(34px,6.4vw,104px);letter-spacing:-.03em;line-height:.95;
  color:var(--paper);
  text-shadow:0 2px 24px rgba(1,5,11,.85);
}
.field-head p{
  max-width:40ch;font-size:clamp(15px,2.1vmin,21px);line-height:1.5;
  color:var(--body-1);text-shadow:0 2px 16px rgba(1,5,11,.9);
}

/* ---- carousel CTA ------------------------------------------------------- */
.carousel-cta{
  position:absolute;left:0;right:0;bottom:2vmin;z-index:3;
  display:flex;justify-content:center;
  padding-left:4vmin;padding-right:4vmin;
  pointer-events:none;
}
.carousel-cta .btn{
  pointer-events:auto;font-size:2.1vmin;padding:2vmin 4.2vmin;min-height:0;
}

/* ==========================================================================
   Aurora overlay
   ========================================================================== */

#aurora{position:fixed;inset:0;z-index:30;pointer-events:none;opacity:0}
#c-aurora{position:absolute;inset:0;width:100%;height:100%}

/* ==========================================================================
   Process — the fixed panning section
   ========================================================================== */

#process{
  position:fixed;inset:0;z-index:40;
  display:flex;flex-direction:column;overflow:hidden;
  padding-top:9vmin;padding-bottom:8vmin;
  pointer-events:none;transform:translateY(100%);
}
.pf-track{
  display:flex;height:100%;gap:3vmin;
  padding-left:3vmin;width:max-content;
}
.pf-card{
  position:relative;display:grid;
  grid-template-columns:1fr minmax(0,.82fr);gap:3.5vmin;align-items:stretch;
  width:62vw;flex:none;overflow:hidden;
  border-radius:var(--r-pf);padding:3.5vmin;
  background:rgba(3,8,15,.86);border:1px solid var(--line-2);
  -webkit-backdrop-filter:blur(20px);backdrop-filter:blur(20px);
  color:var(--paper);
}
.pf-left{display:flex;flex-direction:column;justify-content:space-between;gap:3vmin;min-width:0}
/* The three headings sit on one line across the row. The text block is pinned
   to the bottom of the column, so its height decided where the heading landed:
   Scope's six lines put it a hundred pixels above Build's three, and the
   headings stepped down across the cards. Reserving a fixed share of the
   column fixes the heading's line instead — the cards are all exactly as tall
   as each other, so a percentage resolves to the same pixel in all three. The
   text bottoms go ragged in exchange, which is what text normally does.
   52% clears the tallest block measured (48.3%, Hand over at 900x620); a
   longer paragraph than that would push its own heading up again. */
.pf-left > div{min-height:52%}
.pf-meta{
  display:flex;align-items:center;gap:1.4vmin;
  font-family:var(--mono);font-size:clamp(10.5px,1.35vmin,16px);letter-spacing:.14em;
  text-transform:uppercase;color:var(--body-2);white-space:nowrap;
  /* Matches the surface head's padding, so the step label and the surface's
     own label sit on one line instead of a dozen pixels apart — which reads
     worse than either aligning or clearly not aligning. */
  padding-top:1.6vmin;
}
.pf-meta i{opacity:.45;font-style:normal}

/* ---- the process surfaces ----------------------------------------------
   These cards are three to four times the size of a carousel card, so their
   surfaces cannot keep the carousel's fixed type: at 1920 a 13px row sat next
   to 21px body copy and read as a footnote. Everything inside scales with the
   card, one step below the body copy it stands beside.

   And they size to their contents rather than stretching. Five to eight rows
   cannot fill an 800px column: forcing it either spread the scope sheet's rows
   91px apart or left the other two bunched at the top over a dead band. */
.pf-surface{
  min-width:0;height:auto;max-height:100%;align-self:start;
  border-radius:var(--r-surf);
}
.pf-surface .surf-head,.pf-surface .surf-foot{padding:1.6vmin 2vmin}
.pf-surface .dot,
.pf-surface .surf-head .mono,
.pf-surface .surf-foot .mono,
.pf-surface .log-t,
.pf-surface .log-m,
.pf-surface .mf-row .mono,
.pf-surface .scope-line span:last-child{font-size:clamp(10.5px,1.2vmin,15px)}
.pf-surface .log-d,
.pf-surface .mf-row,
.pf-surface .scope-line span:first-child{font-size:clamp(13px,1.6vmin,19px);line-height:1.45}
.pf-surface .log-row,.pf-surface .mf-row{padding:1.4vmin 2vmin;gap:2vmin}
.pf-surface .manifest{padding:.8vmin 0}
.pf-surface .mf-row::before{width:1.1vmin;height:1.1vmin;min-width:9px;min-height:9px}
/* The status tag never wraps. If something has to give it is the label on the
   left, which is a sentence and reads fine over two lines; "written down"
   broken across two lines just looks like a mistake. */
.pf-surface .mf-row .mono,
.pf-surface .scope-line span:last-child{flex:none;white-space:nowrap}
.pf-surface .scope{justify-content:flex-start;gap:1.9vmin;padding:2vmin}
.pf-surface .scope-total{margin-top:1.4vmin;padding-top:1.6vmin}
.pf-surface .scope-total b{font-size:clamp(19px,2.6vmin,32px)}
.pf-card h2{
  font-family:var(--disp);font-variation-settings:"wdth" 92;
  font-size:7vw;font-weight:200;letter-spacing:-.03em;line-height:.95;
}
.pf-card h2 strong{font-weight:700}
.pf-card p:not(.pf-meta){max-width:34ch;font-size:2vmin;line-height:1.5;color:var(--body-1);margin-top:2vmin}

/* ==========================================================================
   Closing section — after the track
   ========================================================================== */

.close{
  position:relative;z-index:50;
  background-color:var(--ink);
  background-image:radial-gradient(120% 62% at 50% -12%,
    #0B2A54 0%, rgba(9,32,66,.42) 30%, rgba(1,5,11,0) 68%);
  padding-top:clamp(84px,10vw,150px);
  padding-bottom:clamp(40px,5vw,64px);
}
.wrap{
  width:100%;max-width:var(--max);margin-inline:auto;
  padding-left:var(--gut);padding-right:var(--gut);
}
.close h2{
  font-family:var(--disp);font-variation-settings:"wdth" 92;
  font-size:clamp(34px,6vw,64px);letter-spacing:-.03em;line-height:1;
  margin-bottom:14px;
}
.close .lede{max-width:46ch;color:var(--body-1);font-size:clamp(17px,2vw,19px)}
.tiers{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:16px}
.tier{
  display:flex;flex-direction:column;gap:10px;
  padding:26px 24px 24px;border-radius:14px;
  background:var(--card);border:1px solid var(--line);
}
.tier h3{font-family:var(--disp);font-size:22px;font-weight:600;letter-spacing:-.02em}
.tier p{font-size:15px;color:var(--body-2);line-height:1.55}
/* The figure is a <p>, and `.tier p` sets both size and colour at the same
   specificity — so the shared look has to be claimed at two classes deep or the
   price silently renders as body copy. */
.fig{font-family:var(--disp);font-weight:200;letter-spacing:-.02em}
.tier .fig,.price-row .fig{
  font-size:clamp(20px,2.2vw,28px);color:var(--paper);line-height:1.1;
}
.tier .fig{margin-top:auto;padding-top:14px}

/* Scope above the three builds, upkeep below them. Neither is a fourth tier:
   scope is what comes first and upkeep is a different axis entirely, and as
   cards they would both read as a choice against Automation/Agent/Software. */
.price-row{
  display:grid;grid-template-columns:minmax(0,1fr) auto;
  gap:8px 32px;align-items:baseline;
  margin-top:40px;padding:24px;border-radius:14px;
  background:var(--ink-2);border:1px solid var(--line);
}
/* The rungs sit tight against each other; only the first one is set apart from
   the lede above it. */
.price-row + .price-row,.price-row.upkeep{margin-top:16px}
.price-row-main{grid-row:span 2}
.price-row h3{
  font-family:var(--disp);font-size:22px;font-weight:600;letter-spacing:-.02em;
  margin-bottom:6px;
}
.price-row-main p{max-width:56ch;font-size:15px;color:var(--body-2);line-height:1.55}
.price-row .fig{text-align:right;white-space:nowrap}
.price-row.upkeep .fig{font-size:clamp(18px,1.9vw,23px);white-space:normal}
.price-note{text-align:right;max-width:30ch;justify-self:end}
.upkeep-foot{
  grid-column:1 / -1;margin-top:12px;padding-top:16px;
  border-top:1px solid var(--line);
  font-size:15px;color:var(--body-1);
}
.src{
  display:block;
  font-family:var(--mono);font-size:10.5px;line-height:1.5;letter-spacing:.14em;
  text-transform:uppercase;color:var(--muted);
}
/* Links inside running prose. Underlined, because on a page with one accent
   colour, hue alone cannot say "this is a link". */
.pay a,.req-intro a,.req-ok a,.req-status a,.legal a{
  color:var(--paper);text-decoration:underline;
  text-decoration-color:rgba(243,245,249,.4);text-underline-offset:3px;
}
.pay a:hover,.req-intro a:hover,.req-ok a:hover,.req-status a:hover,.legal a:hover{text-decoration-color:var(--paper)}

.pay{display:grid;gap:8px;max-width:72ch;margin-top:24px;font-size:15px;line-height:1.55;color:var(--body-2)}

/* The booking form. The intro sits left and the form right; below 940px they
   stack. Status is carried by words and weight, never by a colour. */
.close-cta{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.35fr);
  gap:32px 56px;align-items:start;
  margin-top:56px;padding-top:44px;border-top:1px solid var(--line);
}
.req-intro h3{
  font-family:var(--disp);font-variation-settings:"wdth" 92;
  font-size:clamp(26px,3vw,34px);font-weight:600;letter-spacing:-.02em;line-height:1.05;
  margin-bottom:14px;
}
.req-intro p{max-width:40ch;color:var(--body-2);font-size:15px}
.req-intro p + p{margin-top:12px}
.req{display:grid;gap:18px}
.req-row{display:grid;grid-template-columns:1fr 1fr;gap:18px}
.req-f{display:grid;gap:8px}
.req input:not([type="checkbox"]),.req textarea{
  width:100%;padding:13px 14px;
  font:inherit;font-size:16px;line-height:1.4;color:var(--paper);
  background:var(--ink-2);border:1px solid var(--line-2);border-radius:var(--r-btn);
  transition:border-color .25s var(--ease);
}
.req input:not([type="checkbox"]):hover,.req textarea:hover{border-color:rgba(255,255,255,.26)}
.req textarea{min-height:128px;resize:vertical}
.req ::placeholder{color:var(--muted);opacity:1}
/* The whole line is the hit area, so the box itself can stay 20px. */
.req-ok{
  display:flex;align-items:flex-start;gap:12px;min-height:44px;padding:8px 0;
  font-size:15px;line-height:1.5;color:var(--body-1);cursor:pointer;
}
.req-ok input{flex:none;width:20px;height:20px;margin:1px 0 0;accent-color:var(--purple);cursor:pointer}
.req-go{display:flex;flex-wrap:wrap;align-items:center;gap:16px 24px}
.req-go .btn[disabled]{opacity:.6;cursor:progress}
.req-status{flex:1;min-width:min(100%,24ch);font-size:15px;color:var(--body-1)}
.req-status.err{color:var(--paper);font-weight:600}
.req-hp{position:absolute;left:-10000px;width:1px;height:1px;overflow:hidden}
.req-done{padding:28px;border-radius:14px;background:var(--card);border:1px solid var(--line-2)}
.req-done h3{font-family:var(--disp);font-size:26px;font-weight:600;letter-spacing:-.02em;line-height:1.1}
.req-done p{margin-top:8px;color:var(--body-1);font-size:15px}

.foot{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:16px;margin-top:56px;padding-top:24px;border-top:1px solid var(--line);
}
.foot nav{display:flex;flex-wrap:wrap;gap:12px 20px}
.foot a:hover{color:var(--paper)}

/* Who the business legally is, on every page. */
.legal{display:grid;gap:4px;margin-top:20px;font-size:13px;line-height:1.55;color:var(--body-2)}
.legal b{color:var(--paper);font-weight:600}
.accept{display:flex;flex-wrap:wrap;align-items:center;gap:8px 10px;margin-top:12px}
.scheme{flex:none;width:38px;height:24px}

/* ---- mobile dock -------------------------------------------------------- */
#dock{
  position:fixed;left:0;right:0;bottom:0;z-index:90;
  display:none;align-items:center;gap:12px;
  padding:12px var(--gut) calc(12px + env(safe-area-inset-bottom));
  background:rgba(1,5,11,.88);
  -webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);
  border-top:1px solid var(--line);
  transform:translateY(110%);visibility:hidden;
  transition:transform .4s var(--ease),visibility .4s;
}
#dock.up{transform:none;visibility:visible}
#dock p{flex:1;min-width:0;font-size:13px;line-height:1.3;color:var(--body-2)}
#dock .btn{padding:12px 20px;font-size:15px;min-height:44px;flex:none}

/* ==========================================================================
   Responsive
   ========================================================================== */

/* The lede stops where the docked surface starts. This has to sit AFTER the
   base `.hero-foot .lede` rule: same specificity, so source order decides, and
   declared earlier it silently did nothing. */
@media (orientation:landscape){
  .hero-foot .lede{
    max-width:min(30rem, calc(50vw + var(--sr-slot-x) - var(--sr-slot-w) / 2 - 4vmin - 64px));
  }
}

@media (max-width:1024px){
  .pf-card h2{font-size:8vw}
  .cta-block p{max-width:44vw}
}

@media (max-width:940px){
  .hero-rule,.hero-meta{display:none}
  .nav-links{display:none}
  .nav-toggle{display:flex}
  #dock{display:flex}
  .carousel-cta{display:none}
  .cta-block{padding:7vmin}
  .cta-block h2{max-width:88vw}
  .cta-block p{max-width:80vw;font-size:3.2vmin}
  .cta-block .btn{font-size:3vmin;padding:2.6vmin 5vmin;min-height:44px}
  .tiers{grid-template-columns:1fr}
  .close-cta{grid-template-columns:minmax(0,1fr)}
}

/* Portrait: the process cards stack, and the section keeps clear of the fixed
   nav above and the action bar below. */
@media (orientation:portrait){
  #process{
    padding-top:84px;
    padding-bottom:calc(80px + env(safe-area-inset-bottom));
  }
  .pf-card{
    grid-template-columns:1fr;grid-template-rows:auto minmax(0,1fr);
    width:84vw;padding:5vmin;gap:3vmin;
  }
  .pf-left{justify-content:flex-start;gap:2.5vmin}
  .pf-meta{font-size:10.5px;padding-top:0}
  .pf-card h2{font-size:max(13vw,42px)}
  .pf-card p:not(.pf-meta){font-size:15px;max-width:40ch;margin-top:12px}
  /* Stacked here, so the surface takes the row it was given rather than
     hugging its contents at the top of a column that no longer exists. */
  .pf-surface{height:100%;max-height:none;align-self:stretch}
  .pf-surface .scope{justify-content:space-between}
  /* the copy sits in the upper half, the mark drops in below it */
  .cta-block{justify-content:flex-start;padding:26vh 7vmin 0}
  .cta-block p{font-size:15px;max-width:34ch}
  .cta-block .btn{font-size:16px;padding:15px 30px;min-height:48px}
}

@media (max-width:720px){
  .off::before{transform:translate(5px,5px)}
  .off:hover::before,.off:focus-visible::before{transform:translate(8px,8px)}
  /* Three steps, not four squeezed in. The run shortens with the rail; the
     timing does not compress, so the pulse still reads as one thing moving. */
  .wire-node:nth-of-type(4){display:none}
  .wire-node:nth-of-type(1){--wd:.35s}
  .wire-node:nth-of-type(2){--wd:1.24s}
  .wire-node:nth-of-type(3){--wd:2.13s}
  .price-row{grid-template-columns:minmax(0,1fr)}
  .price-row-main{grid-row:auto}
  .price-row .fig,.price-note{text-align:left;justify-self:start;white-space:normal}
  .price-note{max-width:none}
  .upkeep-foot{margin-top:4px}
  /* clears the fixed nav, which sits 2vmin from the screen edge */
  .hero-head{padding:76px 20px 20px}
  .hero-head h1{font-size:max(11vw,34px)}
  .hero-foot{padding:20px;gap:16px}
  .hero-foot .lede{font-size:14px}
  .hero-btns{flex-direction:column;align-items:stretch;gap:12px}
  .hero-btns .btn{width:100%;font-size:15px}
  .hero-rule,.hero-meta{display:none}
  .log-m,.tile-line span:last-child{display:none}
  .pcard h2{font-size:5.4vmin}
  .daycard h2{font-size:4.9vmin}
  .pcard-light h2{font-size:4.2vmin}
  .pcard-pill .v{font-size:2.8vmin}
  .pcard-pill .k{font-size:1.9vmin}
  .pcard-q{font-size:2.2vmin}
  .pcard-top .mono,.pcard-light .mono,.hcard-top .mono{font-size:10px}
  .hcard-in h2{font-size:5.4vmin}
  .cta-block h2{font-size:11vw}
  /* Centred blocks are left-aligned on a narrow screen (CLAUDE.md 4.4). */
  .field-head{align-items:flex-start;text-align:left;padding-left:20px;padding-right:20px}
  .field-head h2{font-size:11vw;max-width:none}
  .mq-item{font-size:11vw}
  .hero-rot h2{font-size:5vmin}
  .foot{flex-direction:column;align-items:flex-start}
  .close-cta .btn{width:100%}
  .req-row{grid-template-columns:minmax(0,1fr)}
}

/* Narrow surfaces. Everything is sized in vmin so a 250px-wide card still
   reads as a screen, and no mono label drops below the contrast floor: the
   small ones move off --muted rather than shrinking into it. */
@media (max-width:620px){
  .surf-head,.surf-foot{padding:2vmin 2.4vmin}
  .log-row{padding:1.8vmin 2.4vmin;gap:1.8vmin}
  .log-d{font-size:3.1vmin;line-height:1.3}
  .log-t{font-size:2.6vmin;color:var(--body-2)}
  .surf-head .mono,.surf-foot .mono,.dot{font-size:2.4vmin}
  .mf-row{font-size:3.1vmin;padding:1.6vmin 2.4vmin}
  .mf-row .mono{font-size:2.4vmin}
  .wire{padding:2vmin 2vmin 2vmin 4.8vmin;gap:1.4vmin}
  .wire-rail{left:2.4vmin;top:2vmin;bottom:2vmin}
  .wire-node{font-size:2.9vmin;padding:1.5vmin 1.6vmin}
  .wire-node .mono{font-size:2.3vmin}
  /* Three steps here instead of four, so there is vertical room the desktop
     card does not have. Let the step wrap rather than truncate — the type tag
     is half the meaning and neither half should be the one that goes. */
  .wire-node > span:first-child{white-space:normal;overflow:visible}
  .waiting{padding:2.2vmin 2.4vmin;gap:1.8vmin}
  .wait-row{padding-left:1.8vmin}
  .wait-row b{font-size:3.4vmin}
  .wait-row span{font-size:2.9vmin}
  .scope{padding:2vmin 2.4vmin;gap:1.6vmin}
  .scope-line span:first-child{font-size:3.1vmin}
  .scope-line span:last-child{font-size:2.5vmin}
  .scope-total b{font-size:4.2vmin}
  /* A carousel card is 94vmin tall on a phone. Rather than clip the last row
     mid-sentence, drop it: the surface has to read complete at any size. */
  .pcard-surface .surf-body > .log-row:nth-child(n+4){display:none}

  /* The run log keeps all seven rows at every width — the sequence IS the
     argument, so it shrinks rather than losing steps. Below 620px the status
     column is already gone, so the line has the room to go back up in size. */
  .rl-body .log-d{font-size:3.1vmin}
  .rl-body .log-t{font-size:2.6vmin}
  .rl-head{padding:1.3vmin 2.4vmin}
  .rl-tab{font-size:2.2vmin;padding:.8vmin 1.5vmin}
  .rl-label{font-size:2.2vmin}
  .rl-phases{padding:1.1vmin 2.4vmin;gap:.7vmin}
  .rl-phase{font-size:2vmin;padding:.4vmin 1vmin}
  .rl-ref{font-size:2.2vmin}
  .rl-out{padding:1.3vmin 2.4vmin;gap:.5vmin}
  .rl-task{font-size:2.9vmin;padding-left:1.4vmin}
  .rl-task .mono{font-size:2.3vmin}
}

/* ==========================================================================
   Static mode
   Served when JS is unavailable, WebGL is unavailable, or the visitor asks
   for reduced motion. Same markup, same words, no pinning and no motion:
   one ordinary page you can read top to bottom.
   ========================================================================== */

html:not([data-mode="showreel"]) body{
  background-color:var(--ink);
  background-image:radial-gradient(120% 62% at 50% -12%,
    #0B2A54 0%, rgba(9,32,66,.42) 30%, rgba(1,5,11,0) 68%);
  background-attachment:fixed;background-repeat:no-repeat;
}
html:not([data-mode="showreel"]) #loader,
html:not([data-mode="showreel"]) #aurora,
html:not([data-mode="showreel"]) .marquee-wrap,
html:not([data-mode="showreel"]) .stage-bg,
html:not([data-mode="showreel"]) .hero-scrim,
html:not([data-mode="showreel"]) .hero-rot,
html:not([data-mode="showreel"]) .carousel-cta,
html:not([data-mode="showreel"]) .target-frame,
html:not([data-mode="showreel"]) .reveal-mark,
html:not([data-mode="showreel"]) #dock,
html:not([data-mode="showreel"]) canvas{display:none}

html:not([data-mode="showreel"]) #hdr{opacity:1;transform:none;position:absolute}
html:not([data-mode="showreel"]) .track{height:auto}
html:not([data-mode="showreel"]) .sticky{
  position:static;height:auto;overflow:visible;
  padding-top:calc(66px + 6vh);padding-bottom:0;padding-left:0;padding-right:0;
}
html:not([data-mode="showreel"]) .scene{display:block;width:100%;height:auto;perspective:none}
html:not([data-mode="showreel"]) .rig{position:static;transform:none!important}
/* minmax(0,1fr), not 1fr: an auto grid column is sized by its widest item's
   min-content, and one long mono label would push every card past the gutter. */
html:not([data-mode="showreel"]) .carousel{
  display:grid;grid-template-columns:minmax(0,1fr);
  gap:var(--gut);width:100%;height:auto;
  max-width:var(--max);margin-inline:auto;
  padding-left:var(--gut);padding-right:var(--gut);
}
html:not([data-mode="showreel"]) .card{
  position:static!important;transform:none!important;opacity:1!important;
  width:auto!important;height:auto!important;
}
/* Height comes from content, not from the card box. A min-height on the wrapper
   leaves a dead band below every card (the surface inside cannot resolve a
   percentage height against it) and stretches every surface's internal spacing. */
html:not([data-mode="showreel"]) .pcard-surface{flex:none}
html:not([data-mode="showreel"]) .wire{justify-content:flex-start}
html:not([data-mode="showreel"]) .scope-total{margin-top:8px}
html:not([data-mode="showreel"]) .hcard-face{min-height:34svh}
html:not([data-mode="showreel"]) .hero-card{background:var(--card);border:1px solid var(--line)}
html:not([data-mode="showreel"]) .hero-head{position:static;padding-bottom:0}
html:not([data-mode="showreel"]) .hero-head h1{font-size:clamp(38px,8vw,88px)}
html:not([data-mode="showreel"]) .hero-slot{position:static;display:block;perspective:none;padding:0 40px}
html:not([data-mode="showreel"]) .hero-slot-in{
  position:static;transform:none!important;
  width:100%!important;height:auto!important;margin-top:28px;
}
html:not([data-mode="showreel"]) .hero-surf{position:relative;opacity:1!important;transform:none!important}
/* It used to be hidden here, which was fine while it was a bare document. Now
   it carries a heading and the page's only all-amber surface, so it reads on
   after the run log instead — unturned, and without its own card shell, since
   it is already inside one. */
html:not([data-mode="showreel"]) .hero-surf-b{position:relative;left:auto;margin-top:28px}
html:not([data-mode="showreel"]) .hero-turn{
  position:static;transform:none;
  width:auto!important;height:auto!important;
}
html:not([data-mode="showreel"]) .daycard{
  height:auto;background:none;border:0;padding:0;overflow:visible;
}
html:not([data-mode="showreel"]) .daycard .pcard-surface{margin-top:16px}
html:not([data-mode="showreel"]) .waiting{gap:16px}
/* No JS means no tabs, so all three runs are shown one under the other rather
   than two thirds of the argument being locked behind a dead control. Each
   panel still carries its own reference and phases, so they read apart. */
html:not([data-mode="showreel"]) .rl-tabs{display:none}
html:not([data-mode="showreel"]) .rl-panel[hidden]{display:flex}
html:not([data-mode="showreel"]) .rl-panel + .rl-panel{border-top:1px solid var(--line-2)}
html:not([data-mode="showreel"]) .rl-body{flex:none;overflow:visible}
html:not([data-mode="showreel"]) .rl-label{margin-left:0}
/* Every row is shown filled here, so every phase has run. Leaving the pills in
   their "not yet" state would contradict the log right under them. */
html:not([data-mode="showreel"]) .rl-phase{color:var(--purple);border-color:rgba(139,92,246,.5)}
html:not([data-mode="showreel"]) .rl-task > span:first-child{white-space:normal;overflow:visible}
html:not([data-mode="showreel"]) .hero-foot{position:static;margin-top:8px}
html:not([data-mode="showreel"]) .hero-head *,
html:not([data-mode="showreel"]) .cta-block *,
html:not([data-mode="showreel"]) .rv-h1 *,
html:not([data-mode="showreel"]) .rv-h2 *{
  transform:none!important;filter:none!important;opacity:1!important;
}
html:not([data-mode="showreel"]) .hero-head .hv,
html:not([data-mode="showreel"]) .cta-block h2 .hv{opacity:.55!important}
html:not([data-mode="showreel"]) .card-4{display:block}
html:not([data-mode="showreel"]) .pcard,
html:not([data-mode="showreel"]) .hcard-face{position:relative;inset:auto;width:100%;height:100%}
html:not([data-mode="showreel"]) .pcard h2{font-size:clamp(26px,4vw,42px)}
html:not([data-mode="showreel"]) .pcard-light h2{font-size:clamp(22px,3.2vw,34px)}
html:not([data-mode="showreel"]) .pcard-top .mono,
html:not([data-mode="showreel"]) .hcard-top .mono{font-size:11px}
html:not([data-mode="showreel"]) .pcard-pill .v{font-size:20px}
html:not([data-mode="showreel"]) .pcard-pill .k{font-size:12px}
html:not([data-mode="showreel"]) .pcard-q{font-size:15px}
html:not([data-mode="showreel"]) .hcard-in h2{font-size:clamp(26px,4vw,42px)}
html:not([data-mode="showreel"]) .reveal{
  position:static;width:auto;height:auto;transform:none!important;
  -webkit-mask:none;mask:none;background:none;margin-top:var(--gut);
}
/* the portal layers are showreel machinery; here they must not even be boxes */
html:not([data-mode="showreel"]) .rv-clip,
html:not([data-mode="showreel"]) .rv-anti{
  display:contents;
  -webkit-mask:none;mask:none;
}
html:not([data-mode="showreel"]) .reveal-in{
  position:static;width:auto;height:auto;transform:none!important;
  display:flex;flex-direction:column;gap:20px;
  padding:36px 32px;border-radius:var(--r-card);
  background:var(--ink-2);border:1px solid var(--line);
}
html:not([data-mode="showreel"]) .rv-h1,
html:not([data-mode="showreel"]) .rv-h2{
  position:static;font-size:clamp(44px,11vw,120px);align-items:flex-start;text-align:left;
}
html:not([data-mode="showreel"]) .rv-h2{flex-direction:row;gap:.22em}
html:not([data-mode="showreel"]) .rv-body{
  position:static;max-width:60ch;font-size:16px;gap:14px;color:var(--body-1);
}
html:not([data-mode="showreel"]) .tile{display:none}
/* No field to fly through here, so the line stands on its own between the
   process and the close. */
html:not([data-mode="showreel"]) .field-head{
  position:static;transform:none!important;opacity:1!important;visibility:visible!important;
  align-items:flex-start;text-align:left;
  max-width:var(--max);margin-inline:auto;
  padding:clamp(64px,8vw,110px) var(--gut) 0;
}
html:not([data-mode="showreel"]) .field-head h2{font-size:clamp(34px,6vw,64px);max-width:20ch}
html:not([data-mode="showreel"]) .field-head h2 .hv{opacity:.55}
html:not([data-mode="showreel"]) .target{
  position:static;width:auto;height:auto;transform:none!important;
  opacity:1!important;border-radius:0!important;
  margin-top:clamp(84px,10vw,150px);
  background:
    radial-gradient(90% 70% at 50% 0%, rgba(139,92,246,.3) 0%, rgba(1,5,11,0) 62%),
    var(--ink);
  border-top:1px solid var(--line);
}
html:not([data-mode="showreel"]) .cta-block{
  position:static;padding:clamp(64px,9vw,120px) var(--gut);
  max-width:var(--max);margin-inline:auto;
}
html:not([data-mode="showreel"]) .cta-block h2{font-size:clamp(38px,8vw,88px);max-width:none}
html:not([data-mode="showreel"]) .cta-block p{max-width:46ch;font-size:18px}
html:not([data-mode="showreel"]) .cta-block .btn{font-size:17px;padding:16px 34px;min-height:48px}
html:not([data-mode="showreel"]) #process{
  position:static;transform:none!important;padding:clamp(84px,10vw,150px) 0 0;
  pointer-events:auto;
}
html:not([data-mode="showreel"]) .pf-track{
  display:grid;grid-template-columns:minmax(0,1fr);
  gap:var(--gut);width:100%;height:auto;
  max-width:var(--max);margin-inline:auto;
  padding-left:var(--gut);padding-right:var(--gut);
  transform:none!important;
}
html:not([data-mode="showreel"]) .pf-card{width:auto;min-height:46svh;padding:36px 32px}
html:not([data-mode="showreel"]) .pf-card h2{font-size:clamp(38px,7vw,76px)}
html:not([data-mode="showreel"]) .pf-card > p{font-size:17px}
html:not([data-mode="showreel"]) .pf-meta{font-size:11px}
html:not([data-mode="showreel"]) .pf-surface{width:100%;max-height:none;height:auto;margin-top:24px}
html:not([data-mode="showreel"]) .pf-top{flex-direction:column;gap:20px}

/* Reduced motion always lands on the static page, plus no residual motion. */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important;
  }
}

/* ==========================================================================
   Phones: no backdrop blur
   ==========================================================================
   backdrop-filter makes a phone read back everything behind the element and
   blur it, every frame. Here that was seven elements, and two of them are the
   expensive kind: .surf sits inside 3D-transformed cards, and .pf-card is
   three panels 62vw wide sliding horizontally with a 20px blur. Measured on
   the device, the frame median was already a healthy 17ms — this is not what
   fills a frame, it is what makes a frame stall.

   The blur is barely legible on an almost-black page anyway. The two large
   surfaces get a more opaque fill in exchange, so nothing behind them shows
   through where the blur used to hide it. The small ones only lose the filter;
   at chip size there was nothing to see.
   ========================================================================== */
@media (max-width:940px), (hover:none) and (pointer:coarse){
  .surf{
    background:rgba(2,7,16,.95);
    -webkit-backdrop-filter:none;backdrop-filter:none;
  }
  .pf-card{
    background:rgba(3,8,15,.97);
    -webkit-backdrop-filter:none;backdrop-filter:none;
  }
  #dock{
    background:rgba(1,5,11,.97);
    -webkit-backdrop-filter:none;backdrop-filter:none;
  }
  .btn-ghost,.chip,.pcard-pill{
    -webkit-backdrop-filter:none;backdrop-filter:none;
  }
}
