/* ============================================================
   THE BUREAU OF DECEIVERS — optical, blocky, square-modular.
   Two worlds, one page:
     · the opening — darkness, the spirograph, the forming poster
     · the mosaic — a continuous grid of ink/paper blocks the
       poster docks into. Pure HTML/CSS below the fold: illusions
       are gradients, entrances are CSS scroll-driven animations,
       the hover misregistration is plain :hover. JS exists only
       where it IS the piece (spirograph, halftone, scanline
       title, the formation scrub).
   ============================================================ */

/* ============================================================
   TOKENS
   ============================================================ */
:root {
  /* The two surfaces of the mosaic */
  --ink:   #131111;
  --paper: #ede8e8;
  --mid:   #55504c;      /* secondary text on paper */
  --mid-p: #c3beb7;      /* secondary text on ink (AA on the field) */
  --mortar:#a8a29c;      /* exhibit mortar grey */

  /* Bureau red — reserved for the pulse dot */
  --red: #e03a3e;

  /* Misregistration plates (transient colour only) */
  --plate-c: rgba(0, 136, 176, 0.6);
  --plate-m: rgba(214, 0, 108, 0.6);

  /* Opening (dark world) text */
  --text-primary:   oklch(94% 0.005 85);
  --c-teal:         oklch(72% 0.065 212);

  /* Layout */
  --nav-h: 42px;
  --gap: 12px;

  /* Type */
  --serif: 'Operator SSm', Georgia, serif;               /* the speaking voice */
  --mono:  'Operator Mono', 'Courier New', monospace;    /* the typed voice */
  --font-body: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Arial, sans-serif;

  /* ── Type presets — the eight voices of the site.
     Media queries retune THESE, never individual selectors. ── */
  --t-display: clamp(3.2rem, 8.5vw, 9.6rem);   /* the question */
  --t-title-1: clamp(2.2rem, 4.2vw, 4.6rem);   /* hero, findings, case titles */
  --t-title-2: clamp(1.9rem, 3vw, 3.6rem);     /* card titles */
  --t-title-3: clamp(1.6rem, 2.4vw, 2.8rem);   /* CTA line, rail numerals */
  --t-lead:    clamp(1.3rem, 1.8vw, 2rem);     /* statements, archive line */
  --t-body:    clamp(1rem, 1.15vw, 1.25rem);   /* reading text (16px floor) */
  --t-caption: 0.85rem;                        /* notes, replies, art caption */
  --t-label:   0.72rem;                        /* buttons, meta, footer, nav */
  --t-stamp:   clamp(0.85rem, 1vw, 1rem);      /* kickers (file stamps) */

  --lh-display: 1.05;
  --lh-body:    1.5;
  --ls-display: -0.03em;
  --ls-label:   0.18em;
  --ls-stamp:   0.24em;

  /* Easing */
  --ease-expo: cubic-bezier(0.16, 1, 0.3, 1);

  /* Formation scrub (written by js/posterize.js) */
  --p: 0;
  --tiles: 0;
  --fade-out: 1;
  --face-in: 0;
  --title-s: 1;
  --poster-w: 400px;
  --poster-h: 556px;
  --dock-x: 0px;
  --dock-y: 0px;
}

/* ============================================================
   RESET & BASE
   ============================================================ */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 16px;
  scroll-behavior: smooth;
  background-color: #101014;
}

body {
  background-color: transparent;
  color: var(--text-primary);
  font-family: var(--serif);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

a { color: inherit; text-decoration: none; }
button { font: inherit; }

/* ============================================================
   BACKGROUND LAYERS
   ============================================================ */

/* Halftone field — WebGL, the darkness the flower draws in */
#bg-cv {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 0;
}

/* Scanlines — the whole page is a transmission */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  background: repeating-linear-gradient(
    to bottom,
    transparent,
    transparent 1px,
    oklch(0% 0 0 / 0.016) 1px,
    oklch(0% 0 0 / 0.016) 2px
  );
  pointer-events: none;
  z-index: 999;
}

/* ============================================================
   NAV — the menu stays on top
   ============================================================ */
.nav {
  /* absolute, not fixed: inside the pinned hero on the home page
     (rides the narrative, scrolls away with it), plain top-of-page
     on the subpages */
  position: absolute;
  top: 0;
  left: var(--gap);
  right: var(--gap);
  z-index: 50;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 0 20px;
  /* a slim stripe of the same material as the dark blocks: flush
     with the top edge, inset at the sides, one block-gap above
     the poster. Appears only once the poster is formed (the
     nav-ready class - static on subpages, scrub-driven on home) */
  color: var(--paper);
  /* the type rides the flower from the first frame; the slab
     itself arrives with the poster (body.nav-ready) */
  background: transparent;
  transition: background 0.5s ease;
}
body.nav-ready .nav { background: rgba(0, 0, 0, 0.5); }

.nav-brand {
  font-family: var(--mono);
  font-size: var(--t-label);
  font-weight: 700;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
}

.nav-links {
  display: flex;
  gap: clamp(14px, 2.4vw, 28px);
  font-family: var(--mono);
  font-size: var(--t-label);
  font-style: italic;
}
.nav-links a { transition: opacity 0.2s ease; }
.nav-links a:hover,
.nav-links a:focus-visible { opacity: 0.55; }

/* ============================================================
   OPENING — pinned region; the formation scrub
   ============================================================ */
#hero-scroll {
  position: relative;
  z-index: 1;
  /* formation (0–.66) + band build (.56–.96); see js/posterize.js */
  height: 340vh;
}

#hero-scroll #hero {
  position: sticky;
  top: 0;
  height: 100svh;
  /* overflow stays visible: clipping would slice the poster's
     cast shadow */
  overflow: visible;
}

/* ── The hero unit: poster left, full height; text beside it ── */
.hero-band {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: stretch;
  gap: clamp(24px, 4vw, 72px);
  padding: calc(var(--nav-h) + var(--gap)) var(--gap) var(--gap);
  pointer-events: none;
}
#hero.settled .hero-band { pointer-events: auto; }

