/* =========================================================================
   Reigen Arataka — unofficial fan tribute
   All character artwork is original hand-authored CSS/SVG. The only raster
   assets are three licensed photographic textures used as low-opacity
   backdrops (see assets/textures/ and the Image credits block in the footer).
   Layout: single long scroll, mobile-first, no build step.
   ========================================================================= */

/* ------------------------------- TOKENS ------------------------------- */
:root {
  /* Colour — "poster paint on newsprint" reading of the series' palette.
     Contrast ratios are measured against --ink from rendered pixels. Text over
     a textured surface measures lower, because the texture lightens the real
     backdrop under the glyphs. Magenta is the darkest accent and so sets the
     ceiling on how far any texture may lighten a surface — which is why magenta
     *text* uses its own lighter token (see --magenta-txt) while the saturated
     hue stays for fills, borders and auras. */
  --ink:        #0c0c11;   /* page base                                  */
  --ink-2:      #14141c;   /* raised surface                             */
  --ink-3:      #1d1d28;   /* card surface                               */
  --line:       #2c2c3a;   /* hairline borders                           */
  --line-2:     #3d3d50;

  --paper:      #f2ede2;   /* primary text            (16.71:1)         */
  --paper-dim:  #b8b2a6;   /* secondary text           (9.25:1)         */
  --paper-mute: #a5a096;   /* tertiary / fine print    (7.50:1)         */

  --magenta:    #ff3d7f;   /* aura / fills / borders   (5.62:1 on ink)  */
  /* Magenta as *text*. #ff3d7f measured 4.95:1 over the textured panel — on the
     AA line with no headroom left for the texture layer. This lighter mix keeps
     the hue and buys ~1.3 stops, so every textured surface can carry visible
     grain and still clear 5:1 on small magenta type. */
  --magenta-txt: #ff5c94;  /* magenta text            (6.50:1 on ink)  */
  --teal:       #17d6c6;   /* aura / links            (10.66:1)         */
  --acid:       #d8f24a;   /* highlight               (15.53:1)         */
  --tan:        #d9b483;   /* warm neutral            (10.04:1)         */
  --tan-dark:   #b18f66;

  /* Portrait palette. Overridden per instance for the manga/anime compare. */
  --fig-skin:    #e8c69e;
  --fig-skin-2:  #c69a6b;
  --fig-skin-3:  #a3763f;
  --fig-line:    #47331f;
  --fig-hair:    #c9884a;
  --fig-hair-2:  #e0aa72;
  --fig-suit:    #3b3b47;
  --fig-suit-2:  #26262f;
  --fig-shirt:   #ece7dd;
  --fig-shirt-2: #c8c2b5;
  --fig-tie:     #ef5f96;
  --fig-tie-2:   #c9265d;

  /* Type */
  --f-display: 'Archivo Black', 'Archivo', 'Helvetica Neue', Arial, sans-serif;
  --f-body:    'Archivo', 'Helvetica Neue', Arial, sans-serif;
  --f-quote:   'Newsreader', Georgia, 'Times New Roman', serif;
  --f-mono:    ui-monospace, 'Cascadia Mono', 'SF Mono', Menlo, Consolas, monospace;
  /* Latin webfonts carry no kanji — Japanese text needs its own stack. */
  --f-ja: 'Hiragino Kaku Gothic ProN', 'Hiragino Sans', 'Yu Gothic UI', 'Yu Gothic',
          'Meiryo', 'MS PGothic', 'Noto Sans JP', 'Noto Sans CJK JP', sans-serif;

  --fs-xs:   0.75rem;
  --fs-sm:   clamp(0.8125rem, 0.79rem + 0.12vw, 0.9375rem);
  --fs-base: clamp(1rem, 0.96rem + 0.2vw, 1.125rem);
  --fs-md:   clamp(1.0625rem, 1rem + 0.35vw, 1.3125rem);
  --fs-lg:   clamp(1.3125rem, 1.16rem + 0.75vw, 1.875rem);
  --fs-xl:   clamp(1.625rem, 1.32rem + 1.5vw, 2.75rem);
  --fs-2xl:  clamp(2rem, 1.5rem + 2.6vw, 3.75rem);
  --fs-hero: clamp(2.75rem, 1.4rem + 9.4vw, 8.5rem);

  /* Space */
  --sp-1: 0.25rem; --sp-2: 0.5rem;  --sp-3: 0.75rem; --sp-4: 1rem;
  --sp-5: 1.5rem;  --sp-6: 2rem;    --sp-7: 3rem;    --sp-8: 4rem;
  --sp-9: clamp(3.5rem, 2rem + 7vw, 7rem);

  --measure: 62ch;
  --wrap: 74rem;
  --pad: clamp(1rem, 0.5rem + 2.5vw, 3rem);
  --radius: 2px;
  /* Anchor offset for the sticky header. Mobile-first: the header stacks the
     brand over the nav strip (~98px). Overridden at >=56rem where it is one row. */
  --header-h: 6.25rem;

  /* Texture paths — relative, so the project subpath on GitHub Pages works.
     --tex-paper is a grain *plate*, not a photograph: the source paper shot was
     nearly flat (sigma 4.6 of 255), so its flat tone was subtracted and only the
     detail kept, amplified and highlight-clipped. See the .tex block. */
  --tex-paper:    url('../assets/textures/paper-grain.jpg');
  --tex-city:     url('../assets/textures/city-night.jpg');
  --tex-bokeh:    url('../assets/textures/bokeh-dust.jpg');

  /* Motion */
  --dur-fast: 150ms;
  --dur: 240ms;
  --dur-reveal: 560ms;
  --ease: cubic-bezier(0.2, 0.7, 0.3, 1);
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  color-scheme: dark;
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--f-body);
  font-size: var(--fs-base);
  line-height: 1.6;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  overflow-wrap: break-word;
  touch-action: manipulation;
  -webkit-tap-highlight-color: rgba(216, 242, 74, 0.2);
}

/* Subtle halftone texture — decorative, never intercepts input. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 60;
  pointer-events: none;
  background-image: radial-gradient(circle at center, rgba(242,237,226,0.5) 0.5px, transparent 0.6px);
  background-size: 4px 4px;
  opacity: 0.05;
}

h1, h2, h3, h4 {
  margin: 0;
  line-height: 1.08;
  font-weight: 700;
  letter-spacing: -0.015em;
  text-wrap: balance;
}
p, ul, ol, figure, table, blockquote { margin: 0; }
p { text-wrap: pretty; }
ul, ol { padding: 0; list-style: none; }
img, svg { max-width: 100%; }
table { border-collapse: collapse; }
cite { font-style: italic; }

a { color: var(--teal); text-decoration-thickness: 1px; text-underline-offset: 0.18em; }
a:hover { color: var(--acid); }

:focus-visible {
  outline: 3px solid var(--acid);
  outline-offset: 3px;
  border-radius: var(--radius);
}

[lang="ja"] { font-family: var(--f-ja); }

.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}

/* ---------------------------- SKIP LINK -------------------------------- */
.skip-link {
  position: absolute;
  left: var(--sp-4);
  top: -6rem;
  z-index: 100;
  padding: var(--sp-3) var(--sp-5);
  background: var(--acid);
  color: var(--ink);
  font-weight: 700;
  text-decoration: none;
  transition: top var(--dur) var(--ease);
}
.skip-link:focus { top: var(--sp-3); color: var(--ink); }

