/* styles.css
   konadami.com
   A thermal receipt system: printed paper, monospaced type, dashed tear lines.
   The objects on it are real things: a black leather organiser, a black
   envelope, a photo, sticky notes. Handwriting stays handwriting. */

/* ============================================================
   1. Tokens
   ============================================================ */

:root {
  /* Thermal paper and its ink. The ink is never pure black: a thermal head
     prints a soft charcoal that fades a little at the edges of the roll. */
  --paper:      #F1EFE9;
  --paper-hi:   #F6F4EF;
  --paper-lo:   #E6E3DB;
  --ink:        #1D1D1C;
  --ink-body:   #2A2927;
  --ink-soft:   #5A5852;
  --ink-faint:  #8E8B83;
  --rule:       #B9B5AB;

  /* Accents. One per project, bound to --accent on the project element. */
  --accent-reel:         #1D1D1C;
  --accent-acg:          #2E5C8A;
  --accent-becreatives:  #8A4D2E;
  --accent-wheelsys:     #3D2E8A;
  --accent-fitnessmeals: #2E8C6D;
  --accent-thesoul:      #6A2E8C;

  --ph-fill: #DEDBD3;

  /* Markers: connector nodes, chips, the panels a work builds. A work can
     carry its own, and the modal sets it for its own contents. */
  --mark: #2E2A8E;
  /* A second marker, for work that is itself colour coded. */
  --mark-alt: #2E2A8E;
  /* A third, for the single line a work calls out against the rest. */
  --mark-call: #2E2A8E;

  /* Black leather, amber saddle stitching, nickel hardware. */
  --leather:     #17181B;
  --leather-hi:  #26282D;
  --leather-lo:  #0D0E10;
  --stitch:      #B58E45;
  --nickel-hi:   #EEF0F2;
  --nickel:      #A5AAB0;
  --nickel-lo:   #6C7278;

  /* Black envelope stock. */
  --env-hi:  #2A2B2F;
  --env:     #1E1F22;
  --env-lo:  #121315;

  /* Sticky notes and the chapter dividers. */
  --sticky:    #EFE5B0;
  --sticky-lo: #E6D99A;
  --tab-1: #6FBF9B;
  --tab-2: #E8C86A;
  --tab-3: #DE8AAE;
  --tab-4: #74B8D8;

  --mono:   'IBM Plex Mono', 'Noto Sans Mono', ui-monospace, 'SFMono-Regular', Menlo, Consolas, monospace;
  --display: 'Dirty Bleed Display', 'IBM Plex Mono', sans-serif;
  --pen:     'Caveat', cursive;

  /* Photocopy grit: sparse toner specks, and the odd larger fleck of dust. */
  --speckle: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='s' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.5' numOctaves='1' seed='21' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.09 0 0 0 0 0.09 0 0 0 0 0.09 -15 0 0 0 5.35'/%3E%3C/filter%3E%3Crect width='300' height='300' filter='url(%23s)'/%3E%3C/svg%3E");
  --dust: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='520' height='520'%3E%3Cfilter id='d' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.28' numOctaves='3' seed='44' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.07 0 0 0 0 0.07 0 0 0 0 0.07 -26 0 0 0 7.3'/%3E%3C/filter%3E%3Crect width='520' height='520' filter='url(%23d)'/%3E%3C/svg%3E");

  /* Textures, drawn once as tiles and layered wherever a surface needs them. */
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)' opacity='0.24'/%3E%3C/svg%3E");
  --grain-soft: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='3' seed='5' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)' opacity='0.14'/%3E%3C/svg%3E");
  --leather-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='l' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.25' numOctaves='3' seed='9' stitchTiles='stitch'/%3E%3CfeDiffuseLighting surfaceScale='1.5' diffuseConstant='1' lighting-color='%23ffffff'%3E%3CfeDistantLight azimuth='225' elevation='56'/%3E%3C/feDiffuseLighting%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23l)'/%3E%3C/svg%3E");

  /* The print head lays down rows, and the roll greys a touch at its edges. */
  --bands: repeating-linear-gradient(180deg, rgba(29, 29, 28, 0.022) 0 1px, transparent 1px 4px);
  --fade:  linear-gradient(90deg, rgba(29, 29, 28, 0.035), transparent 14%, transparent 86%, rgba(29, 29, 28, 0.035));

  --shadow-rest: 0 1px 2px rgba(0, 0, 0, 0.06), 0 8px 20px rgba(0, 0, 0, 0.08);
  --shadow-lift: 0 2px 4px rgba(0, 0, 0, 0.08), 0 16px 32px rgba(0, 0, 0, 0.14);

  /* The whole motion vocabulary. Three curves, nothing else. */
  --enter: cubic-bezier(0.22, 1, 0.36, 1);
  --micro: cubic-bezier(0.34, 1.3, 0.64, 1);
  --exit:  ease-in;
  --t-enter: 420ms;
  --t-micro: 180ms;
  --t-exit:  240ms;
}

/* ============================================================
   2. Type
   ============================================================ */

@font-face {
  font-family: 'Dirty Bleed Display';
  src: url('assets/type/DirtyBleedDisplay.woff2') format('woff2'),
       url('assets/type/DirtyBleedDisplay.woff') format('woff');
  font-display: swap;
}

*,
*::before,
*::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background-color: var(--paper);
  background-image: var(--grain), var(--bands);
  background-blend-mode: multiply, normal;
  color: var(--ink-body);
  font-family: var(--mono);
  font-size: 15px;
  line-height: 1.7;
  font-weight: 400;
  /* A thermal head bleeds its dots very slightly into the paper. */
  text-shadow: 0 0 0.35px rgba(29, 29, 28, 0.3);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

body.is-locked { overflow: hidden; }

:lang(el),
.greek { font-family: 'Noto Sans Mono', var(--mono); }

.t-identity {
  font-size: 19px;
  font-weight: 500;
  letter-spacing: 0.02em;
  line-height: 1.5;
  color: var(--ink);
}

.t-name {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.3em;
  line-height: 1.3;
  text-transform: uppercase;
  color: var(--ink);
}

/* The display face. Wide, heavy and bled, for the few words that are meant
   to be seen before they are read. */
.t-title {
  font-family: var(--display);
  font-size: 40px;
  font-weight: 400;
  letter-spacing: 0.01em;
  line-height: 1;
  color: var(--ink);
  text-shadow: none;
}

.t-modal-title {
  font-family: var(--display);
  font-size: 22px;
  font-weight: 400;
  letter-spacing: 0.02em;
  line-height: 1.12;
  text-transform: uppercase;
  color: var(--ink);
  text-shadow: none;
  margin: 0;
}

.t-body {
  font-size: 14.5px;
  font-weight: 400;
  line-height: 1.75;
  color: var(--ink-body);
}

.t-credit {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.02em;
  line-height: 1.55;
  color: var(--ink-soft);
}

.t-eyebrow {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  line-height: 1.3;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.t-caption {
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.03em;
  line-height: 1.45;
  color: var(--ink-faint);
}

/* Pen handwriting. */
.t-annotation {
  font-family: var(--pen);
  font-size: 28px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--ink-soft);
  text-shadow: none;
}

.t-measure { max-width: 64ch; }

.svg-defs { position: absolute; width: 0; height: 0; overflow: hidden; }

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--ink);
  color: var(--paper);
  padding: 10px 16px;
  z-index: 300;
}

.skip-link:focus { left: 8px; top: 8px; }

:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }

a { color: var(--ink); }

/* ============================================================
   3. Thermal surfaces and receipt furniture
   ============================================================ */

/* Every printed surface is the same stock. */
.book__left,
.book__right,
.leaf__face,
.modal,
.postcard__face,
.clipnote__sheet,
.env-letter,
.photo__frame,
.nb-page,
.nb-face.nb-sheet__front,
.nb-face.nb-sheet__back {
  background-color: var(--paper);
  background-image: var(--grain), var(--bands), var(--fade);
  background-blend-mode: multiply, normal, normal;
}

/* A receipt tears off its roll with a sawtooth at top and bottom. Two thin
   masked strips sit just outside the edges, so the panel itself keeps its
   shadow and never needs a mask of its own. */
.receipt { position: relative; }

.receipt::before,
.receipt::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  height: 6px;
  background: var(--paper);
  pointer-events: none;
}

.receipt::before {
  top: -5px;
  -webkit-mask: conic-gradient(from 135deg at 50% 0, #000 0 90deg, #0000 0) 0 0 / 12px 100% repeat-x;
          mask: conic-gradient(from 135deg at 50% 0, #000 0 90deg, #0000 0) 0 0 / 12px 100% repeat-x;
}

.receipt::after {
  bottom: -5px;
  -webkit-mask: conic-gradient(from -45deg at 50% 100%, #000 0 90deg, #0000 0) 0 0 / 12px 100% repeat-x;
          mask: conic-gradient(from -45deg at 50% 100%, #000 0 90deg, #0000 0) 0 0 / 12px 100% repeat-x;
}

/* The dashed line a receipt uses between sections. */
.rcpt-rule {
  height: 1px;
  margin: 22px 0;
  background: repeating-linear-gradient(90deg, var(--ink-soft) 0 6px, transparent 6px 11px);
  opacity: 0.7;
}

.rcpt-sub {
  margin: 6px 0 0;
  text-align: center;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.rcpt-stamp {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  margin: 18px 0 0;
  font-size: 11.5px;
  letter-spacing: 0.12em;
  color: var(--ink-soft);
}

.barcode {
  width: min(230px, 72%);
  margin: 4px auto 0;
  text-align: center;
}

.barcode svg {
  display: block;
  width: 100%;
  height: 42px;
  fill: var(--ink);
}

.barcode__num {
  display: block;
  margin-top: 6px;
  font-size: 10.5px;
  letter-spacing: 0.34em;
  color: var(--ink-soft);
}

/* ============================================================
   4. The landing page. One viewport, no scroll.
   ============================================================ */

.page {
  position: relative;
  transition: opacity var(--t-enter) var(--enter), filter var(--t-enter) var(--enter);
}

/* While the book or a modal is open, the landing sits back.

   It sits back on opacity alone. It used to be blurred as well, and a blur
   across a whole viewport is a layer the compositor has to keep re-making:
   underneath a playing film it took enough off the frame rate that picture
   and sound came apart. Tested by elimination in the browser, with the
   blur the only thing changed. At eighteen percent there is little left to
   soften, so nothing is really lost. Do not put it back. */
.page.is-behind {
  opacity: 0.18;
  pointer-events: none;
}

.landing {
  position: relative;
  height: 100vh;
  height: 100dvh;
  min-height: 620px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  padding: clamp(26px, 4vh, 50px) 5vw clamp(16px, 3vh, 32px);
}

/* The homepage is a photocopy: a grey sheet, toner specks and dust, the
   crease of a fold each way, and the edges gone dark where the lid did not
   sit flat. */
.landing {
  background-color: #D7D5CF;
  background-image:
    var(--dust),
    var(--speckle),
    var(--grain),
    linear-gradient(90deg, transparent calc(50% - 1px), rgba(0, 0, 0, 0.07) calc(50% - 1px), rgba(255, 255, 255, 0.4) 50%, transparent calc(50% + 1.5px)),
    linear-gradient(180deg, transparent calc(57% - 1px), rgba(0, 0, 0, 0.06) calc(57% - 1px), rgba(255, 255, 255, 0.34) 57%, transparent calc(57% + 1.5px)),
    radial-gradient(ellipse 78% 72% at 50% 46%, transparent 52%, rgba(0, 0, 0, 0.2)),
    repeating-linear-gradient(180deg, rgba(0, 0, 0, 0.02) 0 1px, transparent 1px 3px);
  background-blend-mode: normal, normal, multiply, normal, normal, normal, normal;
}

.landing__head {
  position: relative;
  z-index: 3;
  text-align: center;
  flex: none;
}

.landing__name {
  margin: 0 0 12px;
  font-size: clamp(14px, 1.05vw, 18px);
  font-weight: 700;
  letter-spacing: 0.34em;
  color: var(--ink);
}

.landing__identity {
  margin: 0 auto 12px;
  max-width: 1100px;
  font-family: var(--display);
  font-size: clamp(26px, 3.1vw, 46px);
  font-weight: 400;
  letter-spacing: 0;
  line-height: 1.02;
  color: var(--ink);
  text-shadow: none;
}

/* The role line, printed as a strip of label tape so it reads at a glance. */
.landing__eyebrow {
  display: inline-block;
  margin: 2px 0 0;
  padding: 5px 12px 4px;
  font-size: clamp(12px, 0.95vw, 16px);
  font-weight: 700;
  letter-spacing: 0.22em;
  color: #EEECE6;
  background: var(--ink);
}

/* The tear line under the header, the way a receipt closes its top block. */
.landing__head::after {
  content: '';
  display: block;
  width: min(440px, 64%);
  height: 1px;
  margin: 16px auto 0;
  background: repeating-linear-gradient(90deg, var(--ink-soft) 0 6px, transparent 6px 11px);
  opacity: 0.55;
}

/* The field the objects are placed on. Everything below is positioned
   against this box, so the composition scales with the viewport. */
.landing__stage {
  position: relative;
  z-index: 2;
  flex: 1 1 auto;
  min-height: 0;
}

/* The watermark. Texture, not content, sitting under everything. */
/* The word, set huge in the display face and screened into halftone dots,
   the way a photocopier renders a grey. It sits under everything. */
.watermark {
  position: absolute;
  left: 50%;
  top: 46%;
  transform: translate(-50%, -50%);
  z-index: 0;
  display: flex;
  align-items: center;
  gap: 0.05em;
  font-family: var(--display);
  font-size: clamp(56px, 8.4vw, 190px);
  line-height: 0.9;
  white-space: nowrap;
  color: var(--ink);
  opacity: 0;
  text-shadow: none;
  pointer-events: none;
  user-select: none;
  -webkit-mask: radial-gradient(circle, #000 1.3px, transparent 1.9px) 0 0 / 4.4px 4.4px;
          mask: radial-gradient(circle, #000 1.3px, transparent 1.9px) 0 0 / 4.4px 4.4px;
}

.watermark__star { width: 0.52em; height: 0.52em; flex: none; }
.watermark__star line { stroke: var(--ink); stroke-width: 15; stroke-linecap: round; }

/* ============================================================
   5. Capability labels
   ============================================================ */

.caps {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
}

.cap {
  position: absolute;
  left: var(--x);
  top: var(--y);
  display: flex;
  align-items: flex-start;
  white-space: nowrap;
}

.cap__square {
  width: 7px;
  height: 7px;
  margin-top: 6px;
  background: var(--ink);
  flex: none;
  transform: scale(0);
}

.cap__rule {
  width: 14px;
  height: 1px;
  margin-top: 9px;
  background: var(--ink-soft);
  flex: none;
  transform: scaleX(0);
  transform-origin: left center;
}

/* Printed white out of a solid black block, like a strip of label tape. */
.cap__box {
  background: var(--ink);
  padding: 4px 10px 3px;
  color: #EEECE6;
  text-shadow: none;
  opacity: 0;
  transform: translateX(6px);
}

/* The three stage assembly. The per label delay is set from the script. */
.is-lit .cap__square {
  animation: cap-square var(--t-micro) var(--micro) forwards;
  animation-delay: var(--d);
}

.is-lit .cap__rule {
  animation: cap-rule 200ms ease-out forwards;
  animation-delay: calc(var(--d) + 60ms);
}

.is-lit .cap__box {
  animation: cap-box 220ms ease-out forwards;
  animation-delay: calc(var(--d) + 120ms);
}

@keyframes cap-square { to { transform: scale(1); } }
@keyframes cap-rule   { to { transform: scaleX(1); } }
@keyframes cap-box    { to { opacity: 1; transform: translateX(0); } }

/* ============================================================
   6. Page load sequence
   ============================================================ */

.rise { opacity: 0; transform: translateY(8px); }

.is-lit .rise {
  animation: rise 500ms var(--enter) forwards;
  animation-delay: var(--d, 0ms);
}

@keyframes rise { to { opacity: 1; transform: translateY(0); } }

.is-lit .watermark { animation: watermark 900ms var(--enter) forwards; }
@keyframes watermark { to { opacity: 0.9; } }

/* ============================================================
   7. The three landing objects
   ============================================================ */

.thing {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--w);
  z-index: 4;
  padding: 0;
  border: 0;
  background: none;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
  opacity: 0;
}

.is-lit .thing { animation: rise 500ms var(--enter) forwards; animation-delay: var(--d); }

/* Centred on its own width. Margin, not transform, because the entrance
   animation owns transform and would otherwise cancel the centring. */
.thing--centred { margin-left: calc(var(--w) / -2); }
.thing.is-dragging { cursor: grabbing; z-index: 30; }

/* -- Portrait -------------------------------------------------------
   Printed on the same stock as everything else, so the photograph takes a
   thermal halftone: grey, contrasty, and broken into a fine dot screen.
   ------------------------------------------------------------------- */

/* The card is tipped two degrees, which lifts its top corner about four
   pixels above the box it is measured by. Without this the corner came
   within thirteen pixels of the label above it, and read as touching. */
.photo { --w: 224px; margin-top: 12px; }

.photo__frame {
  position: relative;
  padding: 9px 9px 8px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12), 0 10px 22px rgba(0, 0, 0, 0.12);
  transform: rotate(2deg);
  transition: transform 260ms var(--enter);
}

.photo:hover .photo__frame { transform: rotate(3.4deg) scale(1.02); }

.photo__well {
  position: relative;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: var(--ph-fill);
}

/* The same two prints as the About me card, cropped to the head and
   shoulders and read from the top. Halftone at rest, like every tile.

   The well it sits in was built for a single photograph that it screened
   itself: it hides its picture until a load flag arrives, drains the
   colour out of it and lays a dot pattern over the top. This portrait
   brings its own screen as a second image, so all three of those are
   turned off for it. */
.photo__well--port { background: #F7F4EC; --x: -400px; --y: -400px; }
.photo__well.photo__well--port img { opacity: 1; filter: none; }
.photo__well--port::after { display: none; }

.photo__colour,
.photo__dots {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
}

.photo__dots {
  opacity: 1;
  transition: opacity 300ms var(--enter);
  -webkit-mask-image: radial-gradient(circle 86px at var(--x) var(--y),
    transparent 0%, transparent 40%, #000 100%);
  mask-image: radial-gradient(circle 86px at var(--x) var(--y),
    transparent 0%, transparent 40%, #000 100%);
}

@media (prefers-reduced-motion: reduce) {
  .photo__dots { transition: none; }
}

.photo__well img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  filter: grayscale(1) contrast(1.55) brightness(1.08);
  transition: opacity 260ms var(--enter);
}

/* The dot screen a copier prints a photograph through. */
.photo__well::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  background-image: radial-gradient(rgba(29, 29, 28, 0.55) 0.8px, transparent 1.3px);
  background-size: 3.6px 3.6px;
  mix-blend-mode: multiply;
  opacity: 0.75;
}

/* Only a loaded file is shown, so a missing one leaves the placeholder alone. */
.photo__well img.is-ready { opacity: 1; }
.photo__well img.is-ready.is-hidden { opacity: 0; }
.photo__well .media__ph .t-caption { font-size: 9px; letter-spacing: 0; }

.photo__caption {
  display: block;
  text-align: center;
  padding: 12px 4px 7px;
  font-size: 19px;
  color: var(--ink);
}

/* A piece of tape at one corner. */
.photo__tape {
  position: absolute;
  top: -12px;
  right: -13px;
  width: 62px;
  height: 22px;
  transform: rotate(-38deg);
  background: rgba(222, 216, 202, 0.6);
  border-left: 1px solid rgba(0, 0, 0, 0.05);
  border-right: 1px solid rgba(0, 0, 0, 0.05);
  z-index: 5;
  pointer-events: none;
}

/* -- Leather ---------------------------------------------------------
   One recipe for every leather surface: an embossed grain tile blended
   into a graded black, with a soft sheen where the light catches it.
   ------------------------------------------------------------------- */

.nb-board,
.nb-face.nb-cover__front,
.nb-face.nb-cover__inside,
.nb-snap,
.book__spread {
  background-color: var(--leather);
  background-image:
    radial-gradient(ellipse 120% 80% at 18% 0%, rgba(255, 255, 255, 0.075), transparent 55%),
    var(--leather-grain),
    linear-gradient(140deg, var(--leather-hi), var(--leather) 45%, var(--leather-lo));
  background-size: auto, 240px 240px, auto;
  background-blend-mode: normal, overlay, normal;
}

/* Saddle stitching, run a few millimetres in from the edge. */
.nb-cover__front::after,
.nb-cover__inside::after,
.book__spread::before {
  content: '';
  position: absolute;
  inset: 7px;
  border: 1.5px dashed var(--stitch);
  border-radius: 6px;
  opacity: 0.78;
  pointer-events: none;
}

/* On the face, the stitching starts after the spine. */
.nb-cover__front::after { left: calc(13% + 4px); }

/* -- Notebook -------------------------------------------------------
   A bound black leather notebook with its title stamped on the cover.
   Hover runs in two steps. The cover turns over to the left, showing the
   bare leather inside it, while the book slides back so the open spread
   stays centred. Then the first sheet turns across after it, uncovering
   the page with the copy. Leaving runs the same steps backwards.
   ------------------------------------------------------------------- */

.notebook {
  --w: 280px;
  --rule: 22px;
  --turn: cubic-bezier(0.45, 0.05, 0.25, 1);
}

.nb {
  position: relative;
  aspect-ratio: 4 / 3;
}

/* Every part is drawn on the right hand half of this box, the spine down
   its middle. Shut, the book is moved half a page left so the cover sits
   centred. The parts are layered by z-index, not by depth, so a turning
   page never cuts through the one it lands on. */
.nb-book {
  position: absolute;
  inset: 0;
  perspective: 1300px;
  perspective-origin: 50% 45%;
  transform: translateX(-25%);
  /* Closing: it slides back with the cover. */
  transition: transform 440ms var(--turn) 300ms;
}

/* The back board. Open, it shows as a leather border round the page. */
.nb-board {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  right: 0;
  z-index: 1;
  border-radius: 2px 8px 8px 2px;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.05), 0 12px 24px rgba(0, 0, 0, 0.32);
}

/* The page with the copy, and the first sheet over it. Both are inset from
   the board, with the edges of the pages under them showing at the side. */
.nb-page,
.nb-sheet {
  position: absolute;
  top: 6px;
  bottom: 6px;
  left: 50%;
  right: 7px;
}

.nb-page {
  z-index: 2;
  border-radius: 0 2px 2px 0;
  overflow: hidden;
  box-shadow: inset 12px 0 14px -12px rgba(0, 0, 0, 0.45), 1px 0 0 #D8D3C8, 2px 0 0 #B9B4A9, 3px 0 0 #D8D3C8;
}

/* Ruled paper. The rules are drawn on the same rhythm the copy is set to,
   offset so a rule lands exactly on the first baseline of the copy,
   measured against Caveat at this size. */
.nb-page,
.nb-face.nb-sheet__back {
  background-image:
    repeating-linear-gradient(
      to bottom,
      transparent 0 calc(var(--rule) - 1px),
      rgba(29, 29, 28, 0.13) calc(var(--rule) - 1px) var(--rule)
    ),
    var(--grain);
  background-blend-mode: normal, multiply;
  background-position: 0 20.67px, 0 0;
}

/* Written on the page, not printed on it: two words, one to a ruling, in
   ink, tipped a couple of degrees off square the way a hand writes. The
   line height is two rulings so each baseline lands on a ruled line. */
.nb-page__word {
  position: absolute;
  left: 13%;
  right: 8%;
  top: 22px;
  margin: 0;
  transform: rotate(-2deg);
  transform-origin: left top;
  font-family: var(--pen);
  font-size: 24px;
  font-weight: 600;
  line-height: calc(var(--rule) * 2);
  color: var(--ink);
  text-shadow: none;
}

.nb-page__line {
  display: block;
  /* Long words are brought in rather than allowed off the page. */
  max-width: 100%;
  white-space: nowrap;
}

.nb-sheet {
  z-index: 3;
  transform-origin: left center;
  transform-style: preserve-3d;
  transform: rotateY(0deg);
  /* Closing: the sheet turns back first. */
  transition: transform 340ms var(--turn) 0ms;
}

.nb-face {
  position: absolute;
  inset: 0;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}

/* The face of the sheet: clean, shaded where it curves into the spine. */
.nb-face.nb-sheet__front {
  border-radius: 0 2px 2px 0;
  background-image:
    linear-gradient(90deg, rgba(0, 0, 0, 0.18), transparent 14%),
    var(--grain);
  background-blend-mode: normal, multiply;
}

/* Its back, ruled, shaded at the spine once it lies on the left. */
.nb-face.nb-sheet__back {
  transform: rotateY(180deg);
  border-radius: 2px 0 0 2px;
  box-shadow: inset -12px 0 14px -12px rgba(0, 0, 0, 0.45);
}

/* The hard cover, hinged at the spine. */
.nb-cover {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  right: 0;
  z-index: 5;
  transform-origin: left center;
  transform-style: preserve-3d;
  transform: rotateY(0deg);
  /* Closing: the cover waits for the sheet, and comes back over it. */
  transition: transform 440ms var(--turn) 300ms, z-index 0s linear 300ms;
}

.nb-face.nb-cover__front {
  container-type: inline-size;
  border-radius: 3px 9px 9px 3px;
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.05),
    inset 0 -18px 24px -20px rgba(0, 0, 0, 0.7),
    0 12px 24px rgba(0, 0, 0, 0.32);
}

/* The inside of the cover: bare leather, darker toward the spine. */
.nb-face.nb-cover__inside {
  transform: rotateY(180deg);
  border-radius: 9px 3px 3px 9px;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.04), 0 12px 24px rgba(0, 0, 0, 0.32);
}

.nb-cover__inside::before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  width: 16%;
  border-radius: 0 3px 3px 0;
  background: linear-gradient(270deg, rgba(0, 0, 0, 0.5), transparent);
}

/* The spine, where the cover folds, sits a shade darker. */
.nb-spine {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 13%;
  z-index: 1;
  border-radius: 3px 0 0 3px;
  background: linear-gradient(90deg, rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0.22) 70%, rgba(255, 255, 255, 0.05));
  box-shadow: 1px 0 0 rgba(255, 255, 255, 0.05);
}

/* The title, stamped into the leather in pale foil. Sized to the cover. */
.nb-title {
  position: absolute;
  left: 13%;
  right: 0;
  top: 27%;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  font-family: var(--display);
  font-size: 14cqw;
  font-weight: 400;
  line-height: 0.96;
  letter-spacing: 0.01em;
  color: #ECE6D6;
  text-align: center;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.6), 0 -1px 0 rgba(255, 255, 255, 0.07);
}