/* The dock target: left margin, whole vertical space */
.hero-poster-slot {
  height: 100%;
  aspect-ratio: 0.72;
  flex: none;
}

/* Text appears on the shared clock with the RGB reveal:
   split plates collapse as --tt reaches 1, then stay sharp */
.hero-band .hero-unit {
  --tt: clamp(0, calc((var(--tiles, 0) - var(--d, 0)) * var(--dinv, 1)), 1);
  opacity: var(--tt);
  transform: translate(calc(var(--tx, 0px) * (1 - var(--tt))), 0);
}
.hero-unit :is(.kicker, .hero-title, .hero-sub, .cta-alt) {
  text-shadow:
    calc(10px * (1 - var(--tt, 0))) 0 var(--plate-m),
    calc(-10px * (1 - var(--tt, 0))) 0 var(--plate-c);
}

.hero-unit {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  text-align: left;
  gap: clamp(12px, 1.8vh, 20px);
  padding-right: clamp(12px, 3vw, 60px);
  color: var(--paper);
}
.hero-unit .kicker { color: var(--mid-p); }
.hero-kicker { font-size: calc(var(--t-stamp) * 1.18); letter-spacing: var(--ls-stamp); }
.hero-title {
  font-family: var(--mono);
  font-weight: 700;
  font-size: var(--t-title-1);
  line-height: var(--lh-display);
  letter-spacing: var(--ls-display);
  color: var(--paper);
}
.hero-title em { font-weight: 400; font-style: italic; }
.hero-sub {
  font-family: var(--serif);
  font-size: var(--t-lead);   /* promoted: reads at statement size */
  line-height: 1.45;
  color: var(--mid-p);
  max-width: 46ch;
}
.hero-sub strong { color: var(--paper); font-weight: 600; }
.hero-ctas { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.hero-unit .cta-alt { color: var(--mid-p); }
.hero-unit .claim-reply { color: var(--mid-p); }

/* ── The poster slot: carries the dock drift ── */
.poster-slot {
  position: absolute;
  inset: 0;
  z-index: 4;
  transform: translate(
    calc(var(--dock-x) * var(--p)),
    calc(var(--dock-y) * var(--p)));
  pointer-events: none;
}

/* The frame that becomes the poster */
.poster {
  position: absolute;
  inset: 0;
  margin: auto;
  overflow: hidden;
  z-index: 2;
  width:  calc(100%  * (1 - var(--p)) + var(--poster-w) * var(--p));
  height: calc(100% * (1 - var(--p)) + var(--poster-h) * var(--p));
  background: oklch(9% 0.015 262 / var(--p));
  box-shadow:
    0 calc(6px  * var(--p)) calc(18px * var(--p)) oklch(0% 0 0 / calc(0.4 * var(--p))),
    0 calc(20px * var(--p)) calc(44px * var(--p)) oklch(0% 0 0 / calc(0.3 * var(--p))),
    inset 0 0 0 calc(1px * var(--p)) oklch(100% 0 0 / 0.07);
}

/* Silk sheen inside the poster only */
.poster::before {
  content: '';
  position: absolute;
  inset: -20%;
  background:
    linear-gradient(118deg, transparent 38%, oklch(48% 0.10 262 / 0.18) 50%, transparent 62%),
    linear-gradient(295deg, transparent 55%, oklch(40% 0.08 268 / 0.12) 70%, transparent 85%);
  opacity: var(--p);
  pointer-events: none;
}

/* Spirograph keeps its buffer aspect — the flower never distorts */
.spiro-wrap {
  position: absolute;
  top: calc(var(--spiro-top, 0px) * var(--p));
  left: 50%;
  transform: translateX(-50%);
  width: calc(100% * (1 - var(--p)) + var(--spiro-w, 100%) * var(--p));
  aspect-ratio: var(--cv-ar, 1.6);
  z-index: 1;
}

#cv { display: block; width: 100%; height: 100%; }

/* Centre dot */
.hero-dot {
  position: absolute;
  top: 44%;   /* the flower's centre rides high (spirograph CY) */
  left: 50%;
  transform: translate(-50%, -50%);
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #ff0000;
  z-index: 5;
}

/* ── Fullscreen overlay (dissolves as the frame closes) ── */
.hero-inner {
  position: absolute;
  inset: 0;
  z-index: 3;
}

.hero-decl {
  position: absolute;
  z-index: 10;
  top: 56%;
  left: 50%;
  transform: translateX(-50%) scale(var(--title-s));
  transform-origin: top center;
  /* the opening is textless: the title belongs to the poster and
     arrives with the other faces */
  opacity: var(--face-in, 0);
}

#title-cv { display: block; opacity: 0; }
#title-cv-mobile { display: none; opacity: 0; }
@media (max-width: 600px) {
  #title-cv { display: none; }
  #title-cv-mobile { display: block; }
}

/* The stem: a hairline rising from the page bottom toward the
   flower, stopping well short of it — the scroll suggestion */
.scroll-pip {
  position: absolute;
  bottom: clamp(18px, 3vh, 30px);
  left: 50%;
  transform: translateX(-50%);
  width: 1px;
  height: 192px;  /* the original pip, six times its first size */
  background: var(--c-teal);
  opacity: 0;
}

/* Stem reveal (after the first curve) */
#hero.hero-revealed .scroll-pip {
  animation: fadein 1s var(--ease-expo) 0.8s forwards,
             pipbob 2.6s ease-in-out 1.8s infinite;
}

/* Frozen poster: the dot holds solid */
#hero.frozen .hero-dot {
  animation: none !important;
  opacity: 1 !important;
}

/* The stem dissolves as the frame closes in */
#hero.scrubbing .scroll-pip {
  animation: none;
  opacity: var(--fade-out);
}