/* -------------------------- TEXTURE BACKDROPS -------------------------- */
/* Shared machinery. A textured surface paints an opaque background, isolates
   itself, then layers a texture above that background but below its own content
   (negative z-index inside the isolated group). None of these backdrops has
   ever shown up as an LCP candidate in a trace — not because pseudo-elements
   are exempt (they are not), but because each is stretched over a large area
   and so falls under Chromium's low-entropy threshold for background images.
   The hero's bokeh plate does qualify; see the note on .hero__art::before.

   Two rules make this layer behave, both learned the hard way:

   1. `screen`, never `soft-light`. Per the W3C compositing formula soft-light
      collapses toward the backdrop as the backdrop goes to black, so on this
      near-black palette it discards the source almost entirely — four textures
      decoded and composited for a change measuring under 2.5 of 765. `screen`
      over a dark backdrop is effectively additive, so it survives; it also
      never darkens, which keeps the coloured gradients under .section--quotes
      intact instead of washing them flat.

   2. `.tex` declares its own background-color. A blend mode is only defined
      against a known backdrop, and two sections here never set one — so their
      blend degenerated to plain source-over and the texture landed at full
      alpha while every other section got a near-no-op. Same declaration, two
      completely different renderings, decided by whether the consumer happened
      to declare a background. Consumers may still override this; they must not
      have to.

   Because the blend is additive, the *brightest* texture pixel sets the worst
   contrast case under a glyph. The plates are therefore highlight-clipped at
   source (max ~115 of 255) so `opacity` alone bounds the worst case: peak lift
   is about opacity x 115. Raising any --tex-op means re-measuring. */
.tex {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background-color: var(--ink);
}
.tex::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image: var(--tex-img);
  background-position: var(--tex-pos, center);
  background-size: var(--tex-size, cover);
  background-repeat: var(--tex-repeat, no-repeat);
  opacity: var(--tex-op, 0.2);
  mix-blend-mode: var(--tex-blend, screen);
  /* No grayscale() pass: the two grain plates already ship as 8-bit Greyscale.
     Only city-night and bokeh-dust are sRGB, and both desaturate themselves. */
  filter: var(--tex-filter, none);
}

/* Every grain surface uses the one paper plate, as a seamless 256px tile painted
   1:1 — never `cover`. Upscaling a grain tile averages the grain away: the
   section that did that measured under one RGB step of variation across a whole
   band, a flat grey wash rather than texture. Only the opacity varies per
   surface, set beside each section below.

   A second plate (worn concrete) used to back .section--origin and .site-footer
   and has been deleted. Its source photo was flatter still (sigma 3.3 of 255),
   so the 12x amplification needed to make it visible also amplified its coarse
   trowel streaks — and at any tile size small enough to be worth shipping those
   streaks repeated legibly, as a mirror motif or a seam depending on how the
   tile was closed. It could be visible, or it could be seamless, but not both. */
.section--who,
.section--beyond,
.section--quotes,
.section--origin,
.panel--fake,
.site-footer {
  --tex-img: var(--tex-paper);
  --tex-size: 256px 256px;
  --tex-repeat: repeat;
}

/* ------------------------------ HEADER -------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(12, 12, 17, 0.9);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}

.site-header__inner {
  max-width: var(--wrap);
  margin-inline: auto;
  padding: 0 var(--pad);
  display: flex;
  flex-direction: column;
  gap: 0;
}

/* Reading-position bar. Gated behind @supports so browsers without
   scroll-driven animations get nothing rather than a permanently full bar. */
.scroll-progress { display: none; }
@supports (animation-timeline: scroll()) {
  .scroll-progress {
    display: block;
    position: absolute;
    left: 0; right: 0; bottom: -1px;
    height: 2px;
    pointer-events: none;
  }
  .scroll-progress span {
    display: block;
    height: 100%;
    background: linear-gradient(90deg, var(--magenta), var(--tan), var(--acid));
    transform: scaleX(0);
    transform-origin: 0 50%;
    animation: read-progress linear both;
    animation-timeline: scroll(root block);
  }
  @keyframes read-progress {
    from { transform: scaleX(0); }
    to   { transform: scaleX(1); }
  }
}

.brand {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) 0 var(--sp-2);
  color: var(--paper);
  text-decoration: none;
  min-height: 44px;
}
.brand__mark {
  flex: none;
  width: 2rem; height: 2rem;
  display: grid; place-items: center;
  background: var(--magenta);
  color: var(--ink);
  font-size: 1.25rem;   /* 霊 is a dense glyph — needs the extra size to read */
  font-weight: 500;
  line-height: 1;
  transition: background var(--dur) var(--ease);
}
.brand__text { display: flex; flex-direction: column; line-height: 1.15; }
.brand__text b { font-size: var(--fs-sm); letter-spacing: 0.01em; }
.brand__text small {
  font-family: var(--f-mono);
  font-size: 0.625rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--paper-mute);
}
.brand:hover .brand__text b { color: var(--acid); }
.brand:hover .brand__mark { background: var(--acid); }

/* Nav: horizontal scroller on narrow screens, never widens the page. */
.site-nav { position: relative; margin-inline: calc(var(--pad) * -1); }

/* Fade at the right edge hints that the strip scrolls. Removed at >=72rem,
   the width at which all ten chips fit inside the wrapper. */