.nb-title__line { display: block; white-space: nowrap; }

.nb-title::after {
  content: '';
  width: 38%;
  height: 2px;
  margin-top: 0.34em;
  background: currentColor;
  opacity: 0.7;
}

/* The stud tab, sewn to the back board and reaching round to hold the
   cover shut. Opening, it lets go first. Closing, it fastens last. */
.nb-snap {
  position: absolute;
  top: 50%;
  right: -15px;
  z-index: 7;
  width: 36px;
  height: 28px;
  transform: translateY(-50%);
  border-radius: 3px 13px 13px 3px;
  box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.45), inset 0 0 0 1px rgba(255, 255, 255, 0.04);
  transition: transform 160ms var(--enter) 720ms;
}

.nb-snap::after {
  content: '';
  position: absolute;
  inset: 4px 5px 4px 3px;
  border: 1px dashed var(--stitch);
  border-left: 0;
  border-radius: 0 9px 9px 0;
  opacity: 0.7;
}

.nb-snap__stud {
  position: absolute;
  top: 50%;
  right: 8px;
  width: 11px;
  height: 11px;
  transform: translateY(-50%);
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, var(--nickel-hi), var(--nickel) 45%, var(--nickel-lo));
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.6);
}

/* Opening. The tab lets go, the cover turns over as the book slides back
   to centre, and it drops under the sheet once it lies flat. Then the
   sheet turns across. */

.notebook:hover .nb-snap,
.notebook:focus-visible .nb-snap {
  transform: translateY(-50%) translateX(17px);
  transition: transform 160ms var(--enter) 0ms;
}

.notebook:hover .nb-book,
.notebook:focus-visible .nb-book {
  transform: translateX(0);
  transition: transform 440ms var(--turn) 100ms;
}

.notebook:hover .nb-cover,
.notebook:focus-visible .nb-cover {
  z-index: 2;
  transform: rotateY(-180deg);
  animation: none;
  transition: transform 440ms var(--turn) 100ms, z-index 0s linear 540ms;
}

.notebook:hover .nb-sheet,
.notebook:focus-visible .nb-sheet {
  transform: rotateY(-180deg);
  transition: transform 420ms var(--turn) 500ms;
}

/* -- Envelope -------------------------------------------------------
   Black stock. Stacked back to front: the inside wall, the letter, the
   pocket, then the flap on top. Opening runs in three steps, in order:
   the flap swings up, drops behind the letter at the halfway point, and
   only once it is clear does the letter ride up out of the pocket.
   Closing runs the same steps backwards.
   ------------------------------------------------------------------- */

.envelope { --w: 206px; }

.env {
  position: relative;
  aspect-ratio: 3 / 2;
  margin-top: 64px;
  perspective: 900px;
}

.env-back,
.env-front,
.env-flap {
  background-color: var(--env);
  background-image: var(--grain-soft), linear-gradient(180deg, var(--env-hi), var(--env) 55%, var(--env-lo));
  background-blend-mode: screen, normal;
}

.env-back {
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: 3px;
  background-image: var(--grain-soft), linear-gradient(180deg, #0F1012, #17181B);
}

.env-letter {
  position: absolute;
  left: 8%;
  right: 8%;
  top: 7%;
  height: 86%;
  z-index: 2;
  padding: 12px 11px 0;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
  transform: translateY(0);
  /* Closing: the letter goes back in first. */
  transition: transform 280ms var(--exit) 0ms;
}

/* The printed rows of the slip, and its barcode. */
.env-letter__print { display: flex; flex-direction: column; gap: 6px; }

.env-letter__row {
  display: block;
  height: 3px;
  background: var(--ink-soft);
  opacity: 0.55;
}

.env-letter__row:first-child { height: 5px; opacity: 0.8; margin: 0 auto 3px; }

.env-letter__code {
  position: absolute;
  left: 22%;
  right: 22%;
  bottom: 18%;
  height: 14px;
  background: repeating-linear-gradient(90deg,
    var(--ink) 0 1px, transparent 1px 3px,
    var(--ink) 3px 5px, transparent 5px 6px,
    var(--ink) 6px 7px, transparent 7px 10px);
  opacity: 0.75;
}

/* The pocket, painted over the letter, with its two folds meeting at the
   middle of the envelope. */
.env-front {
  position: absolute;
  inset: 0;
  z-index: 3;
  border-radius: 3px;
  clip-path: polygon(0 0, 50% 54%, 100% 0, 100% 100%, 0 100%);
  container-type: inline-size;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 11%;
  background-image: var(--grain-soft), linear-gradient(180deg, var(--env), var(--env-lo));
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.28);
}

.env-folds {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.env-folds polyline {
  fill: none;
  stroke: rgba(255, 255, 255, 0.13);
  stroke-width: 1.2;
}

/* Written across the black in a pale paint pen, sized to the envelope so it
   always sits inside the pocket, under the point where the folds meet. */
.env-front__word {
  position: relative;
  z-index: 2;
  font-family: var(--display);
  font-size: 7.2cqw;
  font-weight: 400;
  letter-spacing: 0.02em;
  line-height: 1;
  white-space: nowrap;
  color: #ECE8DE;
  text-shadow: none;
}

.env-flap {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 58%;
  z-index: 4;
  clip-path: polygon(0 0, 100% 0, 50% 100%);
  transform-origin: top center;
  transform: rotateX(0deg);
  background-image: var(--grain-soft), linear-gradient(180deg, var(--env-hi), var(--env));
  /* Closing: after the letter is back in, the flap swings down, and it comes
     back to the front as soon as it passes edge on. The swing is fast at the
     start, so that is about 40ms in, well before its tip reaches the pocket. */
  transition: transform 380ms var(--enter) 260ms, z-index 0s linear 300ms;
}

.envelope:hover .env-flap,
.envelope:focus-visible .env-flap {
  z-index: 1;
  transform: rotateX(-178deg);
  /* Opening: the flap goes first and drops behind the letter half way. */
  transition: transform 380ms var(--enter) 0ms, z-index 0s linear 190ms;
}

.envelope:hover .env-letter,
.envelope:focus-visible .env-letter {
  transform: translateY(-64%);
  /* Opening: the letter only moves once the flap is out of its way. */
  transition: transform 440ms var(--enter) 360ms;
}

/* -- Idle motion, one object at a time -------------------------- */

.thing.is-idle.notebook .nb-cover { animation: idle-lift 700ms var(--enter); }

@keyframes idle-lift {
  0%   { transform: rotateY(0deg); }
  50%  { transform: rotateY(-14deg); }
  100% { transform: rotateY(0deg); }
}

.thing.is-idle.photo .photo__frame { animation: idle-tilt 700ms var(--enter); }

@keyframes idle-tilt {
  0%   { transform: rotate(2deg); }
  50%  { transform: rotate(3deg); }
  100% { transform: rotate(2deg); }
}

/* The flap lifts a finger's width and settles, as if caught by air. */
.thing.is-idle.envelope .env-flap { animation: idle-flap 700ms var(--enter); }

@keyframes idle-flap {
  0%   { transform: rotateX(0deg); }
  50%  { transform: rotateX(-24deg); }
  100% { transform: rotateX(0deg); }
}

/* ============================================================
   8. Shared pieces: labels, media wells, placeholders
   ============================================================ */

/* The tag above each preview. Printed straight onto the page, anchored by
   its foot to the top of the frame so it never covers the picture. */
/* Held to the card's own width, so a long tag wraps onto a second line
   instead of running into the tag of the card beside it. */
.label {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 0;
  right: 0;
  z-index: 4;
  display: flex;
  align-items: flex-start;
  gap: 6px;
}

.label__square {
  width: 8px;
  height: 8px;
  margin-top: 2px;
  background: var(--accent);
  flex: none;
  transition: transform var(--t-micro) var(--micro);
}

.project:hover .label__square { transform: scale(1.15); }

.label__text {
  min-width: 0;
  font-size: 10px;
  letter-spacing: 0.1em;
  line-height: 1.25;
  color: var(--ink);
}

.media {
  position: relative;
  width: 100%;
  aspect-ratio: var(--ratio, 16 / 9);
  background: var(--ph-fill);
  overflow: hidden;
}

.media__ph {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 10px;
  text-align: center;
  border: 1px solid var(--rule);
  color: var(--ink-faint);
  word-break: break-word;
}

.media img,
.media video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  opacity: 0;
  transition: opacity var(--t-exit) var(--enter);
}

.media img.is-ready,
.media video.is-ready { opacity: 1; }

.media video { z-index: 2; }
.media img { z-index: 1; }

.play {
  position: absolute;
  z-index: 6;
  left: 12px;
  bottom: 12px;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 7px 14px 7px 11px;
  background: var(--paper);
  border: 1px solid var(--ink-soft);
  color: var(--ink);
  font: inherit;
  cursor: pointer;
}

.play__glyph {
  width: 0;
  height: 0;
  border-left: 9px solid var(--ink);
  border-top: 6px solid transparent;
  border-bottom: 6px solid transparent;
}

.play.is-playing .play__glyph {
  width: 9px;
  height: 12px;
  border: 0;
  background: linear-gradient(to right, var(--ink) 0 3px, transparent 3px 6px, var(--ink) 6px 9px);
}

/* ============================================================
   9. The book
   ============================================================ */

.book-root[hidden] { display: none !important; }

/* Room is left on the right for the tabs, which ride outside the book.

   Centring is done with auto margins on the book, not with align-items:
   center. A centred flex item that is taller than its container overflows
   equally in both directions, and the overflow above the top edge cannot be
   scrolled to. Auto margins centre only while there is room to spare. */
.book-root {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: flex;
  align-items: flex-start;
  justify-content: flex-start;
  padding: 3vh clamp(52px, 6vw, 96px) 3vh clamp(16px, 4vw, 64px);
  overflow: auto;
}

.book {
  position: relative;
  width: 100%;
  max-width: 1600px;
  margin: auto;
  flex: 0 0 auto;
  perspective: 1900px;
  opacity: 0;
  transform: scale(0.94);
  transition: opacity var(--t-enter) var(--enter), transform var(--t-enter) var(--enter);
}

.book.is-open { opacity: 1; transform: scale(1); }

/* The open organiser. It always fills the height of the window, so it is the
   same object from chapter to chapter, and the works are sized to fit it. */
.book__spread {
  --page-pad-y: clamp(22px, 3.6vh, 42px);
  --page-pad-left: 34px;
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 32fr) minmax(0, 68fr);
  gap: 26px;
  padding: 16px;
  border-radius: 12px;
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.05),
    0 30px 70px rgba(0, 0, 0, 0.42);
  min-height: calc(100vh - 6vh);
}

.book__spread::before { inset: 8px; border-radius: 8px; z-index: 5; }

.book__left,
.book__right {
  position: relative;
  min-width: 0;
  border-radius: 3px;
}

/* A shade where each page curves into the spine. */
.book__left  { box-shadow: inset -16px 0 22px -18px rgba(0, 0, 0, 0.55); }
.book__right { box-shadow: inset 16px 0 22px -18px rgba(0, 0, 0, 0.55); }

/* Nickel rings down the spine, centred in the gutter. */
.book__spread::after {
  content: '';
  position: absolute;
  left: calc(16px + (100% - 58px) * 0.32 + 13px);
  top: 30px;
  bottom: 30px;
  width: 24px;
  transform: translateX(-50%);
  z-index: 6;
  background: repeating-linear-gradient(180deg,
    transparent 0 7px,
    var(--nickel-lo) 7px 8px,
    var(--nickel-hi) 8px 10px,
    var(--nickel) 10px 11px,
    var(--nickel-lo) 11px 12px,
    transparent 12px 24px);
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.5));
  pointer-events: none;
}

.book__left {
  display: flex;
  flex-direction: column;
  padding: var(--page-pad-y) 30px var(--page-pad-y) var(--page-pad-left);
}

.book__right { padding: var(--page-pad-y) var(--page-pad-left) var(--page-pad-y) 30px; }

.book__chapter-title {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(18px, 1.7vw, 25px);
  font-weight: 400;
  letter-spacing: 0.01em;
  line-height: 1.05;
  text-transform: uppercase;
  color: var(--ink);
  text-shadow: none;
}

/* The receipt tear line under the chapter title. */
.book__chapter-title::after {
  content: '';
  display: block;
  height: 1px;
  margin-top: 16px;
  background: repeating-linear-gradient(90deg, var(--ink-soft) 0 6px, transparent 6px 11px);
  opacity: 0.6;
}

/* The questions, printed on a slip and clipped to the page. The slip is
   pushed out to the page edge so the clip bites onto the leather. */
.clipnote {
  position: relative;
  margin: 26px 0 0 calc(-1 * var(--page-pad-left) - 10px);
  padding-left: 20px;
  max-width: 330px;
}

.clipnote__sheet {
  padding: 20px 20px 22px 24px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 10px 20px rgba(0, 0, 0, 0.12);
  transform: rotate(-1.2deg);
}

.clipnote__line {
  position: relative;
  z-index: 1;
  margin: 0 0 14px;
  font-size: 13.5px;
  font-weight: 500;
  line-height: 1.6;
  color: var(--ink);
}

/* Each question is a line item on the slip. */
.clipnote__line::before {
  content: '>';
  margin-right: 8px;
  color: var(--ink-faint);
}

.clipnote__line:last-child { margin-bottom: 0; }

/* The binder clip, gripping the left edge of the slip and overhanging the cover. */
.clipnote__clip {
  position: absolute;
  top: 50%;
  left: 0;
  z-index: 3;
  width: 34px;
  height: 46px;
  transform: translateY(-50%) rotate(-1.2deg);
  background: linear-gradient(90deg, #111214, #2A2C30 55%, #16171A);
  border-radius: 2px;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.4);
}

.clipnote__clip::before,
.clipnote__clip::after {
  content: '';
  position: absolute;
  left: -6px;
  height: 15px;
  width: 20px;
  border: 2px solid var(--nickel);
  border-right: 0;
  border-radius: 8px 0 0 8px;
}

.clipnote__clip::before { top: 6px; }
.clipnote__clip::after { bottom: 6px; }

/* The sticky note that shows what was mine on the work being hovered. It
   keeps its space when empty, so the page never jumps. */
.hovernote {
  position: relative;
  margin: 28px 0 0 6px;
  width: min(260px, 100%);
  min-height: 168px;
  padding: 16px 18px 18px;
  background: linear-gradient(180deg, var(--sticky), var(--sticky-lo));
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1), 0 14px 18px -10px rgba(0, 0, 0, 0.4);
  opacity: 0;
  transform: rotate(var(--tilt, -1.6deg)) translateY(6px);
  transition: opacity 220ms var(--enter), transform 260ms var(--enter);
  pointer-events: none;
}

.hovernote.is-shown {
  opacity: 1;
  transform: rotate(var(--tilt, -1.6deg)) translateY(0);
}

/* The corner of a sticky note lifts where the glue stops. */
.hovernote::after {
  content: '';
  position: absolute;
  right: 0;
  bottom: 0;
  width: 26px;
  height: 26px;
  background: linear-gradient(315deg, rgba(0, 0, 0, 0.09), transparent 60%);
}

.hovernote__head {
  margin: 0 0 8px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.14em;
  line-height: 1.4;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.hovernote__mine {
  margin: 0;
  font-family: var(--pen);
  font-size: 23px;
  font-weight: 600;
  line-height: 1.22;
  color: var(--ink);
  text-shadow: none;
}

.hovernote__credit {
  margin: 12px 0 0;
  padding-top: 8px;
  border-top: 1px dashed rgba(29, 29, 28, 0.3);
  font-size: 10.5px;
  line-height: 1.5;
  color: var(--ink-soft);
}

.hovernote__credit[hidden] { display: none; }

/* The work count closes the page like the item total on a receipt. */
.book__count {
  margin: auto 0 0;
  padding-top: 18px;
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.book__close,
.modal__close {
  position: absolute;
  z-index: 9;
  width: 38px;
  height: 38px;
  border: 1px dashed var(--ink-soft);
  background: var(--paper);
  color: var(--ink);
  font: 400 18px/1 var(--mono);
  cursor: pointer;
}

.book__close { top: 26px; right: 26px; }
.book__close:hover,
.modal__close:hover { border-style: solid; }

/* The drawn button is 38 square, which is smaller than a fingertip. This
   reaches 3px past every edge so the touch target is 44, without moving
   anything or changing what is on screen. */
.book__close::after,
.modal__close::after {
  content: '';
  position: absolute;
  top: -3px;
  right: -3px;
  bottom: -3px;
  left: -3px;
}

/* Chapter tabs read as the coloured dividers of the organiser. They size to
   their own words, so every chapter name reads in full, always. */
.tabs {
  position: absolute;
  top: 6%;
  right: 0;
  transform: translateX(100%);
  z-index: 7;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  max-height: 88%;
}

.tab {
  position: relative;
  flex: 0 0 auto;
  border: 0;
  border-radius: 0 6px 6px 0;
  background: var(--tab);
  color: var(--ink);
  padding: 14px 11px;
  cursor: pointer;
  writing-mode: vertical-rl;
  font-family: var(--mono);
  font-size: clamp(8.5px, 1.05vh, 11px);
  font-weight: 600;
  letter-spacing: 0.1em;
  line-height: 1;
  text-transform: uppercase;
  white-space: nowrap;
  opacity: 0.8;
  box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.18);
  transition: opacity var(--t-exit) var(--enter), transform var(--t-exit) var(--enter);
}

.tab:hover { opacity: 0.92; }
.tab[aria-selected="true"] { opacity: 1; transform: translateX(4px); }

.tab:nth-child(2) { --tab: var(--tab-1); }
.tab:nth-child(3) { --tab: var(--tab-2); }
.tab:nth-child(4) { --tab: var(--tab-3); }
.tab:nth-child(5) { --tab: var(--tab-4); }

.tabs__marker { display: none; }

/* The turning leaf. Its box is measured from the right page by the script.
   Two faces, so the back of the sheet shows as it swings. */
.leaf {
  position: absolute;
  z-index: 6;
  transform-origin: left center;
  transform-style: preserve-3d;
  pointer-events: none;
  will-change: transform;
}

.leaf__face {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: 3px;
  backface-visibility: hidden;
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.2);
}

/* The reverse of the sheet: blank stock. */
.leaf__face--back { transform: rotateY(180deg); }

.leaf.is-turning { animation: leaf-turn 660ms cubic-bezier(0.42, 0.02, 0.28, 1) forwards; }
.leaf.is-turning-back { animation: leaf-turn-back 660ms cubic-bezier(0.42, 0.02, 0.28, 1) forwards; }

/* The sheet lifts off the page as it swings, so it does not scrape across
   the cover, and settles flat again on the far side. */
@keyframes leaf-turn {
  0%   { transform: rotateY(0deg) translateZ(0); }
  50%  { transform: rotateY(-90deg) translateZ(26px); }
  100% { transform: rotateY(-180deg) translateZ(0); }
}

@keyframes leaf-turn-back {
  0%   { transform: rotateY(-180deg) translateZ(0); }
  50%  { transform: rotateY(-90deg) translateZ(26px); }
  100% { transform: rotateY(0deg) translateZ(0); }
}

/* The shadow the sheet casts on the page under it, and the shading that
   crosses the sheet itself as it turns edge on. */
.leaf__shade {
  position: absolute;
  inset: 0;
  z-index: 3;
  border-radius: 3px;
  background: linear-gradient(90deg, rgba(0, 0, 0, 0.34), rgba(0, 0, 0, 0.04) 55%, transparent);
  opacity: 0;
}

.leaf.is-turning .leaf__shade,
.leaf.is-turning-back .leaf__shade { animation: leaf-shade 660ms cubic-bezier(0.42, 0.02, 0.28, 1) forwards; }

@keyframes leaf-shade {
  0%   { opacity: 0; }
  46%  { opacity: 1; }
  100% { opacity: 0; }
}

.book.is-turning .book__right { animation: page-settle 660ms var(--enter); }

@keyframes page-settle {
  0%   { opacity: 0.55; transform: scale(0.995); }
  60%  { opacity: 0.9; }
  100% { opacity: 1; transform: scale(1); }
}

/* ============================================================
   10. Works inside a chapter
   ============================================================ */

/* Every preview is one square. The script works out the largest square the
   page allows and the column count that gets there (see fitGrid), and hands
   both over as --card-w and --cols. These defaults only hold until it does. */
.projects {
  --label-h: 28px;
  display: grid;
  grid-template-columns: repeat(var(--cols, 3), var(--card-w, 180px));
  justify-content: center;
  align-content: start;
  align-items: start;
  gap: 22px;
  min-width: 0;
}

/* align-items: start matters. Stretched to the row height, a button centres
   its own content, which drops the shorter card in a row a few pixels and
   throws the titles out of line. Left at their natural height they all
   begin at the top of the row. */
.project {
  position: relative;
  display: block;
  width: 100%;
  padding: var(--label-h) 0 0;
  border: 0;
  background: none;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
  opacity: 0;
  transform: translateY(6px);
  animation: rise 420ms var(--enter) forwards;
  animation-delay: var(--d, 0ms);
}

.project__frame {
  position: relative;
  background: var(--ph-fill);
  box-shadow: var(--shadow-rest);
  transition: transform var(--t-exit) var(--enter), box-shadow var(--t-exit) var(--enter);
}

.project:hover .project__frame,
.project:focus-visible .project__frame { transform: translateY(-2px); box-shadow: var(--shadow-lift); }

.project.is-pressed .project__frame { transform: scale(0.97); }

.projects .media { aspect-ratio: 1 / 1; }

/* Once a picture has loaded its label underneath is no longer wanted, even
   where the crop leaves a margin. */
.media.is-loaded .media__ph { visibility: hidden; }

/* A loaded preview is printed onto the page. No grey well and no card
   shadow: its light ground is already lifted out of the picture, and its
   edges fade into the paper, so every preview holds the same square in the
   same way. A solid dark ground is carried to the edges from the script. */
.projects .media.is-loaded {
  background: none;
  -webkit-mask-image:
    linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent),
    linear-gradient(180deg, transparent, #000 5%, #000 95%, transparent);
  -webkit-mask-composite: source-in;
          mask-image:
    linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent),
    linear-gradient(180deg, transparent, #000 5%, #000 95%, transparent);
          mask-composite: intersect;
}

.project__frame:has(> .media.is-loaded),
.project:hover .project__frame:has(> .media.is-loaded),
.project:focus-visible .project__frame:has(> .media.is-loaded) {
  background: none;
  box-shadow: none;
}

/* The lead graphic in a modal prints the same way, on the receipt. */
.media.is-printed { background: none; }

/* A document is shown whole. Its well is cut to the shape it declares, but
   the picture is fitted inside rather than filled to the edges, so a shape
   that disagrees with the file by even a little loses nothing off the sides.
   Edge type is the first thing a crop takes, and it is never recoverable. */
.lead-graphic .media img { object-fit: contain; }

/* At rest a preview prints like the rest of the page, in thermal greys.
   Hovered, it comes up in full colour. The whole well is toned, so a ground
   carried to its edges greys along with the picture. */
.project .media {
  filter: grayscale(1) contrast(1.08) brightness(0.9);
  transition: filter var(--t-exit) var(--enter);
}

.project .media img,
.project .media video { transition: opacity var(--t-exit) var(--enter); }

.project:hover .media,
.project:focus-visible .media { filter: none; }

/* Where the pixels could be read, the resting preview is a thermal print
   laid over the picture, and the picture comes up in its place on hover.
   The print is already ink on paper, so it takes no filter. */
.project .media.has-print { filter: none; }

.media__print {
  position: absolute;
  z-index: 3;
  pointer-events: none;
  transition: opacity var(--t-exit) var(--enter);
}

.project .media.has-print img,
.project .media.has-print video { opacity: 0; }

.project:hover .media.has-print img,
.project:focus-visible .media.has-print img,
.project:hover .media.has-print video.is-ready,
.project:focus-visible .media.has-print video.is-ready { opacity: 1; }

.project:hover .media__print,
.project:focus-visible .media__print { opacity: 0; }

.project:hover .media.has-print,
.project:focus-visible .media.has-print { background-color: var(--ground, transparent); }

.project__title {
  display: block;
  margin-top: 10px;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  line-height: 1.35;
  text-transform: uppercase;
  color: var(--ink);
}

.project__blurb {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 4;
  overflow: hidden;
  margin: 5px 0 0;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--ink-soft);
}

/* Shown on touch only, where there is no hover to raise the sticky note. */
.project__mine,
.project__credit { display: none; }

/* ============================================================
   11. Modals
   ============================================================ */

.modal-root[hidden] { display: none !important; }

.modal-root {
  position: fixed;
  inset: 0;
  z-index: 160;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  overflow-y: auto;
  padding: 6vh 4vw;
}

/* A receipt is narrow, so the modal is too. */
.modal {
  position: relative;
  width: 100%;
  max-width: min(780px, 100%);
  padding: 46px 46px 40px;
  box-shadow: 0 30px 60px rgba(0, 0, 0, 0.3);
}

.modal__close { top: 16px; right: 16px; }

.modal .t-modal-title,
.postcard__face .t-modal-title {
  padding: 0 48px;
  text-align: center;
}

.modal__rule {
  width: 64px;
  height: 3px;
  margin: 14px auto 0;
  background: var(--accent, var(--ink));
}

/* Line items: the key, a dotted leader, the value. */
.modal__meta {
  display: block;
  margin: 26px 0 0;
  padding: 0;
}

.modal__meta > div {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 4px 0;
}

.modal__meta dt {
  flex: 1 1 auto;
  display: flex;
  align-items: baseline;
  min-width: 8em;
  margin: 0;
}

