/* ═══════════ METHOD OVERLAY ═══════════
   The "?" overlay holds three sibling pages — Method (orientation),
   Map (schema), Sources (papers). Shared chrome (page header, sub-nav,
   replay-tour launcher) lives here. Page-specific blocks (.method-*,
   .model-*, .lit-*) follow further down. */

/* Method-page hero. Two columns on wide screens — the value-prop block
   on the left (kicker → headline → three-question teaser) and the
   tour CTA as a self-contained dark pill on the right. The CTA sizes
   to content and centers vertically; we don't stretch it to fill the
   hero, which kept it looking hollow. Stacks under 720px. */
.method-hero {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--space-xl);
  margin-bottom: var(--space-3xl);
  padding: var(--space-xl);
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
@media (max-width: 720px) {
  .method-hero {
    grid-template-columns: 1fr;
    padding: var(--space-lg);
    gap: var(--space-lg);
  }
}

.method-hero-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  min-width: 0;
}

/* Labels (kicker, question numbers) stay quiet — accent is reserved
   for semantic leverage (+Xy, modifiable-budget segment) so it doesn't
   lose meaning by appearing on every chrome element. */
.method-hero-kicker {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--text-dim);
}

/* One typographic step above the framework-overview-title (22px) used
   by Sources and Model — Method is the orientation page and is allowed
   to read a touch more hero-y, but the gap is small enough that the
   three pages still share one register. */
.method-hero-title {
  font-size: 24px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.3px;
  color: var(--text-primary);
  margin: 0;
  max-width: 28ch;
}
@media (max-width: 720px) {
  .method-hero-title { font-size: 21px; }
}

.method-hero-sub {
  font-size: 13px;
  color: var(--text-secondary);
  letter-spacing: 0.2px;
  margin: var(--space-sm) 0 var(--space-xs) 0;
}

