/* Machine Politics: the reading room, not the rally.
   Semantic rules live in DESIGN.md and config/config.py; tokens.css is
   generated from config and must be loaded before this file. */

* { box-sizing: border-box; }

html {
  background: var(--ground);
  color: var(--ink);
  font-family: var(--font-data);
  font-size: 16px;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100vh;
  line-height: 1.55;
}

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

h1, h2, h3, .display {
  font-family: var(--font-display);
  font-weight: 500;
  line-height: 1.15;
  margin: 0 0 0.5em;
  letter-spacing: 0.005em;
}

h1 { font-size: clamp(1.9rem, 4.5vw, 3.1rem); }
h2 { font-size: clamp(1.3rem, 2.6vw, 1.8rem); margin-top: 2.2em; }
h3 { font-size: 1.1rem; margin-top: 1.6em; }

p { max-width: 62ch; }

a {
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

a:hover { text-decoration-thickness: 2px; }

a:focus-visible, button:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
  border-radius: 2px;
}

/* Citations render smaller and softer throughout; the hanging indent
   applies only inside evidence lists, where citations stack */
.citation {
  font-size: 0.82rem;
  color: var(--ink-soft);
  display: block;
  margin-top: 0.35rem;
}

li > .citation {
  padding-left: 1.1rem;
  text-indent: -1.1rem;
}

/* Evidence quotes read in the record's own voice: the serif */
.signal .quote {
  font-family: var(--font-display);
  font-size: 1.04rem;
}

/* Confidence conventions: hue never changes, treatment does.
   PROVISIONAL takes the same lowered-confidence treatment; its note
   renders as a visible caption wherever the coding renders. */
.conf-INFERRED { text-decoration: underline dotted 1px; text-underline-offset: 0.22em; }
.conf-AMBIGUOUS { text-decoration: underline dotted 1px; text-underline-offset: 0.22em; }
.conf-PROVISIONAL { text-decoration: underline dotted 1px; text-underline-offset: 0.22em; }

/* ------------------------------------------------------------------ */
/* Shell                                                               */
/* ------------------------------------------------------------------ */

.shell {
  max-width: 1100px;
  margin: 0 auto;
  padding: 0 clamp(1rem, 4vw, 2.5rem);
}

/* Ledger masthead: a thick rule over a thin one, like a ruled record book */
header.masthead {
  border-bottom: 2px solid var(--ink);
  box-shadow: 0 5px 0 -4px var(--rule);
  padding: 0.9rem 0 0.8rem;
  margin-bottom: 2rem;
}

.masthead-inner {
  display: flex;
  align-items: baseline;
  gap: 1.6rem;
  flex-wrap: wrap;
}

.wordmark {
  font-family: var(--font-display);
  font-size: 1.3rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}

.masthead-date {
  margin-left: auto;
  font-size: 0.78rem;
  color: var(--ink-soft);
}

@media (max-width: 720px) {
  .masthead-date { display: none; }
}

nav.primary { display: flex; gap: 1.1rem; flex-wrap: wrap; }

@media (max-width: 720px) {
  nav.primary {
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    max-width: 100%;
    padding-bottom: 0.2rem;
  }
  nav.primary::-webkit-scrollbar { display: none; }
  nav.primary a { white-space: nowrap; }
}

nav.primary a {
  font-size: 0.9rem;
  text-decoration: none;
  color: var(--ink-soft);
}

nav.primary a[aria-current="page"] { color: var(--ink); font-weight: 600; }
nav.primary a:hover { color: var(--ink); }

footer.colophon {
  margin-top: 4rem;
  border-top: 1px solid var(--rule);
  padding: 1.4rem 0 2.2rem;
  font-size: 0.85rem;
  color: var(--ink-soft);
}

footer.colophon p { margin: 0.3rem 0; }

