/* ══════════════════════════════════════════════════════════════════════
   REFRACT STUDIO
   ──────────────────────────────────────────────────────────────────────
   Structural colour idea: the page is lit by two opposed fixtures.
   KEY  = violet  #5332FD  (top-left source)
   FILL = terracotta #CA4E4E (bottom-right source)
   Every section declares a gel via data attributes; main.js blends the
   active gels by viewport overlap and writes --key-rgb / --fill-rgb /
   --house-rgb / --ink-rgb here. Nothing in this file hard-codes a
   section colour except the terracotta payoff in §07.
   ══════════════════════════════════════════════════════════════════════ */

/* ─────────────────────────────────────────────── TOKENS ── */
:root{
  /* The five-colour system, by its names in the brand guidelines. The
     Electric Indigo / Blushed Brick pairing is structural rather than
     decorative — violet is doing a lot of work in software branding just
     now, and the terracotta against it is what stops this reading as one
     more SaaS palette. Applied with restraint, never as a gradient. */
  --violet:#5332FD;   /* Electric Indigo */
  --terra:#CA4E4E;    /* Blushed Brick  */
  --ice:#D4F2FF;      /* Pale Sky       */
  --slate:#3D3C4D;    /* Graphite       */
  --cream:#FFEACC;    /* House Glow     */
  --black:#131218;    /* Umbra          */

  /* Corona — the guide's fixed logo ink for dark grounds (p.15). The mark
     is held to this regardless of section, per p.12: "without pulling
     from the UI accent palette." */
  --corona:247 241 232;

  /* live, JS-driven (rgb triplets so we can vary alpha) */
  --key-rgb:83 50 253;
  --fill-rgb:202 78 78;
  --house-rgb:8 7 12;
  --ink-rgb:212 242 255;

  --key:rgb(var(--key-rgb));
  --fill:rgb(var(--fill-rgb));
  --house:rgb(var(--house-rgb));
  --ink:rgb(var(--ink-rgb));

  /* scroll drivers, written every frame by main.js */
  --scroll:0;        /* 0–1 document progress */
  --vel:0;           /* -1 – 1 signed, smoothed scroll velocity */
  --vabs:0;          /* 0–1 absolute velocity */
  --mx:50vw;         /* pointer */
  --my:50vh;
  --lamp:0;          /* 0–1 lamp presence */

  /* the mark: one supplied logo, used as a mask everywhere so it inherits
     the live ink rather than baking in a colour. --mark-ar is the file's
     own box, 794.64 : 192.36. */
  --mark:url(images/logo/refract-wordmark.svg);
  --mark-ar:4.3191;
  --lockup:url(images/logo/refract-lockup.svg);
  --lockup-ar:3.1184;  /* the studio lockup, 817.90 : 262.28 */

  /* type */
  --sans:"articulat-cf","Helvetica Neue",Arial,sans-serif;
  --heavy:"articulat-heavy-cf","articulat-cf","Helvetica Neue",Arial,sans-serif;
  --mono:"cofo-sans-mono-variable",ui-monospace,"SFMono-Regular",Menlo,monospace;

  /* rhythm */
  --gut:clamp(14px,2.2vw,32px);
  --edge:clamp(14px,2.4vw,40px);
  --deck-h:clamp(52px,5.4vw,68px);
  --hair:1px;
  --line:rgb(var(--ink-rgb) / .16);
  --line-soft:rgb(var(--ink-rgb) / .08);

  --ease:cubic-bezier(.16,1,.3,1);
  --ease-io:cubic-bezier(.65,0,.35,1);

  color-scheme:dark;
}

/* ─────────────────────────────────────────────── RESET ── */
*,*::before,*::after{box-sizing:border-box;border-radius:0}
html,body{margin:0;padding:0}
html{
  -webkit-text-size-adjust:100%;
  scrollbar-width:none;
  background:var(--black);
}
html::-webkit-scrollbar{width:0;height:0}
@media (prefers-reduced-motion:no-preference){ html{scroll-behavior:smooth} }

body{
  font-family:var(--sans);
  font-weight:400;
  background:var(--house);
  color:var(--ink);
  overflow-x:clip;
  line-height:1.28;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  transition:background-color .4s linear;
}
body[data-gate="on"]{overflow:hidden;height:100vh}

