:root {
  --press: #0b0a09;
  --paper: #efe8d6;
  --ink: #1d1c19;
  --fg: #fff;
  --line: rgba(255, 255, 255, .3);
  --ink-line: rgba(29, 28, 25, .28);   /* the same hairline, read on paper */
  --serif: "Newsreader", "Iowan Old Style", Georgia, serif;
  --sans: "Geist", "Helvetica Neue", Arial, sans-serif;
  --mono: "Geist Mono", ui-monospace, Menlo, monospace;
  --ease: cubic-bezier(.22, 1, .36, 1);
  --v1: 5.3%;
  --v2: 85.6%;
  --top: 76px;
  color-scheme: light only;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { background: var(--press); }
body { color: var(--fg); font-family: var(--sans); -webkit-font-smoothing: antialiased; }
body.on-paper { --fg: var(--ink); --line: rgba(29, 28, 25, .28); }
a { color: inherit; text-decoration: none; }

/* ---------- the stage: a tall track with one pinned frame ---------- */
/* tracks: 420vh header, 300vh station I, 240vh the pigeon film, 300vh station II,
   120vh the corners' crossing to III, 300vh station III, then 100 burn to IV, 300 IV, 120 the seal opens
   onto V, 300 V (the vault film), 120 the shut door engraved like a banknote, 150 VI assembled,
   300 VI, 160 VII assembled, 300 VII, 100 burn to VIII, 300 VIII, 120 the thread to IX, 300 IX,
   200 the sweep to the end, 200 the end, + one screen */
.stage { position: relative; height: 5520vh; }
/* the shut vault re-cut as a banknote engraving: a canvas laid exactly on the film's frame */
.eng { position: absolute; left: 0; top: 0; pointer-events: none; visibility: hidden; }
/* the second half: one container per painting, planes built by main.js */
.stx { position: absolute; inset: 0; overflow: hidden; visibility: hidden; }
.stx .in { position: absolute; inset: 0; }
.glow {
  position: absolute; left: 0; top: 0; width: 70vmin; height: 70vmin; border-radius: 50%; opacity: 0; pointer-events: none;
  background: radial-gradient(closest-side, rgba(255, 228, 165, .95), rgba(255, 170, 70, .35) 30%, rgba(255, 140, 40, 0));
  mix-blend-mode: screen;
}
/* free words: paper only where paper is the subject (I, IV). Elsewhere the text sits straight on the calm
   part of the picture, white on the dark, ink on the pale, standing on a hairline of its own */
.card2.free { background: none; padding: 0 0 16px; color: #fff; }
.card2.free::before {
  left: -14px; right: -14px; top: auto; bottom: 0; border-top: 0; border-bottom: 1px solid var(--line);
  transform: scaleX(var(--ln, 0)); transform-origin: 0 50%;
}
.card2.free::after { display: none; }
/* no sheet to hide the rail any more: free words on the left keep clear of its labels */
.card2.free:not(.card3):not(.c-bottom) { left: calc(var(--v1) + 11vw); }
#card2.free { top: 11.5vh; }   /* station II: above the dot-screened cloud, which would eat the paragraph */
/* low on the left, so the thread can leave the line's far end for what stands above without crossing the words */
.card2.c-low { top: auto; bottom: 9vh; }
.card2.free .tag { justify-self: start; background: rgba(255, 255, 255, .14); }
.card2.free .t { text-align: left; }
.card2.free.c-bottom .t, .card2.free.c-bottom .c { text-align: center; }
.card2.free.c-bottom::before { transform-origin: 50% 50%; }
.card2.free.ink { color: var(--ink); }
.card2.free.ink::before { border-bottom-color: rgba(29, 28, 25, .28); }
.card2.free.ink .tag { background: rgba(29, 28, 25, .08); }
/* V under the burin: a real sheet, like the cartels of I and IV, with its crop marks past the corners. It is
   a child, not a background, so the fire can uncover it; the words keep clear of its edges, tag included */
.sheet { display: none; position: absolute; left: -22px; right: -22px; top: -22px; bottom: -6px; background: var(--paper); z-index: -1; }
.boxed > .sheet { display: block; }
 /* the crop marks run on the sheet's own edges and a little past its corners, exactly as on the cartels of I
    and IV: they are drawn by the card, whose pseudo-elements are the only ones the engraving cannot cover */
.card2.free.boxed::before { left: -36px; right: -36px; top: -22px; bottom: -6px; transform: none;
  border-top: 1px solid var(--ink-line); border-bottom: 1px solid var(--ink-line); }
.card2.free.boxed::after { display: block; left: -22px; right: -22px; top: -36px; bottom: -20px;
  border-left: 1px solid var(--ink-line); border-right: 1px solid var(--ink-line); }
.inkover { position: absolute; inset: 0; pointer-events: none; isolation: isolate; }   /* its own stacking context, or the sheet's z-index -1 sinks behind the pictures */
.pins.ink line { stroke: rgba(29, 28, 25, .28); }
.pins.ink rect { fill: rgba(29, 28, 25, .28); }
.card2.c-top { left: 50%; top: calc(var(--top) + 3vh); transform: translateX(-50%); }
.card2.c-bottom { left: 50%; top: auto; bottom: 7vh; transform: translateX(-50%); }
.hero.fin { opacity: 0; top: 30vh; left: calc(var(--v1) + 11vw); }   /* clear of the rail's column, whose labels now reach this height */
.fin .sub span { display: block; }
.st3 { position: absolute; inset: 0; overflow: hidden; visibility: hidden; }
/* station III's cartel hangs on the right: the empty side changes from one station to the next */
.card2.card3 { left: auto; right: calc(100% - var(--v2) + 2.6vw); }   /* two classes: wins over .card2's left */

.st1 { position: absolute; inset: 0; overflow: hidden; visibility: hidden; clip-path: inset(50% 50% 50% 50%); }
.st2 { position: absolute; inset: 0; overflow: hidden; visibility: hidden; }
.film { position: absolute; inset: 0; width: 100%; height: 100%; visibility: hidden; pointer-events: none; }
/* station II's cartel: the same sheet, size and place as station I's once it has settled */
.card2 {
  position: absolute; left: calc(var(--v1) + 2.6vw); top: 30vh;
  display: grid; width: max-content; padding: 22px; opacity: 0;
  background: var(--paper); color: var(--ink);
}
.card2::before, .card2::after { content: ""; position: absolute; pointer-events: none; }
.card2::before { left: -14px; right: -14px; top: 0; bottom: 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.card2::after { top: -14px; bottom: -14px; left: 0; right: 0; border-left: 1px solid var(--line); border-right: 1px solid var(--line); }
.card2 .tag { justify-self: start; background: rgba(29, 28, 25, .08); font-size: 6px; padding: 4px 5px; }
.card2 .t { margin-top: 14px; text-align: center; font: 300 clamp(19px, 2.6vw, 45px)/1.04 var(--serif); letter-spacing: -.02em; }
.card2 .c { margin-top: 12px; width: 0; min-width: 100%; font: 500 clamp(12px, .92vw, 14px)/1.38 var(--sans); }
/* under the line: a short paragraph that says what the line means, quieter and narrower than it */
.card2 .p { margin-top: 10px; width: 0; min-width: 100%; max-width: 38ch; opacity: .62;
  font: 400 clamp(11px, .78vw, 12.5px)/1.5 var(--sans); }
/* the cartel: a flat sheet with its own hairlines running a little past the corners, like crop marks */
.cbox { position: absolute; left: 0; top: 0; background: var(--paper); visibility: hidden; }
.cbox::before, .cbox::after { content: ""; position: absolute; pointer-events: none; }
.cbox::before { left: -14px; right: -14px; top: 0; bottom: 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.cbox::after { top: -14px; bottom: -14px; left: 0; right: 0; border-left: 1px solid var(--line); border-right: 1px solid var(--line); }
.pins { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; }
.pins line { stroke: var(--line); stroke-width: 1; }
.pins rect { fill: var(--line); }
.pinmark { opacity: 0; }   /* not .pin: that is the sticky frame holding the whole scene */
.s1cap .p { display: block; margin-top: 10px; max-width: 38ch; opacity: .62; font: 400 clamp(11px, .78vw, 12.5px)/1.5 var(--sans); }
.finp { position: absolute; top: 30vh; right: calc(100% - var(--v2) + 2.6vw); width: 26ch; margin: 0; opacity: 0;
  color: var(--fg); font: 400 clamp(11px, .8vw, 13px)/1.6 var(--sans); }
.finp::before { content: ""; position: absolute; left: 0; right: 0; top: -14px; border-top: 1px solid var(--line); }
.s1cap .w, .card2 .w { text-decoration: underline 1px transparent; text-underline-offset: .16em; transition: text-decoration-color .4s var(--ease); }
.s1cap .w.on, .card2 .w.on { text-decoration-color: currentColor; }
.s1cap {
  position: absolute; left: 0; top: 0; opacity: 0;
  font: 500 clamp(12px, .92vw, 14px)/1.38 var(--sans); color: var(--ink);
}
.pin { position: sticky; top: 0; height: 100vh; height: 100svh; overflow: hidden; }

.plate { position: absolute; inset: 0; will-change: filter; opacity: 0; transition: opacity .6s linear; }
.ready .plate { opacity: 1; }
.lay {
  position: absolute; left: 0; top: 0;
  transform-origin: 0 0; will-change: transform;
  user-select: none; pointer-events: none;
}
.burn { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }

.grain {
  position: absolute; inset: -50%; pointer-events: none; opacity: .1; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  animation: grain .8s steps(5) infinite;
}
@keyframes grain {
  0% { transform: translate(0, 0); } 20% { transform: translate(-3%, 2%); }
  40% { transform: translate(2%, -4%); } 60% { transform: translate(-4%, -1%); }
  80% { transform: translate(3%, 3%); } 100% { transform: translate(0, 0); }
}

/* ---------- the frame ---------- */
.chrome i { position: absolute; background: var(--line); transition: background-color .5s var(--ease); }
.h { left: 0; right: 0; height: 1px; }
.h-top { top: var(--top); }
.h-low { top: 71%; }
.v { top: 0; bottom: 0; width: 1px; }
.v-1 { left: var(--v1); }
.v-2 { left: var(--v2); top: var(--top); }
.star { position: absolute; width: 12px; height: 12px; fill: var(--fg); transform: translate(-50%, -50%); top: 71%; transition: fill .5s var(--ease); }
.s-1 { left: var(--v1); }
.s-2 { left: var(--v2); }

.logo { position: absolute; top: 24px; left: calc(var(--v1) / 2); transform: translateX(-50%); width: 28px; height: 28px; }
.logo svg { width: 100%; height: 100%; fill: none; stroke: var(--fg); stroke-width: 1.4; transition: stroke .5s var(--ease); }
.menu { position: absolute; top: 108px; left: calc(var(--v1) / 2); transform: translateX(-50%); display: grid; grid-template-columns: 4px 4px; gap: 3px; }
.menu i { width: 4px; height: 4px; background: var(--fg); transition: background-color .5s var(--ease); }

.rail { position: absolute; top: 140px; left: var(--v1); list-style: none; }
.rail li {
  position: relative; height: 24px; padding-left: 34px;   /* tight enough that every label clears the cartels */
  font: 400 10px/1 var(--mono); letter-spacing: .2em; text-transform: uppercase;
  color: transparent; transition: color .4s var(--ease);
}
.rail li::before {
  content: ""; position: absolute; left: 0; top: 0; width: 8px; height: 1px;
  background: var(--line); transition: width .5s var(--ease), background-color .4s var(--ease);
}
.rail li.on { color: var(--fg); }
.rail li.on::before { width: 22px; background: var(--fg); }
.rail li { line-height: 0; }

.btn, .cta {
  display: inline-flex; align-items: center; gap: 14px; border: 0; cursor: pointer; appearance: none;
  overflow: hidden;
  background: var(--press); color: #fff; border-radius: 4px;
  font: 400 11px/1 var(--mono); letter-spacing: .2em; text-transform: uppercase;
  padding: 8px 8px 8px 14px;
  transition: background-color .26s var(--ease);
}
.btn { position: absolute; top: 22px; right: 2.1%; }
.cta { position: relative; }
.arr { position: relative; display: grid; place-items: center; width: 20px; height: 20px; border: 1px solid rgba(255, 255, 255, .35); border-radius: 2px; font-size: 11px; letter-spacing: 0; }
.btn:hover, .cta:hover { background: #22201c; }
/* while the film plays, the arrow becomes two bars, centred in their square by their own middle and not by a
   grid that still holds the arrow's line; a hairline under the words fills with the film. The label never
   changes, so the button keeps its width instead of jumping */
.playing .arr { color: transparent; }
.playing .arr::before, .playing .arr::after {   /* two bars as wide as the gap between them, as a pause is */
  content: ""; position: absolute; top: 50%; width: 3px; height: 10px; margin-top: -5px; background: #fff;
}
.playing .arr::before { left: calc(50% - 4.5px); }
.playing .arr::after { left: calc(50% + 1.5px); }
.btn::after, .cta::after {
  content: ""; position: absolute; left: 14px; right: 42px; bottom: 5px; height: 1px;
  background: rgba(255, 255, 255, .45); transform: scaleX(var(--p, 0)); transform-origin: 0 50%;
}

/* ---------- words ---------- */
.hero { position: absolute; left: calc(var(--v1) + 2.6vw); top: 25vh; width: min(48vw, 760px); }
.hero h1 {
  font: 300 clamp(40px, 4.6vw, 86px)/.98 var(--serif);
  letter-spacing: -.025em;
  text-shadow: 0 1px 40px rgba(0, 18, 60, .22);
}
.sub { margin-top: 1.1vw; font: 300 clamp(18px, 1.6vw, 28px)/1.2 var(--serif); }
.sub .ln { display: block; }
.cta { margin-top: 2.6vw; }

.lower {
  position: absolute; top: calc(71% + 26px); left: calc(var(--v1) + 2.6vw);
  display: grid; grid-template-columns: 15vw minmax(0, 26vw); align-items: start;
}
.tag {
  justify-self: start; padding: 6px 8px; border-radius: 3px;
  font: 400 9.5px/1 var(--mono); letter-spacing: .2em; text-transform: uppercase;
  background: rgba(255, 255, 255, .14); backdrop-filter: blur(10px) saturate(1.2);
}
.lower p { font: 500 clamp(13px, 1.02vw, 16px)/1.38 var(--sans); }

.hint {
  position: absolute; bottom: 26px; left: calc(var(--v1) + 2.6vw);
  display: flex; align-items: center; gap: 12px;
  font: 400 10px/1 var(--mono); letter-spacing: .2em; text-transform: uppercase;
}
.hint i { position: relative; width: 38px; height: 1px; background: var(--line); overflow: hidden; }
.hint i::after { content: ""; position: absolute; inset: 0; background: var(--fg); animation: hint 2.2s var(--ease) infinite; }
@keyframes hint { 0% { transform: translateX(-100%); } 60%, 100% { transform: translateX(100%); } }

/* line by line, pure opacity, no travel */
.ln { opacity: 0; transition: opacity .35s linear; transition-delay: calc(1.1s + var(--i) * .13s); }
.ready .ln { opacity: 1; }
.settled .ln { transition-delay: 0s; }   /* the stagger is for the entrance only: leaving must not lag */

/* the frame the hairlines close round the last words: a flat sheet, no hatching */
.frame { position: absolute; inset: 0; pointer-events: none; }
.fbox { position: absolute; left: 0; top: 0; width: 0; height: 0; background: var(--paper); }
.fl { position: absolute; left: 0; right: 0; top: 0; height: 1px; background: var(--line); opacity: 0; will-change: transform; }
.fl.fv { right: auto; bottom: 0; width: 1px; height: auto; }
.fs { top: 0; left: 0; opacity: 0; }
/* the crossing hairlines: brighter twins of the grid lines, full height and full width, no shadow */
.sweep {
  position: absolute; top: 0; bottom: 0; left: 0; width: 1px; opacity: 0;
  background: var(--line); will-change: transform;
}
.sweep.sweep-h { bottom: auto; right: 0; width: auto; height: 1px; }
.swst { top: 0; left: 0; opacity: 0; }
/* III → IV: the hairlines stay put and their colour follows what lies under them, pixel by pixel: dark on the paper,
   light on the painting (a cream line in difference at the strength of the usual hairlines) */
/* the blend sits on the layers themselves: on each line it only met the layer's own emptiness */
.chrome.diff, .frame.diff { mix-blend-mode: difference; }
.chrome.diff i, .sweep.diff { background: rgba(255, 239, 201, .3) !important; transition: none; }
/* IV → V: the grid's own lines are away travelling; their stand-ins carry them */
.chrome.lifted i { visibility: hidden; }
/* VII → VIII: the whole grid is away (lines and stars): its lines close into a frame round VIII's words, then open */
.chrome.lifted8 i, .chrome.lifted8 .star { visibility: hidden; }
/* VII → VIII: the right hairline, tilted, crossing the frame */
.swl { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; opacity: 0; }
.swl line { stroke-width: 1; }
.swl line.i { stroke: rgba(29, 28, 25, .55); }   /* on the paper */
.swl line.w { stroke: rgba(255, 255, 255, .85); } /* on the painting */

.endcard {
  position: absolute; left: 50%; top: 50%; width: max-content; max-width: 88vw;
  transform: translate(-50%, -50%); text-align: center; opacity: 0; color: var(--ink);
}
.endcard .tag { background: rgba(29, 28, 25, .08); display: inline-block; }
.endcard p { margin-top: 22px; font: 300 clamp(30px, 4.2vw, 72px)/1.04 var(--serif); letter-spacing: -.02em; }

@media (max-width: 720px) {
  :root { --v1: 12%; --v2: 92%; --top: 64px; }
  .hero { top: 20vh; width: 76vw; }
  .lower { grid-template-columns: 1fr; gap: 12px; }
  .lower p { max-width: 70vw; }
  .rail { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .grain, .hint i::after { animation: none; }
}