.method-hero-questions {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.method-hero-questions li {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-size: 14px;
  color: var(--text-primary);
  letter-spacing: 0.1px;
}
.method-hero-q-num {
  flex: 0 0 auto;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.2px;
  color: var(--text-dim);
  min-width: 22px;
}
.method-hero-q-text {
  font-weight: 400;
}

/* Tour CTA — designed as a stopwatch-dial instrument tag, not a
   generic primary button. The dial carries the "quick tour" cue:
   fine ticks around the perimeter + 4 quarter marks, framed by corner
   registration brackets on a sharp-cornered card. Carries action-weight
   through typography, framing, and motion rather than by borrowing the
   accent color. */
.method-hero-cta {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  gap: 18px;
  padding: 18px 22px;
  background: var(--accent-soft);
  border: 1px solid rgba(8, 145, 178, 0.28);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  min-width: 300px;
  transition: background-color 200ms ease, border-color 200ms ease, box-shadow 200ms ease, transform 200ms ease;
}
.method-hero-cta:hover,
.method-hero-cta:focus-visible {
  background: rgba(8, 145, 178, 0.13);
  border-color: var(--accent);
  outline: none;
  transform: translateY(-1px);
  box-shadow: 0 6px 18px -10px rgba(8, 145, 178, 0.55);
}
.method-hero-cta:focus-visible {
  box-shadow: 0 0 0 2px var(--bg-panel), 0 0 0 3px var(--accent), 0 6px 18px -10px rgba(8, 145, 178, 0.55);
}

/* Corner registration brackets — typographic crop marks at top-left
   and bottom-right. Drawn with two pseudo-elements; the bracket is
   the union of a top/left border (TL) or bottom/right border (BR). */
.method-hero-cta::before,
.method-hero-cta::after {
  content: '';
  position: absolute;
  width: 9px;
  height: 9px;
  pointer-events: none;
  transition: border-color 200ms ease;
}
.method-hero-cta::before {
  top: 5px;
  left: 5px;
  border-top: 1.5px solid var(--accent);
  border-left: 1.5px solid var(--accent);
}
.method-hero-cta::after {
  bottom: 5px;
  right: 5px;
  border-bottom: 1.5px solid var(--accent);
  border-right: 1.5px solid var(--accent);
}

/* Stopwatch dial — 44px circle housing two ring layers and a glyph.
   Outer ring: 60 thin minute ticks (one per second). Inner ring just
   inside it: 4 longer quarter ticks at 12/3/6/9. The dial center
   holds a static ↻ glyph. On hover, the minute ring rotates one full
   turn (800ms) and the quarter ring rotates a quarter-turn the other
   way — gives the impression of a watch movement winding. */
.method-hero-cta-dial {
  position: relative;
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  border-radius: 50%;
}

/* Outer minute ring — 60 ticks (every 6°). Mask carves the inner
   area to a hollow ring so the ticks read as a perimeter, not a
   starburst. */
.method-hero-cta-dial-ticks {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: repeating-conic-gradient(
    from -0.3deg,
    var(--accent) 0deg 0.6deg,
    transparent 0.6deg 6deg
  );
  -webkit-mask: radial-gradient(circle, transparent 0 65%, #000 67% 100%);
          mask: radial-gradient(circle, transparent 0 65%, #000 67% 100%);
  transition: transform 800ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* Quarter ring — 4 longer ticks at the cardinal positions. Sits
   slightly inboard of the minute ring and uses a thicker arc so it
   reads as the "hour" register on a watch face. */
.method-hero-cta-dial-quarters {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: repeating-conic-gradient(
    from -0.9deg,
    var(--accent) 0deg 1.8deg,
    transparent 1.8deg 90deg
  );
  -webkit-mask: radial-gradient(circle, transparent 0 55%, #000 57% 65%, transparent 67% 100%);
          mask: radial-gradient(circle, transparent 0 55%, #000 57% 65%, transparent 67% 100%);
  transition: transform 800ms cubic-bezier(0.22, 1, 0.36, 1);
}

.method-hero-cta:hover .method-hero-cta-dial-ticks,
.method-hero-cta:focus-visible .method-hero-cta-dial-ticks {
  transform: rotate(360deg);
}
.method-hero-cta:hover .method-hero-cta-dial-quarters,
.method-hero-cta:focus-visible .method-hero-cta-dial-quarters {
  transform: rotate(-90deg);
}

/* ↻ glyph centered in the dial — static while the rings spin. The
   replay semantics (this tour can be re-watched) live here. */
.method-hero-cta-glyph {
  position: absolute;
  inset: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  font-weight: 500;
  line-height: 1;
  color: var(--accent);
  z-index: 1;
}

.method-hero-cta-body {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}
/* Title — uppercase mono with tracking, matching the
   technical/instrument register established by the dial and brackets. */
.method-hero-cta-label {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-primary);
  white-space: nowrap;
}
.method-hero-cta-sub {
  font-size: 11px;
  letter-spacing: 0.2px;
  color: var(--text-secondary);
}

.method-hero-cta-arrow {
  flex: 0 0 auto;
  margin-left: auto;
  padding-left: 14px;
  font-size: 14px;
  color: var(--accent);
  transition: transform 220ms cubic-bezier(0.22, 1, 0.36, 1), color 200ms ease;
}
.method-hero-cta:hover .method-hero-cta-arrow,
.method-hero-cta:focus-visible .method-hero-cta-arrow {
  color: var(--accent);
  transform: translateX(4px);
}

/* Inline leverage token used in method-page prose to point at the
   leverage color the user sees throughout the dashboard. */
.framework-leverage-token {
  color: var(--leverage);
  font-weight: 600;
}

/* ═══════════ METHOD PAGE ═══════════
   Visual-first orientation surface. Three sections, each carried by a
   figure with a single-paragraph caption underneath. No bullet trios,
   no nested term/definition blocks — the prose is captioning the
   visual, not substituting for it. */

.method-section {
  margin-bottom: var(--space-2xl);
}
.method-section:last-child {
  margin-bottom: 0;
}

/* Numbered kicker + bibliographic-scale title. Method intentionally
   skips the top-hairline anchoring used on Sources/Model — the
   numbered kicker (01 — 02 — 03) already structures the page, and
   stacking three rules across the reading made the surface read
   harder than the prose justifies. */
.method-section-head {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: var(--space-lg);
}

.method-section-kicker {
  display: inline-block;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--text-dim);
}

.method-section-title {
  font-size: 18px;
  font-weight: 500;
  color: var(--text-primary);
  line-height: 1.3;
  letter-spacing: -0.2px;
  margin: 0;
}

/* Brief figcaption sitting muted under each figure — names what the
   visual depicts in a phrase. Echoes the small "median lifespan"
   axis-tick subtext that used to live inside the projection curve;
   now promoted to a real <figcaption> so it labels the figure as a
   whole, not just one tick. */
.method-figcaption {
  display: block;
  font-size: 11px;
  color: var(--text-dim);
  letter-spacing: 0.3px;
  text-align: center;
  margin-top: var(--space-md);
}
/* Section 3's figure ends with the cyan Mortality-Profile output card —
   a heavier visual tail than sections 1/2's airy axis ticks. The
   figcaption needs more room above it to breathe. */
.method-figure-inputs .method-figcaption {
  margin-top: var(--space-xl);
}

/* Description paragraph beneath each figure. Generous top margin so
   it sits clearly below the figcaption regardless of how visually
   heavy the figure's tail is — section 3's cyan Mortality-Profile
   output card crowds at a tighter margin. Same gap on all three. */
.method-desc {
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.7;
  margin: var(--space-2xl) 0 0 0;
}

.method-desc strong {
  color: var(--text-primary);
  font-weight: 600;
}

.method-desc em {
  font-style: italic;
  color: var(--text-secondary);
}

/* Shared figure container. Figures sit bare on the page — no border,
   no fill — so the hero card above stays the page's only true "card"
   and the figures read as figures inside an article (kicker + title
   above, caption below). Horizontal margin (not padding — the variant
   classes own padding for their internal layouts) insets the figure
   under its section header so it reads as a child of the section
   rather than a full-bleed sibling. The inset replaces the visual
   cue the old border used to provide. */
.method-figure {
  margin: 0 var(--space-3xl);
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: 0;
}
@media (max-width: 720px) {
  .method-figure { margin: 0 var(--space-md); }
}

/* ── Projection figure (survival curves) ───────────────────────────
   Gompertz-style schematic, two variants:
   • 'projection' — single curve with a median marker.
   • 'ceiling'    — same curve + a shifted-right ceiling curve. The lens
     between them is the modifiable-budget shade.
   Both variants share the same viewBox so the projection median sits in
   the same place across figures — section 02 reads as section 01 + gain.
   Schematic only; not personalized. */

.method-figure-curve {
  padding: var(--space-sm) 0 0;
  position: relative;
}

/* aspect-ratio matches the viewBox so circles render circular regardless
   of container width. preserveAspectRatio="none" on the SVG element
   becomes irrelevant once the display aspect matches the viewBox. */
.method-curve-svg {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1000 / 200;
  overflow: visible;
}

/* Curve stroke + fill — the dark stroke reads as the trajectory, the
   soft fill underneath gives it weight without competing with the data. */
.method-curve-stroke {
  fill: none;
  stroke: var(--text-primary);
  stroke-width: 2.5;
  vector-effect: non-scaling-stroke;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.method-curve-stroke--ceil {
  stroke: var(--leverage);
}
.method-curve-area {
  /* fill set inline via url(#…) gradient */
}
.method-curve-baseline {
  stroke: var(--border);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
.method-curve-median {
  stroke: var(--text-primary);
  stroke-width: 1;
  stroke-dasharray: 3 3;
  vector-effect: non-scaling-stroke;
  opacity: 0.45;
}
.method-curve-median--ceil {
  stroke: var(--leverage);
  opacity: 0.9;
}
.method-curve-dot {
  fill: var(--bg-panel);
  stroke: var(--text-primary);
  stroke-width: 2.5;
  vector-effect: non-scaling-stroke;
}
.method-curve-dot--ceil {
  stroke: var(--leverage);
}
.method-curve-budget {
  /* fill via url(#…) */
}

/* X-axis ticks — positioned absolutely so they line up with the median
   verticals in the SVG (which use percentage-based x coords in viewBox).
   Each .method-curve-tick is centered on its left: % anchor. */
.method-curve-xaxis {
  position: relative;
  margin-top: var(--space-sm);
  height: 36px;
}
.method-curve-tick {
  position: absolute;
  top: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  transform: translateX(-50%);
  white-space: nowrap;
}
.method-curve-tick[style*="left: 0%"] {
  transform: translateX(0);
  align-items: flex-start;
}
.method-curve-tick-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.method-curve-tick--proj .method-curve-tick-label,
.method-curve-tick--ceil .method-curve-tick-label {
  color: var(--text-primary);
}
.method-curve-tick--ceil .method-curve-tick-label {
  color: var(--leverage);
}

/* ── Inputs figure ─────────────────────────────────────────────────
   Five fixed-height tiles → an SVG of converging paths → an accented
   synthesis card. The card has a two-line reserved name region so
   single-word names ("Genome") and wrapping names ("Personal history")
   render at the same shape. The synthesis is the value prop, so it gets
   the visual weight: cyan accent + tokens listing what's in the profile. */

.method-figure-inputs {
  padding: var(--space-sm) 0 0;
}

/* No column dividers — the five title-underlines align at the same y
   to form their own rhythm. Grid alignment + whitespace structure the
   columns; the synthesis box below earns its own border as the
   climax. */
.method-inputs-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: var(--space-lg);
}
@media (max-width: 760px) {
  .method-inputs-grid { grid-template-columns: repeat(2, 1fr); gap: var(--space-md); }
}
@media (max-width: 420px) {
  .method-inputs-grid { grid-template-columns: 1fr; }
}

/* Centered so each column's content sits over the point where its flow
   line emerges. Left-aligned text drifted to the side of the column and
   the line looked like it came from empty space. Each input is its own
   bordered tile — once the outer figure frame was dropped, the loose
   columns needed individual boundaries to read as discrete inputs the
   engine consumes. */
.method-input {
  position: relative;
  display: flex;
  flex-direction: column;
  text-align: center;
  padding: var(--space-md) var(--space-sm);
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

/* Channel glyph that sits above the kicker. Stroke-based at 24×24 so it
   reads in the same idiom as the engine-pillar icons below. Sized small
   (18px) and centered so all five icons share a baseline and the kicker
   row underneath stays aligned across cards regardless of glyph shape. */
.method-input-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 26px;
  margin: 4px 0 7px;
  color: var(--text-dim);
}
.method-input-icon svg {
  width: 24px;
  height: 24px;
}

/* Channel-number kicker that sits above the title. Stacks vertically
   instead of fighting for space in the top-right corner with long titles
   like 'Demographics'. */
.method-input-tag {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.2px;
  color: var(--text-dim);
  margin-bottom: 4px;
}
/* All five titles are single-word now (History, not Personal history)
   so no 2-line reservation is needed — they all sit at the same y by
   default, and the divider below them aligns across cards. */
.method-input-name {
  font-size: 13px;
  font-weight: 400;
  color: var(--text-primary);
  letter-spacing: 0.2px;
  line-height: 1.25;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
}
.method-input-items {
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.method-input-items li {
  font-size: 11px;
  color: var(--text-dim);
  letter-spacing: 0.4px;
  line-height: 1.5;
}

/* ── Pipeline SVG (converge → engine → profile) ───────────────────────
   Mirrors the landing page's "360° View" diagram (`lp-howflow`) so the
   two surfaces read as one composition at two zoom levels. Same color
   vocabulary (cyan engine, red/amber/green vertices), same hexagonal
   engine, same LONGEVITY PROFILE frame + triangle + payoff. Static —
   no hover or animation; the landing animates because card hovers
   drive it, here it's a reference figure on an orientation page. */
.method-pipeline-svg {
  display: block;
  width: 100%;
  height: auto;
  max-width: 520px;
  margin: var(--space-lg) auto 0;
  font-family: var(--font-mono);
}

/* Converge S-curves: gray→cyan vertical gradient inherited from the
   linked <linearGradient> on the stroke. No CSS needed beyond the
   tag — markup carries the stroke + width. */

/* Aescle engine — hexagonal chip. Same shape and stroke language as
   the landing version so the two diagrams are immediately recognized
   as the same element. */
.method-engine-hex-outer {
  fill: #ffffff;
  stroke: #0891b2;
  stroke-width: 1.7;
  stroke-linejoin: round;
}
.method-engine-hex-inner {
  fill: none;
  stroke: #0891b2;
  stroke-opacity: 0.34;
  stroke-width: 1.1;
  stroke-linejoin: round;
}
.method-engine-ticks circle {
  fill: #0891b2;
}
.method-engine-line1,
.method-engine-line2 {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 2px;
  fill: var(--accent);
}
.method-engine-glyphs {
  color: #0891b2;
  opacity: 0.55;
  pointer-events: none;
}
.method-engine-glyph rect,
.method-engine-glyph circle {
  fill: currentColor;
}
.method-engine-glyph line {
  stroke: currentColor;
  stroke-width: 1.1;
  stroke-linecap: round;
}

/* Mortality profile frame + bisecting legend pill. Mirrors the
   landing's fieldset-legend treatment: subtle surface fill on the
   frame, pill centered horizontally with its midline punching through
   the frame's top edge. */
.method-profile-frame {
  fill: rgba(8, 145, 178, 0.025);
  stroke: var(--border);
  stroke-width: 1;
}
.method-profile-pill-bg {
  fill: var(--bg-panel);
  stroke: var(--border);
  stroke-width: 1;
}
.method-profile-pill-text {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 2px;
  fill: var(--text-secondary);
  text-transform: uppercase;
}

/* Triangle edges + reveal arrow. Single stroke style for all four so
   the triangle closes visibly and the engine→profile reveal reads as
   the same kind of object. Reveal arrow takes a cyan tint to inherit
   the converge trunk's color (the engine's input and output are one
   flow). */
.method-flow-edge {
  stroke: color-mix(in srgb, var(--text-dim) 72%, transparent);
  stroke-width: 1.4;
  fill: none;
}
.method-flow-edge.method-flow-edge--reveal {
  stroke: #0891b2;
  stroke-opacity: 0.7;
}

/* Vertices — halo + dot + uppercase label. Halo colors match the
   landing per-vertex tint so threats/targets/actions carry the same
   semantic warm-amber-green language across both surfaces. */
.method-flow-vertex .v-halo {
  fill: transparent;
}
.method-flow-vertex[data-vertex="threats"] .v-halo { fill: rgba(220, 38, 38, 0.08); }
.method-flow-vertex[data-vertex="targets"] .v-halo { fill: rgba(217, 119, 6, 0.10); }
.method-flow-vertex[data-vertex="actions"] .v-halo { fill: rgba(22, 163, 74, 0.10); }
.method-flow-vertex .v-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 2px;
  fill: var(--text-secondary);
  text-transform: uppercase;
}

/* Payoff chip — green-tinted pill at the triangle's centroid. The
   cycle around it is the centerpiece; the chip is the result. */
.method-payoff-pill {
  fill: rgba(22, 163, 74, 0.12);
  stroke: #16a34a;
  stroke-opacity: 0.7;
  stroke-width: 1.4;
}
.method-payoff-text {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 1.8px;
  fill: #15803d;
}

/* ── Methodology appendix ──────────────────────────────────────────
   Demoted disclosure for the math/limitations. Most users don't care,
   but it needs to be discoverable for the ones who do. Quieter than a
   section: top rule, kicker + small heading, dim body text. */
.method-appendix {
  margin-top: var(--space-2xl);
  padding-top: var(--space-lg);
  border-top: 1px solid var(--border);
}

.method-appendix-head {
  margin-bottom: var(--space-sm);
}

.method-appendix-kicker {
  display: inline-block;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: 4px;
}

.method-appendix-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-secondary);
  letter-spacing: 0.2px;
  margin: 0;
}

.method-appendix-body {
  font-size: 12px;
  color: var(--text-dim);
  line-height: 1.7;
  margin: 0;
}
.method-appendix-body strong {
  color: var(--text-secondary);
  font-weight: 600;
}

/* ═══════════ FRAMEWORK SUB-NAV + PAGE HEADER ═══════════
   The overlay carries three sibling pages — Method (prose), Model
   (schema), Sources (papers). The chrome band is one horizontal row
   split into two zones by a vertical hairline: a left section-identity
   block ("How it works / The framework") and the right tab strip
   (Method / Model / Sources). They share the row as structural
   peers — section on the left, pages on the right — rather than as
   a label-above-tabs stack, which has no anchor when the "tabs"
   below are three equal-weight cells. A two-step accent indicator
   runs along the chrome's bottom edge: soft under the section
   block (always-on, "you're in this section") and full-opacity
   under the active tab ("on this page"). Together they form one
   continuous you-are-here strip across the chrome. */

/* Chrome band: full-bleed strip attached to the topbar. The flex
   row lets the section block size to its content (left-anchored
   at the 1080px content column's left edge) and the tab strip
   fill the remaining width. Pinned to the top of the scroll so
   the sub-nav stays reachable as the user reads down the page. */
.framework-pageheader {
  display: flex;
  align-items: stretch;
  background: var(--bg-surface);
  border-bottom: 1px solid var(--border);
  padding: 0 max(var(--space-lg), calc((100% - 1080px) / 2 + var(--space-lg)));
  margin-bottom: 0;
  position: sticky;
  top: 0;
  z-index: 5;
}

/* Section identity zone — left rail of the chrome row. Distinct
   typographic grammar from the tabs: single-line title (14px / 600
   / 2px / --text-secondary), no descriptor below. The big lever
   here is FORMAT not WEIGHT — section is one line, tabs are two —
   which is what makes the section read as a different KIND of
   element (heading vs control). Size is bumped one step above the
   tab labels (14px vs 13px) to reinforce; color stays at
   --text-secondary so the section title doesn't out-compete the
   active tab's --accent for focal weight. Vertical hairline on
   the right matches the chrome band's bottom border, meeting at
   the corner. Not interactive: this is identity, not a control. */
.framework-section {
  position: relative;
  display: flex;
  align-items: center;
  padding: 14px var(--space-lg) 14px var(--space-md);
  margin-right: var(--space-lg);
  border-right: 1px solid var(--border);
  flex-shrink: 0;
  user-select: none;
}
/* Section flag — a small accent rail at the section's left edge,
   vertically centered. Orthogonal to the active-tab indicator's
   horizontal axis, so the two coexist without competing: the
   vertical rail says "this is a marked section," the horizontal
   indicator says "this is the active page." Together they form a
   simple two-axis coordinate system across the chrome (vertical =
   section, horizontal = page) — cleaner than the prior bottom-edge
   accent strip, which left a visible gap between section and
   active-tab when Method was selected. */
.framework-section::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 2px;
  height: 22px;
  background: var(--accent);
}
.framework-section-label {
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--text-secondary);
}

/* Tab strip — fills the right zone of the chrome row. Equal-width
   cells preserved (just on the narrower remaining canvas), so the
   traveling active indicator pattern still works as before. */
.framework-subnav {
  display: flex;
  flex: 1;
  gap: 0;
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: 0;
}

/* Mobile — shrink the section title and tighten its padding to
   claw back horizontal space for the tabs. Title stays single-line
   and visually dominant relative to tab labels (which keep their
   13px size), just at a less ceremonial scale. */
@media (max-width: 720px) {
  .framework-pageheader {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    padding: 0;
  }
  .framework-section {
    min-width: 0;
    padding: 13px var(--space-md);
    margin-right: 0;
    border-right: 0;
  }
  .framework-section-label {
    font-size: 13px;
    letter-spacing: 1.5px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .framework-subnav {
    grid-column: 1 / -1;
    grid-row: 2;
    min-width: 0;
    border-top: 1px solid var(--border);
  }
  .framework-subnav-tab {
    min-width: 0;
    padding: 13px var(--space-sm);
  }
  .framework-subnav-label {
    font-size: 12px;
    white-space: nowrap;
  }
}

/* Mobile-only close button on the framework header. On desktop the
   topbar `?` button toggles the overlay open/closed, but on phones
   the overlay covers the topbar entirely (see layout.css 720px rule),
   so we need an in-overlay dismiss. Matches the .slide-over-close
   icon button styling family. */
.framework-close {
  display: none;
  width: 32px;
  height: 32px;
  align-self: center;
  margin-left: var(--space-sm);
  border: none;
  background: none;
  font-size: 16px;
  color: var(--text-dim);
  cursor: pointer;
  border-radius: var(--radius-sm);
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: all 0.12s;
}
.framework-close:hover {
  color: var(--text-primary);
  background: var(--bg-hover);
}
@media (max-width: 720px) {
  .framework-close { display: flex; }
}
.framework-subnav-tab {
  appearance: none;
  background: transparent;
  border: 0;
  padding: 14px var(--space-lg);
  font-family: inherit;
  cursor: pointer;
  position: relative;
  display: flex;
  flex: 1;
  align-items: center;
  justify-content: center;
  text-align: center;
  transition: background-color 160ms ease, color 160ms ease;
}
.framework-subnav-tab:hover {
  background: var(--bg-panel);
}

/* Sentence-shaped labels — one line of plain text per tab, no eyebrow.
   Sentence case (not the uppercase chrome treatment used for short
   nouns) because the labels are full phrases. */
.framework-subnav-label {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.2px;
  color: var(--text-secondary);
  transition: color 160ms ease;
}

.framework-subnav-tab:hover .framework-subnav-label {
  color: var(--text-primary);
}

/* Active tab: accent label + a 2px accent segment that sits on the
   hairline rail under just this cell, mirroring the bottom-nav
   indicator pattern. */
.framework-subnav-tab.active .framework-subnav-label {
  color: var(--accent);
}
.framework-subnav-tab.active::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  background: var(--accent);
}

/* Persistent footer strip — lives in the overlay chrome (inside
   .framework-scroll, outside .framework-pagewrap) so both tabs share
   it. Horizontal padding matches .framework-pageheader so the rails
   align with the AESCLE logo / topbar buttons gutter; justify-between
   anchors contact to the left rail and legal links to the right so
   the wide span reads as footer structure, not an orphaned label. */
.framework-footer {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-lg);
  padding: var(--space-lg) max(var(--space-lg), calc((100% - 1080px) / 2 + var(--space-lg)));
  border-top: 1px solid var(--border);
  background: var(--bg-surface);
}
.framework-footer-contact {
  display: flex;
  align-items: baseline;
  gap: var(--space-md);
}
.framework-footer-legal {
  display: flex;
  gap: var(--space-lg);
}
.framework-footer-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-dim);
}
.framework-footer-link {
  font-size: 13px;
  color: var(--text-secondary);
  text-decoration: none;
  border-bottom: 1px solid var(--border);
  transition: color 160ms ease, border-color 160ms ease;
}
.framework-footer-link:hover {
  color: var(--accent);
  border-bottom-color: currentColor;
}
@media (max-width: 560px) {
  .framework-footer {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-md);
  }
}

