/* ==========================================================================
   The Shot List / Harakiri (1962)
   Design system: "paper, ink and the wound"
   A poster sheet: off-white paper, stark black, and blood red used only
   where it hits. One theme, no switching.
   ========================================================================== */

/* ---------- Tokens ---------- */
:root {
  --bg: #f3f1ec;
  --bg-2: #ebe8e1;
  --bg-3: #dedad1;
  --ink: #0b0b0b;
  --ink-2: #2a2927;
  --ink-3: #6b675f;
  --rule: #d3cec4;
  --accent: #c8141c;
  --accent-2: #a50f16;
  --on-accent: #fbf7f2;
  --frame: #0b0b0b;
  --frame-ink: #f3f1ec;

  --f-display: "Anton", "Impact", "Haettenschweiler", "Arial Narrow Bold", sans-serif;
  --f-jp: "Shippori Mincho B1", "Hiragino Mincho ProN", "Yu Mincho", "YuMincho", serif;
  --f-brush: "Yuji Boku", "Shippori Mincho B1", "Hiragino Mincho ProN", "Yu Mincho", serif;
  --f-body: "Newsreader", Georgia, "Times New Roman", serif;
  --f-mono: "IBM Plex Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;

  --fs-body: clamp(18px, 0.6vw + 15px, 21px);
  --measure: 66ch;
  --wide: 1100px;
  --sheet: 1320px;
  --gutter: 16px;
  --mast-h: 58px;

  color-scheme: light;
}

@media (min-width: 720px) {
  :root { --gutter: clamp(24px, 4vw, 48px); --mast-h: 64px; }
}

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  background: var(--bg);
}

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--f-body);
  font-size: var(--fs-body);
  font-optical-sizing: auto;
  line-height: 1.65;
  overflow-wrap: break-word;
  font-kerning: normal;
  font-variant-ligatures: common-ligatures;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

main { display: block; overflow-x: clip; }

:lang(ja) { font-family: var(--f-jp); }

::selection { background: var(--accent); color: var(--on-accent); }

a {
  color: inherit;
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: var(--ink-3);
  text-underline-offset: 0.22em;
  transition: color 160ms ease, text-decoration-color 160ms ease;
}
a:hover { color: var(--accent-2); text-decoration-color: currentColor; }