.modal__meta dt::after {
  content: '';
  flex: 1;
  margin: 0 0 0.3em 10px;
  border-bottom: 1px dotted var(--ink-faint);
}

.modal__meta dd {
  flex: 0 1 auto;
  max-width: 62%;
  margin: 0;
  text-align: right;
  font-size: 13.5px;
  color: var(--ink);
}

.modal__video { margin: 0 0 28px; }

.modal__video .embed {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: var(--ph-fill);
}

.modal__video .embed iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

.modal__clips {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 18px;
  margin: 0 0 28px;
}

.modal__body p { margin: 0 0 18px; }
.modal__body p:last-child { margin-bottom: 0; }

.modal__credits {
  margin: 26px 0 0;
  padding: 16px 0 0;
  border-top: 1px dashed var(--rule);
}

.modal__credits p { margin: 0 0 6px; }

.subitem {
  margin: 30px 0 0;
  padding: 22px 0 0;
  border-top: 1px dashed var(--rule);
  max-width: 64ch;
}

.subitem__title {
  margin: 0 0 4px;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
}

.subitem__credit { margin: 0 0 12px; }
.subitem p { margin: 0 0 12px; }
.subitem p:last-child { margin-bottom: 0; }

/* The graphics of a work, printed straight onto the receipt: no frame, no
   ground of their own. At rest they come off the thermal head in greys,
   hovered they show their colour. */
/* A strip that runs out of width goes on to a second row rather than
   scrolling, so every graphic of a work is in view at once. */
.strip {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 26px 34px;
  overflow-x: auto;
  padding: 10px 2px 18px;
  margin: 30px 0 0;
}

.artefact {
  flex: 0 0 auto;
  border: 0;
  background: none;
  padding: 0;
  cursor: zoom-in;
  color: inherit;
  font: inherit;
  text-align: left;
}

/* The caption wraps to the width of its own graphic, never wider. */
.artefact__figure { margin: 0; width: min-content; }

.artefact__art {
  position: relative;
  height: 230px;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  transition: transform var(--t-exit) var(--enter);
}

.artefact:hover .artefact__art { transform: translateY(-2px); }

.artefact__art img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 0;
  mix-blend-mode: multiply;
  filter: grayscale(1) contrast(1.12);
  transition: opacity var(--t-exit) var(--enter), filter var(--t-exit) var(--enter);
}

.artefact__art.is-ready img { opacity: 1; }

.artefact:hover .artefact__art img,
.artefact:focus-visible .artefact__art img { filter: none; }

/* Until the file exists, only its name is printed where it will go. */
.artefact__ph {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 10px;
  text-align: center;
  word-break: break-word;
}

.artefact__art.is-ready .artefact__ph { display: none; }

/* A PDF is drawn as a page with its corner folded, in ink on the receipt. */
.artefact__art--pdf {
  aspect-ratio: 3 / 4;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 6px;
  padding: 16px 14px;
  border: 1.5px solid var(--ink);
  clip-path: polygon(0 0, calc(100% - 26px) 0, 100% 26px, 100% 100%, 0 100%);
  cursor: pointer;
}

.artefact__art--pdf::before {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  width: 26px;
  height: 26px;
  background: linear-gradient(225deg, transparent 50%, var(--ink) 50%, var(--ink) calc(50% + 1.5px), transparent calc(50% + 1.5px));
}

.artefact__art--pdf::after {
  content: '';
  position: absolute;
  left: 14px;
  right: 14px;
  top: 40px;
  height: 46%;
  background: repeating-linear-gradient(180deg, var(--ink-soft) 0 2px, transparent 2px 9px);
  opacity: 0.35;
}

.artefact__kind {
  font-family: var(--display);
  font-size: 26px;
  line-height: 1;
  color: var(--ink);
  text-shadow: none;
}

.artefact__name {
  font-size: 10px;
  line-height: 1.35;
  color: var(--ink-soft);
  word-break: break-word;
}

.artefact figcaption { margin-top: 10px; max-width: 280px; }

/* A graphic in the lead place of a work, where a clip would otherwise
   stand. Capped in width, so a tall one never buries the copy under it. */
.modal__clip--graphic { width: 100%; max-width: 520px; justify-self: center; }

.lead-graphic {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
}

/* A run of full width figures, set off like the other sections. */
.figblock {
  margin: 30px 0 0;
  padding: 22px 0 0;
  border-top: 1px dashed var(--rule);
}

.figblock__eyebrow { margin: 0 0 6px; }
.figblock__title { margin: 0 0 16px; }

.figblock__figure { margin: 0 0 26px; }
.figblock__figure:last-child { margin-bottom: 0; }
.figblock__figure figcaption { margin-top: 10px; }

/* A sequence of images and connectors, set off like the other sections. */
.seq {
  margin: 30px 0 0;
  padding: 22px 0 0;
  border-top: 1px dashed var(--rule);
}

.seq__figure { margin: 0; }
.seq__eyebrow { margin: 0 0 14px; }

/* A drawing whose argument lives in its fine print would lose that print
   before it lost the screen, so on a narrow one it keeps a width it can
   still be read at and moves sideways instead. */
@media (max-width: 699px) {
  .seq__figure--wide {
    overflow-x: auto;
    overflow-y: hidden;
    touch-action: pan-x pan-y;
    scrollbar-width: thin;
    scrollbar-color: var(--rule) transparent;
  }

  .seq__figure--wide::-webkit-scrollbar { height: 6px; }
  .seq__figure--wide::-webkit-scrollbar-track { background: transparent; }
  .seq__figure--wide::-webkit-scrollbar-thumb { background: var(--rule); }

  .seq__figure--wide .lead-graphic { min-width: var(--least, 760px); }
}

/* Credit lines at the foot of a modal, above the barcode. */
.modal__foot { margin-top: 34px; }

/* What may be shown and what may not, at the foot in the machine's type. */
.modal__note {
  margin: 30px 0 0;
  padding: 16px 0 0;
  max-width: 76ch;
  border-top: 1px dashed var(--rule);
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink-soft);
}

.modal__note p { margin: 0 0 6px; }
.modal__note p:last-child { margin-bottom: 0; }

/* -- Film sections in a sequence -------------------------------------- */

.seq__film {
  max-width: none;
  margin: 0;
  padding: 0;
  border-top: 0;
}

.seq__film .t-body,
.seq__film .subitem__credit { max-width: 64ch; }

.film__embed {
  aspect-ratio: 16 / 9;
  margin: 0 0 18px;
  border: 3px solid #14110F;
  background: #14110F;
}

.film__embed iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

/* A film that sets its own shape keeps its frame on the box. */
.film__embed--pad iframe { position: absolute; inset: 0; }

/* A film whose own embed code sets the shape. The padding holds the box
   open and the frame fills it, so nothing is cropped to the house ratio. */
.film__embed--pad {
  aspect-ratio: auto;
  position: relative;
  height: 0;
  padding-top: calc(var(--pad) * 1%);
}

.film__embed--pad iframe {
  position: absolute;
  top: 0;
  left: 0;
}

.seq__embedcap {
  margin: 0 0 18px;
  max-width: 76ch;
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink-soft);
}

.film__link {
  display: inline-block;
  margin: 2px 0 0;
  font-size: 12px;
  letter-spacing: 0.08em;
  color: #14110F;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
}

.film__link:hover { text-decoration-thickness: 2px; }

.film__after { margin-top: 26px; }

/* -- Crew sheet ------------------------------------------------------- */

.crew { margin: 0 0 10px; }

.crew__top {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  margin: 0 0 14px;
}

.crew__eyebrow,
.crew__flag {
  margin: 0;
  font-size: 11px;
  letter-spacing: 0.2em;
  line-height: 1.4;
  text-transform: uppercase;
}

.crew__eyebrow {
  display: flex;
  align-items: center;
  gap: 10px;
  color: #57514A;
}

.crew__eyebrow::before {
  content: '';
  width: 10px;
  height: 10px;
  flex: none;
  background: var(--mark);
}

.crew__flag { color: var(--mark); white-space: nowrap; }

.crew__title {
  margin: 0 0 8px;
  font-family: var(--mono);
  font-size: 24px;
  font-weight: 700;
  letter-spacing: 0.08em;
  line-height: 1.1;
  text-transform: uppercase;
  color: #14110F;
}

.crew__sub {
  margin: 0 0 18px;
  font-size: 12.5px;
  letter-spacing: 0.04em;
  line-height: 1.5;
  color: #57514A;
}

.crew__scroll { overflow-x: auto; }

.crew__grid {
  position: relative;
  min-width: 676px;
  border: 1.5px solid #14110F;
  background: #EFEDE7;
}

.crew__head,
.crew__row {
  display: grid;
  grid-template-columns: minmax(168px, 1fr) repeat(9, 56px);
}

.crew__head {
  height: 58px;
  background: #14110F;
  color: #F4F2EC;
}

.crew__head span {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  line-height: 1.6;
  text-transform: uppercase;
  border-left: 1px solid rgba(244, 242, 236, 0.16);
}

.crew__head span:first-child {
  justify-content: flex-start;
  padding-left: 14px;
  font-size: 11px;
  letter-spacing: 0.2em;
  border-left: 0;
}

.crew__row {
  min-height: 60px;
  border-top: 1px solid #C9C3B6;
}

.crew__row:nth-child(odd) { background: #E6E3DA; }

.crew__film {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  padding: 10px 14px;
}

.crew__film strong {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.1em;
  line-height: 1.3;
  text-transform: uppercase;
  color: #14110F;
}

.crew__film span {
  font-size: 10.5px;
  letter-spacing: 0.06em;
  color: #8A8378;
}

.crew__cell {
  display: flex;
  align-items: center;
  justify-content: center;
  border-left: 1px solid #C9C3B6;
}

.crew__mark { display: block; width: 26px; height: 26px; }

/* Half a seat: the square is cut on the diagonal and only the bottom left
   of it is filled, which is how the table says second chair. */
.crew__mark--half {
  background:
    linear-gradient(to top right,
      var(--mark) 0 calc(50% - 0.5px),
      transparent calc(50% + 0.5px) 100%);
  box-shadow: inset 0 0 0 1.5px var(--mark);
}

.crew__mark--half {
  opacity: 0;
  transform: scale(0.6);
  transition: opacity 240ms var(--enter), transform 240ms var(--enter);
}

.crew.is-in .crew__mark--half { opacity: 1; transform: scale(1); }

.crew__mark--on {
  background: var(--mark);
  opacity: 0;
  transform: scale(0.6);
  transition: opacity 240ms var(--enter), transform 240ms var(--enter);
}

.crew__mark--off rect {
  fill: none;
  stroke: #C9C3B6;
  stroke-width: 1.5;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  transition: stroke-dashoffset 240ms var(--enter);
}

.crew.is-in .crew__mark--on { opacity: 1; transform: scale(1); }
.crew.is-in .crew__mark--off rect { stroke-dashoffset: 0; }

/* The column where the work changed hands, ruled once the rows are in. */



.crew__legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 8px 16px;
  margin: 14px 0 0;
  font-size: 11.5px;
  letter-spacing: 0.06em;
  color: #14110F;
}

.crew__key {
  display: inline-block;
  width: 14px;
  height: 14px;
  margin-right: 10px;
  vertical-align: -2px;
  background: var(--mark);
}

/* The same half square the table uses, in the legend that names it. It is
   written after the plain key so it wins on order rather than on weight. */
.crew__key--half {
  background:
    linear-gradient(to top right,
      var(--mark) 0 calc(50% - 0.5px),
      transparent calc(50% + 0.5px) 100%);
  box-shadow: inset 0 0 0 1.5px var(--mark);
}

/* -- Beat player ------------------------------------------------------
   The board and the delivered frame in one stage, split by a handle.
   ------------------------------------------------------------------- */

.beats { margin: 0; }
.beats__title { margin: 0 0 16px; }

/* Every beat sits on the strip at once. Equal columns, nothing scrolls,
   so the whole spot is in view and any beat is one click away. */
.beats__strip {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  margin: 0 0 16px;
  border-bottom: 1px solid var(--rule);
}

.beats__tab {
  display: block;
  min-width: 0;
  padding: 10px 12px 9px;
  border: 0;
  border-bottom: 3px solid transparent;
  background: none;
  font-family: var(--mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-align: left;
  color: var(--ink-soft);
  cursor: pointer;
}

.beats__tab.is-on {
  color: var(--ink);
  border-bottom-color: var(--mark);
}

.beats__num { display: block; font-size: 13px; font-weight: 700; }
.beats__name { display: block; font-size: 13px; }
.beats__time { display: block; margin-top: 2px; font-size: 11px; letter-spacing: 0.04em; }

.beats__stage {
  --wipe: 50%;
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border: 3px solid #14110F;
  background: #14110F;
  touch-action: none;
  cursor: ew-resize;
}

.beats__pane {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 180ms linear;
}

.beats__pane.is-on { opacity: 1; }

.beats__shot {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.beats__shot.is-gone { display: none; }

/* A frame still to come. It holds the space and names the file, on its
   own side of the handle so the two sides never print over each other. */
.beats__ph {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  padding: 44px 16px;
  color: rgba(241, 239, 233, 0.45);
}

.beats__clip .beats__ph { align-items: flex-start; justify-content: flex-start; }

.beats__clip {
  position: absolute;
  inset: 0;
  clip-path: inset(0 calc(100% - var(--wipe)) 0 0);
}

.beats__handle {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--wipe);
  z-index: 3;
  width: 3px;
  margin-left: -1.5px;
  background: var(--mark);
  cursor: ew-resize;
}

.beats__grab {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 18px;
  height: 18px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: var(--mark);
  box-shadow: 0 0 0 2px rgba(244, 242, 236, 0.7);
}

.beats__handle:focus-visible { outline: none; }
.beats__handle:focus-visible .beats__grab { box-shadow: 0 0 0 3px var(--paper), 0 0 0 5px var(--mark); }

/* The one nudge on first view, and nothing else animated while dragging. */
.is-settling .beats__clip { transition: clip-path 620ms var(--enter); }
.is-settling .beats__handle { transition: left 620ms var(--enter); }

.beats__chip {
  position: absolute;
  top: 10px;
  z-index: 2;
  padding: 4px 9px;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink);
  background: rgba(241, 239, 233, 0.82);
}

.beats__chip--board { left: 10px; }
.beats__chip--final { right: 10px; }

.beats__read { margin: 14px 0 0; }

.beats__shotnote {
  margin: 0 0 8px;
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.beats__say {
  margin: 0;
  max-width: 54ch;
  font-size: 18px;
  line-height: 1.5;
  color: var(--ink);
}

/* A run of frames reads the same way, with the two coded colours on the
   corners and one fixed notice under the stage. */
.beats--wipe .beats__chip--board { border-left: 3px solid var(--mark-alt); }
.beats--wipe .beats__chip--final { border-right: 3px solid var(--mark); }

.beats__rights {
  margin: 0;
  max-width: 76ch;
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink-soft);
}

@media (max-width: 699px) {
  .beats__tab { padding: 8px 6px 7px; letter-spacing: 0.04em; }
  .beats__num, .beats__name { font-size: 10.5px; }
  .beats__time { font-size: 9.5px; letter-spacing: 0.02em; }
  .beats__say { font-size: 16px; }
  .beats__rights { font-size: 12px; }
  .beats__chip { padding: 3px 7px; font-size: 11px; letter-spacing: 0.08em; }
}

/* -- Animatic ---------------------------------------------------------
   The storyboard at the durations written on it. The bar under the stage
   is cut one segment to a frame, each as wide as its frame is long, so
   the pacing reads standing still.
   ------------------------------------------------------------------- */

.anim { margin: 0; }
.anim__title { margin: 0 0 8px; }

.anim__note {
  margin: 0 0 16px;
  max-width: 64ch;
  font-size: 15px;
  line-height: 1.55;
  color: var(--ink-soft);
}

.anim__stage {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border: 3px solid #14110F;
  background: #14110F;
}

.anim__shot {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
}

.anim__shot.is-on { opacity: 1; }

.anim__chip {
  position: absolute;
  z-index: 2;
  right: 10px;
  padding: 4px 9px;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.12em;
  color: var(--ink);
  background: rgba(241, 239, 233, 0.82);
}

.anim__chip--count { top: 10px; }
.anim__chip--held { bottom: 10px; }

.anim__bar {
  display: flex;
  gap: 3px;
  margin: 10px 0 0;
}

.anim__seg {
  flex: 0 1 0%;
  height: 12px;
  padding: 0;
  border: 1px solid var(--rule);
  background: none;
  cursor: pointer;
}

.anim__seg.is-on { border-color: var(--mark); }

.anim__fill {
  display: block;
  width: 0;
  height: 100%;
  background: var(--mark);
}

.anim__controls {
  display: flex;
  align-items: center;
  gap: 16px;
  margin: 12px 0 0;
}

.anim__play {
  padding: 8px 22px;
  border: 1.5px solid #14110F;
  background: var(--paper-hi);
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink);
  cursor: pointer;
}

.anim__play:hover { background: #E4E1D8; }

.anim__run {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
}

.anim__thumbs {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 10px;
  margin: 20px 0 0;
  padding: 0;
  list-style: none;
}

.anim__thumb { margin: 0; }

.anim__thumb img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border: 1.5px solid #14110F;
}

.anim__thumbline {
  display: flex;
  justify-content: space-between;
  gap: 6px;
  margin: 6px 0 0;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
}

@media (max-width: 699px) {
  .anim__thumbs { grid-template-columns: repeat(2, 1fr); }
}

/* -- Setup matrix -----------------------------------------------------
   Rows are setups, columns are the places their pictures land. Taking
   hold of either dims everything it does not touch.
   ------------------------------------------------------------------- */

.mtx, .tests { margin: 0; }

.mtx__top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin: 0 0 10px;
}

/* The two labels sit at either end of one line. Where that line is too
   short for both, they take a line each rather than breaking a label
   across three. */
@media (max-width: 560px) {
  .mtx__top { flex-wrap: wrap; gap: 4px 16px; }
  .mtx__top > * { flex: 1 0 100%; }
}

.mtx__eyebrow { margin: 0; }
.mtx__flag {
  margin: 0;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--mark);
  white-space: nowrap;
}

.mtx__title {
  margin: 0 0 8px;
  font-family: var(--mono);
  font-size: 26px;
  line-height: 1.15;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ink);
}

.mtx__note {
  margin: 0 0 22px;
  max-width: 64ch;
  font-size: 15px;
  line-height: 1.55;
  color: var(--ink-soft);
}

.mtx__scroll { overflow-x: auto; }

.mtx__table {
  width: 100%;
  border-collapse: collapse;
  border: 2px solid #14110F;
  font-size: 14px;
}

.mtx__corner,
.mtx__col {
  padding: 12px 8px;
  background: var(--mark-alt);
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  line-height: 1.35;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--paper-hi);
  transition: opacity 150ms linear, color 150ms linear;
}