/* Shared overview block — the orientation header for Model and Sources.
   Mirrors Method's hero structurally (kicker → title → one-line sub →
   optional 3-stat strip) and matches its panel chrome (bordered card
   on bg-panel) so all three tabs share the same top-of-page idiom.
   No tour CTA — Model and Sources are working surfaces, not pitches. */
.framework-overview {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  column-gap: var(--space-xl);
  row-gap: var(--space-xl);
  margin-bottom: var(--space-3xl);
  padding: var(--space-xl);
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
@media (max-width: 720px) {
  .framework-overview { padding: var(--space-lg); grid-template-columns: 1fr; }
}

/* Section emblem — mirrors Method's CTA slot in grid col 2. Tile-framed
   icon, content-sized, vertically centered with the head. */
.framework-overview-hero {
  grid-column: 2;
  width: 120px;
  height: 120px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 28px;
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  color: var(--text-secondary);
}
.framework-overview-hero svg { width: 100%; height: 100%; display: block; }

.framework-overview-head {
  grid-column: 1;
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  min-width: 0;
}
.framework-overview-stats { grid-column: 1 / -1; }
.framework-overview-kicker {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--text-dim);
}
.framework-overview-kicker-icon {
  display: inline-flex;
  width: 13px;
  height: 13px;
  color: var(--accent);
}
.framework-overview-kicker-icon svg { width: 100%; height: 100%; display: block; }
.framework-overview-title {
  font-size: 22px;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.3px;
  color: var(--text-primary);
  margin: 0;
}
.framework-overview-sub {
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.6;
  margin: 0;
}
/* Stats sit inside the overview card, so they shed their own card
   chrome — typographic stats separated by a top hairline read as
   summary metadata for the card above them, not as nested tiles. */
.framework-overview-stats {
  display: grid;
  /* Auto-fit lets the strip grow from 3 → 4 columns when a page passes
     a fourth stat (Sources), and drops cleanly to 2 then 1 on narrow
     viewports without each page declaring its own grid. */
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--space-lg);
  padding-top: var(--space-xl);
  border-top: 1px solid var(--border);
}
@media (max-width: 640px) {
  .framework-overview-stats { grid-template-columns: 1fr; gap: var(--space-md); }
}
/* Stat cell layout — when an icon is present, the cell becomes a
   two-column flex row with the icon anchoring the left edge and the
   number+label stacked to its right. Without an icon (other pages that
   may use renderOverview later), the body div just fills the cell on
   its own. */
.framework-overview-stat {
  display: flex;
  align-items: center;
  gap: var(--space-md);
}
.framework-overview-stat-icon {
  flex: 0 0 auto;
  display: inline-flex;
  width: 28px;
  height: 28px;
  color: var(--text-secondary);
}
.framework-overview-stat-icon svg { width: 100%; height: 100%; display: block; }
.framework-overview-stat-body {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.framework-overview-stat-num {
  font-size: 24px;
  font-weight: 600;
  color: var(--text-primary);
  letter-spacing: -0.5px;
  line-height: 1.2;
}
.framework-overview-stat-label {
  font-size: 10px;
  color: var(--text-dim);
  letter-spacing: 1px;
  text-transform: uppercase;
  margin-top: 8px;
}

/* No-stats variant — Model has only kicker/title/sub, no stat strip
   on the right to occupy the slot a CTA or stats column would fill.
   Shrink the card to its content so the head's 720px cap defines the
   right edge and there's no empty quadrant beside the prose. */
.framework-overview:not(:has(.framework-overview-stats)) {
  width: fit-content;
  max-width: 100%;
}

/* ═══════════ MODEL PAGE — schematic + trace explorer ═══════════
   Two surfaces stacked: a static schematic establishing the
   Actions → Levers → Threats vocabulary, then a trace explorer that
   lets the user walk the graph by clicking. The selection model is
   one anchor at a time; the trace card surfaces its 1-hop neighbours
   in both directions with per-edge years promoted where the data
   carries them (lever ↔ threat). Action edges are connections only. */

/* ── Hero ─────────────────────────────────────────────────────────
   One composed surface: header text, schema flow, caption. Single
   outer card; the flow sits inside chromelessly as a figure inside
   an article. The three layers each get a visual that reflects what
   *kind* of thing the layer is — checklist for actions, sliders for
   levers, mortality bars for threats — so the columns can't be
   mistaken for each other at a glance. */
/* Matches Sources' framework-overview chrome: same padding + gap so
   the three top-of-page cards (Method hero, Model hero, Sources hero)
   read at one rhythm. Internal flow + caption divisions are carried by
   hairlines, not by extra outer padding. */
.model-hero {
  margin: 0 0 var(--space-3xl);
  padding: var(--space-xl);
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  display: flex;
  flex-direction: column;
  gap: var(--space-xl);
}
.model-hero-head {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  max-width: 720px;
}
.model-hero-title {
  font-size: 22px;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.3px;
  color: var(--text-primary);
  margin: 0;
}
.model-hero-lede {
  margin: 0;
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.6;
}

.model-hero-flow {
  display: grid;
  grid-template-columns: 1fr auto 1fr auto 1fr;
  gap: var(--space-md);
  align-items: start;
  padding-top: var(--space-xl);
  border-top: 1px solid var(--border-subtle);
}
@media (max-width: 720px) {
  .model-hero-flow {
    grid-template-columns: 1fr;
    gap: var(--space-lg);
  }
}

.model-layer {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-sm);
  position: relative;
  padding: var(--space-md) var(--space-sm) var(--space-sm);
  background: none;
  border: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  border-radius: 8px;
  transition: transform 0.25s ease, background-color 0.25s ease;
}
.model-layer:hover,
.model-layer:focus-visible {
  transform: translateY(-2px);
  background-color: var(--bg-surface);
}
.model-layer:focus-visible {
  outline: 2px solid var(--leverage);
  outline-offset: 2px;
}
/* Top-stripe encodes the axis: agency (green) → leverage (cyan) →
   severity (red). Matches the trace explorer's row-side bars below. */
