/* Cutscene launch site.
   The page is built as a trace: a scrubber across the top, real recorded step
   ids in the gutter, and one box motif that transforms scene to scene.
   Palette comes from packages/editor/src/tokens.css so the site and the
   instrument agree. */

:root {
  --ink: #0e1013;
  --bg: #16181c;
  --surface: #1e2126;
  --line: #2a2e35;
  --line-hi: #3c424b;
  --text: #eef1f5;
  --mid: #b3bac4;
  --dim: #868e9a;
  --hot: #f2a63b;
  --bad: #e2706a;

  --display: 'Archivo', system-ui, sans-serif;
  --mono: 'IBM Plex Mono', ui-monospace, monospace;

  --pad: clamp(1.15rem, 4vw, 4.5rem);
  --gut: clamp(0rem, 6vw, 7rem);
  --out: cubic-bezier(0.16, 1, 0.3, 1);
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--display);
  font-size: clamp(1rem, 0.96rem + 0.2vw, 1.09rem);
  font-weight: 500;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, video { display: block; max-width: 100%; }
::selection { background: var(--hot); color: var(--ink); }
a { color: inherit; }
:focus-visible { outline: 2px solid var(--hot); outline-offset: 3px; }

.skip {
  position: fixed; z-index: 60; top: 0; left: 0;
  padding: 0.8rem 1.1rem;
  background: var(--hot); color: var(--ink);
  font: 500 0.85rem var(--mono);
  transform: translateY(-130%);
}
.skip:focus { transform: none; }

/* ─────────────────────────────────────────────────────────── scrubber ── */

.scrub {
  position: fixed; z-index: 50; inset: 0 0 auto 0;
  height: 2px; background: var(--line);
}
.scrub i {
  display: block; height: 100%; width: 100%;
  background: var(--hot);
  transform-origin: 0 50%;
  scale: 0 1;
}

/* ───────────────────────────────────────────────────────────── gutter ── */
/* The recorded step the current scene corresponds to. Real ids, not decor. */

.gutter {
  position: fixed; z-index: 40;
  left: clamp(0.6rem, 1.6vw, 1.4rem);
  top: 50%; translate: 0 -50%;
  display: grid; gap: 0.25rem;
  font: 500 0.66rem/1.2 var(--mono);
  letter-spacing: 0.1em;
  color: var(--dim);
  writing-mode: vertical-rl;
  text-orientation: mixed;
}
.gutter-t { color: var(--line-hi); }
@media (max-width: 1100px) { .gutter { display: none; } }

/* ─────────────────────────────────────────────────────────────── hero ── */

.hero {
  position: relative;
  min-height: 100svh;
  padding: clamp(1rem, 2.5vw, 2rem) var(--pad) clamp(2rem, 6vh, 4rem) calc(var(--pad) + var(--gut));
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: clamp(1.5rem, 4vh, 3rem);
  overflow: hidden;
}

.masthead {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 1rem; flex-wrap: wrap;
  font: 500 0.74rem var(--mono);
  letter-spacing: 0.16em; text-transform: uppercase;
}
.masthead nav { display: flex; gap: 1.5rem; }
.masthead a { color: var(--dim); text-decoration: none; }
.masthead a:hover { color: var(--text); }

.mega {
  margin: 0;
  align-self: center;
  font-size: clamp(3.2rem, 13.5vw, 13rem);
  font-weight: 900;
  line-height: 0.83;
  letter-spacing: -0.045em;
  text-transform: none;
}
.mega span { display: block; }
.mega .hot { color: var(--hot); }

.hero-foot {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: clamp(1.25rem, 3vw, 3rem);
  align-items: end;
  max-width: 78rem;
}
.hero-foot p { margin: 0; max-width: 44ch; color: var(--mid); }