.site-nav::after {
  content: "";
  position: absolute;
  right: 0; top: 0; bottom: 0;
  width: 2.5rem;
  pointer-events: none;
  background: linear-gradient(90deg, rgba(12,12,17,0), rgba(12,12,17,0.95));
}
.site-nav ul {
  display: flex;
  gap: var(--sp-1);
  overflow-x: auto;
  scrollbar-width: none;
  padding: 0 var(--pad) var(--sp-2);
  scroll-snap-type: x proximity;
}
.site-nav ul::-webkit-scrollbar { display: none; }
.site-nav li { flex: none; scroll-snap-align: start; }
.site-nav a {
  display: block;
  padding: var(--sp-2) var(--sp-3);
  color: var(--paper-dim);
  font-family: var(--f-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  border: 1px solid transparent;
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.site-nav a:hover { color: var(--paper); border-color: var(--line-2); }
.site-nav a[aria-current="true"] {
  color: var(--ink);
  background: var(--acid);
  border-color: var(--acid);
  font-weight: 600;
}

@media (min-width: 56rem) {
  /* Brand and nav share one row from here, so the header is shorter. */
  :root { --header-h: 4.25rem; }
  .site-header__inner { flex-direction: row; align-items: center; justify-content: space-between; gap: var(--sp-5); }
  .brand { padding: var(--sp-4) 0; }
  .site-nav { margin-inline: 0; min-width: 0; }
  .site-nav ul { padding: 0; }
}
@media (min-width: 72rem) {
  .site-nav::after { display: none; }
  .site-nav ul { overflow-x: visible; }
}

/* ------------------------------- HERO --------------------------------- */
.hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  max-width: 100%;
  padding: var(--sp-8) var(--pad) var(--sp-9);
  min-height: min(92svh, 54rem);
  display: grid;
  align-content: center;
}

/* --- hero art: photo bloom + aura blobs + rays + the portrait --- */
.hero__art {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
}

/* Bokeh/dust plate. Blurred and desaturated to near-abstraction so it reads
   as depth rather than as a photograph. ~10 KB.

   Known and accepted: this plate IS the page's LCP element, reported against
   its originating element. Moving it from a real <span> to this pseudo-element
   did NOT remove candidacy — a background-image is an LCP candidate either way;
   only Chromium's low-entropy exclusion keeps the .tex backdrops out, and this
   plate carries too much detail per painted pixel to qualify. It stays because
   it is 10 KB and paints alongside the heading, so the metric names a
   decorative layer without actually delaying anything a reader waits for. If
   that trade stops being acceptable, replace the photo with CSS gradients —
   no image, no candidate. */
.hero__art::before {
  content: "";
  position: absolute;
  inset: -12%;
  background: var(--tex-bokeh) center / cover no-repeat;
  filter: blur(7px) saturate(0.4) brightness(0.9);
  opacity: 0.3;
}

/* Scrim: keeps the art bright on the right, guarantees text contrast on the
   left where the copy sits. Without this the aura undercuts AA on the kicker. */
.hero__art::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    /* darkens the copy side */
    linear-gradient(90deg,
      rgba(12,12,17,0.90) 0%, rgba(12,12,17,0.68) 32%,
      rgba(12,12,17,0.18) 55%, rgba(12,12,17,0) 70%),
    /* tames the aura glare behind the kicker on narrow screens */
    linear-gradient(180deg, rgba(12,12,17,0.45) 0%, rgba(12,12,17,0) 40%);
}

.aura {
  position: absolute;
  border-radius: 50%;
  filter: blur(46px);
  opacity: 0.5;
}
.aura--a {
  width: 34rem; height: 34rem;
  right: -12rem; top: -10rem;
  background: radial-gradient(circle at 50% 50%, var(--magenta) 0%, rgba(255,61,127,0) 68%);
}
.aura--b {
  width: 30rem; height: 30rem;
  left: -12rem; bottom: -8rem;
  background: radial-gradient(circle at 50% 50%, var(--teal) 0%, rgba(23,214,198,0) 68%);
  opacity: 0.4;
}
.aura--c {
  width: 22rem; height: 22rem;
  right: 8%; bottom: 6%;
  background: radial-gradient(circle at 50% 50%, var(--acid) 0%, rgba(216,242,74,0) 66%);
  opacity: 0.16;
}

.rays {
  position: absolute;
  right: -6rem;
  top: 46%;
  translate: 0 -50%;
  width: 30rem;
  color: var(--tan);
  opacity: 0.22;
}

/* The portrait. Halo and outer ring live outside the reusable symbol because
   they only belong to the hero composition. */
.figure {
  position: absolute;
  right: -4.5rem;
  bottom: -3rem;
  width: 18rem;
  opacity: 0.62;
}
.fg-halo {
  fill: none;
  stroke: var(--tan);
  stroke-width: 26;
  opacity: 0.16;
}
.fg-ring {
  fill: none;
  stroke: var(--acid);
  stroke-width: 1.5;
  stroke-dasharray: 2 12;
  opacity: 0.5;
}

.hero__salt {
  position: absolute;
  right: 46%;
  bottom: 16%;
  width: 9rem;
  color: var(--tan);
  opacity: 0.5;
  rotate: -14deg;
}

/* 48-68rem: the portrait becomes a subject again, so the copy measure is
   pulled in to keep text and artwork from ever overlapping. Measured at 768px:
   tagline 8.0:1, fine print 6.5:1. */
@media (min-width: 48rem) {
  .hero { --hero-measure: 36ch; }
  .figure { width: 20rem; right: -3rem; bottom: -3.5rem; opacity: 0.95; }
  .rays { right: -4rem; width: 30rem; opacity: 0.26; }
  .hero__salt { width: 10rem; right: 40%; bottom: 24%; }
  .hero__note { max-width: 44ch; }
}
@media (min-width: 68rem) {
  .hero { --hero-measure: 46ch; }
  .figure { width: 31rem; right: 4%; }
  .rays { right: -1rem; width: 36rem; opacity: 0.28; }
  .hero__salt { width: 15rem; right: 32%; }
  .hero__note { max-width: 56ch; }
}

/* --- hero text --- */
.hero__body {
  position: relative;
  max-width: var(--wrap);
  width: 100%;
  margin-inline: auto;
}

.kicker {
  font-family: var(--f-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--magenta-txt);
  margin-bottom: var(--sp-3);
  width: fit-content;
}
.kicker--strike span {
  position: relative;
  display: inline-block;
  padding-right: 0.2em;
}
.kicker--strike span::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 52%;
  height: 2px;
  background: var(--magenta);
  transform-origin: left center;
}

.hero__title {
  font-family: var(--f-display);
  font-size: var(--fs-hero);
  line-height: 0.86;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  margin-bottom: var(--sp-3);
}
.hero__title span { display: block; }
/* Second word outlined rather than filled: poster device, and it lets the
   portrait read through the letterforms. */
.hero__title span:last-child {
  color: transparent;
  -webkit-text-stroke: clamp(1.5px, 0.28vw, 3px) var(--tan);
}
@supports not ((-webkit-text-stroke: 1px #000)) {
  .hero__title span:last-child { color: var(--tan); }
}

.hero__ja {
  font-size: var(--fs-lg);
  font-weight: 500;
  letter-spacing: 0.28em;
  color: var(--paper-dim);
  margin-bottom: var(--sp-5);
  width: fit-content;
}

.hero__claim {
  font-family: var(--f-quote);
  font-style: italic;
  font-size: var(--fs-md);
  color: var(--acid);
  border-left: 3px solid var(--acid);
  padding-left: var(--sp-4);
  margin-bottom: var(--sp-5);
  max-width: 34ch;
}

.hero__tagline {
  max-width: var(--hero-measure, 46ch);
  color: var(--paper-dim);
  margin-bottom: var(--sp-6);
}

.stat-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-bottom: var(--sp-6);
}
.stat-chips li {
  display: flex;
  align-items: baseline;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-4);
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-left: 3px solid var(--teal);
}
.stat-chips__k {
  font-family: var(--f-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--paper-dim);
}
.stat-chips__v {
  font-family: var(--f-display);
  font-size: var(--fs-md);
  color: var(--acid);
}
.stat-chips li:has(.stat-chips__v--zero) { border-left-color: var(--magenta); }
.stat-chips__v--zero { color: var(--magenta-txt); }