.updated-through {
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------------ */
/* Guided tour (scaffold; scroll choreography is enhancement)          */
/* ------------------------------------------------------------------ */

/* The skip link is a designed element visible from first paint,
   never a hidden accessibility afterthought */
.skip-board {
  display: inline-block;
  margin: 1.2rem 0 0;
  font-size: 0.88rem;
  border: 1px solid var(--ink);
  border-radius: 3px;
  padding: 0.35rem 0.9rem;
  text-decoration: none;
}

.skip-board:hover { background: var(--ink); color: var(--ground); }

/* P1c scaffold: beats are a stacked prose column. P2c adds the sticky
   canvas beside them; this layout IS the no-JS and reduced-motion path. */
.tour .beat {
  padding: 3rem 0;
  border-bottom: 1px solid var(--rule-faint);
}

.tour .beat:last-child { border-bottom: none; }

.beat-copy { max-width: 34rem; }

.beat-copy h2 { margin-top: 0; }

.beat-copy p { font-size: 1.05rem; }

/* Citation line under a beat: present and checkable, never louder than the
   narration it supports. */
.beat-copy p.beat-cite {
  font-size: 0.82rem;
  line-height: 1.45;
  color: var(--ink-soft);
  margin-top: 0.75rem;
}

.beat-copy p.beat-cite a { color: inherit; }

@media (max-width: 860px) {
  .tour .beat { padding: 2.2rem 0; }
}

/* Mobile stepper: tap-through beats, one at a time. The display rule on
   .beat outranks the UA [hidden] default, so restate it explicitly. */
.tour .beat[hidden] { display: none; }

.tour-stepper {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.8rem 0 0.4rem;
  font-size: 0.88rem;
}

.tour-stepper button {
  font: inherit;
  background: none;
  border: 1px solid var(--ink);
  border-radius: 3px;
  padding: 0.55rem 1.1rem;
  min-height: 44px;
  cursor: pointer;
  color: var(--ink);
}

.tour-stepper button:disabled {
  border-color: var(--rule);
  color: var(--ink-soft);
  cursor: default;
}

/* ------------------------------------------------------------------ */
/* The persistent canvas (P2c). Server-rendered end state, hidden until
   JS enhances; the sticky stage centers in the viewport (craft
   standard), never hugs the top.                                      */
/* ------------------------------------------------------------------ */

.tour-enhanced .scrolly {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr);
  gap: 3rem;
  align-items: start;
}

.tour-enhanced .beat {
  min-height: 110vh;
  border-bottom: none;
  display: flex;
  align-items: center;
}

.scrolly-canvas {
  position: sticky;
  top: 0;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.8rem;
  min-width: 0;
}

/* display rules on these outrank the UA [hidden] default; restate it */
.scrolly-canvas[hidden],
.c-teach[hidden],
.c-statset[hidden] { display: none; }

.c-teach-slot { min-height: 2.4em; }

.c-teach { margin: 0; font-size: 0.92rem; max-width: none; }

.c-board-wrap { position: relative; }

.c-board {
  position: relative;
  height: 320px;
}

/* Row state is CSS-transition-driven: setBeat writes target transform,
   height, and the c-off class; the browser interpolates. One tempo in
   every direction (neutrality in motion). */
.c-row {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 62px;
  opacity: 0;
  visibility: hidden;
  transition: transform 0.55s ease-in-out, height 0.55s ease-in-out,
    opacity 0.35s linear, visibility 0s 0.35s;
}

.tour-enhanced .c-row:not(.c-off),
.tour-stepped .c-row:not(.c-off) {
  opacity: 1;
  visibility: visible;
  transition: transform 0.55s ease-in-out, height 0.55s ease-in-out,
    opacity 0.35s linear, visibility 0s;
}

.c-board { transition: height 0.55s ease-in-out; }

.c-deadline { transition: opacity 0.4s linear, visibility 0s 0.4s; }

/* The line draws down by clip reveal, so the stroke keeps its dashed
   identity (DrawSVG would rewrite the dash pattern to draw). */
.c-deadline svg {
  clip-path: inset(0 0 100% 0);
  transition: clip-path 0.9s linear;
}

.c-deadline[data-state="faint"] svg,
.c-deadline[data-state="draw"] svg { clip-path: inset(0 0 0 0); }

.c-deadline[data-state="draw"] { opacity: 1; visibility: visible; transition: opacity 0.4s linear, visibility 0s; }