.model-layer::before {
  content: "";
  position: absolute;
  inset: 0 20% auto;
  height: 2px;
  background: var(--text-dim);
  border-radius: 1px;
  transition: inset 0.25s ease;
}
.model-layer:hover::before,
.model-layer:focus-visible::before {
  inset: 0 10% auto;
}
.model-layer-action::before { background: var(--green); }
.model-layer-lever::before  { background: var(--leverage); }
.model-layer-threat::before { background: var(--red); }

.model-layer-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.model-layer-name {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 1.5px;
  text-transform: uppercase;
}
.model-layer-action .model-layer-name { color: var(--green); }
.model-layer-lever  .model-layer-name { color: var(--leverage); }
.model-layer-threat .model-layer-name { color: var(--red); }
.model-layer-count {
  font-size: 11px;
  color: var(--text-dim);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

.model-visual {
  display: block;
  width: 90px;
  height: 56px;
}
.model-layer-action .model-visual { color: var(--green); }
.model-layer-lever  .model-visual { color: var(--leverage); }
.model-layer-threat .model-visual { color: var(--red); }

/* ─── Visual hover animations ─────────────────────────────────────────
   Each layer's mini-diagram comes alive on hover with motion that maps
   to its semantic: actions tick themselves off, levers slide their
   markers, threats shrink their bars. SVG geometry properties (cx,
   x2, y, height) are animated via CSS — modern browsers only. */

/* Actions — staggered "todo completes itself" */
.model-action-row .model-action-box {
  fill-opacity: 0;
  opacity: 0.6;
  transition: fill-opacity 0.3s ease, opacity 0.3s ease;
}
.model-action-row .model-action-check {
  stroke-dasharray: 10;
  stroke-dashoffset: 10;
  transition: stroke-dashoffset 0.35s ease;
}
.model-action-row .model-action-line {
  opacity: 0.45;
  transition: opacity 0.3s ease;
}
.model-action-row.is-checked .model-action-box  { fill-opacity: 1; opacity: 1; }
.model-action-row.is-checked .model-action-check { stroke-dashoffset: 0; }
.model-action-row.is-checked .model-action-line { opacity: 0.8; }

.model-layer-action:hover .model-action-row:not(.is-checked) .model-action-box,
.model-layer-action:focus-visible .model-action-row:not(.is-checked) .model-action-box {
  fill-opacity: 1;
  opacity: 1;
  transition-delay: calc(var(--i, 0) * 110ms);
}
.model-layer-action:hover .model-action-row:not(.is-checked) .model-action-check,
.model-layer-action:focus-visible .model-action-row:not(.is-checked) .model-action-check {
  stroke-dashoffset: 0;
  transition-delay: calc(var(--i, 0) * 110ms + 90ms);
}
.model-layer-action:hover .model-action-row:not(.is-checked) .model-action-line,
.model-layer-action:focus-visible .model-action-row:not(.is-checked) .model-action-line {
  opacity: 0.8;
  transition-delay: calc(var(--i, 0) * 110ms);
}

/* Levers — staggered "marker glides" */
.model-lever-bg {
  stroke: currentColor;
  stroke-width: 1;
  opacity: 0.35;
}
.model-lever-fill {
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  transition: x2 0.6s cubic-bezier(0.4, 0, 0.2, 1);
  transition-delay: calc(var(--i, 0) * 90ms);
}
.model-lever-dot {
  fill: #fff;
  stroke: currentColor;
  stroke-width: 1.6;
  transition: cx 0.6s cubic-bezier(0.4, 0, 0.2, 1);
  transition-delay: calc(var(--i, 0) * 90ms);
}
.model-layer-lever:hover .model-lever-fill,
.model-layer-lever:focus-visible .model-lever-fill { x2: var(--to); }
.model-layer-lever:hover .model-lever-dot,
.model-layer-lever:focus-visible .model-lever-dot   { cx: var(--to); }

/* Threats — staggered "slam down" with overshoot, ghost outlines
   fade in to mark the reclaimed gap, baseline pulses brighter. */
.model-threat-ghost {
  opacity: 0;
  transition: opacity 0.45s ease;
  transition-delay: calc(var(--i, 0) * 80ms);
}
.model-threat-bar {
  transition: y 0.55s cubic-bezier(0.34, 1.56, 0.64, 1),
              height 0.55s cubic-bezier(0.34, 1.56, 0.64, 1),
              opacity 0.3s ease;
  transition-delay: calc(var(--i, 0) * 80ms);
}
.model-threat-base {
  transition: opacity 0.3s ease, stroke-width 0.3s ease;
}
.model-layer-threat:hover .model-threat-ghost,
.model-layer-threat:focus-visible .model-threat-ghost {
  opacity: calc(var(--base-opacity, 0.6) * 0.55);
}
.model-layer-threat:hover .model-threat-bar,
.model-layer-threat:focus-visible .model-threat-bar {
  y: var(--to-y);
  height: var(--to-h);
}
.model-layer-threat:hover .model-threat-base,
.model-layer-threat:focus-visible .model-threat-base {
  opacity: 0.85;
  stroke-width: 1.4;
}

@media (prefers-reduced-motion: reduce) {
  .model-layer,
  .model-layer::before,
  .model-action-box,
  .model-action-check,
  .model-action-line,
  .model-lever-fill,
  .model-lever-dot,
  .model-threat-bar,
  .model-threat-ghost,
  .model-threat-base {
    transition: none !important;
  }
}

.model-layer-def {
  font-size: 12px;
  font-weight: 500;
  color: var(--text-primary);
  letter-spacing: 0.2px;
}
.model-layer-examples {
  font-size: 11px;
  color: var(--text-dim);
  line-height: 1.5;
  max-width: 200px;
  letter-spacing: 0.2px;
}

.model-edge {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  color: var(--text-dim);
  min-width: 96px;
  padding-top: 56px;
}
.model-edge-svg {
  width: 80px;
  height: 12px;
}
.model-edge-verb {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-secondary);
}
@media (max-width: 720px) {
  .model-edge {
    position: relative;
    width: 100%;
    min-height: 42px;
    padding-top: 0;
    min-width: 0;
    flex-direction: row;
    justify-content: center;
    gap: 0;
  }
  .model-edge-svg {
    width: 52px;
    height: 12px;
    flex: 0 0 auto;
    transform: rotate(90deg);
  }
  .model-edge-verb {
    position: absolute;
    left: calc(50% + 28px);
    top: 50%;
    transform: translateY(-50%);
  }
}

.model-hero-caption {
  margin: 0;
  font-size: 12px;
  color: var(--text-secondary);
  line-height: 1.7;
  text-align: center;
  max-width: 640px;
  margin-left: auto;
  margin-right: auto;
  padding-top: var(--space-lg);
  border-top: 1px solid var(--border-subtle);
}
.model-hero-caption-link {
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  border-bottom: 1px dotted var(--border);
  transition: border-color 120ms ease;
}
.model-hero-caption-link:hover,
.model-hero-caption-link:focus-visible {
  border-bottom-color: var(--leverage);
  outline: none;
}

/* The return arc that closes the linear flow. Sits below the three
   layer cards; curves from below THREATS back up under ACTIONS with an
   arrowhead at the actions end and a "prioritizes" verb label centered
   in the arc's bowl. The verb mirrors the MOVES / REDUCES edges on the
   forward flow, completing the loop symmetrically. Hidden on narrow
   viewports where the flow stacks vertically. */
.model-hero-loop {
  position: relative;
  height: 44px;
  margin-top: 0;
  color: var(--text-dim);
}
.model-hero-loop-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.model-hero-loop-arrow {
  position: absolute;
  /* Arc path ends at viewBox (104, 9) inside the 800×44 SVG. With the
     SVG filling the 44px container, viewBox y=9 maps to css y=9.
     The chevron's wing base (polyline y=9 of viewBox 12×10) must sit
     at css y=9 so it caps the arc end cleanly — no curve poking
     through the V. top: 0 puts the chevron tip at css y=1 and wings
     at css y=9, kissing the arc tip exactly.
     Arc's left endpoint x=104/800 → 13%, ≈ Actions column center. */
  top: 0;
  left: calc(13% - 6px);
  width: 12px;
  height: 10px;
  color: var(--text-dim);
}
.model-hero-loop-verb {
  position: absolute;
  bottom: 2px;
  left: 50%;
  transform: translateX(-50%);
  padding: 0 8px;
  background: var(--bg-panel);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-secondary);
}
@media (max-width: 720px) {
  .model-hero-loop { display: none; }
}

/* ── Trace explorer ───────────────────────────────────────────────
   Picker rail (left) + trace card (right). The rail lists anchors
   of the active kind; the card is the focused neighborhood of the
   selected anchor. Kind tabs sit above both. */
.trace {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}
/* Same anchoring pattern as Sources' lit-sect-head — top hairline, a
   primary-colored uppercase kicker as the "section title", a dim
   one-line sub. Pulls the trace explorer into the same section-break
   register the rest of the overlay uses. */
.trace-head {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-top: var(--space-lg);
  border-top: 1px solid var(--border);
}
.trace-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
  letter-spacing: 1.8px;
  text-transform: uppercase;
  margin: 0;
}
.trace-sub {
  margin: 0;
  font-size: 12px;
  color: var(--text-dim);
  line-height: 1.6;
  letter-spacing: 0.2px;
}

.trace-tabs {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--border);
}
.trace-tab {
  appearance: none;
  background: transparent;
  border: 0;
  border-bottom: 2px solid transparent;
  padding: var(--space-sm) var(--space-md);
  font-family: inherit;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: -1px;
  transition: color 120ms ease, border-color 120ms ease;
}
/* Per-kind glyph that sits before the label — bars / sliders / check.
   Picks up the active tab's accent via currentColor; resting tabs
   inherit the dim label color so the icons stay paired with their
   text rather than out-shouting it. */