.hero__note {
  max-width: 56ch;
  font-size: var(--fs-sm);
  color: var(--paper-dim);
  border-top: 1px solid var(--line);
  padding-top: var(--sp-4);
}

/* Below 48rem the copy fills the hero, so there is no honest room for the
   portrait as a subject. It drops back to a watermark behind the type —
   measured at 9:1 for the title and 5.1:1 for the tagline over its brightest
   area, both clear of AA. */
@media (max-width: 47.9375rem) {
  .figure {
    width: 21rem;
    right: -5.5rem;
    top: 2rem;
    bottom: auto;
    opacity: 0.2;
  }
  .hero__salt { top: 24rem; bottom: auto; right: 56%; width: 7rem; opacity: 0.4; }
  /* The copy runs the full width here, so the aura and the scrim both have to
     work harder. Sampled: the Japanese name went from 3.46:1 to 5.4:1. */
  .aura--a { opacity: 0.34; }
  .aura--b { opacity: 0.26; }
  .hero__art::after {
    background:
      linear-gradient(180deg, rgba(12,12,17,0.66) 0%, rgba(12,12,17,0.46) 40%,
                              rgba(12,12,17,0.34) 72%, rgba(12,12,17,0.52) 100%),
      linear-gradient(90deg, rgba(12,12,17,0.5) 0%, rgba(12,12,17,0.28) 62%,
                             rgba(12,12,17,0.18) 100%);
  }
}

/* Below the wide breakpoint the portrait sits directly behind this fine print
   and dropped it under AA (measured 3.35:1 at 320px). A solid backdrop takes
   the art out from behind the text entirely. */
@media (max-width: 47.9375rem) {
  .hero__note {
    position: relative;
    z-index: 1;
    /* Solid behind every glyph, fading only across the bottom padding so the
       backdrop's edge doesn't slice visibly through the figure behind it. */
    background: linear-gradient(
      to bottom,
      var(--ink) 0,
      var(--ink) calc(100% - var(--sp-3)),
      rgba(12, 12, 17, 0) 100%
    );
    padding-bottom: var(--sp-3);
  }
}

/* Sits over the teal aura, which pushed 10px mute text to 3.1:1. A scrim that
   fades out to the right takes the glow out from behind the glyphs. */
.scroll-cue {
  position: absolute;
  left: 0;
  bottom: var(--sp-4);
  padding: var(--sp-1) 4rem var(--sp-1) var(--pad);
  background: linear-gradient(90deg, rgba(12,12,17,0.92) 0%, rgba(12,12,17,0.9) 55%, rgba(12,12,17,0) 100%);
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  font-family: var(--f-mono);
  font-size: 0.625rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--paper-mute);
}
.scroll-cue span {
  width: 2.5rem;
  height: 1px;
  background: var(--paper-mute);
  animation: cue 2.4s var(--ease) infinite;
  transform-origin: left center;
}
@keyframes cue {
  0%, 100% { transform: scaleX(0.4); opacity: 0.4; }
  50%      { transform: scaleX(1);   opacity: 1; }
}

/* ------------------------- SALT-SPLASH RULE ---------------------------- */
/* Hand-placed dot field standing in for a thrown handful of salt. */
.salt-rule {
  height: 3.5rem;
  background-repeat: no-repeat;
  background-color: transparent;
  background-image:
    radial-gradient(circle at 4%  60%, var(--tan) 0 2.6px, transparent 2.7px),
    radial-gradient(circle at 9%  35%, var(--tan) 0 1.6px, transparent 1.7px),
    radial-gradient(circle at 14% 72%, var(--tan) 0 2.1px, transparent 2.2px),
    radial-gradient(circle at 20% 44%, var(--paper-dim) 0 1.2px, transparent 1.3px),
    radial-gradient(circle at 26% 66%, var(--tan) 0 2.8px, transparent 2.9px),
    radial-gradient(circle at 32% 30%, var(--tan) 0 1.4px, transparent 1.5px),
    radial-gradient(circle at 38% 58%, var(--paper-dim) 0 2px, transparent 2.1px),
    radial-gradient(circle at 44% 76%, var(--tan) 0 1.3px, transparent 1.4px),
    radial-gradient(circle at 50% 40%, var(--tan) 0 2.4px, transparent 2.5px),
    radial-gradient(circle at 56% 64%, var(--paper-dim) 0 1.5px, transparent 1.6px),
    radial-gradient(circle at 62% 32%, var(--tan) 0 2.2px, transparent 2.3px),
    radial-gradient(circle at 68% 70%, var(--tan) 0 1.7px, transparent 1.8px),
    radial-gradient(circle at 74% 48%, var(--paper-dim) 0 2.6px, transparent 2.7px),
    radial-gradient(circle at 80% 26%, var(--tan) 0 1.2px, transparent 1.3px),
    radial-gradient(circle at 86% 62%, var(--tan) 0 2px, transparent 2.1px),
    radial-gradient(circle at 92% 38%, var(--paper-dim) 0 1.6px, transparent 1.7px),
    radial-gradient(circle at 97% 68%, var(--tan) 0 2.3px, transparent 2.4px);
  opacity: 0.6;
}

/* The photographic salt band that used to sit behind this rule is gone. Its
   asset had been made "seamless" by mirroring the whole frame, which folded the
   rim of the salt jar into a four-way kaleidoscope. soft-light hid that; once
   the blend actually rendered it read as repeating ornament, not as salt, and
   no crop of the surviving 520px derivative tiles without either that pattern
   or a visible seam. The hand-placed dot field above already tells the story in
   pure CSS, so the 28 KB photograph was deleted rather than left invisible. */

/* ----------------------------- SECTIONS -------------------------------- */
.section {
  max-width: var(--wrap);
  margin-inline: auto;
  padding: var(--sp-9) var(--pad);
  scroll-margin-top: calc(var(--header-h) + 1rem);
}

/* Full-bleed variant: the section paints edge to edge while its children stay
   on the same measure as every other section. A single centred grid column
   does the work, so children narrower than the wrapper still align left
   instead of drifting to the middle of the page. */
.section--bleed {
  max-width: none;
  display: grid;
  grid-template-columns: minmax(0, var(--wrap));
  justify-content: center;
}