/* ── Poster face ── */
.poster-face {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;
  opacity: var(--face-in);
  text-align: center;
  font-family: var(--font-body);
  text-transform: uppercase;
  pointer-events: none;
}
.poster-billing {
  top: 79%;
  width: 88%;
  font-size: clamp(0.44rem, calc(var(--poster-w) * 0.0145), 0.62rem);
  letter-spacing: 0.2em;
  line-height: 1.9;
  color: oklch(76% 0.07 212 / 0.92);   /* the strap's light-blue */
}
.poster-coming {
  bottom: 3%;
  font-size: clamp(0.45rem, calc(var(--poster-w) * 0.0135), 0.6rem);
  letter-spacing: 0.46em;
  color: var(--spiro-ink, oklch(74% 0.07 212 / 0.85));
  white-space: nowrap;
}

/* ============================================================
   THE CARDS — one topic per block (Apple grammar, Bureau ink)
   ============================================================ */
.cards {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--gap);
  padding: 0 var(--gap) var(--gap);
}

.card {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  min-height: clamp(480px, 72svh, 640px);
  padding: clamp(44px, 7vh, 84px) clamp(20px, 3vw, 48px) 0;
  gap: clamp(14px, 2vh, 24px);
}
.c-ink   { background: rgba(0, 0, 0, 0.5); color: var(--paper); }
.c-paper { background: var(--paper); color: var(--ink);
           box-shadow: inset 0 0 0 1px oklch(0% 0 0 / 0.06); }
.card-full { grid-column: 1 / -1; min-height: clamp(560px, 84svh, 760px); }
.card-half { min-height: clamp(460px, 68svh, 620px); }
/* Text-only cards size to their content */
.card-compact {
  min-height: 0;
  justify-content: center;
  padding-bottom: clamp(44px, 7vh, 84px);
}

/* The case page: room under the fixed nav; a taller opening card */
.page-cards { padding-top: calc(var(--nav-h) + var(--gap)); }
.page-hero { min-height: min(78svh, 700px); }
.page-hero .hero-ctas { justify-content: center; }
.case-decl { display: flex; justify-content: center; margin: clamp(8px, 1.6vh, 22px) 0; }
#case-title-cv { display: block; opacity: 0; max-width: 100%; }
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.card-copy {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(10px, 1.5vh, 18px);
  max-width: 62ch;
}
.card-h2 {
  font-family: var(--mono);
  font-weight: 700;
  font-size: var(--t-title-2);
  line-height: 1.08;
  letter-spacing: var(--ls-display);
}
.card-sub {
  font-family: var(--serif);
  font-size: var(--t-lead);   /* promoted: reads at statement size */
  line-height: 1.45;
  color: var(--mid);
  max-width: 52ch;
}
.c-ink .card-sub { color: var(--mid-p); }
.c-ink .card-sub strong, .c-ink .card-sub em { color: var(--paper); }
.card-sub strong { font-weight: 600; }

/* The claim card: copy left, spatial stand-in right */
.card-split {
  flex-direction: row;
  align-items: center;
  text-align: left;
  gap: clamp(24px, 4vw, 80px);
  padding-bottom: clamp(44px, 7vh, 84px);
}
.card-split .card-copy { flex: 1.5; align-items: flex-start; max-width: none; }
.card-split .card-copy .card-h2 { max-width: none; }
.card-art3d {
  flex: 1;
  display: grid;
  place-items: center;
  perspective: 1000px;
}
/* The morphing wireframe — sphere, cube, one-sheet; frameless,
   always turning, glitching through each transformation */
.wire3d {
  --wd: clamp(160px, 22vw, 300px);
  width: var(--wd);
  aspect-ratio: 1;
  transform-style: preserve-3d;
  animation: spin3d 16s linear infinite,
             wire-glitch 21s step-end infinite;
}
.w-face {
  position: absolute;
  inset: 0;
  border: 1px solid oklch(100% 0 0 / 0.55);
}
.w-f1 { animation: morph-1 21s ease-in-out infinite; }
.w-f2 { animation: morph-2 21s ease-in-out infinite; }
.w-f3 { animation: morph-3 21s ease-in-out infinite; }
.w-f4 { animation: morph-4 21s ease-in-out infinite; }
.w-f5 { animation: morph-5 21s ease-in-out infinite; }
.w-f6 { animation: morph-6 21s ease-in-out infinite; }

/* The visual fills the card's lower half */
.card-art {
  margin-top: auto;
  align-self: stretch;
  height: clamp(180px, 34svh, 320px);
  display: flex;
  flex-direction: column;
}
.card-art-center { align-items: center; justify-content: center; }
.card-art .linefield { flex: 1; }

/* ── The misregistration: reserved for the interactable —
   the exhibits (the visual puzzles), never whole blocks ── */
@media (hover: hover) and (pointer: fine) {
  .card-exhibit { transition: filter 0.12s ease; cursor: pointer; }
  .card-exhibit:hover {
    filter: invert(1);
    box-shadow: 5px 0 0 var(--plate-c), -5px 0 0 var(--plate-m);
    z-index: 6;
  }
}

/* ── The RGB reveal: every text arrives split, then locks in
   focus (scroll-driven; degrades to plain visible) ── */
/* ── Reveals (driven by js/reveal.js — one-shot, every engine) ──
   Text arrives on the RGB split; blocks rise. Without JS nothing
   is ever hidden. */
.rgb-pending { opacity: 0; }
.rgb-reveal  { animation: rgb-in 0.7s ease-out both; }

.cards .card {
  transition: opacity 0.7s ease, transform 0.8s var(--ease-expo);
}
.cards .card.card-pending {
  opacity: 0;
  transform: translateY(44px);
}

/* ============================================================
   SHARED TYPE
   ============================================================ */
.kicker {
  font-family: var(--mono);
  font-size: var(--t-stamp);
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: var(--ls-stamp);
  text-transform: uppercase;
  color: var(--mid);
}
.c-ink .kicker { color: var(--mid-p); }

/* Metadata row */
.meta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 36px;
}
.meta-row div { display: flex; flex-direction: column; gap: 3px; }

