/* Mirage (Espejismo) — IDFA DocLab prototype
   Drenched dark: the room of the installation. Two poles: red / white. */

@font-face {
  font-family: "Archivo";
  src: url("../fonts/archivo.woff2") format("woff2");
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
}
@font-face {
  font-family: "Martian Mono";
  src: url("../fonts/martian.woff2") format("woff2");
  font-weight: 100 800;
  font-display: swap;
}
/* Serif italics for the question. Three vendored candidates — all OFL. */
@font-face {
  font-family: "Instrument Serif";
  src: url("../fonts/instrument-serif-italic.woff2") format("woff2");
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "EB Garamond";
  src: url("../fonts/ebgaramond-italic.woff2") format("woff2");
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Playfair";
  src: url("../fonts/playfair-italic.woff2") format("woff2");
  font-style: italic;
  font-display: swap;
}

:root {
  --void: oklch(0.14 0.008 25);
  --void-deep: oklch(0.11 0.006 25);
  --surface: oklch(0.19 0.01 25);
  --line: oklch(0.32 0.012 25);
  --ink: oklch(0.96 0.004 25);
  --ink-dim: oklch(0.75 0.008 25);
  --ink-faint: oklch(0.62 0.008 25);
  --red: oklch(0.58 0.23 27);
  --red-bright: oklch(0.66 0.25 27);
  --red-dim: oklch(0.42 0.16 27);
  --white-pole: oklch(0.98 0 0);

  --font-display: "Archivo", system-ui, sans-serif;
  --font-mono: "Martian Mono", ui-monospace, monospace;
  /* Swap to "EB Garamond" or "Playfair" to change the question's voice. */
  --font-serif: "Instrument Serif", Georgia, serif;

  --z-nav: 10;
  --z-tooltip: 20;
  --z-modal: 30;

  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html { scroll-behavior: smooth; }

body {
  background: var(--void);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 1.0625rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

::selection { background: var(--red); color: var(--white-pole); }

img, video, svg, canvas { display: block; max-width: 100%; }

a { color: var(--ink); text-decoration-color: currentColor; text-underline-offset: 3px; }
a:hover { color: var(--red-bright); }

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

h1, h2, h3 { text-wrap: balance; }
p { text-wrap: pretty; }

/* ---------- nav ---------- */

.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: var(--z-nav);
  display: flex;
  align-items: center;
  gap: 2rem;
  padding: 0.85rem clamp(1.25rem, 4vw, 3rem);
  background: color-mix(in oklab, var(--void-deep) 82%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid color-mix(in oklab, var(--line) 55%, transparent);
}
.nav-mark {
  font-weight: 800;
  font-stretch: 118%;
  letter-spacing: 0.01em;
  font-size: 0.95rem;
  text-decoration: none;
  white-space: nowrap;
}
.nav-mark em { font-style: normal; color: var(--red-bright); }
.nav-links {
  display: flex;
  gap: 1.4rem;
  margin-inline: auto;
}
.nav-links a {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--ink-dim);
  text-decoration: none;
}
.nav-links a:hover { color: var(--ink); }
.nav-tag {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  color: var(--ink-faint);
  white-space: nowrap;
}
@media (max-width: 860px) {
  .nav-links { display: none; }
  .nav-tag { margin-left: auto; }
}
@media (max-width: 480px) {
  .nav-tag { max-width: 46vw; overflow: hidden; text-overflow: ellipsis; }
}

/* ---------- hero ---------- */

.hero {
  position: relative;
  min-height: 100svh;
  display: grid;
  place-content: center;
  text-align: center;
  padding: 6rem clamp(1.25rem, 5vw, 4rem) 4rem;
  overflow: hidden;
  background: radial-gradient(120% 90% at 50% 110%, oklch(0.17 0.03 27) 0%, var(--void) 55%);
}
.hero-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.hero-scrim {
  position: absolute;
  inset: 0;
  background: radial-gradient(55% 52% at 50% 50%, oklch(0.05 0.008 25 / 0.8) 0%, oklch(0.06 0.008 25 / 0.55) 40%, oklch(0.07 0.008 25 / 0.2) 68%, oklch(0.08 0.008 25 / 0) 100%);
  background-color: oklch(0.05 0.008 25 / 0.38);
}
@media (max-width: 700px) {
  .hero-scrim {
    background: radial-gradient(85% 62% at 50% 50%, oklch(0.05 0.008 25 / 0.85) 0%, oklch(0.06 0.008 25 / 0.6) 45%, oklch(0.07 0.008 25 / 0.22) 72%, oklch(0.08 0.008 25 / 0) 100%);
    background-color: oklch(0.05 0.008 25 / 0.42);
  }
}
.hero-inner {
  position: relative;
  max-width: 60rem;
  text-shadow: 0 1px 3px oklch(0 0 0 / 0.5);
}
.hero h1 {
  /* Same step as the question beat (.qb-text) — the site's largest type. The
     title and the question are the two things the site says at full scale. */
  font-size: clamp(3.1rem, 11vw, 8.6rem);
  font-weight: 800;
  font-stretch: 122%;
  line-height: 0.98;
  letter-spacing: -0.02em;
  text-transform: uppercase;
}
.hero-mirror {
  display: block;
  font-size: 0.72em;
  font-stretch: 100%;
  letter-spacing: 0.01em;
  margin-top: -0.04em;
  transform: scaleY(-1);
  /* fine grain, like desert sand / a field of data points: two tiny red
     dot grids clipped to the letterforms, drifting so they interfere */
  color: transparent;
  background-image:
    radial-gradient(circle, var(--red-bright) 26%, transparent 34%),
    radial-gradient(circle, oklch(0.48 0.18 27) 22%, transparent 30%);
  background-size: 3px 3px, 4.5px 4.5px;
  background-position: 0 0, 1px 2px;
  -webkit-background-clip: text;
  background-clip: text;
  opacity: 0.62;
  -webkit-mask-image: linear-gradient(to bottom, transparent 6%, black 88%);
  mask-image: linear-gradient(to bottom, transparent 6%, black 88%);
  filter: url(#mirage-grain);
  animation: mirage-halftone 11s linear infinite;
  text-shadow: none;
}
@keyframes mirage-halftone {
  from { background-position: 0 0, 1px 2px; }
  to   { background-position: 15px 8px, -10px 20px; }
}
.hero-es {
  margin-top: 0.9rem;
  font-family: var(--font-mono);
  font-size: clamp(0.72rem, 1.6vw, 0.85rem);
  color: var(--ink);
  letter-spacing: 0.08em;
}
.hero-lede {
  margin: 2.2rem auto 0;
  max-width: 44rem;
  font-size: clamp(1.05rem, 2vw, 1.25rem);
  line-height: 1.6;
  color: var(--ink);
}
.hero-lede strong { color: var(--ink); font-weight: 600; }
.hero-scroll {
  position: absolute;
  bottom: 1.4rem;
  left: 50%;
  translate: -50% 0;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  color: var(--ink-dim);
  letter-spacing: 0.12em;
  animation: drift-down 2.4s var(--ease-out) infinite;
}
@keyframes drift-down {
  0%, 100% { transform: translateY(0); opacity: 0.7; }
  55% { transform: translateY(7px); opacity: 1; }
}

/* ---------- shared section chrome ---------- */

.section {
  padding: clamp(4rem, 9vw, 7.5rem) clamp(1.25rem, 4vw, 3rem);
  max-width: 90rem;
  margin-inline: auto;
}
.section-head { max-width: 46rem; margin-bottom: 2.75rem; }
.fig-caption {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.06em;
  color: var(--red-bright);
  margin-bottom: 0.9rem;
}
.section-head h2 {
  font-size: clamp(1.7rem, 4vw, 2.6rem);
  font-weight: 800;
  font-stretch: 116%;
  line-height: 1.08;
  letter-spacing: -0.015em;
}
.section-head p {
  margin-top: 1.1rem;
  color: var(--ink-dim);
  max-width: 65ch;
}
.section-head p strong { color: var(--ink); font-weight: 600; }

.viz-frame {
  position: relative;
  border: 1px solid var(--line);
  background: var(--void-deep);
  border-radius: 6px;
  overflow: hidden;
}
.viz-hint {
  position: absolute;
  top: 0.8rem;
  right: 1rem;
  z-index: 2;
  font-family: var(--font-mono);
  font-size: 0.6rem;
  color: var(--ink);
  letter-spacing: 0.05em;
  pointer-events: none;
}

/* ---------- concept strip ---------- */

.concept-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 5rem);
  align-items: start;
}
.concept-grid h2 {
  font-size: clamp(1.6rem, 3.4vw, 2.3rem);
  font-weight: 800;
  font-stretch: 116%;
  line-height: 1.1;
}
.concept-grid .col p + p { margin-top: 1rem; }
.concept-grid p { color: var(--ink-dim); }
.concept-grid p strong { color: var(--ink); font-weight: 600; }
.machine-index {
  margin-top: 2rem;
  padding: 1.35rem 1.5rem;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--void-deep);
  font-family: var(--font-mono);
  letter-spacing: 0.03em;
}
.machine-index b { color: var(--red-bright); font-weight: 700; }
.mi-title {
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-faint);
  margin-bottom: 1.1rem;
}
.mi-intro {
  font-size: 0.72rem;
  letter-spacing: 0.01em;
  line-height: 1.55;
  color: var(--ink-dim);
  max-width: 60ch;
  margin-bottom: 1.4rem;
}
.mi-stats {
  display: flex;
  flex-wrap: wrap;
  margin: 0;
  gap: clamp(1.5rem, 3vw, 3rem);
}
.mi-stat {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding-right: clamp(1.5rem, 3vw, 3rem);
  border-right: 1px solid var(--line);
}
.mi-stat:last-child { border-right: none; padding-right: 0; }
.mi-stat dt, .mi-stat dd { margin: 0; }
.mi-stat dt {
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--ink-faint);
}
.mi-stat dd {
  font-size: 1.4rem;
  font-weight: 700;
  line-height: 1;
  color: var(--ink);
}
.mi-sub {
  display: block;
  margin-top: 0.35rem;
  font-size: 0.6rem;
  font-weight: 400;
  letter-spacing: 0.02em;
  color: var(--ink-dim);
}
.mi-meta {
  margin: 1.25rem 0 0;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
  font-size: 0.65rem;
  color: var(--ink-faint);
  letter-spacing: 0.02em;
}
@media (max-width: 640px) {
  .mi-stats { flex-direction: column; gap: 0.9rem; }
  .mi-stat {
    border-right: none;
    padding-right: 0;
    padding-bottom: 0.9rem;
    border-bottom: 1px solid var(--line);
  }
  .mi-stat:last-child { border-bottom: none; padding-bottom: 0; }
}
@media (max-width: 860px) {
  .concept-grid { grid-template-columns: 1fr; }
}