.c-deadline[data-state="faint"] { opacity: 0.15; visibility: visible; transition: opacity 0.4s linear, visibility 0s; }

.c-deadline[data-state="faint"] .c-deadline-label { opacity: 0; }

@media (prefers-reduced-motion: reduce) {
  .c-row, .c-board, .c-deadline, .c-deadline svg, .c-band, .c-seam,
  .c-mark, .c-note, .c-track, .c-label { transition: none; }
}

.c-label {
  position: absolute;
  left: 0;
  top: 2px;
  font-size: 0.88rem;
  font-weight: 600;
  white-space: nowrap;
}

/* xl rows reserve a caption line beneath the track so the provisional
   note never runs into the band */
.c-track { position: absolute; left: 0; right: 0; top: 26px; bottom: 38px; }

.c-note {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  margin: 0;
  font-size: 0.7rem;
  line-height: 1.25;
}

/* Mid scale (movers, camps): label as a left column, track beside it,
   so early-starting bands never run under the state name */
#c-board[data-scale="m"] .c-label,
#c-board[data-scale="s"] .c-label {
  top: 50%;
  transform: translateY(-50%);
  font-size: 0.78rem;
  font-weight: 400;
  max-width: 10rem;
  overflow: hidden;
  text-overflow: ellipsis;
}

#c-board[data-scale="m"] .c-track,
#c-board[data-scale="s"] .c-track { left: 10.5rem; top: 0; bottom: 0; }

#c-board[data-scale="s"] .c-label { font-size: 0.68rem; }

/* Poster scale: no labels, full-width tracks, compact marks */
#c-board[data-scale="xs"] .c-label { display: none; }
#c-board[data-scale="xs"] .c-track { left: 0; top: 0; bottom: 0; }
#c-board:not([data-scale="xl"]) .c-note { display: none; }

/* Progressive reveal (P3c): marks appear per beat; color arrives as an
   event at beat 5 (bands, then the seam); the provisional note rides
   with the band. All reveals are opacity/transform transitions at one
   tempo; nothing is ever rebuilt. */
.c-band {
  position: absolute;
  top: 50%;
  height: 58%;
  transform: translateY(-50%) scaleX(0);
  transform-origin: left center;
  border-radius: 2px;
  transition: transform 0.7s ease-in-out;
}

#c-board.c-bands-on .c-band { transform: translateY(-50%) scaleX(1); }

#c-board .c-seam {
  opacity: 0;
  transition: opacity 0.35s linear 0.55s;
}

#c-board.c-bands-on .c-seam { opacity: 1; }

.c-mark { transition: opacity 0.4s linear; }

#c-board.c-marks-1 .c-mark:nth-of-type(n+2) { opacity: 0; }
#c-board.c-marks-0 .c-mark { opacity: 0; }

.c-note { opacity: 0; transition: opacity 0.4s linear 0.7s; }

#c-board.c-bands-on[data-scale="xl"] .c-note { opacity: 1; }

/* Muting is focus, never judgment: the focal rows keep full contrast,
   the rest drop together, and every element gets its turn. */
.c-row.c-dim .c-track,
.c-row.c-dim .c-label { opacity: 0.42; transition: opacity 0.4s linear; }

.c-row .c-track,
.c-row .c-label { transition: opacity 0.4s linear; }

/* The seam: red's second reserved meaning, the moment a position
   changes. Direction-neutral by construction. */
/* The seam marks the moment a coded position changed, and is one of red's two
   reserved meanings. Red alone cannot carry it: simulated under deuteranopia
   the seam separates from a REG-SOFT band by 32 on a scale where about 90 is
   the threshold, so it would vanish into exactly the band it is meant to cut.
   The hairline edge makes the seam's position legible as a shape, so the datum
   survives without spending a second colour on it. */
.c-seam {
  position: absolute;
  top: 6%;
  height: 88%;
  width: 2.5px;
  margin-left: -1.25px;
  background: var(--integrity-red);
  box-shadow: 0 0 0 1px rgba(26, 26, 26, 0.55);
}

.c-mark {
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  line-height: 0;
}

.c-mark svg { display: block; }