button { font: inherit; color: inherit; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
[tabindex="-1"]:focus { outline: none; }

cite { font-style: italic; }

h1, h2, h3, p, figure, dl, dd, ul, blockquote { margin: 0; }

/* the ink filters live in an inline SVG in index.html */
.ink-defs {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

.skip-link {
  position: absolute;
  left: 12px;
  top: -60px;
  z-index: 100;
  padding: 10px 14px;
  background: var(--ink);
  color: var(--bg);
  font: 500 12px/1 var(--f-mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-decoration: none;
}
.skip-link:focus { top: 12px; color: var(--bg); }

/* ---------- Reading progress ---------- */
.progress {
  position: fixed;
  inset: 0 0 auto 0;
  height: 3px;
  z-index: 60;
  pointer-events: none;
}
.progress-bar {
  display: block;
  height: 100%;
  background: var(--accent);
  transform-origin: 0 50%;
  transform: scaleX(0);
  will-change: transform;
}

/* ---------- Masthead ---------- */
.masthead {
  position: relative;
  z-index: 3;
  border-bottom: 1px solid var(--ink);
}
.masthead-inner {
  width: min(var(--sheet), 100% - 2 * var(--gutter));
  min-height: var(--mast-h);
  margin-inline: auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.brand {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
  color: var(--ink);
  text-decoration: none;
}
.brand:hover { color: var(--ink); }
.brand-mark {
  flex: none;
  width: 11px;
  height: 11px;
  background: var(--accent);
}
.brand-name {
  font: 400 15px/1 var(--f-display);
  letter-spacing: 0.3em;
  margin-right: -0.3em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* ---------- Hero: the poster sheet ---------- */
.hero {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  border-bottom: 1px solid var(--ink);
}
.hero-art {
  position: relative;
  z-index: 0;
  pointer-events: none;
}
.hero-art > svg {
  display: block;
  width: 100%;
  height: 100%;
}
.hero-text {
  position: relative;
  z-index: 1;
  min-width: 0;
}
.hero-kicker {
  display: flex;
  align-items: center;
  gap: 10px;
  font: 500 10.5px/1.2 var(--f-mono);
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--ink);
}
.hero-kicker::before {
  content: "";
  flex: none;
  width: 7px;
  height: 7px;
  background: var(--ink);
}
/* Dry-brush capitals: #ink-xl (index.html) warps the strokes, roughens the
   contour and, at the tops and bottoms of the letters, where the brush
   lifts off, carves a few long bristle streaks that run down the strokes
   and taper inward. Its effect is sized in pixels, so the same brush
   comes in three scales, picked by title size below: #ink-xl-s under
   about 120px, #ink-xl to about 170px, #ink-xl-l above.
   Each letter is its own span, set a hair off the baseline and the square,
   the way a hand-lettered poster title sits. */
.hero-title {
  margin: 0.12em 0 0;
  font: 400 clamp(84px, 25.5vw, 150px)/0.92 var(--f-display);
  letter-spacing: 0.015em;
  margin-left: -0.035em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--ink);
  filter: url(#ink-xl);
}
/* the title's size is clamp(84px, 25.5vw, 150px) below 900px and
   clamp(110px, 11.4vw, 196px) above: under 120px in the first two ranges
   here, over 170px in the last */
@media (max-width: 469px), (min-width: 900px) and (max-width: 1052px) {
  .hero-title { filter: url(#ink-xl-s); }
}
@media (min-width: 1492px) {
  .hero-title { filter: url(#ink-xl-l); }
}
.hero-title > span {
  display: inline-block;
  transform: translateY(var(--y, 0)) rotate(var(--r, 0deg));
  transform-origin: 50% 85%;
}
.hero-title > span:nth-child(1) { --y: 0.006em;  --r: -0.9deg; }
.hero-title > span:nth-child(2) { --y: -0.012em; --r: 0.7deg; }
.hero-title > span:nth-child(3) { --y: 0.008em;  --r: -0.4deg; }
.hero-title > span:nth-child(4) { --y: -0.004em; --r: 1.1deg; }
.hero-title > span:nth-child(5) { --y: 0.012em;  --r: -0.8deg; }
.hero-title > span:nth-child(6) { --y: -0.01em;  --r: 0.6deg; }
.hero-title > span:nth-child(7) { --y: 0.005em;  --r: -0.7deg; }
.hero-title > span:nth-child(8) { --y: -0.008em; --r: 1.2deg; }

/* on load the title is stamped in letter by letter, 切腹 inks in after it,
   and the hero's red lands last (art.js plays the hero art itself) */
@media (prefers-reduced-motion: no-preference) {
  .hero-title > span { animation: title-stamp 0.55s cubic-bezier(0.3, 1.4, 0.45, 1) both; }
  .hero-title > span:nth-child(1) { animation-delay: 0.10s; }
  .hero-title > span:nth-child(2) { animation-delay: 0.16s; }
  .hero-title > span:nth-child(3) { animation-delay: 0.22s; }
  .hero-title > span:nth-child(4) { animation-delay: 0.28s; }
  .hero-title > span:nth-child(5) { animation-delay: 0.34s; }
  .hero-title > span:nth-child(6) { animation-delay: 0.40s; }
  .hero-title > span:nth-child(7) { animation-delay: 0.46s; }
  .hero-title > span:nth-child(8) { animation-delay: 0.52s; }
  .hero-jp { animation: title-ink 0.7s ease-out 0.8s both; }
  .hero-art.art-play .art-splash { animation-delay: 0.95s; }
  .hero-art.art-play .art-spray { animation-delay: 1.12s; }
}
@keyframes title-stamp {
  0% { opacity: 0; scale: 1.8; }
  55% { opacity: 1; scale: 0.95; }
  100% { opacity: 1; scale: 1; }
}
@keyframes title-ink {
  from { opacity: 0; }
  to { opacity: 1; }
}
.hero-jp {
  margin-top: 0.18em;
  font: 400 clamp(34px, 9vw, 52px)/1 var(--f-brush);
  letter-spacing: 0.08em;
  color: var(--accent);
  filter: url(#ink-sm);
}
.hero-film {
  margin-top: 22px;
  font: 500 1.06rem/1.3 var(--f-body);
  letter-spacing: 0.01em;
  color: var(--ink);
}
.hero-film span { margin: 0 0.3em; color: var(--ink-3); }
.hero-dek {
  margin-top: 12px;
  max-width: 34ch;
  font: 400 clamp(1.08rem, 0.98rem + 0.35vw, 1.22rem)/1.5 var(--f-body);
  color: var(--ink-2);
  text-wrap: pretty;
}
.hero-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  row-gap: 6px;
  margin-top: 22px;
  font: 400 10.5px/1.3 var(--f-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.hero-meta > * + *::before {
  content: "";
  display: inline-block;
  width: 14px;
  height: 1px;
  margin: 0 0.85em;
  vertical-align: middle;
  background: currentColor;
  opacity: 0.7;
}
.hero-by { color: var(--ink); }
.hero-credit {
  margin-top: 30px;
  padding-top: 12px;
  max-width: 62ch;
  border-top: 1px solid var(--accent);
  font: 500 9.5px/1.85 var(--f-mono);
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--accent-2);
  text-wrap: pretty;
}

/* The kneeling figure in art.js sits on a flat ground line at --ground of
   its 1000 x 1000 box (keep it in step with the hero builder there). Both
   layouts draw that line as an ink hairline, so the silhouette kneels on
   the sheet, and both keep paper below it: the edge of the hero never
   crops the figure's base. */
.hero-art { --ground: 0.898; }
.hero-art::after {
  content: "";
  position: absolute;
  top: calc(var(--ground) * 100%);
  height: 1px;
  background: var(--ink);
}

/* phones and narrow tablets: the figure on top, bleeding off the sheet,
   kneeling on a hairline that runs edge to edge */
@media (max-width: 899px) {
  .hero { padding-bottom: 48px; }
  .hero-art {
    width: min(122vw, 760px);
    aspect-ratio: 1 / 1;
    margin: -4vw 0 -7vw;
    left: 50%;
    transform: translateX(-50%);
  }
  .hero-art::after {
    left: 50%;
    width: 100vw;
    transform: translateX(-50%);
  }
  .hero-text {
    width: min(620px, 100% - 2 * var(--gutter));
    margin-inline: auto;
  }
}

/* desktop: a poster sheet about one screen tall; type left, figure right.
   The art hangs off the right edge of the content column (the same
   min(--sheet, 100% - 2 gutters) box the type is set in), not off the
   window, so text and figure stay one composition at any width. */
@media (min-width: 900px) {
  .hero {
    min-height: clamp(600px, 88svh, 1000px);
    display: flex;
    align-items: center;
  }
  .hero-art {
    /* capped so that, with the title at full size, the drips and the
       scabbard stay clear of the type */
    --art: min(60vw, 96svh, 900px);
    /* window edge to the content column's right edge */
    --col-edge: max(var(--gutter), (100% - var(--sheet)) / 2);
    /* paper between the figure's floor and the bottom of the sheet */
    --floor-gap: clamp(32px, 5svh, 56px);
    position: absolute;
    bottom: calc(var(--floor-gap) - var(--art) * (1 - var(--ground)));
    right: calc(var(--col-edge) - var(--art) * 0.12);
    width: var(--art);
    aspect-ratio: 1 / 1;
  }
  /* the floor: from just behind the scabbard's tip to the column's edge */
  .hero-art::after {
    left: 6%;
    right: 12%;
  }
  .hero-text {
    width: min(var(--sheet), 100% - 2 * var(--gutter));
    margin-inline: auto;
    padding: clamp(40px, 7svh, 88px) 0 clamp(44px, 7svh, 88px);
  }
  .hero-text > * { max-width: min(42vw, 600px); }
  .hero-text > .hero-title { max-width: none; }
  .hero-title { font-size: clamp(110px, 11.4vw, 196px); }
  .hero-jp { font-size: clamp(40px, 3.6vw, 62px); }
  .hero-dek { max-width: min(36ch, 40vw); }
  .hero-credit { max-width: min(40vw, 560px); }
}

/* ---------- Parts ---------- */
.part { position: relative; }
.part-head {
  padding: clamp(4.5rem, 11vw, 8rem) var(--gutter) clamp(2.75rem, 6vw, 4.5rem);
  text-align: center;
  scroll-margin-top: 24px;
}
.part--review .part-head { padding-top: clamp(3.75rem, 8vw, 6.5rem); }
.part-mark {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}
.part-kanji {
  font: 400 clamp(2.6rem, 2rem + 2vw, 3.4rem)/1 var(--f-brush);
  color: var(--ink);
  margin-bottom: 8px;
}
.part-label {
  font: 500 11px/1 var(--f-mono);
  letter-spacing: 0.32em;
  margin-right: -0.32em;
  text-transform: uppercase;
  color: var(--ink);
}
.part-sub {
  font: italic 400 1rem/1.3 var(--f-body);
  color: var(--ink-3);
}

/* ---------- The flow grid ---------- */
.flow {
  --wide-extra: calc((var(--wide) - var(--measure)) / 2);
  position: relative;
  display: grid;
  grid-template-columns:
    [full-start] minmax(var(--gutter), 1fr)
    [wide-start] minmax(0, var(--wide-extra))
    [text-start] min(var(--measure), 100% - 2 * var(--gutter))
    [text-end] minmax(0, var(--wide-extra))
    [wide-end] minmax(var(--gutter), 1fr)
    [full-end];
}
.flow > * { grid-column: text; min-width: 0; }
.flow > * + * { margin-top: 1.15em; }

.chapter { scroll-margin-top: 24px; }
.chapter + .chapter { margin-top: clamp(4.5rem, 9vw, 7.25rem); }

.flow > p {
  text-wrap: pretty;
  hanging-punctuation: first;
}
@media (max-width: 559px) {
  .flow > p { hyphens: auto; -webkit-hyphens: auto; }
}

.flow > :is(figure, aside) { margin-top: clamp(2.5rem, 6vw, 3.75rem); }
.flow > :is(figure, aside) + * { margin-top: clamp(2.5rem, 6vw, 3.75rem); }
/* a still that is not on the page leaves no gap behind it */
html:not(.show-placeholders) .flow > .still--missing + :not(figure, aside) { margin-top: 1.15em; }
.flow > .ch-title + * { margin-top: 1.05em; }

/* ---------- Chapter headings ---------- */
.ch-title {
  font: 400 clamp(1.9rem, 1.35rem + 1.9vw, 2.75rem)/1.04 var(--f-display);
  letter-spacing: 0.012em;
  text-transform: uppercase;
  color: var(--ink);
  text-wrap: balance;
}
.ch-title:not(.ch-title--num)::before {
  content: "";
  display: block;
  width: 2.1rem;
  height: 4px;
  margin-bottom: 0.6em;
  background: var(--ink);
}
.ch-title--num {
  display: flex;
  align-items: center;
}
.ch-num {
  flex: none;
  display: inline-grid;
  place-items: center;
  min-width: 1.1em;
  padding-right: 0.42em;
  font: 400 1.02em/1 var(--f-brush);
  color: var(--accent);
  align-self: stretch;
}
.ch-en { min-width: 0; }
.ch-title--num .ch-en {
  padding-left: 0.48em;
  border-left: 2px solid var(--ink);
}

/* ---------- Drop caps ---------- */
.dropcap::first-letter {
  float: left;
  font-family: var(--f-display);
  font-weight: 400;
  font-size: 3.9em;
  line-height: 0.82;
  margin: 0.06em 0.09em 0 -0.02em;
  color: var(--ink);
}
@supports (initial-letter: 3) or (-webkit-initial-letter: 3) {
  .dropcap::first-letter {
    float: none;
    font-size: inherit;
    line-height: inherit;
    margin: 0 0.12em 0 0;
    -webkit-initial-letter: 3;
    initial-letter: 3;
  }
}

/* ---------- Sidenotes ---------- */
.sn { white-space: normal; }
.sn-ref {
  position: relative;
  top: -0.55em;
  margin: 0 0.02em 0 0.04em;
  padding: 0 0.1em;
  border: 0;
  background: none;
  font: 500 0.6em/1 var(--f-mono);
  color: var(--ink-2);
  cursor: pointer;
  vertical-align: baseline;
  transition: color 160ms ease;
}
.sn-ref::after {
  content: "";
  position: absolute;
  inset: -10px -7px;
}
.sn-ref:hover,
:root:not(.sn-margin) .sn-ref[aria-expanded="true"],
.sn.is-hot .sn-ref { color: var(--accent-2); }

.sn-note {
  display: none;
  font-size: 0.8em;
  line-height: 1.55;
  color: var(--ink-3);
  text-wrap: pretty;
  hyphens: manual;
}
.sn-num {
  font: 500 0.82em/1 var(--f-mono);
  color: var(--ink-2);
  margin-right: 0.65em;
}
.sn.is-hot .sn-num { color: var(--accent-2); }

/* inline (narrow) mode: tap to expand */
.no-js .sn-note,
.sn.is-open .sn-note {
  display: block;
  margin: 0.85em 0 0.95em;
  padding: 0.15em 0 0.15em 1.05em;
  border-left: 2px solid var(--ink);
  color: var(--ink-2);
}

/* margin mode (wide screens), positioned by page.js */
.sn-margin .sn-note {
  display: block;
  position: absolute;
  top: 0;
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 0.74em;
  line-height: 1.5;
  transition: color 200ms ease;
}
/* margin mode, but no room beside the reference (a still or a plate fills the
   margin there, or the chapter ends): page.js sets the note open under its
   line, exactly as in inline mode */
.sn-margin .sn.sn-inline .sn-note {
  position: static;
  width: auto;
  margin: 0.85em 0 0.95em;
  padding: 0.15em 0 0.15em 1.05em;
  border-left: 2px solid var(--ink);
  font-size: 0.8em;
  line-height: 1.55;
  color: var(--ink-2);
}
.sn-margin .sn.is-hot .sn-note { color: var(--ink); }

/* ---------- Film stills ---------- */
.flow > .still { grid-column: full; }
@media (min-width: 720px) {
  .flow > .still { grid-column: wide; }
}
.still { container-type: inline-size; }
.still-frame {
  position: relative;
  overflow: hidden;
  aspect-ratio: 2.35 / 1;
  background: var(--frame);
}
.still-frame img {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
  opacity: 0;
}
.still--loaded .still-frame img { opacity: 1; }
/* a hairline keyline, so pale skies and sand still read as the edge of a frame */
.still--loaded .still-frame::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink) 45%, transparent);
  pointer-events: none;
}
.still--missing .still-frame img { display: none; }
/* Where the 2.35:1 crop falls. s02, s05 and s06 carry burned-in subtitles near
   the bottom edge, so they keep it; s01 and s12 (about 2.2:1) give up a little
   of the dark above rather than the floor. */
.still[data-still="s02"] img,
.still[data-still="s05"] img,
.still[data-still="s06"] img { object-position: 50% 100%; }
.still[data-still="s01"] img { object-position: 50% 35%; }
.still[data-still="s12"] img { object-position: 50% 90%; }

/* Until page.js has found its file, a still holds its place in the layout
   but is not drawn, so a missing one never flashes up as an empty frame
   and a found one appears without moving anything below it. The class is
   page.js's: if page.js never runs it is gone by load, and nothing hides. */
.stills-probing .still:not(.still--found):not(.still--missing) { visibility: hidden; }

/* a still whose file does not exist is not on the page at all;
   ?placeholders in the URL shows a labelled placeholder in its place */
.still--missing { display: none; }
.show-placeholders .flow > .still--missing { display: block; }
.still-ph { display: none; }
.still--missing .still-frame {
  background: var(--bg-2);
  border: 1px dashed var(--ink-3);
}
.still--missing .still-ph {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: max(6px, 0.9cqw);
  padding: 4% 8%;
  text-align: center;
}
.still-ph-id {
  font: 500 max(10px, 1.08cqw)/1.3 var(--f-mono);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink);
}
.still-ph-id span { color: var(--ink-3); }
.still-ph-desc {
  max-width: 46ch;
  font: italic 400 max(13px, 1.7cqw)/1.4 var(--f-body);
  color: var(--ink-2);
  text-wrap: balance;
}
.still-ph-file {
  font: 400 max(9.5px, 0.95cqw)/1.3 var(--f-mono);
  letter-spacing: 0.06em;
  color: var(--ink-3);
}
@container (max-width: 520px) {
  .still-ph-desc { display: none; }
}

.still figcaption {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 5px;
  margin-top: 14px;
  max-width: 62ch;
  font-size: 0.82em;
  line-height: 1.5;
  color: var(--ink-2);
  text-wrap: pretty;
}
@media (max-width: 719px) {
  .still figcaption { padding-inline: var(--gutter); }
}
.still-label,
.art figcaption::before,
.structure-figure figcaption::before {
  font: 500 10px/1.6 var(--f-mono);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ink);
}
.still-scene { color: var(--ink); }
.still-line { font-style: italic; }
.still-tag {
  margin-left: 0.5em;
  font: 400 9.5px/1 var(--f-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
  white-space: nowrap;
}

/* ---------- Pull line: one spoken line lifted into the text, set like a script ---------- */
.flow > .pull + * { margin-top: 1.5em; }
.pull {
  display: grid;
  gap: 0.8rem;
  padding: 0.15rem 0 0.3rem clamp(1.15rem, 2.6vw, 1.6rem);
  border-left: 4px solid var(--ink);
}
.pull-who {
  font: 500 11px/1.2 var(--f-mono);
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--ink);
}
.pull-line p {
  max-width: 30ch;
  font: italic 400 clamp(1.5rem, 1.1rem + 1.35vw, 2.1rem)/1.22 var(--f-body);
  color: var(--ink);
  text-wrap: balance;
  text-indent: -0.4em;  /* hang the opening quote mark */
}

/* ---------- Illustrations & structure (mounts) ---------- */
body { counter-reset: plate; }
.flow > .art {
  grid-column: wide;
  justify-self: center;
  width: 100%;
  max-width: 920px;
}
.flow > .art[data-art="armor"] { max-width: 520px; }
.flow > .structure-figure {
  grid-column: wide;
  justify-self: center;
  width: 100%;
}
.art-canvas,
.structure-mount { width: 100%; }
.art-canvas > svg { display: block; width: 100%; height: auto; }

.art figcaption,
.structure-figure figcaption {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 5px;
  margin-top: 16px;
  max-width: 62ch;
  font-size: 0.82em;
  line-height: 1.5;
  color: var(--ink-2);
  text-wrap: pretty;
}
.art figcaption::before {
  counter-increment: plate;
  content: "Plate " counter(plate);
}
.structure-figure figcaption::before { content: "Structure"; }
@media (min-width: 720px) {
  .art figcaption,
  .structure-figure figcaption,
  .still figcaption {
    grid-template-columns: 7.5rem minmax(0, 1fr);
    align-items: baseline;
    gap: 16px;
    /* the label column plus a full caption measure, so short captions
       under a wide frame run on one line */
    max-width: calc(7.5rem + 16px + 60ch);
  }
  .art[data-art="armor"] figcaption { grid-template-columns: minmax(0, 1fr); gap: 5px; max-width: 62ch; }
}

/* ---------- Stamps: a rough red block, the type knocked out in paper ---------- */
.stamp {
  position: relative;
  isolation: isolate;
  color: var(--on-accent);
}
.stamp::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--accent);
  filter: url(#ink-sm);
}
.stamp::after {
  content: "";
  position: absolute;
  inset: var(--stamp-inset, 8%);
  border: 1.5px solid var(--on-accent);
  filter: url(#ink-xs);
  pointer-events: none;
}
.stamp > span { position: relative; filter: url(#ink-xs); }

/* ---------- Decorative splatter mounts (filled by art.js) ---------- */
.splat {
  position: absolute;
  z-index: 0;
  pointer-events: none;
}

/* ---------- The record (the film's fictional ledger) ---------- */
.flow > .record {
  grid-column: wide;
  justify-self: center;
  width: 100%;
  max-width: calc(var(--measure) + 80px);
}
.record-sheet {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  background: var(--bg);
  border: 1px solid var(--ink);
  border-top-width: 4px;
}
.record-head {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 6px 18px;
  padding: 15px 20px 13px;
  border-bottom: 1px solid var(--ink);
}
.record-title {
  font: 500 11px/1.3 var(--f-mono);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ink);
}
.record-sub {
  font: 400 10px/1.3 var(--f-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.record-body {
  --lh: 2rem;
  position: relative;
  padding: var(--lh) clamp(16px, 3.5vw, 32px) calc(var(--lh) * 2) clamp(36px, 6vw, 64px);
  font: 400 1.0625rem/var(--lh) var(--f-body);
  font-size: clamp(1rem, 0.92rem + 0.3vw, 1.1rem);
  line-height: var(--lh);
  color: var(--ink);
  background-image: linear-gradient(to bottom, transparent calc(var(--lh) - 1px), var(--rule) calc(var(--lh) - 1px));
  background-size: 100% var(--lh);
  background-position: 0 0;
}
.record-body::before,
.record-body::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--ink);
}
.record-body::before { left: clamp(18px, 3vw, 34px); }
.record-body::after { left: calc(clamp(18px, 3vw, 34px) + 4px); }
.record-body p + p { margin-top: var(--lh); }
.record-date { font-weight: 600; }
.record-spine {
  grid-column: 2;
  grid-row: 2;
  writing-mode: vertical-rl;
  padding: 2rem clamp(10px, 2vw, 16px);
  border-left: 1px solid var(--ink);
  font: 500 0.9rem/1 var(--f-jp);
  letter-spacing: 0.6em;
  color: var(--ink);
}
.record-seal {
  position: absolute;
  right: clamp(56px, 9vw, 92px);
  bottom: 18px;
  display: grid;
  place-items: center;
  width: 64px;
  height: 64px;
  --stamp-inset: 7px;
  transform: rotate(5deg);
}
.record-seal span {
  writing-mode: vertical-rl;
  font: 800 19px/1 var(--f-jp);
  letter-spacing: 0.1em;
}
@media (max-width: 479px) {
  .record-spine { display: none; }
  .record-sheet { grid-template-columns: minmax(0, 1fr); }
  .record-body { padding-left: 34px; padding-right: 16px; padding-bottom: calc(var(--lh) * 2.5); }
  .record-body::before { left: 16px; }
  .record-body::after { left: 20px; }
  .record-seal { right: 16px; bottom: 14px; width: 56px; height: 56px; }
  .record-seal span { font-size: 17px; }
}

/* ---------- Spoiler gate: a black band across the sheet ---------- */
.gate {
  --gate-pt: clamp(3.5rem, 8vw, 5.5rem);  /* band top to stamp top; the splat's mask reads it too */
  position: relative;
  margin-top: clamp(5rem, 12vw, 8.5rem);
  padding: var(--gate-pt) var(--gutter) clamp(3.25rem, 7vw, 5rem);
  background: var(--frame);
  color: var(--frame-ink);
  overflow: hidden;
  isolation: isolate;
}
.gate-inner {
  width: min(var(--wide), 100%);
  margin-inline: auto;
  text-align: center;
}
.gate-rule {
  display: flex;
  justify-content: center;
  /* clears the splatter's drips, which hang well below the stamp */
  margin-bottom: 4.25rem;
}
.gate-warning,
.gate-open-text { position: relative; z-index: 1; }
.gate-stamp {
  position: relative;
  isolation: isolate;
  display: inline-block;
}
/* The splatter (art.js) sits in a box 3.4 stamps tall around the stamp, and
   its spray flies well past that box, far enough to reach the top of the
   band, which would cut it off square. So the box grows by --reach on every
   side while the drawing keeps its size and place, and a mask thins the
   spray out just inside the band instead. --band is the top edge of the
   band measured from the top of the grown box: the stamp's top is 1.2
   stamp-heights (1.2 / 3.4 of the drawing) below the drawing's top, and
   --gate-pt above the stamp. */
.gate-stamp .splat {
  --reach: 64px;
  --band: calc(var(--reach) + (100% - 2 * var(--reach)) * 0.352941 - var(--gate-pt));
  inset: calc(-120% - var(--reach)) calc(-55% - var(--reach));
  -webkit-mask-image: linear-gradient(to bottom, transparent calc(var(--band) + 3px), #000 calc(var(--band) + 24px));
  mask-image: linear-gradient(to bottom, transparent calc(var(--band) + 3px), #000 calc(var(--band) + 24px));
}
.gate-stamp .splat > svg {
  left: var(--reach);
  top: var(--reach);
  width: calc(100% - 2 * var(--reach));
  height: calc(100% - 2 * var(--reach));
}
.gate-tag {
  position: relative;
  z-index: 1;
  display: inline-block;
  padding: 13px 18px 12px 23px;
  --stamp-inset: 5px;
  font: 400 clamp(20px, 2.4vw, 26px)/1 var(--f-display);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  transform: rotate(-3deg);
}
.gate-warning cite,
.gate-open-text cite { font-style: normal; }
.gate-warning {
  max-width: 38ch;
  margin-inline: auto;
  font: italic 400 clamp(1.12rem, 0.95rem + 0.65vw, 1.4rem)/1.5 var(--f-body);
  color: var(--frame-ink);
  text-wrap: balance;
}
.gate-actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
  margin-top: clamp(1.75rem, 4vw, 2.5rem);
}
.gate-button {
  min-height: 48px;
  padding: 15px 26px 15px 28px;
  border: 0;
  border-radius: 0;
  background: var(--frame-ink);
  color: var(--ink);
  font: 500 11.5px/1.3 var(--f-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color 160ms ease, color 160ms ease;
}
.gate-button:hover { background: var(--accent); color: var(--on-accent); }
.gate-button:focus-visible { outline-color: var(--frame-ink); }
.gate-open { display: none; }
/* set in <head> for a returning reader, before page.js removes [hidden] */
[data-spoilers="revealed"] #reading[hidden] { display: block; }
[data-spoilers="revealed"] .gate-closed { display: none; }
[data-spoilers="revealed"] .gate-open { display: block; }
[data-spoilers="revealed"] .gate {
  --gate-pt: clamp(3rem, 6vw, 4rem);
  padding-top: var(--gate-pt);
  padding-bottom: clamp(2.25rem, 4.5vw, 3rem);
}
[data-spoilers="revealed"] .gate-rule { margin-bottom: 4rem; }
.gate-open-text {
  max-width: 40ch;
  margin-inline: auto;
  font: italic 400 1.05rem/1.5 var(--f-body);
  color: color-mix(in srgb, var(--frame-ink) 82%, transparent);
  text-wrap: balance;
}
.gate-hide {
  margin-top: 12px;
  padding: 8px 4px;
  border: 0;
  background: none;
  font: 500 10.5px/1 var(--f-mono);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--frame-ink) 66%, transparent);
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--frame-ink) 30%, transparent);
  text-underline-offset: 0.4em;
  cursor: pointer;
}
.gate-hide:hover { color: var(--frame-ink); }
.gate :focus-visible { outline-color: var(--frame-ink); }

/* ---------- Sign-off ---------- */
/* The closing plate: the kneeling figure and the name in the red (drawn
   by art.js, 1500 x 660), on open paper above the footer. Without the
   script the name stands alone in red. */
.signoff {
  padding: clamp(6rem, 13vw, 10rem) var(--gutter) 0;
}
.signoff-art {
  width: min(100%, var(--sheet));
  margin-inline: auto;
}
.signoff-art > svg { display: block; width: 100%; height: auto; }
/* phones: the plate runs to the edges of the screen, like the hero */
@media (max-width: 639px) {
  .signoff-art { width: auto; margin-inline: calc(-1 * var(--gutter)); }
}
.signoff-fallback {
  display: block;
  font: 400 clamp(96px, 20vw, 280px)/0.92 var(--f-display);
  text-transform: uppercase;
  text-align: center;
  color: var(--accent);
}
.signoff-line {
  margin-top: clamp(1.25rem, 2.6vw, 2rem);
  text-align: center;
  font: 500 10.5px/1.6 var(--f-mono);
  letter-spacing: 0.26em;
  margin-right: -0.26em;
  text-transform: uppercase;
  color: var(--ink-3);
}
main:has(.signoff) + .site-footer { margin-top: clamp(4rem, 9vw, 6.5rem); }

/* ---------- Footer ---------- */
.site-footer {
  margin-top: clamp(6rem, 14vw, 10rem);
  padding: 40px var(--gutter) 56px;
  border-top: 4px solid var(--ink);
}
.footer-inner {
  width: min(var(--wide), 100%);
  margin-inline: auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 24px;
}
@media (min-width: 820px) {
  .footer-inner {
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 48px;
  }
}
.footer-brand {
  display: flex;
  align-items: center;
  gap: 12px;
}
.footer-name {
  font: 400 15px/1 var(--f-display);
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--ink);
  white-space: nowrap;
}
.colophon {
  max-width: 56ch;
  font: 400 10.5px/1.75 var(--f-mono);
  letter-spacing: 0.06em;
  color: var(--ink-3);
}
.back-top {
  justify-self: start;
  font: 500 10.5px/1 var(--f-mono);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink);
}

/* ---------- Motion ---------- */
/* Nothing animates on load or on scroll. Hover transitions only. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }
}

/* ---------- Utilities ---------- */
.nowrap { white-space: nowrap; }
.visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

@media print {
  .progress, .gate-actions, .gate-open { display: none !important; }
  #reading[hidden] { display: block; }
  .sn-note { display: block; }
  .gate { background: none; color: var(--ink); }
}