/* ---------- example 1: dispute graph ---------- */

#graph-svg { width: 100%; height: min(78vh, 46rem); min-height: 30rem; cursor: grab; }
#graph-svg:active { cursor: grabbing; }
.pole-label {
  font-family: var(--font-mono);
  font-weight: 700;
  letter-spacing: 0.18em;
  font-size: 0.78rem;
}
.graph-label {
  font-family: var(--font-mono);
  font-size: 0.58rem;
  letter-spacing: 0.04em;
  cursor: pointer;
  user-select: none;
}
.moment-node { cursor: pointer; }

.chipbar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  padding: 1rem 1.1rem;
  border-top: 1px solid var(--line);
  background: var(--void-deep);
}
.chipbar-title {
  font-family: var(--font-mono);
  font-size: 0.6rem;
  color: var(--ink-faint);
  letter-spacing: 0.08em;
  flex-basis: 100%;
}
.chip {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.03em;
  color: var(--ink-dim);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.32rem 0.75rem;
  cursor: pointer;
  transition: color 0.18s var(--ease-out), border-color 0.18s var(--ease-out), background 0.18s var(--ease-out);
}
.chip:hover { color: var(--ink); border-color: var(--ink-faint); }
.chip[aria-pressed="true"] {
  color: var(--void-deep);
  background: var(--red-bright);
  border-color: var(--red-bright);
  font-weight: 600;
}
.chip.emotion[aria-pressed="true"] {
  background: var(--white-pole);
  border-color: var(--white-pole);
}

/* tooltip */
.tip {
  position: fixed;
  z-index: var(--z-tooltip);
  pointer-events: none;
  width: 15rem;
  background: color-mix(in oklab, var(--void-deep) 92%, transparent);
  backdrop-filter: blur(8px);
  border: 1px solid var(--line);
  border-radius: 6px;
  overflow: hidden;
  opacity: 0;
  translate: 0 4px;
  transition: opacity 0.15s var(--ease-out), translate 0.15s var(--ease-out);
}
.tip.on { opacity: 1; translate: 0 0; }
.tip img { width: 100%; aspect-ratio: 16/9; object-fit: cover; }
.tip-body { padding: 0.6rem 0.7rem 0.7rem; }
.tip-title { font-size: 0.8rem; font-weight: 700; line-height: 1.25; }
.tip-meta {
  margin-top: 0.35rem;
  font-family: var(--font-mono);
  font-size: 0.58rem;
  color: var(--ink-dim);
  letter-spacing: 0.03em;
}
.tip-meta .v { color: var(--red-bright); font-weight: 700; }
.tip-meta .nv { color: var(--white-pole); font-weight: 700; }

/* ---------- example 2: latent 3d ---------- */

#latent-canvas { width: 100%; height: min(80vh, 48rem); min-height: 30rem; cursor: grab; touch-action: none; }
#latent-canvas:active { cursor: grabbing; }
.latent-tag {
  position: absolute;
  z-index: 2;
  pointer-events: none;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  color: var(--ink);
  background: color-mix(in oklab, var(--void-deep) 88%, transparent);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 0.3rem 0.55rem;
  opacity: 0;
  transition: opacity 0.12s;
  white-space: nowrap;
}

/* ---------- example 3: spectrum ---------- */

.spectrum-wrap { position: relative; }
.spectrum-scale {
  display: flex;
  justify-content: space-between;
  gap: 0.8rem;
  padding: 0.9rem 1.1rem 0;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  color: var(--ink);
}
.spectrum-scale .end-nv { color: var(--ink); font-weight: 700; white-space: nowrap; }
.spectrum-scale .end-v { color: var(--red-bright); font-weight: 700; white-space: nowrap; }
.spec-readout { color: var(--ink-dim); text-align: center; }
/* The stage holds three layers: the scrolling viewport, the ruler, and the cut. Only the
   track inside the viewport zooms — the frame never changes size, and the chrome above it
   stays at a constant, legible, grabbable size at every zoom level. */
.spec-stage {
  position: relative;
  display: grid;
  grid-template-rows: 1fr auto;
  overflow: hidden;
}
.spectrum {
  block-size: clamp(260px, 50vh, 520px);
  overflow: auto;
  scrollbar-gutter: stable; /* so the frame doesn't reflow when zoom crosses the fit point */
  display: grid;
  place-content: safe center;
  user-select: none;
  touch-action: pan-x pan-y; /* the browser owns touch panning; JS only pans with a mouse */
  scrollbar-width: thin;
  scrollbar-color: var(--red-dim) transparent;
}
/* only claim it is draggable when there is somewhere to drag it to */
.spectrum.is-pannable { cursor: grab; }
.spectrum.is-pannable:active { cursor: grabbing; }
.spec-track {
  --col-w: 5.6rem;
  --cut-pct: 45%;
  zoom: var(--z, 1);
  display: flex;
  align-items: stretch;
  gap: 3px;
  padding: 1.6rem 1.1rem;
  /* the pole wash is anchored to the cut, so the two screens read as two */
  background:
    linear-gradient(90deg,
      color-mix(in oklab, var(--white-pole) 9%, transparent) 0%,
      transparent calc(var(--cut-pct) - 14%),
      transparent var(--cut-pct),
      color-mix(in oklab, var(--red) 9%, transparent) calc(var(--cut-pct) + 5%),
      color-mix(in oklab, var(--red) 20%, transparent) 100%);
}
.spec-bin {
  flex: 0 0 var(--col-w);
  display: grid;
  grid-template-rows: 1fr auto; /* stack, then the ruler tick */
}
.spec-stack {
  display: flex;
  flex-direction: column-reverse; /* lowest score sits lowest */
  justify-content: center;        /* the ridge: mass grows out from a centre line */
  gap: 3px;
}
.spec-thumb {
  position: relative;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  border-radius: 3px;
  line-height: 0;
}
.spec-thumb img {
  width: 100%;
  aspect-ratio: 16/9;
  object-fit: cover;
  border-radius: 3px;
  filter: saturate(0.85);
  -webkit-user-drag: none;
  user-select: none;
  transition: filter 0.2s var(--ease-out), transform 0.2s var(--ease-out);
}
.spec-thumb:hover img { filter: saturate(1.15); transform: scale(1.05); }
.spec-thumb:focus-visible { outline: none; }
.spec-thumb:focus-visible img {
  filter: saturate(1.15);
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}
.spec-thumb.sel img { filter: saturate(1.2); transform: scale(1.08); }
/* verdict is encoded by line style as well as colour: solid = violent, dashed = peaceful */
.spec-thumb.sel[data-verdict="violent"] img { outline: 2px solid var(--red-bright); outline-offset: 1px; }
.spec-thumb.sel[data-verdict="not-violent"] img { outline: 2px dashed var(--white-pole); outline-offset: 1px; }