/* Credits: a formal 2x2 register, centred under the copy */
.meta-credits {
  display: grid;
  grid-template-columns: repeat(2, minmax(240px, 380px));
  justify-content: center;
  gap: clamp(20px, 3vh, 34px) clamp(36px, 5vw, 84px);
  margin-top: clamp(10px, 2vh, 24px);
  text-align: center;
}
.meta-credits div { display: flex; flex-direction: column; gap: 6px; align-items: center; }
.meta-credits dt { font-size: var(--t-label); letter-spacing: var(--ls-label); }
.meta-credits dd {
  font-size: var(--t-body);
  font-weight: 600;
  line-height: 1.45;
  max-width: 34ch;
}
@media (max-width: 940px) {
  .meta-credits { grid-template-columns: minmax(0, 1fr); }
}
.meta-row dt {
  font-family: var(--mono);
  font-size: var(--t-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--mid);
}
.meta-row dd { font-weight: 600; }
.c-ink .meta-row dt { color: var(--mid-p); }

/* ============================================================
   EXHIBITS — illusions as pure CSS
   ============================================================ */
.exhibit-caption {
  padding: 10px 14px;
  font-family: var(--mono);
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--paper);
}
/* Exhibit C — line interference: the lines are not moving */
.linefield {
  flex: 1;
  min-height: 0;
  position: relative;
  background: repeating-linear-gradient(90deg, var(--paper) 0 3px, transparent 3px 14px);
  overflow: hidden;
}
.linefield::after {
  content: '';
  position: absolute;
  inset: -10%;
  background: repeating-linear-gradient(90deg, var(--ink) 0 3px, transparent 3px 13px);
  animation: field-drift 9s ease-in-out infinite;
}

/* Moiré — concentric interference */
.moire { position: absolute; inset: 0; }
.moire::before,
.moire::after {
  content: '';
  position: absolute;
  inset: -25%;
  background: repeating-radial-gradient(circle at 50% 50%, var(--ink) 0 5px, var(--paper) 5px 11px);
}
.moire::after {
  background: repeating-radial-gradient(circle at 50% 50%, var(--ink) 0 5px, transparent 5px 11px);
  mix-blend-mode: screen;
  opacity: 0.9;
  animation: moire-drift 8s ease-in-out infinite;
}

/* Blinking eye */
.eye {
  width: 52%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--paper);
  display: grid;
  place-items: center;
  animation: eye-blink 5.2s ease-in-out infinite;
}
.pupil {
  width: 42%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--ink);
}
/* ============================================================
   CTA PILL (Bureau red pulse)
   ============================================================ */
.cta {
  display: inline-flex;
  align-items: center;
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--ink);
  border-radius: 1.6em;
  padding: 0.85em 1.4em;
  font-family: var(--mono);
  font-size: var(--t-label);
  line-height: 1.2;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  cursor: pointer;
  align-self: flex-start;
  transition: background 0.25s ease, color 0.25s ease;
}
.cta i {
  width: 0.5em;
  height: 0.5em;
  margin-right: 0.7rem;
  position: relative;
  flex: 0 0 auto;
}
.cta i::before {
  content: '';
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: var(--red);
  animation: ctapulse1 2s linear infinite;
}
.cta i::after {
  content: '';
  position: absolute;
  top: 0; left: 0;
  width: 100%;
  height: 100%;
  border: 1px solid var(--red);
  border-radius: 50%;
  animation: ctapulse2 2s linear infinite;
}
.cta:hover,
.cta:focus-visible { background: var(--ink); color: var(--paper); }
.cta-onink { color: var(--paper); border-color: var(--paper); }
/* Primary: solid white pill */
.cta-solid {
  background: var(--paper);
  color: var(--ink);
  border-color: var(--paper);
}
.cta-solid:hover,
.cta-solid:focus-visible { background: transparent; color: var(--paper); }
.cta-solid { font-weight: 700; }
.cta-note {
  font-family: var(--serif);
  font-style: italic;
  font-size: var(--t-caption);
  color: var(--mid-p);
  align-self: center;
}
.cta-onink:hover,
.cta-onink:focus-visible { background: var(--paper); color: var(--ink); }
.cta-alt {
  font-family: var(--serif);
  font-style: italic;
  font-size: var(--t-caption);
  color: var(--mid);
}

.cta-wrap { display: flex; flex-direction: column; gap: 10px; }
.card-art .cta-wrap { align-items: center; margin-top: clamp(8px, 1.4vh, 16px); text-align: center; }
.card-art .cta { align-self: center; }

/* The observers card: its art (counter + button) sizes to content —
   the fixed art height was clipping the button out of existence */
#observers .card-art {
  height: auto;
  padding-bottom: clamp(28px, 4.5vh, 52px);
}
#observers .counter-block { align-items: center; }
.claim-reply {
  display: none;
  font-family: var(--serif);
  font-style: italic;
  font-size: var(--t-caption);
  line-height: var(--lh-body);
  color: var(--mid-p);
}
.claim-reply.show { display: block; }
/* Counter (scanline 33) */
.counter-block { display: flex; flex-direction: column; align-items: flex-start; }
#counter-cv { display: block; opacity: 0; max-width: 100%; }
/* ============================================================
   MOSAIC PLACEMENTS (desktop)
   ============================================================ */
/* ── The question card ── */
.card-question { justify-content: center; padding-bottom: clamp(44px, 7vh, 84px); }
.question-display {
  font-family: var(--mono);
  font-weight: 700;
  font-size: var(--t-display);
  line-height: var(--lh-display);
  letter-spacing: var(--ls-display);
  max-width: 15em;
}
.question-display em { font-weight: 400; font-style: italic; }
.q-mark {
  color: transparent;
  -webkit-text-stroke: 2px var(--ink);
  animation: q-glitch 3.4s step-end infinite;
}

/* ── Preliminary findings: one piece, centred like a plaque ── */
.card-findings { min-height: 0; padding-bottom: clamp(60px, 8vh, 110px); }
.findings-title { font-size: var(--t-title-1); }