#c-board[data-scale="s"] .c-mark svg,
#c-board[data-scale="xs"] .c-mark svg { display: none; }

#c-board[data-scale="s"] .c-mark,
#c-board[data-scale="xs"] .c-mark {
  width: 4px;
  height: 92%;
  border-radius: 0.5px;
  background: var(--ink);
}

#c-board[data-scale="s"] .c-mark-N,
#c-board[data-scale="xs"] .c-mark-N {
  background: none;
  border: 1px solid var(--ink);
}

#c-board[data-scale="s"] .c-mark-A,
#c-board[data-scale="xs"] .c-mark-A { opacity: 0.55; }

#c-board[data-scale="s"] .c-mark-X,
#c-board[data-scale="xs"] .c-mark-X { opacity: 0.18; }

.c-deadline {
  position: absolute;
  top: -6px;
  bottom: -6px;
  width: 10px;
  margin-left: -5px;
  opacity: 0;
  visibility: hidden;
}

.c-deadline svg { width: 100%; height: 100%; display: block; }

.c-deadline-label {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  white-space: nowrap;
  margin-top: 0.5rem;
}

.c-stats {
  display: flex;
  gap: 1.6rem;
  flex-wrap: wrap;
  min-height: 3.2em;
}

.c-statset { display: flex; gap: 1.6rem; flex-wrap: wrap; }

.c-stat { font-size: 0.8rem; color: var(--ink-soft); }

.c-stat strong {
  display: block;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 1.6rem;
  line-height: 1.15;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 860px) {
  .tour-enhanced .scrolly { display: block; }
}

/* The release affordance appears only at beat 10; skip-board's display
   rule outranks the UA [hidden] default, so restate it */
.c-release { align-self: flex-start; }
.c-release[hidden] { display: none; }

/* Once the board is live (beat 10), rows advertise their telemetry */
.c-live .c-row:not(.c-off) { cursor: pointer; }

@media (hover: hover) {
  .c-live .c-row:not(.c-off):hover { background: var(--ground-raise); }
}

/* Stepper mode (mobile, P4c): the canvas is a card above the prose,
   driven by the same beat states as the scroll mode */
.tour-stepped .scrolly { display: flex; flex-direction: column-reverse; }

.tour-stepped .scrolly-canvas {
  position: static;
  height: auto;
  border: 1px solid var(--rule);
  border-radius: 3px;
  background: var(--ground-raise);
  padding: 0.9rem 1rem 1.1rem;
  margin-bottom: 1rem;
  scroll-margin-top: 3.6rem; /* clears the preview banner on step taps */
}

.tour-stepped .c-teach-slot { min-height: 3.2em; }

/* ------------------------------------------------------------------ */
/* Trajectory board                                                    */
/* ------------------------------------------------------------------ */

/* Board head: thesis left, reading key right; stacks on mobile */
.board-head {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(16rem, 1fr);
  gap: 2.5rem;
  align-items: start;
  margin-top: 2.2rem;
}

.board-lede h1 { margin-top: 0; }
.board-lede h1 em { font-style: italic; }

.board-key {
  border: 1px solid var(--rule);
  border-radius: 3px;
  background: var(--ground-raise);
  padding: 1rem 1.2rem;
}

.board-key .board-legend {
  display: block;
  border-bottom: none;
  padding: 0;
}

.board-key .board-legend > span {
  display: block;
  padding: 0.28rem 0;
}

.board-key .board-legend > span + span {
  border-top: 1px solid var(--rule-faint);
}

@media (max-width: 860px) {
  .board-head { grid-template-columns: 1fr; gap: 1.2rem; }
}

.board {
  margin-top: 1.5rem;
  border-top: 1px solid var(--rule);
}

.board-axis {
  position: sticky;
  top: 0;
  z-index: 4;
  background: var(--ground);
  border-bottom: 1px solid var(--rule);
  display: grid;
  grid-template-columns: var(--label-col) 1fr;
  align-items: end;
}

.board-axis .axis-label {
  font-size: 0.78rem;
  color: var(--ink-soft);
  padding: 0.5rem 0.6rem 0.35rem 0;
}