.mtx__corner { width: 34%; padding-left: 18px; text-align: left; }
.mtx__col { width: 9.4%; text-align: center; cursor: pointer; }
.mtx__col.is-lit { color: #7FC4EE; }

.mtx__row { background: var(--paper-hi); cursor: pointer; transition: opacity 150ms linear; }
.mtx__row:nth-child(even) { background: #E6E3DA; }

.mtx__setup {
  padding: 13px 8px 13px 18px;
  text-align: left;
  font-weight: 400;
  vertical-align: middle;
}

.mtx__id {
  display: inline-block;
  min-width: 30px;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  color: var(--mark);
  vertical-align: top;
}

.mtx__text { display: inline-block; }
.mtx__name { display: block; font-weight: 700; color: var(--ink); transition: color 150ms linear; }
.mtx__desc { display: block; margin-top: 1px; font-size: 13px; color: var(--ink-faint); }
.mtx__setup.is-lit .mtx__name { color: var(--mark); }

.mtx__cell { padding: 10px 8px; text-align: center; transition: opacity 150ms linear; }

.mtx__mark {
  display: inline-block;
  width: 28px;
  height: 28px;
  border: 1.5px solid #C9C3B6;
  background: none;
  vertical-align: middle;
}

.mtx__mark.is-on { border-color: var(--mark); background: var(--mark); }

/* Holding a row keeps that row. Holding a column keeps that column. */
.mtx.is-row .mtx__row { opacity: 0.25; }
.mtx.is-row .mtx__row.is-on { opacity: 1; }
.mtx.is-col .mtx__cell,
.mtx.is-col .mtx__col { opacity: 0.25; }
.mtx.is-col .mtx__cell.is-on,
.mtx.is-col .mtx__col.is-on { opacity: 1; }

.mtx__under {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
  margin: 16px 0 0;
}

.mtx__legend,
.mtx__read {
  margin: 0;
  font-family: var(--mono);
  font-size: 12.5px;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
}

.mtx__legend { display: flex; align-items: center; gap: 10px; flex: none; }
.mtx__legend .mtx__mark { width: 14px; height: 14px; }
.mtx__read { text-align: right; color: var(--ink); }

.mtx__foot {
  margin: 18px 0 0;
  padding-top: 14px;
  border-top: 1px dashed var(--rule);
  font-family: var(--mono);
  font-size: 12.5px;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
}

@media (max-width: 699px) {
  .mtx__title { font-size: 20px; }
  .mtx__table { min-width: 620px; }
  /* The setup stays in view while the outputs scroll past it. */
  .mtx__corner,
  .mtx__setup {
    position: sticky;
    left: 0;
    z-index: 2;
    width: 190px;
    min-width: 190px;
  }
  .mtx__setup { background: inherit; }
  .mtx__row { background-clip: padding-box; }
  .mtx__under { display: block; }
  .mtx__read { margin-top: 10px; text-align: left; }
}

/* -- Flip tests -------------------------------------------------------
   A pair of options, and the reason for the test on the back of both.
   ------------------------------------------------------------------- */

.flip { margin: 0 0 26px; }

.flip__label {
  margin: 0 0 10px;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--mark);
}

.flip__pane {
  position: relative;
  min-height: 116px;
  transform-style: preserve-3d;
  transition: transform 300ms var(--enter);
}

.flip__pane.is-flipped { transform: rotateY(180deg); }

.flip__face {
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.flip__face--front {
  display: flex;
  align-items: stretch;
  gap: 18px;
}

.flip__face--back {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  padding: 20px 22px;
  transform: rotateY(180deg);
  border: 0;
  background: var(--mark-alt);
  text-align: left;
  cursor: pointer;
}

.flip__pane:not(.is-flipped) .flip__face--back { pointer-events: none; }
.flip__pane.is-flipped .flip__face--front { pointer-events: none; }

.flip__card {
  position: relative;
  flex: 1 1 0;
  display: flex;
  align-items: flex-start;
  gap: 0;
  padding: 0;
  border: 2px solid #14110F;
  background: #E6E3DA;
  text-align: left;
  cursor: pointer;
}

.flip__badge {
  flex: none;
  align-self: stretch;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  background: var(--mark);
  font-family: var(--mono);
  font-size: 17px;
  font-weight: 700;
  color: var(--paper-hi);
}

.flip__copy {
  padding: 18px 20px 30px;
  font-size: 16px;
  line-height: 1.4;
  color: var(--ink);
}

.flip__cue {
  position: absolute;
  right: 12px;
  bottom: 9px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.flip__vs {
  align-self: center;
  flex: none;
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.flip__reason {
  margin: 0;
  max-width: 72ch;
  font-size: 16px;
  line-height: 1.5;
  color: var(--paper-hi);
}

.flip__face--back .flip__cue {
  position: static;
  flex: none;
  color: rgba(241, 239, 233, 0.6);
}

@media (prefers-reduced-motion: reduce) {
  .flip__pane { transition: none; }
  .flip__pane.is-flipped { transform: none; }
  .flip__face { backface-visibility: visible; transition: opacity 200ms linear; }
  .flip__face--back { transform: none; opacity: 0; }
  .flip__pane.is-flipped .flip__face--front { opacity: 0; }
  .flip__pane.is-flipped .flip__face--back { opacity: 1; }
}

@media (max-width: 699px) {
  .flip__face--front { flex-direction: column; gap: 10px; }
  .flip__vs { align-self: flex-start; }
  .flip__pane { min-height: 0; }
  .flip__face--back { position: static; margin-top: 10px; }
  .flip__pane:not(.is-flipped) .flip__face--back { display: none; }
  .flip__pane.is-flipped .flip__face--front { display: none; }
  .flip__pane, .flip__pane.is-flipped { transform: none; transition: none; }
}

/* -- The submission ---------------------------------------------------
   Both decks in one run that scrolls sideways, in the order they were
   sent, so the enlarged view walks the whole submission.
   ------------------------------------------------------------------- */

.subm { margin: 0; }
.subm__title { margin: 0 0 8px; }

.subm__note {
  margin: 0 0 20px;
  max-width: 64ch;
  font-size: 15px;
  line-height: 1.55;
  color: var(--ink-soft);
}

.subm__strip {
  display: flex;
  align-items: flex-end;
  gap: 40px;
  overflow-x: auto;
  padding-bottom: 8px;
  cursor: grab;
  scrollbar-width: thin;
}

.subm__strip.is-held { cursor: grabbing; }
.subm__strip:focus-visible { outline: 2px solid var(--mark); outline-offset: 4px; }

.subm__group { flex: none; }

.subm__label {
  margin: 0 0 8px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  white-space: nowrap;
}

.subm__line { display: flex; gap: 14px; }

.subm__rule {
  flex: none;
  align-self: stretch;
  width: 2px;
  background: #C9C3B6;
}

.subm__page {
  position: relative;
  flex: none;
  width: 190px;
  aspect-ratio: 16 / 9;
  padding: 0;
  border: 2px solid #14110F;
  background: var(--ph-fill);
  cursor: zoom-in;
}

.subm__page img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity var(--t-exit) var(--enter);
}

.subm__page.is-loaded img { opacity: 1; }

.subm__ph {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 8px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.04em;
  text-align: center;
  color: var(--ink-faint);
  word-break: break-word;
}

.subm__links {
  display: flex;
  flex-wrap: wrap;
  gap: 28px;
  margin: 20px 0 0;
}

.subm__link {
  font-family: var(--mono);
  font-size: 15px;
  letter-spacing: 0.04em;
  color: var(--mark);
  text-decoration: none;
  border-bottom: 1px solid currentColor;
}

.subm__link:hover { color: var(--mark-alt); }

.subm__foot {
  margin: 14px 0 0;
  max-width: 76ch;
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink-soft);
}


/* -- The scrubber ------------------------------------------------------
   The ribbon is the film at scale: each section as wide as its own length.
   The stage answers the playhead. Before the product appears there is no
   frame to answer with, which is the whole point, so the panel says so. */

.scrub { margin: 0; }
.scrub__title { margin: 0 0 8px; }

.scrub__note {
  margin: 0 0 16px;
  max-width: 64ch;
  font-size: 15px;
  line-height: 1.55;
  color: var(--ink-soft);
}

.scrub__stage {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border: 3px solid #14110F;
  background: #14110F;
}

.scrub__shot {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 150ms linear;
}

.scrub__shot.is-on { opacity: 1; }

/* What the film has still not shown, along the foot of the stage, on a
   strip of paper thin enough to keep the frame underneath it readable.
   It goes the moment the product arrives. */
.scrub__bar {
  position: absolute;
  z-index: 2;
  right: 0;
  bottom: 0;
  left: 0;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  padding: 8px 12px;
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.4;
  background: rgba(241, 239, 233, 0.82);
  opacity: 0;
  visibility: hidden;
  transition: opacity 150ms linear, visibility 0s linear 150ms;
}

.scrub__bar.is-on {
  opacity: 1;
  visibility: visible;
  transition: opacity 150ms linear, visibility 0s;
}

.scrub__flag {
  letter-spacing: 0.1em;
  color: var(--mark-call);
}

.scrub__pct {
  white-space: nowrap;
  color: var(--ink-soft);
}

.scrub__clock {
  position: absolute;
  z-index: 2;
  top: 10px;
  right: 10px;
  padding: 4px 9px;
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.1em;
  color: var(--ink);
  background: rgba(241, 239, 233, 0.82);
}

/* What is being said over that frame, as written and as it reads. */
.scrub__said {
  min-height: 74px;
  margin: 12px 0 0;
  max-width: 76ch;
  opacity: 0;
  transition: opacity 150ms linear;
}

.scrub__said.is-on { opacity: 1; }

.scrub__greek {
  margin: 0;
  font-size: 16px;
  line-height: 1.5;
  color: var(--ink);
}

.scrub__english {
  margin: 4px 0 0;
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.6;
  color: var(--mark);
}

.scrub__ribbon {
  position: relative;
  margin: 14px 0 0;
  cursor: grab;
  touch-action: none;
  user-select: none;
}

.scrub__ribbon.is-held { cursor: grabbing; }
.scrub__ribbon:focus-visible { outline: 2px solid var(--mark); outline-offset: 4px; }

.scrub__bands {
  display: flex;
  height: 68px;
  pointer-events: none;
}

.scrub__band {
  display: flex;
  flex: 0 1 0%;
  flex-direction: column;
  align-items: flex-start;
  overflow: hidden;
  padding: 8px 0 0;
  min-width: 0;
}

/* Each label sits at its own width, so a band can be asked whether the
   name it carries actually fits inside it. */
.scrub__bandnum,
.scrub__bandname,
.scrub__bandtime {
  flex: none;
  width: max-content;
  padding: 0 8px;
  font-family: var(--mono);
  color: var(--paper);
  white-space: nowrap;
}

.scrub__band.is-tight .scrub__bandname { display: none; }
.scrub__band.is-cramped .scrub__bandtime { display: none; }

.scrub__bandnum {
  font-size: 11px;
  line-height: 1.25;
  letter-spacing: 0.14em;
  opacity: 0.75;
}

.scrub__bandname {
  margin: 2px 0 0;
  font-size: 13px;
  line-height: 1.25;
  letter-spacing: 0.1em;
}

.scrub__bandtime {
  margin: 2px 0 0;
  font-size: 11px;
  line-height: 1.25;
  letter-spacing: 0.08em;
  opacity: 0.75;
}

/* The playhead. It sits on the line rather than between the bands, so the
   second it is reading is never in doubt. */
.scrub__head {
  position: absolute;
  top: -6px;
  bottom: -6px;
  left: 0;
  width: 3px;
  margin-left: -1px;
  background: var(--ink);
  pointer-events: none;
}

.scrub__grab {
  position: absolute;
  top: -7px;
  left: 50%;
  width: 15px;
  height: 15px;
  transform: translateX(-50%) rotate(45deg);
  background: var(--ink);
}

.scrub__ribbon:focus-visible .scrub__grab {
  box-shadow: 0 0 0 3px var(--paper), 0 0 0 5px var(--mark);
}

/* The transport. One button and the rate it runs at, nothing else. */
.scrub__trans {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 18px 0 0;
}

.scrub__play {
  flex: none;
  padding: 8px 22px;
  font-family: var(--mono);
  font-size: 15px;
  letter-spacing: 0.12em;
  color: var(--ink);
  background: var(--paper);
  border: 2px solid var(--ink);
  cursor: pointer;
}

.scrub__play:hover { background: var(--paper-hi); }
.scrub__play:focus-visible { outline: 2px solid var(--mark); outline-offset: 3px; }

.scrub__rate {
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
}

/* Below 700px the ribbon keeps its full width, so the proportions still
   read. The names are what goes, because the numbers carry the order. */
@media (max-width: 699px) {
  .scrub__bands { height: 46px; }
  .scrub__band { padding: 6px 0 0; }
  .scrub__bandnum,
  .scrub__bandname,
  .scrub__bandtime { padding: 0 4px; }
  .scrub__bandname { display: none; }
  .scrub__bandnum { font-size: 10px; line-height: 1.25; letter-spacing: 0.08em; }
  .scrub__bandtime { font-size: 10px; line-height: 1.25; margin: 2px 0 0; }
  .scrub__said { min-height: 96px; }
  .scrub__greek { font-size: 15px; }
  .scrub__bar {
    flex-direction: column;
    align-items: flex-start;
    gap: 1px;
    padding: 6px 10px;
    font-size: 11px;
  }
  .scrub__flag { letter-spacing: 0.06em; }
  .scrub__clock { font-size: 12px; }
  .scrub__trans,
  .stops__trans { flex-direction: column; align-items: stretch; gap: 8px; }
  .scrub__play { width: 100%; }
}

/* Reduced motion cuts rather than fades. */
@media (prefers-reduced-motion: reduce) {
  .scrub__shot,
  .scrub__bar,
  .scrub__bar.is-on,
  .scrub__said { transition: none; }
}


/* -- The phone -------------------------------------------------------
   The guide made to be done. Paper ground, ink lines, nothing rounded
   that is not a phone. */

.phone { margin: 0; }

.phone__stage {
  position: relative;
  margin: 0 0 22px;
}

.phone__art {
  display: block;
  overflow: hidden;
}

.phone__art svg,
.phone__fallback {
  display: block;
  width: 100%;
  height: auto;
}

/* Everything the first recordings got wrong, going one at a time. */
.phone__art svg .is-gone {
  opacity: 0;
  visibility: hidden;
  transition: opacity 300ms linear, visibility 0s linear 300ms;
}

.phone__art svg #bad-wall,
.phone__art svg #bad-wardrobe,
.phone__art svg #bad-light-back,
.phone__art svg #bad-light-front,
.phone__art svg #bad-sound-fan,
.phone__art svg #bad-sound-meter,
.phone__art svg #bad-sound-notif,
.phone__art svg #good-sound-meter {
  transition: opacity 300ms linear, visibility 0s;
}

.phone__art svg #good-sound-meter { opacity: 0; visibility: hidden; }
.phone__art svg #good-sound-meter:not(.is-gone) { opacity: 1; visibility: visible; }

/* The frame itself: off axis and too low until the phone is set right. */
.phone__art svg #framing {
  transform-box: view-box;
  transform-origin: 800px 450px;
  transform: rotate(-6deg) translate(150px, 80px) scale(0.86);
  transition: transform 450ms ease;
}

.phone__art svg #framing.is-set { transform: none; }

.phone__count {
  position: absolute;
  top: 14px;
  right: 16px;
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin: 0;
  padding: 6px 12px;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.12em;
  color: var(--ink);
  background: rgba(241, 239, 233, 0.92);
}

.phone__reset {
  padding: 0;
  border: 0;
  background: none;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.phone__reset:hover { color: var(--ink); }
.phone__reset:focus-visible { outline: 2px solid var(--mark); outline-offset: 3px; }

/* Nothing to stamp until every one of them is fixed. */
.phone__stamp {
  position: absolute;
  left: 50%;
  top: 50%;
  padding: 18px 30px;
  transform: translate(-50%, -50%) rotate(-5deg) scale(0.9);
  border: 3px solid var(--mark);
  background: var(--paper);
  text-align: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity 250ms linear, transform 250ms var(--enter), visibility 0s linear 250ms;
}

.phone__stamp.is-on {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, -50%) rotate(-5deg) scale(1);
  transition: opacity 250ms linear, transform 250ms var(--enter), visibility 0s;
}

.phone__stampline {
  margin: 0;
  font-family: var(--mono);
  font-size: 19px;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--mark);
}

.phone__stampnote {
  margin: 6px 0 0;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--ink-soft);
}

.phone__rows {
  margin: 0 0 4px;
  padding: 0;
  list-style: none;
  border-top: 1px dashed var(--rule);
}

.phone__row {
  padding: 12px 0;
  border-bottom: 1px dashed var(--rule);
}

.phone__toggle {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  text-align: left;
  cursor: pointer;
}

.phone__toggle:focus-visible { outline: 2px solid var(--mark); outline-offset: 4px; }

.phone__box {
  flex: none;
  width: 18px;
  height: 18px;
  border: 2px solid var(--ink);
  background: transparent;
  transition: background 150ms linear;
}

.phone__row.is-fixed .phone__box { background: var(--ink); }

.phone__name {
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.1em;
  color: var(--ink);
}

.phone__row.is-fixed .phone__name { color: var(--ink-soft); }

.phone__line {
  display: none;
  margin: 8px 0 0 32px;
  max-width: 64ch;
  font-family: var(--mono);
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--ink-soft);
}

.phone__row.is-fixed .phone__line { display: block; }

/* -- The trace -------------------------------------------------------
   The editor above, what it rendered below, and the links between. */

.trace { margin: 0; }

.trace__wrap {
  position: relative;
  display: block;
}

.trace__img {
  display: block;
  width: 100%;
  height: auto;
}

/* The drawn rect stays true to the graphic. The hit area is grown by a
   pseudo element, so a finger has something to find without the outline
   lying about where the thing is. */
.trace__spot {
  position: absolute;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  outline-offset: 0;
}

.trace__spot::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 100%;
  height: 100%;
  min-width: 44px;
  min-height: 44px;
  transform: translate(-50%, -50%);
}

.trace__spot.is-lit {
  outline: 3px solid var(--mark);
  background: color-mix(in srgb, var(--mark) 12%, transparent);
}

.trace__spot--plain.is-lit { background: transparent; }
.trace__spot:focus-visible { outline: 3px solid var(--mark); }

.trace__badge {
  position: absolute;
  left: 0;
  top: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  background: var(--mark);
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 700;
  color: var(--paper);
}

.trace__read {
  margin: 14px 0 0;
  min-height: 3.2em;
  max-width: 76ch;
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink);
}

/* -- The stops -------------------------------------------------------
   Script to publication, with the two gates marked. */

.stops { margin: 0; }

.stops__read {
  min-height: 96px;
  margin: 0 0 22px;
  max-width: 76ch;
}

.stops__num {
  margin: 0;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.16em;
  color: var(--mark);
}

.stops__name {
  margin: 4px 0 0;
  font-family: var(--mono);
  font-size: 17px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink);
}

.stops__line {
  margin: 6px 0 0;
  font-size: 15px;
  line-height: 1.55;
  color: var(--ink-soft);
}

.stops__track {
  position: relative;
  container-type: inline-size;
  --inset: 10cqw;
  height: 124px;
  margin: 0 0 18px;
  cursor: pointer;
  touch-action: none;
  user-select: none;
}

.stops__track:focus-visible { outline: 2px solid var(--mark); outline-offset: 4px; }

.stops__rail {
  position: absolute;
  left: var(--inset);
  right: var(--inset);
  top: 11px;
  height: 2px;
  background: var(--rule);
}

.stops__tick {
  position: absolute;
  top: 0;
  width: 0;
}

.stops__mark {
  position: absolute;
  left: -6px;
  top: 6px;
  width: 12px;
  height: 12px;
  background: var(--ink);
}

.stops__tick--gate .stops__mark {
  left: -8px;
  top: 4px;
  width: 16px;
  height: 16px;
  background: var(--mark);
}

/* A label is given a fifth of the track less a gutter, which is twice the
   space between two stops because its neighbours sit on the other row.
   Written in the track's own width, it holds as the modal changes size. */
.stops__tag {
  position: absolute;
  left: 0;
  top: 26px;
  width: calc(1.8 * var(--inset));
  margin-left: calc(-0.9 * var(--inset));
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  line-height: 1.35;
  text-align: center;
  color: var(--ink-faint);
}

/* A dropped row, with a leader so a label still reads as its tick's. */
.stops__tick[data-row2='1'] .stops__tag { top: 76px; }

.stops__tick[data-row2='1']::after {
  content: '';
  position: absolute;
  left: -1px;
  top: 22px;
  width: 1px;
  height: 50px;
  background: var(--rule);
}


.stops__tick.is-past .stops__tag { color: var(--ink-soft); }

.stops__tick.is-on .stops__tag {
  color: var(--ink);
  font-weight: 700;
}

.stops__head {
  position: absolute;
  top: -4px;
  width: 3px;
  height: 32px;
  margin-left: -1px;
  background: var(--ink);
  transition: left 200ms var(--enter);
  pointer-events: none;
}

.stops__trans {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 0 0 4px;
}

/* Under about 430px a label on two rows would be narrower than the longest
   word in it, so the stops take three rows and a quarter of the track each,
   and the rail is held further in to pay for the wider ends. */
@media (max-width: 430px) {
  .stops__track { --inset: 14cqw; height: 164px; }

  .stops__tag {
    width: calc(1.79 * var(--inset));
    margin-left: calc(-0.895 * var(--inset));
  }

  .stops__tick[data-row2='1'] .stops__tag { top: 26px; }
  .stops__tick[data-row2='1']::after { content: none; }

  .stops__tick[data-row3='1'] .stops__tag { top: 72px; }
  .stops__tick[data-row3='2'] .stops__tag { top: 118px; }

  .stops__tick[data-row3='1']::after,
  .stops__tick[data-row3='2']::after {
    content: '';
    position: absolute;
    left: -1px;
    top: 22px;
    width: 1px;
    background: var(--rule);
  }

  .stops__tick[data-row3='1']::after { height: 46px; }
  .stops__tick[data-row3='2']::after { height: 92px; }
}

/* -- The flip strip --------------------------------------------------
   Four more courses, the frame on the front and the build on the back. */

.courses { margin: 0; }

.courses__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 22px;
}

.courses__cell { min-width: 0; }

.courses__pane {
  min-height: 0;
  aspect-ratio: 1200 / 910;
}

.courses__front,
.courses__back {
  position: absolute;
  inset: 0;
  width: 100%;
  padding: 0;
  border: 3px solid var(--ink);
  background: var(--paper);
  cursor: pointer;
}

.courses__front {
  display: block;
  overflow: hidden;
}

/* The fronts are not all one height, so they sit to the top of a shared
   shape rather than being stretched to fill it. */
.courses__shot {
  display: block;
  width: 100%;
  height: auto;
}

.courses__back {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: 0;
  padding: 20px 22px;
  overflow: auto;
  text-align: left;
}

.courses__rows {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 6px 16px;
  margin: 0;
}

.courses__key {
  margin: 0;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  white-space: nowrap;
}

.courses__val {
  margin: 0;
  font-size: 14px;
  line-height: 1.45;
  color: var(--ink);
}

.courses__made {
  margin: 14px 0 0;
  padding-top: 10px;
  border-top: 1px dashed var(--rule);
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.5;
  color: var(--ink-soft);
}

/* -- The reel --------------------------------------------------------
   The film and its cut list, reading each other. The bar is the cut list
   drawn to scale: a section's share of the thirty five seconds is its
   width, so the picture of the reel is also its measure. */

.reel { margin: 0; }

/* The film sits in the house frame, with its poster until it is asked for. */
.reel__stage { position: relative; margin: 0 0 18px; }




/* The paper triangle inside the ink square. */


/* The panel head, with the square the rest of the receipt uses. */
.reel__eyebrow { display: flex; align-items: center; gap: 8px; }

.reel__sq {
  width: 8px;
  height: 8px;
  background: var(--accent);
  flex: none;
}

/* -- The range filter ------------------------------------------------ */

.reel__range {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 0 0 18px;
}

.reel__chip {
  padding: 6px 12px;
  border: 2px solid var(--ink);
  background: var(--paper);
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.08em;
  color: var(--ink);
  cursor: pointer;
}

.reel__chip:hover { background: var(--paper-hi); }
.reel__chip.is-on { background: var(--ink); color: var(--paper); }
.reel__chip:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }

.reel__tally {
  margin: 0 0 0 auto;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
  white-space: nowrap;
}

/* -- The bar ---------------------------------------------------------- */

.reel__bar {
  position: relative;
  margin: 0 0 22px;
}

.reel__segs {
  position: relative;
  display: flex;
  gap: 2px;
  height: 28px;
}

.reel__seg {
  position: relative;
  flex: 0 1 0;
  min-width: 0;
  padding: 0;
  border: 0;
  background: #14110F;
  cursor: pointer;
  transition: transform var(--t-micro) var(--micro), opacity var(--t-micro) var(--micro);
}

.reel__seg--source { background: var(--accent); }

/* Stock is not mine, so it is drawn as paper that has been marked up. */
.reel__seg--stock {
  background: var(--paper);
  outline: 2px solid #4A443C;
  outline-offset: -2px;
  background-image: repeating-linear-gradient(
    45deg,
    #8B8478 0 2px,
    transparent 2px 7px
  );
}

.reel__seg.is-on {
  transform: translateY(-4px);
  outline: 3px solid var(--accent);
  outline-offset: 0;
  z-index: 2;
}

.reel__seg.is-dim { opacity: 0.25; }
.reel__seg:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; z-index: 3; }

.reel__nums {
  display: flex;
  gap: 2px;
  margin: 7px 0 0;
}

.reel__num {
  flex: 0 1 0;
  min-width: 0;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-align: center;
  color: var(--ink-faint);
  transition: opacity var(--t-micro) var(--micro);
}

.reel__num.is-dim { opacity: 0.25; }

/* The film's own clock, laid over the cut list. */
.reel__head {
  position: absolute;
  left: 0;
  top: -5px;
  width: 2px;
  height: 38px;
  margin-left: -1px;
  background: var(--ink);
  opacity: 0;
  pointer-events: none;
  z-index: 4;
  transition: left 120ms linear;
}

.reel__head.is-live { opacity: 1; }

/* -- The scrub preview ------------------------------------------------- */

/* It rests over the middle of the bar until a pointer gives it a place,
   or it would hang off the paper before it had ever been asked for. */
.reel__peek {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 12px);
  width: 240px;
  margin-left: -120px;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  z-index: 5;
  transition: opacity var(--t-micro) var(--micro), visibility var(--t-micro) var(--micro);
}

.reel__peek.is-up { opacity: 1; visibility: visible; }

.reel__peekart {
  width: 240px;
  height: 135px;
  border: 3px solid var(--ink);
  background-repeat: no-repeat;
  background-color: #14110F;
}

.reel__peektime {
  margin: 0;
  padding: 4px 0;
  background: var(--ink);
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.1em;
  text-align: center;
  color: var(--paper);
}

/* The cut list as a picture, where scripts never ran. */
.reel__plain { display: block; width: 100%; height: auto; }

/* -- The readout -------------------------------------------------------- */

.reel__read {
  display: flex;
  gap: 18px;
  min-height: 150px;
  margin: 0 0 18px;
}

.reel__shot {
  flex: none;
  width: 212px;
  height: auto;
  align-self: flex-start;
  border: 3px solid var(--ink);
}

.reel__text { min-width: 0; }

.reel__rest {
  margin: 0;
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
}

.reel__name {
  margin: 0;
  font-family: var(--mono);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--ink);
}

.reel__kind {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 6px 0 0;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.1em;
  color: var(--ink-soft);
}

.reel__tc {
  margin: 4px 0 0;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.06em;
  color: var(--ink-faint);
}

.reel__row {
  margin: 10px 0 0;
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink-body);
}

.reel__lab {
  margin-right: 10px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  color: var(--ink-faint);
}

.reel__forms { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }

.reel__form {
  padding: 3px 8px;
  border: 1px solid var(--ink);
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  color: var(--ink);
}

/* The three kinds, in the same fills the bar uses. */
.reel__mark {
  width: 12px;
  height: 12px;
  flex: none;
  background: #14110F;
}

.reel__mark--source { background: var(--accent); }

.reel__mark--stock {
  background: var(--paper);
  outline: 2px solid #4A443C;
  outline-offset: -2px;
  background-image: repeating-linear-gradient(
    45deg,
    #8B8478 0 2px,
    transparent 2px 7px
  );
}

.reel__legend {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 24px;
  margin: 0;
  padding-top: 14px;
  border-top: 1px dashed var(--rule);
}

.reel__leg {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
}

/* -- The sources --------------------------------------------------------
   Three places the work came from, each one a card of its own. */

.srcs {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  margin: 0;
}

.srcs__card {
  display: flex;
  flex-direction: column;
  border: 3px solid var(--ink);
  background: var(--paper);
  transition: border-color var(--t-micro) var(--micro);
}

.srcs__card:hover,
.srcs__card:focus-visible,
.srcs__card:focus-within { border-color: var(--accent); outline: none; }

.srcs__head {
  margin: 0;
  padding: 10px 14px;
  background: var(--ink);
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 400;
  letter-spacing: 0.1em;
  line-height: 1.35;
  color: var(--paper);
}

/* The buttons sit at the bottom of the card, which is what keeps the
   three cards the same height whatever their copy runs to. */
.srcs__ways {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  margin-top: auto;
  padding-top: 12px;
}

.srcs__body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  gap: 10px;
  padding: 14px;
}

.srcs__line {
  margin: 0;
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink-body);
}

.srcs__role {
  margin: 0 0 auto;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--ink-soft);
}

.srcs__link {
  align-self: flex-start;
  padding: 6px 11px;
  border: 2px solid var(--accent);
  background: var(--paper);
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.08em;
  color: var(--ink);
  cursor: pointer;
}

.srcs__link:hover { background: var(--paper-hi); }
.srcs__link:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }

/* -- beCreatives ------------------------------------------------------
   A queue of a thousand videos, read through the few things that made it
   repeatable: the count, the sample, the five statuses, the project files
   and what the juniors were taught. Teal is this work's marker. */

.seq__text { margin: 0 0 18px; }
.seq__text:last-child { margin-bottom: 0; }

.seq__credit {
  margin: 14px 0 0;
  max-width: 76ch;
  font-family: var(--mono);
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--ink-soft);
}

/* -- The count strip --------------------------------------------------- */

.cstrip {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 18px;
  margin: 4px 0 22px;
  padding: 18px 0;
  border-top: 1px dashed var(--rule);
  border-bottom: 1px dashed var(--rule);
}

.cstrip__fig {
  margin: 0;
  font-family: var(--mono);
  font-size: 30px;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: 0.01em;
  color: var(--mark);
  font-variant-numeric: tabular-nums;
}

.cstrip__fixed { font-weight: 700; }

.cstrip__lab {
  margin: 7px 0 0;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  color: var(--ink-soft);
}

/* -- The wall ----------------------------------------------------------- */

.wall { margin: 0 0 6px; }

.wall__tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 12px;
}

.wall__tab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 12px;
  border: 2px solid var(--ink);
  background: var(--paper);
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.08em;
  color: var(--ink);
  cursor: pointer;
}

/* The tab is 36 tall. The target reaches 4px above and below it, which
   makes 44, and never sideways, where the next tab is. */
.wall__tab { position: relative; }

.wall__tab::after {
  content: '';
  position: absolute;
  top: -4px;
  bottom: -4px;
  left: 0;
  right: 0;
}

.wall__tab:hover { background: var(--paper-hi); }
.wall__tab.is-on { background: var(--ink); color: var(--paper); }
.wall__tab:focus-visible { outline: 3px solid var(--mark); outline-offset: 3px; }

.wall__tabn {
  padding: 1px 6px;
  border: 1px solid currentColor;
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
}

.wall__read {
  margin: 0 0 14px;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.1em;
  color: var(--ink-faint);
}

/* The devices sit over the grid now, so the grid takes the whole width. */
/* The stacked arrangement is the default, because it is the one that
   always has room. Sharing a line is the exception, and it is asked for
   against the width the devices actually have rather than the width of
   the window, which is not the same thing inside a modal. */
.wall__stage { container-type: inline-size; }

/* With nothing chosen there is no stage at all, so the wall does not sit
   under a gap waiting for a device that may never be asked for. */
.wall__stage:not(.is-live) .wall__devices { display: none; }

/* The device arrives rather than appearing: it comes up a little as it
   fades in, which reads as a thing being brought out. */
@keyframes wall-rise {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}

.wall__bay.is-rising { animation: wall-rise 220ms var(--enter) both; }

@media (prefers-reduced-motion: reduce) {
  .wall__bay.is-rising { animation: none; }
}

.wall__devices {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
  gap: 24px;
  margin: 0 0 18px;
}

.wall__bay {
  width: 100%;
  min-width: 0;
  transition: opacity 250ms var(--enter), transform 250ms var(--enter);
}

/* On its own the phone has no monitor to match, so it keeps a size a
   phone should be rather than growing to the width of the page. */
.wall__bay--phone { max-width: 324px; margin: 0 auto; }

/* 256 against 81 is 16/9 against 9/16, so with an aspect ratio on each
   screen the two come out at the same height and the monitor takes about
   three quarters of the row. 743px is the width below which that split
   would leave the monitor under 520px of screen, which is the point the
   two stop sharing a line. */