.section__head { margin-bottom: var(--sp-7); max-width: var(--measure); }
.section__num {
  font-family: var(--f-display);
  font-size: var(--fs-md);
  color: var(--magenta-txt);
  letter-spacing: 0.06em;
  margin-bottom: var(--sp-2);
}
.section h2 {
  font-family: var(--f-display);
  font-size: var(--fs-2xl);
  text-transform: uppercase;
  letter-spacing: -0.025em;
  line-height: 0.95;
}
.section__lede {
  margin-top: var(--sp-4);
  font-size: var(--fs-md);
  color: var(--paper-dim);
}

.fine-print {
  margin-top: var(--sp-4);
  font-family: var(--f-mono);
  font-size: var(--fs-xs);
  line-height: 1.7;
  color: var(--paper-mute);
}
.fine-print--wide { max-width: var(--measure); margin-top: var(--sp-6); }

@media (min-width: 56rem) {
  .section__head { display: grid; grid-template-columns: 4rem 1fr; column-gap: var(--sp-5); max-width: none; }
  .section__num { grid-row: 1 / span 2; margin: 0; padding-top: 0.35em; }
  .section__lede { max-width: var(--measure); }
}

/* --------------------------- PROFILE TABLE ----------------------------- */
.table-scroll {
  overflow-x: auto;
  border: 1px solid var(--line);
  background: var(--ink-2);
}

.data-table { width: 100%; font-size: var(--fs-sm); }
.data-table td { color: var(--paper); }
.data-table th {
  font-family: var(--f-mono);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--paper-mute);
  text-align: left;
}
.t-ja { color: var(--tan); letter-spacing: 0.12em; margin-left: 0.4em; white-space: nowrap; }
/* Marks a value the sources disagree on, in words as well as in style. */
.t-note { color: var(--magenta-txt); font-family: var(--f-mono); font-size: var(--fs-xs); }

/* Narrow screens: label above value, one block per row. Reads far better at
   320px than a horizontally scrolling grid. ARIA roles in the markup keep the
   table semantics intact. */
@media (max-width: 43.999rem) {
  .data-table tr { display: block; padding: var(--sp-4) var(--sp-4); }
  .data-table tr + tr { border-top: 1px solid var(--line); }
  .data-table th,
  .data-table td { display: block; padding: 0; }
  .data-table th { margin-bottom: var(--sp-1); }
}

@media (min-width: 44rem) {
  .data-table th,
  .data-table td { padding: var(--sp-4) var(--sp-5); vertical-align: top; }
  .data-table th { width: 32%; white-space: nowrap; }
  .data-table tr + tr th,
  .data-table tr + tr td { border-top: 1px solid var(--line); }
  .data-table tbody tr:hover td { background: var(--ink-3); }
}

/* ------------------------------ PROSE ---------------------------------- */
.section--who {
  border-top: 1px solid var(--line);
  --tex-op: 0.26;
}

.prose { max-width: var(--measure); font-size: var(--fs-md); }
.prose p + p { margin-top: var(--sp-5); }
.prose em { color: var(--acid); font-style: italic; }

.prose__drop::first-letter {
  float: left;
  font-family: var(--f-display);
  font-size: 3.6em;
  line-height: 0.78;
  padding: 0.06em 0.12em 0 0;
  color: var(--magenta-txt);
}

.pull {
  margin-top: var(--sp-6);
  padding: var(--sp-5) 0 var(--sp-5) var(--sp-5);
  border-left: 3px solid var(--teal);
  font-family: var(--f-quote);
  font-style: italic;
  font-size: var(--fs-lg);
  line-height: 1.35;
  color: var(--paper);
}

/* ---------------------------- ORIGIN STORY ----------------------------- */
/* The shabby rented room the business started in: a raised surface, and the
   heaviest grain on the page bar the full-bleed prose sections. */
.section--origin {
  background: var(--ink-2);
  border-block: 1px solid var(--line);
  --tex-op: 0.20;
}
.section--origin .pull { border-left-color: var(--tan); }

.origin { display: grid; gap: var(--sp-6); }
@media (min-width: 62rem) {
  .origin { grid-template-columns: minmax(0, 1fr) 17rem; gap: var(--sp-8); align-items: start; }
}

/* Door plate for the office. Original CSS, no photograph. */
.plaque {
  position: relative;
  padding: var(--sp-6) var(--sp-5);
  background:
    linear-gradient(150deg, rgba(217,180,131,0.14), rgba(217,180,131,0.03) 60%),
    var(--ink-3);
  border: 1px solid var(--tan-dark);
  box-shadow: inset 0 0 0 1px rgba(12,12,17,0.8), 0 14px 30px -18px rgba(0,0,0,0.9);
  text-align: center;
}
/* Two screw heads, because it is screwed to a door. */
.plaque::before,
.plaque::after {
  content: "";
  position: absolute;
  top: var(--sp-3);
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--tan-dark);
  opacity: 0.7;
}
.plaque::before { left: var(--sp-3); }
.plaque::after  { right: var(--sp-3); }

.plaque__mark {
  display: block;
  font-size: 1.75rem;
  line-height: 1;
  color: var(--tan);
  margin-bottom: var(--sp-3);
}
.plaque__name {
  font-family: var(--f-display);
  font-size: var(--fs-sm);
  line-height: 1.35;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--paper);
  overflow-wrap: normal;
}
.plaque__meta {
  margin-top: var(--sp-4);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--tan-dark);
  font-family: var(--f-mono);
  font-size: var(--fs-xs);
  line-height: 1.6;
  color: var(--paper-dim);
}

/* ----------------------------- TRAITS ---------------------------------- */
.trait-grid {
  display: grid;
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
}
@media (min-width: 40rem) { .trait-grid { grid-template-columns: 1fr 1fr; } }
@media (min-width: 64rem) { .trait-grid { grid-template-columns: repeat(3, 1fr); } }

.trait {
  position: relative;
  background: var(--ink-2);
  padding: var(--sp-5);
  transition: background var(--dur) var(--ease);
}
.trait::after {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: var(--magenta);
  transform: scaleY(0);
  transform-origin: 50% 0;
  transition: transform var(--dur) var(--ease);
}
.trait:hover { background: var(--ink-3); }
.trait:hover::after { transform: scaleY(1); }
.trait h3 {
  font-size: var(--fs-md);
  margin-bottom: var(--sp-3);
  color: var(--tan);
}
.trait p { font-size: var(--fs-sm); color: var(--paper-dim); }

/* ------------------------------ THE LOOK ------------------------------- */
.section--look {
  background:
    linear-gradient(90deg, rgba(107,70,48,0.16) 0%, rgba(12,12,17,0) 42%,
                           rgba(12,12,17,0) 58%, rgba(239,95,150,0.14) 100%),
    var(--ink);
  border-block: 1px solid var(--line);
}