.axis-track { position: relative; height: 34px; }

.axis-tick {
  position: absolute;
  bottom: 0;
  width: 1px;
  height: 8px;
  background: var(--ink);
  opacity: 0.5;
}

.axis-tick > span {
  position: absolute;
  bottom: 10px;
  left: 3px;
  font-size: 0.7rem;
  color: var(--ink-soft);
  opacity: 1;
}

.board-row {
  display: grid;
  grid-template-columns: var(--label-col) 1fr;
  align-items: center;
  border-bottom: 1px solid var(--rule-faint);
}

.board-row:target, .board-row:hover { background: var(--ground-raise); }

.row-label {
  font-size: 0.86rem;
  padding: 0.28rem 0.6rem 0.28rem 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.row-label a { text-decoration: none; }
.row-label a:hover { text-decoration: underline; }

.row-track {
  position: relative;
  height: 30px;
  background-image: var(--year-grid);
}

.band {
  position: absolute;
  top: 7px;
  height: 16px;
  border-radius: 1px;
}

/* Position hue arrives as --fill rather than an inline background shorthand,
   so the texture classes below can layer a background-image over it. */
/* Kept to a single class so .band-hatch, which follows, can win on source
   order and keep its paper background. A descendant selector here would
   outrank it and leave the AMBIG swatch transparent. */
.band, .c-band, .swatch {
  background-color: var(--fill, transparent);
}

/* ---------------------------------------------------------------------------
   Position textures.

   Hue alone cannot carry these categories. Simulated under deuteranopia,
   LBI-OPEN and CCW-ONLY separate by 30 where about 90 is the threshold for
   reading as different fills, and REG-SOFT collides with integrity red at 32,
   which would quietly break the promise that saturated red means only a
   data-integrity notice. Repaletting cannot fix it: the best available move
   takes the worst pair from 30 to 32, because the binding constraint just
   becomes ochre against red.

   So orientation carries the category alongside hue. Orientation is the right
   channel because it survives at 16px tall and stays readable on a band a few
   pixels wide, which is what a state that moves twice in a year produces.
   Every pair below differs in orientation or density, so no two are alike once
   the colour is removed. LBI-BAN is deliberately plain: it is the largest
   category, and leaving it untextured keeps the board quiet.

   Class names are assigned in config.POSITION_TEXTURES.
   --------------------------------------------------------------------------- */

.band-horizontal {   /* LBI-OPEN */
  background-image: repeating-linear-gradient(
    0deg,
    transparent 0 4px,
    rgba(255, 255, 255, 0.42) 4px 5.5px
  );
}

.band-grid {   /* REG-SOFT */
  background-image:
    repeating-linear-gradient(
      90deg,
      transparent 0 6px,
      rgba(255, 255, 255, 0.36) 6px 7.5px
    ),
    repeating-linear-gradient(
      0deg,
      transparent 0 5px,
      rgba(255, 255, 255, 0.36) 5px 6.5px
    );
}

.band-backslash {   /* CCW-ONLY */
  background-image: repeating-linear-gradient(
    135deg,
    transparent 0 5px,
    rgba(255, 255, 255, 0.42) 5px 6.5px
  );
}

.band-dots {   /* OPPOSE */
  background-image: radial-gradient(
    rgba(255, 255, 255, 0.5) 1.1px, transparent 1.2px
  );
  background-size: 6px 6px;
}

/* AMBIG is a designed hatch texture: never gray, never a blend. It is the one
   category with no hue at all, so its hatch is ink on paper rather than a
   lightening of a fill, and it stays the coarsest texture on the board. */
.band-hatch {
  background-image: repeating-linear-gradient(
    45deg,
    transparent 0 4px,
    rgba(26, 26, 26, 0.55) 4px 5.5px
  );
  background-color: var(--ground);
}

.vote-mark, .shift-node {
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  background: none;
  border: none;
  padding: 4px;
  margin: 0;
  cursor: pointer;
  line-height: 0;
}

/* Coarse pointers: the marks sit too close together for per-mark 44px
   targets, so the whole track is the tap target and opens one sheet
   with the row's full record. Keyboard access keeps the buttons. */
@media (pointer: coarse) {
  .vote-mark, .shift-node { pointer-events: none; }
  .row-track { cursor: pointer; }
  .popover a {
    display: inline-block;
    padding: 0.75em 0.2em;
    min-height: 44px;
    box-sizing: border-box;
  }
}

.shift-node > span {
  display: block;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  border: 2px solid var(--ink);
  background: var(--ground);
  position: relative;
}

.shift-node > span::after {
  content: "";
  position: absolute;
  inset: 2.5px;
  border-radius: 50%;
  background: var(--ink);
}

.board-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.4rem;
  font-size: 0.82rem;
  color: var(--ink-soft);
  padding: 0.9rem 0;
  border-bottom: 1px solid var(--rule);
}

