/* Startup Arena Volt, the halftone press.
   The brush title printed as a press: one solid volt key plate, and the pink and cyan plates
   dot screened from the same letterforms on their own screen angles, printed off register,
   with a spread so a dotted rim survives behind the key. Load after stage.css; the geometry
   (screen box, masks, plate offsets) is set by halftone-press.js from its preset.
   Sources, read 2026-09-23 from the vault (what/content/assets/startup_arena_slides/):
     hero  round4/hero_04b_halftone_ink.html  (1692px title, the squeegee, the wave, the mark)
     quiet round4/fireside_01_backdrop.html  (1240px title, the swing only)
   The CSS below is those two files' press rules, with the --sa-* names read from the repo
   tokens (see stage.css). Keyframe names carry a press- prefix; nothing else is changed. */

/* ---- the screens, both presets -------------------------------------------------------
   Each screen is a canvas with its lattice drawn at its own angle, not a tiled background
   under a CSS rotation, so nothing is resampled per frame and each screen box is only as
   large as its own painted words. The mask is the type rendered to a full stage canvas. */
.press { position: absolute; inset: 0; }
.press .scr {
  position: absolute; opacity: 0;
  mask-size: 1920px 1080px; mask-repeat: no-repeat;
  -webkit-mask-size: 1920px 1080px; -webkit-mask-repeat: no-repeat;
}
.is-inked .press .scr { opacity: 1; }
.press .plate { position: absolute; left: 0; top: 0; }
.press .scr-cyan, .press .scr-pink, .press .scr-wave-c, .press .scr-wave-p {
  mask-image: var(--m-plate); -webkit-mask-image: var(--m-plate);
}
.press .scr-key {
  mask-image: var(--m-key); -webkit-mask-image: var(--m-key);
  background: var(--press-key, var(--sab-volt));
}

/* ---- hero: the luminance wave (04b) --------------------------------------------------
   The same screens in a heavier dot, clipped to one hard edged diagonal band that crosses
   the stage once per loop. The band carries a transform and the plate inside it carries
   the exact inverse, so the dots stay registered while the band travels and both halves
   ride the compositor. */
.press .wband { position: absolute; inset: 0; will-change: transform; }
.press .scr-wave-c .wband, .press .scr-wave-p .wband {
  clip-path: polygon(0 0, 520px 0, 620px 300px, 100px 300px);
  animation: press-wave-sweep 12s linear infinite;
}
.press .scr-wave-c .plate, .press .scr-wave-p .plate { animation: press-wave-hold 12s linear infinite; }
@keyframes press-wave-sweep { from { transform: translateX(-700px); } to { transform: translateX(1900px); } }
@keyframes press-wave-hold  { from { transform: translateX(700px); } to { transform: translateX(-1900px); } }

/* ---- hero: the wordmark press (04b) ---------------------------------------------------
   A solid mark with its own pink and cyan halftone plates, at the title's registration
   offset scaled by the size ratio of the two marks: the mark paints 121px tall against the
   title's 206, so 24 and 20 become 14 and 12, the 18px pitch becomes 10 and the 6px spread
   becomes 4. The plate box is larger than the mark so the spread has somewhere to print:
   the mask is 8px wider, centred on the key. The page positions .press-mark. */
.press-mark { position: absolute; width: 260px; height: 121px; }
.press-mark .wm-key { left: 0; top: 0; width: 260px; height: 121px; color: var(--press-mark, var(--sab-volt)); }
.press-mark .wm-plate {
  left: -8px; top: -5px; width: 276px; height: 131px; background: none;
  mask-size: 268px 125px; mask-position: center; -webkit-mask-size: 268px 125px; -webkit-mask-position: center;
}
.press-mark .wm-pink { transform: translate(-14px, 12px); }
.press-mark .wm-cyan { transform: translate(14px, -12px); }

/* ---- hero: the squeegee and the stock ------------------------------------------------ */
/* the press leaves a tooth on the stock: a neutral grain, no colour. On an ink ground
   multiply has nothing to take away, so the tooth is a screen plate. */
.press-stock {
  position: absolute; inset: -40px; pointer-events: none; mix-blend-mode: screen; opacity: 0.14;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='s' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.38' numOctaves='2' seed='8' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncR type='linear' slope='0.8' intercept='0.34'/%3E%3CfeFuncG type='linear' slope='0.8' intercept='0.34'/%3E%3CfeFuncB type='linear' slope='0.8' intercept='0.34'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='300' height='300' filter='url(%23s)'/%3E%3C/svg%3E");
  background-size: 300px 300px;
}
.press-squeegee {
  position: absolute; left: 0; top: 0; width: 1920px; height: 120px;
  background: var(--press-bar, var(--sab-volt)); transform: translateY(-160px);
  animation: press-sq-pass 12s linear infinite;
}
@keyframes press-sq-pass {
  0%    { transform: translateY(-160px); }
  7.5%  { transform: translateY(1084px); }
  100%  { transform: translateY(1084px); }
}