.clause {
  font-family: var(--serif);
  font-size: var(--t-lead);
  line-height: 1.45;
}
.clause em {
  font-style: italic;
  color: var(--mid);
}


/* ── Correspondence card ── */
.cta-line-a {
  font-family: var(--serif);
  font-style: italic;
  font-size: var(--t-lead);
  color: var(--mid);
}
.cta-line-b {
  display: inline-block;
  font-family: var(--mono);
  font-weight: 700;
  font-size: var(--t-title-3);
  letter-spacing: -0.02em;
  border-bottom: 3px solid var(--ink);
  padding-bottom: 2px;
  margin-top: 6px;
  transition: opacity 0.2s ease;
}
.cta-line-b:hover,
.cta-line-b:focus-visible { opacity: 0.6; }
/* Anchor offsets under the sticky nav */
#work, #question, #findings, #mosaic { scroll-margin-top: calc(var(--nav-h) + var(--gap)); }

/* ============================================================
   FOOTER
   ============================================================ */
footer {
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  padding: 30px 20px 42px;
  font-family: var(--mono);
  font-size: var(--t-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--mid);
}
.footer-brand { font-weight: 700; color: var(--paper); }
footer { color: var(--mid-p); }

/* ============================================================
   KEYFRAMES
   ============================================================ */
@keyframes fadein { from { opacity: 0; } to { opacity: 1; } }
@keyframes q-glitch {
  0%, 100% { -webkit-text-stroke-color: var(--ink);
             text-shadow: none; }
  12%      { -webkit-text-stroke-color: #d6006c;
             text-shadow: 3px 0 var(--plate-c); }
  18%      { -webkit-text-stroke-color: var(--ink);
             text-shadow: none; }
  47%      { -webkit-text-stroke-color: #0088b0;
             text-shadow: -3px 0 var(--plate-m); }
  54%      { -webkit-text-stroke-color: var(--ink);
             text-shadow: none; }
  76%      { -webkit-text-stroke-color: #d6006c;
             text-shadow: -2px 0 var(--plate-c), 2px 0 var(--plate-m); }
  83%      { -webkit-text-stroke-color: var(--ink);
             text-shadow: none; }
}
/* centre origin: the stem extends in BOTH directions */
@keyframes pipbob {
  0%, 100% { transform: translateX(-50%) scaleY(1);    opacity: 0.4;  }
  50%      { transform: translateX(-50%) scaleY(1.24); opacity: 0.75; }
}
@keyframes rgb-in {
  0%   { opacity: 0;
         text-shadow: 9px 0 var(--plate-m), -9px 0 var(--plate-c); }
  55%  { opacity: 1;
         text-shadow: 4px 0 var(--plate-m), -4px 0 var(--plate-c); }
  100% { opacity: 1;
         text-shadow: 0 0 rgba(214, 0, 108, 0), 0 0 rgba(0, 136, 176, 0); }
}
}
@keyframes g-pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.13); } }
@keyframes eye-blink { 0%, 92%, 100% { transform: scaleY(1); } 96% { transform: scaleY(0.08); } }
@keyframes spin3d {
  from { transform: rotateX(-18deg) rotateY(0deg); }
  to   { transform: rotateX(-18deg) rotateY(360deg); }
}
@keyframes moire-drift { 0%, 100% { transform: translate(-6%, -4%); } 50% { transform: translate(6%, 4%); } }
@keyframes field-drift { 0%, 100% { transform: translateX(-8px); } 50% { transform: translateX(8px); } }
@keyframes ctapulse1 {
  0%   { transform: scale(0.8); opacity: 1; }
  50%  { transform: scale(1);   opacity: 1; }
  100% { transform: scale(0.8); opacity: 1; }
}
@keyframes ctapulse2 {
  0%   { transform: scale(1);   opacity: 0.9; }
  100% { transform: scale(2.6); opacity: 0; }
}

/* ============================================================
   SKIP LINK
   ============================================================ */
.skip-link {
  position: fixed;
  top: -60px;
  left: 12px;
  z-index: 1000;
  padding: 10px 16px;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-body);
  font-size: 0.8rem;
  border-radius: 4px;
  transition: top 0.2s ease;
}
.skip-link:focus-visible { top: 12px; }

/* ============================================================
   ACCESSIBILITY
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  #hero-scroll { height: calc(100svh - var(--nav-h)); }

  .hero-band [data-tile] { --tt: 1; }
  .x-pulse::before, .eye, .moire::after, .linefield::after,
  .cta i::before, .cta i::after, .scroll-pip, .wire3d, .q-mark,
  .w-face, .strip-track, .corr-disc, .strip-captions span, .state {
    animation: none !important;
  }
  .card-findings .clause {
    opacity: 1; filter: none; text-shadow: none; animation: none;
  }
  .strip-captions span { opacity: 0; }
  .strip-captions span:first-child { opacity: 1; }
  #title-cv, #title-cv-mobile { animation: none !important; opacity: 1 !important; }
}

/* ============================================================
   MORPH TIMELINE — 21s: sphere (0–20%) → morph → cube (28–48%)
   → morph → one-sheet (56–76%) → morph home. The glitch plates
   fire only inside the morph windows.
   ============================================================ */
@keyframes wire-glitch {
  0%, 20%  { filter: none; }
  21%      { filter: drop-shadow(4px 0 rgba(214,0,108,0.75)) drop-shadow(-4px 0 rgba(0,136,176,0.75)); }
  24%      { filter: drop-shadow(-3px 0 rgba(214,0,108,0.75)) drop-shadow(3px 0 rgba(0,136,176,0.75)); }
  28%, 48% { filter: none; }
  49%      { filter: drop-shadow(4px 0 rgba(0,136,176,0.75)) drop-shadow(-4px 0 rgba(214,0,108,0.75)); }
  52%      { filter: drop-shadow(-3px 0 rgba(0,136,176,0.75)) drop-shadow(3px 0 rgba(214,0,108,0.75)); }
  56%, 76% { filter: none; }
  77%      { filter: drop-shadow(4px 0 rgba(214,0,108,0.75)) drop-shadow(-4px 0 rgba(0,136,176,0.75)); }
  80%      { filter: drop-shadow(-3px 0 rgba(0,136,176,0.75)) drop-shadow(3px 0 rgba(214,0,108,0.75)); }
  84%, 100% { filter: none; }
}