.board-legend .swatch {
  display: inline-block;
  width: 1.5em;
  height: 0.85em;
  vertical-align: -0.12em;
  margin-right: 0.45em;
  border-radius: 1px;
}

.board-controls {
  display: flex;
  gap: 0.8rem;
  align-items: baseline;
  padding: 0.8rem 0;
  font-size: 0.88rem;
}

.board-controls button {
  font: inherit;
  background: none;
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: 0.25rem 0.7rem;
  cursor: pointer;
  color: var(--ink);
}

.board-controls button[aria-pressed="true"] {
  background: var(--ink);
  color: var(--ground);
  border-color: var(--ink);
}

/* ------------------------------------------------------------------ */
/* Evidence popover / bottom sheet                                     */
/* ------------------------------------------------------------------ */

.popover {
  position: absolute;
  z-index: 9;
  max-width: 26rem;
  background: var(--ground);
  border: 1px solid var(--ink);
  border-radius: 4px;
  padding: 0.9rem 1rem;
  font-size: 0.88rem;
  box-shadow: 0 2px 4px var(--shadow-tint);
}

.popover .quote { font-family: var(--font-display); }

@media (max-width: 640px) {
  .popover {
    position: fixed;
    left: 0; right: 0; bottom: 0; top: auto;
    max-width: none;
    border-radius: 10px 10px 0 0;
    border-bottom: none;
    padding-bottom: 1.6rem;
  }
}

/* ------------------------------------------------------------------ */
/* State pages: three-signal layout                                    */
/* ------------------------------------------------------------------ */

.signal {
  margin-top: 2rem;
  padding-top: 1.2rem;
  border-top: 1px solid var(--rule);
}

.signal h2 { margin-top: 0; }

.coverage-card {
  border: 1px solid var(--rule);
  border-radius: 4px;
  padding: 1rem 1.2rem;
  max-width: 40rem;
  font-size: 0.92rem;
  color: var(--ink-soft);
}

/* State-page mini track: the state's own row from the board */
.state-track {
  max-width: 44rem;
  margin: 1.4rem 0 0.4rem;
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: 0.15rem 0.5rem 0.4rem;
  background: var(--ground-raise);
}

.state-track .track-years {
  display: flex;
  justify-content: space-between;
  font-size: 0.7rem;
  color: var(--ink-soft);
  padding: 0.2rem 0;
}

/* Monochrome tally bar: ink intensity, never hue */
.tally-bar {
  display: flex;
  max-width: 44rem;
  height: 10px;
  border-radius: 2px;
  overflow: hidden;
  margin: 0.6rem 0 0.9rem;
  background: var(--ground-raise);
}

.tally-bar > span { display: block; background: var(--ink); }
.tally-bar > span + span { border-left: 1px solid var(--ground); }

.vote-table { border-collapse: collapse; font-variant-numeric: tabular-nums; }
.vote-glyph svg { vertical-align: -0.12em; margin-right: 0.25em; }
.vote-table th, .vote-table td {
  text-align: left;
  padding: 0.45rem 1.1rem 0.45rem 0;
  border-bottom: 1px solid var(--rule-faint);
  font-size: 0.92rem;
}
.vote-table th { font-weight: 600; font-size: 0.85rem; }

.vote-glyph { font-size: 1rem; }

/* ------------------------------------------------------------------ */
/* Instruments page: endorsement record, quadrant view, wave map       */
/* ------------------------------------------------------------------ */