/* moments the visitor's cut has re-judged, against the machine */
.spec-thumb[data-rejudged] img { filter: saturate(1); }
.spec-thumb[data-rejudged="violent"] img { outline: 1px solid var(--red-bright); }
.spec-thumb[data-rejudged="not-violent"] img { outline: 1px dashed var(--white-pole); }
.spec-thumb[data-mark]::before {
  content: attr(data-mark);
  position: absolute;
  top: 2px;
  left: 2px;
  z-index: 1;
  padding: 0 2px;
  border-radius: 2px;
  font-family: var(--font-mono);
  font-size: 0.5rem;
  line-height: 1.4;
  color: var(--ink);
  background: color-mix(in oklab, var(--void-deep) 78%, transparent);
}
.spec-thumb.sel::after {
  content: "CLICK ×2 — PLAY";
  position: absolute;
  left: 50%;
  top: -1.35rem;
  translate: -50% 0;
  font-family: var(--font-mono);
  font-size: 0.52rem;
  letter-spacing: 0.06em;
  color: var(--ink);
  white-space: nowrap;
  line-height: 1;
}
/* the ruler is chrome: outside the zoomed track, so it never shrinks into illegibility */
.spec-ruler {
  position: relative;
  block-size: 1.6rem;
  border-top: 1px solid var(--line);
}
.spec-ruler i {
  position: absolute;
  top: 0;
  inline-size: 1px;
  block-size: 0.3rem;
  background: var(--line);
}
.spec-ruler span {
  position: absolute;
  top: 0.45rem;
  translate: -50% 0;
  font-family: var(--font-mono);
  font-size: 0.55rem;
  color: var(--ink-faint);
  white-space: nowrap;
}
/* The cut: a real control, not a rule. It sits in the stage layer at constant size, so it
   stays grabbable however far the archive is zoomed out. Dragging it re-splits the archive. */
.spec-cut {
  position: absolute;
  top: 0;
  bottom: 0;
  inline-size: 2px;
  z-index: 2;
  background: var(--red-bright);
  border-radius: 1px;
  cursor: ew-resize;
  touch-action: none;
}
.spec-cut::before { /* a 28px grab target around a 2px line */
  content: "";
  position: absolute;
  inset: 0 -0.85rem;
}
.spec-cut::after { /* the handle */
  content: "⇄";
  position: absolute;
  top: 0.3rem;
  left: 50%;
  translate: -50% 0;
  display: grid;
  place-items: center;
  inline-size: 1.3rem;
  block-size: 1.3rem;
  border-radius: 3px;
  background: var(--red-bright);
  color: var(--void-deep);
  font-family: var(--font-mono);
  font-size: 0.62rem;
  line-height: 1;
}
.spec-cut:hover::after, .spec-cut:focus-visible::after { background: var(--ink); }
.spec-cut:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }
.spec-cut.dragging, .spec-cut.dragging::after { background: var(--ink); }
.spec-cut-label {
  position: absolute;
  top: 2rem;
  left: 0.5rem;
  writing-mode: vertical-rl;
  font-family: var(--font-mono);
  font-size: 0.52rem;
  letter-spacing: 0.14em;
  color: var(--red-bright);
  white-space: nowrap;
  pointer-events: none;
}

/* the bar under the strip: hint, live cost of the cut, reset, zoom */
.spec-bar {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  flex-wrap: wrap;
  padding: 0.5rem 1.1rem 0.6rem;
  border-top: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.05em;
}
.spec-bar .viz-hint { position: static; margin-right: auto; color: var(--ink-faint); }
.spec-rejudged { color: var(--red-bright); white-space: nowrap; }
.spec-reset {
  font: inherit;
  letter-spacing: inherit;
  color: var(--ink-dim);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 0.34rem 0.6rem;
  cursor: pointer;
}
.spec-reset:hover { color: var(--ink); background: var(--surface); }
.spec-reset[hidden] { display: none; }

/* ---------- example 4: the montage engine ---------- */

.render-grid {
  display: grid;
  grid-template-columns: 1fr 24rem;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  align-items: start;
}
.render-stage {
  position: relative;
  aspect-ratio: 16 / 9;
  background: #000;
  overflow: hidden;
}
.render-v {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  visibility: hidden;
}
.render-idle {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  color: var(--ink-faint);
  text-align: center;
  padding: 1.5rem;
  /* the two poles, heavily darkened — never an empty black box */
  background:
    linear-gradient(90deg,
      color-mix(in oklab, var(--white-pole) 6%, transparent) 0%,
      transparent 40%,
      transparent 60%,
      color-mix(in oklab, var(--red) 14%, transparent) 100%);
}
.render-idle-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  max-width: 26rem;
}
.render-idle-title {
  display: block;
  letter-spacing: 0.14em;
  color: var(--ink-muted);
  text-transform: uppercase;
}
.render-idle-sub {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.03em;
  line-height: 1.55;
  color: var(--ink-faint);
  text-transform: none;
  margin: 0;
}
.render-idle[hidden] { display: none; }
.render-edl {
  position: absolute;
  inset: 0;
  padding: 1rem 1.2rem;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  overflow: hidden;
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.08em;
  color: var(--ink);
  background: color-mix(in oklab, var(--void-deep) 55%, transparent);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.25s var(--ease-out);
}
.render-edl.on { opacity: 1; }
.render-edl span {
  opacity: 0;
  translate: 0 6px;
  transition: opacity 0.3s var(--ease-out), translate 0.3s var(--ease-out);
}
.render-edl.on span { opacity: 1; translate: 0 0; }
.render-progress {
  height: 3px;
  background: var(--surface);
}
.render-progress i {
  display: block;
  height: 100%;
  background: var(--red-bright);
  transform: scaleX(0);
  transform-origin: left;
}
.render-bar { row-gap: 0.5rem; }
.render-side {
  display: flex;
  gap: 2px;
}
.render-side button {
  font: inherit;
  letter-spacing: inherit;
  padding: 0.34rem 0.7rem;
  cursor: pointer;
  border-radius: 4px;
  background: transparent;
  color: var(--ink-dim);
  border: 1px solid var(--line);
}
/* selection also differs by border style, not colour alone */
.render-side button[aria-pressed="true"] { border-style: double; font-weight: 700; }
#rnd-nonviolent[aria-pressed="true"] {
  background: var(--white-pole);
  color: var(--void-deep);
  border-color: var(--white-pole);
}
#rnd-violent[aria-pressed="true"] {
  background: var(--red-bright);
  color: var(--void-deep);
  border-color: var(--red-bright);
}
.render-go {
  font: inherit;
  letter-spacing: inherit;
  font-weight: 700;
  padding: 0.34rem 0.9rem;
  cursor: pointer;
  border-radius: 4px;
  background: transparent;
  color: var(--red-bright);
  border: 1px solid var(--red-bright);
}
.render-go:hover, .render-go:focus-visible {
  background: var(--red-bright);
  color: var(--void-deep);
}
.render-go[disabled] {
  color: var(--ink-faint);
  border-color: var(--line);
  cursor: default;
  background: transparent;
}
.render-status { color: var(--ink-dim); }
.render-shot { margin-left: auto; color: var(--ink-faint); white-space: nowrap; }
#rnd-mute.is-muted { color: var(--red-bright); }
.render-grid {
  display: grid;
  grid-template-columns: 1fr 24rem;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  align-items: start;
}
.render-how { max-width: 60ch; }
.render-how .mi-title {
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  color: var(--ink-dim);
  margin-bottom: 0.9rem;
}
.render-steps {
  margin: 1rem 0 1.4rem;
  padding-left: 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  font-size: 0.92rem;
  line-height: 1.5;
  color: oklch(0.84 0.006 25);
}
.render-steps strong { color: var(--ink); font-weight: 700; letter-spacing: 0.03em; }
.render-how .mi-meta {
  margin: 1.4rem 0 0;
  padding-top: 1.1rem;
  border-top: 1px solid var(--line);
  font-size: 0.88rem;
  line-height: 1.6;
  color: oklch(0.82 0.006 25);
  letter-spacing: 0.015em;
}

@media (max-width: 900px) {
  .render-grid { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
  .render-edl, .render-edl span { transition: none; }
}

/* the plunger */
.charge-btn {
  position: absolute;
  top: 0.65rem;
  left: 1rem;
  z-index: 2;
  overflow: hidden;
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.05em;
  color: var(--ink);
  background: color-mix(in oklab, var(--void-deep) 80%, transparent);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 0.5rem 0.85rem;
  cursor: pointer;
  touch-action: none;
  user-select: none;
}
.charge-btn:hover { color: var(--ink); border-color: var(--ink-faint); }
.charge-btn span { position: relative; }
.charge-btn i {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0%;
  background: color-mix(in oklab, var(--red) 45%, transparent);
  transition: width 0.05s linear;
}
@media (max-width: 640px) {
  /* on narrow frames the hint and the charge button (both corner overlays
     sized to their own text) collide with each other and with the graph's
     floating labels — stack them in flow above/below the graph instead */
  #dispute-viz > .viz-hint {
    position: static;
    display: block;
    padding: 0.9rem 1.2rem 0;
  }
  #dispute-viz > .charge-btn {
    position: static;
    margin: 0.8rem 1.2rem 0;
  }
}

/* ---------- method ---------- */

.method ol {
  counter-reset: step;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 1px;
  border: 1px solid var(--line);
  border-radius: 6px;
  overflow: hidden;
  background: var(--line);
}
.method li {
  counter-increment: step;
  background: var(--void-deep);
  padding: 1.6rem 1.4rem 1.8rem;
}
.method li::before {
  content: counter(step, decimal-leading-zero);
  display: block;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--red-bright);
  margin-bottom: 0.9rem;
}
.method h3 { font-size: 1.02rem; font-weight: 700; margin-bottom: 0.5rem; }
.method li p { font-size: 0.9rem; color: var(--ink-dim); line-height: 1.55; }
.method-note {
  margin-top: 2rem;
  max-width: 62ch;
  font-size: 0.92rem;
  color: var(--ink-dim);
}
.method-note strong { color: var(--ink); }

