/* nicolasweinbrecht.com: the ink story.
   Tokens follow docs/SPEC.md §3 and docs/experience/DESIGN.md. Two layouts share this file:
   the static flow (default: no JS, reduced motion, no WebGL) and the motion theatre
   (html.is-motion: every scene's stage is fixed, its section is a scroll spacer). */

@font-face {
  font-family: 'Kalnia';
  src: url('/fonts/kalnia-latin-wdth-normal.woff2') format('woff2-variations'),
       url('/fonts/kalnia-latin-wdth-normal.woff2') format('woff2');
  font-weight: 100 700;
  font-stretch: 100% 125%;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Schibsted Grotesk';
  src: url('/fonts/schibsted-grotesk-latin-wght-normal.woff2') format('woff2-variations'),
       url('/fonts/schibsted-grotesk-latin-wght-normal.woff2') format('woff2');
  font-weight: 400 900;
  font-style: normal;
  font-display: swap;
}

:root {
  /* palette (SPEC §3): nothing else, except each logo's own colours on hover */
  --paper: #FFFFFF;
  --ink: #111111;
  --red: #AB1215;
  --night: #0E0E0E;
  --graphite: #6B6B6B;

  --font-display: 'Kalnia', 'Iowan Old Style', 'Palatino Linotype', Georgia, serif;
  --font-text: 'Schibsted Grotesk', 'Helvetica Neue', Arial, sans-serif;

  /* type scale (Bringhurst's classic steps; display sizes follow the viewport) */
  --fs-micro: 12px;
  --fs-ui: 13px;
  --fs-caption: 15px;
  --lh-caption: 1.45;
  --fs-hero: clamp(52px, min(8.6vw, 13.2svh), 148px);
  --fs-title: clamp(60px, min(12.4vw, 21svh), 214px);
  --fs-finale: clamp(46px, min(9vw, 15svh), 164px);

  --gutter: clamp(16px, 2.8vw, 44px);
  --inset: clamp(16px, 1.9vw, 28px);
  --stage-h: 100vh;
  --toolbar-gap: 0px;

  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --ease-inout: cubic-bezier(.65, 0, .35, 1);
}
@supports (height: 100lvh) {
  :root { --stage-h: 100lvh; --toolbar-gap: calc(100lvh - 100svh); }
}