.endorser-list {
  max-width: none;
  font-size: 0.92rem;
  line-height: 1.9;
}

.nonmember-list {
  list-style: none;
  padding-left: 0;
  max-width: 44rem;
}

.nonmember-list li {
  padding: 0.35rem 0;
  border-bottom: 1px solid var(--rule-faint);
  font-size: 0.92rem;
}

/* Scrub controls: plain range inputs, enabled only when JS is live */
.scrub-control {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  flex-wrap: wrap;
  margin: 1.2rem 0 0.2rem;
  font-size: 0.9rem;
  max-width: 44rem;
}

.scrub-control input[type="range"] {
  flex: 1;
  min-width: 10rem;
  min-height: 44px;
  accent-color: var(--ink);
  margin: 0;
}

.scrub-control output {
  font-variant-numeric: tabular-nums;
  font-size: 0.85rem;
  color: var(--ink-soft);
  flex-basis: 100%;
}

/* Quadrant state search: the primary nav into the chart (DESIGN v2
   mobile contract). Disabled until JS enables it, like the scrubs. */
.quadrant-search {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  flex-wrap: wrap;
  margin: 1.2rem 0 0.2rem;
  font-size: 0.9rem;
  max-width: 44rem;
}

.quadrant-search input[type="search"] {
  flex: 1;
  min-width: 12rem;
  padding: 0.4rem 0.6rem;
  border: 1px solid var(--rule);
  border-radius: 3px;
  background: var(--ground-raise);
  color: var(--ink);
  font: inherit;
  font-size: 0.9rem;
}

.quadrant-search input[type="search"]:disabled { opacity: 0.45; }

.quadrant-search input[type="search"]:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

@media (pointer: coarse) {
  .quadrant-search input[type="search"] { min-height: 44px; }
}

/* Quadrant view: monochrome ink dots, unlabeled regions (DESIGN v2) */
.quadrant-scroll { overflow-x: auto; margin-top: 0.8rem; }

.quadrant-svg { display: block; width: 100%; min-width: 640px; }

.quadrant-svg .q-axis {
  font-family: var(--font-data);
  font-size: 12px;
  fill: var(--ink-soft);
}

.quadrant-svg .q-dot { fill: var(--ink); fill-opacity: 0.5; }

/* Search hit: an ink ring and a radius bump, never a color change */
.quadrant-svg .q-dot.q-hit { stroke: var(--ink); stroke-width: 2; }

.quadrant-table th, .quadrant-table td { font-size: 0.85rem; }

/* Wave map: radios are 44px targets; the container gets height only when
   the map actually initialises, so the no-JS page never shows a dead box */
.map-controls {
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: 0.4rem 0.9rem 0.6rem;
  margin: 1.2rem 0 0;
  max-width: 44rem;
}

.map-controls legend {
  font-size: 0.85rem;
  color: var(--ink-soft);
  padding: 0 0.3rem;
}

.map-radio {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  min-height: 44px;
  font-size: 0.9rem;
  cursor: pointer;
}

.map-radio input {
  accent-color: var(--ink);
  width: 1.05rem;
  height: 1.05rem;
  margin: 0;
}

.map-radio .swatch {
  display: inline-block;
  width: 1.5em;
  height: 0.85em;
  border-radius: 1px;
}

.wave-map { max-width: 100%; }

.wave-map-live {
  height: 420px;
  margin-top: 0.8rem;
  border: 1px solid var(--rule);
  border-radius: 3px;
  background: var(--ground-raise);
}

@media (max-width: 640px) {
  .wave-map-live { height: 320px; }
}

.map-fallback {
  border: 1px dashed var(--rule);
  border-radius: 3px;
  padding: 0.8rem 1rem;
  color: var(--ink-soft);
  font-size: 0.9rem;
  max-width: 44rem;
  margin-top: 0.8rem;
}

.map-fallback[hidden] { display: none; }

/* ------------------------------------------------------------------ */
/* Doctrine timeline: era bands, filled core / outlined context marks  */
/* ------------------------------------------------------------------ */