@container (min-width: 743px) {
  .wall__devices:not(.is-solo) {
    grid-template-columns: 256fr 81fr;
    align-items: stretch;
    justify-items: stretch;
  }

  .wall__devices:not(.is-solo) .wall__bay--phone { max-width: none; margin: 0; }

  /* Stretched to the monitor's height, the phone takes its width from its
     own shape instead of setting the height of the row. */
  .wall__devices:not(.is-solo) .bcphone {
    display: flex;
    flex-direction: column;
    height: 100%;
  }

  .wall__devices:not(.is-solo) .bcphone__screen {
    flex: 1 1 auto;
    aspect-ratio: auto;
  }
}

.wall__bay.is-off {
  display: none;
  opacity: 0;
  transform: translateY(8px);
}

.wall__out--stage { grid-column: 1 / -1; text-align: center; }

.wall__body { display: block; }

.wall__grid {
  display: grid;
  grid-template-columns: repeat(10, 1fr);
  gap: 10px;
}

.wall__cell { grid-column: span 2; min-width: 0; }
.wall__cell--h { grid-column: span 5; }
.wall__cell[hidden] { display: none; }

.wall__card {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  transition: transform var(--t-micro) var(--micro);
}

.wall__shot {
  position: relative;
  display: block;
  border: 3px solid var(--ink);
  background: var(--ph-fill);
  /* The rest of the page prints in thermal greys and comes up in colour
     when it is pointed at. A poster is no different. */
  filter: grayscale(1) contrast(1.08) brightness(0.9);
  transition: filter var(--t-exit) var(--enter);
}

.wall__shot img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 9 / 16;
  object-fit: cover;
}

.wall__cell--h .wall__shot img { aspect-ratio: 16 / 9; }

.wall__card:hover,
.wall__card:focus-visible { transform: translateY(-4px) rotate(var(--tilt, 0deg)); }
.wall__card:focus-visible { outline: 3px solid var(--mark); outline-offset: 4px; }

.wall__card:hover .wall__shot,
.wall__card:focus-visible .wall__shot { filter: none; }

.wall__card.is-playing .wall__shot {
  filter: none;
  border-color: var(--mark);
}

/* One line of type, clipped rather than wrapped: three wrapped lines were
   covering half of every vertical poster. */
.wall__chip {
  position: absolute;
  left: 0;
  bottom: 0;
  max-width: 100%;
  padding: 4px 7px;
  background: var(--ink);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  line-height: 1.25;
  color: var(--paper);
  text-align: left;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.wall__now {
  position: absolute;
  left: 0;
  top: 0;
  padding: 4px 7px;
  background: var(--mark);
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.08em;
  color: var(--paper);
}

/* A landscape cut opens where it sits, at the width of the row. */
.wall__hold { display: none; }

.wall__hold.is-open {
  display: block;
  margin: 10px 0 0;
  aspect-ratio: 16 / 9;
  border: 3px solid var(--ink);
  background: #14110F;
}

.wall__hold iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

.wall__out { margin: 6px 0 0; }
.wall__out:empty { margin: 0; }

.wall__link {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
  text-decoration: underline;
  text-underline-offset: 4px;
}

.wall__link:hover { color: var(--ink); }

.bcphone {
  position: relative;
  padding: 12px 10px;
  border: 3px solid var(--ink);
  border-radius: 26px;
  background: var(--ink);
}

.bcphone__notch {
  position: absolute;
  left: 50%;
  top: 5px;
  width: 54px;
  height: 4px;
  margin-left: -27px;
  border-radius: 2px;
  background: var(--paper-lo);
  opacity: 0.4;
}

.bcphone__screen {
  position: relative;
  z-index: 1;
  isolation: isolate;
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 9 / 16;
  background: #14110F;
  overflow: hidden;
}

.bcphone__screen iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

.bcphone__idle {
  margin: 0;
  padding: 0 14px;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.08em;
  text-align: center;
  color: var(--ink-faint);
}

/* -- The monitor ------------------------------------------------------
   The phone's counterpart, in the same ink and the same corner, so the
   two read as a pair rather than as two different drawings. */

.bcmon { display: flex; flex-direction: column; align-items: center; }

.bcmon { width: 100%; }

.bcmon__body {
  width: 100%;
  padding: clamp(6px, 1.2%, 14px) clamp(6px, 1.2%, 14px) clamp(9px, 1.8%, 20px);
  border: 3px solid var(--ink);
  border-radius: clamp(10px, 1.6%, 18px);
  background: var(--ink);
}

.bcmon__screen {
  position: relative;
  z-index: 1;
  isolation: isolate;
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 16 / 9;
  background: #14110F;
  overflow: hidden;
}

.bcmon__screen iframe,
.bcmon__screen video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  object-fit: cover;
}

.bcmon__idle {
  margin: 0;
  padding: 0 14px;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.08em;
  text-align: center;
  color: var(--ink-faint);
}

.bcmon__neck { width: 9%; min-width: 40px; height: clamp(12px, 2.4%, 26px); background: var(--ink); }

.bcmon__foot {
  width: 24%;
  min-width: 96px;
  height: clamp(6px, 1%, 11px);
  border-radius: 4px;
  background: var(--ink);
}

/* -- One job, five steps ------------------------------------------------ */

.job { margin: 0 0 6px; }
.job__flat img { display: block; width: 100%; height: auto; }

.job__ask {
  margin: 0 0 16px;
  padding: 8px 14px;
  border: 2px solid var(--ink);
  background: var(--paper);
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  cursor: pointer;
}

.job__track {
  position: relative;
  display: flex;
  align-items: stretch;
  margin: 34px 0 22px;
  padding-top: 30px;
}

.job__node {
  flex: 1 1 0;
  min-width: 0;
  padding: 9px 4px;
  border: 2px solid var(--rule);
  background: var(--paper);
  font-family: var(--mono);
  cursor: pointer;
  transition: border-color var(--t-micro) var(--micro), background var(--t-micro) var(--micro);
}

.job__num { display: block; font-size: 10.5px; letter-spacing: 0.1em; color: var(--ink-faint); }
.job__name { display: block; margin-top: 3px; font-size: 10.5px; letter-spacing: 0.04em; line-height: 1.3; color: var(--ink-soft); }
.job__node.is-on { border-color: var(--mark); background: var(--paper-hi); }
.job__node.is-on .job__name { color: var(--ink); font-weight: 700; }
.job__node.is-on .job__num { color: var(--mark); }
.job__node:focus-visible { outline: 3px solid var(--mark); outline-offset: 3px; }

.job__flow {
  flex: 0 0 20px;
  align-self: center;
  height: 0;
  border-top: 2px dashed var(--rule);
}

/* The ticket sits above its node, never over the number. */
.job__ticket {
  position: absolute;
  top: 0;
  transform: translateX(-50%);
  pointer-events: none;
  transition: left 420ms var(--enter), top 420ms var(--enter);
  z-index: 2;
}

.job__tchip {
  display: inline-block;
  padding: 4px 9px;
  background: var(--mark);
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  white-space: nowrap;
  color: var(--paper);
}

.job__views { margin: 0 0 12px; }

.job__frame {
  position: relative;
  overflow: hidden;
  border: 3px solid var(--ink);
  background: var(--paper-lo);
  aspect-ratio: var(--ratio, 1600 / 1000);
}

.job__plane {
  position: relative;
  width: 100%;
  transform-origin: 50% 50%;
  transition: transform 500ms var(--enter);
}

.job__img {
  display: block;
  width: 100%;
  height: auto;
  transition: opacity 200ms var(--enter);
}

.job__img.is-fading { opacity: 0; }
.job__plane.is-held .job__img { opacity: 0.55; }

.job__spot {
  position: absolute;
  padding: 0;
  border: 2px solid transparent;
  background: none;
  cursor: pointer;
  z-index: 3;
  transition: border-color var(--t-micro) var(--micro);
}

.job__spot--thin::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 28px;
  transform: translateY(-50%);
}

.job__badge {
  position: absolute;
  left: -2px;
  top: -2px;
  min-width: 17px;
  padding: 1px 3px;
  background: var(--mark);
  font-family: var(--mono);
  font-size: 10px;
  line-height: 1.4;
  text-align: center;
  color: var(--paper);
  z-index: 4;
}

/* The label rides beside its marker rather than under the picture. */
.job__tag {
  position: absolute;
  left: 100%;
  top: -2px;
  margin-left: 6px;
  padding: 2px 7px;
  background: var(--ink);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.05em;
  white-space: nowrap;
  color: var(--paper);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t-micro) var(--micro);
  z-index: 5;
}

.job__spot--flip .job__tag {
  left: auto;
  right: 100%;
  margin-left: 0;
  margin-right: 6px;
}

.job__spot.is-lit { border-color: var(--mark); border-width: 3px; }
.job__spot.is-lit .job__tag { opacity: 1; }
.job__spot:focus-visible { outline: 3px solid var(--mark); outline-offset: 2px; }

/* The box a followed file lights, on whichever picture is showing. */
.job__fbox {
  position: absolute;
  border: 3px solid var(--mark);
  pointer-events: none;
  z-index: 4;
}

.job__fbox.is-pulse { animation: bc-pulse 650ms var(--enter) 1; }

.job__phone { width: 190px; margin: 0 auto; }

.job__play {
  position: absolute;
  inset: 0;
  padding: 0;
  border: 0;
  background: #14110F;
  cursor: pointer;
}

.job__playshot { display: block; width: 100%; height: 100%; object-fit: cover; }

.job__playmark {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 52px;
  height: 52px;
  margin: -26px 0 0 -26px;
  background: var(--ink);
}

.job__playmark::after {
  content: '';
  position: absolute;
  left: 20px;
  top: 16px;
  border-style: solid;
  border-width: 10px 0 10px 16px;
  border-color: transparent transparent transparent var(--paper);
}

.job__viewtabs { display: flex; gap: 8px; margin: 0 0 12px; }

.job__viewtab {
  padding: 5px 11px;
  border: 1px solid var(--rule);
  background: var(--paper);
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
  cursor: pointer;
}

.job__viewtab.is-on { border-color: var(--mark); background: var(--mark); color: var(--paper); }
.job__viewtab:focus-visible { outline: 3px solid var(--mark); outline-offset: 2px; }

.job__line {
  margin: 0;
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink-body);
}

.job__read {
  margin: 4px 0 0;
  min-height: 1.3em;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--mark);
}

.job__reset {
  margin: 10px 0 0;
  padding: 6px 11px;
  border: 2px solid var(--ink);
  background: var(--paper);
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  cursor: pointer;
}

.job__files {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 7px;
  margin: 18px 0;
  transition: opacity var(--t-micro) var(--micro);
}

.job__files.is-dim { opacity: 0.55; }

.job__fileslab {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  color: var(--ink-faint);
}

.job__file {
  padding: 5px 9px;
  border: 1px solid var(--rule);
  background: var(--paper);
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.03em;
  color: var(--ink-soft);
  cursor: pointer;
}

.job__file.is-on { border-color: var(--mark); background: var(--mark); color: var(--paper); }
.job__file:focus-visible { outline: 3px solid var(--mark); outline-offset: 2px; }

.job__trans { display: flex; align-items: center; gap: 12px; margin: 0 0 16px; }

.job__t {
  position: relative;
  width: 38px;
  height: 34px;
  flex: none;
  border: 2px solid var(--ink);
  background: var(--paper);
  cursor: pointer;
}

.job__t:focus-visible { outline: 3px solid var(--mark); outline-offset: 3px; }
.job__t::before, .job__t::after { content: ''; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }

.job__t--play::before { border-style: solid; border-width: 7px 0 7px 11px; border-color: transparent transparent transparent var(--ink); margin-left: 1px; }
.job__t--play.is-playing::before { border: 0; width: 4px; height: 13px; margin-left: -4px; background: var(--ink); }
.job__t--play.is-playing::after { width: 4px; height: 13px; margin-left: 4px; background: var(--ink); }
.job__t--back::before { border-style: solid; border-width: 6px 9px 6px 0; border-color: transparent var(--ink) transparent transparent; }
.job__t--fwd::before { border-style: solid; border-width: 6px 0 6px 9px; border-color: transparent transparent transparent var(--ink); }
.job__t--back::after, .job__t--fwd::after { width: 2px; height: 13px; background: var(--ink); }
.job__t--back::after { margin-left: -7px; }
.job__t--fwd::after { margin-left: 7px; }

.job__scrub { position: relative; flex: 1 1 auto; height: 28px; cursor: pointer; touch-action: none; }
.job__scrub::before { content: ''; position: absolute; left: 0; right: 0; top: 13px; height: 2px; background: var(--rule); }
.job__scrubfill { position: absolute; left: 0; top: 13px; height: 2px; background: var(--mark); }
.job__knob { position: absolute; top: 7px; width: 14px; height: 14px; margin-left: -7px; background: var(--ink); transition: left 200ms var(--enter); }
.job__scrub:focus-visible { outline: 2px solid var(--mark); outline-offset: 3px; }

.job__count { flex: none; font-family: var(--mono); font-size: 11px; letter-spacing: 0.1em; color: var(--ink-faint); font-variant-numeric: tabular-nums; }

.job__turn {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 20px;
  margin: 0 0 16px;
  padding: 14px 0;
  border-top: 1px dashed var(--rule);
}

.job__pills { display: flex; flex-wrap: wrap; gap: 7px; }

.job__pill {
  padding: 6px 11px;
  border: 2px solid var(--ink);
  background: var(--paper);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  cursor: pointer;
}

.job__pill.is-on { background: var(--mark); border-color: var(--mark); color: var(--paper); }
.job__pill:focus-visible { outline: 3px solid var(--mark); outline-offset: 3px; }

.job__ring { position: relative; width: 78px; flex: none; text-align: center; }
.job__ring svg { display: block; width: 78px; height: 78px; }
.job__ringfig { position: absolute; left: 0; right: 0; top: 28px; margin: 0; font-family: var(--mono); font-size: 14px; font-weight: 700; }
.job__ringlab { margin: 3px 0 0; font-family: var(--mono); font-size: 9px; letter-spacing: 0.1em; color: var(--ink-faint); }

.job__turnlab { margin: 0; font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.12em; color: var(--ink-faint); }
.job__turnfig { margin: 4px 0 0; font-family: var(--mono); font-size: 16px; font-weight: 700; color: var(--mark); }

.job__note { margin: 0; flex: 1 1 180px; font-size: 12.5px; line-height: 1.5; color: var(--ink-soft); }

.job__stats { display: flex; flex-wrap: wrap; gap: 8px 22px; padding-top: 12px; border-top: 1px dashed var(--rule); }
.job__stat { margin: 0; font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.08em; color: var(--ink-soft); }

/* -- FireCut ------------------------------------------------------------ */

.fc { margin: 0 0 6px; }

.fc__title {
  margin: 0 0 8px;
  font-family: var(--mono);
  font-size: 15px;
  letter-spacing: 0.12em;
  color: var(--ink);
}

/* It sits in the flow with room of its own, rather than being run over by
   the grid that follows it. */
.fc__line {
  display: block;
  position: static;
  margin: 0 0 24px;
  max-width: 76ch;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink-body);
}

.fc__grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; }
.fc__cell { min-width: 0; }

.fc__card { display: block; width: 100%; padding: 0; border: 0; background: none; cursor: pointer; }
.fc__card:focus-visible { outline: 3px solid var(--mark); outline-offset: 3px; }

.fc__well {
  position: relative;
  display: block;
  aspect-ratio: 16 / 9;
  border: 3px solid var(--ink);
  background: #14110F;
  overflow: hidden;
}

.fc__shot, .fc__vid {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.fc__vid { opacity: 0; transition: opacity var(--t-micro) var(--micro); }
.fc__well.is-live .fc__vid { opacity: 1; }

.fc__lab {
  margin: 7px 0 0;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
}

.fc__jump {
  margin: 6px 0 0;
  padding: 3px 8px;
  border: 1px solid var(--mark);
  background: var(--paper);
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.06em;
  color: var(--ink);
  cursor: pointer;
}

.fc__jump:focus-visible { outline: 3px solid var(--mark); outline-offset: 2px; }

.fc__foot {
  margin: 16px 0 0;
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.6;
  color: var(--ink-faint);
}

/* The tool on a monitor, in the page. */
.fc__stage { margin: 0 0 24px; }

.fc__stageshot,
.fc__stagevid {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.fc__bar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  margin: 14px 0 0;
}

.fc__now {
  margin: 0;
  min-width: 15ch;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-align: center;
  color: var(--ink);
}

.fc__step {
  position: relative;
  width: 38px;
  height: 34px;
  flex: none;
  border: 2px solid var(--ink);
  background: var(--paper);
  cursor: pointer;
}

.fc__step:hover { background: var(--paper-hi); }
.fc__step:focus-visible { outline: 3px solid var(--mark); outline-offset: 3px; }
.fc__stage:focus-visible { outline: 3px solid var(--mark); outline-offset: 4px; }

.fc__step::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  border-style: solid;
  transform: translate(-50%, -50%);
}

.fc__step--prev::before { border-width: 7px 10px 7px 0; border-color: transparent var(--ink) transparent transparent; }
.fc__step--next::before { border-width: 7px 0 7px 10px; border-color: transparent transparent transparent var(--ink); }

/* The card whose clip is on the monitor. */
.fc__cell.is-on .fc__well { border-color: var(--mark); }

.fc__now2 {
  position: absolute;
  left: 0;
  top: 0;
  padding: 3px 7px;
  background: var(--mark);
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.08em;
  color: var(--paper);
  z-index: 2;
}

/* -- A work still to come ----------------------------------------------
   The same card without the door. Nothing lifts, nothing presses. */

.project--soon { cursor: default; }
.project--soon .project__frame { opacity: 0.86; }

/* -- The seat note in the crew table ------------------------------------ */


/* -- What a work is, where that is not what it looks like --------------- */

.modal__stamp {
  margin: 10px 0 0;
  font-family: var(--mono);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  line-height: 1.4;
  text-transform: uppercase;
  color: var(--accent);
}

/* -- Two sides of one tape ----------------------------------------------
   The card is the thing that turns, so both faces live inside it and the
   turn is one transform on one layer. */

.tape { margin: 26px 0 0; }

.tape__stage {
  /* Without a vanishing point a turn around the vertical axis reads as a
     squash. This is what makes it a turn. */
  perspective: 1200px;
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}

.tape__card {
  position: relative;
  width: min(100%, 340px);
  aspect-ratio: 8 / 5;
  padding: 0;
  border: 0;
  border-radius: 10px;
  background: #14110F;
  box-shadow: 3px 3px 0 rgba(0, 0, 0, 0.22);
  cursor: pointer;
  transform-style: preserve-3d;
  transition: transform 500ms var(--enter);
}

.tape__card.is-over { transform: rotateY(180deg); }
.tape__card:focus-visible,
.tape__flip:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