/* ---------- footer ---------- */

.footer {
  border-top: 1px solid var(--line);
  padding: 3rem clamp(1.25rem, 4vw, 3rem) 4rem;
  background: var(--void-deep);
}
.footer-grid {
  max-width: 90rem;
  margin-inline: auto;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 2rem;
  font-size: 0.88rem;
  color: var(--ink-dim);
}
.footer h3 {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  color: var(--ink-faint);
  margin-bottom: 0.7rem;
}
.footer p { line-height: 1.7; }
.footer a { color: var(--ink-dim); }
.footer a:hover { color: var(--red-bright); }
.footer-mark {
  max-width: 90rem;
  margin: 3rem auto 0;
  font-family: var(--font-mono);
  font-size: 0.6rem;
  color: var(--ink-faint);
  letter-spacing: 0.05em;
}

/* ---------- film card dialog ---------- */

dialog.filmcard {
  z-index: var(--z-modal);
  position: fixed;
  inset: 0;
  margin: auto; /* the global reset kills the UA centering; restore it */
  width: min(64rem, calc(100vw - 2rem));
  height: fit-content;
  max-height: calc(100dvh - 3rem);
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--void-deep);
  color: var(--ink);
  padding: 0;
  overflow: hidden;
  box-shadow: 0 30px 90px oklch(0.03 0.01 25 / 0.55);
}
dialog.filmcard::backdrop {
  background: oklch(0.06 0.01 25 / 0.45);
  backdrop-filter: blur(2.5px);
}
.fc-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
}
.fc-media { background: black; align-self: stretch; display: grid; }
.fc-media video { width: 100%; height: 100%; object-fit: contain; aspect-ratio: 16/9; }
.fc-media iframe { width: 100%; height: 100%; aspect-ratio: 16/9; border: 0; }
.fc-media img.fc-fallback { width: 100%; height: 100%; object-fit: cover; aspect-ratio: 16/9; }
.fc-body { padding: 1.5rem 1.5rem 1.6rem; display: flex; flex-direction: column; gap: 0.95rem; min-width: 0; }
.fc-close {
  position: absolute;
  top: 0.7rem;
  right: 0.7rem;
  width: 2.1rem;
  height: 2.1rem;
  display: grid;
  place-items: center;
  background: color-mix(in oklab, var(--void-deep) 75%, transparent);
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--ink);
  font-size: 1rem;
  cursor: pointer;
}
.fc-close:hover { border-color: var(--red-bright); color: var(--red-bright); }

