/* ============================================================================
   BASE — tokens, reset, typography, layout primitives.
   Loaded on every page. The world itself lives in seal.css; the manuscript
   typesetting lives in paper.css and loads only on the two paper pages.
   ========================================================================= */

:root {
  /* --- The field ------------------------------------------------------
     Cinnabar is 印泥, seal paste. It is a ground, not an accent: it owns
     whole regions. Every value below was chosen by computing the relative
     luminance ratio, not by eye — the three that look right (a lighter red,
     a 0.86 bone, a darker red rule) measure 4.90, 4.47 and 1.19 and fail. */
  --cinnabar: #B22D22;        /* the field.            bone on it = 5.55:1 */
  --cinnabar-lift: #C9412F;   /* hover / raised */
  --cinnabar-press: #8E2118;  /* pressed */
  --indigo: #1B3B5A;          /* second register — the economics half */
  --indigo-press: #12293F;
  --ink: #14151A;             /* type on bone.         on bone   = 15.84:1 */
  --bone: #F1EFE8;            /* the document panel.   on cinnabar = 5.55:1 */
  --bone-dim: #E5E1D7;        /* secondary panel, table stripe */
  --bone-lift: #FFFDF7;       /* hover only. Pure white is a fourth neutral
                                 nobody chose, and reads cold against cinnabar. */

  /* Quiet tones. 0.66 over bone measures 5.6:1; the obvious 0.55 measures
     3.9 and is unreadable for anyone who needs the contrast. On cinnabar
     nothing below 0.90 clears 4.5, so body-size text there is never tinted. */
  --ink-quiet: rgba(20, 21, 26, 0.66);
  --ink-faint: rgba(20, 21, 26, 0.42);   /* rules only, never text */
  --bone-quiet: rgba(241, 239, 232, 0.90);
  --bone-faint: rgba(241, 239, 232, 0.28); /* hairlines on cinnabar */

  /* --- Type -----------------------------------------------------------
     Archivo carries a width axis, so display type is cut wide to fill its
     square the way a seal character fills its field. Spectral reads two
     full manuscripts. Martian Mono is measurement, never costume. */
  --cjk: "Songti SC", "Noto Serif SC", "Source Han Serif SC", serif;
  --display: "Archivo", "Helvetica Neue", Arial, "Songti SC", sans-serif;
  --text: "Spectral", Georgia, "Songti SC", serif;
  --mono: "Martian Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* The Ideographic Description Characters (U+2FF0-U+2FFB) are drawn as
     inline SVG by tools/build_pages.py rather than set as type. No font in
     any plausible fallback stack carries them — Apple Symbols and Songti were
     both checked against their cmap tables, and the Noto Sans Symbols 2 build
     in google/fonts turns out to lack the block too — so the previous build
     rendered the notation this site is about as tofu boxes. */

  --t-display: clamp(42px, 7.6vw, 96px);
  --t-h1: clamp(32px, 5vw, 56px);
  --t-h2: clamp(25px, 3.2vw, 38px);
  --t-h3: clamp(19px, 2vw, 25px);
  /* One step between h2 and h3, for the objects that rank below a section
     heading but above a run-in: arm titles, entry titles, the primary contact
     value, a manuscript section head. Five slightly different bespoke clamps
     were doing this job, which flattened the hero — the thesis and the arm
     titles ended up 33px against 30px, when the bridge is supposed to
     outrank both. */
  --t-lead: clamp(21px, 2.4vw, 30px);
  --t-body: clamp(17px, 0.4vw + 16px, 19px);
  --t-small: 15.5px;
  --t-label: 10.5px;

  /* Manuscript ramp. A Read surface carries its own smaller scale: a
     twenty-thousand-word paper with tables of numbers cannot be set on the
     display ramp without the tables outgrowing the column. */
  --t-ms: 13.5px;      /* manuscript secondary: contents, tables, references */
  --t-ms-sm: 13px;     /* equations, figure captions, footnotes */
  --t-data: 12px;      /* tabular figures */

  /* --- Space — one rhythm, used everywhere -------------------------- */
  --s1: 6px;  --s2: 12px; --s3: 20px; --s4: 32px;
  --s5: 52px; --s6: 84px; --s7: 128px;

  --shell: 1180px;
  --measure: 68ch;
  --gutter: clamp(20px, 5vw, 56px);

  /* Stamps land: fast down, no bounce. */
  --press: cubic-bezier(0.18, 0.9, 0.28, 1);

  /* A ring that survives both grounds: the bone stop reads on cinnabar,
     the ink stop reads on bone, so one declaration works everywhere. */
  --ring: 0 0 0 2px var(--bone), 0 0 0 5px var(--ink);
}