.trace-tab-icon {
  display: inline-flex;
  width: 16px;
  height: 16px;
  color: var(--text-dim);
  transition: color 120ms ease;
}
.trace-tab-icon svg { width: 100%; height: 100%; display: block; }
.trace-tab:hover .trace-tab-icon { color: var(--text-secondary); }
.trace-tab.active .trace-tab-icon { color: inherit; }
.trace-tab-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-dim);
}
.trace-tab-count {
  font-size: 11px;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
.trace-tab:hover .trace-tab-label { color: var(--text-secondary); }
.trace-tab.active {
  border-bottom-color: currentColor;
}
.trace-tab-threat.active { color: var(--red); }
.trace-tab-lever.active  { color: var(--leverage); }
.trace-tab-action.active { color: var(--green); }
.trace-tab.active .trace-tab-label { color: inherit; }

.trace-mobile-select,
.trace-picker-backdrop,
.trace-picker-sheet {
  display: none;
}

.trace-body {
  display: grid;
  grid-template-columns: minmax(220px, 280px) 1fr;
  gap: var(--space-md);
  /* Top-aligned columns: rail flows to natural height, card sticks so
     it stays in view as the page scrolls past long rails. No nested
     scroll container means no hidden-scrollbar problem to fight. */
  align-items: start;
}
@media (max-width: 920px) {
  .trace-body { grid-template-columns: 1fr; }
}
@media (max-width: 720px) {
  .trace {
    position: relative;
  }
  .trace-tabs {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .trace-tabs::-webkit-scrollbar { display: none; }
  .trace-tab {
    flex: 0 0 auto;
    padding-left: var(--space-sm);
    padding-right: var(--space-sm);
  }
  .trace-mobile-select {
    display: block;
    position: sticky;
    top: 96px;
    z-index: 4;
    margin-top: -4px;
    padding: 6px 0;
    background: var(--bg-panel);
  }
  .trace-mobile-trigger {
    width: 100%;
    min-height: 48px;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 10px;
    padding: 9px 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-surface);
    font-family: inherit;
    text-align: left;
    cursor: pointer;
  }
  .trace-mobile-trigger-kicker {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    color: var(--accent);
  }
  .trace-mobile-trigger-main {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
  }
  .trace-mobile-trigger-name {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .trace-mobile-trigger-group {
    font-size: 10px;
    letter-spacing: 1px;
    text-transform: uppercase;
    color: var(--text-dim);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .trace-mobile-trigger-caret {
    font-size: 16px;
    color: var(--text-dim);
  }
  .trace-body {
    display: block;
  }
  .trace-body > .trace-rail {
    display: none;
  }
  .trace-picker-backdrop {
    position: fixed;
    inset: 0;
    z-index: 70;
    background: rgba(15, 20, 30, 0.22);
  }
  .trace-picker-sheet {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 71;
    max-height: min(78vh, 640px);
    padding: 14px 14px max(18px, env(safe-area-inset-bottom));
    border-top: 1px solid var(--border);
    border-radius: 12px 12px 0 0;
    background: var(--bg-panel);
    box-shadow: 0 -12px 32px rgba(15, 20, 30, 0.14);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }
  .trace.is-picker-open .trace-picker-backdrop,
  .trace.is-picker-open .trace-picker-sheet {
    display: block;
  }
  .trace-picker-head {
    position: sticky;
    top: -14px;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-md);
    margin: -14px -14px 8px;
    padding: 14px;
    border-bottom: 1px solid var(--border);
    background: var(--bg-panel);
  }
  .trace-picker-kicker {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 1.4px;
    text-transform: uppercase;
    color: var(--text-dim);
  }
  .trace-picker-title {
    margin: 2px 0 0;
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    color: var(--text-primary);
  }
  .trace-picker-close {
    width: 34px;
    height: 34px;
    border: 0;
    border-radius: var(--radius-sm);
    background: var(--bg-surface);
    color: var(--text-secondary);
    font-family: inherit;
    font-size: 18px;
    cursor: pointer;
  }
  .trace-picker-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
  }
  .trace-picker-list .trace-rail-group + .trace-rail-group {
    margin-top: var(--space-sm);
  }
  .trace-picker-list .trace-rail-row {
    min-height: 40px;
    padding-top: 8px;
    padding-bottom: 8px;
  }
}

/* ── Anchor rail ── */
.trace-rail {
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.trace-rail-group {
  display: flex;
  flex-direction: column;
  gap: 0;
}
.trace-rail-group + .trace-rail-group { margin-top: var(--space-md); }
.trace-rail-group-head {
  display: flex;
  align-items: baseline;
  gap: var(--space-sm);
  padding: 14px 10px 6px 14px;
}
.trace-rail-group:first-child .trace-rail-group-head { padding-top: 6px; }
.trace-rail-group-label {
  font-size: 10px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-dim);
  font-weight: 600;
}
.trace-rail-row {
  appearance: none;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 4px;
  padding: 6px 10px 6px 20px;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  display: flex;
  align-items: center;
  gap: 8px;
  position: relative;
  transition: background-color 120ms ease;
}
.trace-rail-icon {
  display: inline-flex;
  flex: 0 0 auto;
  color: var(--text-dim);
  transition: color 120ms ease;
}
.trace-rail-row:hover .trace-rail-icon,
.trace-rail-row.active .trace-rail-icon { color: var(--red); }
.trace-rail-row:hover {
  background: var(--bg-hover);
}
.trace-rail-row.active {
  background: var(--bg-hover);
}
.trace-rail-row.active::before {
  content: "";
  position: absolute;
  left: 10px;
  top: 6px;
  bottom: 6px;
  width: 2px;
  border-radius: 1px;
  background: var(--text-primary);
}
.trace-rail-row.active .trace-rail-label {
  color: var(--text-primary);
  font-weight: 500;
}
.trace-rail-main {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  flex: 1 1 auto;
}
.trace-rail-label {
  font-size: 12px;
  font-weight: 400;
  color: var(--text-primary);
  line-height: 1.4;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.trace-rail-sub {
  font-size: 10px;
  color: var(--text-dim);
  letter-spacing: 0.3px;
  text-transform: uppercase;
}
.trace-rail-meta {
  font-size: 11px;
  font-weight: 400;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  flex: 0 0 auto;
}
.trace-rail-row.active .trace-rail-meta { color: var(--text-secondary); }

/* ── Trace track ───────────────────────────────────────────────────
   Three fixed bands stacked vertically: Threats / Levers / Actions.
   The selected node lives in its own band as a focal headline; the
   other two bands list its 1-hop neighbours. Bands never swap
   positions — the geometry is the lesson.

   No bordered card-in-card. The outer container is a single quiet
   surface; each band is separated by a hairline. Neighbour rows are
   hairline-divided too — list, not tile grid. */
.trace-track {
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.trace-band {
  padding: var(--space-md) var(--space-lg);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  border-top: 1px solid var(--border);
}
.trace-band:first-child { border-top: 0; }

/* Focal band — slightly more padding and a subtle tint so the eye
   lands on the selected node first. The band still doesn't change
   position; only the focal band carries this treatment. */
.trace-band.is-focal {
  padding-top: var(--space-lg);
  padding-bottom: var(--space-lg);
  background: var(--bg-surface);
}

.trace-band-head {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}
/* Per-kind glyph at the head of each band — same icon set as the
   trace tabs above. Color tracks the layer (red / cyan / green) so
   the band identity reads at a glance as the user scrolls the focal
   card, mirroring the active-tab color above. */
.trace-band-icon {
  display: inline-flex;
  width: 14px;
  height: 14px;
  flex: 0 0 auto;
}
.trace-band-icon svg { width: 100%; height: 100%; display: block; }
.trace-band-icon { color: var(--text-dim); }
.trace-band.is-focal.trace-band-threat .trace-band-icon { color: var(--red); }
.trace-band.is-focal.trace-band-lever  .trace-band-icon { color: var(--leverage); }
.trace-band.is-focal.trace-band-action .trace-band-icon { color: var(--green); }
.trace-band-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.trace-band-count {
  font-size: 11px;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
.trace-band-empty {
  margin: 0;
  font-size: 12px;
  color: var(--text-dim);
  font-style: italic;
}
.trace-band-group-head {
  display: flex;
  align-items: baseline;
  gap: var(--space-sm);
  padding: var(--space-sm) 14px 2px;
}
.trace-band-group-head:first-of-type { padding-top: 0; }
.trace-band-group-label {
  font-size: 10px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-dim);
}
/* Focal node — name + optional sub + meta line. Medium weight
   (not bold) on the name; the band dot and the "here" tag carry
   the visual emphasis instead of typographic weight. */
.trace-focal {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding-left: 14px; /* aligns under the dot + label rhythm */
}
.trace-focal.has-icon {
  flex-direction: row;
  align-items: flex-start;
  gap: var(--space-md);
}
.trace-focal-icon {
  display: inline-flex;
  flex: 0 0 auto;
  color: var(--red);
  margin-top: 2px;
}
.trace-focal-body {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
  flex: 1 1 auto;
}
.trace-focal-name {
  font-size: 17px;
  font-weight: 500;
  color: var(--text-primary);
  letter-spacing: -0.2px;
  line-height: 1.3;
}
.trace-focal-sub {
  font-size: 12px;
  color: var(--text-secondary);
  line-height: 1.5;
}
.trace-focal-meta {
  font-size: 12px;
  color: var(--text-secondary);
  margin-top: 2px;
}
.trace-focal-desc {
  margin: var(--space-sm) 0 0;
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.6;
  max-width: 64ch;
}
/* Focal "View sources" affordance — quiet bottom-bordered text link,
   matches the .lit-entry-link / .lit-cs-link grammar on the Sources
   page so the transition reads as continuous. */
.trace-focal-sources {
  appearance: none;
  background: transparent;
  border: 0;
  border-bottom: 1px solid transparent;
  margin: var(--space-md) 0 0;
  padding: 1px 0 2px;
  align-self: flex-start;
  cursor: pointer;
  font-family: inherit;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.6px;
  color: var(--accent);
  transition: border-color 120ms ease;
}
.trace-focal-sources:hover { border-bottom-color: var(--accent); }
.trace-focal-sources:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

/* Neighbour list — hairline-divided rows, no per-row border,
   no per-row background. */
.trace-band-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}
.trace-band-list > li + li { border-top: 1px solid var(--border-subtle); }
.trace-row {
  appearance: none;
  background: transparent;
  border: 0;
  padding: 8px 14px 8px 14px;
  margin: 0;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-md);
  width: 100%;
  transition: background-color 120ms ease;
}
.trace-row:hover { background: var(--bg-hover); }
.trace-row-main {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  min-width: 0;
  flex: 1 1 auto;
}
.trace-row-icon {
  display: inline-flex;
  flex: 0 0 auto;
  color: var(--text-dim);
  transition: color 120ms ease;
}
.trace-row:hover .trace-row-icon { color: var(--red); }
.trace-row-name {
  font-size: 13px;
  font-weight: 400;
  color: var(--text-primary);
  line-height: 1.4;
}
.trace-row-sub {
  font-size: 10px;
  color: var(--text-dim);
  letter-spacing: 0.3px;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.trace-row-years {
  font-size: 12px;
  font-weight: 400;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.2px;
  white-space: nowrap;
  flex: 0 0 auto;
}
/* Neutralize the leverage token inside the trace surface — the rows
   already form a column of Ny values; the color stripe is noise here. */
.trace-band .framework-leverage-token {
  color: inherit;
  font-weight: 400;
}
.trace-priority {
  font-size: 10px;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  color: var(--text-dim);
  white-space: nowrap;
  flex: 0 0 auto;
}

/* ═══════════ LITERATURE PAGE — bibliography reading list ═══════════
   Editorial table of contents, not a tile grid. Three layers stacked:

     1) Authorities masthead — italic wordmarks grouped into peer-
        reviewed journals and clinical guideline bodies. The social
        proof sits before any individual entry; the eye reads the
        institutions before reading a single takeaway.
     2) Filter rail — typographic taxonomy index, not chip pills. One
        line of text labels with a thin underline marking the active
        filter. Reads as a catalog filter, not a button bar.
     3) Bibliography list — each paper a two-column entry: a margin
        sidebar (year, journal, italic citation marginalia) and a body
        (title, italic abstract, threat + lever tag rows, link).
        Hairlines between entries; no card backgrounds, no card
        borders. The column rhythm and the typography do all the work.

   Citation counts are deliberately demoted — ~10px italic gray, the
   way a footnote sits beside a paragraph, not the way a stat sits in a
   dashboard. The year is the load-bearing identifier in each row.
   The page reads slowly and looks scholarly. */

.lit-board {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

/* ── Foundation reading (cornerstones triptych) ───────────────────
   No outer container — to avoid stacking two near-identical
   rounded rectangles, the section sheds its mat and lets three
   pillar cards float directly on the page background. The
   centered header sits in open space above them, marking a
   "section break" rather than a second hero panel. Topology is
   the differentiator: overview = one card; foundation = a row of
   discrete elements with no enclosing frame. */
.lit-cornerstones {
  position: relative;
  margin: var(--space-xl) 0 var(--space-2xl);
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

/* Shared section-head pattern across the Sources page. A top hairline
   anchors each section as its own stratum; the kicker + lede sit
   left-aligned with a constrained measure so heads read as editorial
   intros even when the content below spans full width. Without this
   structure the page reads flat — same width, same weight, no eye
   anchors between Foundation Reading / Browse by Domain / Bibliography. */
.lit-sect-head {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-top: var(--space-lg);
  border-top: 1px solid var(--border);
}
.lit-sect-kicker {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 1.8px;
  text-transform: uppercase;
  color: var(--text-primary);
}
.lit-sect-sub {
  font-size: 12px;
  color: var(--text-dim);
  line-height: 1.6;
  margin: 0;
  max-width: 64ch;
}
.lit-sect-sub em {
  font-style: normal;
  font-weight: 500;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
.lit-sect-sub strong {
  color: var(--text-primary);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* Bibliography head sits below the medallion grid with a touch more
   air above so the list reads as its own section, not a continuation
   of the grid. */
.lit-list-head {
  margin-top: var(--space-lg);
}

/* Cornerstones head — left-aligned (override the prior centered
   layout); inherits .lit-sect-head structure above. */
.lit-cornerstones-head { /* placeholder kept for future overrides */ }

.lit-cornerstones-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-md);
  align-items: stretch;
}
@media (max-width: 960px) {
  .lit-cornerstones-grid { grid-template-columns: 1fr; }
}

/* Pillars: bordered white cards arranged as an editorial entry —
   left-aligned, three zones (header / body / footer). Header pairs
   a framed icon with the topic kicker and source line; body holds
   the slug + takeaway; footer is the stat strip. Title-link
   stretches across the whole card for click. */
.lit-cornerstone {
  position: relative;
  display: grid;
  grid-template-rows: auto 1fr auto;
  align-items: start;
  row-gap: var(--space-md);
  padding: var(--space-md);
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  text-align: left;
  opacity: 0;
  transform: translateY(12px);
  animation: lit-cs-rise 560ms cubic-bezier(0.22, 0.61, 0.36, 1) var(--cs-delay, 0ms) forwards;
  transition: border-color 160ms ease, box-shadow 160ms ease;
}
.lit-cornerstone:hover {
  border-color: rgba(8, 145, 178, 0.45);
  box-shadow: 0 1px 0 rgba(8, 145, 178, 0.06);
}
@keyframes lit-cs-rise {
  to { opacity: 1; transform: translateY(0); }
}

/* Stretched click target — anchor occupies the whole card so the
   user doesn't have to aim at the title. Visually invisible. */
.lit-cs-title-link {
  position: absolute;
  inset: 0;
  z-index: 1;
  text-indent: -9999px;
  overflow: hidden;
}

/* Header zone — icon left, topic + venue text right. Tight little
   masthead at the top of every card. */
.lit-cs-head {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  width: 100%;
  padding-bottom: var(--space-sm);
  border-bottom: 1px solid var(--border-subtle);
}
.lit-cs-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent);
}
.lit-cs-icon svg {
  width: 24px;
  height: 24px;
  display: block;
}
.lit-cs-head-text {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}
.lit-cs-topic-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.8px;
  text-transform: uppercase;
  color: var(--accent);
}
.lit-cs-source {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  font-size: 11px;
  color: var(--text-dim);
  letter-spacing: 0.2px;
}
.lit-cs-source-venue { font-style: italic; color: var(--text-secondary); }
.lit-cs-source-year { font-variant-numeric: tabular-nums; }
.lit-cs-source-sep { opacity: 0.55; }

/* Body zone — slug on top (small italic, since the labels are slug-
   like, not real titles), takeaway below as the primary read. Left-
   aligned monospace at 12.5px / 1.6 reads cleanly. */
.lit-cs-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-self: start;
}
.lit-cs-slug {
  font-size: 11px;
  font-style: italic;
  color: var(--text-secondary);
  line-height: 1.45;
  margin: 0;
}
.lit-cs-takeaway {
  font-size: 12.5px;
  font-weight: 400;
  color: var(--text-primary);
  line-height: 1.6;
  margin: 0;
}