dialog.lightbox {
  position: fixed;
  inset: 0;
  margin: auto;
  width: fit-content;
  height: fit-content;
  max-width: calc(100vw - 3rem);
  max-height: calc(100dvh - 3rem);
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--void-deep);
  padding: 0;
  overflow: hidden;
  box-shadow: 0 30px 90px oklch(0.03 0.01 25 / 0.55);
}
dialog.lightbox::backdrop {
  background: oklch(0.06 0.01 25 / 0.7);
  backdrop-filter: blur(2.5px);
}
dialog.lightbox img {
  display: block;
  max-width: calc(100vw - 3rem);
  max-height: calc(100dvh - 3rem);
}
[data-lightbox] { cursor: zoom-in; }
.lightbox-arrow {
  position: absolute;
  top: 50%;
  translate: 0 -50%;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: color-mix(in oklab, var(--void-deep) 70%, transparent);
  color: var(--ink);
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
  transition: border-color 0.2s var(--ease-out), color 0.2s var(--ease-out);
}
.lightbox-arrow:hover { border-color: var(--red); color: var(--red); }
.lightbox-arrow.prev { left: 0.8rem; }
.lightbox-arrow.next { right: 0.8rem; }
.lightbox-arrow[hidden] { display: none; }
.fc-title { font-size: 1.35rem; font-weight: 800; font-stretch: 112%; line-height: 1.15; }
.fc-byline { font-family: var(--font-mono); font-size: 0.6rem; color: var(--ink-faint); letter-spacing: 0.04em; margin-top: 0.35rem; }
.fc-verdict {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.06em;
}
.fc-verdict .badge {
  padding: 0.28rem 0.65rem;
  border-radius: 3px;
  font-weight: 700;
}
.fc-verdict .badge.violent { background: var(--red); color: var(--white-pole); }
.fc-verdict .badge.not-violent { background: var(--white-pole); color: var(--void-deep); }
.fc-meter { flex: 1; height: 4px; border-radius: 2px; background: var(--surface); overflow: hidden; }
.fc-meter i {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--red-dim), var(--red-bright));
  transition: width 0.5s var(--ease-out);
}
.fc-score { color: var(--ink-dim); }
.fc-chips { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.fc-chips .chip { cursor: default; }
.fc-chips .chip.cult { color: var(--red-bright); border-color: var(--red-dim); }
.fc-chips .chip.emo { color: var(--ink-dim); }
.fc-desc {
  font-size: 0.86rem;
  color: var(--ink-dim);
  line-height: 1.6;
  max-height: 9.5rem;
  overflow-y: auto;
}
.fc-actions { margin-top: auto; display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: center; }
.btn {
  font-family: var(--font-mono);
  font-size: 0.64rem;
  letter-spacing: 0.05em;
  padding: 0.55rem 0.95rem;
  border-radius: 4px;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  text-decoration: none;
  transition: border-color 0.18s, color 0.18s, background 0.18s;
}
.btn:hover { border-color: var(--red-bright); color: var(--red-bright); }
.btn.primary { background: var(--red); border-color: var(--red); color: var(--white-pole); font-weight: 600; }
.btn.primary:hover { background: var(--red-bright); border-color: var(--red-bright); color: var(--white-pole); }
.fc-dispute-note {
  font-family: var(--font-mono);
  font-size: 0.58rem;
  color: var(--ink-faint);
  line-height: 1.7;
}
@media (max-width: 780px) {
  .fc-grid { grid-template-columns: 1fr; }
  .fc-desc { max-height: 6rem; }
}

/* ---------- reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .hero-scroll { animation: none; }
  .hero-mirror { animation: none; filter: none; }
  .hero-video { display: none; }
  * { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}

/* ---------- spectrum zoom controls ---------- */

.zoom-ctl {
  position: absolute;
  right: 1rem;
  bottom: 1rem;
  z-index: 2;
  display: flex;
  gap: 2px;
  border: 1px solid var(--line);
  border-radius: 4px;
  overflow: hidden;
  background: color-mix(in oklab, var(--void-deep) 85%, transparent);
}
.zoom-ctl button {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  color: var(--ink-dim);
  background: transparent;
  border: none;
  padding: 0.42rem 0.7rem;
  cursor: pointer;
}
.zoom-ctl button:hover { color: var(--ink); background: var(--surface); }
/* the spectrum's controls live in .spec-bar, not on top of the ticks they'd obscure */
.zoom-ctl-inline { position: static; right: auto; bottom: auto; }

/* ---------- spectrum: narrow viewports ---------- */

@media (max-width: 900px) {
  .spec-track { --col-w: 4.4rem; }
}
@media (max-width: 720px) {
  .spectrum-scale { flex-wrap: wrap; justify-content: center; letter-spacing: 0.08em; }
  .spec-readout { order: 3; flex-basis: 100%; text-align: center; }
  .spec-bar { font-size: 0.56rem; }
  .spec-bar .viz-hint { flex-basis: 100%; margin-right: 0; }
}
@media (max-width: 600px) {
  .spec-track { --col-w: 3.4rem; padding: 1.4rem 0.7rem; }
  .spectrum-scale { font-size: 0.56rem; padding: 0.8rem 0.7rem 0; }
}

@media (prefers-reduced-motion: reduce) {
  .spec-thumb:hover img,
  .spec-thumb:focus-visible img,
  .spec-thumb.sel img { transform: none; }
}

/* ---------- fig 4: the room ---------- */

.room-stage {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
}
.room-floor {
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg,
    color-mix(in oklab, var(--red) 13%, transparent) 0%,
    transparent 42%,
    transparent 58%,
    color-mix(in oklab, var(--white-pole) 9%, transparent) 100%);
}
.room-svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.room-wall { fill: none; stroke: var(--line); stroke-width: 2.5; }
.room-trace { fill: none; stroke-width: 2.5; stroke-dasharray: 10 14; }
.room-trace.red { stroke: var(--red-bright); opacity: 0.75; animation: trace-run 1.1s linear infinite; }
.room-trace.white { stroke: var(--white-pole); opacity: 0.6; animation: trace-run 1.1s linear infinite; }
@keyframes trace-run { to { stroke-dashoffset: -24; } }
.room-pod { cursor: pointer; }
.room-pod ellipse {
  fill: var(--surface);
  stroke: var(--ink-faint);
  stroke-width: 1.5;
  transition: stroke 0.2s, fill 0.2s;
}
.room-pod:hover ellipse, .room-pod:focus-visible ellipse { stroke: var(--ink); fill: oklch(0.24 0.012 25); }
.room-sign {
  fill: var(--ink-dim);
  font-family: var(--font-mono);
  font-size: 26px;
  letter-spacing: 0.5em;
}
.room-sign-mirror {
  transform-box: fill-box;
  transform-origin: center;
  transform: scaleY(-1);
  font-size: 22px;
  letter-spacing: 0.42em;
  fill: var(--red-bright);
  opacity: 0.75;
  filter: url(#mirage-grain-sm);
  -webkit-mask-image: linear-gradient(to top, transparent 3%, black 78%);
  mask-image: linear-gradient(to top, transparent 3%, black 78%);
}
@media (prefers-reduced-motion: reduce) {
  .room-sign-mirror { filter: none; }
}

.room-screen, .room-tablet, .room-table {
  position: absolute;
  cursor: pointer;
  transition: opacity 0.25s var(--ease-out);
}
#room-diagram.focus [data-caption]:not(.hot) { opacity: 0.4; }

.room-screen { width: 8.75%; height: 46.7%; top: 25.5%; margin: 0; display: grid; }
.room-screen img {
  grid-area: 1 / 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 3px;
  opacity: 0;
  transition: opacity 1.1s var(--ease-out);
}
.room-screen img.on { opacity: 1; }
.room-screen.violent {
  left: 6.9%;
  box-shadow: 0 0 30px 4px color-mix(in oklab, var(--red) 55%, transparent);
  animation: pulse-red 3.2s ease-in-out infinite;
}
.room-screen.calm {
  left: 84.4%;
  box-shadow: 0 0 30px 4px color-mix(in oklab, var(--white-pole) 35%, transparent);
  animation: pulse-white 3.8s ease-in-out infinite;
}
@keyframes pulse-red {
  50% { box-shadow: 0 0 46px 9px color-mix(in oklab, var(--red) 70%, transparent); }
}
@keyframes pulse-white {
  50% { box-shadow: 0 0 42px 8px color-mix(in oklab, var(--white-pole) 48%, transparent); }
}

.room-table {
  left: 50%;
  top: 55.5%;
  width: 10.5%;
  aspect-ratio: 1;
  translate: -50% -50%;
}
.room-table i {
  display: block;
  width: 100%;
  height: 100%;
  rotate: 45deg;
  background: var(--surface);
  border: 1.5px solid var(--ink-faint);
  box-shadow: 0 0 26px 3px color-mix(in oklab, var(--white-pole) 22%, transparent);
}

.room-tablet { width: 9.4%; margin: 0; translate: -50% -50%; display: grid; }
.room-tablet img {
  grid-area: 1 / 1;
  width: 100%;
  aspect-ratio: 16/9;
  object-fit: cover;
  border-radius: 2px;
  border: 1px solid var(--line);
  opacity: 0;
  transition: opacity 1.1s var(--ease-out);
}
.room-tablet img.on { opacity: 1; }
.room-tablet figcaption { grid-area: 2 / 1; }
.room-tablet.t1 { left: 50%; top: 36.5%; }
.room-tablet.t2 { left: 60.5%; top: 55.5%; }
.room-tablet.t3 { left: 50%; top: 74.5%; }
.room-tablet.t4 { left: 39.5%; top: 55.5%; }
.room-tablet figcaption {
  margin-top: 0.3rem;
  font-family: var(--font-mono);
  font-size: clamp(0.42rem, 0.65vw, 0.6rem);
  line-height: 1.4;
  color: var(--ink-faint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.room-tablet figcaption .v { color: var(--red-bright); }
.room-tablet figcaption .nv { color: var(--ink); }

.room-sketch-overlay {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  pointer-events: none;
}
.room-sketch-ctl {
  position: absolute;
  left: 1rem;
  bottom: 1rem;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.6rem;
  border-radius: 4px;
  border: 1px solid var(--line);
  background: color-mix(in oklab, var(--void-deep) 85%, transparent);
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.05em;
  color: var(--ink);
}
.room-sketch-ctl input[type="range"] {
  width: 64px;
  height: 1px;
  appearance: none;
  background: var(--line);
}
.room-sketch-ctl input[type="range"]::-webkit-slider-thumb {
  appearance: none;
  width: 10px;
  height: 10px;
  rotate: 45deg;
  background: var(--red-bright);
  border: 1.5px solid var(--red-bright);
  cursor: pointer;
  box-shadow: 0 0 6px color-mix(in oklab, var(--red-bright) 60%, transparent);
}
.room-sketch-ctl input[type="range"]::-moz-range-thumb {
  width: 10px;
  height: 10px;
  rotate: 45deg;
  background: var(--red-bright);
  border: 1.5px solid var(--red-bright);
  cursor: pointer;
  border-radius: 0;
  box-shadow: 0 0 6px color-mix(in oklab, var(--red-bright) 60%, transparent);
}
.room-sketch-ctl input[type="range"]:hover::-webkit-slider-thumb,
.room-sketch-ctl input[type="range"]:focus-visible::-webkit-slider-thumb {
  background: var(--white-pole);
  border-color: var(--white-pole);
}

.room-captionbar {
  border-top: 1px solid var(--line);
  padding: 0.85rem 1.1rem;
  font-family: var(--font-mono);
  font-size: 0.64rem;
  letter-spacing: 0.05em;
  color: var(--ink);
  min-height: 2.6rem;
}

@media (prefers-reduced-motion: reduce) {
  .room-trace.red, .room-trace.white, .room-screen.violent, .room-screen.calm { animation: none; }
}
@media (max-width: 640px) {
  /* the room's aspect-ratio box shrinks in height along with its width, but
     this hint's text doesn't — on narrow frames it wraps and collides with
     the MIRAGE sign inside the SVG, which scales down right along with it */
  #room > .viz-hint {
    position: static;
    display: block;
    padding: 0.9rem 1.1rem;
  }
}

/* ============================================================
   v2 narrative rebuild — S0-S7 sections, placeholders, logos
   ============================================================ */
.ph{position:relative;display:flex;align-items:center;justify-content:center;
  min-height:200px;border:1px dashed var(--line);border-radius:2px;
  background:repeating-linear-gradient(45deg,transparent 0 12px,var(--surface) 12px 24px);
  color:var(--ink-faint);font-family:var(--font-mono);font-size:.68rem;
  letter-spacing:.06em;text-transform:uppercase;text-align:center;padding:1.4rem;}
.ph[data-ar="16:9"]{aspect-ratio:16/9;min-height:0;}
.ph[data-ar="4:3"]{aspect-ratio:4/3;min-height:0;}
.ph::before{content:"▨ " attr(data-slot);position:absolute;top:.5rem;left:.6rem;
  color:var(--ink-faint);opacity:.7;font-size:.6rem;}
.ph.is-media{background:none;overflow:hidden;border-style:solid;}
.ph.is-media video,.ph.is-media img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block;cursor:pointer;}
.ph.is-media::before{content:none;}
.ph-grid{display:grid;gap:12px;margin-top:12px;}
.ph-grid.cols-2{grid-template-columns:repeat(2,1fr);}
.ph-grid.cols-3{grid-template-columns:repeat(3,1fr);}
.experience-renders{margin:1.6rem 0 2rem;}
@media(max-width:760px){.ph-grid.cols-2,.ph-grid.cols-3{grid-template-columns:1fr;}}

/* ---------- experience beats (S2) ---------- */
.experience-beats{counter-reset:xbeat;list-style:none;display:flex;flex-direction:column;gap:1.8rem;margin:1.6rem 0 1.6rem;}
.experience-beats li{counter-increment:xbeat;display:grid;grid-template-columns:1.1fr 1fr;gap:1.8rem;align-items:start;}
.experience-beats li:nth-child(even) .beat-fig{order:-1;}
.experience-beats .beat-num{display:block;font-family:var(--font-mono);font-size:.68rem;font-weight:700;
  letter-spacing:.08em;text-transform:uppercase;color:var(--red-bright);margin-bottom:.6rem;}
.experience-beats .beat-num::before{content:counter(xbeat,decimal-leading-zero) " — ";}
.experience-beats h3{font-size:1.08rem;font-weight:700;margin-bottom:.5rem;}
.experience-beats li p{font-size:.92rem;color:var(--ink-dim);line-height:1.6;}
.experience-beats .beat-fig{min-height:0;}
@media(max-width:760px){
  .experience-beats li{grid-template-columns:1fr;}
  .experience-beats li:nth-child(even) .beat-fig{order:0;}
}

/* the annotation carousel runs full width, so the shared 1.8rem flex gap reads
   as cramped under its dot bar — give beat 03 extra air */
.experience-beats li.beat-annotation{grid-template-columns:1fr;margin-bottom:2.8rem;}

.tablet-viz{max-width:640px;margin:1.8rem auto 0;}
.tablet-slider-stage{position:relative;overflow:hidden;aspect-ratio:16/9;background:var(--surface);}
.tablet-slider-track{display:flex;height:100%;transition:transform .45s var(--ease-out);}
.tablet-slide{flex:0 0 100%;width:100%;height:100%;margin:0;}
.tablet-slide img{display:block;width:100%;height:100%;object-fit:contain;background:var(--void-deep);}
.tablet-slider-arrow{position:absolute;top:50%;translate:0 -50%;width:34px;height:34px;
  display:flex;align-items:center;justify-content:center;border:1px solid var(--line);border-radius:50%;
  background:color-mix(in oklab, var(--void-deep) 70%, transparent);color:var(--ink-dim);
  font-size:1.1rem;line-height:1;cursor:pointer;
  transition:border-color .2s var(--ease-out),color .2s var(--ease-out);}
.tablet-slider-arrow:hover{border-color:var(--red);color:var(--red);}
.tablet-slider-arrow.prev{left:.7rem;}
.tablet-slider-arrow.next{right:.7rem;}
.tablet-slider-bar{display:flex;align-items:center;justify-content:space-between;gap:1rem;
  background:var(--ink);padding:.85rem 1.1rem;min-height:2.6rem;}
#tablet-slider-caption{font-family:var(--font-mono);font-size:.64rem;letter-spacing:.05em;
  font-weight:700;color:var(--void-deep);}