.hero-vid {
  position: absolute;
  z-index: -1;
  right: -12%; bottom: -6%;
  width: min(58vw, 46rem);
  aspect-ratio: 16/9;
  object-fit: cover;
  opacity: 0.16;
  filter: grayscale(1) contrast(1.1);
  mask-image: linear-gradient(285deg, #000 20%, transparent 78%);
  pointer-events: none;
}

/* ──────────────────────────────────────────────────────────── buttons ── */

.actions { display: flex; flex-wrap: wrap; gap: 0.7rem; }

.btn {
  position: relative; isolation: isolate;
  display: inline-flex; align-items: center; gap: 0.7rem;
  padding: 0.9rem 1.4rem;
  border: 1px solid var(--hot);
  background: var(--hot); color: var(--ink);
  font: 500 0.92rem var(--mono);
  text-decoration: none; overflow: hidden;
}
.btn svg { width: 22px; height: 12px; fill: none; stroke: currentColor; stroke-width: 1.7; transition: translate 0.4s var(--out); }
.btn::before {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background: var(--text); translate: -101% 0;
  transition: translate 0.45s var(--out);
}
.btn:hover::before, .btn:focus-visible::before { translate: 0 0; }
.btn:hover svg, .btn:focus-visible svg { translate: 6px 0; }
.btn.ghost { border-color: var(--line-hi); background: transparent; color: var(--text); }
.btn.ghost::before { background: var(--surface); }
.btn.ghost:hover, .btn.ghost:focus-visible { border-color: var(--text); }

/* ────────────────────────────────────────────────────────────── scenes ── */
/* Each scene is a tall track with a sticky stage. Children hang off the
   track's own view timeline, so scrolling scrubs the scene rather than
   triggering a one-shot reveal. */

.scene {
  position: relative;
  height: 300vh;
  view-timeline-name: --track;
  view-timeline-axis: block;
}
.scene.wide { height: 420vh; }
.scene.dark { background: var(--ink); }

.stage {
  position: sticky; top: 0;
  min-height: 100svh;
  padding: clamp(3.5rem, 9vh, 6rem) var(--pad) clamp(2.5rem, 6vh, 4rem) calc(var(--pad) + var(--gut));
  display: grid;
  align-content: center;
  gap: clamp(1.25rem, 3vh, 2.25rem);
  overflow: hidden;
}

.lbl {
  margin: 0 0 0.9rem;
  color: var(--dim);
  font: 500 0.7rem var(--mono);
  letter-spacing: 0.18em; text-transform: uppercase;
}

.scene-copy { max-width: 60rem; }
.scene-copy h2, .climax h2, .end h2 {
  margin: 0;
  font-weight: 900;
  letter-spacing: -0.04em;
  line-height: 0.95;
  text-wrap: balance;
}
/* Pinned stages clip at 100svh, so display type inside them is a step down
   from the hero and the copy stays short. */
.scene-copy h2 { font-size: clamp(1.9rem, 4.6vw, 4rem); }
.say {
  margin: 1.1rem 0 0;
  max-width: 54ch;
  color: var(--mid);
  font-size: 0.98rem;
  text-wrap: pretty;
}
.wide-say { max-width: 72ch; }

/* Scene 01 reads as two columns on wide screens: the argument on the left,
   the evidence on the right. */
@media (min-width: 1100px) {
  #capture .stage {
    grid-template-columns: minmax(16rem, 25rem) minmax(0, 1fr);
    grid-template-areas: "copy fig" "trace fig";
    column-gap: clamp(1.5rem, 3vw, 3.25rem);
    row-gap: 1.25rem;
    align-content: center;
  }
  /* the column is narrow, so this heading sizes to the column not the page */
  #capture .scene-copy h2 { font-size: clamp(1.9rem, 3.3vw, 3.1rem); text-wrap: pretty; }
  #capture .scene-copy { grid-area: copy; align-self: end; }
  #capture .wipe { grid-area: fig; align-self: center; }
  #capture .trace { grid-area: trace; align-self: start; display: grid; gap: 0; }
}