img,svg,canvas{display:block;max-width:100%}
h1,h2,h3,p,ol,ul,dl,dd,figure{margin:0;padding:0}
ol,ul{list-style:none}
a{color:inherit;text-decoration:none}
button,input,select,textarea{
  font:inherit;color:inherit;background:none;border:0;
  border-radius:0;-webkit-appearance:none;appearance:none;
}
button{cursor:pointer}
::selection{background:var(--key);color:#fff}

.vh{
  position:absolute;width:1px;height:1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;
}
.skip{
  position:fixed;top:8px;left:8px;z-index:9999;padding:10px 14px;
  background:var(--ice);color:#000;font:600 11px/1 var(--mono);
  letter-spacing:.14em;transform:translateY(-200%);
  border-radius:2px;   /* Radius Small, p.35 */
}
.skip:focus{transform:none}
:focus-visible{outline:2px solid var(--ice);outline-offset:3px}

/* ─────────────────────────────────────────────── SHARED TYPE ── */
.tag,.lbl{
  font-family:var(--mono);
  font-size:clamp(9px,.72vw,11px);
  font-weight:500;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:rgb(var(--ink-rgb) / .5);
  font-feature-settings:"tnum" 1;
}
.tag--r{text-align:right}
.mono-dim{font-family:var(--mono);font-size:11px;letter-spacing:.12em;color:rgb(var(--ink-rgb) / .38)}

.spec{
  display:grid;gap:0;
  border-top:var(--hair) solid var(--line);
}
.spec > div{
  display:grid;grid-template-columns:minmax(72px,7em) 1fr;gap:1em;
  padding:.62em 0;border-bottom:var(--hair) solid var(--line-soft);
  font-family:var(--mono);font-size:clamp(9px,.7vw,11px);
  letter-spacing:.14em;text-transform:uppercase;
}
.spec dt{color:rgb(var(--ink-rgb) / .38)}
.spec dd{color:rgb(var(--ink-rgb) / .82);margin:0}
.spec--tight > div{padding:.42em 0}

/* Display type carries two opposed light sources. At rest the sources are
   coincident and the type is clean; the smear only appears while the light
   is moving — a long exposure of a fixture in transit. */
.lit-type{
  text-shadow:
    calc(var(--vel) * -16px) calc(var(--vabs) * -5px) 0 rgb(var(--key-rgb) / calc(var(--vabs) * .85)),
    calc(var(--vel) *  16px) calc(var(--vabs) *  5px) 0 rgb(var(--fill-rgb) / calc(var(--vabs) * .75));
}

/* Cue-out curtain. Every pinned section takes itself to house black over
   the last half-viewport of its track, so handing off to the next pin
   reads as a blackout between looks instead of a mechanical slide. */
.mast__pin::after,.mani__pin::after,.svc__pin::after,
.work__pin::after,.about__pin::after{
  content:"";position:absolute;inset:0;z-index:60;pointer-events:none;
  background:rgb(var(--house-rgb));
  opacity:var(--exit,0);
}

/* ─────────────────────────────────────────────── MORSE ──
   Light is how this studio signals, so the site signals back. Marks are
   built by main.js from [data-morse]; dots and dashes are square, in
   keeping with the no-radius motif. */
.morse{
  display:inline-flex;align-items:center;
  gap:4px;vertical-align:middle;
  margin-left:.9em;
  color:currentColor;
}
.morse .mch{display:inline-flex;align-items:center;gap:2px}
.morse i{display:block;height:2px;background:currentColor;opacity:.42}
.morse i.dot{width:2px}
.morse i.dash{width:8px}
.morse .mw{width:9px;flex:0 0 auto}          /* word gap, no ink */
/* full-bleed variants distribute their letters across the whole width */
.morse--wide{flex:1;justify-content:space-between;margin:0;gap:0;position:relative}
.morse--wide::before{
  content:"";position:absolute;left:0;right:0;top:50%;height:1px;
  background:currentColor;opacity:.1;
}
.morse--wide .mw{width:0}
/* progressively keyed out by scroll */
.morse--wide i{opacity:.14;transition:opacity .35s linear}
.morse--wide i.sent{opacity:.8}

/* ─────────────────────────────────────────────── HOUSE LAYERS ── */
.grain{
  position:fixed;inset:-50%;z-index:900;pointer-events:none;
  opacity:.5;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='.55'/%3E%3C/svg%3E");
  animation:grainshift 7s steps(6) infinite;
}
@keyframes grainshift{
  0%{transform:translate(0,0)}    16%{transform:translate(-2%,1%)}
  32%{transform:translate(1%,-2%)} 48%{transform:translate(-1%,-1%)}
  64%{transform:translate(2%,1%)}  80%{transform:translate(-2%,2%)}
  100%{transform:translate(0,0)}
}
.vignette{
  position:fixed;inset:0;z-index:899;pointer-events:none;
  background:radial-gradient(120% 90% at 50% 45%,transparent 42%,rgb(0 0 0 / .62) 100%);
}

/* ─────────────────────────────────────────────── CURSOR / LAMP ── */
.lamp{
  position:fixed;top:0;left:0;z-index:950;pointer-events:none;
  width:0;height:0;
  transform:translate3d(var(--lx,-100px),var(--ly,-100px),0);
  opacity:var(--lamp);
  transition:opacity .35s linear;
  will-change:transform;
}
.lamp__wash{
  position:absolute;left:50%;top:50%;width:400px;height:400px;
  margin:-200px 0 0 -200px;
  background:radial-gradient(circle,
    rgb(var(--key-rgb) / .30) 0%,
    rgb(var(--key-rgb) / .12) 26%,
    rgb(var(--fill-rgb) / .05) 52%,
    transparent 72%);
  mix-blend-mode:screen;
  transform:scale(var(--lamp-scale,1));
  transition:transform .5s var(--ease);
}
.lamp__core{
  position:absolute;left:50%;top:50%;width:7px;height:7px;margin:-3.5px 0 0 -3.5px;
  background:var(--ice);mix-blend-mode:screen;
  box-shadow:0 0 12px 2px rgb(212 242 255 / .8);
  transform:scale(var(--core-scale,1));
  transition:transform .25s var(--ease);
}
.lamp__cross{position:absolute;left:50%;top:50%;background:rgb(212 242 255 / .30);mix-blend-mode:screen}
.lamp__cross--h{width:44px;height:1px;margin:0 0 0 -22px}
.lamp__cross--v{width:1px;height:44px;margin:-22px 0 0 0}
/* state: over an interactive target the lamp irises down to a hot spot */
body.is-hot .lamp{--lamp-scale:.42;--core-scale:2.6}
@media (hover:none),(pointer:coarse){ .lamp{display:none} }

/* per-character refraction, applied by main.js to [data-refract] */
.ch{display:inline-block;will-change:transform;transform:translate3d(var(--cdx,0),var(--cdy,0),0)}
.ch--near{
  text-shadow:
    calc(var(--cdx) * -.55) calc(var(--cdy) * -.55) 0 rgb(var(--key-rgb) / .85),
    calc(var(--cdx) *  .55) calc(var(--cdy) *  .55) 0 rgb(var(--fill-rgb) / .8);
}

/* ─────────────────────────────────────────────── GATE ── */
/* Seven channels, seven letters. gate.js lights a letter when its channel
   actually lands, so the sequence you watch IS the load — see gate.js.
   No copy, no channel names: the mark, a bar and a number.

   Each channel masks to its OWN letter file (images/logo/letters/), all of
   which keep the full wordmark viewBox — so the seven stack straight on
   top of each other and no letter can bleed into its neighbour. See the
   note in gate.js for why one shared mark cut into seven does not work. */
.gate{
  position:fixed;inset:0;z-index:1000;background:#000;
  display:grid;place-items:center;overflow:hidden;
  clip-path:inset(0 0 0 0);
  transition:clip-path .8s var(--ease-io),opacity .3s linear .5s;
}
.gate__inner{position:relative;width:min(760px,84vw)}

.gate__chs{position:relative;width:100%;aspect-ratio:var(--mark-ar)}
.gate__ch{position:absolute;inset:0;transform-origin:var(--gc,50%) 50%}
.gate__ltr,
.gate__ch::before,
.gate__ch::after{
  position:absolute;inset:0;
  -webkit-mask:var(--ltr) no-repeat 50% 50% / 100% 100%;
  mask:var(--ltr) no-repeat 50% 50% / 100% 100%;
}
.gate__ltr{
  display:block;
  background-color:rgb(212 242 255 / .07);
  transition:background-color .5s var(--ease);
}
.gate__ch.is-on .gate__ltr{background-color:var(--ice)}
/* a channel that never arrived sits between the two, rather than
   reporting good — the only signal it needs is that it is not lit */
.gate__ch.is-late .gate__ltr{background-color:rgb(212 242 255 / .2)}

/* The strike, as refraction rather than a split: the letter arrives already
   dispersed — two gel ghosts thrown either side of it — and they bend back
   into the letter as it resolves. Nothing separates; it converges. */
.gate__ch::before,.gate__ch::after{
  content:"";opacity:0;pointer-events:none;
  /* both ghosts sit above the letter so the two sides of the dispersion
     read the same weight; they fade to nothing, so nothing is covered */
  z-index:1;
  mix-blend-mode:screen;
  transform-origin:var(--gc,50%) 50%;
}
.gate__ch::before{background:var(--key)}
.gate__ch::after{background:var(--fill)}
.gate__ch.is-struck .gate__ltr{animation:chresolve .76s var(--ease)}
.gate__ch.is-struck::before{animation:chrefract-a .76s var(--ease)}
.gate__ch.is-struck::after{animation:chrefract-b .76s var(--ease)}
@keyframes chresolve{
  0%  {opacity:.12;filter:blur(5px)}
  45% {opacity:.86}
  100%{opacity:1;filter:blur(0)}
}
@keyframes chrefract-a{
  0%  {opacity:.95;transform:translateX(-2.6%) scaleX(1.055);filter:blur(9px)}
  55% {opacity:.5}
  100%{opacity:0;transform:none;filter:blur(1px)}
}
@keyframes chrefract-b{
  0%  {opacity:.9;transform:translateX(2.6%) scaleX(1.055);filter:blur(9px)}
  55% {opacity:.45}
  100%{opacity:0;transform:none;filter:blur(1px)}
}

.gate__bar{margin-top:clamp(22px,5vh,44px);height:1px;background:rgb(212 242 255 / .12)}
.gate__bar i{display:block;height:100%;width:0;background:var(--ice)}
.gate__pct{
  margin-top:10px;text-align:right;
  font-family:var(--mono);font-size:clamp(9px,.8vw,11px);letter-spacing:.2em;
  color:rgb(212 242 255 / .34);
  font-feature-settings:"tnum" 1;
}
.gate__pct b{color:var(--ice);font-weight:700}

/* a beat at full, then a hard blackout — the same handover the pinned
   sections make to each other */
.gate.is-black .gate__chs,
.gate.is-black .gate__pct,
.gate.is-black .gate__bar{opacity:0;transition:none;animation:none}
/* ...and the gate closes like a shutter, opening on the site */
.gate.is-out{clip-path:inset(50% 0 50% 0);opacity:0}

/* ─────────────────────────────────────────────── PREVIEW / PLAYER ── */
/* Same desk as the rest of the site: the playhead is a fader, the
   volume is a level, the state is GO / HOLD. Coloured by the show's own
   gel, which main.js writes onto .vp as --cue-rgb when it opens. */
.vp{
  position:fixed;inset:0;z-index:1100;
  display:grid;place-items:center;
  padding:clamp(12px,3vh,40px) clamp(12px,3vw,48px);
  --cue-rgb:var(--key-rgb);
}
.vp[hidden]{display:none}
body[data-vp="on"]{overflow:hidden}
body[data-vp="on"] .lamp{display:none}      /* the real pointer runs the desk */
.vp__scrim{
  position:absolute;inset:0;
  background:rgb(2 2 5 / .93);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
}
.vp__frame{
  position:relative;z-index:1;
  width:min(1180px,100%);max-height:100%;
  display:flex;flex-direction:column;
  background:#050409;
  border:var(--hair) solid rgb(var(--ink-rgb) / .14);
  box-shadow:0 40px 120px rgb(0 0 0 / .8),0 0 60px rgb(var(--cue-rgb) / .12);
}
.vp__frame:fullscreen{width:100%;max-height:none;height:100%;border:0}

.vp__head{
  display:flex;align-items:center;gap:1.4em;
  padding:clamp(9px,1.4vh,15px) clamp(12px,1.6vw,22px);
  border-bottom:var(--hair) solid rgb(var(--ink-rgb) / .12);
  font-family:var(--mono);font-size:clamp(9px,.74vw,11px);letter-spacing:.2em;
}
.vp__name{
  flex:1;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  color:rgb(var(--ink-rgb) / .82);text-transform:uppercase;
}
.vp__close{
  font-family:var(--mono);font-size:inherit;letter-spacing:.2em;
  color:rgb(var(--ink-rgb) / .5);
  padding:.35em .6em;
  border:var(--hair) solid rgb(var(--ink-rgb) / .16);
  border-radius:2px;   /* ghost button — Radius Small, p.35 */
  transition:color .3s linear,border-color .3s linear,background .3s linear;
}
.vp__close:hover,.vp__close:focus-visible{
  color:var(--cream);border-color:rgb(var(--cue-rgb));
  background:rgb(var(--cue-rgb) / .16);
}

.vp__stage{
  position:relative;flex:1;min-height:0;
  background:#000;display:grid;place-items:center;
}
.vp__video{
  display:block;width:100%;height:100%;
  max-height:min(72vh,100%);object-fit:contain;background:#000;
}
.vp__frame:fullscreen .vp__video{max-height:none}
/* the whole plate is the play control, with a mark that only shows when
   it is paused — nothing sits over the picture while it is running */
.vp__hit{
  position:absolute;inset:0;
  display:grid;place-items:center;
  background:rgb(2 2 5 / .34);
  transition:background .35s var(--ease),opacity .35s var(--ease);
}
.vp.is-playing .vp__hit{background:transparent;opacity:0}
.vp.is-playing .vp__hit:hover,
.vp.is-playing .vp__hit:focus-visible{opacity:1;background:rgb(2 2 5 / .22)}
.vp__mark{
  width:clamp(52px,7vw,86px);aspect-ratio:1;border-radius:50%;
  border:var(--hair) solid rgb(var(--ink-rgb) / .7);
  background:rgb(4 3 9 / .55);
  position:relative;display:block;
  transition:transform .4s var(--ease),background .4s var(--ease),border-color .4s var(--ease);
}
.vp__mark::after{
  content:"";position:absolute;top:50%;left:55%;transform:translate(-50%,-50%);
  border-left:clamp(15px,2vw,24px) solid rgb(var(--ink-rgb) / .95);
  border-top:clamp(10px,1.3vw,16px) solid transparent;
  border-bottom:clamp(10px,1.3vw,16px) solid transparent;
}
/* running: the mark becomes a pause, drawn from the same box */
.vp.is-playing .vp__mark::after{
  border:0;left:50%;
  width:clamp(13px,1.7vw,20px);height:clamp(17px,2.2vw,26px);
  background:linear-gradient(90deg,
    rgb(var(--ink-rgb) / .95) 0 34%,transparent 34% 66%,rgb(var(--ink-rgb) / .95) 66%);
}
.vp__hit:hover .vp__mark,.vp__hit:focus-visible .vp__mark{
  transform:scale(1.09);
  background:rgb(var(--cue-rgb) / .85);border-color:rgb(var(--cue-rgb));
}
.vp__wait{
  position:absolute;left:0;right:0;bottom:clamp(10px,2vh,20px);
  text-align:center;pointer-events:none;
  font-family:var(--mono);font-size:9px;letter-spacing:.34em;
  color:rgb(var(--cue-rgb));
  opacity:0;transition:opacity .3s linear;
}
.vp.is-waiting .vp__wait{opacity:1;animation:vpwait 1.1s steps(1) infinite}
@keyframes vpwait{50%{opacity:.25}}

.vp__transport{
  display:flex;align-items:center;gap:clamp(10px,1.4vw,22px);
  padding:clamp(10px,1.5vh,16px) clamp(12px,1.6vw,22px);
  border-top:var(--hair) solid rgb(var(--ink-rgb) / .12);
  font-family:var(--mono);font-size:clamp(9px,.74vw,11px);letter-spacing:.18em;
  color:rgb(var(--ink-rgb) / .55);
  font-feature-settings:"tnum" 1;
}
.vp__go{
  display:flex;align-items:center;gap:.6em;
  min-width:6.4em;
  padding:.5em .85em;
  font-family:var(--mono);font-size:inherit;letter-spacing:.2em;font-weight:700;
  color:rgb(var(--cue-rgb));
  border:var(--hair) solid rgb(var(--cue-rgb) / .5);
  background:rgb(var(--cue-rgb) / .1);
  border-radius:4px;   /* primary transport button — Radius Medium, p.35 */
  transition:background .3s linear,color .3s linear;
}
.vp__go:hover,.vp__go:focus-visible{background:rgb(var(--cue-rgb) / .24);color:var(--cream)}
.vp__go i{width:7px;height:7px;background:rgb(var(--cue-rgb));display:block}
.vp.is-playing .vp__go i{animation:vprun 1.6s var(--ease-io) infinite}
@keyframes vprun{50%{opacity:.25}}

/* the playhead, built like the desk's own faders */
.vp__fader{
  position:relative;flex:1;min-width:0;height:20px;
  display:flex;align-items:center;
  cursor:pointer;touch-action:none;
}
.vp__fader::before{
  content:"";position:absolute;left:0;right:0;height:2px;
  background:rgb(var(--ink-rgb) / .14);
}
.vp__buf,.vp__fill{position:absolute;left:0;height:2px;width:0}
.vp__buf{background:rgb(var(--ink-rgb) / .22)}
.vp__fill{background:rgb(var(--cue-rgb));box-shadow:0 0 10px rgb(var(--cue-rgb) / .6)}
.vp__knob{
  position:absolute;left:0;top:50%;
  width:3px;height:14px;margin-left:-1.5px;
  background:var(--cream);
  transform:translateY(-50%);
  box-shadow:0 0 8px rgb(var(--cue-rgb) / .8);
  transition:height .2s var(--ease);
}
.vp__fader:hover .vp__knob,.vp__fader:focus-visible .vp__knob{height:20px}
.vp__fader:focus-visible{outline:var(--hair) solid rgb(var(--cue-rgb));outline-offset:4px}

.vp__tc{white-space:nowrap;color:rgb(var(--ink-rgb) / .42)}
.vp__tc b{color:var(--ink);font-weight:700}
.vp__lvl,.vp__full{
  font-family:var(--mono);font-size:inherit;letter-spacing:.18em;
  color:rgb(var(--ink-rgb) / .5);white-space:nowrap;
  padding:.4em .55em;
  border:var(--hair) solid rgb(var(--ink-rgb) / .14);
  border-radius:2px;   /* ghost button — Radius Small, p.35 */
  transition:color .3s linear,border-color .3s linear;
}
.vp__lvl b{color:var(--ink);font-weight:700}
.vp__lvl:hover,.vp__full:hover,
.vp__lvl:focus-visible,.vp__full:focus-visible{
  color:var(--cream);border-color:rgb(var(--cue-rgb) / .6);
}
.vp.is-muted .vp__lvl{color:var(--terra);border-color:rgb(202 78 78 / .5)}

@media (max-width:760px){
  .vp{padding:0}
  .vp__frame{width:100%;height:100%;max-height:none;border:0}
  .vp__transport{gap:9px;flex-wrap:wrap}
  .vp__fader{order:-1;flex:1 0 100%}
  .vp__full{display:none}
}

/* ─────────────────────────────────────────────── DECK / NAV ── */
.deck{
  position:fixed;top:0;left:0;right:0;z-index:800;
  height:var(--deck-h);
  display:grid;
  grid-template-columns:minmax(180px,1fr) auto minmax(180px,1fr);
  align-items:center;
  padding:0 var(--edge);
  border-bottom:var(--hair) solid var(--line-soft);
  background:linear-gradient(180deg,rgb(var(--house-rgb)) 0%,rgb(var(--house-rgb)) 62%,rgb(var(--house-rgb) / 0) 100%);
}
.lockup{display:flex;align-items:center}
.lockup__word{
  /* the supplied studio lockup, carried as a mask so it takes the live gel
     ink instead of freezing one colour into an image. Sized off the deck so
     it holds the same optical weight as the bar shrinks. */
  display:block;
  height:min(34px,calc(var(--deck-h) * .5));
  aspect-ratio:var(--lockup-ar);
  background-color:rgb(var(--corona) / .88);
  -webkit-mask:var(--lockup) no-repeat 50% 50% / contain;
  mask:var(--lockup) no-repeat 50% 50% / contain;
  transition:background-color .5s linear;
}
.lockup:hover .lockup__word{background-color:rgb(var(--corona))}

.patch{display:flex;gap:clamp(10px,1.6vw,28px);justify-self:center}
.patch a{
  position:relative;
  font-family:var(--mono);font-size:clamp(9px,.72vw,11px);
  letter-spacing:.18em;color:rgb(var(--ink-rgb) / .46);
  padding:6px 0 6px 0;
  transition:color .3s linear;
}
.patch a::after{
  content:"";position:absolute;left:0;bottom:0;width:100%;height:1px;
  background:var(--key);transform:scaleX(0);transform-origin:0 50%;
  transition:transform .45s var(--ease);
}
.patch a:hover,.patch a.is-live{color:rgb(var(--ink-rgb) / 1)}
.patch a:hover::before,.patch a.is-live::before{color:var(--key)}
.patch a.is-live::after,.patch a:hover::after{transform:scaleX(1)}

.deck__meta{
  display:flex;align-items:center;gap:8px;justify-self:end;
  font-family:var(--mono);font-size:clamp(9px,.72vw,11px);
  letter-spacing:.18em;color:rgb(var(--ink-rgb) / .46);
  font-feature-settings:"tnum" 1;
}
.deck__tz{color:rgb(var(--ink-rgb) / .26)}

/* ═══════════════════════════════════════════════ SECTION SHELL ══ */
.sec{position:relative}
.sec--mast   .mast__track{height:190vh}
.sec--mani   .mani__track{height:240vh}
.sec--svc    .svc__track{height:520vh}
/* scroll length per cue, not per stack: shows.js writes --cues from the
   shows/ folder, so adding a show lengthens the track instead of making
   every cue fire faster */
.sec--work   .work__track{height:calc(100vh + var(--cues,7) * 77vh)}
.sec--about  .about__track{height:300vh}

.mast__pin,.mani__pin,.svc__pin,.work__pin,.about__pin{
  position:sticky;top:0;height:100vh;height:100svh;overflow:hidden;
}

/* ═══════════════════════════════════════════════ 01 · MASTHEAD ══ */
.mast__pin{display:flex;flex-direction:column;justify-content:center}

/* the slit: a hard aperture of light that widens as the prism separates */
.mast__slit{
  position:absolute;left:0;right:0;top:0;height:100%;
  background:linear-gradient(90deg,
    transparent 0%,
    rgb(var(--key-rgb) / .16) 30%,
    rgb(var(--ink-rgb) / .06) 50%,
    rgb(var(--fill-rgb) / .14) 70%,
    transparent 100%);
  /* This is the light the mark sits in, so it goes when the mark goes and
     it holds still while it is here — it used to keep opening against
     scroll long after there was nothing left in the frame to light. */
  transform:scaleX(.1) scaleY(.02);
  transform-origin:50% 50%;
  filter:blur(40px);
  opacity:calc(.35 * (1 - var(--split,0)));
}

/* Stills from the work, adrift behind the mark on landing — built by
   shows.js (see the note on [data-mast-scatter] in index.html) from the
   same photo records §04 uses, so nothing here is hand-picked or hand-
   positioned: each card's geometry is hashed from its own file path, the
   same way the §04 stage is, so the arrangement looks thrown but is
   identical on every visit. They stand down with the slit and the strap
   once the mark starts to separate — this is a landing, not a backdrop
   for reading, so it has no business competing with type further down. */
.mast__scatter{
  position:absolute;inset:0;z-index:0;overflow:hidden;pointer-events:none;
  opacity:calc(1 - var(--split,0));
}
.mast__photo{
  position:absolute;left:calc(var(--x) * 1%);top:calc(var(--y) * 1%);
  width:calc(var(--w) * 1%);aspect-ratio:var(--ar,4/3);
  margin:0;border-radius:10px;overflow:hidden;
  opacity:0;
  transform:translate(-50%,-50%) rotate(calc(var(--r) * 1deg));
  transition:opacity 1.6s var(--ease);
}
.mast__photo.is-on{opacity:.4}
.mast__photo i{
  display:block;width:100%;height:100%;
  animation:mastfloat calc(var(--fd) * 1s) var(--ease-io) calc(var(--fo) * -1s) infinite alternate;
}
.mast__photo img{
  width:100%;height:100%;object-fit:cover;object-position:50% 45%;
  filter:saturate(.55) brightness(.72);
}
@keyframes mastfloat{
  0%  {transform:translate3d(0,0,0)}
  100%{transform:translate3d(calc(var(--fx) * 1%),calc(var(--fy) * 1%),0)}
}

.prism{
  position:relative;
  z-index:1;   /* above the scatter — the mark still reads first */
  /* the box IS the mark's own box (--mark-ar); the canvas measures itself
     off it, so the optics are computed in the mark's own units */
  align-self:center;
  width:min(82vw,calc(28vh * var(--mark-ar)));
  aspect-ratio:var(--mark-ar);
  margin:0 var(--edge);
}
.prism__mark{
  position:absolute;inset:0;
  background-color:rgb(var(--corona));
  -webkit-mask:var(--mark) no-repeat 50% 50% / 100% 100%;
  mask:var(--mark) no-repeat 50% 50% / 100% 100%;
}
/* The pieces sit exactly on the mark box — they are the same wordmark, cut
   up — and they leave it when they part, so nothing here may clip them. The
   two bands take their colour from main.js, which holds them both on the ink
   until the split pulls them apart. */
.prism__pieces{position:absolute;inset:0;overflow:visible}
.prism__pieces svg{display:block;width:100%;height:100%;overflow:visible}
.prism__pieces [id^="mk-top"]   {color:var(--mk-top,rgb(var(--corona)))}
.prism__pieces [id^="mk-bottom"]{color:var(--mk-bot,rgb(var(--corona)))}
.prism.is-live .prism__mark{opacity:0}

.mast__strap{
  position:relative;   /* stays above the photo scatter, which is
                          absolutely positioned across the whole pin and
                          would otherwise paint over it in DOM order */
  display:flex;justify-content:center;flex-wrap:wrap;
  gap:clamp(8px,1.2vw,20px);align-items:center;
  margin:clamp(18px,3vh,40px) var(--edge) 0;
  font-family:var(--mono);font-size:clamp(9px,.78vw,12px);
  letter-spacing:.34em;color:rgb(var(--ink-rgb) / .55);
}
.mast__strap i{color:var(--key);font-style:normal}
.mast__strap span{
  display:inline-block;
  transform:translateY(calc(var(--p,0) * -14px));
  /* the strap stands down while the mark is in pieces — the lower band
     comes through where it sits, and two things in that space is one too many */
  opacity:calc((1 - var(--p,0) * .7) * (1 - var(--split,0) * .8));
}

/* ═══════════════════════════════════════════════ 02 · MANIFESTO ══ */
.mani__pin{display:grid;place-items:center;padding:calc(var(--deck-h) + 3vh) var(--edge) 8vh}

/* The beam and the text's own unmasking edge are driven by the same --b,
   but they used to measure it against different boxes — the cone against
   the full pin width, the type against .mani__stack's (capped at 1180px
   and centred once the viewport is wider than that). They only lined up
   by coincidence under 1180px, which is why it drifted on desktop. This
   wrapper gives the cone the exact same box as .mani__stack, on any
   viewport, so --b means the same physical position to both. */
.mani__beam{
  position:absolute;top:0;bottom:0;left:50%;
  width:min(1180px,100%);
  transform:translateX(-50%);
  container-type:inline-size;
  pointer-events:none;
}

/* Physical beam cone behind the type, tracked to the wipe. Built like a
   real fixture rather than a flat wedge: the source sits directly overhead
   and throws straight down, and it is two layers — a wide soft penumbra
   and a hot core inside it. Both fall off radially from the source, so the
   beam dims with distance the way light actually does instead of fading on
   a straight ramp. Sized in cqw off .mani__beam (not vw) so the throw
   scales with the text box it is lighting, not the raw viewport. Its own
   cut is dead vertical, which is what lets it line up with the type's
   unmasking edge below (also 90deg) rather than crossing it at an angle. */
.mani__cone{
  position:absolute;top:-32vh;left:calc(var(--b,0) * 1% - 14%);
  width:38cqw;height:156vh;
  opacity:calc(.62 + var(--vabs) * .38);
  mix-blend-mode:screen;
  pointer-events:none;
}
/* the penumbra — wide, soft-edged, carrying most of the haze */
.mani__cone::before{
  content:"";position:absolute;inset:0;
  background:radial-gradient(58% 96% at 50% 0%,
    rgb(var(--key-rgb) / .62) 0%,
    rgb(var(--key-rgb) / .30) 26%,
    rgb(var(--key-rgb) / .11) 54%,
    rgb(var(--key-rgb) / .03) 78%,
    transparent 100%);
  clip-path:polygon(43% 0%,57% 0%,100% 100%,0% 100%);
  filter:blur(26px);
}
/* the core — narrower and far less diffused, so the beam keeps an axis
   instead of reading as one even smear */
.mani__cone::after{
  content:"";position:absolute;inset:0;
  background:radial-gradient(30% 82% at 50% 0%,
    rgb(var(--fill-rgb) / .34) 0%,
    rgb(var(--key-rgb) / .40) 18%,
    rgb(var(--key-rgb) / .12) 52%,
    transparent 88%);
  clip-path:polygon(47% 0%,53% 0%,73% 100%,27% 100%);
  filter:blur(10px);
}

.tag--tl{position:absolute;top:calc(var(--deck-h) + 14px);left:var(--edge)}
.tag--tr{position:absolute;top:calc(var(--deck-h) + 14px);right:var(--edge)}

.mani__stack{position:relative;width:min(1180px,100%)}
.mani__type{
  font-family:var(--sans);font-weight:500;
  font-size:clamp(26px,4.55vw,74px);
  line-height:1.08;letter-spacing:-.022em;
  text-wrap:balance;
}
.mani__type--base{color:rgb(var(--ink-rgb) / .09)}
.mani__type--lit,.mani__type--edge{position:absolute;inset:0}
.mani__type--lit{
  color:var(--ink);
  /* 90deg: a dead-vertical edge, the same cut the beam above throws, so
     the light and the reveal line agree rather than crossing at an angle */
  -webkit-mask-image:linear-gradient(90deg,
    #000 calc(var(--b,0) * 1% - 4%),
    rgb(0 0 0 / .35) calc(var(--b,0) * 1% + 3%),
    transparent calc(var(--b,0) * 1% + 13%));
  mask-image:linear-gradient(90deg,
    #000 calc(var(--b,0) * 1% - 4%),
    rgb(0 0 0 / .35) calc(var(--b,0) * 1% + 3%),
    transparent calc(var(--b,0) * 1% + 13%));
}
/* the hot leading edge of the beam, in the key gel */
.mani__type--edge{
  color:var(--key);
  mix-blend-mode:screen;
  -webkit-mask-image:linear-gradient(90deg,
    transparent calc(var(--b,0) * 1% - 6%),
    #000 calc(var(--b,0) * 1% + 1%),
    transparent calc(var(--b,0) * 1% + 8%));
  mask-image:linear-gradient(90deg,
    transparent calc(var(--b,0) * 1% - 6%),
    #000 calc(var(--b,0) * 1% + 1%),
    transparent calc(var(--b,0) * 1% + 8%));
}

/* annotations that exist only inside the cursor's light */
.mani__gobo{
  position:absolute;inset:0;pointer-events:none;
  -webkit-mask-image:radial-gradient(circle 190px at var(--mx) var(--my),#000 0%,rgb(0 0 0 / .5) 55%,transparent 100%);
  mask-image:radial-gradient(circle 190px at var(--mx) var(--my),#000 0%,rgb(0 0 0 / .5) 55%,transparent 100%);
}
.mani__gobo span{
  position:absolute;left:var(--gx);top:var(--gy);
  font-family:var(--mono);font-size:10px;letter-spacing:.2em;
  color:rgb(var(--fill-rgb) / .95);white-space:nowrap;
  padding-left:14px;
}
.mani__gobo span::before{
  content:"";position:absolute;left:0;top:50%;width:9px;height:1px;
  background:rgb(var(--fill-rgb) / .7);
}

/* ═══════════════════════════════════════════════ 03 · SERVICES ══ */
.svc__pin{display:flex;flex-direction:column}
.svc__head{
  display:flex;justify-content:space-between;align-items:center;
  padding:calc(var(--deck-h) + 12px) var(--edge) 12px;
  border-bottom:var(--hair) solid var(--line-soft);
}
.svc__rail{
  flex:1;display:flex;align-items:stretch;
  transform:translate3d(calc(var(--x,0) * -1px),0,0);
  will-change:transform;
}
.svc__panel{
  position:relative;flex:0 0 auto;
  width:min(78vw,880px);
  padding:clamp(22px,3.4vw,58px) clamp(20px,3vw,52px);
  border-right:var(--hair) solid var(--line-soft);
  display:flex;flex-direction:column;justify-content:center;
  overflow:hidden;
}
.svc__panel--intro{width:min(64vw,660px);justify-content:center;gap:2em}
.svc__introtype{
  font-family:var(--heavy);font-weight:900;
  font-size:clamp(42px,6.6vw,104px);line-height:.9;letter-spacing:-.035em;
  color:var(--ink);
}
.svc__introcopy{
  max-width:34ch;font-size:clamp(14px,1.15vw,19px);line-height:1.42;
  color:rgb(var(--ink-rgb) / .62);font-weight:400;
}
.svc__scrollcue{
  font-family:var(--mono);font-size:10px;letter-spacing:.28em;
  color:var(--key);
  animation:nudge 2.6s var(--ease-io) infinite;
}
@keyframes nudge{0%,100%{transform:translateX(0)}50%{transform:translateX(10px)}}

.svc__ch{
  position:absolute;top:clamp(16px,2.4vw,40px);right:clamp(20px,3vw,52px);
  font-family:var(--mono);font-weight:700;
  font-size:clamp(40px,5.6vw,92px);letter-spacing:-.02em;
  color:transparent;
  -webkit-text-stroke:1px rgb(var(--ink-rgb) / .22);
  line-height:1;pointer-events:none;
  /* counter-drift : the number moves against the rail = diagonal travel */
  transform:translate3d(0,calc(var(--drift,0) * 42px),0);
}
.svc__body{position:relative;z-index:2;display:flex;flex-direction:column;gap:clamp(14px,1.6vw,26px);max-width:min(46ch,88%)}
.svc__title{
  font-family:var(--heavy);font-weight:900;
  font-size:clamp(34px,5vw,80px);line-height:.9;letter-spacing:-.035em;
  color:var(--ink);
  transform:translate3d(0,calc(var(--drift,0) * -30px),0);
}
.svc__copy{
  font-size:clamp(13.5px,1.05vw,17.5px);line-height:1.46;
  color:rgb(var(--ink-rgb) / .6);max-width:42ch;
  transform:translate3d(0,calc(var(--drift,0) * -12px),0);
}
.svc__panel .spec{
  transform:translate3d(0,calc(var(--drift,0) * 22px),0);
  max-width:38ch;
}
/* procedural fixture bank inside each panel */
.svc__rig{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  opacity:calc(.18 + var(--near,0) * .55);
  transition:opacity .5s linear;
  background-image:var(--rig-bg,none);
  transform:translate3d(calc(var(--drift,0) * 60px),0,0);
}
.svc__meter{
  height:2px;background:rgb(var(--ink-rgb) / .1);
  margin:0 var(--edge) 16px;
}
.svc__meter i{display:block;height:100%;width:0;background:var(--key)}

/* ═══════════════════════════════════════════════ 04 · WORK / CUE STACK ══ */
.work__pin{display:flex;flex-direction:column}
.console{flex:1;display:flex;flex-direction:column;min-height:0}
.console__bar{
  display:grid;
  grid-template-columns:1fr auto;
  align-items:baseline;gap:clamp(12px,2vw,32px);
  padding:calc(var(--deck-h) + 12px) var(--edge) 12px;
  border-bottom:var(--hair) solid var(--line);
}
.console__state{
  font-family:var(--mono);font-size:clamp(9px,.74vw,11px);
  letter-spacing:.18em;color:rgb(var(--ink-rgb) / .5);
  font-feature-settings:"tnum" 1;
}
.console__state{color:var(--fill)}

.console__body{
  flex:1;display:grid;
  grid-template-columns:1fr minmax(280px,38%);
  min-height:0;
}

/* ── cue list ── */
.cues{
  display:flex;flex-direction:column;justify-content:center;
  border-right:var(--hair) solid var(--line-soft);
  min-height:0;overflow:hidden;
}
.cue{
  position:relative;
  border-bottom:var(--hair) solid var(--line-soft);
  --i:0;                     /* intensity 0–1, driven by JS */
}
.cue::before{
  /* the fill wipe : a cue coming up to level */
  content:"";position:absolute;inset:0;z-index:0;
  background:linear-gradient(90deg,
    rgb(var(--cue-rgb,var(--key-rgb)) / .30) 0%,
    rgb(var(--cue-rgb,var(--key-rgb)) / .06) 60%,
    transparent 100%);
  transform:scaleX(var(--i));transform-origin:0 50%;
  transition:transform .12s linear;
}
.cue::after{
  content:"";position:absolute;left:0;top:0;bottom:0;width:2px;z-index:1;
  background:rgb(var(--cue-rgb,var(--key-rgb)));
  transform:scaleY(var(--i));transform-origin:50% 100%;
}
.cue__hit{
  position:relative;z-index:2;width:100%;text-align:left;
  display:grid;
  grid-template-columns:minmax(0,1.45fr) minmax(0,.88fr) 3.4em 10.6em 5.4em;
  align-items:center;gap:clamp(6px,1vw,18px);
  padding:clamp(9px,1.35vh,17px) var(--edge);
  font-family:var(--mono);font-size:clamp(9px,.72vw,11.5px);
  letter-spacing:.13em;color:rgb(var(--ink-rgb) / .4);
  transition:color .3s linear;
  font-feature-settings:"tnum" 1;
}
.cue.is-live .cue__hit,.cue.is-hi .cue__hit{color:rgb(var(--ink-rgb) / .9)}
.cue.is-done .cue__hit{color:rgb(var(--ink-rgb) / .26)}
.cue__name{
  font-family:var(--sans);font-weight:700;
  font-size:clamp(14px,1.5vw,25px);letter-spacing:-.012em;
  color:currentColor;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  transition:transform .55s var(--ease);
}
.cue.is-live .cue__name{transform:translateX(clamp(4px,.7vw,12px))}
.cue__client{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cue__year,.cue__dept{color:rgb(var(--ink-rgb) / .34)}
.cue__dept{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cue__int{position:relative;display:flex;align-items:center;gap:6px}
.cue__int i{
  flex:1;height:2px;background:rgb(var(--ink-rgb) / .14);position:relative;
}
.cue__int i::after{
  content:"";position:absolute;inset:0;background:rgb(var(--cue-rgb,var(--key-rgb)));
  transform:scaleX(var(--i));transform-origin:0 50%;
}

/* geometry change, not a fade : the row physically opens */
.cue__detail{
  position:relative;z-index:2;
  display:grid;grid-template-rows:0fr;
  transition:grid-template-rows .7s var(--ease);
}
.cue.is-open .cue__detail{grid-template-rows:1fr}
.cue__detailinner{
  overflow:hidden;
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:clamp(14px,2vw,40px);
  padding:0 var(--edge);
}
.cue.is-open .cue__detailinner{padding-bottom:clamp(12px,1.6vh,22px)}
.cue__detailinner p{
  font-size:clamp(12.5px,.95vw,15.5px);line-height:1.45;
  color:rgb(var(--ink-rgb) / .58);max-width:44ch;
}
.cue__copy{min-width:0}
.cue__copy p + p{margin-top:.6em}

/* ── stage: the firing cue's stills, floating ──
   No rig, no gel wash, nothing composited over the photographs — they
   are the work, so they are left alone. main.js writes each card's
   geometry (--x/--y/--r/--sc/--ar) once at build time from a hash of
   its own path, so the scatter is random-looking but stable, and then
   only moves cards between states as the playhead travels. */
.stage{
  position:relative;overflow:hidden;
  background:#040309;
}
.stage__scatter{position:absolute;inset:0;z-index:0}
.stage__card{
  position:absolute;left:calc(var(--x) * 1%);top:calc(var(--y) * 1%);
  width:calc(var(--w) * 1%);aspect-ratio:var(--ar,4/3);
  margin:0;
  border-radius:10px;   /* Radius Medium, p.35 — the one exception to Radius
                           None: a card floating free of any frame reads as
                           a print in a hand, not a print on a page */
  overflow:hidden;
  box-shadow:0 22px 54px rgb(0 0 0 / .6),0 2px 10px rgb(0 0 0 / .45);
  opacity:0;pointer-events:none;
  transform:translate(-50%,-50%) rotate(calc(var(--r) * 1deg)) scale(.82);
  transition:
    opacity .8s var(--ease),
    transform 1.1s var(--ease),
    filter .8s var(--ease);
}
/* only the cards actually on screen are worth compositing or drifting —
   a long stack builds a lot of these */
.stage__card.is-live,.stage__card.is-near{will-change:transform,opacity}
.stage__card:not(.is-live):not(.is-near) .stage__cardin{animation-play-state:paused}
.stage__card img{
  width:100%;height:100%;object-fit:cover;object-position:50% 45%;
  border-radius:inherit;
}
/* neighbouring cues hang back, out of focus, so the stack reads as a
   shoot you are moving through rather than a slideshow */
.stage__card.is-near{
  opacity:.26;z-index:1;
  filter:blur(2.5px) saturate(.75);
  transform:
    translate(-50%,-50%)
    translate(calc(var(--dx) * 1%),calc(var(--dy) * 1%))
    rotate(calc(var(--r) * 1.6deg)) scale(.72);
}
.stage__card.is-live{
  opacity:1;z-index:2;
  filter:none;
  transform:translate(-50%,-50%) rotate(calc(var(--r) * 1deg)) scale(1);
}
/* the still the contact strip has selected sits proud of the rest */
.stage__card.is-lead{
  z-index:3;
  transform:translate(-50%,-50%) rotate(calc(var(--r) * .4deg)) scale(1.1);
  box-shadow:0 30px 70px rgb(0 0 0 / .66),0 3px 14px rgb(0 0 0 / .5);
}

/* ── hover : the card is picked up ──
   Straightens against its own angle, lifts, and takes the show's gel as
   a rim light, so pointing at a photograph reads as putting a hand on
   it. Only live cards respond — the ones behind stay where they are. */
.stage__card.is-live{pointer-events:auto}
.stage__card--video.is-live{cursor:pointer}
.stage__card.is-live:hover,
.stage__card.is-live:focus-within{
  z-index:6;
  transform:
    translate(-50%,-50%)
    translateY(-1.6%)
    rotate(calc(var(--r) * .18deg))
    scale(1.13);
  box-shadow:
    0 40px 90px rgb(0 0 0 / .7),
    0 0 0 1px rgb(var(--cue-rgb) / .55),
    0 0 34px rgb(var(--cue-rgb) / .32);
  transition:
    opacity .3s var(--ease),
    transform .5s var(--ease),
    box-shadow .5s var(--ease),
    filter .3s var(--ease);
}
.stage__card.is-lead:hover,.stage__card.is-lead:focus-within{
  transform:translate(-50%,-50%) translateY(-1.6%) rotate(0deg) scale(1.2);
}
.stage__card.is-live:hover .stage__cardin,
.stage__card.is-live:focus-within .stage__cardin{animation-play-state:paused}
.stage__card img{transition:transform 1.2s var(--ease),filter .5s var(--ease)}
.stage__card.is-live:hover img,
.stage__card.is-live:focus-within img{transform:scale(1.06);filter:saturate(1.1) contrast(1.03)}
/* the rest of the scatter steps back so the one under the pointer wins */
.stage__scatter:hover .stage__card.is-live:not(:hover){opacity:.5;filter:saturate(.8)}

/* ── the preview tile ──
   Not a poster with a triangle on it: the preview itself, running
   silently on a loop while its cue is live. It reads as a screen among
   prints — a gel-lit edge, a running tally in the corner — and clicking
   it is a hand-off to the player with the sound up, not a load. */
.stage__card--video{
  box-shadow:
    0 22px 54px rgb(0 0 0 / .6),
    0 0 0 1px rgb(var(--cue-rgb) / .3);
}
.stage__card--video.is-live{
  box-shadow:
    0 26px 60px rgb(0 0 0 / .62),
    0 0 0 1px rgb(var(--cue-rgb) / .55),
    0 0 30px rgb(var(--cue-rgb) / .18);
}
.stage__vid{
  width:100%;height:100%;
  /* the tile is cut to the video's own shape, so contain fills it
     exactly — and letterboxes rather than crops in the one case the
     shape could not be read from the file (webm, ogv) */
  object-fit:contain;
  display:block;background:#040309;
  border-radius:inherit;
}
/* the corner tally: a live dot and the word, the way the deck reports */
.stage__vtag{
  position:absolute;top:0;left:0;z-index:5;
  display:flex;align-items:center;gap:.6em;
  padding:.7em .9em;
  font-family:var(--mono);font-size:9px;letter-spacing:.26em;
  color:rgb(var(--ink-rgb) / .62);
  text-shadow:0 1px 6px rgb(0 0 0 / .9);
  pointer-events:none;
}
.stage__vtag::before{
  content:"";width:5px;height:5px;
  background:rgb(var(--ink-rgb) / .35);
  transition:background .3s linear,box-shadow .3s linear;
}
.stage__card--video.is-rolling .stage__vtag::before{
  background:rgb(var(--cue-rgb));
  box-shadow:0 0 8px rgb(var(--cue-rgb));
  animation:vtally 2s var(--ease-io) infinite;
}
@keyframes vtally{50%{opacity:.3}}

/* the sound affordance sits out of the way until pointed at — the tile
   is already moving, so it does not need a mark to say it is a video */
.stage__play{
  position:absolute;inset:0;z-index:4;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:.85em;
  background:transparent;
  opacity:0;
  transition:opacity .4s var(--ease),background .4s var(--ease);
}
.stage__card--video.is-live .stage__play{opacity:.5}
.stage__card--video.is-live:hover .stage__play,
.stage__play:focus-visible{opacity:1;background:rgb(4 3 9 / .5)}
/* until it rolls, the mark is the whole message */
.stage__card--video:not(.is-rolling) .stage__play{opacity:1}
.stage__playmark{
  width:clamp(30px,4.4vw,52px);aspect-ratio:1;
  border:var(--hair) solid rgb(var(--ink-rgb) / .8);
  border-radius:50%;
  background:rgb(4 3 9 / .5);
  display:block;position:relative;
  transition:transform .45s var(--ease),background .45s var(--ease),border-color .45s var(--ease);
}
/* the triangle, drawn rather than typed, so it sits on the optical centre */
.stage__playmark::after{
  content:"";position:absolute;top:50%;left:54%;
  transform:translate(-50%,-50%);
  border-left:clamp(9px,1.3vw,15px) solid rgb(var(--ink-rgb) / .92);
  border-top:clamp(6px,.86vw,10px) solid transparent;
  border-bottom:clamp(6px,.86vw,10px) solid transparent;
}
.stage__card--video.is-live:hover .stage__playmark,
.stage__play:focus-visible .stage__playmark{
  transform:scale(1.12);
  background:rgb(var(--cue-rgb) / .9);
  border-color:rgb(var(--cue-rgb));
}
.stage__playlabel{
  font-family:var(--mono);font-size:9px;letter-spacing:.28em;
  color:rgb(var(--ink-rgb) / .86);
  text-shadow:0 1px 6px rgb(0 0 0 / .9);
  opacity:0;transition:opacity .35s var(--ease);
}
.stage__card--video.is-live:hover .stage__playlabel,
.stage__play:focus-visible .stage__playlabel{opacity:1}
/* a preview whose file will not load says so instead of sitting blank */
.stage__card--video.is-dead .stage__vtag{color:var(--terra)}
/* the float itself, on an inner layer so it never fights the state
   transition above it */
.stage__cardin{
  display:block;width:100%;height:100%;
  animation:cardfloat calc(var(--fd) * 1s) var(--ease-io) calc(var(--fo) * -1s) infinite alternate;
}
@keyframes cardfloat{
  0%  {transform:translate3d(0,0,0) rotate(0deg)}
  100%{transform:translate3d(calc(var(--fx) * 1%),calc(var(--fy) * 1%),0) rotate(calc(var(--fr) * 1deg))}
}

/* inline still inside an open cue, for viewports with no stage column */
.cue__shot{display:none;margin:0;border-radius:10px;overflow:hidden}
.cue__shot img{
  width:100%;height:clamp(150px,26vh,260px);object-fit:cover;
  object-position:50% 45%;
  opacity:0;transition:opacity .6s var(--ease);
}
.cue__shot img.is-on{opacity:1}

/* the in-row preview control: only where there is no scatter to click */
.cue__play{
  display:none;grid-column:1/-1;
  align-items:center;gap:.8em;
  margin-top:clamp(8px,1.2vh,14px);
  padding:.7em 1em;
  justify-self:start;
  font-family:var(--mono);font-size:10px;letter-spacing:.24em;
  color:rgb(var(--ink-rgb) / .8);
  border:var(--hair) solid rgb(var(--cue-rgb,var(--key-rgb)) / .5);
  background:rgb(var(--cue-rgb,var(--key-rgb)) / .12);
  border-radius:2px;   /* ghost button — Radius Small, p.35 */
  transition:background .3s linear,color .3s linear;
}
.cue__play:hover,.cue__play:focus-visible{
  background:rgb(var(--cue-rgb,var(--key-rgb)) / .3);color:var(--cream);
}
.cue__play i{
  width:0;height:0;display:block;
  border-left:9px solid rgb(var(--cue-rgb,var(--key-rgb)));
  border-top:6px solid transparent;border-bottom:6px solid transparent;
}

/* contact strip : a show folder holding more than one still gets the
   rest of the shoot here, selectable without leaving the cue. Only
   rendered when there is more than one. */
.cue__thumbs{
  grid-column:1/-1;
  display:flex;flex-wrap:wrap;gap:6px;
  margin-top:clamp(8px,1.1vh,14px);
}
.cue__thumb{
  width:clamp(44px,4vw,60px);aspect-ratio:3/2;padding:0;
  border:var(--hair) solid rgb(var(--ink-rgb) / .16);
  border-radius:4px;   /* Radius Small, p.35 */
  background:#040309;overflow:hidden;
  opacity:.4;
  transition:opacity .35s var(--ease),border-color .35s var(--ease);
}
.cue__thumb img{width:100%;height:100%;object-fit:cover;object-position:50% 45%}
.cue__thumb:hover,.cue__thumb:focus-visible{opacity:.82}
.cue__thumb.is-on{opacity:1;border-color:rgb(var(--cue-rgb,var(--key-rgb)))}

/* stack with nothing patched into it — no shows/ folder, or the index
   never arrived. Says which, in the console's own register. */
.cues__empty{
  padding:clamp(9px,1.35vh,17px) var(--edge);
  font-family:var(--mono);font-size:10px;letter-spacing:.16em;
  color:rgb(var(--ink-rgb) / .3);
}
.stage__hud{
  position:absolute;left:0;right:0;bottom:0;z-index:5;
  display:flex;justify-content:space-between;gap:1em;
  padding:12px var(--gut);
  border-top:var(--hair) solid rgb(var(--ink-rgb) / .12);
  font-family:var(--mono);font-size:9.5px;letter-spacing:.18em;
  color:rgb(var(--ink-rgb) / .6);
  font-feature-settings:"tnum" 1;
}
.stage__hud span:last-child{color:rgb(var(--cue-rgb));text-align:right}

/* ═══════════════════════════════════════════════ 05 · SET PIECE ══ */

/* ═══════════════════════════════════════════════ 06 · ABOUT ══ */
.about__pin{display:flex;flex-direction:column;padding:0}
.about__rules{
  position:absolute;inset:0;display:grid;grid-template-columns:repeat(12,1fr);
  padding:0 var(--edge);pointer-events:none;
}
.about__rules i{border-left:var(--hair) solid rgb(var(--ink-rgb) / .05)}
.about__rules i:last-child{border-right:var(--hair) solid rgb(var(--ink-rgb) / .05)}
.about__head{
  display:flex;justify-content:space-between;align-items:baseline;
  padding:calc(var(--deck-h) + 14px) var(--edge) 14px;
  border-bottom:var(--hair) solid var(--line-soft);
}
.about__grid{
  position:relative;flex:1;min-height:0;
  display:grid;
  /* tracks are lerped live by main.js — the layout geometry itself
     reconfigures on scroll */
  grid-template-columns:var(--c1,4fr) var(--c2,4fr) var(--c3,4fr);
  align-items:start;
}
.about__col{
  padding:clamp(20px,3vh,44px) clamp(16px,2vw,40px);
  border-left:var(--hair) solid var(--line-soft);
  min-width:0;height:100%;
  display:flex;flex-direction:column;gap:1.1em;
  overflow:hidden;
  /* type is sized against the column, not the viewport — so when the
     grid re-proportions, the setting re-proportions with it instead of
     overflowing */
  container-type:inline-size;
  /* the column taking the width is the one under the reading light;
     the other two stand back rather than just quietly changing size */
  opacity:var(--e,1);
  transition:opacity .6s var(--ease);
}
.about__col--a{border-left:0;position:relative;justify-content:center;--e:var(--e1,1)}
.about__lead{
  font-family:var(--heavy);font-weight:900;
  font-size:clamp(22px,15cqw,64px);line-height:.92;letter-spacing:-.035em;
  color:var(--ink);
}
.about__body{
  font-size:clamp(11.5px,4.6cqw,17px);line-height:1.5;
  color:rgb(var(--ink-rgb) / .66);max-width:52ch;
}
.about__body--dim{color:rgb(var(--ink-rgb) / .36)}
.about__col--b{justify-content:center;--e:var(--e2,1)}
.about__col--c{justify-content:center;--e:var(--e3,1)}

.tenets{display:flex;flex-direction:column}
.tenets li{
  display:grid;grid-template-columns:2.9em 1fr;gap:.7em;
  padding:.86em 0;border-top:var(--hair) solid var(--line-soft);
  opacity:.32;transform:translateY(10px);
  transition:opacity .6s var(--ease),transform .6s var(--ease);
}
.tenets li.is-on{opacity:1;transform:none}
/* three children, two tracks — pin them explicitly or the paragraph
   auto-places into the cue-number gutter */
.tenets span{
  grid-column:1;grid-row:1 / span 2;
  font-family:var(--mono);font-size:10px;letter-spacing:.14em;
  color:var(--key);font-feature-settings:"tnum" 1;
}
.tenets b,.tenets p{grid-column:2}
.tenets b{
  font-family:var(--mono);font-weight:700;font-size:clamp(9px,3.4cqw,12px);
  letter-spacing:.12em;color:var(--ink);display:block;margin-bottom:.4em;
}
.tenets p{font-size:clamp(10.5px,4.1cqw,14.5px);line-height:1.4;color:rgb(var(--ink-rgb) / .48)}

/* ═══════════════════════════════════════════════ 07 · CONTACT ══ */
/* The violet pole finally beats the terracotta. Hard-coded on purpose. */
.sec--contact{
  background:var(--violet);
  color:var(--cream);
  --ink-rgb:255 234 204;
  --line:rgb(255 234 204 / .28);
  --line-soft:rgb(255 234 204 / .16);
  padding:clamp(60px,11vh,140px) 0 clamp(40px,7vh,90px);
}
.contact__inner{padding:0 var(--edge)}
.contact__head{display:flex;justify-content:space-between;gap:1em;border-bottom:1px solid var(--line);padding-bottom:12px}
.sec--contact .tag{color:rgb(255 234 204 / .62)}
.contact__lead{
  font-family:var(--heavy);font-weight:900;
  font-size:clamp(48px,12.4vw,196px);line-height:.84;letter-spacing:-.045em;
  margin:clamp(24px,5vh,64px) 0 clamp(28px,6vh,72px);
  color:var(--cream);
}
.contact__cols{
  display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr);
  gap:clamp(24px,4vw,80px);
  border-top:1px solid var(--line);padding-top:clamp(22px,3.4vh,44px);
}

.patchsheet{display:grid;grid-template-columns:1fr 1fr;gap:0 clamp(16px,2vw,32px)}
.field{grid-column:1/-1;display:flex;flex-direction:column;gap:6px;padding:.8em 0;border-bottom:1px solid var(--line-soft)}
.field--half{grid-column:span 1}
.field label{
  font-family:var(--mono);font-size:9.5px;letter-spacing:.2em;
  color:rgb(255 234 204 / .55);
}
.field input,.field select,.field textarea{
  font-family:var(--sans);font-weight:500;
  font-size:clamp(15px,1.35vw,22px);letter-spacing:-.01em;
  color:var(--cream);padding:2px 0;width:100%;resize:none;
}
.field textarea{font-size:clamp(13px,1vw,16px);line-height:1.4;font-family:var(--mono);letter-spacing:.06em}
.field select{
  /* square indicator — no native chrome, no rounding */
  background:linear-gradient(var(--cream),var(--cream)) no-repeat right .35em center / 9px 9px;
  padding-right:22px;cursor:pointer;
}
.field input::placeholder,.field textarea::placeholder{color:rgb(255 234 204 / .3)}
.field select option{background:var(--violet);color:var(--cream)}
.field:focus-within{border-bottom-color:var(--cream)}

.send{
  grid-column:1/-1;margin-top:clamp(16px,2.4vh,30px);
  display:flex;justify-content:space-between;align-items:center;
  padding:clamp(14px,1.9vh,22px) clamp(16px,2vw,26px);
  background:var(--cream);color:var(--violet);
  font-family:var(--mono);font-weight:700;font-size:12px;letter-spacing:.24em;
  position:relative;overflow:hidden;
  border-radius:4px;   /* primary button — Radius Medium, p.35 */
}
.send::before{
  content:"";position:absolute;inset:0;background:var(--terra);
  transform:scaleX(0);transform-origin:0 50%;
  transition:transform .5s var(--ease);
}
.send:hover::before,.send:focus-visible::before{transform:scaleX(1)}
/* while the cue is on its way to the server — the form stays readable,
   it just stops taking a second press */
.send:disabled{cursor:progress}
.patchsheet.is-sending{opacity:.58;pointer-events:none}
.send span{position:relative;z-index:1;transition:color .35s linear}
.send:hover span,.send:focus-visible span{color:var(--cream)}
.send__go{opacity:.55}
.patchsheet__note{
  grid-column:1/-1;margin-top:10px;min-height:1.4em;
  font-family:var(--mono);font-size:10px;letter-spacing:.18em;
  color:rgb(255 234 204 / .8);
}

.contact__meta{display:grid;grid-template-columns:1fr 1fr;gap:clamp(18px,2.4vw,36px) clamp(16px,2vw,28px);align-content:start}
.metablock{display:flex;flex-direction:column;gap:5px}
.metablock .lbl{color:rgb(255 234 204 / .5);margin-bottom:4px}
.metablock a,.metablock p{
  font-family:var(--mono);font-size:clamp(11px,.9vw,13px);
  letter-spacing:.08em;line-height:1.55;color:var(--cream);
}
.metablock a{position:relative;width:fit-content}
.metablock a::after{
  content:"";position:absolute;left:0;bottom:-2px;width:100%;height:1px;
  background:currentColor;transform:scaleX(0);transform-origin:100% 50%;
  transition:transform .4s var(--ease);
}
.metablock a:hover::after{transform:scaleX(1);transform-origin:0 50%}
.metablock .mono-dim{color:rgb(255 234 204 / .5)}

/* ═══════════════════════════════════════════════ HOUSE / FOOTER ══ */
.house{background:var(--black);color:var(--cream);padding:clamp(28px,5vh,60px) 0}
.house__inner{padding:0 var(--edge)}
.house__top{
  display:flex;justify-content:space-between;align-items:center;
  border-top:1px solid rgb(255 234 204 / .18);
  border-bottom:1px solid rgb(255 234 204 / .18);
  padding:clamp(18px,3vh,34px) 0;
  font-family:var(--heavy);font-weight:900;
  font-size:clamp(24px,4.4vw,68px);letter-spacing:-.03em;
  transition:color .4s linear,letter-spacing .5s var(--ease);
}
.house__top:hover{color:var(--violet);letter-spacing:-.01em}
.house__arrow{font-size:.4em;opacity:.5}
.house__cols{
  display:grid;grid-template-columns:repeat(3,1fr);gap:1em;
  padding-top:18px;
  font-family:var(--mono);font-size:9.5px;letter-spacing:.18em;
  color:rgb(255 234 204 / .4);
}
.house__cols span:last-child{text-align:right}

/* ═══════════════════════════════════════════════ RESPONSIVE ══ */
/* Ordered widest-first. They overlap on purpose, so a narrower block must
   come after every block it needs to beat — 600 used to sit above 760 and
   was being overridden by it. */

@media (max-width:1100px){
  .console__body{grid-template-columns:1fr}
  .stage{display:none}
  .cue__play{display:inline-flex}
  /* no stage column here, so the still moves inside the open cue */
  .cue__shot{display:block;grid-column:1/-1;margin-bottom:.9em}
  .cue__hit{grid-template-columns:minmax(0,1.6fr) minmax(0,1fr) 3.2em 5em}
  .cue__dept{display:none}
  .cue__int{grid-column:4}
}

@media (max-width:960px){
  /* the patch bay tightens up rather than collapsing — the labels are
     the only thing naming a section now, so they have to stay legible */
  .deck{grid-template-columns:auto 1fr auto;gap:10px}
  .patch{gap:clamp(9px,2.6vw,16px);justify-self:end}
  .patch a{padding:10px 0;font-size:9px;letter-spacing:.12em}

  .contact__cols{grid-template-columns:1fr}
  .house__cols{grid-template-columns:1fr;gap:.6em 1em}
  .house__cols span:last-child{text-align:left}
}

@media (max-width:760px){
  :root{--deck-h:52px}
  .prism{width:min(90vw,calc(20vh * var(--mark-ar)))}
  /* Shorter than desktop on purpose, not just reflowed at the same length:
     both effects finish inside the first chunk of their track (the split
     in ~.58 viewport-heights of scroll, the wipe well under one screen),
     so the desktop's length is mostly a held pin with nothing new
     happening — fine with a mouse wheel, a lot of empty thumb-scrolling on
     a phone. These are cut down to roughly what each effect needs. */
  .sec--mast .mast__track{height:130vh}
  .sec--mani .mani__track{height:150vh}
  .sec--about .about__track{height:auto}

  .mast__strap{letter-spacing:.2em;font-size:9px}

  /* the manifesto is one pinned screen of type — it has to fit the
     screen it is pinned to, so it is sized off the viewport here */
  .mani__pin{padding:calc(var(--deck-h) + 2vh) var(--edge) 5vh}
  .mani__type{font-size:clamp(19px,5.6vw,34px);line-height:1.14}

  /* services drop the horizontal rail for a vertical stack */
  .sec--svc .svc__track{height:auto}
  .svc__pin{position:static;height:auto;overflow:visible}
  .svc__rail{flex-direction:column;transform:none!important}
  /* Sized to their own content, not stretched to fill a screen each: six
     near-full-height panels stacked was the desktop rail poured into a
     column rather than actually redrawn for a thumb scrolling a phone. */
  .svc__panel{width:100%;border-right:0;border-bottom:var(--hair) solid var(--line-soft);min-height:auto}
  .svc__panel--intro{width:100%;min-height:auto}
  /* the rail is a vertical stack here, so there is nothing left to drag */
  .svc__scrollcue{display:none}
  .svc__ch,.svc__title,.svc__copy,.svc__panel .spec,.svc__rig{transform:none!important}
  .svc__meter{display:none}
  /* the ghost channel number sits over the title once the panel narrows,
     so it goes back to being a label above it rather than an overlay */
  .svc__ch{position:static;font-size:clamp(28px,9vw,44px);margin-bottom:.15em}
  .svc__body{max-width:100%}

  /* about stacks and stops reconfiguring */
  .about__pin{position:static;height:auto;overflow:visible}
  .about__grid{grid-template-columns:1fr!important;display:block}
  .about__col{border-left:0;border-top:var(--hair) solid var(--line-soft);height:auto}
  .about__rules{display:none}

  /* A phone screen doesn't hold a pinned console AND an open cue's still
     and copy at once — scrolling the cue list inside a pinned viewport
     meant two scroll containers fighting the same gesture, and an opened
     cue's content could land outside the clipped pin with no way to
     reach it. Unpin instead, the same way services and about already do
     here: the stack becomes a normal flowing list, every cue sits open,
     and the scroll-linked arm/fire choreography (main.js) stands down
     for the same reason it already does under reduced motion. */
  .sec--work .work__track{height:auto}
  .work__pin{position:static;height:auto;overflow:visible}
  .cue__detail{grid-template-rows:1fr}
  .cues{justify-content:flex-start;overflow:visible;border-right:0}
  /* the arm/fire level is a scroll-linked playhead that no longer runs
     here (main.js) — every cue reads at full level instead of arriving
     dim and never lighting up */
  .cue{--i:1}
  .cue__hit{
    color:rgb(var(--ink-rgb) / .9);
    grid-template-columns:minmax(0,1fr) 4.8em;
    grid-template-areas:"name int" "client int";
    gap:3px 10px;
    padding:9px var(--edge);
  }
  .cue__shot img{height:clamp(96px,15vh,150px)}
  .cue__detailinner p{font-size:12.5px;line-height:1.38}
  /* every cue is open here — see the note above — so the padding that
     used to arrive only with .is-open applies unconditionally */
  .cue__detailinner{padding-bottom:10px}
  .spec--tight > div{padding:.3em 0}
  .cue__name{grid-area:name;font-size:15px}
  .cue__client{grid-area:client;font-size:9px}
  .cue__int{grid-area:int}
  .cue__year{display:none}
  .cue__detailinner{grid-template-columns:1fr}
  .console__bar{grid-template-columns:1fr auto;gap:4px 12px}
  .console__state{display:none}

  .patchsheet{grid-template-columns:1fr}
  .field--half{grid-column:1/-1}
  .contact__meta{grid-template-columns:1fr}
  /* iOS zooms the page in on any field it thinks is under 16px, and never
     zooms back out — so the controls hold 16px here whatever the scale */
  .field input,.field select,.field textarea{font-size:16px}
  .field textarea{font-size:16px;line-height:1.45}
  .send{font-size:11px;letter-spacing:.18em;gap:1em}
}

@media (max-width:600px){
  .deck__meta{display:none}
  .deck{grid-template-columns:auto 1fr;gap:8px}
  /* five labels stop fitting a phone in one line long before they stop
     being readable, so the bay scrolls instead of wrapping or shrinking */
  .patch{
    justify-self:end;gap:14px;
    max-width:100%;overflow-x:auto;
    scrollbar-width:none;-webkit-overflow-scrolling:touch;
  }
  .patch::-webkit-scrollbar{display:none}
  .patch a{flex:0 0 auto;font-size:9px;letter-spacing:.1em}

  .contact__lead{font-size:clamp(40px,13vw,72px)}
  .house__top{font-size:clamp(21px,7vw,34px)}
  .house__cols{font-size:9px;letter-spacing:.14em}
  .stage__hud{font-size:8.5px;letter-spacing:.12em;padding:9px var(--gut)}
}

/* Phones in landscape have the width but almost none of the height, and
   every pinned section is sized in svh — so the type has to come down or
   it runs straight out of the bottom of its own pin. */
@media (max-height:520px) and (orientation:landscape){
  :root{--deck-h:44px}
  .mani__type{font-size:clamp(16px,2.9vw,26px);line-height:1.16}
  .prism{width:min(62vw,calc(34svh * var(--mark-ar)))}
  .mast__strap{margin-top:10px}
  .svc__panel{min-height:auto;padding-block:clamp(18px,7svh,40px)}
  .svc__introtype{font-size:clamp(30px,5.4vw,56px)}
  .sec--contact{padding:clamp(34px,8vh,70px) 0}
}

/* ═══════════════════════════════════════════ TOUCH / COARSE POINTER ══ */
/* Nothing here is hover-dependent by the time it reaches a phone: the
   pointer effects are already off, so what is left is making the things
   you actually press big enough to press. */
@media (hover:none),(pointer:coarse){
  /* the annotations live inside the cursor's light, and there is no
     cursor — without this they sit in the top-left corner, half lit */
  .mani__gobo{display:none}

  .patch a{padding:12px 2px;min-height:44px;display:flex;align-items:center}
  .cue__hit{min-height:46px}
  .cue__play{padding:.9em 1.15em;min-height:44px}
  .cue__thumb{width:clamp(54px,13vw,72px)}
  .stage__play{min-height:44px}
  .send{min-height:52px}
  .metablock a{padding:3px 0;display:inline-block}
  .house__top{padding-block:clamp(20px,3.4vh,34px)}
  /* the grey flash the browser paints on tap is the one bit of chrome
     this page has no say over otherwise */
  a,button,summary,label{-webkit-tap-highlight-color:rgb(83 50 253 / .18)}
}

/* Notched and rounded screens: the fixed deck and anything that runs to
   the edge keep clear of the cutout and the home indicator. */
@supports (padding:max(0px)){
  @media (max-width:760px){
    .deck{
      padding-left:max(var(--edge),env(safe-area-inset-left));
      padding-right:max(var(--edge),env(safe-area-inset-right));
    }
    .house{padding-bottom:max(clamp(28px,5vh,60px),env(safe-area-inset-bottom))}
    .vp__transport{padding-bottom:max(12px,env(safe-area-inset-bottom))}
  }
}

/* ═══════════════════════════════════════════════ REDUCED MOTION ══ */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;
  }
  .grain{animation:none}
  .lamp{display:none}
  /* the preview tile holds on its poster; the mark is the way in */
  .stage__card--video .stage__play{opacity:1}
  .stage__card--video .stage__playlabel{opacity:1}
  .prism__pieces{display:none}
  .mani__type--lit{-webkit-mask-image:none;mask-image:none}
  .mani__type--edge,.mani__cone,.mast__slit{display:none}
  .svc__rail{transform:none!important;flex-direction:column}
  .svc__scrollcue{display:none}
  .svc__pin,.about__pin{position:static;height:auto;overflow:visible}
  .sec--svc .svc__track,.sec--about .about__track{height:auto}
  .svc__panel{width:100%;min-height:auto;border-right:0;border-bottom:var(--hair) solid var(--line-soft)}
  .about__grid{grid-template-columns:1fr!important}
  .tenets li{opacity:1;transform:none}
  /* every cue is open here, so the stack cannot live inside one pinned
     viewport — un-pin it and give each cue its own still inline */
  .cue{--i:1}
  .cue__hit{color:rgb(var(--ink-rgb) / .9)}
  .cue__detail{grid-template-rows:1fr}
  .cue__detailinner{padding-bottom:clamp(12px,1.6vh,22px)}
  .work__pin{position:static;height:auto;overflow:visible}
  .sec--work .work__track{height:auto}
  .console__body{grid-template-columns:1fr}
  .cues{justify-content:flex-start;overflow:visible;border-right:0}
  .stage{display:none}
  .cue__play{display:inline-flex}
  .cue__shot{display:block;grid-column:1/-1;margin-bottom:.9em;max-width:820px}
  .cue__shot img{height:clamp(180px,34vh,360px)}
}