.tablet-slider-dots{display:flex;gap:.5rem;flex:0 0 auto;}
.tablet-slider-dot{width:7px;height:7px;border-radius:50%;border:1px solid var(--void-deep);
  background:none;padding:0;cursor:pointer;}
.tablet-slider-dot:hover{border-color:var(--red-dim);}
.tablet-slider-dot.is-active{background:var(--red-bright);border-color:var(--red-bright);}

/* ---- S0b · fragments ------------------------------------------------- */
.fragments{max-width:1180px;margin-inline:auto;}
/* The invitation and the question are the same voice: this is set in the same
   italic serif as "Is this violent?", one register down, so the beat further on
   reads as that voice finally raising itself. Centred on a short measure so it
   lands as a title card over the player rather than as body copy — everything
   below it (controls, strip, credit) stays left-aligned, and that is the
   contrast that separates the invitation from the machine. */
.fragments-lede{font-family:var(--font-serif);
  /* The vendored serif is an italic-only face — without this the line falls
     back to Georgia and jumps family mid-page. Same constraint as .qb-text. */
  font-style:italic;
  color:var(--ink-dim);
  font-size:clamp(1.25rem,2.1vw,1.6rem);line-height:1.5;
  max-width:52ch;margin:0 auto 2.4rem;
  text-align:center;text-wrap:balance;}