.tape__face {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 9% 8% 7%;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

/* Side B is already turned away, so the card's own angle is what decides
   which one you are looking at. */
.tape__face--b { transform: rotateY(180deg); }

.tape__label {
  border: 1px solid rgba(20, 17, 15, 0.18);
  background: var(--paper, #F1EFE9);
  overflow: hidden;
}

.tape__band {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding: 5px 8px;
  background: var(--band);
}

.tape__side,
.tape__name {
  font-family: var(--mono);
  font-size: clamp(8px, 2.4cqw, 10px);
  font-weight: 700;
  letter-spacing: 0.12em;
  line-height: 1;
  white-space: nowrap;
  color: #F7F5F0;
}

.tape__note {
  margin: 0;
  padding: 7px 8px 9px;
  font-family: var(--mono);
  font-size: clamp(7.5px, 2.2cqw, 9px);
  letter-spacing: 0.1em;
  line-height: 1.3;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--ink);
}

.tape__reels {
  display: flex;
  justify-content: space-around;
  padding: 0 14%;
}

.tape__reel {
  width: 22%;
  aspect-ratio: 1;
  border: 3px solid #8E8A82;
  border-radius: 50%;
  background:
    conic-gradient(from 0deg, #4A4640 0 12%, #2A2622 12% 25%,
                   #4A4640 25% 37%, #2A2622 37% 50%,
                   #4A4640 50% 62%, #2A2622 62% 75%,
                   #4A4640 75% 87%, #2A2622 87% 100%);
}

.tape__card.is-spinning .tape__reel { animation: tape-spin 500ms linear; }

@keyframes tape-spin { to { transform: rotate(360deg); } }

.tape__flip {
  display: inline-flex;
  align-items: center;
  padding: 8px 12px;
  border: 2px solid var(--accent);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  white-space: nowrap;
}

.tape__flip:hover { background: var(--accent); color: #F7F5F0; }

/* The tape and its FLIP button are one row. The work underneath starts
   a clear distance below them rather than against them. */
.tape__body {
  margin-top: 40px;
  transition: opacity 250ms var(--enter);
}

.tape__body > :first-child { margin-top: 0; }
.tape__body.is-out { opacity: 0; }

/* -- Four floors --------------------------------------------------------
   The indicator above a lift door. It stays at the top of the body while
   the body scrolls, so the floor you are on is never in doubt. */

.lift { margin: 0; }

.lift__bar {
  position: sticky;
  top: 0;
  z-index: 4;
  display: flex;
  align-items: stretch;
  gap: 10px;
  margin: 0 0 18px;
  padding: 8px 10px;
  border: 2px solid var(--ink);
  border-radius: 12px;
  /* Paper, not ink. The bar used to set small grey type on a dark ground
     and ask people to squint at it. */
  background: #F7F4EC;
}

.lift__read {
  display: grid;
  place-items: center;
  flex: none;
  min-width: 56px;
  padding: 0 12px;
  border-radius: 7px;
  background: var(--ink);
}

.lift__digit {
  font-family: var(--mono);
  font-size: 28px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.04em;
  color: #FFFFFF;
}

.lift__buttons {
  display: flex;
  align-items: stretch;
  gap: 6px;
  /* Sized from the space it has, so it never needs a scroll bar. */
  flex: 1 1 auto;
  min-width: 0;
}

.lift__btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  flex: 1 1 0;
  min-width: 44px;
  min-height: 44px;
  padding: 6px 4px;
  border: 2px solid var(--ink);
  border-radius: 8px;
  background: #FFFFFF;
  cursor: pointer;
}

.lift__num {
  font-family: var(--mono);
  font-size: 22px;
  font-weight: 700;
  line-height: 1;
  color: var(--ink);
}

.lift__name {
  max-width: 100%;
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 1px;
  line-height: 1.1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--ink);
}

.lift__btn:hover { border-color: #1F5FA8; }

/* The floor you are on is filled, a size larger, and the only one in colour. */
.lift__btn.is-on {
  flex-grow: 1.9;
  border-color: #1F5FA8;
  background: #1F5FA8;
}

.lift__btn.is-on .lift__num { font-size: 28px; color: #FFFFFF; }
.lift__btn.is-on .lift__name { font-size: 14px; font-weight: 700; color: #FFFFFF; }
.lift__btn:focus-visible { outline: 3px solid #1F5FA8; outline-offset: 3px; }

.lift__car { position: relative; min-width: 0; overflow: hidden; }

.lift__doors {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
}

.lift__door {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 50.5%;
  background: #14110F;
  transition: transform 175ms var(--enter);
}

.lift__door--l { left: 0; transform: translateX(-101%); }
.lift__door--r { right: 0; transform: translateX(101%); }
.lift__doors.is-shut .lift__door--l,
.lift__doors.is-shut .lift__door--r { transform: translateX(0); }

@media (max-width: 560px) {
  /* Too narrow for four names. The floor you are on keeps its, the rest
     are numbers, which is all a lift ever shows anyway. */
  .lift__btn:not(.is-on) .lift__name { display: none; }
  .lift__btn.is-on { flex-grow: 2.4; }
  .lift__btn.is-on .lift__name { font-size: 11px; }
  .lift__read { min-width: 46px; padding: 0 8px; }
  .lift__digit { font-size: 22px; }
}

/* -- Two cans ----------------------------------------------------------- */

.cans { margin: 26px 0 0; }

.cans__rack {
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
  margin-bottom: 22px;
}

.cans__can {
  flex: 1 1 160px;
  max-width: 230px;
  min-width: 0;
  padding: 0 0 10px;
  border: 0;
  background: transparent;
  cursor: pointer;
}

.cans__lid {
  display: grid;
  place-items: center;
  width: 100%;
  aspect-ratio: 1;
  border: 3px solid var(--ink);
  border-radius: 50%;
  background:
    repeating-radial-gradient(circle at 50% 50%,
      rgba(20, 17, 15, 0.06) 0 6px, transparent 6px 13px),
    var(--paper, #F1EFE9);
  transition: transform 500ms var(--enter), box-shadow var(--t-micro) var(--micro);
}

.cans__hub {
  width: 26%;
  aspect-ratio: 1;
  border: 3px solid var(--ink);
  border-radius: 50%;
  background: var(--paper, #F1EFE9);
}

.cans__can.is-on .cans__lid {
  border-color: var(--accent);
  box-shadow: 0 5px 0 rgba(20, 17, 15, 0.16);
}

.cans__can.is-spinning .cans__lid { transform: rotate(360deg) translateY(-4px); }
.cans__can:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }

.cans__strip {
  display: block;
  margin-top: 10px;
  padding: 6px 8px;
  border: 1px solid var(--ink-faint);
  background: var(--paper, #F1EFE9);
}

.cans__n,
.cans__name,
.cans__note {
  display: block;
  font-family: var(--mono);
  letter-spacing: 0.11em;
  line-height: 1.3;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cans__n { font-size: 8px; font-weight: 700; color: var(--accent); }
.cans__name { font-size: 10px; font-weight: 700; color: var(--ink); }
.cans__note { font-size: 8px; color: var(--ink-soft); }

.cans__body { transition: opacity 250ms var(--enter); }
.cans__body.is-out { opacity: 0; }

.cans__card {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin: 22px 0;
  padding: 14px 16px;
  border: 2px dashed var(--ink-faint);
}

.cans__cardline {
  flex: 1 1 200px;
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink);
}

.cans__go {
  padding: 8px 12px;
  border: 2px solid var(--accent);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  white-space: nowrap;
}

.cans__go:hover { background: var(--accent); color: #F7F5F0; }
.cans__go:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

/* -- The platform, clicked through -------------------------------------- */

.thru { margin: 30px 0 0; }
.thru:focus-visible { outline: 2px solid var(--accent); outline-offset: 6px; }
.thru__lead { margin: 0 0 14px; }

.thru__frame {
  position: relative;
  border: 3px solid var(--ink);
  background: var(--paper, #F1EFE9);
}

.thru__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 10px;
  background: var(--ink);
}

.thru__label {
  font-size: 9px;
  letter-spacing: 0.12em;
  white-space: nowrap;
  color: #F1EFE9;
}

.thru__tag {
  flex: none;
  padding: 3px 7px;
  /* The tag keeps its own colour exactly. On an ink bar that colour is
     too close to the bar to carry dark type, so the type is set in paper
     instead of the colour being moved. */
  background: var(--accent);
  font-size: 8px;
  letter-spacing: 0.12em;
  white-space: nowrap;
  color: var(--paper);
}

.thru__stage {
  position: relative;
  width: 100%;
  /* The tallest screen decides the room, so changing screen never jumps. */
  padding-top: calc(var(--tall) * 100%);
}

.thru__shot {
  position: absolute;
  inset: 0;
  transition: opacity 180ms var(--enter);
}

.thru__shot.is-out { opacity: 0; pointer-events: none; }

.thru__img {
  display: block;
  width: 100%;
  height: auto;
}

.thru__spots { position: absolute; inset: 0; }

.thru__spot {
  position: absolute;
  padding: 0;
  border: 2px solid transparent;
  border-radius: 4px;
  background: transparent;
  cursor: pointer;
}

.thru__spot:hover,
.thru__spot:focus-visible { border-color: var(--accent); outline: none; }

.thru__spot--hint::after {
  content: '';
  position: absolute;
  inset: -4px;
  border: 2px solid var(--accent);
  border-radius: 6px;
  animation: thru-pulse 1600ms var(--enter) infinite;
}

@keyframes thru-pulse {
  0%, 100% { opacity: 0.25; transform: scale(1); }
  50%      { opacity: 1;    transform: scale(1.06); }
}

.thru__hint {
  position: absolute;
  top: 46px;
  right: -8px;
  margin: 0;
  transform: rotate(-6deg);
  font-family: var(--pen);
  font-size: 19px;
  line-height: 1;
  color: var(--accent);
}

.thru.is-touched .thru__hint,
.thru.is-touched .thru__spot--hint::after { display: none; }

.thru__line {
  margin: 12px 0 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink-soft);
}

/* -- The visitor pass --------------------------------------------------- */

.pass {
  position: relative;
  margin-top: 16px;
  padding: 14px 16px 16px;
  border: 1px solid var(--ink-faint);
  background: var(--paper, #F1EFE9);
  box-shadow: 2px 2px 0 rgba(20, 17, 15, 0.12);
}

.pass__title {
  margin: 0 0 12px;
  font-size: 9.5px;
  letter-spacing: 0.16em;
  color: var(--ink-soft);
}

.pass__slots {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 8px;
}

.pass__slot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
}

.pass__ring {
  position: relative;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 2px dashed var(--ink-faint);
  border-radius: 50%;
}

.pass__slot.is-at .pass__ring { border-style: solid; border-color: var(--ink); }

.pass__stamp {
  width: 34px;
  height: 34px;
  border: 3px solid var(--accent);
  border-radius: 50%;
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  opacity: 0;
  transform: scale(1.4) rotate(var(--tilt, 0deg));
}

.pass__slot.is-stamped .pass__stamp {
  opacity: 1;
  transform: scale(1) rotate(var(--tilt, 0deg));
  animation: pass-land 200ms var(--enter);
}

@keyframes pass-land {
  0%   { opacity: 0; transform: scale(1.4) rotate(var(--tilt, 0deg)); }
  80%  { opacity: 1; transform: scale(1)   rotate(var(--tilt, 0deg)) translateY(2px); }
  100% { opacity: 1; transform: scale(1)   rotate(var(--tilt, 0deg)); }
}

.pass__name {
  font-family: var(--mono);
  font-size: 7.5px;
  letter-spacing: 0.08em;
  line-height: 1.2;
  text-align: center;
  white-space: nowrap;
  color: var(--ink-soft);
}

.pass__slot:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.pass__award {
  margin: 14px auto 0;
  max-width: 320px;
  padding: 14px 18px 16px;
  border: 1px solid #1F3A6B;
  background: #FFFFFF;
  text-align: center;
  opacity: 0;
  transform: translateY(26px);
  transition: opacity 400ms var(--enter), transform 400ms var(--enter);
}

.pass__award.is-up { opacity: 1; transform: translateY(0); }

.pass__level {
  margin: 0;
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.16em;
  line-height: 1.4;
  text-transform: uppercase;
  color: #1F3A6B;
}

.pass__rule {
  display: block;
  width: 44px;
  height: 2px;
  margin: 8px auto;
  background: #B4453C;
}

.pass__by {
  margin: 0;
  font-family: var(--mono);
  font-size: 8px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #4A4640;
}

@media (max-width: 560px) {
  .pass__slots { grid-template-columns: repeat(5, minmax(44px, 1fr)); gap: 5px; }
  .pass__name { font-size: 6.5px; letter-spacing: 0.04em; }
}

/* -- Four films, one folder ---------------------------------------------
   The tabs share the width between them rather than running off the side,
   so all four are readable without a scroll bar at any desk width. */

.films { margin: 30px 0 0; }

.films__title {
  margin: 0 0 6px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink);
}

.films__line { margin: 0 0 16px; }

.films__tabs {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 4px;
}

.films__tab {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  min-height: 44px;
  padding: 8px 6px;
  border: 2px solid var(--ink-faint);
  border-bottom: 0;
  border-radius: 6px 6px 0 0;
  background: var(--paper, #F1EFE9);
  cursor: pointer;
  color: var(--ink-soft);
}

.films__tabtext {
  /* The longest label decides the size, and it still sits on one line. */
  font-size: clamp(6.5px, 0.78vw, 9px);
  letter-spacing: 0.06em;
  line-height: 1.2;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

.films__tab.is-on { border-color: var(--ink); background: var(--ink); color: #F1EFE9; }
.films__tab:hover:not(.is-on) { border-color: var(--ink); color: var(--ink); }
.films__tab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

@media (max-width: 560px) {
  .films__tabs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .films__tab { border-bottom: 2px solid var(--ink-faint); border-radius: 6px; }
  .films__tab.is-on { border-color: var(--ink); }
  .films__tabtext { font-size: 8px; }
}

.films__swap { transition: opacity 250ms var(--enter); }
.films__swap.is-out { opacity: 0; }

/* ---- what is in this folder */

.films__count {
  margin: 16px 0 8px;
  font-size: 9px;
  letter-spacing: 0.16em;
  color: var(--ink-soft);
}

.films__index {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin: 0 0 14px;
}

.films__card {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 1 auto;
  min-height: 44px;
  padding: 6px 10px 6px 6px;
  border: 1px solid var(--ink-faint);
  background: var(--paper, #F1EFE9);
  cursor: pointer;
}

.films__thumb {
  flex: none;
  width: 30px;
  height: 38px;
  object-fit: cover;
  object-position: top center;
  border: 1px solid var(--ink-faint);
  background: #FFFFFF;
}

.films__cardline { display: flex; flex-direction: column; gap: 2px; min-width: 0; }

.films__cardnum {
  font-family: var(--mono);
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.1em;
  line-height: 1;
  color: var(--accent);
}

.films__cardname {
  font-family: var(--mono);
  font-size: 8.5px;
  letter-spacing: 0.08em;
  line-height: 1.1;
  white-space: nowrap;
  color: var(--ink);
}

.films__card.is-on { border-color: var(--ink); background: var(--ink); }
.films__card.is-on .films__cardname { color: #F1EFE9; }
.films__card.is-on .films__cardnum { color: #F1EFE9; }
.films__card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---- the film and its words */

.films__stage { margin: 18px 0 0; }

.films__name {
  margin: 0 0 4px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink);
}

.films__credit { margin: 0 0 10px; }
.films__body { margin: 0 0 10px; }

/* -- The paperwork ------------------------------------------------------
   The sheet turns around its top edge, under the clip, and the pages it
   has not reached yet show their edges behind it. */

.board { position: relative; }

.board__board,
.board { }

.board {
  position: relative;
  padding: 26px 14px 16px;
  border: 3px solid var(--ink);
  background: #CFC9BC;
}

.board__clip {
  position: absolute;
  top: -9px;
  left: 50%;
  z-index: 3;
  width: 92px;
  height: 22px;
  transform: translateX(-50%);
  border: 3px solid var(--ink);
  border-radius: 4px;
  background: #8E8A82;
}

/* One edge per page still underneath, each a little down and to the right
   of the one above it. */
.board__under { position: absolute; inset: 26px 14px 16px; pointer-events: none; }

.board__edge {
  position: absolute;
  inset: 0;
  transform: translate(calc(var(--i) * 4px), calc(var(--i) * 4px));
  border: 1px solid rgba(20, 17, 15, 0.22);
  background: var(--paper, #F1EFE9);
  box-shadow: 1px 1px 0 rgba(20, 17, 15, 0.1);
}

.board__well {
  position: relative;
  z-index: 1;
  perspective: 1400px;
  overflow: hidden;
  transition: height 260ms var(--enter);
}

.board__sheet {
  position: relative;
  transform-origin: top center;
  transition: transform 450ms var(--enter), opacity 260ms var(--enter);
}

.board__sheet.is-turning { transform: rotateX(90deg); }
.board__sheet.is-in { transform: translateY(-14px); opacity: 0; }

.board__img {
  display: block;
  width: 100%;
  height: auto;
  background: var(--paper, #F1EFE9);
  box-shadow: 1px 2px 0 rgba(20, 17, 15, 0.2);
}

/* The turned up corner, big enough to be a target and named for where it
   goes rather than for what it is. */
.board__corner {
  position: absolute;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 10px 12px 10px 22px;
  border: 0;
  background: var(--ink);
  color: #F1EFE9;
  cursor: pointer;
  white-space: nowrap;
  clip-path: polygon(16px 0, 100% 0, 100% 100%, 0 100%);
  transform-origin: bottom right;
  transition: transform 300ms var(--enter), background var(--t-micro) var(--micro);
}

.board__cornertext { font-size: 8.5px; letter-spacing: 0.12em; }

.board__arrow {
  width: 0;
  height: 0;
  flex: none;
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
  border-left: 8px solid #F1EFE9;
}

.board__corner:hover { background: var(--accent); }
.board__corner:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* It lifts once, the first time the board is seen. */
@keyframes board-peel {
  0%   { transform: none; }
  45%  { transform: translateY(-6px) rotate(-1.4deg); }
  100% { transform: none; }
}

.board__corner.is-peeling { animation: board-peel 600ms var(--enter); }

@media (prefers-reduced-motion: reduce) {
  .tape__card,
  .tape__body,
  .lift__door,
  .cans__lid,
  .cans__body,
  .thru__shot,
  .pass__stamp,
  .pass__award,
  .board__well,
  .board__sheet,
  .board__corner,
  .films__swap { transition: none; }
  .board__corner.is-peeling { animation: none; }
  .tape__card.is-over { transform: rotateY(180deg); }
  .cans__can.is-spinning .cans__lid { transform: none; }
  .tape__card.is-spinning .tape__reel,
  .pass__slot.is-stamped .pass__stamp,
  .thru__spot--hint::after { animation: none; }
  .board__sheet.is-turning,
  .board__sheet.is-in { transform: none; opacity: 1; }
}

/* -- Press the button ---------------------------------------------------
   A dark stage with a soft light in the middle of it, the way every one of
   these films opens. */

.stage { margin: 26px 0 0; }

.stage__frame {
  border: 3px solid var(--ink);
  background: var(--paper, #F1EFE9);
}

.stage__floor {
  position: relative;
  display: grid;
  place-items: center;
  padding: 44px 26px;
  min-height: 300px;
  background:
    radial-gradient(60% 70% at 50% 46%, #3A3630 0%, #14110F 62%, #0B0A09 100%);
  overflow: hidden;
}

.stage__floor:focus-visible { outline: 3px solid var(--accent); outline-offset: -5px; }

/* The film that plays quietly behind the buttons. */
.stage__peek {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 300ms var(--enter);
}

.stage__floor.is-peeking .stage__peek { opacity: 0.45; }
.stage__floor.is-showing .stage__peek { opacity: 0; }

.stage__pills {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px 18px;
  width: 100%;
  max-width: 560px;
  transition: opacity 300ms var(--enter);
}

.stage__floor.is-showing .stage__pills { opacity: 0; pointer-events: none; }

/* A moulded pill: a light rim, a dark core, and a gloss on the top half. */
.stage__pill {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-height: 62px;
  padding: 12px 14px;
  border: 0;
  border-radius: 999px;
  background:
    linear-gradient(#2A2622, #1A1714) padding-box,
    linear-gradient(#C9C5BE, #6E6A64) border-box;
  border: 2px solid transparent;
  box-shadow: 0 6px 14px rgba(0, 0, 0, 0.45);
  cursor: pointer;
  overflow: hidden;
  transition: transform 140ms var(--micro), box-shadow 140ms var(--micro),
              opacity 300ms var(--enter);
}

.stage__gloss {
  position: absolute;
  left: 6%;
  right: 6%;
  top: 4px;
  height: 42%;
  border-radius: 999px;
  background: linear-gradient(rgba(255, 255, 255, 0.26), rgba(255, 255, 255, 0));
  pointer-events: none;
}

.stage__label {
  position: relative;
  font-family: var(--mono);
  /* The longest of the four decides the size, so none of them wraps. */
  font-size: clamp(8px, 1.5cqw, 11px);
  font-weight: 700;
  letter-spacing: 0.08em;
  line-height: 1.1;
  text-align: center;
  white-space: nowrap;
  color: #FFFFFF;
}

.stage__sub {
  position: relative;
  font-family: var(--mono);
  font-size: 7.5px;
  letter-spacing: 0.16em;
  line-height: 1;
  white-space: nowrap;
  color: #8E8A82;
}

.stage__pill:hover,
.stage__pill:focus-visible {
  transform: translateY(-2px);
  background:
    linear-gradient(#332F2A, #201C19) padding-box,
    linear-gradient(#F1EFE9, #9A968F) border-box;
  outline: none;
}

.stage__pill:focus-visible { box-shadow: 0 0 0 3px var(--accent), 0 6px 14px rgba(0, 0, 0, 0.45); }
.stage__pill.is-gone { opacity: 0; pointer-events: none; }

/* Pressed: it sinks, and a ring goes out from where it was pressed. */
.stage__pill.is-pressed { transform: translateY(3px); }

.stage__pill.is-pressed::after {
  content: '';
  position: absolute;
  left: var(--px, 50%);
  top: var(--py, 50%);
  width: 10px;
  height: 10px;
  margin: -5px 0 0 -5px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.85);
  animation: stage-ring 300ms var(--enter) forwards;
}

@keyframes stage-ring {
  from { transform: scale(1); opacity: 1; }
  to   { transform: scale(26); opacity: 0; }
}

/* The cursor that never presses anything. */
.stage__cursor {
  position: absolute;
  z-index: 3;
  width: 20px;
  height: 24px;
  pointer-events: none;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.5));
  animation: stage-drift 8000ms var(--enter) infinite;
}

@keyframes stage-drift {
  0%   { left: 26%; top: 34%; }
  25%  { left: 70%; top: 36%; }
  50%  { left: 72%; top: 70%; }
  75%  { left: 28%; top: 68%; }
  100% { left: 26%; top: 34%; }
}

.stage__floor.is-showing .stage__cursor,
.stage__floor.is-peeking .stage__cursor { opacity: 0; }

.stage__film {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: 100%;
  background: #000000;
}

.stage__back {
  position: absolute;
  z-index: 4;
  left: 10px;
  top: 10px;
  padding: 8px 11px;
  border: 1px solid #5A5852;
  background: rgba(11, 10, 9, 0.84);
  color: #F1EFE9;
  cursor: pointer;
  white-space: nowrap;
  font-size: 8.5px;
  letter-spacing: 0.12em;
}

.stage__back:hover { background: var(--accent); border-color: var(--accent); }
.stage__back:focus-visible { outline: 2px solid #F1EFE9; outline-offset: 2px; }

@media (max-width: 560px) {
  .stage__pills { grid-template-columns: minmax(0, 1fr); }
  .stage__floor { padding: 28px 16px; }
  .stage__label { font-size: 9px; }
}

/* -- The film card ------------------------------------------------------ */

.card { margin: 18px 0 0; transition: opacity 200ms var(--enter); }
.card.is-out { opacity: 0; }

.card__head { margin: 0 0 12px; }

.card__name {
  margin: 0;
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink);
}

.card__rule {
  display: block;
  width: 46px;
  height: 3px;
  margin: 7px 0 9px;
  background: var(--accent);
}

.card__meta { display: flex; align-items: center; gap: 10px; margin: 0; }

.card__chip {
  padding: 3px 8px;
  background: var(--ink);
  font-family: var(--mono);
  font-size: 8px;
  letter-spacing: 0.14em;
  white-space: nowrap;
  color: var(--paper, #F1EFE9);
}

.card__run {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  color: var(--ink-soft);
}

/* -- Who sat where ------------------------------------------------------ */

.seats { margin: 0 0 18px; }

.seats__title {
  /* The heading sat on the column labels. It keeps its own line now. */
  margin: 0 0 8px;
  padding-bottom: 8px;
  font-size: 9.5px;
  letter-spacing: 0.16em;
  color: var(--ink-soft);
}

.seats__scroll { overflow-x: auto; scrollbar-width: thin; }

.seats__grid {
  display: grid;
  grid-template-columns: minmax(112px, max-content) repeat(var(--cols), minmax(42px, 1fr));
  gap: 4px 6px;
  min-width: 100%;
}

.seats__row { display: contents; }

.seats__col {
  font-family: var(--mono);
  font-size: 7.5px;
  letter-spacing: 0.06em;
  line-height: 1.2;
  text-align: center;
  color: var(--ink-soft);
}

.seats__role {
  font-family: var(--mono);
  font-size: 8.5px;
  letter-spacing: 0.08em;
  line-height: 1.3;
  white-space: nowrap;
  align-self: center;
  color: var(--ink);
}

.seats__cell {
  justify-self: center;
  width: 18px;
  height: 18px;
  border: 1.5px solid var(--ink-faint);
  background: transparent;
}

.seats__cell.is-on { border-color: var(--mark, var(--accent)); background: var(--mark, var(--accent)); }

.seats__legend {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 9px 0 0;
  font-family: var(--mono);
  font-size: 8px;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
}

.seats__key {
  width: 11px;
  height: 11px;
  background: var(--mark, var(--accent));
}

/* -- Change here for ---------------------------------------------------- */

.change {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  margin: 18px 0 0;
  padding: 13px 15px;
  border: 2px solid var(--ink);
  background: var(--paper, #F1EFE9);
  cursor: pointer;
  text-align: left;
}

.change__mark {
  flex: none;
  width: 15px;
  height: 15px;
  border: 3px solid var(--ink);
  border-radius: 50%;
  background: var(--paper, #F1EFE9);
}

.change__line {
  min-width: 0;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  line-height: 1.45;
  color: var(--ink);
}

.change:hover { background: var(--ink); }
.change:hover .change__line { color: var(--paper, #F1EFE9); }
.change:hover .change__mark { border-color: var(--accent); background: var(--accent); }
.change:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

@media (prefers-reduced-motion: reduce) {
  .stage__peek,
  .stage__pills,
  .stage__pill,
  .card { transition: none; }
  .stage__cursor { display: none; }
  .stage__pill.is-pressed::after { animation: none; display: none; }
}

/* -- The network --------------------------------------------------------
   One circle line, seven stops, a hub in the middle that every spoke runs
   to. The map draws itself when the work opens and is finished inside a
   second and a half. */

.net { margin: 26px 0 0; }

.net__frame {
  border: 3px solid var(--ink);
  background: var(--paper, #F1EFE9);
}

.net__stage { position: relative; }
.net__svg { display: block; width: 100%; height: auto; }

.net__loopline { fill: none; stroke-width: 16; }

/* Every piece is briefed in the middle and signed off there. */
.net__spoke {
  stroke: #C9C3B6;
  stroke-width: 3;
  stroke-dasharray: 10 10;
  opacity: 0;
  transition: opacity 320ms var(--enter);
}

.net.is-spoked .net__spoke,
.net.is-drawn .net__spoke { opacity: 1; }

/* ---- the stops */

.net__stop { cursor: pointer; opacity: 0; }
.net__stop.is-in,
.net.is-drawn .net__stop { opacity: 1; }
.net__stop:focus-visible,
.net__hub:focus-visible { outline: none; }

.net__ring {
  fill: #FFFFFF;
  stroke-width: 9;
  transform-box: fill-box;
  transform-origin: center;
  transition: transform 160ms var(--micro);
}

.net__stop.is-in .net__ring { animation: net-pop 200ms var(--enter); }

@keyframes net-pop {
  from { transform: scale(0); }
  to   { transform: scale(1); }
}

.net__num {
  font-family: var(--mono);
  font-size: 26px;
  font-weight: 700;
  fill: var(--ink);
  pointer-events: none;
}

.net__pill { transition: filter 160ms var(--micro); }

.net__pilltext {
  font-family: var(--mono);
  font-size: 19px;
  font-weight: 700;
  letter-spacing: 0.06em;
  fill: #FFFFFF;
  pointer-events: none;
}

.net__count {
  font-family: var(--mono);
  font-size: 17px;
  letter-spacing: 0.04em;
  fill: #6E6A64;
  pointer-events: none;
}

.net__stop:hover .net__ring,
.net__stop:focus-visible .net__ring { transform: scale(1.12); }
.net__stop:hover .net__pill,
.net__stop:focus-visible .net__pill { filter: brightness(0.86); }
.net__stop:focus-visible .net__ring { stroke-dasharray: 4 5; }

/* The stop whose panel is open keeps a ring going out from it. */
@keyframes net-pulse {
  0%   { stroke-width: 9; opacity: 1; }
  70%  { stroke-width: 22; opacity: 0.1; }
  100% { stroke-width: 22; opacity: 0.1; }
}

.net__stop.is-at .net__ring { animation: net-pulse 1500ms var(--enter) infinite; }

/* One blink each, in platform order, to say they can be pressed. */
@keyframes net-wave {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.22); }
}

.net__stop.is-waving .net__ring { animation: net-wave 420ms var(--enter); }

/* ---- the hub */

.net__hubbody { fill: #FFFFFF; stroke: var(--ink); stroke-width: 8; }

.net__hubtext {
  font-family: var(--mono);
  font-size: 28px;
  font-weight: 700;
  letter-spacing: 0.05em;
  fill: var(--ink);
  pointer-events: none;
}

.net__hub { cursor: pointer; }
.net__hub:hover .net__hubbody,
.net__hub:focus-visible .net__hubbody { stroke: #2E2A8E; }

.net__here { transition: transform 300ms var(--enter); }

.net__heretext {
  font-family: var(--mono);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: 0.1em;
  fill: #FFFFFF;
}

/* ---- the hand that says the map is a thing you press */

.net__note {
  position: absolute;
  left: 3%;
  top: 6%;
  display: flex;
  align-items: flex-start;
  gap: 2px;
  pointer-events: none;
}

.net__notetext {
  max-width: 150px;
  margin: 0;
  transform: rotate(-4deg);
  font-family: var(--pen);
  font-size: 21px;
  line-height: 1.15;
  color: var(--ink);
}

.net__arrow { width: 54px; height: 36px; margin-top: 4px; }
.net__arrowline { fill: none; stroke: var(--ink); stroke-width: 2.2; }
.net__arrowhead { fill: var(--ink); }

.net.is-touched .net__note { display: none; }

/* -- The departures board ----------------------------------------------
   The same seven stops in words, for anyone who would rather read a list
   than a picture. The characters turn in like a split flap sign. */

.dep {
  margin: 14px 0 0;
  padding: 10px;
  border-radius: 8px;
  background: var(--ink);
}

.dep__row {
  display: grid;
  grid-template-columns: auto 16px minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 44px;
  padding: 7px 9px;
  border: 0;
  border-bottom: 1px solid #3A3630;
  background: transparent;
  cursor: pointer;
  text-align: left;
}

/* A phone cannot hold platform, dot, name, count and GO on one line
   without the name running into the GO. The count goes, because the map
   above already prints it against the stop. */
@media (max-width: 560px) {
  .dep__row {
    grid-template-columns: auto 14px minmax(0, 1fr) auto;
    gap: 8px;
    padding: 7px 7px;
  }

  .dep__count { display: none; }

  /* The longest names still do not fit on one line beside PLATFORM and GO
     at 360. A split flap board is a row of separate characters, so it can
     turn the corner on to a second line without anything being cut: every
     character stays its own size and stays readable. */
  .dep__name { flex-wrap: wrap; }
}

.dep__row:last-child { border-bottom: 0; }
.dep__row:hover { background: #221E1A; }
.dep__row:focus-visible { outline: 2px solid #F1EFE9; outline-offset: -3px; }
.dep__row.is-at { background: var(--line); }

.dep__dot {
  width: 14px;
  height: 14px;
  background: var(--line);
}

.dep__row.is-at .dep__dot { background: #FFFFFF; }

.dep__flaps { display: flex; gap: 1px; }

/* A word is a run of cells that stays together. The gap inside it is the
   same one pixel as between any other two cells, so nothing moves. */
.dep__word { display: inline-flex; gap: 1px; }

.dep__flap {
  display: inline-block;
  padding: 2px 1px;
  border-right: 1px solid rgba(20, 17, 15, 0.55);
  background: #1E1A17;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  line-height: 1.3;
  white-space: pre;
  color: #F1EFE9;
}

.dep__row.is-at .dep__flap { background: rgba(20, 17, 15, 0.42); color: #FFFFFF; }
.dep__plat .dep__flap { color: #B9B5AB; }
.dep__count .dep__flap { color: #B9B5AB; }
.dep__go .dep__flap { color: #F1EFE9; }
.dep__row.is-at .dep__plat .dep__flap,
.dep__row.is-at .dep__count .dep__flap { color: #F1EFE9; }

/* The characters turn in one at a time when the board is first shown.
   Readable is the resting state and the flip is the way in, not the other
   way round: a sign whose text only appears if an animation runs is a sign
   that says nothing on a machine that will not run it. */
.dep__flap { transform-origin: center top; }
.dep__row.is-in .dep__flap { animation: dep-flip 300ms var(--enter) backwards; }

@keyframes dep-flip {
  from { transform: rotateX(90deg); }
  to   { transform: rotateX(0deg); }
}

.dep__flap:nth-child(1)  { animation-delay: 0ms; }
.dep__flap:nth-child(2)  { animation-delay: 14ms; }
.dep__flap:nth-child(3)  { animation-delay: 28ms; }
.dep__flap:nth-child(4)  { animation-delay: 42ms; }
.dep__flap:nth-child(5)  { animation-delay: 56ms; }
.dep__flap:nth-child(6)  { animation-delay: 70ms; }
.dep__flap:nth-child(7)  { animation-delay: 84ms; }
.dep__flap:nth-child(8)  { animation-delay: 98ms; }
.dep__flap:nth-child(n+9) { animation-delay: 112ms; }

@media (max-width: 560px) {
  .dep__row { grid-template-columns: auto 12px minmax(0, 1fr) auto; gap: 8px; }
  .dep__count { display: none; }
  .dep__flap { font-size: 10px; }
}

/* -- The panel ---------------------------------------------------------- */

.net__panel { margin: 20px 0 0; transition: opacity 200ms var(--enter); }
.net__panel.is-out { opacity: 0; }

.net__cardhead {
  margin: 0 0 10px;
  font-size: 9.5px;
  letter-spacing: 0.16em;
  color: var(--ink-soft);
}

.net__seats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 10px;
  margin: 0 0 20px;
}

.net__seat {
  padding: 12px 13px;
  border: 1px solid var(--ink);
  background: var(--paper, #F1EFE9);
}

.net__seat--lead { background: var(--ink); border-color: var(--ink); }

.net__role { margin: 0 0 5px; font-size: 9px; letter-spacing: 0.14em; color: var(--ink-soft); }
.net__seat--lead .net__role { color: #B9B5AB; }

.net__who {
  margin: 0 0 6px;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--ink);
}

.net__owns, .net__joined, .net__seatnote {
  margin: 0 0 4px;
  font-size: 11px;
  line-height: 1.45;
  color: var(--ink-soft);
}

.net__joined { font-family: var(--mono); font-size: 9px; letter-spacing: 0.08em; }
.net__seat--lead .net__who { color: #F1EFE9; }
.net__seat--lead .net__owns,
.net__seat--lead .net__joined,
.net__seat--lead .net__seatnote { color: #B9B5AB; }

.net__built { margin: 0 0 22px; }

.net__figure { margin: 0 0 20px; }
.net__figure img { display: block; width: 100%; height: auto; }

.net__stophead {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
  margin: 0 0 10px;
}

.net__stopname {
  margin: 0;
  font-family: var(--mono);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink);
}

.net__stoprule { display: block; width: 52px; height: 3px; margin-top: 7px; }

.net__stopcount {
  flex: none;
  font-size: 10px;
  letter-spacing: 0.12em;
  white-space: nowrap;
  color: var(--ink-soft);
}

.net__stopnote { margin: 0 0 18px; }
.net__media { margin: 0 0 18px; }

.net__shot {
  display: block;
  width: 100%;
  height: auto;
  margin: 0 0 10px;
  border: 1px solid var(--ink-faint);
}

.net__run { margin: 0 0 14px; }
.net__runbar { display: flex; align-items: center; gap: 12px; margin: 8px 0 0; }

.net__runbtn {
  min-height: 36px;
  padding: 7px 10px;
  border: 1px solid var(--ink-faint);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
}

.net__runbtn:hover { border-color: var(--ink); }
.net__runbtn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.net__runcount {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  color: var(--ink-soft);
}

.net__loops {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px;
}

.net__loop { margin: 0; }
.net__loop video { display: block; width: 100%; height: auto; background: #14110F; }

@media (max-width: 560px) {
  .net__loops { grid-template-columns: minmax(0, 1fr); }
}

/* -- The lanyards -------------------------------------------------------
   Six event passes on a rail. They hang at the angle a pass hangs at. */

.lan { margin: 0 0 18px; container-type: inline-size; }

.lan__rail {
  display: flex;
  gap: 12px;
  padding: 0 8px 18px;
  border-top: 4px solid var(--ink);
  /* A pass that swings forward must not swing out of the panel. The clip
     is on the sideways axis only, so the shadow under the cards is kept. */
  overflow-x: clip;
  overflow-y: visible;
}

.lan__pass {
  position: relative;
  /* The rail minus its gaps, divided by the number of passes. */
  flex: 0 0 calc((100% - (var(--n, 6) - 1) * 12px) / var(--n, 6));
  min-width: 0;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  transform: rotate(var(--tilt, 0deg));
  transform-origin: top center;
  transition: transform 500ms var(--enter), opacity 300ms var(--enter);
}

.lan__strap {
  display: block;
  width: 12px;
  height: 26px;
  margin: 0 auto;
  background: var(--line);
}

.lan__clip {
  display: block;
  width: 20px;
  height: 8px;
  margin: 0 auto 2px;
  border: 2px solid #8E8A82;
  border-radius: 3px;
  background: #CFC9BC;
}

.lan__card {
  position: relative;
  display: block;
  padding: 0 0 8px;
  border: 1px solid var(--ink-faint);
  background: #FFFFFF;
  box-shadow: 2px 3px 0 rgba(20, 17, 15, 0.16);
  overflow: hidden;
}

.lan__band { display: block; height: 12px; background: var(--line); }

.lan__city {
  display: block;
  margin: 8px 6px 2px;
  font-family: var(--mono);
  /* Shrinks with the pass, but never under eleven. */
  font-size: clamp(11px, 2.6cqw, 13px);
  font-weight: 700;
  letter-spacing: 0.06em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--ink);
}

.lan__name, .lan__date {
  display: block;
  margin: 0 6px;
  font-family: var(--mono);
  font-size: 8px;
  letter-spacing: 0.06em;
  line-height: 1.4;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--ink-soft);
}

.lan__code { display: flex; gap: 1px; margin: 8px 6px 0; height: 16px; }
.lan__code i { width: var(--w, 1px); background: var(--ink); }

.lan__next {
  position: absolute;
  right: 4px;
  top: 16px;
  padding: 2px 5px;
  background: var(--ink);
  font-family: var(--mono);
  font-size: 7px;
  letter-spacing: 0.12em;
  color: #FFFFFF;
}

.lan__pass:hover { transform: rotate(calc(var(--tilt, 0deg) + 2deg)) translateY(2px); }
.lan__pass:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

/* The chosen pass swings forward; the rest stand back. */
.lan__pass.is-on {
  /* Anchored at the clip, so it swings down from the rail rather than
     sideways out of the panel. */
  transform-origin: top center;
  transform: rotate(0deg) translateY(6px) scale(1.06);
  z-index: 2;
}

.lan__pass.is-on .lan__card { box-shadow: 3px 5px 0 rgba(20, 17, 15, 0.26); }
.lan__rail:has(.lan__pass.is-on) .lan__pass:not(.is-on) { opacity: 0.5; }

.lan__body { transition: opacity 200ms var(--enter); }
.lan__body.is-out { opacity: 0; }

.lan__place {
  margin: 0 0 6px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
}

.lan__note { margin: 0 0 14px; }

@media (max-width: 720px) {
  .lan__rail {
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: thin;
  }
  .lan__pass { flex: 0 0 120px; scroll-snap-align: start; }
  .lan__city { font-size: 12px; }
}

/* -- The facts receipt --------------------------------------------------- */

.facts { margin: 14px 0 0; }

.facts__row {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 0 0 7px;
}

.facts__row dt {
  flex: none;
  font-size: 9px;
  letter-spacing: 0.14em;
  color: var(--ink-soft);
}

.facts__row::after {
  content: '';
  order: 1;
  flex: 1 1 auto;
  height: 0;
  margin: 0 2px;
  border-bottom: 1px dotted var(--ink-faint);
}

.facts__row dd {
  order: 2;
  margin: 0;
  font-family: var(--mono);
  font-size: 11px;
  text-align: right;
  color: var(--ink);
}

/* -- The magazine -------------------------------------------------------- */

.mag { margin: 0 0 18px; }
.mag__head { margin: 0 0 10px; font-size: 9.5px; letter-spacing: 0.16em; color: var(--ink-soft); }

.mag__spread {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  /* The spine: a soft shadow falling both ways from the middle. */
  background:
    linear-gradient(90deg, transparent 48%, rgba(20, 17, 15, 0.22) 50%, transparent 52%);
}

.mag__page {
  position: relative;
  cursor: pointer;
  transition: transform 160ms var(--micro);
}

.mag__page img { display: block; width: 100%; height: auto; }
.mag__page.is-on { transform: translateY(-4px); outline: 3px solid var(--ink); z-index: 1; }
.mag__page:focus-visible { outline: 3px solid var(--accent); }

.mag__picks { display: flex; gap: 6px; margin: 12px 0; flex-wrap: wrap; }

.mag__pick {
  min-height: 40px;
  padding: 8px 11px;
  border: 1px solid var(--ink-faint);
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
  white-space: nowrap;
}

.mag__pick.is-on { border-color: var(--ink); background: var(--ink); color: var(--paper, #F1EFE9); }
.mag__pick:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.mag__open { transform-origin: left center; transition: transform 450ms var(--enter); }
.mag__open.is-turning { transform: rotateY(-88deg); }
.mag__full { display: block; width: 100%; height: auto; border: 1px solid var(--ink-faint); }

@media (max-width: 560px) {
  .mag__spread { grid-template-columns: minmax(0, 1fr); background: none; }
  .mag__page:not(.is-on) { display: none; }
}

/* -- The case studies ---------------------------------------------------- */

.docs { margin: 0 0 18px; }
.docs__covers { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }

.docs__cover {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
}

.docs__cover img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--ink-faint);
  box-shadow: 2px 3px 0 rgba(20, 17, 15, 0.14);
  transition: transform 160ms var(--micro);
}

.docs__cover:hover img { transform: translateY(-3px); }
.docs__cover:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.docs__name { font-size: 9px; letter-spacing: 0.12em; color: var(--ink); }

.docs__back {
  min-height: 40px;
  margin: 0 0 10px;
  padding: 8px 11px;
  border: 1px solid var(--ink-faint);
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
}

.docs__back:hover { border-color: var(--ink); color: var(--ink); }
.docs__back:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.docs__title { margin: 0 0 8px; font-size: 9.5px; letter-spacing: 0.16em; color: var(--ink-soft); }

.docs__sheet { perspective: 1600px; }
.docs__sheet:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.docs__page {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--ink-faint);
  transform-origin: left center;
  transition: transform 300ms var(--enter);
}

.docs__sheet.is-curling .docs__page { transform: rotateY(-16deg) translateX(-2%); }
.docs__bar { display: flex; align-items: center; gap: 12px; margin: 10px 0 0; }

@media (max-width: 560px) {
  .docs__covers { grid-template-columns: minmax(0, 1fr); }
}

/* -- The strategy folder -------------------------------------------------- */

.fold { margin: 0 0 18px; }
.fold__tabs { display: flex; gap: 5px; }

.fold__tab {
  min-height: 42px;
  padding: 9px 14px;
  border: 2px solid var(--ink-faint);
  border-bottom: 0;
  border-radius: 8px 8px 0 0;
  background: var(--paper, #F1EFE9);
  color: var(--ink-soft);
  cursor: pointer;
  white-space: nowrap;
}

.fold__tab.is-on { border-color: var(--ink); background: var(--ink); color: #F1EFE9; }
.fold__tab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.fold__sheet { border: 2px solid var(--ink); background: #FFFFFF; }
.fold__img { display: block; width: 100%; height: auto; }

/* -- The website, three stops --------------------------------------------- */

.web3 { margin: 0 0 18px; }

.web3__track {
  position: relative;
  display: flex;
  justify-content: space-between;
  gap: 8px;
  margin: 0 0 16px;
}

/* The little line the three stops sit on. */
.web3__track::before {
  content: '';
  position: absolute;
  left: 10%;
  right: 10%;
  top: 11px;
  height: 6px;
  background: var(--line);
}

.web3__stop {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  flex: 1 1 0;
  min-width: 0;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
}

.web3__dot {
  width: 24px;
  height: 24px;
  border: 5px solid var(--line);
  border-radius: 50%;
  background: #FFFFFF;
  transition: background 160ms var(--micro);
}

.web3__stop.is-on .web3__dot { background: var(--line); }

.web3__name {
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.08em;
  line-height: 1.2;
  text-align: center;
  color: var(--ink-soft);
}

.web3__stop.is-on .web3__name { font-weight: 700; color: var(--ink); }
.web3__stop:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.web3__note { margin: 0 0 12px; }

/* -- Before and after ------------------------------------------------------
   Before on the left, after on the right. The handle uncovers the after
   picture from the right hand edge, so dragging left shows more of the new
   design. Both pictures sit in the same sixteen by nine frame at full
   width, so neither is zoomed. */

.wipe2 { margin: 0 0 16px; }

.wipe2__stage {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--ink-faint);
  aspect-ratio: 16 / 9;
  --at: 50%;
}

.wipe2__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
}

/* The after picture is clipped from the right edge inwards. */
.wipe2__after {
  position: absolute;
  inset: 0;
  left: var(--at);
  overflow: hidden;
}

.wipe2__after .wipe2__img {
  width: auto;
  height: 100%;
  left: auto;
  right: 0;
  aspect-ratio: 16 / 9;
}

.wipe2__chip {
  position: absolute;
  top: 8px;
  z-index: 3;
  padding: 3px 7px;
  background: var(--ink);
  font-family: var(--mono);
  font-size: 8px;
  letter-spacing: 0.12em;
  white-space: nowrap;
  color: var(--paper, #F1EFE9);
}

.wipe2__chip--b { left: 8px; }
.wipe2__chip--a { right: 8px; }

.wipe2__handle {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--at);
  z-index: 4;
  width: 3px;
  margin-left: -1.5px;
  background: var(--ink);
  pointer-events: none;
}

.wipe2__grip {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 34px;
  height: 34px;
  margin: -17px 0 0 -17px;
  border: 3px solid var(--ink);
  border-radius: 50%;
  background: var(--paper, #F1EFE9);
}

/* The slider is the real control, lying over the picture. */
.wipe2__slider {
  position: absolute;
  inset: 0;
  z-index: 5;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: ew-resize;
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
}

.wipe2__slider:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; opacity: 0.001; }

/* -- The academy ---------------------------------------------------------- */

.acad { margin: 0 0 18px; }

.acad__facts {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
  margin: 16px 0 0;
}

.acad__fact {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px 10px;
  border: 1px solid var(--ink-faint);
  background: var(--paper, #F1EFE9);
}

.acad__big {
  font-family: var(--mono);
  font-size: clamp(15px, 3.4cqw, 26px);
  font-weight: 700;
  line-height: 1;
  color: var(--ink);
}

.acad__small { font-size: 8px; letter-spacing: 0.12em; color: var(--ink-soft); }

@media (max-width: 560px) {
  .acad__facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* -- One episode --------------------------------------------------------
   The series itself, in the site's own frame, before any account of how
   it is put together. */

.ep { margin: 0 0 22px; }

.ep__title {
  margin: 0 0 10px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink);
}

.ep__frame {
  border: 3px solid var(--ink);
  background: var(--paper, #F1EFE9);
}

.ep__film {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: #14110F;
}

.ep__line { margin: 10px 0 0; }

/* -- The television -----------------------------------------------------
   A series lives on a screen, so it is shown on one. The cabinet is ink
   and the channel buttons are its dial, but the screen itself is paper:
   the episode is a white product screen and the other two channels are
   pages of small type, and a dark ground with a tint over it hid the one
   thing the set exists to show. */

.tv { margin: 0 0 18px; container-type: inline-size; }

.tv__set {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 140px;
  gap: 14px;
  padding: 14px;
  border-radius: 14px;
  background: #14110F;
  box-shadow: 3px 4px 0 rgba(20, 17, 15, 0.22);
}

.tv__screen {
  position: relative;
  border-radius: 8px;
  /* Paper, so black type on it reads. */
  background: #F7F4EC;
  overflow: hidden;
  aspect-ratio: 16 / 9;
  transition: height 300ms var(--enter);
}

/* Given the room to show a whole page rather than a window on to one. */
.tv__screen.is-tall { aspect-ratio: auto; }

.tv__picture {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: thin;
}

/* A page is shown at the screen's full width and read from the top. It is
   never shrunk to fit: small type scaled down is small type lost. */
.tv__shot {
  display: block;
  width: 100%;
  min-width: 100%;
  height: auto;
}

/* The episode keeps its own shape inside the paper frame. */
.tv__film {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: #F7F4EC;
}

/* Lines across the glass belong to a film. On a page they are noise over
   type, so they are only drawn for channel one, and faintly. */
.tv__scan {
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
  background: repeating-linear-gradient(
    to bottom, rgba(20, 17, 15, 0.05) 0 1px, transparent 1px 3px);
}

.tv__screen.is-film .tv__scan { opacity: 1; }

/* The moment of noise between channels, then nothing. */
.tv__noise {
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
  background-image: radial-gradient(#14110F 0.5px, transparent 0.5px),
    radial-gradient(#14110F 0.5px, transparent 0.5px);
  background-size: 3px 3px, 4px 4px;
  background-position: 0 0, 2px 1px;
}

.tv__screen.is-static .tv__noise { opacity: 0.45; animation: tv-static 150ms steps(5) 1; }

@keyframes tv-static {
  0%   { background-position: 0 0, 2px 1px; }
  25%  { background-position: 2px 3px, 0 2px; }
  50%  { background-position: 1px 1px, 3px 0; }
  75%  { background-position: 3px 2px, 1px 3px; }
  100% { background-position: 0 1px, 2px 2px; }
}

/* Green on paper is not a colour anyone can read, so the number keeps its
   own patch of ink to sit on. */
.tv__num {
  position: absolute;
  right: 8px;
  top: 8px;
  z-index: 2;
  padding: 3px 7px;
  border-radius: 4px;
  background: #14110F;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: #6BE08A;
  pointer-events: none;
}

.tv__tag {
  position: absolute;
  left: 8px;
  top: 8px;
  z-index: 2;
  padding: 3px 7px;
  background: #B5179E;
  font-size: 8px;
  letter-spacing: 0.12em;
  white-space: nowrap;
  color: #FFFFFF;
}

/* Says the page goes on below, until the viewer finds that out.

   A display rule beats the hidden attribute, so anything here that is put
   away with hidden has to say so itself. Without this the hint sat over
   the episode, where there is nothing to scroll. */
.tv__hint[hidden],
.docs__covers[hidden],
.mock__rest[hidden] { display: none; }

.tv__hint {
  position: absolute;
  left: 50%;
  bottom: 8px;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 9px;
  border-radius: 999px;
  transform: translateX(-50%);
  background: #14110F;
  font-family: var(--mono);
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: #F7F4EC;
  pointer-events: none;
}

.tv__hintarrow {
  width: 0;
  height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 6px solid #F7F4EC;
}

.tv__dial { display: flex; flex-direction: column; gap: 10px; justify-content: center; }

.tv__knob {
  display: flex;
  align-items: center;
  gap: 9px;
  min-height: 44px;
  padding: 8px 9px;
  border: 1px solid #5A5852;
  border-radius: 8px;
  background: transparent;
  cursor: pointer;
  text-align: left;
}

.tv__knobdot {
  flex: none;
  width: 20px;
  height: 20px;
  border: 3px solid #B9B5AB;
  border-radius: 50%;
  background: #0B0A09;
}

.tv__knoblabel {
  min-width: 0;
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.05em;
  line-height: 1.25;
  /* Paper on ink, not grey on ink. */
  color: #F1EFE9;
}

.tv__knob.is-on { border-color: #B5179E; background: rgba(181, 23, 158, 0.16); }
.tv__knob.is-on .tv__knobdot { border-color: #B5179E; background: #B5179E; }
.tv__knob.is-on .tv__knoblabel { font-weight: 700; color: #FFFFFF; }
.tv__knob:hover { border-color: #B9B5AB; }
.tv__knob:focus-visible { outline: 2px solid #F1EFE9; outline-offset: 2px; }

.tv__note {
  margin: 12px 0 0;
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.65;
  color: var(--ink-body);
}

.tv__under { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 12px 0 0; }

.tv__film-line {
  margin: 0;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--ink-body);
}

.tv__film-name { font-weight: 700; color: var(--ink); }

.tv__bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.tv__steps { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }

.tv__step,
.tv__go,
.tv__grow {
  min-height: 42px;
  padding: 9px 13px;
  border: 2px solid var(--ink);
  background: var(--paper, #F1EFE9);
  font-size: 13px;
  color: var(--ink);
  cursor: pointer;
  white-space: nowrap;
}

.tv__step span, .tv__go span, .tv__grow span { font-size: 13px; letter-spacing: 0.06em; }

/* The step being shown is the one in colour. */
.tv__step.is-on { background: #B5179E; border-color: #B5179E; color: #FFFFFF; }
.tv__step:hover:not(.is-on),
.tv__go:hover,
.tv__grow:hover { background: var(--paper-hi, #F6F4EF); }
.tv__step:focus-visible,
.tv__go:focus-visible,
.tv__grow:focus-visible { outline: 3px solid #B5179E; outline-offset: 3px; }

.tv__count {
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.08em;
  color: var(--ink);
}

.tv__arrow {
  width: 0;
  height: 0;
  flex: none;
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
  border-left: 7px solid var(--ink);
}

@media (max-width: 720px) {
  .tv__set { grid-template-columns: minmax(0, 1fr); }
  .tv__dial { flex-direction: row; }
  .tv__knob { flex: 1 1 0; flex-direction: column; gap: 5px; text-align: center; }
  .tv__knoblabel { font-size: 8.5px; }
}

@media (prefers-reduced-motion: reduce) {
  .tv__screen { transition: none; }
  .tv__screen.is-static .tv__noise { animation: none; opacity: 0; }
}

/* -- The product films stop ---------------------------------------------
   The same stage as the work itself, at the size of a panel. */

.mini { margin: 0 0 18px; container-type: inline-size; }

.mini__floor {
  padding: 16px;
  border: 3px solid var(--ink);
  background: radial-gradient(60% 70% at 50% 42%, #3A3630 0%, #14110F 62%, #0B0A09 100%);
}

.mini__screen {
  position: relative;
  margin: 0 0 16px;
  aspect-ratio: 16 / 9;
  background: #000000;
  overflow: hidden;
}

.mini__peek {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 300ms var(--enter);
}

.mini__screen.is-live .mini__peek { opacity: 1; }

.mini__pills { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }

.mini__pill {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-height: 54px;
  padding: 10px 12px;
  border: 2px solid transparent;
  border-radius: 999px;
  background:
    linear-gradient(#2A2622, #1A1714) padding-box,
    linear-gradient(#C9C5BE, #6E6A64) border-box;
  box-shadow: 0 5px 12px rgba(0, 0, 0, 0.45);
  cursor: pointer;
  overflow: hidden;
  transition: transform 140ms var(--micro), background 140ms var(--micro);
}

.mini__gloss {
  position: absolute;
  left: 6%;
  right: 6%;
  top: 3px;
  height: 42%;
  border-radius: 999px;
  background: linear-gradient(rgba(255, 255, 255, 0.24), rgba(255, 255, 255, 0));
  pointer-events: none;
}

.mini__label {
  position: relative;
  font-family: var(--mono);
  font-size: clamp(7px, 1.7cqw, 10px);
  font-weight: 700;
  letter-spacing: 0.07em;
  line-height: 1.1;
  text-align: center;
  white-space: nowrap;
  color: #FFFFFF;
}

.mini__sub {
  position: relative;
  font-family: var(--mono);
  font-size: 7px;
  letter-spacing: 0.15em;
  line-height: 1;
  white-space: nowrap;
  color: #8E8A82;
}

.mini__pill:hover,
.mini__pill:focus-visible {
  transform: translateY(-2px);
  background:
    linear-gradient(#332F2A, #201C19) padding-box,
    linear-gradient(#F1EFE9, #9A968F) border-box;
  outline: none;
}

.mini__pill:focus-visible { box-shadow: 0 0 0 3px #6A4C93, 0 5px 12px rgba(0, 0, 0, 0.45); }
.mini__pill.is-pressed { transform: translateY(3px); }

.mini__now {
  margin: 12px 0 0;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  color: var(--ink);
}

.mini__card:empty { display: none; }

@media (max-width: 560px) {
  .mini__pills { grid-template-columns: minmax(0, 1fr); }
}

@media (prefers-reduced-motion: reduce) {
  .mini__peek,
  .mini__pill,
  .tv__knob { transition: none; }
  .tv__screen.is-static .tv__noise { animation: none; opacity: 0; }
}

/* -- The browser frame ---------------------------------------------------- */

.mock { margin: 0 0 8px; }
.mock__chrome { border: 1px solid var(--ink); background: #FFFFFF; }

.mock__top {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 9px;
  background: #E6E3DD;
  border-bottom: 1px solid var(--ink-faint);
}

.mock__dots { display: flex; gap: 5px; flex: none; }
.mock__dots i { width: 9px; height: 9px; border-radius: 50%; background: #B9B5AB; }

.mock__url {
  flex: 1 1 auto;
  min-width: 0;
  padding: 4px 9px;
  border-radius: 999px;
  background: #FFFFFF;
  font-family: var(--mono);
  font-size: 8.5px;
  letter-spacing: 0.04em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: #6E6A64;
}

.mock__toggle { display: flex; gap: 4px; flex: none; }

.mock__tog {
  min-height: 32px;
  padding: 5px 8px;
  border: 1px solid var(--ink-faint);
  background: transparent;
  font-size: 8px;
  color: var(--ink-soft);
  cursor: pointer;
}

.mock__tog.is-on { border-color: var(--ink); background: var(--ink); color: var(--paper, #F1EFE9); }
.mock__tog:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.mock__well { display: grid; place-items: center; padding: 12px; background: #CFC9BC; }

.mock__rest {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
}

.mock__rest img { display: block; width: 100%; height: auto; }

.mock__go {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  padding: 10px 14px;
  background: var(--ink);
  font-size: 9px;
  letter-spacing: 0.12em;
  white-space: nowrap;
  color: var(--paper, #F1EFE9);
}

.mock__rest:hover .mock__go { background: #2E2A8E; }
.mock__rest:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.mock__hold { overflow: hidden; background: #FFFFFF; }
.mock__frame { display: block; border: 0; }
.mock__scroll { width: 100%; max-height: 70vh; overflow-y: auto; background: #FFFFFF; }
.mock__capture { display: block; width: 100%; height: auto; }

.mock__phone {
  position: relative;
  padding: 14px 10px;
  border: 3px solid var(--ink);
  border-radius: 36px;
  background: #14110F;
}

.mock__notch {
  position: absolute;
  left: 50%;
  top: 6px;
  width: 78px;
  height: 14px;
  transform: translateX(-50%);
  border-radius: 0 0 9px 9px;
  background: #14110F;
  z-index: 2;
}

.mock__screen { overflow: hidden; border-radius: 22px; background: #FFFFFF; }

.mock__full {
  min-height: 40px;
  margin: 10px 0 0;
  padding: 8px 11px;
  border: 1px solid var(--ink-faint);
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
}

.mock__full:hover { border-color: var(--ink); color: var(--ink); }
.mock__full:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.mock__note {
  margin: 9px 0 0;
  font-family: var(--mono);
  font-size: 9px;
  line-height: 1.5;
  color: var(--ink-soft);
}

/* -- The map on a phone ----------------------------------------------------
   The map keeps its shape and its pills, and the board does the work. */

@media (max-width: 720px) {
  /* The pill lettering is set in script, with the pill built around it. */
  .net__num { font-size: 34px; }
  .net__hubtext { font-size: 34px; }

  /* The note moves under the map, pointing down at the board. */
  .net__note {
    position: static;
    justify-content: center;
    padding: 10px 12px 0;
  }
  .net__notetext { max-width: none; }
  .net__arrow { transform: rotate(72deg); }
}

@media (prefers-reduced-motion: reduce) {
  .net__ring,
  .net__pill,
  .net__here,
  .net__panel,
  .lan__pass,
  .lan__body,
  .mag__page,
  .mag__open,
  .docs__page,
  .docs__cover img,
  .web3__dot { transition: none; }
  .net__stop.is-at .net__ring,
  .net__stop.is-in .net__ring,
  .net__stop.is-waving .net__ring,
  .dep__row.is-in .dep__flap { animation: none; }
  .dep__flap { transform: none; }
  .net__spoke { opacity: 1; }
  .net__stop { opacity: 1; }
  .mag__open.is-turning { transform: none; }
  .docs__sheet.is-curling .docs__page { transform: none; }
}

/* -- The timeline trace -------------------------------------------------- */

.ttrace { margin: 0 0 6px; }

.ttrace__tabs { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 12px; }

.ttrace__tab {
  padding: 7px 13px;
  border: 2px solid var(--ink);
  background: var(--paper);
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.08em;
  color: var(--ink);
  cursor: pointer;
}

.ttrace__tab.is-on { background: var(--ink); color: var(--paper); }
.ttrace__tab:focus-visible { outline: 3px solid var(--mark); outline-offset: 3px; }

.ttrace__chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 12px; }

.ttrace__chip {
  padding: 5px 11px;
  border: 1px solid var(--rule);
  background: var(--paper);
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
  cursor: pointer;
}

.ttrace__chip.is-on { border-color: var(--mark); background: var(--mark); color: var(--paper); }
.ttrace__chip:focus-visible { outline: 3px solid var(--mark); outline-offset: 2px; }

.ttrace__frame {
  position: relative;
  overflow: hidden;
  border: 3px solid var(--ink);
  background: var(--paper-lo);
}

.ttrace__plane {
  position: relative;
  transform-origin: 50% 50%;
  transition: transform 400ms var(--enter);
}

.ttrace__img { display: block; width: 100%; height: auto; }

.ttrace__wires {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 2;
}

.ttrace__mark {
  position: absolute;
  padding: 0;
  border: 2px solid transparent;
  background: none;
  cursor: pointer;
  z-index: 3;
  transition: border-color var(--t-micro) var(--micro), opacity var(--t-micro) var(--micro);
}

/* A box a hair tall still has to be clickable, so it grows a hit area
   outwards without the drawn outline moving. */
.ttrace__mark--thin::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 28px;
  transform: translateY(-50%);
}

.ttrace__badge {
  position: absolute;
  left: -2px;
  top: -2px;
  min-width: 17px;
  padding: 1px 3px;
  background: var(--mark);
  font-family: var(--mono);
  font-size: 10px;
  line-height: 1.4;
  text-align: center;
  color: var(--paper);
  z-index: 4;
}

.ttrace__plane.is-held .ttrace__img { opacity: 0.45; }
.ttrace__img { transition: opacity var(--t-micro) var(--micro); }

.ttrace__mark.is-lit { border-color: var(--mark); border-width: 3px; }
.ttrace__mark.is-lit { animation: bc-pulse 600ms var(--enter) 1; }
.ttrace__mark:focus-visible { outline: 3px solid var(--mark); outline-offset: 2px; }

@keyframes bc-pulse {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--mark) 60%, transparent); }
  100% { box-shadow: 0 0 0 10px transparent; }
}

.ttrace__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: 12px 0 0;
}

.ttrace__read {
  margin: 0;
  flex: 1 1 260px;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--ink-soft);
}

.ttrace__reset {
  padding: 6px 11px;
  border: 2px solid var(--ink);
  background: var(--paper);
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  color: var(--ink);
  cursor: pointer;
}

.ttrace__reset:focus-visible { outline: 3px solid var(--mark); outline-offset: 3px; }

/* -- The mentoring list -------------------------------------------------- */

.mentor {
  margin: 0 0 18px;
  padding: 0;
  list-style: none;
}

.mentor__row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 9px 0;
  border-bottom: 1px dashed var(--rule);
}

.mentor__box {
  flex: none;
  width: 13px;
  height: 13px;
  margin-top: 3px;
  border: 2px solid var(--rule);
  background: transparent;
  transition: background var(--t-micro) var(--micro), border-color var(--t-micro) var(--micro);
}

.mentor__row.is-on .mentor__box { background: var(--mark); border-color: var(--mark); }

.mentor__text {
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-body);
}

/* -- Narrower ------------------------------------------------------------ */

@media (max-width: 899px) {
  .wall__devices { display: none; }
  .wall__grid { grid-template-columns: repeat(6, 1fr); }
  .wall__cell { grid-column: span 2; }
  .wall__cell--h { grid-column: span 3; }
  /* With the phone gone, a vertical cut opens where it sits. */
  .wall__cell--v .wall__hold.is-open { aspect-ratio: 9 / 16; }

  .job__track { flex-direction: column; align-items: stretch; padding-top: 0; }
  .job__node { flex: none; }
  .job__flow { flex: none; width: 0; height: 16px; margin-left: 22px; border-top: 0; border-left: 2px dashed var(--rule); }
  .job__ticket { position: static; transform: none; margin: 0 0 10px; }
  .fc__grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 559px) {
  .cstrip { grid-template-columns: repeat(2, 1fr); }
  .wall__grid { grid-template-columns: repeat(4, 1fr); }
  .wall__cell { grid-column: span 2; }
  .wall__cell--h { grid-column: span 4; }
  .cstrip__fig { font-size: 24px; }
  .fc__grid { grid-template-columns: 1fr; }
  .job__files { gap: 6px; }
  .job__file { flex: 1 1 calc(50% - 6px); }
  .job__turn { gap: 12px; }
  /* Without room for a frame, the clip is simply the clip. */
  .fc__stage .bcmon__body { padding: 0; border-width: 2px; border-radius: 0; }
  .fc__stage .bcmon__neck, .fc__stage .bcmon__foot { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .wall__cell,
  .wall__card,
  .wall__shot,
  .job__ticket,
  .job__knob,
  .job__img,
  .job__plane,
  .fc__vid,
  .ttrace__plane,
  .ttrace__img,
  .ttrace__mark,
  .mentor__box { transition: none; }

  .wall__card:hover,
  .wall__card:focus-visible { transform: none; }

  .job__fbox.is-pulse { animation: none; }
  .ttrace__mark.is-lit { animation: none; }
}

/* -- A spread of pages ------------------------------------------------ */

.pages { margin: 0; }
.pages__wrap { position: relative; display: block; }

.pages__img {
  display: block;
  width: 100%;
  height: auto;
}

.pages__half {
  position: absolute;
  top: 0;
  height: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: zoom-in;
}

.pages__half:hover { background: color-mix(in srgb, var(--mark) 8%, transparent); }
.pages__half:focus-visible { outline: 3px solid var(--mark); outline-offset: -3px; }

.pages__link {
  display: inline-block;
  margin: 12px 0 0;
  padding: 0;
  border: 0;
  background: none;
  font-family: var(--mono);
  font-size: 12.5px;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
  text-decoration: underline;
  text-underline-offset: 4px;
  cursor: pointer;
}

.pages__link:hover { color: var(--ink); }
.pages__link:focus-visible { outline: 2px solid var(--mark); outline-offset: 3px; }

/* The quantities on a chip, while they run up. */
.out-chip__n { font-variant-numeric: tabular-nums; }

@media (max-width: 699px) {
  .phone__count { top: 8px; right: 8px; gap: 9px; font-size: 11px; padding: 5px 9px; }
  .phone__reset { font-size: 11px; }
  .phone__stamp { padding: 12px 18px; }
  .phone__stampline { font-size: 15px; letter-spacing: 0.1em; }
  .phone__stampnote { font-size: 11px; }
  .phone__line { margin-left: 0; }
  .stops__tag { font-size: 9px; letter-spacing: 0.04em; }
  .stops__read { min-height: 128px; }
  .courses__grid { grid-template-columns: 1fr; }
  .srcs { grid-template-columns: 1fr; }
  .reel__chip { font-size: 11px; padding: 6px 10px; }
  .reel__tally { width: 100%; margin: 2px 0 0; }
  .reel__peek { width: 160px; margin-left: -80px; }
  .reel__peekart { width: 160px; height: 90px; }
  .reel__read { flex-direction: column; gap: 14px; min-height: 0; }
  .reel__shot { width: 100%; }
  .reel__legend { gap: 8px 16px; }

  /* The bar is drawn at 28px, but a finger is given the full 44. */
  .reel__seg::before {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    top: -8px;
    bottom: -8px;
  }
  .courses__back { padding: 14px 16px; }
  .courses__val { font-size: 13px; }
  .trace__read { min-height: 4.8em; }
}

@media (prefers-reduced-motion: reduce) {
  .phone__art svg #framing,
  .phone__art svg .is-gone,
  .phone__art svg #good-sound-meter,
  .phone__box,
  .stops__head,
  .reel__head,
  .reel__peek,

  .phone__stamp,
  .phone__stamp.is-on {
    transition: none;
    transform: translate(-50%, -50%) rotate(-5deg);
  }
}

/* The enlarged view steps through a run of pages. */
.lightbox__step,
.lightbox__count {
  position: fixed;
  z-index: 2;
  margin: 0;
  font-family: var(--mono);
  color: var(--paper-hi);
}

.lightbox__step {
  top: 50%;
  width: 54px;
  height: 54px;
  transform: translateY(-50%);
  border: 1.5px solid rgba(241, 239, 233, 0.45);
  background: rgba(10, 10, 10, 0.5);
  font-size: 26px;
  line-height: 1;
  cursor: pointer;
}

.lightbox__step:hover { background: rgba(10, 10, 10, 0.8); border-color: var(--paper-hi); }
.lightbox__step--back { left: 3vw; }
.lightbox__step--on { right: 3vw; }

.lightbox__count {
  left: 50%;
  bottom: 3vh;
  transform: translateX(-50%);
  padding: 6px 14px;
  background: rgba(10, 10, 10, 0.5);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.crew__note { color: #57514A; }

.crew__caption {
  margin: 18px 0 0;
  padding-top: 14px;
  border-top: 1px dashed #C9C3B6;
  font-size: 12.5px;
  letter-spacing: 0.06em;
  color: #57514A;
}

@media (prefers-reduced-motion: reduce) {
  .crew__mark--on,
  .crew__mark--half,
  .crew__mark--off rect,
  .crew__mark--on,
  .crew__mark--half { opacity: 1; transform: none; }
  .crew__mark--off rect { stroke-dashoffset: 0; }
}

.conn-box { margin: 8px 0; }

.conn {
  display: block;
  width: 100%;
  height: auto;
  margin: 0 auto;
}

.conn text { font-family: var(--mono); }
.conn__node { fill: var(--mark); }

/* Below 700px the narrow drawings take over, so no curve is squashed and
   no label shrinks past reading. */
.conn--narrow { display: none; }

@media (max-width: 699px) {
  .conn--wide { display: none; }
  .conn--narrow { display: block; }
}

.chip-row {
  display: flex;
  justify-content: center;
  margin: 4px 0 0;
}

.out-chip {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  margin: 0;
  padding: 14px 22px;
  border: 1.5px solid #14110F;
  background: #E4E1D8;
  font-family: var(--mono);
  font-size: 15px;
  line-height: 1.3;
  color: #14110F;
}

.out-chip__mark {
  width: 10px;
  height: 10px;
  flex: none;
  background: var(--mark);
}

/* Before and after. Two screenshots at one shape, read from the top of the
   page down, in greys at rest and in colour on hover. Each opens full size. */
.compare {
  margin: 30px 0 0;
  padding: 22px 0 0;
  border-top: 1px dashed var(--rule);
}

.compare__title { margin: 0 0 14px; }

.compare__pair {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: 16px;
}

.compare__side {
  display: block;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: zoom-in;
}

/* Printed white out of black, like the labels on the homepage. */
.compare__tag {
  display: inline-block;
  margin: 0 0 8px;
  padding: 3px 8px 2px;
  background: var(--ink);
  color: #EEECE6;
}

.compare__shot {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--ph-fill);
  box-shadow: 0 0 0 1px rgba(29, 29, 28, 0.2), 0 6px 14px -8px rgba(0, 0, 0, 0.35);
}

.compare__shot img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
  opacity: 0;
  filter: grayscale(1) contrast(1.08);
  transition: opacity var(--t-exit) var(--enter), filter var(--t-exit) var(--enter);
}

.compare__shot.is-ready img { opacity: 1; }
.compare__shot.is-ready .artefact__ph { display: none; }

.compare__side:hover .compare__shot img,
.compare__side:focus-visible .compare__shot img { filter: none; }

/* Sits level with the screenshots, below the tags. */
.compare__arrow {
  padding-top: 28px;
  font-size: 20px;
  color: var(--ink-soft);
}

.lightbox[hidden] { display: none !important; }

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(10, 10, 10, 0.74);
  display: flex;
  align-items: flex-start;
  justify-content: flex-start;
  padding: 5vh 5vw;
  overflow: auto;
  cursor: zoom-out;
}

.lightbox > * { margin: auto; }

.lightbox img { max-width: 100%; max-height: 90vh; object-fit: contain; background: var(--paper-hi); }

.lightbox .media__ph {
  position: static;
  width: min(720px, 90vw);
  aspect-ratio: 4 / 3;
  background: var(--ph-fill);
}

/* -- The portrait -------------------------------------------------------
   A print taped to the page: the colour photograph underneath, the ink
   halftone over it, and a hole in the top layer that follows the pointer. */

/* The receipt is a narrow column by design, so the picture sits above the
   words rather than beside them: a photograph at the size it wants would
   leave the text about two hundred pixels of line, which is no column at
   all. Where the container is wide enough for both, it takes the left. */
.about__open {
  container-type: inline-size;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 22px;
  align-items: start;
  margin: 0 0 8px;
}

.port { width: 100%; max-width: 400px; }
.about__words > p:first-child { margin-top: 0; }

@container (min-width: 720px) {
  .about__open {
    grid-template-columns: minmax(300px, 380px) minmax(0, 1fr);
    gap: 30px;
  }
}

.port {
  position: relative;
  margin: 0;
  padding: 14px 14px 10px;
  border: 1px solid var(--ink);
  background: #F7F4EC;
  box-shadow: 4px 6px 0 rgba(20, 17, 15, 0.14);
  transform: rotate(1.5deg);
  transition: transform 200ms var(--enter);
}

.port:hover { transform: rotate(0deg); }

/* Two strips of tape, one over each top corner. */
.port__tape {
  position: absolute;
  top: -11px;
  width: 78px;
  height: 24px;
  background: rgba(233, 226, 205, 0.86);
  box-shadow: 0 1px 0 rgba(20, 17, 15, 0.1);
}

.port__tape--l { left: -14px; transform: rotate(-7deg); }
.port__tape--r { right: -14px; transform: rotate(6deg); }

.port__well {
  position: relative;
  aspect-ratio: 1;
  overflow: hidden;
  background: #F7F4EC;
  /* The hole rests off the picture until a pointer puts it somewhere. */
  --x: -400px;
  --y: -400px;
}

.port__colour,
.port__dots {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* At rest the dots cover the colour completely. Where the pointer is, the
   top layer is cut away in a soft circle and the print shows through. */
.port__dots {
  opacity: 1;
  transition: opacity 300ms var(--enter);
  -webkit-mask-image: radial-gradient(circle 130px at var(--x) var(--y),
    transparent 0%, transparent 42%, #000 100%);
  mask-image: radial-gradient(circle 130px at var(--x) var(--y),
    transparent 0%, transparent 42%, #000 100%);
}

.port__well.is-bare .port__dots { opacity: 0; }

/* The tap target a touch screen gets in place of a pointer. */
.port__tap {
  position: absolute;
  inset: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
}

.port__tap:focus-visible { outline: 3px solid var(--accent); outline-offset: -4px; }

/* The print coming up: the colour first, then the dots settling over it. */
@keyframes port-develop {
  0%   { opacity: 0; }
  35%  { opacity: 0; }
  100% { opacity: 1; }
}

.port.is-developing .port__dots {
  animation: port-develop 1200ms var(--enter);
  -webkit-mask-image: none;
  mask-image: none;
}

.port__note {
  position: absolute;
  right: -14px;
  bottom: -20px;
  max-width: 190px;
  padding: 10px 12px;
  background: #F2E9A8;
  box-shadow: 2px 3px 0 rgba(20, 17, 15, 0.16);
  transform: rotate(-2.5deg);
  font-family: var(--pen);
  font-size: 17px;
  line-height: 1.2;
  color: var(--ink);
}

@media (prefers-reduced-motion: reduce) {
  .port,
  .port__dots { transition: none; }
  .port.is-developing .port__dots { animation: none; }
}

/* -- About ------------------------------------------------------ */

.sheet { max-width: min(680px, 100%); }
.sheet .modal__body { margin: 0 auto; }

/* -- Contact ----------------------------------------------------- */

.postcard-scene { perspective: 1600px; max-width: 600px; width: 100%; margin: auto; }

.postcard {
  position: relative;
  transform-style: preserve-3d;
  transition: transform 500ms var(--enter);
}

.postcard.is-flipped { transform: rotateY(180deg); }

.postcard__face {
  padding: 44px 40px 38px;
  box-shadow: 0 26px 60px rgba(0, 0, 0, 0.32);
  backface-visibility: hidden;
}

/* The contact side sits in the flow and sets the height. The written side
   is laid over it, so the card is never clipped to the shorter face. */
.postcard__face--back { transform: rotateY(180deg); }

.postcard__face--front {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
}

.postcard__word { font-size: 34px; }

.postcard__name { margin: 0; }

.postcard__list { margin: 0; padding: 0; list-style: none; }

.card-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 7px 0;
}

.card-row__k {
  flex: 1 1 auto;
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 8.5em;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.card-row__k::after {
  content: '';
  flex: 1;
  margin-bottom: 0.3em;
  border-bottom: 1px dotted var(--ink-faint);
}

.card-row__v {
  flex: 0 1 auto;
  max-width: 64%;
  text-align: right;
  font-size: 13.5px;
  color: var(--ink);
  word-break: break-word;
}

a.card-row__v {
  text-decoration: none;
  border-bottom: 1px solid var(--rule);
}

a.card-row__v:hover { border-bottom-color: var(--ink); }

.li-mark {
  width: 14px;
  height: 14px;
  flex: none;
  align-self: center;
  color: var(--ink);
}

.postcard__annotation { margin: 0 0 18px; text-align: center; transform: rotate(-2deg); }

/* ============================================================
   12. Linear layout, under 900px
   ============================================================ */

@media (max-width: 899px) {
  body { font-size: 14px; }
  .t-identity, .t-body { font-size: 14px; }
  .t-title { font-size: 30px; }
  .t-modal-title { font-size: 18px; }
  .t-annotation { font-size: 24px; }

  /* The landing gives up the fixed viewport and stacks. */
  .landing {
    height: auto;
    min-height: 0;
    overflow: visible;
    padding: 34px 7vw 44px;
  }

  .landing__identity { font-size: 24px; }

  .landing__stage {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 52px;
    padding: 36px 0 16px;
  }

  .watermark { font-size: clamp(60px, 20vw, 150px); top: 34%; }

  .thing { position: static; width: 100%; max-width: 268px; transform: none; margin: 0; }
  .thing--centred { transform: none; margin: 0; }
  .photo { max-width: 224px; }
  .envelope { max-width: 220px; }
  .notebook { max-width: 300px; }
  .landing__eyebrow { font-size: 10px; letter-spacing: 0.14em; padding: 4px 9px 3px; }

  /* No hover on touch, so the envelope rests open with the letter out. */
  .env { margin-top: 72px; }
  .env-flap { z-index: 1; transform: rotateX(-178deg); }
  .env-letter { transform: translateY(-50%); }

  .caps {
    position: static;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 10px 14px;
    margin: 24px 0 0;
  }

  .cap { position: static; }
  .cap__box { font-size: 10px; padding: 2px 8px; }

  /* No book on touch. Chapters stack and expand in place, inside one sheet
     wrapped tightly by the leather, with even margins. */
  .book-root { padding: 16px 12px 28px; align-items: stretch; }
  .book { max-width: none; margin: 0; perspective: none; transform: none; }
  .book__spread { display: block; min-height: 0; padding: 12px; gap: 0; border-radius: 10px; box-shadow: none; }
  .book__spread::after { display: none; }
  .book__spread::before { inset: 6px; }
  .book__left, .book__right { border-radius: 0; box-shadow: none; }
  .book__left { border-radius: 3px 3px 0 0; padding: 58px 7vw 22px; }
  .book__right { border-radius: 0 0 3px 3px; padding: 4px 7vw 34px; }
  .book__chapter-title { text-align: center; }
  .tabs { display: none; }

  .projects { grid-template-columns: minmax(0, 1fr); gap: 40px; }
  .project { width: 100%; }
  .project__blurb { display: block; overflow: visible; }

  .project__mine,
  .project__credit {
    display: block;
    margin: 8px 0 0;
    font-size: 12px;
    line-height: 1.5;
    color: var(--ink-body);
  }

  .project__mine::before {
    content: 'MY PART  ';
    font-weight: 600;
    letter-spacing: 0.14em;
    color: var(--ink-soft);
  }

  .project__credit { color: var(--ink-soft); }

  /* The clipped slip keeps its side clip but stays inside the page on a phone. */
  .book__left, .book__right { --page-pad-left: 0px; }
  .clipnote { margin: 0 0 24px; max-width: none; }

  .chapter-list { margin: 0; padding: 0; list-style: none; }
  .chapter-list > li { border-top: 1px dashed var(--rule); }

  .chapter-list__head {
    width: 100%;
    display: flex;
    align-items: baseline;
    gap: 14px;
    padding: 20px 0;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
  }

  .chapter-list__title {
    font-size: 15px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink);
  }

  .chapter-list__panel { padding: 0 0 36px; }
  .chapter-list__panel[hidden] { display: none; }

  .modal-root { padding: 14px 10px 24px; align-items: flex-start; }
  .modal { padding: 52px 6vw 36px; }
  .postcard-scene { max-width: none; }
  .postcard__face { padding: 44px 6vw 34px; }
  .card-row { flex-wrap: wrap; }
  .card-row__v { max-width: 100%; text-align: left; }
  .modal__meta dd { max-width: 58%; }
  .strip { gap: 14px; }
  .artefact__art { height: 170px; }

  /* On a phone the pair stacks, the arrow turned to point down. */
  .compare__pair { grid-template-columns: minmax(0, 1fr); gap: 10px; }
  .compare__arrow { padding-top: 0; justify-self: center; transform: rotate(90deg); }
}

/* ============================================================
   13. Reduced motion. Opacity only, capped at 200ms.
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 200ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 200ms !important;
    transition-delay: 0ms !important;
    transition-property: opacity !important;
    scroll-behavior: auto !important;
  }

  .rise, .project { transform: none !important; }

  .thing.is-idle .nb-cover,
  .thing.is-idle .photo__frame,
  .thing.is-idle .env-flap { animation: none !important; }

  .notebook:hover .nb-book { transform: translateX(-25%) !important; }
  .notebook:hover .nb-cover,
  .notebook:hover .nb-sheet { transform: none !important; }
  .notebook:hover .nb-cover,
  .notebook:hover .nb-sheet,
  .notebook:hover .nb-snap { opacity: 0; }
  .photo:hover .photo__frame { transform: rotate(2deg) !important; }

  /* The envelope rests open, the letter part way out. Nothing swings. */
  .env-flap { z-index: 1 !important; transform: rotateX(-178deg) !important; }
  .env-letter { transform: translateY(-50%) !important; }

  .hovernote { transform: none !important; }

  .book { transform: none !important; }
  .leaf { display: none !important; }

  /* No flip. The contact side is simply the card. */
  .postcard.is-flipped { transform: none !important; }
  .postcard__face--back { transform: none !important; }
  .postcard__face--front { display: none; }
}