/* ─────────────────────────────────────────────── scene 01: the wipe ── */

.wipe {
  position: relative;
  margin: 0;
  border: 1px solid var(--line);
  background: var(--ink);
  max-width: min(100%, 76rem);
  justify-self: start;
}
.wipe img { width: 100%; height: auto; max-height: 62svh; aspect-ratio: 1400/875; object-fit: cover; }
.wipe .over { position: absolute; inset: 0; }
.wipe-edge { display: none; }
.wipe figcaption {
  padding: 0.7rem 0.9rem;
  border-top: 1px solid var(--line);
  color: var(--dim);
  font: 0.76rem/1.5 var(--mono);
}

.trace {
  margin: 0;
  display: flex; flex-wrap: wrap;
  gap: 0 clamp(1.25rem, 3vw, 2.75rem);
  font: 0.78rem var(--mono);
}
.trace div { display: flex; gap: 0.55rem; padding: 0.3rem 0; }
.trace dt { color: var(--dim); text-transform: uppercase; letter-spacing: 0.08em; }
.trace dd { margin: 0; color: var(--hot); }


/* Where the wipe cannot run, the two frames stack so the comparison is still
   made rather than the raw frame simply being hidden underneath. */
@media (prefers-reduced-motion: reduce), (max-width: 780px), (max-height: 620px) {
  .wipe .over { position: static; border-top: 1px solid var(--line); }
  .wipe img { max-height: none; }
}
@supports not (animation-timeline: view()) {
  .wipe .over { position: static; border-top: 1px solid var(--line); }
}

/* ────────────────────────────────────────── scene 02: artifact strip ── */

.scene-copy.top { align-self: start; }
.strip-wrap { overflow-x: auto; overscroll-behavior-x: contain; }
.strip {
  list-style: none; margin: 0; padding: 0;
  display: flex; gap: clamp(0.75rem, 1.5vw, 1.25rem);
  width: max-content;
}
.strip li {
  width: clamp(15rem, 26vw, 21rem);
  display: grid;
  align-content: start;
  gap: 0.45rem;
  border: 1px solid var(--line);
  background: var(--surface);
  padding-bottom: 0.9rem;
}
.strip figure { margin: 0; border-bottom: 1px solid var(--line); background: var(--ink); }
.strip img { width: 100%; height: clamp(9rem, 26svh, 15rem); object-fit: cover; object-position: top left; }
.strip .txt {
  height: clamp(9rem, 26svh, 15rem); padding: 0.9rem 1rem; overflow: hidden;
}
.strip .txt pre { margin: 0; }
.strip .txt code {
  font: 0.72rem/1.6 var(--mono);
  color: var(--mid);
  white-space: pre;
}
.strip .txt.hot code { color: var(--hot); }
.strip b { padding: 0 1rem; font: 500 0.86rem var(--mono); color: var(--text); }
.strip span { padding: 0 1rem; color: var(--dim); font-size: 0.86rem; line-height: 1.45; }
.strip-note { margin: 0; color: var(--dim); font: 0.8rem var(--mono); }

/* ───────────────────────────────────────────────── scene 03: report ── */