.compare { display: grid; gap: var(--sp-5); }
@media (min-width: 54rem) {
  .compare { grid-template-columns: 1fr auto 1fr; align-items: stretch; gap: var(--sp-6); }
}

.ver {
  display: flex;
  flex-direction: column;
  padding: var(--sp-5);
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-top: 4px solid var(--ver-accent, var(--line-2));
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.ver:hover { background: var(--ink-3); }

.ver--manga {
  --ver-accent: #a8714c;
  --fig-hair: #5f3d28;
  --fig-hair-2: #7d5438;
  --fig-tie: #1b1b22;
  --fig-tie-2: #101015;
}
.ver--anime {
  --ver-accent: var(--magenta);
  --fig-hair: #cf8b48;
  --fig-hair-2: #ecb677;
  --fig-tie: #ef5f96;
  --fig-tie-2: #cf4278;
}

.ver__tag {
  font-family: var(--f-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ver-accent);
  margin-bottom: var(--sp-4);
}

.ver__art {
  display: grid;
  place-items: center;
  height: 12rem;
  margin-bottom: var(--sp-5);
  background:
    radial-gradient(9rem 7rem at 50% 42%, color-mix(in srgb, var(--ver-accent) 22%, transparent), transparent 70%),
    var(--ink);
  border: 1px solid var(--line);
  overflow: hidden;
}
@media (min-width: 54rem) { .ver__art { height: 16rem; } }

/* The svg viewBox crops to head-and-tie: the hair colour and the tie colour
   are the whole point of this section. */
.ver__figure {
  width: auto;
  height: 104%;
  max-width: none;
  transition: translate var(--dur) var(--ease);
}
.ver__figure--flip { scale: -1 1; }
.ver:hover .ver__figure { translate: 0 -3%; }

.ver h3 { font-size: var(--fs-md); margin-bottom: var(--sp-4); }

.swatches { display: grid; gap: var(--sp-2); margin-bottom: var(--sp-4); }
.swatches li {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  font-family: var(--f-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--paper-dim);
}
/* The chip is a second cue only — every swatch is also named in words. */
.sw {
  flex: none;
  width: 1.5rem; height: 1.5rem;
  background: var(--sw);
  border: 1px solid var(--line-2);
}

.ver__note { font-size: var(--fs-sm); color: var(--paper-dim); margin-top: auto; }

.compare__vs {
  display: grid;
  place-items: center;
  font-family: var(--f-display);
  font-size: var(--fs-md);
  text-transform: uppercase;
  color: var(--paper-mute);
}
.compare__vs span {
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  background: var(--ink);
}
@media (min-width: 54rem) {
  .compare__vs { position: relative; width: 3.5rem; }
  .compare__vs::before {
    content: "";
    position: absolute;
    top: 0; bottom: 0; left: 50%;
    width: 1px;
    background: linear-gradient(180deg, transparent, var(--line-2), transparent);
  }
  .compare__vs span { position: relative; }
}

.shared {
  margin-top: var(--sp-6);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--line);
}
.shared h3 {
  font-family: var(--f-mono);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--acid);
  margin-bottom: var(--sp-4);
}
.tag-list { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
.tag-list li {
  padding: var(--sp-2) var(--sp-4);
  border: 1px dashed var(--line-2);
  font-size: var(--fs-sm);
  color: var(--paper-dim);
}

/* --------------------------- ABILITIES SPLIT --------------------------- */
.split { display: grid; gap: var(--sp-5); }
@media (min-width: 58rem) { .split { grid-template-columns: 1fr 1fr; gap: var(--sp-6); } }

.panel {
  padding: var(--sp-5);
  border: 1px solid var(--line);
  background: var(--ink-2);
}
.panel--real { border-top: 4px solid var(--teal); }
.panel--fake {
  border-top: 4px solid var(--magenta);
  /* The page's tightest contrast case (small magenta headings on a raised
     surface), so this panel runs the grain lower than the full-bleed sections. */
  --tex-op: 0.17;
}

.panel__tag {
  font-family: var(--f-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  margin-bottom: var(--sp-2);
}
.panel--real .panel__tag { color: var(--teal); }
.panel--fake .panel__tag { color: var(--magenta-txt); }

.panel__title {
  font-family: var(--f-display);
  font-size: var(--fs-lg);
  text-transform: uppercase;
  margin-bottom: var(--sp-5);
}
.panel__intro { font-size: var(--fs-sm); color: var(--paper-dim); margin-bottom: var(--sp-5); }

.skill-list li + li { margin-top: var(--sp-5); }
.skill-list__note { margin-top: var(--sp-2); font-size: var(--fs-sm); color: var(--paper-mute); }

/* "100%"-style segmented meter */
.meter__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2);
  margin-bottom: var(--sp-2);
}
.meter__label { font-weight: 600; font-size: var(--fs-sm); }
.meter__val {
  font-family: var(--f-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--teal);
}
.meter--zero .meter__val { color: var(--magenta-txt); }

.meter__track {
  position: relative;
  display: block;
  height: 0.75rem;
  background: var(--ink);
  border: 1px solid var(--line-2);
  overflow: hidden;
}
.meter__fill {
  display: block;
  height: 100%;
  width: var(--pct, 0%);
  background-image:
    repeating-linear-gradient(90deg, var(--teal) 0 8px, transparent 8px 11px);
  background-size: 11px 100%;
  transform-origin: left center;
}
.meter--zero .meter__fill { background-image: none; }
/* Empty-state hatching so the 0% bar still reads as intentional. */
.meter--zero .meter__track {
  border-color: var(--magenta);
  background-image: repeating-linear-gradient(135deg, rgba(255,61,127,0.28) 0 4px, transparent 4px 9px);
}

.punchline {
  margin-top: var(--sp-7);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--line);
  font-family: var(--f-display);
  font-size: var(--fs-lg);
  line-height: 1.2;
  text-transform: uppercase;
  max-width: 40ch;
}
.punchline::first-line { color: var(--magenta-txt); }