/* ---- hero entrance: the squeegee reveals the press, the plates arrive a beat late ----- */
.run .press--hero, .run .press-mark { animation: press-reveal 900ms linear both; }
@keyframes press-reveal { from { clip-path: inset(0 0 100% 0); } to { clip-path: inset(0 0 -4% 0); } }
.run .press-squeegee { animation: press-sq-pass 12s linear both infinite; }
.run .press--hero .scr-pink, .run .press--hero .scr-wave-p { animation: press-arrive-p 260ms var(--sab-ease) 760ms both; }
.run .press--hero .scr-cyan, .run .press--hero .scr-wave-c { animation: press-arrive-c 260ms var(--sab-ease) 840ms both; }
.run .press-mark .wm-pink { animation: press-arrive-wp 260ms var(--sab-ease) 760ms both; }
.run .press-mark .wm-cyan { animation: press-arrive-wc 260ms var(--sab-ease) 840ms both; }
@keyframes press-arrive-p {
  from { transform: translate(-76px, 62px); }
  77%  { transform: translate(-14px, 12px); }
  to   { transform: translate(-24px, 20px); }
}
@keyframes press-arrive-c {
  from { transform: translate(72px, -64px); }
  77%  { transform: translate(13px, -11px); }
  to   { transform: translate(24px, -20px); }
}
/* the mark's own arrival, at the mark's own offset */
@keyframes press-arrive-wp {
  from { transform: translate(-44px, 38px); }
  77%  { transform: translate(-8px, 7px); }
  to   { transform: translate(-14px, 12px); }
}
@keyframes press-arrive-wc {
  from { transform: translate(42px, -38px); }
  77%  { transform: translate(8px, -6px); }
  to   { transform: translate(14px, -12px); }
}

/* ---- quiet entrance: the plates walk into register under the key (fireside) ----------- */
@keyframes press-quiet-arrive-p { from { transform: translate(-58px, 48px); } to { transform: translate(-18px, 15px); } }
@keyframes press-quiet-arrive-c { from { transform: translate(56px, -47px); } to { transform: translate(18px, -15px); } }
.stage.run .press--quiet .scr-pink { animation: press-quiet-arrive-p 700ms var(--sab-ease) both; }
.stage.run .press--quiet .scr-cyan { animation: press-quiet-arrive-c 700ms var(--sab-ease) 140ms both; }
/* ?settled=1 on the quiet press: arrive finished, idle running */
.stage.settled.run .press--quiet .scr-pink, .stage.settled.run .press--quiet .scr-cyan { animation: none; }

/* ---- quiet: the supporting stack, layout A (fireside_01) -------------------------------
   Solid volt type, no second press. The halftone is the brush title's alone; everything
   under the rule is flat colour so the eye reads one piece of art and then two lines of
   information. ArenaPress.stackA places each line from its own measured paint. */
.press-stack-rule {
  position: absolute; left: 340px; top: 287px; width: 1440px; height: 2px;
  background: var(--sab-hair-on-object); opacity: 0;
}
.press-stack-session {
  position: absolute; margin: 0; opacity: 0; left: 0; top: 329px; width: 1920px; white-space: pre;
  color: var(--sab-volt);
  font-family: var(--sab-font-display); font-weight: 900; font-size: 112px;
  line-height: 0.95; letter-spacing: -0.015em; text-transform: uppercase;
}
/* the line takes 04b's date row: the same mono face, 600, uppercase, tabular figures, in
   the same volt on the same ink */
.press-stack-line {
  position: absolute; margin: 0; opacity: 0; left: 0; top: 472px; width: 1920px; white-space: pre;
  color: var(--sab-volt);
  font-family: var(--sab-font-mono); font-weight: 600; font-size: 32px; line-height: 1.2;
  letter-spacing: 0.13em; text-transform: uppercase; font-variant-numeric: tabular-nums;
}
.press-stack-session > span, .press-stack-line > span { display: block; }
.is-inked .press-stack-rule, .is-inked .press-stack-session, .is-inked .press-stack-line { opacity: 1; }
/* Nothing fades: the plates move, everything under the rule cuts. jump-start, not end: played
   live, Chrome can finish a 1ms animation at progress 0.9999999999999, which steps(1, end)
   holds at its first keyframe, so the line sat at opacity 0 for good. */
@keyframes press-cut-on { from { opacity: 0; } to { opacity: 1; } }
.stage.run .press-stack-rule,
.stage.run .press-stack-session { animation: press-cut-on 1ms steps(1, jump-start) 840ms both; }
.stage.run .press-stack-line { animation: press-cut-on 1ms steps(1, jump-start) 1040ms both; }
.stage.settled.run .press-stack-rule, .stage.settled.run .press-stack-session,
.stage.settled.run .press-stack-line { animation: none; }

/* ---- quiet: the grain -------------------------------------------------------------------
   One grayscale tile, screened over the whole stage so the ink field is never a dead flat.
   It shifts on a 14s step loop: the slowest thing on the stage. */
.press-grain {
  position: absolute; inset: 0; pointer-events: none; opacity: 0.08;
  mix-blend-mode: screen; background-repeat: repeat; background-size: 256px 256px;
}
@keyframes press-grain-shift {
  0%   { background-position: 0 0; }
  25%  { background-position: -73px 41px; }
  50%  { background-position: 52px -88px; }
  75%  { background-position: -31px -19px; }
  100% { background-position: 0 0; }
}
.stage.run .press-grain { animation: press-grain-shift 14s steps(1, end) infinite; }

@media (prefers-reduced-motion: reduce) {
  /* arrives printed; one gentle beat stays: the moire keeps drifting */
  .press-squeegee, .press .wband { display: none; }
  /* the quiet stage arrives printed and set, and the grain keeps its one gentle loop */
  .stage .press-grain { animation: press-grain-shift 14s steps(1, end) infinite !important; }
}