/* Each plate: great-circle ring → cube face → stacked sheet */
@keyframes morph-1 {
  0%, 20%   { border-radius: 50%; transform: rotateY(0deg); }
  28%, 48%  { border-radius: 0;   transform: translateZ(calc(var(--wd) / 2)); }
  56%, 76%  { border-radius: 0;   transform: translateZ(-6px) scaleX(0.72); }
  84%, 100% { border-radius: 50%; transform: rotateY(0deg); }
}
@keyframes morph-2 {
  0%, 20%   { border-radius: 50%; transform: rotateY(30deg); }
  28%, 48%  { border-radius: 0;   transform: rotateY(180deg) translateZ(calc(var(--wd) / 2)); }
  56%, 76%  { border-radius: 0;   transform: translateZ(-2px) scaleX(0.72); }
  84%, 100% { border-radius: 50%; transform: rotateY(30deg); }
}
@keyframes morph-3 {
  0%, 20%   { border-radius: 50%; transform: rotateY(60deg); }
  28%, 48%  { border-radius: 0;   transform: rotateY(90deg) translateZ(calc(var(--wd) / 2)); }
  56%, 76%  { border-radius: 0;   transform: translateZ(2px) scaleX(0.72); }
  84%, 100% { border-radius: 50%; transform: rotateY(60deg); }
}
@keyframes morph-4 {
  0%, 20%   { border-radius: 50%; transform: rotateY(90deg); }
  28%, 48%  { border-radius: 0;   transform: rotateY(-90deg) translateZ(calc(var(--wd) / 2)); }
  56%, 76%  { border-radius: 0;   transform: translateZ(6px) scaleX(0.72); }
  84%, 100% { border-radius: 50%; transform: rotateY(90deg); }
}
@keyframes morph-5 {
  0%, 20%   { border-radius: 50%; transform: rotateY(120deg); }
  28%, 48%  { border-radius: 0;   transform: rotateX(90deg) translateZ(calc(var(--wd) / 2)); }
  56%, 76%  { border-radius: 0;   transform: translateZ(10px) scaleX(0.72); }
  84%, 100% { border-radius: 50%; transform: rotateY(120deg); }
}
@keyframes morph-6 {
  0%, 20%   { border-radius: 50%; transform: rotateX(90deg); }
  28%, 48%  { border-radius: 0;   transform: rotateX(-90deg) translateZ(calc(var(--wd) / 2)); }
  56%, 76%  { border-radius: 0;   transform: translateZ(-10px) scaleX(0.72); }
  84%, 100% { border-radius: 50%; transform: rotateX(90deg); }
}

/* ============================================================
   THE LIVING STRIPE — fifteen specimens on a slow loop.
   Fixed square module; the track carries two copies and slides
   half its width for a seamless orbit. Hover pauses the drift;
   the specimens themselves are the interactables.
   ============================================================ */
/* The stripe is not a card: its specimens are blocks of their
   own, floating over the field, separated by the block gap */