/* Footer stat strip — left-aligned to match the rest of the card,
   separated by a hairline. */
.lit-cs-reach {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: flex-start;
  gap: 10px;
  padding-top: var(--space-sm);
  border-top: 1px solid var(--border-subtle);
  width: 100%;
}
.lit-cs-stat {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
}
.lit-cs-stat-num {
  font-size: 12.5px;
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
  letter-spacing: -0.1px;
}
.lit-cs-stat-label {
  font-size: 10px;
  letter-spacing: 0.4px;
  text-transform: lowercase;
  color: var(--text-dim);
}
.lit-cs-stat-hero .lit-cs-stat-num {
  font-size: 14px;
  font-weight: 500;
  letter-spacing: -0.1px;
}
.lit-cs-stat-standard {
  text-transform: uppercase;
  font-weight: 600;
  letter-spacing: 1px;
  font-size: 9px;
  color: var(--text-secondary);
}
.lit-cs-stat-sep { color: var(--text-dim); opacity: 0.45; font-size: 11px; }

/* ── Authorities masthead ─────────────────────────────────────────
   Two grouped rows of italic wordmarks beneath the hero. Roman
   numerals on each row head reinforce the editorial register.
   Hairlines top + bottom, no panel chrome — the strip lives on the
   page background, not in a card, so it reads as a masthead, not a
   sidebar widget. */
.lit-mast {
  margin: var(--space-2xl) 0 var(--space-2xl);
  padding: var(--space-xl) 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}
.lit-mast-head {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  max-width: 640px;
}
.lit-mast-kicker {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--text-dim);
}
.lit-mast-lede {
  font-size: 12px;
  color: var(--text-secondary);
  line-height: 1.7;
  margin: 0;
}
.lit-mast-lede em {
  font-style: italic;
  font-weight: 500;
  color: var(--text-primary);
}

.lit-mast-row {
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: var(--space-xl);
  align-items: baseline;
  padding-top: var(--space-md);
  border-top: 1px solid var(--border-subtle);
}
@media (max-width: 720px) {
  .lit-mast-row {
    grid-template-columns: 1fr;
    gap: var(--space-sm);
  }
}
.lit-mast-rowhead {
  display: flex;
  align-items: baseline;
  gap: var(--space-sm);
}
.lit-mast-rowhead-roman {
  font-size: 12px;
  font-style: italic;
  font-weight: 400;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  width: 18px;
  letter-spacing: 0.5px;
}
.lit-mast-rowhead-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.lit-mast-rowhead-count {
  font-size: 10px;
  font-weight: 600;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  margin-left: auto;
}
.lit-mast-rowbody {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  min-width: 0;
}

/* Tier-1 stamps — bordered bibliographic plates for high-prestige
   venues. The border gives the names visual weight against the
   italicized long-tail list that follows, and the row reads as a
   masthead row of journal nameplates. */
.lit-mast-stamps {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 8px;
  list-style: none;
  padding: 0;
  margin: 0;
}
.lit-mast-stamp {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: var(--bg-panel);
  transition: border-color 120ms ease, color 120ms ease;
}
.lit-mast-stamp:hover {
  border-color: var(--text-dim);
}
.lit-mast-stamp-name {
  font-size: 12px;
  font-weight: 500;
  color: var(--text-primary);
  letter-spacing: -0.1px;
}
.lit-mast-stamp-count {
  font-size: 10px;
  font-weight: 500;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.3px;
}

.lit-mast-list {
  display: flex;
  flex-wrap: wrap;
  gap: 4px var(--space-md);
  list-style: none;
  padding: 0;
  margin: 0;
  font-size: 12px;
  line-height: 1.7;
}
.lit-mast-item {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
}
.lit-mast-name {
  font-style: italic;
  font-weight: 400;
  color: var(--text-secondary);
  letter-spacing: 0.1px;
}
.lit-mast-count {
  font-size: 9px;
  font-weight: 500;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.4px;
  position: relative;
  top: -1px;
}

/* Guideline bodies — clean acronyms (USPSTF · KDIGO · WHO ...). Read
   as institutional shorthand, not italicized prose. */