.frag-stage{position:relative;background:#000;aspect-ratio:16/9;overflow:hidden;}
.frag-stage video{width:100%;height:100%;display:block;object-fit:contain;cursor:pointer;}

.frag-bar{height:3px;background:var(--surface);margin-top:6px;cursor:pointer;}
.frag-bar i{display:block;height:100%;background:var(--red);
  transform:scaleX(0);transform-origin:left;}

.frag-controls{display:flex;align-items:center;gap:1rem;margin-top:.7rem;
  font-family:var(--font-mono);font-size:.62rem;letter-spacing:.12em;
  color:var(--ink-faint);text-transform:uppercase;}
.frag-btn{background:none;border:1px solid var(--line);color:var(--ink-dim);
  width:30px;height:26px;cursor:pointer;font-size:.7rem;line-height:1;
  transition:border-color .2s var(--ease-out),color .2s var(--ease-out);}
.frag-btn:hover{border-color:var(--red);color:var(--red);}
.frag-btn-icon{display:inline-flex;align-items:center;justify-content:center;}
.frag-count{margin-left:auto;}

.frag-striprow{display:flex;align-items:stretch;gap:8px;margin-top:1.4rem;}
.frag-arrow{flex:0 0 auto;width:26px;background:none;border:1px solid var(--line);
  color:var(--ink-faint);cursor:pointer;font-size:.9rem;
  transition:border-color .2s var(--ease-out),color .2s var(--ease-out);}
.frag-arrow:hover{border-color:var(--red);color:var(--red);}

.frag-strip{flex:1 1 auto;display:flex;gap:10px;overflow-x:auto;
  scroll-snap-type:x mandatory;scrollbar-width:thin;
  scrollbar-color:var(--line) transparent;padding-bottom:6px;}
.frag-strip::-webkit-scrollbar{height:5px;}
.frag-strip::-webkit-scrollbar-thumb{background:var(--line);}

.frag-item{flex:0 0 calc((100% - 30px)/4);scroll-snap-align:start;
  background:none;border:1px solid transparent;padding:0;cursor:pointer;
  text-align:left;color:inherit;font:inherit;
  transition:border-color .2s var(--ease-out);}
.frag-item img{width:100%;aspect-ratio:16/9;object-fit:cover;display:block;
  opacity:.55;transition:opacity .25s var(--ease-out);}
.frag-item:hover img,.frag-item.is-current img{opacity:1;}
.frag-item.is-current{border-color:var(--red);}
/* The only caption a thumbnail carries. It inherits the red of the current
   item, which the title used to carry — the border alone reads as a crop mark
   rather than a selection. */
.frag-item-dur{display:block;font-family:var(--font-mono);font-size:.56rem;
  letter-spacing:.06em;color:var(--ink-faint);margin:.45rem .3rem .5rem;}
.frag-item.is-current .frag-item-dur{color:var(--red);}

.frag-credit{font-family:var(--font-mono);font-size:.56rem;letter-spacing:.16em;
  color:var(--ink-faint);margin-top:1.2rem;}

@media(max-width:1100px){.frag-item{flex-basis:calc((100% - 20px)/3);}}
@media(max-width:760px){.frag-item{flex-basis:calc((100% - 10px)/2);}}

/* ---- scroll reveal ---------------------------------------------------- */
/* Fade up as each element enters the viewport. Honours reduced-motion. */
[data-reveal]{opacity:0;transform:translateY(var(--reveal-rise,28px));
  transition:opacity var(--reveal-dur,1.2s) var(--ease-out),
             transform var(--reveal-dur,1.2s) var(--ease-out);
  transition-delay:var(--reveal-delay,0ms);}
[data-reveal].is-revealed{opacity:1;transform:none;}
@media(prefers-reduced-motion:reduce){
  [data-reveal]{opacity:1;transform:none;transition:none;}
}

/* ---- S0c · the question ---------------------------------------------- */
/* The central question of the piece. It gets a screen to itself, and behind
   the line an iris of archive footage opens as you scroll — capped just under
   the width of the text, so "Is" and "?" always overhang it onto black. */
/* Three states, and js/question-beat.js picks exactly one — so the script and
   the stylesheet can never disagree about whether the iris is animating.

   base      no class: one screen, card already open. What you get with the
             script blocked or still parsing — a composed frame, not a stray
             seed sitting in 2.5 screens of emptiness.
   .qb-live  the scrub is running: the section grows a tail to scroll through
             and the stage pins inside it.
   .qb-still reduced motion: no footage at all, matching what the hero does
             with its own background video. */
.question-beat{
  min-height:100svh;
  /* Both are scrubbed 0 → 1 by the script; CSS only reads them. --qb-p is the
     iris, --qb-t the question arriving after it. Defaulting to 1 (not 0) is
     what makes the no-script state the composed frame rather than a bare seed
     under invisible type. */
  --qb-p:1;
  --qb-t:1;
  /* The swell handed over from the iris: 0 = type at rest, 1 = fully swollen.
     Rests at 0 in every state but the live scrub — the composed frame is the
     one without it. */
  --qb-s:0;
  /* How much bigger the question gets once the card has stopped. */
  --qb-swell:0.1;
  /* How far the question rises as it fades in. Scaled to the viewport so the
     travel stays proportional to the type, which is itself a clamp(). */
  --qb-rise:clamp(18px,2.4vw,34px);
  /* Measured at runtime: 0.9 × the widest rendered line of the question. */
  --qb-w-max:32rem;
  /* Card proportion. ~5:4 — an object, not a screen. Tune here. */
  --qb-ratio:0.78;
  /* Seed: letter-sized, so it reads as a glyph in the line before it opens. */
  --qb-seed:0.5em;
}
/* Surplus over the pinned stage = the scroll distance the iris scrubs over.
   Note the script begins scrubbing before the stage locks, so the effective
   run is this surplus plus most of a viewport of approach. */
.question-beat.qb-live{height:250svh;--qb-p:0;--qb-t:0;}
.question-beat.qb-still .qb-frame{display:none;}

.qb-stage{height:100svh;
  display:grid;place-items:center;padding:2rem;text-align:center;}
.qb-live .qb-stage{position:sticky;top:0;}

/* The iris. Both axes are driven independently so it morphs square →
   landscape as it opens, rather than merely scaling. */
.qb-frame{
  grid-area:1/1;position:relative;z-index:0;
  width:calc(var(--qb-seed) + (var(--qb-w-max) - var(--qb-seed)) * var(--qb-p));
  height:calc(var(--qb-seed) + (var(--qb-w-max) * var(--qb-ratio) - var(--qb-seed)) * var(--qb-p));
  /* Radius eases from a fully-rounded seed to a calm card corner. */
  border-radius:calc(0.5 * var(--qb-seed) + (14px - 0.5 * var(--qb-seed)) * var(--qb-p));
  overflow:hidden;
  /* font-size only exists here to give --qb-seed's em something to resolve
     against: one em = the question's own type size. */
  font-size:clamp(3.1rem,11vw,8.6rem);
  /* No will-change: it only promotes for transform/opacity, and width/height
     go through layout regardless. Scaling by transform instead would be
     cheaper but would stretch the footage, which is the whole point of the
     shot — so the iris pays for layout on one isolated element. The text is
     in its own grid area and never reflows with it. */
}
.qb-video{width:100%;height:100%;object-fit:cover;display:block;}
/* Ramps in with the iris so the type keeps contrast as footage arrives.
   Weighted to the centre, where the line sits. The archive swings from night
   interiors to blown-out daylight, so this is set for the brightest frames
   rather than the average one — on dark footage it simply disappears. */
.qb-scrim{position:absolute;inset:0;
  background:radial-gradient(72% 62% at 50% 50%,
    oklch(0.05 0.008 25 / 0.72) 0%, oklch(0.06 0.008 25 / 0.46) 55%,
    oklch(0.07 0.008 25 / 0.16) 100%);
  opacity:var(--qb-p);}

/* Hero-title scale, but set in a true serif italic: the question is asked of
   a person, not announced by the interface. Swap --font-serif below to try
   "EB Garamond" (literary, humane) or "Playfair" (high-contrast, dramatic). */
.qb-text{grid-area:1/1;position:relative;z-index:2;
  margin:0;font-family:var(--font-serif);
  font-size:clamp(3.1rem,11vw,8.6rem);line-height:1.02;font-weight:400;
  /* The vendored serif is an italic-only face, so the whole line must be
     italic — otherwise the white words fall back to Georgia. */
  font-style:italic;
  /* Tight tracking connects the letters; word-spacing has to be given back,
     since negative letter-spacing shrinks the spaces too. */
  letter-spacing:-0.045em;word-spacing:0.16em;color:var(--ink);
  text-shadow:0 1px 3px oklch(0 0 0 / 0.5);
  /* Arrives on the tail of the same scrub that opens the iris: fades up into
     place as the card reaches full size. No transition — the scrub is the
     timing, and a transition on top would lag it and break the sync. */
  opacity:var(--qb-t);
  /* Scale, not font-size: font-size would reflow the line and could re-wrap it
     mid-scroll on a narrow screen, and it would invalidate the measured
     --qb-w-max the card is sized from. transform costs neither. Origin is the
     default centre, so the line swells outward symmetrically and the overhang
     past the card's edges grows with it — which is the effect. */
  transform:translateY(calc((1 - var(--qb-t)) * var(--qb-rise)))
            scale(calc(1 + var(--qb-s) * var(--qb-swell)));}
.qb-text em{color:var(--red);font-style:italic;}

/* The cloud. The vocabulary the archive is actually tagged with, gathering in
   the air around the question — the words the machine has already applied,
   hovering around the one it can't settle. Built and placed by
   js/question-beat.js, because the arrangement is solved against the *measured*
   line and CSS has neither the measurement nor trig. Nothing without the script,
   deliberately: unlike the iris, whose seed state was a broken composition, the
   cloud's absence is exactly the frame this section was before it existed. */
.qb-cloud{
  /* Three layers in the stage's single 1/1 cell, and the order is the whole
     composition: footage at 0, the words over it at 1, the question over both
     at 2. The words are opaque pills, so one crossing the card's edge reads as
     a label laid on the image rather than as something clipped by it. */
  grid-area:1/1;place-self:stretch;position:relative;z-index:1;
  /* Never intercept a drag across the question. */
  pointer-events:none;
  /* The cloud's own driver, and deliberately not --qb-t. Keyed off the iris
     instead, and a little earlier, so the words are already gathering as the
     type begins to rise: one gesture with two parts, not two animations. It
     reaches 1 just before the line settles, leaving the last movement to the
     question — which is the only thing on this screen that should land. */
  --qb-c:clamp(0,calc((var(--qb-p) - 0.42) * 2),1);
  /* Rest just inside their placed positions and open outward as they arrive,
     echoing the iris. Capped at 1: the placement was solved at 1, and going
     past it would walk the outermost chips off the stage. */
  --qb-spread:calc(0.9 + 0.08 * var(--qb-c) + 0.02 * var(--qb-s));
}

.qb-chip{
  position:absolute;left:50%;top:50%;
  /* Load-bearing. An absolutely positioned box shrink-to-fits, so without this
     "Safe-Space" and "Ultra-Right" would break themselves over two lines. */
  white-space:nowrap;user-select:none;
  font-family:var(--font-mono);letter-spacing:.03em;line-height:1;
  /* A step under the real chips in #dispute — these are scenery, not controls,
     so they get none of the button affordances. --qb-w is the label's share of
     the archive: the words it leans on come up a shade in size and brightness,
     which is what the graph says with node radius. */
  /* Comfortably above the real chips in #dispute (0.62rem). These are read at
     arm's length across a dark screen rather than scanned in a dense bar, and
     they are the only other text on the beat — there is nothing here for them
     to out-shout except the question, which is set fifteen times larger. */
  font-size:calc(clamp(.62rem,.48rem + .72vw,.95rem) * (.9 + .1 * var(--qb-w,1)));
  color:var(--ink);
  /* Opaque, and that is what lets a word cross the card's edge and still read
     as a word rather than as a smudge on the footage. */
  background:var(--void-deep);
  border:1px solid var(--line);
  border-radius:999px;padding:.36rem .82rem;
  /* This chip's share of the cloud's arrival. Inner chips get the smaller
     --qb-d, so the cloud blooms outward from the card rather than switching on.
     --qb-k is 1/(1 - d), precomputed in JS so this stays a multiply. */
  --qb-ci:clamp(0,calc((var(--qb-c) - var(--qb-d,0)) * var(--qb-k,1)),1);
  /* Legible first, subordinate second — the hierarchy is carried by size and by
     the mono/serif split, not by hiding the words in the background. The floor
     is what a word the archive uses twice gets; the ceiling is the one it leans
     on hardest. */
  opacity:calc(var(--qb-ci) * (.78 + .22 * var(--qb-w,1)));
  /* Placement on `translate`, drift on `transform`. Two independent properties,
     so the keyframes never need to know where the chip is and the scrub never
     needs to know where it is drifting to — neither can clobber the other.
     The 0px fallbacks are load-bearing: a chip that exists before layout has
     run would otherwise take the whole declaration invalid at computed-value
     time and pile every word on the centre. */
  translate:calc(var(--qb-x,0px) * var(--qb-spread) - 50%)
            calc(var(--qb-y,0px) * var(--qb-spread) - 50% + (1 - var(--qb-ci)) * 10px);
  animation:qb-drift var(--qb-dur,20s) ease-in-out var(--qb-delay,0s) infinite;
  /* Idle unless the beat is near the viewport — the same judgement the observer
     already makes about whether the footage is worth decoding. */
  animation-play-state:paused;
}
.qb-near .qb-chip{animation-play-state:running;}
/* Reduced motion: the cloud stays, the drift goes. Expressed through .qb-still
   rather than a media query, for the reason given below — one decision, read
   once by the script, drives every part of this section. */
.qb-still .qb-chip{animation:none;}

/* A closed loop, not a ping-pong: a ping-pong reads as a pendulum, and eighteen
   pendulums read as breathing in time. This traces a lopsided ellipse instead —
   wider than it is tall, so the motion reads as hovering rather than bobbing —
   and --qb-spin sends half the cloud round it the other way. Amplitude is per
   word and always under PAD, so no amount of drift can carry one onto the type.
   Only transform is animated, so every word stays on the compositor. */
@keyframes qb-drift{
  0%,100%{transform:translate3d(0,0,0) rotate(0deg);}
  20%{transform:translate3d(calc(var(--qb-amp,16px) * .95),calc(var(--qb-amp,16px) * -.34 * var(--qb-spin,1)),0)
              rotate(calc(.9deg * var(--qb-spin,1)));}
  40%{transform:translate3d(calc(var(--qb-amp,16px) * .42),calc(var(--qb-amp,16px) * -.86 * var(--qb-spin,1)),0)
              rotate(calc(-.5deg * var(--qb-spin,1)));}
  60%{transform:translate3d(calc(var(--qb-amp,16px) * -.5),calc(var(--qb-amp,16px) * -.78 * var(--qb-spin,1)),0)
              rotate(calc(-1deg * var(--qb-spin,1)));}
  80%{transform:translate3d(calc(var(--qb-amp,16px) * -.9),calc(var(--qb-amp,16px) * .3 * var(--qb-spin,1)),0)
              rotate(calc(.6deg * var(--qb-spin,1)));}
}

/* No @media(prefers-reduced-motion) block here on purpose: the script reads
   that query once and applies .qb-still, so a single decision drives both the
   layout and whether the video is left on the network. */

/* ---- S4 · semantic print (live from data/moments.json) ----------------
   Short on purpose: it shares a column with the sketch carousel and must not
   out-shout it. Eight dense rows, three rankings, one line of stats. */
.semprint-body{font-family:var(--font-mono);letter-spacing:.03em;
  padding:2.2rem 1.2rem 1.2rem;}
.semprint-hint{margin-top:.45rem;font-size:.6rem;line-height:1.6;
  color:var(--ink-faint);letter-spacing:.04em;}
.semprint-modes{display:flex;gap:.35rem;margin:.9rem 0 1rem;}
.semprint-mode{font-family:var(--font-mono);font-size:.55rem;letter-spacing:.12em;
  padding:.3rem .6rem;border-radius:2px;cursor:pointer;
  color:var(--ink-faint);background:transparent;border:1px solid var(--line);
  transition:color .2s var(--ease-out),border-color .2s var(--ease-out);}
.semprint-mode:hover{color:var(--ink);}
.semprint-mode[aria-checked="true"]{color:var(--red-bright);border-color:var(--red-dim);
  background:color-mix(in oklab, var(--red) 10%, transparent);}
.semprint-bars{list-style:none;display:flex;flex-direction:column;gap:.3rem;}
.semprint-row{display:grid;width:100%;grid-template-columns:minmax(4.5rem,6.5rem) 1fr 2.6rem;
  align-items:center;gap:.7rem;padding:.18rem 0;cursor:pointer;
  background:none;border:0;font-family:inherit;font-size:.6rem;letter-spacing:.05em;
  text-align:left;color:inherit;}
.semprint-label{color:var(--ink-dim);text-transform:uppercase;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  transition:color .2s var(--ease-out);}
.semprint-row:hover .semprint-label,
.semprint-row.is-pinned .semprint-label{color:var(--ink);}
.semprint-track{position:relative;height:5px;background:var(--surface);
  border-radius:3px;overflow:hidden;}
.semprint-track i{display:block;height:100%;width:0;background:var(--red-dim);
  border-radius:3px;transition:width .55s var(--ease-out),background .2s var(--ease-out);}
.semprint.in-view .semprint-track i{width:var(--w,0);}
.semprint-row:hover .semprint-track i,
.semprint-row.is-pinned .semprint-track i{background:var(--red-bright);}
.semprint-count{text-align:right;color:var(--ink-faint);font-variant-numeric:tabular-nums;}
.semprint-row:hover .semprint-count,
.semprint-row.is-pinned .semprint-count{color:var(--ink);}
/* One line instead of the old four-stat block — it swaps between the whole
   archive and whichever label is being hovered or held. */
.semprint-strip{margin-top:1rem;padding-top:.8rem;border-top:1px solid var(--line);
  font-size:.6rem;line-height:1.7;color:var(--ink-faint);letter-spacing:.04em;}
.semprint-strip b{color:var(--ink);font-weight:400;}
.semprint .mi-meta{margin-top:.7rem;padding-top:.7rem;font-size:.55rem;line-height:1.6;}
@media(prefers-reduced-motion:reduce){.semprint-track i{transition:none;}}
@media(max-width:640px){
  .semprint-row{grid-template-columns:5rem 1fr 2.4rem;gap:.5rem;}
  .semprint > .viz-hint{
    position:static;
    display:block;
    padding:.9rem 1.2rem 0;
  }
  .semprint-body{padding-top:1.2rem;}
}

/* ---- S4 · argument left, evidence right ------------------------------- */
/* The whole section is one two-column spread: the reading column on the left,
   the live semantic print and the concept-sketch carousel stacked on the
   right. Nothing here is full-bleed — the graph is capped by its column. */
.s4-grid{display:grid;grid-template-columns:1fr 1fr;
  gap:clamp(1.6rem,3vw,3rem);align-items:start;}
.s4-text .section-head{max-width:none;margin-bottom:2.2rem;}
.s4-visuals{display:flex;flex-direction:column;gap:clamp(1rem,1.6vw,1.4rem);}
.web-head{max-width:none;margin:0 0 1.6rem;}
.web-head h3{margin-top:.5rem;font-family:var(--font-display);
  font-weight:800;font-stretch:116%;letter-spacing:-.01em;
  font-size:clamp(1.15rem,2.2vw,1.5rem);line-height:1.2;}
.web-head p{margin-top:.7rem;color:var(--ink-dim);}
.web-claim-kicker{font-family:var(--font-mono);font-size:.62rem;
  letter-spacing:.14em;color:var(--red-bright);margin-bottom:1rem;}
.web-claim p + p{margin-top:1rem;}
.web-claim p:not(.web-claim-kicker){color:var(--ink-dim);}
.web-claim em{font-style:normal;color:var(--ink);}
@media(max-width:900px){.s4-grid{grid-template-columns:1fr;}}

/* ---- S4 · concept-sketch carousel (loops; a slide opens the lightbox) - */
.sketch-carousel{position:relative;}
.carousel-viewport{overflow:hidden;border:1px solid var(--line);
  border-radius:4px;background:var(--void-deep);}
.carousel-track{display:flex;transition:transform .7s var(--ease-out);}
/* Each slide is a full viewport wide and sized by its own image, so the
   sketch is shown whole at its native ratio — never cropped to a frame. */
.sketch-figure{position:relative;flex:0 0 100%;margin:0;}
.sketch-figure img{display:block;width:100%;height:auto;cursor:zoom-in;}
.carousel-arrow{position:absolute;top:50%;translate:0 -50%;z-index:2;
  width:44px;height:44px;display:grid;place-items:center;
  background:var(--void-deep);
  border:1px solid var(--line);border-radius:50%;color:var(--ink);
  font-size:1.3rem;line-height:1;cursor:pointer;
  transition:background .2s var(--ease-out),border-color .2s var(--ease-out);}
.carousel-arrow:hover{background:var(--void);border-color:var(--red-dim);}
.carousel-prev{left:-14px;}
.carousel-next{right:-14px;}
.carousel-bar{display:flex;align-items:center;justify-content:space-between;
  gap:.8rem;margin-top:.9rem;padding-top:.7rem;border-top:1px solid var(--line);}
.carousel-caption{font-family:var(--font-mono);font-size:.6rem;
  letter-spacing:.1em;color:var(--ink-dim);}
.carousel-dots{display:flex;justify-content:flex-end;gap:.5rem;}
.carousel-dot{width:9px;height:9px;padding:0;border-radius:50%;cursor:pointer;
  border:1px solid var(--line);background:transparent;
  transition:background .25s var(--ease-out),border-color .25s var(--ease-out);}
.carousel-dot[aria-selected="true"]{background:var(--red-bright);border-color:var(--red-bright);}
@media(prefers-reduced-motion:reduce){.carousel-track{transition:none;}}

.ask{font-family:var(--font-display);color:var(--ink);max-width:52ch;
  font-size:clamp(1.15rem,2.6vw,1.7rem);line-height:1.4;margin-top:.4rem;}
.ask strong{color:var(--red-bright);}
.credits-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));
  gap:1.6rem;margin-top:2.2rem;}