/* -------------------------- FAKE TECHNIQUES ---------------------------- */
.tech-list { display: grid; gap: 1px; background: var(--line); border: 1px solid var(--line); }
.tech {
  position: relative;
  background: var(--ink-3);
  padding: var(--sp-5) var(--sp-5) var(--sp-5) 4.25rem;
  transition: background var(--dur) var(--ease);
}
.tech:hover { background: #24242f; }
.tech__icon {
  position: absolute;
  left: var(--sp-3);
  top: calc(var(--sp-5) - 0.1rem);
  width: 2.75rem;
  height: 1.75rem;
  color: var(--tan);
  transition: color var(--dur) var(--ease), rotate var(--dur) var(--ease);
}
.tech:hover .tech__icon { color: var(--acid); rotate: -6deg; }
.tech h4 {
  font-size: var(--fs-md);
  margin-bottom: var(--sp-2);
  color: var(--magenta-txt);
}
.tech p { font-size: var(--fs-sm); color: var(--paper-dim); }

/* ------------------------------ QUOTES --------------------------------- */
/* The emotional core of the page: aged paper, serif at scale, generous air. */
.section--quotes {
  border-block: 1px solid var(--line);
  background-color: var(--ink);
  background-image:
    radial-gradient(60rem 40rem at 85% 0%, rgba(23,214,198,0.10), transparent 70%),
    radial-gradient(50rem 34rem at 0% 100%, rgba(255,61,127,0.10), transparent 70%);
  --tex-op: 0.24;
}

.quote-stack { display: grid; gap: var(--sp-5); }
@media (min-width: 52rem) {
  .quote-stack { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-6); }
  .quote--lead,
  .quote--short { grid-column: 1 / -1; }
}

.quote {
  position: relative;
  padding: var(--sp-7) var(--sp-5) var(--sp-6);
  background: linear-gradient(180deg, rgba(29,29,40,0.9), rgba(20,20,28,0.9));
  border: 1px solid var(--line);
  transition:
    border-color var(--dur) var(--ease),
    background-color var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease);
}
/* Hairline corner marks — a printed-page register mark, not a border. */
.quote::before,
.quote::after {
  content: "";
  position: absolute;
  width: 1.25rem; height: 1.25rem;
  border: 1px solid var(--tan-dark);
  opacity: 0.45;
  transition: opacity var(--dur) var(--ease);
}
.quote::before { top: 6px; left: 6px; border-width: 1px 0 0 1px; }
.quote::after { bottom: 6px; right: 6px; border-width: 0 1px 1px 0; }
.quote:hover {
  border-color: var(--tan-dark);
  box-shadow: 0 18px 40px -28px rgba(0,0,0,0.9);
}
.quote:hover::before,
.quote:hover::after { opacity: 1; }

.quote__glyph {
  position: absolute;
  top: 0;
  left: var(--sp-5);
  translate: 0 -50%;
  width: 2.4rem;
  height: 1.9rem;
  color: var(--magenta-txt);
  background: var(--ink-3);
  padding-inline: var(--sp-3);
  box-sizing: content-box;
  transition: color var(--dur) var(--ease);
}
.quote:hover .quote__glyph { color: var(--acid); }

.quote blockquote p {
  font-family: var(--f-quote);
  font-size: var(--fs-md);
  font-style: italic;
  line-height: 1.5;
  color: var(--paper);
}
.quote--lead { padding-block: var(--sp-8) var(--sp-7); }
.quote--lead blockquote p {
  font-size: var(--fs-lg);
  line-height: 1.4;
  max-width: 46ch;
}
/* Two lines that say the same thing, years apart. Marked as a matched pair. */
.quote--pair { border-top: 3px solid var(--teal); }
.quote--short {
  padding-block: var(--sp-8) var(--sp-7);
  text-align: center;
  background: var(--ink);
}
.quote--short .quote__glyph { left: 50%; translate: -50% -50%; background: var(--ink); }
.quote--short blockquote p {
  font-size: var(--fs-xl);
  font-style: normal;
  line-height: 1.25;
  color: var(--acid);
  max-width: 24ch;
  margin-inline: auto;
}

/* --------------------------- RELATIONSHIPS ----------------------------- */
.rel-list { display: grid; gap: var(--sp-4); }
@media (min-width: 44rem) { .rel-list { grid-template-columns: 1fr 1fr; } }
@media (min-width: 66rem) { .rel-list { grid-template-columns: repeat(3, 1fr); } }

.rel {
  padding: var(--sp-5);
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-left: 3px solid var(--line-2);
  transition: border-left-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.rel:hover { border-left-color: var(--teal); background: var(--ink-3); }
.rel--primary { border-left-color: var(--magenta); }
@media (min-width: 44rem) { .rel--primary { grid-column: 1 / -1; } }

.rel__role {
  font-family: var(--f-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--paper-mute);
  margin-bottom: var(--sp-2);
}
.rel h3 { font-size: var(--fs-md); margin-bottom: var(--sp-3); }
.rel--primary h3 { font-size: var(--fs-lg); }
.rel__alt {
  display: block;
  font-family: var(--f-body);
  font-size: var(--fs-sm);
  font-weight: 400;
  letter-spacing: 0;
  color: var(--tan);
  margin-top: var(--sp-1);
}
.rel p:last-child { font-size: var(--fs-sm); color: var(--paper-dim); }

/* ------------------------------- ARCS ---------------------------------- */
/* Night city behind the arc where he loses everything. Two layers: the photo,
   feathered top and bottom, then a scrim that guarantees text contrast. */
.section--arcs {
  border-top: 1px solid var(--line);
  background-color: var(--ink);
  --tex-img: var(--tex-city);
  --tex-pos: 50% 100%;
  --tex-op: 0.62;
  --tex-blend: normal;
  --tex-filter: saturate(0.5) brightness(0.78) contrast(1.05);
}
.section--arcs::before {
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 22%, #000 72%, transparent);
  mask-image: linear-gradient(180deg, transparent, #000 22%, #000 72%, transparent);
}
.section--arcs::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(12,12,17,0.70) 0%, rgba(12,12,17,0.55) 42%, rgba(12,12,17,0.88) 100%);
}
/* No background-attachment: fixed here. It repaints the whole section every
   frame — measured 4 dropped frames and a 79ms worst frame across a scroll of
   this section, versus none with scroll attachment — for a parallax effect
   subtle enough that nobody misses it. */

.timeline { position: relative; display: grid; gap: var(--sp-4); padding-left: var(--sp-5); }
.timeline::before {
  content: "";
  position: absolute;
  left: 3px; top: 0.75rem; bottom: 0.75rem;
  width: 1px;
  background: linear-gradient(180deg, var(--magenta), var(--teal));
  opacity: 0.6;
}

.arc { position: relative; }
.arc::before {
  content: "";
  position: absolute;
  left: calc(var(--sp-5) * -1);
  top: 0.7rem;
  width: 7px; height: 7px;
  background: var(--teal);
  border-radius: 50%;
}
.arc--spoiler::before { background: var(--magenta); }

.arc__when {
  font-family: var(--f-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--teal);
  margin-bottom: var(--sp-2);
}
.arc--spoiler .arc__when { color: var(--magenta-txt); }
.arc h3 { font-size: var(--fs-lg); margin-bottom: var(--sp-3); }
.arc > p:last-child,
.spoiler__body p { max-width: var(--measure); color: var(--paper-dim); }
.spoiler__body p + p { margin-top: var(--sp-4); }
.spoiler__body em { color: var(--acid); font-style: italic; }