.lit-mast-bodies {
  display: flex;
  flex-wrap: wrap;
  gap: 4px var(--space-md);
  list-style: none;
  padding: 0;
  margin: 0;
}
.lit-mast-body {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  font-size: 12px;
  line-height: 1.6;
}
.lit-mast-body-name {
  font-weight: 600;
  letter-spacing: 0.4px;
  color: var(--text-secondary);
}
.lit-mast-body-count {
  font-size: 9px;
  font-weight: 500;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.4px;
  position: relative;
  top: -1px;
}

/* ── Scope banner ─────────────────────────────────────────────────
   Shown only when Sources is opened from the Model page's focal
   "View sources" affordance. Replaces the category chip rail in
   that mode — a single banner row that names the threat / lever /
   action being scoped to, with a Clear button to return to the
   full list. Uses the accent rail color so it reads as a different
   register from the regular category filter. */
.lit-scope {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  padding: 12px 14px;
  margin-bottom: var(--space-lg);
  background: rgba(8, 145, 178, 0.06);
  border: 1px solid rgba(8, 145, 178, 0.22);
  border-radius: var(--radius-md);
}
.lit-scope-kicker {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--accent);
}
.lit-scope-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
  letter-spacing: -0.1px;
}
.lit-scope-count {
  font-size: 11px;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
.lit-scope-clear {
  appearance: none;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 4px 10px;
  margin-left: auto;
  cursor: pointer;
  font-family: inherit;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.4px;
  color: var(--text-secondary);
  transition: border-color 120ms ease, color 120ms ease;
}
.lit-scope-clear:hover {
  color: var(--text-primary);
  border-color: var(--text-secondary);
}

/* ── Domain medallions ────────────────────────────────────────────
   Ten clickable cards — one per threat — that replace the old chip
   filter. Each medallion carries a cause-of-death glyph (the same
   icons used on the Model page), the threat name, its paper count,
   and a thin weight bar normalized to the highest-paper domain.
   The grid reads two ways at once: a credibility scan (every domain
   is covered) and the page's primary filter (click to scope the
   bibliography below). */
.lit-domains {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
  padding-bottom: var(--space-lg);
}
/* Filtered-state row layout — the kicker, lede, and Show-all button
   collapse onto one line. Overrides the column layout from
   .lit-sect-head. The accent recolor signals the filter is active. */
.lit-domains-head.is-filtered {
  flex-direction: row;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--space-sm) var(--space-md);
  max-width: none;
}
.lit-domains-head.is-filtered .lit-sect-kicker { color: var(--accent); }
.lit-domains-clear {
  appearance: none;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 4px 10px;
  margin-left: auto;
  cursor: pointer;
  font-family: inherit;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.4px;
  color: var(--text-secondary);
  transition: border-color 120ms ease, color 120ms ease;
}
.lit-domains-clear:hover {
  color: var(--text-primary);
  border-color: var(--text-secondary);
}

.lit-domains-grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--space-sm);
  list-style: none;
  padding: 0;
  margin: 0;
}
@media (max-width: 960px) {
  .lit-domains-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .lit-domains-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.lit-domain {
  appearance: none;
  width: 100%;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-md) var(--space-sm) 0;
  font-family: inherit;
  text-align: center;
  cursor: pointer;
  display: grid;
  grid-template-rows: auto auto auto 4px;
  row-gap: 6px;
  align-items: start;
  justify-items: center;
  position: relative;
  overflow: hidden;
  transition:
    border-color 140ms ease,
    background-color 140ms ease,
    transform 140ms ease,
    opacity 180ms ease;
}
.lit-domain:hover {
  border-color: var(--text-dim);
  background: var(--bg-surface);
  transform: translateY(-1px);
}
.lit-domain:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.lit-domain.active {
  border-color: var(--accent);
  background: var(--accent-soft);
}
.lit-domain.dim {
  opacity: 0.42;
}
.lit-domain.dim:hover {
  opacity: 0.85;
}
.lit-domain.empty {
  cursor: not-allowed;
  opacity: 0.32;
}
.lit-domain.empty:hover {
  transform: none;
  background: var(--bg-panel);
  border-color: var(--border);
}

/* Resting icon is muted graphite — the grid is a credibility scan,
   not a severity readout. Saturated red would conflate "we have
   evidence here" with "you are in danger here" (the meaning the same
   glyph carries on Risks/Model). Active state picks up the accent. */
.lit-domain-icon {
  display: inline-flex;
  color: var(--text-secondary);
  width: 32px;
  height: 32px;
  transition: color 140ms ease;
}
.lit-domain-icon svg { width: 100%; height: 100%; display: block; }
.lit-domain.active .lit-domain-icon { color: var(--accent); }
.lit-domain:hover:not(.active):not(.empty) .lit-domain-icon { color: var(--text-primary); }

.lit-domain-name {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-secondary);
  line-height: 1.3;
  max-width: 100%;
  word-break: break-word;
}
.lit-domain.active .lit-domain-name { color: var(--text-primary); }

.lit-domain-count {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  padding-bottom: var(--space-sm);
}
.lit-domain-count-num {
  font-size: 18px;
  font-weight: 600;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.3px;
  line-height: 1;
}
.lit-domain-count-label {
  font-size: 10px;
  color: var(--text-dim);
  letter-spacing: 0.4px;
}
.lit-domain.active .lit-domain-count-num { color: var(--accent); }
.lit-domain.empty .lit-domain-count-num { color: var(--text-dim); }

/* Weight bar — sits flush at the bottom edge, width proportional to
   that domain's share of the corpus. Quiet by default; saturates on
   the active medallion. */
.lit-domain-bar {
  position: absolute;
  left: 0;
  bottom: 0;
  height: 3px;
  width: calc(var(--weight, 0) * 100%);
  background: linear-gradient(to right, color-mix(in srgb, var(--text-dim) 45%, transparent), color-mix(in srgb, var(--text-secondary) 70%, transparent));
  transition: background 140ms ease, width 220ms ease;
}
.lit-domain.active .lit-domain-bar {
  background: linear-gradient(to right, color-mix(in srgb, var(--accent) 55%, transparent), var(--accent));
}
.lit-domain.dim .lit-domain-bar { opacity: 0.5; }
.lit-domain.empty .lit-domain-bar { background: transparent; }

/* ── Bibliography list ────────────────────────────────────────────
   Single-column entries with a top meta line ("journal · year ·
   citations"), then the title (the loudest element in the row), then
   the italic abstract, then the tag rows, then the link. Hairline
   dividers; no card chrome. The title is what the eye lands on first;
   everything else reads as supporting metadata around it. */
.lit-list {
  display: flex;
  flex-direction: column;
}
.lit-entry {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  padding: var(--space-xl) 0;
  border-bottom: 1px solid var(--border);
}
@media (max-width: 720px) {
  .lit-entry { padding: var(--space-lg) 0; }
}

/* Bibliographic header — one inline phrase. Italic for the venue
   (the journal name, in the way bibliographies italicize publications),
   normal for the year and citation count, all small and dim. The
   separator is its own span so the gap is the same on both sides
   regardless of the surrounding text. */
.lit-entry-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px;
  font-size: 11px;
  color: var(--text-dim);
  letter-spacing: 0.2px;
  line-height: 1.5;
}
.lit-entry-meta-venue {
  font-style: italic;
  font-weight: 500;
  color: var(--text-secondary);
}
.lit-entry-meta-year {
  font-variant-numeric: tabular-nums;
  color: var(--text-secondary);
}
.lit-entry-meta-cite {
  font-variant-numeric: tabular-nums;
  color: var(--text-dim);
}
.lit-entry-meta-standard {
  font-weight: 600;
  letter-spacing: 1px;
  text-transform: uppercase;
  font-size: 9px;
  color: var(--text-secondary);
}
.lit-entry-meta-sep {
  color: var(--text-dim);
  opacity: 0.55;
}

.lit-entry-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
  line-height: 1.4;
  letter-spacing: -0.1px;
  margin: 0;
}
.lit-entry-abstract {
  font-size: 13px;
  font-style: italic;
  color: var(--text-secondary);
  line-height: 1.75;
  margin: 4px 0 var(--space-sm);
  max-width: 72ch;
}

/* Tag rows: small uppercase label in a fixed-width column on the
   left, the tags themselves on the right. Two-column rhythm
   echoes the entry-level sidebar/body split. */
.lit-entry-row {
  display: grid;
  grid-template-columns: 120px 1fr;
  gap: var(--space-md);
  align-items: baseline;
}
@media (max-width: 720px) {
  .lit-entry-row {
    grid-template-columns: 1fr;
    gap: 4px;
  }
}
.lit-entry-row-label {
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-dim);
  line-height: 1.6;
}
.lit-entry-row-list {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  align-items: baseline;
}
.lit-entry-threat {
  font-size: 10px;
  letter-spacing: 0.3px;
  color: var(--text-secondary);
  padding: 2px 7px;
  border: 1px solid var(--border);
  border-radius: 3px;
  white-space: nowrap;
}
.lit-entry-lever {
  font-size: 10px;
  color: var(--leverage);
  background: var(--leverage-bg);
  padding: 2px 7px;
  border-radius: 3px;
  letter-spacing: 0.2px;
  white-space: nowrap;
}
.lit-entry-more {
  font-size: 10px;
  font-style: italic;
  color: var(--text-dim);
  letter-spacing: 0.2px;
  padding: 2px 4px;
}

.lit-entry-link {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.6px;
  color: var(--accent);
  text-decoration: none;
  align-self: flex-start;
  margin-top: 4px;
  padding-bottom: 1px;
  border-bottom: 1px solid transparent;
  transition: border-color 120ms ease;
}
.lit-entry-link:hover { border-bottom-color: var(--accent); }

.lit-empty {
  padding: var(--space-2xl) 0;
  text-align: center;
  font-size: 13px;
  font-style: italic;
  color: var(--text-dim);
}

/* ═══════════ FRAMEWORK TOUR OUTRO ═══════════
   Tail-end exit ramp sitting after the trace explorer. Centered,
   separated from the explorer by a hairline rule, framed by a short
   prompt above the .method-hero-cta button. The button itself keeps
   its legacy class names so the dial/bracket choreography is reused. */
.framework-tour-outro {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin-top: var(--space-xl);
  padding-top: var(--space-xl);
  border-top: 1px solid var(--border-subtle);
}
.framework-tour-outro-prompt {
  margin: 0;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-dim);
}


/* ═══════════ METHODOLOGY PAGE ═══════════
   Depersonalized teaching page. Mirrors the Framework tab's two-surface
   cadence: one hero card (explainer) + one section-break tool (goals +
   rail + inspector), then a footnote. The hero chassis matches
   .model-hero; the tool head matches .trace-head. */