.report {
  border: 1px solid var(--line);
  background: var(--surface);
  padding: clamp(1rem, 2.5vw, 1.75rem);
  font-family: var(--mono);
  max-width: min(100%, 68rem);
  justify-self: start;
}
.report p { margin: 0; }
.report-h { color: var(--hot); font-size: 0.9rem; }
.report-f { margin-top: 1.1rem !important; color: var(--dim); font-size: 0.76rem; }
.report ul {
  margin: 0.9rem 0 0; padding: 0; list-style: none;
  display: grid; gap: 0.3rem;
  font-size: 0.82rem; color: var(--mid);
}
.report li { display: flex; flex-wrap: wrap; gap: 0 0.75rem; padding: 0.25rem 0; border-bottom: 1px solid #23272d; }
.report code { color: var(--text); }
.report i { color: var(--dim); font-style: normal; }
.report b { color: var(--text); font-weight: 500; }

/* ────────────────────────────────────────────────── scene 04: drift ── */

.diff {
  margin: 0; padding: clamp(0.7rem, 1.6vw, 1.05rem);
  border: 1px solid var(--line); background: var(--bg);
  font: 0.76rem/1.65 var(--mono);
  overflow-x: auto;
  max-width: min(100%, 68rem);
}
.diff .ctx { color: var(--dim); display: block; }
.diff .del { color: var(--bad); display: block; }
.diff .add { color: var(--hot); display: block; }

.runs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 19rem), 1fr));
  gap: clamp(0.75rem, 2vw, 1.5rem);
  max-width: min(100%, 68rem);
}
.run { border: 1px solid var(--line); background: var(--bg); padding: clamp(0.9rem, 2vw, 1.35rem); }
.run p { margin: 0; display: flex; gap: 0.6rem; align-items: baseline; font: 0.84rem/1.85 var(--mono); }
.run i { font-style: normal; min-width: 1.2rem; color: var(--text); }
.run em { font-style: normal; color: var(--dim); margin-left: auto; font-size: 0.78rem; }
.run-h {
  margin-bottom: 0.8rem !important; padding-bottom: 0.7rem;
  border-bottom: 1px solid var(--line);
  color: var(--dim); font-size: 0.72rem !important;
  letter-spacing: 0.14em; text-transform: uppercase;
}
.run-h b { margin-left: auto; }
.run .ok { color: var(--mid); }
.run .warn { color: var(--text); }
.run .bad, .bad { color: var(--bad); }
.run .hot, .hot { color: var(--hot); }

/* ───────────────────────────────────────────────────────────── climax ── */

.climax {
  min-height: 100svh;
  display: grid; align-content: center;
  padding: clamp(3rem, 10vh, 7rem) var(--pad) clamp(3rem, 10vh, 7rem) calc(var(--pad) + var(--gut));
  background: var(--hot); color: var(--ink);
}
.climax h2 { max-width: 19ch; font-size: clamp(2.1rem, 7.4vw, 6rem); letter-spacing: -0.045em; }

/* ──────────────────────────────────────────────────────────────── end ── */

.end { padding: clamp(4rem, 12vh, 8rem) var(--pad) clamp(1.5rem, 4vh, 2.5rem) calc(var(--pad) + var(--gut)); }
.end h2 { font-size: clamp(2.4rem, 8vw, 6rem); margin-bottom: clamp(2rem, 5vh, 3.5rem); }
.end-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: start;
}
.end p { margin: 0 0 1.6rem; max-width: 46ch; color: var(--mid); }
.end h3 {
  margin: 2.6rem 0 1rem;
  font: 500 0.72rem var(--mono);
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--dim);
}
.end h3 code { color: var(--hot); font-size: inherit; letter-spacing: 0; text-transform: none; }
.limits { margin: 0; padding: 0; list-style: none; display: grid; gap: 0.5rem; color: var(--mid); font-size: 0.95rem; }
.facts { margin: 0; }
.facts div {
  display: flex; flex-wrap: wrap; justify-content: space-between;
  gap: 0.4rem 1.5rem; padding: 0.85rem 0; border-bottom: 1px solid var(--line);
}
.facts dt { color: var(--mid); font-size: 0.95rem; }
.facts dd { margin: 0; font: 500 0.95rem var(--mono); color: var(--hot); }

footer {
  margin-top: clamp(3rem, 8vh, 5rem); padding-top: 1.2rem;
  border-top: 1px solid var(--line);
  display: flex; flex-wrap: wrap; gap: 0.4rem 2rem;
  color: var(--dim); font: 0.78rem var(--mono);
}
footer a { text-decoration: none; }
footer a:hover { color: var(--text); }