/* --- Reset ------------------------------------------------------------ */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Every in-page target clears the stamped header band. */
  scroll-padding-top: 96px;
}

body {
  margin: 0;
  background: var(--cinnabar);
  color: var(--bone);
  font-family: var(--text);
  font-size: var(--t-body);
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img, svg { max-width: 100%; }
img { height: auto; display: block; }

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

button { font: inherit; color: inherit; background: none; border: 0; }

/* --- Focus ------------------------------------------------------------ */

:focus-visible {
  outline: none;
  box-shadow: var(--ring);
  border-radius: 1px;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--ink);
  color: var(--bone);
  padding: 14px 22px;
  font-family: var(--mono);
  font-size: var(--t-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
}
.skip:focus { left: var(--gutter); top: 10px; }

/* --- Type primitives -------------------------------------------------- */

.display,
.h1, .h2, .h3 {
  font-family: var(--display);
  font-weight: 800;
  font-variation-settings: "wdth" 112;
  line-height: 0.98;
  letter-spacing: -0.022em;
  text-wrap: balance;
}

.display { font-size: var(--t-display); font-weight: 900; font-variation-settings: "wdth" 118; }
.h1 { font-size: var(--t-h1); }
.h2 { font-size: var(--t-h2); line-height: 1.04; }
.h3 {
  font-size: var(--t-h3);
  font-weight: 700;
  font-variation-settings: "wdth" 100;
  line-height: 1.16;
  letter-spacing: -0.01em;
}

/* The label is measurement: a figure number, a status, a date, a source.
   It is not applied to every section as decoration. */
.label {
  font-family: var(--mono);
  font-size: var(--t-label);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  line-height: 1.4;
  font-variation-settings: "wdth" 87;
}

.lede {
  font-size: clamp(19px, 1.5vw + 14px, 25px);
  line-height: 1.46;
  max-width: 34ch;
  text-wrap: pretty;
}

.prose { max-width: var(--measure); text-wrap: pretty; }
.prose + .prose { margin-top: var(--s3); }

.note {
  font-size: var(--t-small);
  line-height: 1.55;
  color: var(--ink-quiet);
  max-width: 62ch;
}

em { font-style: italic; }
b, strong { font-weight: 700; }

/* An Ideographic Description Character, drawn rather than set. Sized in em so
   it tracks whatever it sits in, from 10px table cells to 30px prose. */
.idc {
  display: inline-block;
  width: 0.8em;
  height: 0.8em;
  vertical-align: -0.055em;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.15;
  stroke-linecap: square;
}

/* --- Links ------------------------------------------------------------ */

a { color: inherit; }

/* Cinnabar is a ground, not an accent. Whole components that happen to be
   links — the entry cards, the 404 register rows — must not inherit link
   colour for their body copy; only genuine inline links do. */
.doc a:not(.btn):not(.entry):not(.register-row) {
  color: var(--cinnabar);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-color: rgba(178, 45, 34, 0.4);
}
.doc a:not(.btn):not(.entry):not(.register-row):hover { text-decoration-color: currentColor; }

/* --- Layout ----------------------------------------------------------- */

.wrap {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.band { padding-block: var(--s6); }
.band--tight { padding-block: var(--s5); }
.band--indigo { background: var(--indigo); }
.band--ink { background: var(--ink); }

/* More space above a heading than below it, everywhere. */
.band > .wrap > * + * { margin-top: var(--s3); }
.band h2 + *, .band h3 + * { margin-top: var(--s3); }
.band > .wrap > .h2 { margin-top: var(--s5); }
.band > .wrap > :first-child { margin-top: 0; }

/* --- Motion ----------------------------------------------------------- */

/* Content is visible by default and JS removes nothing; the stamp entrance
   is added only when motion is allowed, so no-JS and reduced-motion both
   get the finished composition rather than a blank page. */
@media (prefers-reduced-motion: no-preference) {
  .js [data-press] {
    opacity: 0;
    transform: scale(1.055) rotate(var(--press-tilt, -1.1deg));
  }
  .js [data-press].is-pressed {
    opacity: 1;
    transform: none;
    transition:
      opacity 420ms var(--press),
      transform 520ms var(--press);
    transition-delay: var(--press-delay, 0ms);
  }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