.doctrine-timeline {
  max-width: 44rem;
  margin: 0.6rem 0 0.4rem;
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: 0.15rem 0.5rem 0.4rem;
  background: var(--ground);
  overflow-x: auto;
}

/* Narrow viewports scroll the timeline instead of clipping era labels */
.doctrine-timeline .timeline-inner { min-width: 560px; }

.timeline-svg { display: block; width: 100%; }

.timeline-svg .era-label {
  font-family: var(--font-data);
  font-size: 11px;
  fill: var(--ink-soft);
}

.timeline-svg .timeline-base { stroke: var(--ink); stroke-opacity: 0.3; }

.timeline-svg .tl-core { fill: var(--ink); }

.timeline-svg .tl-context {
  fill: var(--ground);
  stroke: var(--ink);
  stroke-width: 2;
}

.doctrine-timeline .track-years {
  display: flex;
  justify-content: space-between;
  font-size: 0.7rem;
  color: var(--ink-soft);
  padding: 0.2rem 0;
}

/* ---------------------------------------------------------------------------
   Coverage table on the methodology page. Rules, not fills: a table of
   findings should not look scored, and zebra striping would read as ranking
   where the order is alphabetical. Wide content scrolls in its own container
   so the page body never scrolls sideways on a phone.
   --------------------------------------------------------------------------- */

.table-scroll {
  overflow-x: auto;
  margin: 1.4rem 0;
}

.coverage-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
  text-align: left;
}

.coverage-table caption {
  caption-side: top;
  text-align: left;
  font-size: 0.8rem;
  color: var(--ink-soft);
  padding-bottom: 0.7rem;
}

.coverage-table thead th {
  font-size: 0.68rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-soft);
  font-weight: 600;
  border-bottom: 1px solid var(--ink);
  padding: 0 1.2rem 0.45rem 0;
  white-space: nowrap;
}

.coverage-table tbody th,
.coverage-table td {
  border-bottom: 1px solid var(--rule);
  padding: 0.6rem 1.2rem 0.6rem 0;
  vertical-align: top;
  font-weight: 400;
}

.coverage-table tbody th {
  white-space: nowrap;
  font-weight: 600;
}

/* The finding is a two-word verdict, not prose: wrapping it makes the rows
   uneven and the column read as fuller than it is. Only the record wraps. */
.coverage-table tbody td:first-of-type {
  white-space: nowrap;
}

/* The date column lines up; the document titles are prose and wrap. */
.coverage-table td:last-child {
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}

.coverage-table tbody tr:last-child th,
.coverage-table tbody tr:last-child td {
  border-bottom: none;
}

/* Era swatches sit on paper, so they carry a hairline to stay visible */
.era-legend .swatch {
  display: inline-block;
  width: 1.5em;
  height: 0.85em;
  vertical-align: -0.12em;
  margin-right: 0.45em;
  border: 1px solid var(--rule);
  border-radius: 1px;
}

.era-legend > span {
  display: inline-block;
  margin-right: 1.2rem;
  white-space: nowrap;
}

.timeline-list {
  list-style: none;
  padding-left: 0;
  max-width: 44rem;
}

.timeline-list li {
  padding: 0.35rem 0;
  border-bottom: 1px solid var(--rule-faint);
  font-size: 0.92rem;
}

/* Data-integrity notices and the shift-seam are red's only two meanings
   on this site (DESIGN v2.1 rule 10) */
.integrity-notice {
  border-left: 3px solid var(--integrity-red);
  padding: 0.5rem 0 0.5rem 1rem;
  color: var(--ink);
  max-width: 40rem;
}

/* ------------------------------------------------------------------ */
/* Draft banner: preview builds only, never in the deploy artifact     */
/* ------------------------------------------------------------------ */

.draft-banner {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--integrity-red);
  color: #FFF8F0;
  text-align: center;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 0.5rem 1rem;
}

.draft-chip {
  display: inline-block;
  border: 2px solid var(--integrity-red);
  color: var(--integrity-red);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  padding: 0.05rem 0.45rem;
  border-radius: 3px;
  vertical-align: 0.15em;
  margin-left: 0.5rem;
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}