/* ═══════════════════════════════════════════════════════════ motion ═══ */
/* Everything above is the resting state and is fully legible on its own.
   The block below only refines it, so a browser without scroll timelines,
   a headless renderer, or reduced-motion loses choreography and nothing
   else. */

@media (prefers-reduced-motion: no-preference) {

  /* hero: a real load, never tied to scroll */
  .mega span, .hero-foot { animation: enter 0.85s var(--out) backwards; }
  .mega span:nth-child(1) { animation-delay: 0.04s; }
  .mega span:nth-child(2) { animation-delay: 0.12s; }
  .mega span:nth-child(3) { animation-delay: 0.2s; }
  .hero-foot { animation-delay: 0.34s; }

  @supports (animation-timeline: scroll()) {
    .scrub i {
      animation: fill linear both;
      animation-timeline: scroll(root block);
    }
  }

  @supports (animation-timeline: view()) {
    /* Scene 01. The recorded frame is wiped over the raw one, using the same
       clip-path measure the editor draws around a captured element. */
    .wipe .over {
      animation: measure linear both;
      animation-timeline: --track;
      animation-range: contain 8% contain 62%;
    }
    .wipe-edge {
      display: block;
      position: absolute; top: 0; bottom: 0; width: 2px;
      background: var(--hot);
      animation: sweep linear both;
      animation-timeline: --track;
      animation-range: contain 8% contain 62%;
    }
    .trace div {
      animation: lift linear both;
      animation-timeline: --track;
      animation-range: contain 40% contain 78%;
    }
    .trace div:nth-child(2) { animation-range: contain 46% contain 82%; }
    .trace div:nth-child(3) { animation-range: contain 52% contain 86%; }
    .trace div:nth-child(4) { animation-range: contain 58% contain 90%; }

    /* Scene 02. Vertical scroll drives the strip horizontally. */
    .scene.wide .strip-wrap { overflow-x: hidden; }
    .scene.wide .strip {
      animation: pan linear both;
      animation-timeline: --track;
      animation-range: contain 4% contain 96%;
    }

    /* Scene 03 and 04: rows arrive in recorded order. */
    .report li, .run p, .diff span {
      animation: lift linear both;
      animation-timeline: --track;
      animation-range: contain 10% contain 55%;
    }
    .report li:nth-child(2), .run p:nth-child(2) { animation-range: contain 16% contain 60%; }
    .report li:nth-child(3), .run p:nth-child(3) { animation-range: contain 22% contain 65%; }
    .report li:nth-child(4), .run p:nth-child(4) { animation-range: contain 28% contain 70%; }
    .report li:nth-child(5) { animation-range: contain 34% contain 75%; }

    .scene-copy h2 {
      animation: lift linear both;
      animation-timeline: --track;
      animation-range: contain 0% contain 30%;
    }
  }
}

@keyframes enter { from { opacity: 0; translate: 0 1.1rem; } to { opacity: 1; translate: 0 0; } }
@keyframes fill  { from { scale: 0 1; } to { scale: 1 1; } }
@keyframes lift  { from { translate: 0 0.85rem; } to { translate: 0 0; } }
@keyframes measure { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes sweep { from { left: 0; } to { left: calc(100% - 2px); } }
@keyframes pan {
  from { translate: 0 0; }
  to   { translate: calc(-100% + min(100vw - var(--pad) * 2 - var(--gut), 100%)) 0; }
}

/* Static, ordered, fully readable. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .scene, .scene.wide { height: auto; }
  .stage { position: static; }
  .scrub { display: none; }
  .hero-vid { display: none; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* No sticky scenes on short or narrow screens: the content is taller than the
   viewport there, and pinning would clip it. */
@media (max-width: 780px), (max-height: 620px) {
  .scene, .scene.wide { height: auto; }
  .stage { position: static; min-height: 0; padding-block: clamp(3rem, 9vh, 5rem); }
  .scene.wide .strip-wrap { overflow-x: auto; }
  .scene.wide .strip { animation: none; }
}