.card-strip {
  padding: 0;
  min-height: 0;
  overflow: hidden;
  gap: 0;
  background: transparent;
}
.strip-track {
  --sqm: clamp(212px, 25vw, 325px);   /* the module */
  display: flex;
  width: max-content;
  animation: strip-drift 90s linear infinite;
}
.card-strip:hover .strip-track,
.card-strip:hover .strip-captions span { animation-play-state: paused; }
.strip-item {
  width: var(--sqm);
  height: var(--sqm);
  flex: none;
  position: relative;
  overflow: hidden;
  background: var(--paper);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.35);
  /* margin (not flex gap) keeps the loop period exact:
     15 x (module + gap) = half the doubled track */
  margin-right: var(--gap);
}
/* One clean caption line floating on the field, centred */
.strip-captions {
  position: relative;
  height: 1.8em;
  margin-top: var(--gap);
  padding: 0;
}
.strip-captions span {
  position: absolute;
  left: 50%;
  top: 0;
  transform: translateX(-50%);
  white-space: nowrap;
  opacity: 0;
  animation: cap-cycle 90s linear infinite;
  animation-delay: calc(var(--i) * 6s);
}
@keyframes cap-cycle {
  0%      { opacity: 0; transform: translate(-50%, 6px); }
  0.6%    { opacity: 1; transform: translate(-50%, 0); }
  6%      { opacity: 1; transform: translate(-50%, 0); }
  6.7%    { opacity: 0; transform: translate(-50%, -6px); }
  100%    { opacity: 0; transform: translate(-50%, -6px); }
}
@keyframes strip-drift {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
@media (hover: hover) and (pointer: fine) {
  .strip-item { transition: filter 0.12s ease; cursor: pointer; }
  .strip-item:hover { filter: invert(1); z-index: 3; }
}

/* The fifteen specimens — each a different trick of the eye */
.x-hermann { background: var(--ink); background-image:
  repeating-linear-gradient(0deg,  transparent 0 26px, var(--paper) 26px 34px),
  repeating-linear-gradient(90deg, transparent 0 26px, var(--paper) 26px 34px); }
.x-cafe { background-color: var(--mortar); background-image:
  repeating-linear-gradient(90deg, var(--ink) 0 22px, var(--paper) 22px 44px),
  repeating-linear-gradient(90deg, var(--ink) 0 22px, var(--paper) 22px 44px),
  repeating-linear-gradient(90deg, var(--ink) 0 22px, var(--paper) 22px 44px),
  repeating-linear-gradient(90deg, var(--ink) 0 22px, var(--paper) 22px 44px);
  background-size: 100% 23%; background-repeat: no-repeat;
  background-position: 0 0, 11px 33%, 22px 66%, 11px 100%; }
.x-moire::before, .x-moire::after { content: ''; position: absolute; inset: -20%;
  background: repeating-radial-gradient(circle at 50% 50%, var(--ink) 0 4px, var(--paper) 4px 9px); }
.x-moire::after { background: repeating-radial-gradient(circle at 50% 50%, var(--ink) 0 4px, transparent 4px 9px);
  mix-blend-mode: screen; animation: moire-drift 7s ease-in-out infinite; }
.x-lines { background: repeating-linear-gradient(90deg, var(--ink) 0 3px, var(--paper) 3px 12px); }
.x-lines::after { content: ''; position: absolute; inset: -12%;
  background: repeating-linear-gradient(90deg, var(--ink) 0 3px, transparent 3px 11px);
  animation: field-drift 8s ease-in-out infinite; }
.x-checker { background: conic-gradient(var(--ink) 0 90deg, var(--paper) 90deg 180deg,
  var(--ink) 180deg 270deg, var(--paper) 270deg 360deg) 0 0 / 34px 34px; }
.x-burst { background: repeating-conic-gradient(var(--ink) 0 7.5deg, var(--paper) 7.5deg 15deg); }
.x-squares { background: repeating-radial-gradient(closest-side at 50% 50%,
  var(--ink) 0 8px, var(--paper) 8px 16px); }
.x-diag { background:
  repeating-linear-gradient(45deg,  var(--ink) 0 4px, transparent 4px 14px),
  repeating-linear-gradient(-45deg, var(--ink) 0 4px, transparent 4px 14px), var(--paper); }
.x-dots { background: radial-gradient(var(--ink) 30%, transparent 33%) 0 0 / 24px 24px var(--paper); }
.x-dots::after { content: ''; position: absolute; inset: 0;
  background: radial-gradient(var(--ink) 30%, transparent 33%) 12px 12px / 24px 24px;
  animation: moire-drift 9s ease-in-out infinite; opacity: 0.65; }
.x-zollner { background:
  repeating-linear-gradient(0deg, var(--ink) 0 5px, transparent 5px 34px),
  repeating-linear-gradient(65deg, var(--ink) 0 2px, transparent 2px 12px), var(--paper); }
.x-spiral { background: repeating-conic-gradient(from 0deg, var(--ink) 0 12deg, var(--paper) 12deg 24deg); }
.x-spiral::after { content: ''; position: absolute; inset: 18%; border-radius: 50%;
  background: repeating-conic-gradient(from 8deg, var(--ink) 0 12deg, var(--paper) 12deg 24deg); }
.x-bull { background: repeating-radial-gradient(circle at 42% 50%, var(--ink) 0 6px, var(--paper) 6px 13px); }
.x-steps { background: linear-gradient(90deg,
  #131111 0 20%, #3a3634 20% 40%, #6b6560 40% 60%, #a29b94 60% 80%, #ede8e8 80% 100%); }
.x-steps::after { content: ''; position: absolute; top: 40%; bottom: 40%; left: 6%; right: 6%;
  background: #6b6560; }
.x-weave { background:
  repeating-linear-gradient(90deg, var(--ink) 0 10px, transparent 10px 30px),
  repeating-linear-gradient(0deg,  var(--ink) 0 10px, var(--paper) 10px 30px); }
.x-pulse { background: var(--ink); display: grid; place-items: center; }
.x-pulse::before { content: ''; width: 46%; aspect-ratio: 1; border-radius: 50%;
  background: var(--paper); animation: g-pulse 3.6s ease-in-out infinite; }
.x-pulse::after { content: ''; position: absolute; width: 18%; aspect-ratio: 1;
  border-radius: 50%; background: var(--ink); }

/* ============================================================
   FINDINGS — numerals rail left, statements right; the active
   numeral lights as its statement crosses the viewport.
   ============================================================ */
.card-findings { overflow: visible; }  /* the rail must stick to the page */
.findings-layout {
  display: grid;
  grid-template-columns: minmax(120px, 1fr) minmax(0, 3fr);
  gap: clamp(24px, 4vw, 90px);
  width: min(1100px, 100%);
  margin-top: clamp(24px, 4vh, 56px);
  text-align: left;
}
.fnd-rail {
  position: sticky;
  top: calc(var(--nav-h) + 10vh);
  align-self: start;
  display: flex;
  flex-direction: column;
  gap: 0.35em;
}
.fnd-num {
  font-family: var(--mono);
  font-weight: 700;
  font-size: var(--t-title-3);
  line-height: 1.1;
  color: var(--ink);
  opacity: 0.14;
  transition: opacity 0.35s ease, transform 0.35s ease;
}
.fnd-num.active {
  opacity: 1;
  transform: translateX(0.3em);
  animation: num-glitch 0.5s step-end;
}
@keyframes num-glitch {
  0%   { text-shadow: 4px 0 var(--plate-m), -4px 0 var(--plate-c); }
  30%  { text-shadow: -3px 0 var(--plate-c), 3px 0 var(--plate-m); }
  65%  { text-shadow: 2px 0 var(--plate-m), -2px 0 var(--plate-c); }
  100% { text-shadow: none; }
}
.findings-doc { max-width: none; margin-top: 0; text-align: left; }
/* Only the current statement is legible: the rest dissolve into
   an unfocused RGB cloud. The observer toggles .active; the
   transitions carry the smear in and out, the keyframe snaps the
   arrival. */
.card-findings .clause {
  margin-bottom: clamp(22px, 3.6vh, 44px);
  opacity: 0.38;
  filter: blur(3px);
  text-shadow:
    6px 0 5px rgba(214, 0, 108, 0.55),
    -6px 0 5px rgba(0, 136, 176, 0.55);
  transition: opacity 0.55s ease, filter 0.55s ease, text-shadow 0.55s ease;
}
.card-findings .clause.active {
  opacity: 1;
  filter: none;
  text-shadow: 0 0 0 rgba(214, 0, 108, 0), 0 0 0 rgba(0, 136, 176, 0);
  animation: clause-glitch 0.45s step-end;
}
@keyframes clause-glitch {
  0%   { text-shadow: 4px 0 2px rgba(214, 0, 108, 0.6), -4px 0 2px rgba(0, 136, 176, 0.6); }
  40%  { text-shadow: -3px 0 1px rgba(0, 136, 176, 0.6), 3px 0 1px rgba(214, 0, 108, 0.6); }
  75%  { text-shadow: 2px 0 0 rgba(214, 0, 108, 0.5), -2px 0 0 rgba(0, 136, 176, 0.5); }
  100% { text-shadow: 0 0 0 rgba(214, 0, 108, 0), 0 0 0 rgba(0, 136, 176, 0); }
}
.card-findings .clause:last-child { margin-bottom: clamp(30px, 8vh, 90px); }

/* ============================================================
   CORRESPONDENCE — boxless, straight on the living background
   ============================================================ */
.corr {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 10px;
  padding: clamp(90px, 16vh, 190px) 20px clamp(60px, 10vh, 130px);
}
.corr .cta-line-a { color: var(--mid-p); }
.corr .cta-line-b { color: var(--paper); border-bottom-color: var(--paper); }
/* The artwork: black spiral on its paper disc, turning as the
   piece does in exhibition */
.corr-art {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(16px, 2.6vh, 26px);
  margin-top: clamp(40px, 7vh, 90px);
}
.corr-disc {
  width: min(440px, 74vw);
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--paper);
  overflow: hidden;
  animation: corr-spin 45s linear infinite;
}
.corr-disc img {
  display: block;
  width: 100%;
  height: 100%;
}
.art-caption {
  font-family: var(--serif);
  font-size: var(--t-caption);
  letter-spacing: 0.02em;
  color: var(--mid-p);
}
.art-caption em { font-style: italic; }
@keyframes corr-spin { to { transform: rotate(360deg); } }

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width: 940px) {
  /* ── The presets retune; selectors below are layout only ── */
  :root {
    --t-display: clamp(2.5rem, 11vw, 6.4rem);
    --t-title-1: clamp(1.55rem, 5.6vw, 3.2rem);
    --t-title-2: clamp(1.35rem, 4.4vw, 2.6rem);
    --t-title-3: clamp(1.35rem, 3.4vw, 2rem);
    --t-lead:    clamp(1.15rem, 2.6vw, 1.7rem);
    --t-body:    clamp(1rem, 2.2vw, 1.1rem);
    --t-stamp:   clamp(0.78rem, 1.6vw, 0.95rem);
  }
  .nav-links { gap: clamp(10px, 1.6vw, 16px); }

  /* Touch floor for the pills */
  .cta { min-height: 44px; padding: 0.9em 1.6em; }

  /* ── Hero: poster stacks above the text; the slot keeps a real
     rect for the dock (flexes to the space the text leaves) ── */
  .hero-band {
    flex-direction: column;
    align-items: center;
    gap: 14px;
    padding-top: calc(var(--nav-h) + var(--gap));
  }
  .hero-poster-slot {
    height: auto;
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;
    aspect-ratio: auto;
  }
  .hero-unit {
    flex: 0 0 auto;
    align-items: center;
    text-align: center;
    padding-right: 0;
    padding-bottom: clamp(10px, 2svh, 22px);
    gap: 10px;
  }
  .hero-unit .hero-sub { max-width: 38ch; }
  .hero-ctas { justify-content: center; }
  .cta-note { flex-basis: 100%; text-align: center; }

  /* One column of cards */
  .cards { grid-template-columns: 1fr; }
  .card-half, .card-full { grid-column: 1; }
  .card { min-height: clamp(420px, 64svh, 560px); }

  .card-split { flex-direction: column; text-align: center; }
  .card-split .card-copy { align-items: center; }


  /* Stripe module scales down with the screen */
  .strip-track { --sqm: clamp(150px, 44vw, 240px); }

  /* Question fits the narrow column */

  /* Case page */
  .page-hero { min-height: 0; }
  .page-cards { padding-top: calc(var(--nav-h) + var(--gap)); }

  .findings-layout { grid-template-columns: 1fr; }
  .fnd-rail { position: static; flex-direction: row; flex-wrap: wrap; gap: 0.5em; }
  .card-findings .clause { margin-bottom: clamp(40px, 8vh, 80px); }
}

/* ============================================================
   THE OBSERVER STATES — five title/subtitle pairs cycling with
   the misregistration glitch. 5 x 7s = 35s cycle; each state
   holds ~5.5s and hands over through the RGB split.
   ============================================================ */
.card-states { justify-content: flex-start; }
.states {
  position: relative;
  flex: 1;
  align-self: stretch;
  min-height: clamp(230px, 34svh, 320px);
}
.state {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(10px, 1.5vh, 18px);
  text-align: center;
  opacity: 0;
  animation: state-cycle 35s linear infinite;
  animation-delay: calc(var(--s) * 7s);
}
.state .card-h2 { font-size: var(--t-title-1); }
.state .card-sub { max-width: 44ch; }

@keyframes state-cycle {
  /* arrive on the split */
  0%    { opacity: 0; text-shadow: 7px 0 var(--plate-m), -7px 0 var(--plate-c); }
  1.5%  { opacity: 1; text-shadow: 4px 0 var(--plate-m), -4px 0 var(--plate-c); }
  3%    { opacity: 1; text-shadow: -3px 0 var(--plate-c), 3px 0 var(--plate-m); }
  4.5%  { opacity: 1; text-shadow: none; }
  /* hold */
  16%   { opacity: 1; text-shadow: none; }
  /* leave through the plates */
  17.5% { opacity: 1; text-shadow: -4px 0 var(--plate-c), 4px 0 var(--plate-m); }
  19%   { opacity: 0; text-shadow: 7px 0 var(--plate-m), -7px 0 var(--plate-c); }
  100%  { opacity: 0; text-shadow: none; }
}

@media (prefers-reduced-motion: reduce) {
  .state { animation: none; opacity: 0; }
  .state[style*="--s: 0"] { opacity: 1; }
}