/* grounds: every surface sets its own text colours (text on red is always paper) */
[data-ground="paper"] { --bg: var(--paper); --fg: var(--ink); --fg-2: var(--graphite); --rule: var(--ink); }
[data-ground="night"] { --bg: var(--night); --fg: var(--paper); --fg-2: var(--paper); --rule: var(--paper); }
[data-ground="red"]   { --bg: var(--red);   --fg: var(--paper); --fg-2: var(--paper); --rule: var(--paper); }

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body {
  margin: 0;
  overflow-x: clip;
  background: var(--paper);
  color: var(--ink);
  font: 400 var(--fs-caption)/var(--lh-caption) var(--font-text);
  font-kerning: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
h1, h2, h3, p { margin: 0; }
img, canvas, svg { display: block; }
a { color: inherit; }
button { font: inherit; color: inherit; }

.vh {
  position: absolute !important; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
:focus-visible { outline: 2px solid var(--red); outline-offset: 3px; }
[data-ground="red"] :focus-visible { outline-color: var(--paper); }

.skip {
  position: fixed; left: var(--inset); top: var(--inset); z-index: 80;
  padding: 10px 14px; background: var(--ink); color: var(--paper);
  font: 500 var(--fs-ui)/1 var(--font-text); text-decoration: none; border-radius: 999px;
  transform: translateY(-200%);
}
.skip:focus-visible { transform: none; }

/* ------------------------------------------------------------------ chrome */
.chrome {
  position: fixed; inset: 0 0 auto 0; z-index: 60;
  display: flex; align-items: center; justify-content: space-between;
  padding: calc(var(--inset) + env(safe-area-inset-top, 0px)) calc(var(--inset) + env(safe-area-inset-right, 0px)) 0 calc(var(--inset) + env(safe-area-inset-left, 0px));
  pointer-events: none;
  color: var(--chrome-fg, var(--ink));
  --chrome-fg: var(--ink); --chrome-pill-bg: var(--paper); --chrome-pill-fg: var(--ink); --chrome-pill-line: var(--ink);
  --chrome-field: var(--paper);
}
html[data-chrome="night"] .chrome, html[data-chrome="red"] .chrome {
  --chrome-fg: var(--paper); --chrome-pill-bg: var(--paper); --chrome-pill-fg: var(--ink); --chrome-pill-line: var(--paper);
  --chrome-field: var(--night);
}
html[data-chrome="red"] .chrome { --chrome-field: var(--red); }
.chrome > * { pointer-events: auto; }
.monogram {
  display: inline-flex; align-items: center; justify-content: center;
  height: 36px; padding: 0 9px; margin-left: -9px;
  background: var(--chrome-field);   /* a small field of the ground colour, so art never runs under it */
  transition: color .4s var(--ease-out), background-color .4s var(--ease-out);
  font: 500 23px/1 var(--font-display);
  font-stretch: 100%;
  letter-spacing: -0.045em;
  color: var(--chrome-fg);
  text-decoration: none;
}
.pill {
  display: inline-flex; align-items: center; height: 34px; padding: 0 15px 1px;
  border: 1px solid var(--chrome-pill-line); border-radius: 999px;
  background: var(--chrome-pill-bg); color: var(--chrome-pill-fg);
  font: 500 var(--fs-ui)/1 var(--font-text); letter-spacing: 0.005em;
  text-decoration: none; white-space: nowrap;
  transition: background-color .4s var(--ease-out), color .4s var(--ease-out), border-color .4s var(--ease-out);
}
.pill:hover { background: var(--ink); color: var(--paper); border-color: var(--ink); }
/* on the finale the big button is the action: the pill steps aside (one action, one name, once) */
.pill { transition: background-color .4s var(--ease-out), color .4s var(--ease-out), border-color .4s var(--ease-out), opacity .35s var(--ease-out), visibility .35s; }
html[data-chrome="red"] .pill { opacity: 0; visibility: hidden; }
html[data-chrome="night"] .pill:hover, html[data-chrome="red"] .pill:hover { background: var(--night); color: var(--paper); border-color: var(--paper); }
.sound { position: fixed; right: var(--inset); bottom: var(--inset); }

.progress { display: none; }

/* ------------------------------------------------------------------ shared pieces */
/* the comic narration box: small grotesk, thin ink border, paper fill */
.box {
  background: var(--paper); color: var(--ink);
  border: 1px solid var(--ink);
  padding: 11px 14px 12px;
  font: 400 var(--fs-caption)/var(--lh-caption) var(--font-text);
  max-width: 31ch;
  hanging-punctuation: first;
}
.box p { text-wrap: pretty; }

/* a logo drawn as a mask, so one SVG serves ink, paper and any ground */
.logo-mask {
  display: block;
  height: calc(var(--logo-h, 24px) * var(--vs, 1));
  aspect-ratio: var(--ar, 4);
  background: currentColor;
  -webkit-mask: var(--mask) center / contain no-repeat;
  mask: var(--mask) center / contain no-repeat;
  translate: 0 calc(var(--nudge, 0) * 100%);
}

/* sliced type: the reference's end card; JS drives --fill (0..1) and --track (em) */
.sliced {
  display: inline-block;
  --fill: 1; --track: 0em; --band: 0.16em;
  letter-spacing: var(--track);
  -webkit-mask-image: repeating-linear-gradient(to bottom, #000 0, #000 calc(var(--band) * var(--fill)), transparent calc(var(--band) * var(--fill)), transparent var(--band));
  mask-image: repeating-linear-gradient(to bottom, #000 0, #000 calc(var(--band) * var(--fill)), transparent calc(var(--band) * var(--fill)), transparent var(--band));
}
.sliced.is-solid { -webkit-mask-image: none; mask-image: none; }

/* ------------------------------------------------------------------ hero */
.hero { background: var(--paper); color: var(--ink); }
.hero .stage {
  display: grid; place-items: center;
  min-height: 100svh;
  padding: calc(var(--inset) + 52px) var(--gutter) calc(var(--inset) + 8px);
}
.hero-plate {
  position: relative;
  max-width: 100%;
  display: flex; flex-direction: column; align-items: center;
  --portrait-h: min(calc(100svh - 96px - var(--fs-hero) * 1.15), calc((100vw - 2 * var(--gutter)) * 1.25), 860px);
}
.portrait {
  position: relative;
  height: var(--portrait-h);
  aspect-ratio: 4 / 5;
}
line-portrait, .portrait-fallback, .portrait-still {
  display: block; position: absolute; inset: 0; width: 100%; height: 100%;
}
.portrait-fallback[hidden] { display: none; }
.hero-name {
  position: relative; z-index: 1;
  margin-top: calc(var(--fs-hero) * -0.06);
  font: 500 var(--fs-hero)/0.98 var(--font-display);
  font-stretch: 100%;
  letter-spacing: -0.018em;
  text-align: center;
  white-space: nowrap;
}
.hero-caption {
  position: absolute; z-index: 2;
  left: 0; top: 71%;
  translate: -62% 0;
  width: max-content; max-width: 19ch;
}
/* desktop: the portrait is the hero (≥ 78 % of the viewport; 83 % at 1440×900) and the name is its
   label, sized from the portrait so it sits under the frame within its width. The chrome lives in
   the corners, so the portrait can rise to just under the top edge. Phones keep their own layout. */
@media (min-width: 768px) and (min-aspect-ratio: 3001/4000) {
  .hero .stage { padding: calc(var(--inset) + 4px) var(--gutter) calc(var(--inset) + 2px); }
  .hero-plate {
    --portrait-h: min(calc((100svh - 2 * var(--inset) - 6px) / 1.13), calc((100vw - 2 * var(--gutter)) * 1.25), 1120px);
  }
  .hero-name {
    --fs-hero: calc(var(--portrait-h) * 0.106);
    font-size: var(--fs-hero);
    margin-top: calc(var(--fs-hero) * 0.17);
    letter-spacing: -0.012em;
  }
}

/* ------------------------------------------------------------------ title card */
.titlecard { background: var(--night); color: var(--paper); }
.titlecard .stage { position: relative; overflow: hidden; min-height: 100svh; display: grid; place-items: center; padding: 18svh var(--gutter) 30svh; }
.titlecard-title {
  position: relative; z-index: 2;
  font: 400 var(--fs-title)/0.9 var(--font-display);
  font-stretch: 100%;
  letter-spacing: -0.02em;
  text-align: center;
}
.clouds { position: absolute; inset: auto 0 0 0; height: 34%; z-index: 1; pointer-events: none; }
.clouds img { position: absolute; left: -10%; width: 120%; height: auto; max-height: 100%; object-fit: cover; object-position: 50% 0; bottom: 0; max-width: none; will-change: transform; }

.marquee { position: absolute; z-index: 3; left: 0; right: 0; top: 49%; }
.mq-window {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 12%, #000 88%, transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 12%, #000 88%, transparent 100%);
  padding: 18px 0;
}
.mq-track { display: flex; align-items: center; gap: 0; margin: 0; padding: 0; list-style: none; width: max-content; }
.mq-item { flex: none; padding: 0 clamp(36px, 4.2vw, 72px); }
.mq-link {
  position: relative; display: block; color: var(--paper); text-decoration: none;
  --logo-h: clamp(26px, 3.1vw, 46px);
  padding: 14px 18px; margin: -14px -18px;
  border-radius: 2px;
}
.mq-link .logo-mask { transition: opacity .35s var(--ease-out); }
.mq-colour {
  position: absolute; left: 18px; top: 14px;
  height: calc(var(--logo-h) * var(--vs, 1)); width: auto; max-width: none;
  translate: 0 calc(var(--nudge, 0) * 100%);
  opacity: 0; transition: opacity .35s var(--ease-out);
}
.mq-link[data-surface="chip"]::before {
  content: ''; position: absolute; inset: 0; background: var(--paper);
  transform: scaleY(0); transform-origin: 50% 100%;
  transition: transform .45s var(--ease-out);
}
.mq-link:hover .mq-colour, .mq-link:focus-visible .mq-colour { opacity: 1; }
.mq-link:hover .logo-mask, .mq-link:focus-visible .logo-mask { opacity: 0; }
.mq-link[data-surface="chip"]:hover::before, .mq-link[data-surface="chip"]:focus-visible::before { transform: scaleY(1); }
.mq-link:focus-visible { outline-color: var(--paper); outline-offset: 2px; }

/* ------------------------------------------------------------------ chapters */
.chapter { background: var(--bg); color: var(--fg); }
.chapter .stage { position: relative; }
.art { position: relative; overflow: hidden; background: var(--bg); }
.art .key { width: 100%; height: auto; }
.art .frames { position: absolute; inset: 0; width: 100%; height: 100%; }
.layers { position: absolute; inset: 0; pointer-events: none; }
.layers img { position: absolute; height: auto; translate: -50% -100%; will-change: transform; }
.moment { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }

.plate { display: grid; gap: 4px; justify-items: start; color: var(--fg); --logo-h: 22px; }
.plate .plate-logo { margin-bottom: 6px; }
.plate-role { font: 500 var(--fs-ui)/1.3 var(--font-text); max-width: 22ch; }
.plate-years { font: 400 var(--fs-ui)/1.3 var(--font-text); color: var(--fg-2); font-variant-numeric: tabular-nums lining-nums; }

/* the hold (Nic chose "dot"): a quiet control in the plate. Touch shows it as the hint, keyboard
   focus reveals it; holding closes its ring. Static path: a plain play button. */
.hold {
  display: inline-flex; align-items: center; gap: 6px; margin: 8px -3px 0;
  padding: 2px 3px; border: 0; border-radius: 2px; background: none; color: var(--fg);
  font: 400 var(--fs-ui)/1.2 var(--font-text); cursor: pointer; text-align: inherit;
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
  touch-action: pan-y;   /* a swipe that starts on the hint still scrolls the page */
}
.hold[hidden] { display: none; }
.hold-ring { flex: none; width: 24px; height: 24px; overflow: visible; rotate: -90deg; }
.hold-core { fill: var(--red); }
.hold-line, .cursor-ring circle, .touch-ring circle {
  fill: none; stroke: currentColor; stroke-width: var(--line, 1.5px); stroke-linecap: round;
  stroke-dasharray: 1 1; stroke-dashoffset: 1; vector-effect: non-scaling-stroke;
}
/* over engraving the ink line sits on a crisp keyline of the other ink (like a map label) */
.cursor-ring .ring-key, .touch-ring .ring-key { stroke: var(--key, #fff); stroke-width: calc(var(--line, 1.5px) + 2.5px); }
.cursor-ring { opacity: 0; transition: opacity .12s linear; }
.cursor.has-line .cursor-ring { opacity: 1; }
.cursor-label { paint-order: stroke fill; -webkit-text-stroke: 2.25px var(--key, #fff); }
html[data-chrome="night"] .cursor, [data-ground="night"] .touch-ring { --key: var(--night); }
.hold.is-closed .hold-line, .cursor.is-closed .cursor-ring .ring-line, .touch-ring.is-closed .ring-line { animation: ring-close .34s var(--ease-out); }
.hold.is-closed .hold-core, .cursor.is-closed .cursor-core { animation: dot-close .34s var(--ease-out); }
@keyframes ring-close { 0% { stroke-width: var(--line, 1.5px); } 28% { stroke-width: calc(var(--line, 1.5px) * 2.4); } 100% { stroke-width: var(--line, 1.5px); } }
@keyframes dot-close { 0% { scale: 1; } 28% { scale: 1.7; } 100% { scale: 1; } }
.hold-core { transform-box: fill-box; transform-origin: center; }

/* the cursor over a scene that can be held: a 7th-red dot, "hold" beside it, the closing line */
.cursor { position: fixed; left: 0; top: 0; z-index: 70; pointer-events: none; opacity: 0; transition: opacity .18s linear; color: var(--ink); }
.cursor.is-on { opacity: 1; }
html[data-chrome="night"] .cursor { color: var(--paper); }
.cursor-core {
  position: absolute; left: -4px; top: -4px; width: 8px; height: 8px; border-radius: 50%;
  background: var(--red); outline: 1.5px solid var(--paper);   /* stays visible on the red sun */
}
.cursor-ring { position: absolute; left: -21px; top: -21px; overflow: visible; rotate: -90deg; }
.cursor-label { position: absolute; left: 12px; top: -7px; font: 500 11px/1 var(--font-text); letter-spacing: 0.02em; white-space: nowrap; transition: opacity .2s linear; }
.cursor.is-holding .cursor-label { opacity: 0; }

/* touch: the same line closes round the finger */
.touch-ring { position: absolute; left: -34px; top: -34px; z-index: 6; overflow: visible; rotate: -90deg; pointer-events: none; opacity: 0; transition: opacity .2s linear; color: var(--ink); }
[data-ground="night"] .touch-ring { color: var(--paper); }
.touch-ring.is-on { opacity: 1; }

/* ------------------------------------------------------------------ finale */
.finale {
  position: relative; z-index: 50;
  background: var(--red); color: var(--paper);
  min-height: 100svh;
  overflow-x: clip;
  display: grid; grid-template-rows: 1fr auto; grid-template-columns: minmax(0, 1fr);
  padding: 0 var(--gutter);
}
.torn { position: absolute; left: 0; right: 0; bottom: calc(100% - 1px); width: 100%; height: clamp(28px, 5vw, 72px); fill: var(--red); }
.finale-inner { display: grid; place-items: center; align-content: center; gap: clamp(36px, 6svh, 64px); padding: 14svh 0 6svh; text-align: center; }
.finale-title {
  font: 600 var(--fs-finale)/0.94 var(--font-display);
  font-stretch: 100%;
  letter-spacing: -0.02em;
}
.finale-title .sliced { display: block; }
/* desktop: each line stays one line while its tracking tightens (flex centring keeps an
   overflowing line centred), so the reveal never changes the page's height */
@media (min-width: 768px) and (min-aspect-ratio: 3001/4000) {
  .finale-title { display: flex; flex-direction: column; align-items: center; }
  .finale-title .sliced { white-space: nowrap; }
}
.cta-mount { position: relative; display: grid; place-items: center; min-height: 160px; min-width: 280px; }
/* the static ink pill is the symbiote's fallback look; live, the module paints the ink body in
   WebGL under the button's box (site/js/symbiote/README.md) */
.cta {
  position: relative; z-index: 1;
  display: inline-flex; align-items: center; justify-content: center;
  /* the finale's focal object (Nic: "BOLD"): 18 px / 26×44 on phones up to 26 px / 46×82 */
  --cta-k: clamp(0px, (100vw - 390px) / (1440 - 390), 1px);
  padding: calc(26px + 20 * var(--cta-k)) calc(44px + 38 * var(--cta-k)) calc(27px + 20 * var(--cta-k));
  border: 0; border-radius: 999px; background: var(--ink); color: var(--paper);
  font: 650 calc(18px + 8 * var(--cta-k))/1 var(--font-text); letter-spacing: -0.008em;
  cursor: pointer;
}
.footer { padding: 0 0 calc(22px + env(safe-area-inset-bottom, 0px)); text-align: center; font: 400 var(--fs-micro)/1.5 var(--font-text); color: var(--paper); }
.footer a { text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }
.footer-mail:not(:empty)::before { content: '. '; }

.gl-overlay { position: fixed; inset: 0; width: 100%; height: var(--stage-h); z-index: 40; pointer-events: none; visibility: hidden; }
.gl-overlay.is-on { visibility: visible; }

/* ================================================================== static flow */
html:not(.is-motion) .titlecard .stage { padding-bottom: 12svh; grid-template-rows: auto auto; align-content: center; gap: 10svh; }
html:not(.is-motion) .marquee { position: static; }
html:not(.is-motion) .mq-window { -webkit-mask-image: none; mask-image: none; }
html:not(.is-motion) .mq-track { flex-wrap: wrap; justify-content: center; width: auto; row-gap: 28px; }
html:not(.is-motion) .clouds { height: 40%; }
html:not(.is-motion) .chapter .stage { display: grid; gap: 22px; padding: 12svh var(--gutter); max-width: 1180px; margin: 0 auto; }
html:not(.is-motion) .chapter .art { aspect-ratio: 16 / 9; }
html:not(.is-motion) .chapter .layers img { translate: -50% -100%; }
html:not(.is-motion) .box-line { display: none; }
html:not(.is-motion) .chapter .key { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
html:not(.is-motion) .chapter .frames { display: none; }
html:not(.is-motion) .chapter .frames.is-playing { display: block; }
html:not(.is-motion) .chapter .caption { max-width: 46ch; }
html:not(.is-motion) .chapter .hold {
  justify-self: start; margin: 4px 0 0; padding: 10px 18px 11px; border: 1px solid var(--fg); border-radius: 999px;
  touch-action: manipulation;
}
html:not(.is-motion) .hold-ring { display: none; }
html:not(.is-motion) .hero .stage { min-height: 100svh; }
html:not(.is-motion) .finale { margin-top: 72px; }
@media (max-width: 767px), (max-aspect-ratio: 3/4) {
  html:not(.is-motion) .chapter .art { aspect-ratio: 2 / 3; }
}

/* ================================================================== motion theatre */
html.is-motion body { background: var(--night); }
html.is-motion .scene { position: relative; height: calc(var(--len) * 1vh); background: none; }
@supports (height: 100lvh) { html.is-motion .scene { height: calc(var(--len) * 1lvh); } }
html.is-motion .scene > .stage {
  position: fixed; left: 0; top: 0; width: 100%; height: var(--stage-h);
  min-height: 0;
  background: var(--bg);
  opacity: 0; pointer-events: none;
  z-index: var(--z, 10);
  transform-origin: 50% 50%;
}
html.is-motion .scene > .stage.is-on { opacity: 1; pointer-events: auto; }
html.is-motion .hero > .stage { padding-bottom: calc(var(--inset) + 8px + var(--toolbar-gap)); overflow: hidden; }
html.is-motion .hero > .stage, html.is-motion .titlecard > .stage { height: var(--stage-h); }

html.is-motion .chapter .art { position: absolute; inset: 0; }
html.is-motion .chapter .key { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transform-origin: var(--focus-x, 50%) var(--focus-y, 50%); will-change: transform; }
/* placement: chosen per chapter against its real composition (chapter.js CFG), so the caption
   never covers the figure or the red shape */
html.is-motion .chapter .caption, html.is-motion .chapter .plate { position: absolute; z-index: 4; inset: auto; }
html.is-motion .chapter .plate { background: var(--bg); padding: 10px 12px 9px; margin: -10px -12px; }
/* desktop placement: the exact complement of the phone query, so the two never mix */
@media (min-width: 768px) and (min-aspect-ratio: 3001/4000) {
  html.is-motion .chapter[data-cap-d^="t"] .caption { top: calc(var(--inset) + 76px); }
  html.is-motion .chapter[data-cap-d^="b"] .caption { bottom: calc(var(--inset) + 40px + var(--toolbar-gap)); }
  html.is-motion .chapter[data-cap-d$="l"] .caption { left: var(--gutter); }
  html.is-motion .chapter[data-cap-d$="r"] .caption { right: var(--gutter); }
  html.is-motion .chapter[data-plate-d^="t"] .plate { top: calc(var(--inset) + 76px); }
  html.is-motion .chapter[data-plate-d^="b"] .plate { bottom: calc(var(--inset) + 40px + var(--toolbar-gap)); }
  html.is-motion .chapter[data-plate-d$="l"] .plate { left: var(--gutter); }
  html.is-motion .chapter[data-plate-d$="r"] .plate { right: var(--gutter); justify-items: end; text-align: right; }
}
html.is-motion .chapter .dolly { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; visibility: hidden; }
html.is-motion .chapter .key-end { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; visibility: hidden; will-change: transform; pointer-events: none; }
html.is-motion .chapter .key-plate { position: absolute; max-width: none; visibility: hidden; opacity: 0; will-change: transform, opacity; pointer-events: none; }


/* caption box ink-in: the border draws, then the text unveils in slices (JS sets --ink, 0..1) */
html.is-motion .chapter .caption { --ink-in: 1; }
html.is-motion .chapter .caption p { -webkit-mask-image: repeating-linear-gradient(to bottom, #000 0, #000 calc(0.29em * var(--text-in, 1)), transparent calc(0.29em * var(--text-in, 1)), transparent 0.29em); mask-image: repeating-linear-gradient(to bottom, #000 0, #000 calc(0.29em * var(--text-in, 1)), transparent calc(0.29em * var(--text-in, 1)), transparent 0.29em); }
html.is-motion .chapter .caption.is-inked p { -webkit-mask-image: none; mask-image: none; }

html.is-motion .chapter > .stage { touch-action: pan-y; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; overflow: hidden; }
html.is-motion .chapter .frames { transition: opacity .25s linear; }
html.is-motion .chapter .frames.is-hold { transition: none; }
/* a hold clip enters as a line-screen (7 px pitch, the melt's): its strips widen with --ls */
html.is-motion .chapter .frames.is-hold:not(.is-full) {
  -webkit-mask-image: repeating-linear-gradient(90deg, #000 0, #000 calc(var(--ls, 1) * 7px), transparent calc(var(--ls, 1) * 7px), transparent 7px);
  mask-image: repeating-linear-gradient(90deg, #000 0, #000 calc(var(--ls, 1) * 7px), transparent calc(var(--ls, 1) * 7px), transparent 7px);
}
html.is-motion .hold { opacity: 0; transition: opacity .3s var(--ease-out); }
html.is-motion .hold.is-live { opacity: 1; }
/* with a mouse the dot cursor is the invitation; the control stays for the keyboard */
@media (hover: hover) and (pointer: fine) {
  html.is-motion .hold:not(:focus-visible) { position: absolute; width: 1px; height: 1px; margin: 0; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
}
.chapter[data-slug="greensheart"] .art > .key, .chapter[data-slug="greensheart"] .art > .frames { scale: calc(1 + var(--beat, 0) * 0.035); }

/* the caption box inks in: an SVG border draws round, the paper fill wipes down, the text unslices */
html.is-motion .chapter .caption { isolation: isolate; }
html.is-motion .chapter .caption.is-drawing { border-color: transparent; background: transparent; }
html.is-motion .chapter .caption.is-drawing::before {
  content: ''; position: absolute; inset: 0; z-index: -1; background: var(--paper);
  transform: scaleY(var(--fill-in, 1)); transform-origin: 50% 0;
}
.box-line { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.box-line rect { x: 0.5px; y: 0.5px; width: calc(100% - 1px); height: calc(100% - 1px); fill: none; stroke: var(--ink); stroke-width: 1; stroke-dasharray: 1 1; vector-effect: non-scaling-stroke; }

html.is-motion .stage.is-holdable { cursor: none; }
html.is-motion .stage.is-holdable a, html.is-motion .stage.is-holdable .box { cursor: auto; }
html.is-motion .progress {
  display: block; position: fixed; right: 0; top: 0; z-index: 60; width: 2px; height: var(--stage-h); pointer-events: none;
}
html.is-motion .progress span { display: block; width: 2px; height: 9%; background: var(--red); will-change: transform; }
html[data-chrome="red"] .progress span { background: var(--paper); }

html.is-motion .finale { min-height: var(--stage-h); }

/* the marquee in the theatre sits low in the title card */
html.is-motion .titlecard .stage { padding: 0 var(--gutter); }
html.is-motion .titlecard-title { position: absolute; left: var(--gutter); right: var(--gutter); top: 12%; }

/* ================================================================== phones */
@media (max-width: 767px), (max-aspect-ratio: 3/4) {
  :root { --fs-caption: 14px; }
  .hero .stage { padding-top: calc(var(--inset) + 56px); }
  .hero-plate { --portrait-h: min(calc(100svh - 120px - var(--fs-hero) * 2.1), calc((100vw - 2 * var(--gutter)) * 1.25)); }
  .hero-name { white-space: normal; max-width: min(7.2em, 100%); --fs-hero: clamp(42px, 14vw, 88px); font-size: var(--fs-hero); line-height: 0.94; margin-top: calc(var(--fs-hero) * 0.02); }
  .hero-caption { left: 0; translate: -10px 0; top: 76%; max-width: 17ch; }
  .titlecard-title { font-size: clamp(56px, 20vw, 120px); line-height: 0.92; }
  .titlecard-title .sliced { max-width: 6em; }
  .mq-item { padding: 0 26px; }
  .mq-link { --logo-h: 26px; }

  html.is-motion .scene { height: calc(var(--len-m, var(--len)) * 1vh); }
  @supports (height: 100lvh) { html.is-motion .scene { height: calc(var(--len-m, var(--len)) * 1lvh); } }
  html.is-motion .chapter .caption { inset: auto var(--gutter) auto var(--gutter); max-width: none; }
  html.is-motion .chapter[data-cap-m="bottom"] .caption { bottom: calc(var(--inset) + 12px + var(--toolbar-gap)); }
  html.is-motion .chapter[data-cap-m="top"] .caption { top: calc(var(--inset) + 58px); }
  html.is-motion .chapter[data-cap-m="at"] .caption { top: var(--cap-top-m, 30%); }
  html.is-motion .chapter .plate { inset: auto; justify-items: start; text-align: left; --logo-h: 18px; }
  html.is-motion .chapter[data-plate-m="top"] .plate { top: calc(var(--inset) + 58px); left: var(--gutter); }
  html.is-motion .chapter[data-plate-m="bl"] .plate { bottom: calc(var(--inset) + 12px + var(--toolbar-gap)); left: var(--gutter); }
  html.is-motion .chapter[data-plate-m="br"] .plate { bottom: calc(var(--inset) + 12px + var(--toolbar-gap)); right: var(--gutter); justify-items: end; text-align: right; }
  .finale-title { --fs-finale: clamp(42px, 13.2vw, 80px); font-size: var(--fs-finale); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}