.credits-grid h4{font-family:var(--font-mono);font-size:.68rem;letter-spacing:.14em;
  color:var(--red);text-transform:uppercase;margin:0 0 .5rem;}
.credits-grid p{font-size:.92rem;line-height:1.5;color:var(--ink-dim);margin:0;}

.logo-wall{display:flex;flex-wrap:wrap;align-items:center;
  gap:.85rem;padding:2rem 0 .5rem;margin-top:2rem;
  border-top:1px solid var(--line);}
.logo-chip{display:flex;align-items:center;
  transition:opacity .25s var(--ease-out),transform .25s var(--ease-out);}
.logo-chip img{height:52px;width:auto;object-fit:contain;
  border-radius:4px;opacity:.94;}
.logo-chip:hover{opacity:1;transform:translateY(-1px);}
a.logo-chip{cursor:pointer;}

/* ---------- team bios ---------- */
.team-bios-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(1.2rem, 2.5vw, 2rem);
  margin: 2.8rem 0 3.2rem;
}
.team-card {
  background: color-mix(in oklab, var(--surface) 35%, transparent);
  border: 1px solid var(--line);
  padding: clamp(1.2rem, 2vw, 1.6rem);
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  border-radius: 4px;
}
.team-card-role {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  color: var(--red-bright);
  text-transform: uppercase;
}
.team-card-name {
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--ink);
  margin-top: -0.3rem;
}
.team-card-bio {
  font-size: 0.86rem;
  line-height: 1.58;
  color: oklch(0.84 0.006 25);
  flex-grow: 1;
  margin: 0;
}
.team-card-works {
  border-top: 1px solid var(--line);
  padding-top: 0.85rem;
  margin-top: 0.2rem;
}
.team-card-works h5 {
  font-family: var(--font-mono);
  font-size: 0.58rem;
  letter-spacing: 0.12em;
  color: var(--ink-dim);
  margin: 0 0 0.5rem;
  text-transform: uppercase;
}
.team-card-works ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  font-size: 0.8rem;
  color: var(--ink-dim);
}
.team-card-works li strong {
  color: var(--ink);
  font-weight: 600;
}
.team-card-links {
  display: flex;
  gap: 0.9rem;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  margin-top: 0.3rem;
  padding-top: 0.6rem;
  border-top: 1px stroke var(--line);
}
.team-card-links a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: currentColor;
}
.team-card-links a:hover {
  color: var(--red-bright);
}

@media (max-width: 900px) {
  .team-bios-grid { grid-template-columns: 1fr; }
}