/* Spoiler disclosure */
.spoiler { border: 1px dashed var(--line-2); background: rgba(20,20,28,0.88); }
.spoiler[open] { border-style: solid; border-color: var(--line); }

.spoiler > summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  min-height: 44px;
  cursor: pointer;
  list-style: none;
  transition: background var(--dur-fast) var(--ease);
}
.spoiler > summary::-webkit-details-marker { display: none; }
.spoiler > summary:hover { background: var(--ink-3); }

.spoiler__badge {
  flex: none;
  padding: 0.2rem var(--sp-3);
  background: var(--magenta);
  color: var(--ink);
  font-family: var(--f-mono);
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.spoiler__label {
  font-family: var(--f-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--paper-dim);
}
.spoiler > summary::after {
  content: "reveal";
  margin-left: auto;
  font-family: var(--f-mono);
  font-size: 0.625rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--acid);
}
.spoiler[open] > summary::after { content: "hide"; }

.spoiler__body { padding: 0 var(--sp-5) var(--sp-5); border-top: 1px solid var(--line); padding-top: var(--sp-5); }

/* -------------------------- BEYOND THE SERIES -------------------------- */
.section--beyond {
  --tex-op: 0.26;
}

.notes { display: grid; gap: var(--sp-4); counter-reset: note; }
@media (min-width: 60rem) { .notes { grid-template-columns: repeat(3, 1fr); } }

.note {
  position: relative;
  padding: var(--sp-6) var(--sp-5) var(--sp-5);
  background: var(--ink-2);
  border: 1px solid var(--line);
  counter-increment: note;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.note::before {
  content: counter(note, decimal-leading-zero);
  position: absolute;
  top: var(--sp-3);
  right: var(--sp-4);
  font-family: var(--f-display);
  font-size: var(--fs-lg);
  line-height: 1;
  color: var(--line-2);
  transition: color var(--dur) var(--ease);
}
.note:hover { background: var(--ink-3); border-color: var(--line-2); }
.note:hover::before { color: var(--tan-dark); }
.note__tag {
  font-family: var(--f-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--acid);
  margin-bottom: var(--sp-3);
}
.note h3 { font-size: var(--fs-md); margin-bottom: var(--sp-3); color: var(--tan); max-width: 22ch; }
.note p { font-size: var(--fs-sm); color: var(--paper-dim); }

/* ------------------------------ FOOTER --------------------------------- */
.site-footer {
  border-top: 1px solid var(--line);
  background-color: var(--ink-2);
  --tex-op: 0.18;
}
.site-footer__inner {
  max-width: var(--wrap);
  margin-inline: auto;
  padding: var(--sp-8) var(--pad) var(--sp-7);
  display: grid;
  gap: var(--sp-7);
}
@media (min-width: 56rem) {
  /* Sources is the tallest block, so it takes the full-height column and the
     two shorter blocks stack beside it. Keeps the footer from ending in a
     large empty quarter. */
  .site-footer__inner { grid-template-columns: 1.05fr 1fr; gap: var(--sp-7) var(--sp-8); align-items: start; }
  .disclaimer { grid-column: 1; grid-row: 1; }
  .credits    { grid-column: 1; grid-row: 2; }
  .sources    { grid-column: 2; grid-row: 1 / span 2; }
}

.site-footer h2 {
  font-family: var(--f-mono);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--acid);
  margin-bottom: var(--sp-4);
}
.disclaimer p { font-size: var(--fs-sm); color: var(--paper-dim); max-width: 60ch; }
.disclaimer p + p { margin-top: var(--sp-3); }
.disclaimer strong { color: var(--paper); }

.sources__intro { font-size: var(--fs-sm); color: var(--paper-mute); margin-bottom: var(--sp-3); }
.sources ul { display: grid; }
.sources li { font-size: var(--fs-sm); padding-left: var(--sp-4); position: relative; }
/* Padded to keep each link's tap target at least 24px tall. */
.sources a { display: inline-block; padding-block: var(--sp-2); }
.sources li::before {
  content: "";
  position: absolute;
  /* Link padding-top plus half the 1.6 line-height, so the dash centres on the
     first text line at any font size rather than at a fixed offset. */
  left: 0; top: calc(var(--sp-2) + 0.8em);
  width: 5px; height: 1px;
  background: var(--paper-mute);
}

/* Image credits: one texture per row, subject first so the list scans. */
.credits ul { display: grid; gap: var(--sp-3); }
.credits li {
  display: grid;
  gap: var(--sp-1);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--line);
  font-size: var(--fs-xs);
  line-height: 1.7;
}
.credits__what {
  font-family: var(--f-mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--tan);
}
.credits__who { color: var(--paper-mute); }
.credits a { display: inline-block; padding-block: 2px; }

.site-footer__base {
  max-width: var(--wrap);
  margin-inline: auto;
  padding: var(--sp-4) var(--pad) var(--sp-6);
  border-top: 1px solid var(--line);
  font-family: var(--f-mono);
  font-size: var(--fs-xs);
  color: var(--paper-mute);
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-3);
  align-items: center;
}
.site-footer__base > span:first-child { color: var(--magenta-txt); }

/* --------------------------- SCROLL REVEAL ----------------------------- */
/* Hidden state applies ONLY when JS is running (html.js) — a no-JS visitor
   and any browser that never fires the observer sees fully visible content. */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition:
    opacity var(--dur-reveal) var(--ease),
    transform var(--dur-reveal) var(--ease);
  transition-delay: var(--reveal-delay, 0ms);
}
.js [data-reveal].is-revealed { opacity: 1; transform: none; }

.js [data-reveal] .meter__fill {
  transform: scaleX(0);
  transition: transform 900ms var(--ease) 180ms;
}
.js [data-reveal].is-revealed .meter__fill { transform: scaleX(1); }

/* --------------------------- REDUCED MOTION ---------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }
  .js [data-reveal] { opacity: 1; transform: none; }
  .js [data-reveal] .meter__fill,
  .js [data-reveal].is-revealed .meter__fill { transform: none; }
  .scroll-cue span { animation: none; transform: none; opacity: 0.7; }
  /* The bar is driven by a scroll timeline, which the duration override above
     would break. Decorative, so it simply goes away. */
  .scroll-progress { display: none; }
  .trait::after { transform: scaleY(1); opacity: 0; }
  .trait:hover::after { opacity: 1; }
  .ver:hover .ver__figure { translate: none; }
  .tech:hover .tech__icon { rotate: none; }
}

/* ------------------------------ PRINT ---------------------------------- */
@media print {
  body { background: #fff; color: #000; }
  body::after, .hero__art, .site-nav, .scroll-cue, .salt-rule,
  .scroll-progress, .ver__art { display: none; }
  .tex::before, .section--arcs::after { display: none; }
  .js [data-reveal] { opacity: 1 !important; transform: none !important; }
  a { color: #000; }
}