.years-page {
  display: flex;
  flex-direction: column;
  gap: var(--space-3xl);
}

.years-token {
  color: var(--accent);
  font-weight: 600;
}

/* ── Hero (explainer) ─ mirrors .model-hero ── */
.years-hero {
  padding: var(--space-xl);
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  display: flex;
  flex-direction: column;
  gap: var(--space-xl);
}
.years-hero-head {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  max-width: 720px;
}
.years-hero-title {
  font-size: 22px;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.3px;
  color: var(--text-primary);
  margin: 0;
}
.years-hero-lede {
  margin: 0;
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.6;
}
.years-hero-lede strong {
  color: var(--text-primary);
  font-weight: 600;
}
.years-hero-lede em {
  font-style: italic;
  color: var(--text-secondary);
}

/* Apportionment bar — the load-bearing visual. Thin track shows the
   apportionment as proportional widths; labels sit BELOW each segment
   in a flex-matched row so the eye reads "bar with labels", not "row of
   cards". Top hairline + padding mirror .model-hero-flow's separator. */
.years-bar {
  margin: 0;
  padding: var(--space-xl) 0 0;
  border-top: 1px solid var(--border-subtle);
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}
.years-bar-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-md);
}
.years-bar-kicker {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--text-dim);
}
.years-bar-anchor {
  font-size: 16px;
  font-weight: 600;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.3px;
}

/* The bar itself: a single thin, continuous track. Segments distinguished
   by tonal opacity shifts of the leverage accent — no internal borders,
   no per-segment chrome. */
.years-bar-track {
  display: flex;
  height: 20px;
  border-radius: 4px;
  overflow: hidden;
  background: var(--bg-surface);
}
.years-bar-seg {
  min-width: 0;
  transition: filter 120ms ease;
}
.years-bar-seg:hover { filter: brightness(0.96); }

/* Three tones on the same hue — more-saturated = more agency. Lifestyle
   is the most direct lever, screening the most passive. */
.years-bar-seg-lifestyle { background: var(--leverage); }
.years-bar-seg-clinical  { background: var(--leverage); opacity: 0.65; }
.years-bar-seg-screening { background: var(--leverage); opacity: 0.35; }

/* Legend row: flex-basis: 0 + matching flex-grow ensures each cell's
   column width is EXACTLY the same proportion as its bar segment, so
   labels visually anchor to the leading edge of their slice. */
.years-bar-legend {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  gap: 0;
}
.years-bar-legend-item {
  flex-basis: 0;
  flex-shrink: 1;
  min-width: 0;
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding-right: 12px;
}
.years-bar-legend-item:last-child { padding-right: 0; }

.years-bar-legend-swatch {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  margin-top: 5px;
}
.years-bar-legend-body {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}
.years-bar-legend-name {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.years-bar-legend-years {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  line-height: 1.2;
}

/* ── Tool (goals) ─ mirrors .trace + .trace-head ── */
.years-tool {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}
.years-tool-head {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-top: var(--space-lg);
  border-top: 1px solid var(--border);
  max-width: 720px;
}
.years-tool-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
  letter-spacing: 1.8px;
  text-transform: uppercase;
  margin: 0;
}
.years-tool-sub {
  margin: 0;
  font-size: 12px;
  color: var(--text-dim);
  line-height: 1.6;
  letter-spacing: 0.2px;
}

/* ── Goals: rail + inspector ── */
.years-goals {
  display: grid;
  grid-template-columns: minmax(220px, 280px) 1fr;
  gap: var(--space-md);
  align-items: start;
}
@media (max-width: 820px) {
  .years-goals { grid-template-columns: 1fr; }
}

.years-mobile-select,
.years-picker-backdrop,
.years-picker-sheet {
  display: none;
}
@media (max-width: 720px) {
  .years-mobile-select {
    display: block;
    position: sticky;
    top: 96px;
    z-index: 4;
    margin-top: -4px;
    padding: 6px 0;
    background: var(--bg-panel);
  }
  .years-mobile-trigger {
    width: 100%;
    min-height: 50px;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    align-items: center;
    gap: 10px;
    padding: 9px 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-surface);
    font-family: inherit;
    text-align: left;
    cursor: pointer;
  }
  .years-mobile-trigger-kicker {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    color: var(--accent);
  }
  .years-mobile-trigger-main {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
  }
  .years-mobile-trigger-name {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .years-mobile-trigger-group {
    font-size: 10px;
    letter-spacing: 1px;
    text-transform: uppercase;
    color: var(--text-dim);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .years-mobile-trigger-years {
    font-size: 12px;
    font-weight: 600;
    color: var(--accent);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }
  .years-mobile-trigger-caret {
    font-size: 16px;
    color: var(--text-dim);
  }
  .years-goals {
    display: block;
  }
  .years-goals > .years-rail {
    display: none;
  }
  .years-picker-backdrop {
    position: fixed;
    inset: 0;
    z-index: 70;
    background: rgba(15, 20, 30, 0.22);
  }
  .years-picker-sheet {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 71;
    max-height: min(78vh, 640px);
    padding: 14px 14px max(18px, env(safe-area-inset-bottom));
    border-top: 1px solid var(--border);
    border-radius: 12px 12px 0 0;
    background: var(--bg-panel);
    box-shadow: 0 -12px 32px rgba(15, 20, 30, 0.14);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }
  .years-tool.is-picker-open .years-picker-backdrop,
  .years-tool.is-picker-open .years-picker-sheet {
    display: block;
  }
  .years-picker-head {
    position: sticky;
    top: -14px;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-md);
    margin: -14px -14px 8px;
    padding: 14px;
    border-bottom: 1px solid var(--border);
    background: var(--bg-panel);
  }
  .years-picker-kicker {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 1.4px;
    text-transform: uppercase;
    color: var(--text-dim);
  }
  .years-picker-title {
    margin: 2px 0 0;
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    color: var(--text-primary);
  }
  .years-picker-close {
    width: 34px;
    height: 34px;
    border: 0;
    border-radius: var(--radius-sm);
    background: var(--bg-surface);
    color: var(--text-secondary);
    font-family: inherit;
    font-size: 18px;
    cursor: pointer;
  }
  .years-picker-sheet .years-rail {
    display: flex;
    position: static;
    border: 0;
    padding: 0;
    border-radius: 0;
    max-height: none;
    overflow: visible;
  }
  .years-picker-sheet .years-rail-btn {
    min-height: 42px;
  }
}

.years-rail {
  list-style: none;
  margin: 0;
  padding: 4px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-panel);
  position: sticky;
  top: 12px;
  max-height: calc(100vh - 80px);
  overflow-y: auto;
}
.years-rail-btn {
  width: 100%;
  display: grid;
  grid-template-columns: minmax(80px, 1fr) minmax(40px, 70px) 44px;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border: none;
  border-radius: 4px;
  background: transparent;
  font-family: var(--font-mono);
  font-size: 12px;
  text-align: left;
  cursor: pointer;
  transition: background 120ms ease;
}
.years-rail-btn:hover {
  background: var(--bg-hover);
}
.years-rail-row.is-active .years-rail-btn {
  background: var(--accent-soft);
}
.years-rail-label {
  font-size: 12px;
  font-weight: 500;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.years-rail-row.is-active .years-rail-label {
  color: var(--text-primary);
  font-weight: 600;
}
.years-rail-track {
  position: relative;
  height: 6px;
  background: var(--bg-surface);
  border-radius: 2px;
  overflow: hidden;
}
.years-rail-fill {
  position: absolute;
  inset: 0 auto 0 0;
  background: var(--text-dim);
  opacity: 0.7;
  border-radius: 2px;
}
.years-rail-row.is-active .years-rail-fill,
.years-rail-btn:hover .years-rail-fill {
  background: var(--accent);
  opacity: 1;
}
.years-rail-num {
  text-align: right;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
.years-rail-num-unit {
  font-size: 10px;
  font-weight: 500;
  color: var(--text-dim);
  margin-left: 1px;
}

/* ── Inspector ── */
.years-inspector {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-panel);
  padding: 20px 22px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-width: 0;
}
.years-inspector-head {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: start;
  gap: var(--space-md);
  padding-bottom: 14px;
  border-bottom: 1px solid var(--border-subtle);
}
.years-inspector-head-main {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.years-inspector-total {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  padding-top: 4px;
}
.years-inspector-total-num {
  font-size: 28px;
  font-weight: 600;
  letter-spacing: -0.5px;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.years-inspector-total-unit {
  font-size: 16px;
  font-weight: 500;
  color: var(--accent);
  margin-left: 1px;
}
.years-inspector-total-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-dim);
}
.years-inspector-cat {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-dim);
}
.years-inspector-title {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.2px;
  color: var(--text-primary);
}
.years-inspector-sub {
  margin: 2px 0 0;
  font-size: 12px;
  color: var(--text-secondary);
}
.years-inspector-goal {
  margin: 8px 0 0;
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  padding: 5px 10px;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: 4px;
  align-self: flex-start;
}
.years-inspector-goal-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-dim);
}
.years-inspector-goal-value {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
.years-inspector-desc {
  margin: 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--text-secondary);
}

/* ── Per-threat ledger ── */
.years-threats {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.years-threat {
  padding: 10px 12px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background: var(--bg-surface);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.years-threat-row {
  display: grid;
  grid-template-columns: 20px minmax(100px, 140px) 1fr 52px;
  align-items: center;
  gap: 10px;
}
.years-threat-icon {
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--text-secondary);
}
.years-threat-icon svg {
  width: 100%;
  height: 100%;
  display: block;
}
.years-threat-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.years-threat-track {
  position: relative;
  height: 8px;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: 2px;
  overflow: hidden;
}
.years-threat-fill {
  position: absolute;
  inset: 0 auto 0 0;
  background: var(--accent);
  opacity: 0.7;
}
.years-threat-num {
  text-align: right;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
.years-threat-evidence {
  margin: 0;
  padding-left: 34px;
  font-size: 12px;
  line-height: 1.6;
  color: var(--text-secondary);
}

/* ── Sources ── */
.years-sources {
  margin-top: 4px;
  padding-top: 16px;
  border-top: 1px solid var(--border-subtle);
}
.years-sources-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: 10px;
}
.years-sources-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.years-source {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  font-size: 12px;
  line-height: 1.5;
}
.years-source-link {
  color: var(--text-primary);
  text-decoration: none;
  border-bottom: 1px dotted var(--text-dim);
}
.years-source-link:hover {
  color: var(--accent);
  border-bottom-color: var(--accent);
}
.years-source-meta {
  font-size: 11px;
  color: var(--text-dim);
}

