/* =============================================================================
   components.css — reusable building blocks (flat report design, Step 5)
   -----------------------------------------------------------------------------
   Rewritten from scratch for report-v2/index.html. The old root `css/components.css`
   (3755 lines) was mostly a scroll-hijacking "scrollytelling" engine — pinned
   chart+text slides, per-operation/geography/temporal/agency slide positioning,
   the chapter-jump roadmap widget, canister scene choreography. NONE of that
   pinning/step logic is ported here.

   PORTED VERBATIM: buttons, chart/tooltip/donut/geo-chart/heatmap internals
   (targets the same DOM charts.js renders), .note, .reveal fade-in utility,
   .findings-figure/figcaption, .topline-band, data tables, methods-overview
   grid, principle-card styling, the Legal section's OWN `.principles-scrolly`
   (explicitly out of scope for removal per PLAN.md), claims-grid, body-map,
   loading-screen.

   RE-DERIVED as flat equivalents (no position/scroll-step rules): operation
   cards (.findings-op-card/.ops-head*), canister feature cards
   (.canister-cards/.canister-card*), the incidents stat figure
   (.incidents-stat-figure*, now a normal 3-panel flex row), native
   <details class="methods-detail">, .findings-chapter heading rule (fresh —
   the old chapter roadmap widget it replaces is dropped entirely).

   DROPPED as dead weight: .scrolly/.scrolly__stage/.scrolly__slide and every
   slide-layout variant, .chapter-nav roadmap bar, .findings-roadmap index,
   injury carousels (unused in new markup), canister-scene choreography,
   conclusion-cards/recommendation-cards/finding-cards/rank-box/mk9-compare
   (none referenced by report-v2/content.csv's `class` column or index.html).
   ============================================================================ */

/* --- Buttons -------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; gap: var(--space-2);
  font-family: var(--font-sans); font-size: var(--fs-sm); font-weight: 700;
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--phr-red); border-radius: var(--radius);
  background: var(--phr-red); color: var(--white);
  cursor: pointer;
}
.btn:hover { background: #b3001a; text-decoration: none; }
.btn--ghost { background: transparent; color: var(--phr-red); }
.btn--ghost:hover { background: var(--phr-red); color: var(--white); }

/* --- Figure / chart framing ------------------------------------------------ */
figure { margin: var(--space-4) 0; max-width: var(--content-max); }
figcaption {
  font-family: var(--font-sans); font-size: var(--fs-xs);
  color: var(--color-text-muted); margin-top: var(--space-2);
}

/* --- Wide figures with captions (base wrapper for nearly every Findings
   chart/image figure) -------------------------------------------------------- */
.findings-figure { margin: var(--space-5) 0; max-width: var(--content-max); }
.findings-figure .chart--wide { max-width: 920px; }
.findings-figure .chart--donut { max-width: 460px; }
.findings-figure figcaption {
  margin-top: var(--space-2);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  color: var(--color-text-muted);
  max-width: var(--measure);
}
.findings-figure img {
  display: block; width: 100%; max-width: 860px; height: auto;
  border: 1px solid var(--color-border); border-radius: var(--radius);
  background: var(--white); padding: var(--space-3);
}

.findings-figure--expandable {
  cursor: zoom-in;
}
.findings-figure--expandable:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--phr-red) 70%, var(--white));
  outline-offset: 4px;
}
.findings-figure--expandable figcaption::after {
  content: " Click to enlarge.";
  color: var(--phr-red);
  font-weight: 700;
}
.figure-dialog {
  width: min(1120px, calc(100vw - 48px));
  max-width: none;
  max-height: calc(100vh - 48px);
  padding: var(--space-4);
  border: 0;
  border-radius: var(--radius);
  background: var(--white);
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.28);
}
.figure-dialog::backdrop {
  background: rgba(17, 24, 39, 0.58);
}
.figure-dialog__close {
  position: absolute;
  top: var(--space-2);
  right: var(--space-2);
  display: inline-grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border: 1px solid var(--color-border);
  border-radius: 50%;
  background: var(--white);
  color: var(--color-text);
  font-family: var(--font-sans);
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
}
.figure-dialog__close:hover,
.figure-dialog__close:focus-visible {
  border-color: var(--phr-red);
  color: var(--phr-red);
}
.figure-dialog__body {
  overflow: auto;
  max-height: calc(100vh - 96px);
  padding-right: var(--space-2);
}
.figure-dialog .findings-figure {
  max-width: none;
  margin: 0;
  cursor: default;
}
.figure-dialog .findings-figure figcaption {
  max-width: 760px;
}
.figure-dialog .findings-figure figcaption::after {
  content: "";
}
.figure-dialog .chart--wide,
.figure-dialog .chart--clinical {
  max-width: none;
}
.figure-dialog .chart-svg {
  max-height: calc(100vh - 190px);
}
@media (max-width: 640px) {
  .figure-dialog {
    width: calc(100vw - 24px);
    max-height: calc(100vh - 24px);
    padding: var(--space-3);
  }
  .figure-dialog__body {
    max-height: calc(100vh - 72px);
  }
}

/* --- Findings' embedded geography map (js/map.js, a second Leaflet instance
   from the main Map section's) — same sizing/tone treatment as #map in
   map.css, just shorter since it's mid-article rather than the destination. */
.findings-map {
  width: 100%;
  max-width: 920px;
  height: clamp(320px, 46vh, 480px);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-bg-muted);
  z-index: 1;
}

/* --- Charts (rendered by js/charts.js) -----------------------------------
   The SVG scales to its container; a max-width keeps text legible. */
.chart { width: 100%; max-width: 680px; }
.chart-svg {
  width: 100%;
  height: auto;
  display: block;
  /* Prevent the SVG from shrinking so far that axis/label text becomes unreadable
     on narrow viewports. The parent .chart scrolls horizontally when needed. */
  min-width: 320px;
}
.chart--wide .chart-svg,
.chart--donut .chart-svg,
.chart--geo .chart-svg,
.chart--temporal .chart-svg { min-width: 360px; }
@media (max-width: 420px) {
  .chart,
  .chart--wide,
  .chart--donut,
  .chart--geo,
  .chart--temporal { overflow-x: auto; }
}

.chart-label { font-family: var(--font-sans); font-size: 13px; fill: var(--color-text); }
.chart-value { font-family: var(--font-sans); font-size: 12px; font-weight: 700; fill: var(--color-text-muted); }
.chart-axis  { font-family: var(--font-sans); font-size: 11px; fill: var(--color-text-muted); }
.chart-grid  { stroke: var(--color-border); stroke-width: 1; }
.chart--clinical { max-width: 860px; }
.chart-svg--clinical { min-width: 640px; }
.clinical-title { font-weight: 700; fill: var(--color-text); }
.clinical-group {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  fill: var(--color-text-muted);
}
.clinical-track { fill: color-mix(in srgb, var(--color-border) 55%, var(--white)); }
.clinical-row { cursor: default; }
.clinical-row .clinical-bar-fill { transition: filter 0.12s ease; }
.clinical-row:hover .clinical-bar-fill,
.clinical-row:focus .clinical-bar-fill { filter: brightness(1.15); }

.findings-figure--misuse-indicators {
  max-width: 780px;
}
.misuse-indicators {
  width: 100%;
  max-width: 780px;
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--white);
}
.misuse-indicators__title {
  position: relative;
  margin: 0 0 var(--space-3);
  padding-bottom: var(--space-2);
  font-family: var(--font-sans);
  font-size: clamp(1rem, 1.8vw, 1.25rem);
  font-weight: 700;
  line-height: var(--lh-tight);
  text-align: center;
  color: var(--phr-navy);
}
.misuse-indicators__title::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 56px;
  height: 2px;
  transform: translateX(-50%);
  background: var(--phr-red);
}
.misuse-indicators__group {
  --group-color: var(--phr-blue-gray);
  --group-tint: color-mix(in srgb, var(--group-color) 13%, var(--white));
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border);
}
.misuse-indicators__group:first-of-type {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}
.misuse-indicators__group--protected { --group-color: #C85770; }
.misuse-indicators__group--vulnerable { --group-color: #9B4560; }
.misuse-indicators__group--improper { --group-color: #4B2442; }
.misuse-indicators__group-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  min-height: 46px;
  padding: var(--space-2) var(--space-3);
  border-left: 5px solid var(--group-color);
  background: var(--group-tint);
  color: var(--color-text);
}
.misuse-indicators__group-head h5,
.misuse-indicators__group-head strong {
  margin: 0;
  font-family: var(--font-sans);
  font-size: clamp(0.8rem, 1.4vw, 0.95rem);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: 0.04em;
}
.misuse-indicators__group-head strong {
  flex: 0 0 auto;
  text-align: right;
  letter-spacing: 0.01em;
  color: var(--group-color);
}
.misuse-indicators__rows {
  display: grid;
  gap: var(--space-2);
  padding: var(--space-2) 0;
}
.misuse-indicators__row {
  display: grid;
  grid-template-columns: minmax(128px, 31%) minmax(120px, 1fr) minmax(78px, 13%);
  align-items: center;
  column-gap: var(--space-3);
  min-height: 34px;
  padding: 2px 0;
  border-radius: var(--radius);
  outline-offset: 3px;
}
.misuse-indicators__row:hover,
.misuse-indicators__row:focus {
  background: color-mix(in srgb, var(--group-color) 7%, transparent);
}
.misuse-indicators__row:hover .misuse-indicators__bar,
.misuse-indicators__row:focus .misuse-indicators__bar {
  filter: brightness(1.14);
}
.misuse-indicators__label,
.misuse-indicators__value {
  font-family: var(--font-sans);
  font-size: clamp(0.82rem, 1.4vw, 0.95rem);
  line-height: 1.25;
  color: var(--color-text);
}
.misuse-indicators__value {
  color: var(--color-text-muted);
  font-weight: 700;
  white-space: nowrap;
}
.misuse-indicators__track {
  display: block;
  width: 100%;
  height: clamp(18px, 2.7vw, 24px);
  border-radius: 4px;
  background: color-mix(in srgb, var(--color-border) 55%, var(--white));
}
.misuse-indicators__bar {
  display: block;
  width: max(5px, calc((var(--value) / var(--group-max)) * 100%));
  height: 100%;
  border-radius: 2px;
  background: var(--group-color);
  transition: filter 0.12s ease;
}

@media (max-width: 720px) {
  .misuse-indicators {
    padding: var(--space-3);
  }
  .misuse-indicators__group-head {
    align-items: flex-start;
    flex-direction: column;
    min-height: 0;
  }
  .misuse-indicators__group-head strong {
    text-align: left;
  }
  .misuse-indicators__row {
    grid-template-columns: minmax(0, 1fr) minmax(72px, auto);
    row-gap: var(--space-1);
  }
  .misuse-indicators__track {
    grid-column: 1 / -1;
    grid-row: 2;
    height: 24px;
  }
  .misuse-indicators__value {
    text-align: right;
  }
}

/* Interactive hover states */
.bar-row { cursor: default; }
.bar-row:hover .bar-fill,
.bar-row:focus .bar-fill  { filter: brightness(1.2); }

.dot-group { cursor: default; }
.dot-group .dot-fill { transition: r 0.12s ease; }
.dot-group:hover .dot-fill,
.dot-group:focus .dot-fill { r: 6px; }

.bar-segment { transition: opacity 0.2s ease; }
.bar-segment:hover { opacity: 0.8; }
.chart-legend-item text { font-size: 11px; fill: var(--color-text); }

/* --- Floating chart tooltip ----------------------------------------------- */
.chart-tooltip {
  position: fixed;
  background: var(--color-text);
  color: var(--white);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: 600;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius);
  pointer-events: none;
  white-space: nowrap;
  z-index: 1100;
  opacity: 0;
  transition: opacity 0.1s;
}
.chart-tooltip.is-visible { opacity: 1; }

/* --- Geo-chart (US mini-map with city dots) -------------------------------- */
.geo-outline { transition: fill 0.3s; }

.geo-map-container {
  width: 100%;
  min-height: 320px;
  border-radius: var(--radius);
  overflow: hidden;
  /* Match the map tiles' water colour so any area the tile set doesn't cover
     (open Pacific west of the tile boundary) blends into the ocean instead of
     showing a hard beige edge. Shown as a placeholder until Leaflet's tiles
     load, at which point js/charts.js clears it (mapContainer.style.backgroundImage = "none"). */
  background-color: #fafaf8;
  background-image: url("../images/Blank_US_Map_48states.svg");
  background-position: center;
  background-repeat: no-repeat;
  background-size: contain;
}

/* City dots — staggered entrance animation */
.geo-dot { cursor: default; }
.geo-dot__fill {
  transform-box: fill-box;
  transform-origin: center;
  animation: geo-pulse 2.4s ease-in-out infinite;
}
.geo-dot__pulse { display: none; }
.geo-dot:hover .geo-dot__fill,
.geo-dot:focus .geo-dot__fill {
  fill-opacity: 1;
  filter: brightness(1.15);
  animation-play-state: paused;
}

@keyframes geo-pulse {
  0%, 100% { opacity: 0.85; transform: scale(1); }
  50%      { opacity: 0.6; transform: scale(0.9); }
}

.geo-label__city {
  font-family: var(--font-sans);
  font-size: 15px;
  font-weight: 700;
  fill: var(--color-text);
}
.geo-label__count {
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 600;
  fill: var(--phr-red);
}

@media (prefers-reduced-motion: reduce) {
  .geo-dot__fill,
  .geo-dot__pulse,
  .geo-label {
    animation: none !important;
    transform: none !important;
  }
}

/* --- Weekly chart operation bands + temporal-concentration matrix (SVG text/
   line styling only — no scroll-step highlight/dim logic to port; charts.js
   itself toggles the is-highlighted/is-dimmed modifier classes at runtime). -- */
.week-band { transition: opacity 0.3s ease; }
.week-band--context.is-dimmed { opacity: 0.35; }
.tc-band { transition: opacity 0.3s ease; }
.tc-band-label {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 11.5px;
}
.tc-bar { transition: opacity 0.3s ease; }
.tc-bar__fill { transition: opacity 0.15s ease; }
.tc-bar:hover .tc-bar__fill { opacity: 0.78; }
.tc-bar__value {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 11px;
}
.tc-annotation {
  font-family: var(--font-sans);
  font-style: italic;
  font-size: 12px;
}
.tc-lane__label {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 13px;
}
.tc-lane__rule { stroke: var(--color-border); stroke-width: 0.75; }
.tc-lane__base { stroke: #e5e2dd; stroke-width: 1; }
.tc-axis {
  font-family: var(--font-sans);
  font-size: 11px;
  fill: #6b665e;
}
.tc-axis--year { fill: #9b958c; font-size: 10px; }
.tc-caption {
  font-family: var(--font-sans);
  font-style: italic;
  font-size: 10.5px;
  fill: #9b958c;
}

/* --- Callout / methodological note (the "floor not a ceiling" caveats) ---- */
.note {
  font-size: var(--fs-sm);
  color: var(--color-text-muted);
  max-width: var(--measure);
}
.note::before {
  content: "Note: ";
  font-weight: 700;
  color: var(--phr-red);
  font-family: var(--font-sans);
}

/* Allow the map intro's note to span full width, matching map.css's #map-section
   override for the reveal paragraph above it. */
#map-section .note { margin-top: var(--space-3); max-width: none; }

/* --- Home summary paragraph (content.csv `class` value) -------------------- */
.home-summary {
  font-size: var(--fs-base);
  line-height: 1.5;
}

/* --- Scroll-reveal: elements fade/rise in once (set by js/nav.js) ---------
   Gated behind the `js` class so that if JavaScript fails to load, content is
   never left invisible — it just appears with no animation. Unrelated to the
   removed scrollytelling engine; this is a generic on-scroll fade utility. */
.js .reveal { opacity: 0; transform: translateY(16px); }
.js .reveal.is-visible {
  opacity: 1; transform: none;
  transition: opacity var(--duration) var(--ease), transform var(--duration) var(--ease);
}
@media (prefers-reduced-motion: reduce) {
  .js .reveal { opacity: 1; transform: none; }
}

/* =============================================================================
   FINDINGS — flat chapter flow
   ============================================================================ */

/* --- Topline statistics band ------------------------------------------------ */
.topline-band {
  display: flex; flex-wrap: wrap;
  margin-top: var(--space-4);
  padding: var(--space-5) var(--space-3);
  background: var(--white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}
.topline {
  flex: 1 1 140px; min-width: 120px;
  padding: 0 var(--space-4);
  border-left: 1px solid var(--color-border);
}
.topline:first-child { border-left: 0; }
.topline__num {
  display: block;
  font-family: var(--font-sans); font-weight: 700;
  font-size: var(--fs-2xl); line-height: 1;
  font-variant-numeric: tabular-nums; letter-spacing: -0.015em;
  color: var(--phr-red);
}
.topline__label {
  display: block; margin-top: var(--space-2);
  font-family: var(--font-sans); font-size: var(--fs-xs);
  line-height: 1.3; color: var(--color-text-muted);
}
@media (max-width: 600px) {
  .topline-band { gap: var(--space-4); }
  .topline { border-left: 0; padding: 0; flex-basis: 40%; }
}

/* --- Findings chapters (flat headings, no roadmap/dot-nav) -----------------
   Fresh rule: the old scrolly build had a dot-nav "roadmap" widget here; the
   flat design just needs a clear heading + top rule separating each of the
   9 chapters in the normal document flow. */
.findings-chapter {
  margin-top: var(--space-7);
  padding-top: var(--space-5);
  border-top: 3px solid var(--phr-red);
}
.findings-chapter:first-of-type {
  margin-top: var(--space-6);
}
#findings .findings-chapter:first-of-type {
  margin-top: var(--space-2);
  padding-top: var(--space-3);
}
.findings-chapter__title {
  margin-bottom: var(--space-3);
  color: var(--color-text);
}
.findings-chapter > h4,
.findings-chapter__body > h4 {
  margin: var(--space-4) 0 var(--space-2);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border);
  color: var(--phr-red);
  font-size: var(--fs-sm);
  letter-spacing: 0;
  text-transform: uppercase;
}

/* --- Findings "Interpretation" aside ---------------------------------------
   js/content.js's promoteInterpretationAside() moves only the trailing
   "Interpretation" eyebrow + list (plus any plain paragraphs immediately
   before it) into .findings-chapter__body / .findings-chapter__interpretation.
   Everything else in the chapter — chart embeds, the city-video gallery, the
   operation carousel, headings, other eyebrows — stays exactly where it was,
   so every direct child defaults to spanning the full row; only the body/
   interpretation pair (when present) share a row across the two columns. */
.findings-chapter {
  display: grid;
  /* Column 1 is capped to the same reading measure the paragraphs already
     use, so it hugs the prose instead of stretching to the full section
     width and stranding the aside out past a dead gap. */
  grid-template-columns: minmax(0, var(--measure)) minmax(300px, 1fr);
  column-gap: var(--space-5);
  justify-content: start;
  align-items: start;
}
.findings-chapter > * {
  grid-column: 1 / -1;
}
.findings-chapter > .findings-chapter__body {
  grid-column: 1;
  min-width: 0;
}
/* When the body's trailing content is a <details class="methods-detail">
   dropdown (e.g. the MK-9 "Learn more" embed) rather than plain prose, the
   dropdown itself should only occupy the body's column width, not stretch
   full-bleed the way top-level embeds default to. */
.findings-chapter__body--dropdown .methods-detail {
  max-width: none;
}
.findings-chapter > .findings-chapter__interpretation {
  grid-column: 2;
  /* Chapters vary a lot in body length (Overview's two paragraphs vs. Weapons'
     long run of charts/prose). The shared grid row is always as tall as
     whichever column is taller, so anchoring the card to the row's bottom
     keeps it level with the END of the prose (where "Interpretation" actually
     sits) instead of stranding it up near the top on longer chapters. */
  align-self: end;
  background: var(--color-bg-muted);
  border-radius: var(--radius);
  padding: var(--space-4);
}
/* Exception: when the body ends in a dropdown (see
   .findings-chapter__body--dropdown above), the reader's eye lands on the
   paragraph/dropdown pair from the top, not the bottom — so align the card
   with the TOP of that pair instead of the default bottom alignment. */
.findings-chapter__body--dropdown + .findings-chapter__interpretation {
  align-self: start;
}
/* Weapons has an intentionally earlier Interpretation anchor: it sits beside
   the prose immediately below the video instead of the later MK-9 dropdown. */
.findings-chapter__body--early-anchor + .findings-chapter__interpretation {
  align-self: start;
}
.findings-chapter > .findings-chapter__interpretation .pattern-text__eyebrow {
  font-size: var(--fs-xs);
}
.findings-chapter > .findings-chapter__interpretation ul {
  max-width: none;
  font-size: var(--fs-sm);
  line-height: 1.5;
}
@media (max-width: 900px) {
  .findings-chapter {
    display: block;
  }
  .findings-chapter > .findings-chapter__interpretation {
    margin-top: var(--space-4);
  }
}

/* --- Findings index (fixed left rail) ---------------------------------------
   Replacement for the old scrolly build's dot-nav "roadmap"/chapter-nav: since
   Findings is flat now there's no pinned stage to hang a nav off of, so this
   is a plain `position: fixed` rail, shown/hidden by js/nav.js's
   initFindingsIndex() (toggles [hidden] based on whether #findings is the
   scrolled-to section) rather than tied to any scrolly progress event. The
   horizontal fill bar tracks scroll progress through the whole Findings
   section (0% at its top, 100% at its bottom), independent of which chapter
   link is currently marked active. */
.findings-index {
  position: fixed;
  top: 50%;
  left: var(--space-4);
  transform: translateY(-50%);
  z-index: 900; /* below the sticky header (1001) and Leaflet controls (1000) */
  width: 220px;
  max-height: 70vh;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(4px);
  border-radius: 4px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}
.findings-index[hidden] { display: flex; } /* keep transitioning out, not display:none */
.findings-index.is-visible {
  opacity: 1;
  pointer-events: auto;
}
.findings-index__progress {
  position: relative;
  flex: none;
  height: 3px;
  background: var(--color-border);
  border-radius: 999px;
  overflow: hidden;
}
.findings-index__progress-fill {
  display: block;
  height: 100%;
  width: 0%;
  background: var(--phr-red);
  transition: width 0.1s linear;
}
.findings-index__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  overflow-y: auto;
}
.findings-index__link {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  padding: var(--space-1) 0;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--color-text-muted);
  text-decoration: none;
  border-left: 2px solid transparent;
  padding-left: var(--space-2);
  transition: color 0.15s, border-color 0.15s;
}
.findings-index__link:hover { color: var(--color-text); }
.findings-index__link.is-active {
  color: var(--color-text);
  border-left-color: var(--phr-red);
}
.findings-index__num {
  font-variant-numeric: tabular-nums;
  color: var(--color-text-muted);
}
.findings-index__link.is-active .findings-index__num { color: var(--phr-red); }
.findings-index__label { line-height: 1.25; }

@media (max-width: 1560px) {
  /* Content is centered at --content-max (1200px); below ~1560px viewport
     width there isn't enough side margin left for a 220px rail without it
     overlapping the text column, so it's hidden rather than overlapping. */
  .findings-index { display: none !important; }
}

@media (min-width: 1561px) {
  /* The rail sits at a fixed left: var(--space-4), so its right edge is
     ~245.5px from the viewport edge. Most chart content clears that once
     the centered content column reaches that far (~1706px), but the donut
     charts (js/charts.js donutChart(), used for cities/weapons/agencies)
     draw outside-ring callout labels that intentionally render past their
     own SVG box (.chart-svg--donut has overflow: visible) — on the widest
     case (city donut) those labels can start ~85px left of the SVG box
     edge. Rather than hiding the rail until ~1900px (which would push it
     off most laptop screens just to accommodate three charts), nudge only
     those three donut figures right by a fixed amount so their labels
     clear the rail at the narrowest width the rail can appear at (1561px).
     Block-level auto width absorbs the margin, so this doesn't cause
     horizontal overflow. */
  .findings-figure:has(.chart--city-donut),
  .findings-figure:has(.chart--weapon-donut),
  .findings-figure:has(.chart--agency-donut) {
    margin-left: 160px;
  }
}

/* --- Chapter nav bar (narrow-viewport companion to .findings-index) --------
   Same chapter list, same show/hide + active-chapter + progress logic (both
   wired together in initFindingsIndex()), just docked under the header as a
   slim bar instead of pinned to the left edge. Only one of this and
   .findings-index is ever on screen — the media queries below and at
   .findings-index above are mutually exclusive. */
.chapter-nav {
  position: fixed;
  top: var(--top-chrome-height);
  left: 0;
  right: 0;
  z-index: 999; /* under the site header (1001) and section-sticky-title (1000) */
  background: rgba(255, 255, 255, 0.94);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  border-bottom: 1px solid var(--color-border);
  opacity: 0;
  transform: translateY(-8px);
  pointer-events: none;
  transition: opacity 0.2s var(--ease), transform 0.2s var(--ease);
}
.chapter-nav[hidden] { display: block; } /* keep transitioning out, not display:none */
.chapter-nav.is-visible {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}
.chapter-nav__inner {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-4);
}
.chapter-nav__count {
  flex: none;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}
.chapter-nav__list {
  flex: 1 1 auto;
  display: flex;
  gap: var(--space-1);
  margin: 0;
  padding: 0;
  list-style: none;
  overflow-x: auto;
  scrollbar-width: none;
}
.chapter-nav__list::-webkit-scrollbar { display: none; }
.chapter-nav__item { flex: none; }
.chapter-nav__link {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 6px 8px;
  border-radius: 4px;
  white-space: nowrap;
  text-decoration: none;
  color: var(--color-text-muted);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: 600;
  transition: color 0.15s, background 0.15s;
}
.chapter-nav__link:hover { color: var(--color-text); }
.chapter-nav__link.is-active {
  color: var(--color-text);
  background: var(--color-bg-muted);
}
.chapter-nav__num { font-variant-numeric: tabular-nums; color: var(--color-text-muted); }
.chapter-nav__link.is-active .chapter-nav__num { color: var(--phr-red); }
.chapter-nav__progress {
  height: 2px;
  background: var(--color-border);
}
.chapter-nav__progress-fill {
  display: block;
  height: 100%;
  width: 0%;
  background: var(--phr-red);
  transition: width 0.1s linear;
}
@media (min-width: 1561px) {
  .chapter-nav { display: none !important; }
}
@media (max-width: 600px) {
  .chapter-nav__count { display: none; }
}

/* --- Incidents stat figure (re-derived flat 3-panel figure) -----------------
   Old .scrolly__slide--incidents / .incidents-stat-figure was a pinned-slide
   figure sized to fill a fixed-height viewport stage. Re-derived here as a
   normal, contained, 3-panel flex figure inside .findings-figure — no pinning,
   no scroll-step sizing. Bar widths/colors are still driven by the inline
   --share / --bar-color custom properties set in the markup. */
.incidents-stat-figure {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  background: var(--white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  overflow: hidden;
}
.incidents-stat-figure__panel {
  flex: 1 1 260px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
  padding: var(--space-5) var(--space-4);
  border-left: 1px solid var(--color-border);
}
.incidents-stat-figure__panel:first-child { border-left: 0; }
.incidents-stat-figure__panel--total { gap: var(--space-3); }
.incidents-stat-figure__num {
  display: block;
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: clamp(3rem, 6vw, 4.5rem);
  line-height: 0.95;
  color: var(--phr-red);
}
.incidents-stat-figure__label {
  display: block;
  max-width: 18ch;
  margin-top: var(--space-2);
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  line-height: var(--lh-tight);
  color: var(--color-text-muted);
}
.incidents-stat-figure__panel--total p {
  margin: 0;
  padding-top: var(--space-3);
  border-top: 1px solid var(--phr-navy);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  color: var(--phr-blue-gray);
}
.incidents-stat-figure__panel--total strong {
  display: block;
  max-width: 26ch;
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  line-height: 1.2;
  color: var(--phr-red);
}
.incidents-cities__heading {
  margin: 0 0 var(--space-3);
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--phr-navy);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.incidents-stat-figure__sub-stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-4);
  margin: 0 0 var(--space-4);
}
.incidents-sub-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-width: 0;
  padding: 0 var(--space-3);
}
.incidents-sub-stat + .incidents-sub-stat {
  border-left: 1px solid var(--color-border);
}
.incidents-sub-stat__num {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: clamp(2.25rem, 4vw, 3.25rem);
  line-height: 1;
  color: var(--phr-navy);
}
.incidents-sub-stat__label {
  margin-top: var(--space-2);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: 700;
  color: var(--phr-navy);
  text-transform: uppercase;
}
.incidents-state-grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(42px, 1fr));
  gap: 7px;
}
.incidents-state-grid span {
  display: grid;
  place-items: center;
  min-height: 34px;
  border-radius: 3px;
  background: var(--phr-navy);
  color: var(--white);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: 700;
}
.incidents-target-stack {
  display: flex;
  width: 100%;
  height: clamp(56px, 9vw, 90px);
  margin: 0 0 var(--space-4);
  border-radius: 2px;
  overflow: hidden;
  background: var(--color-border);
}
.incidents-target-stack span {
  flex: var(--share) 0 0;
  display: grid;
  place-items: center;
  min-width: 3px;
  border-right: 3px solid var(--white);
  background: var(--bar-color);
  color: var(--white);
  font-family: var(--font-sans);
  font-size: clamp(0.68rem, 1.5vw, var(--fs-base));
  font-weight: 700;
  line-height: 1;
}
.incidents-target-stack span:nth-child(n + 4) { color: transparent; }
.incidents-target-stack span:last-child { border-right: 0; }
.incidents-target-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(118px, 1fr));
  gap: var(--space-3);
}
.incidents-target-list span {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
  padding-left: var(--space-3);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  line-height: 1.25;
  color: var(--color-text-muted);
}
.incidents-target-list span::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 6px;
  height: 100%;
  border-radius: 2px;
  background: var(--bar-color);
}
.incidents-target-list strong {
  display: block;
  color: var(--phr-navy);
  font-size: 0.8rem;
  line-height: 1.1;
}
@media (max-width: 900px) {
  .incidents-stat-figure__panel { flex-basis: 100%; border-left: 0; border-top: 1px solid var(--color-border); }
  .incidents-stat-figure__panel:first-child { border-top: 0; }
}
@media (max-width: 480px) {
  .incidents-target-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* --- "Who was targeted?" pictogram — standalone figure introducing the
   People & injuries chapter (findings-figure--pictogram). One figure per
   documented incident; sized generously since it isn't squeezed into a
   3-panel row like .incidents-stat-figure. */
.findings-figure--pictogram {
  max-width: 820px;
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--white);
}
.target-pictogram__note {
  margin: 0 0 var(--space-4);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  color: var(--color-text-muted);
}
.target-pictogram__body {
  display: flex;
  align-items: flex-start;
  gap: var(--space-6);
}
.target-pictogram__grid {
  flex: 0 1 460px;
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: 5px;
  min-width: 0;
}
.target-pictogram__figure { display: inline-flex; }
.target-pictogram__figure svg { display: block; fill: currentColor; }
.target-pictogram__legend {
  flex: 0 0 250px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
}
.target-pictogram__row {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  padding: var(--space-2) 0;
  border-top: 1px solid var(--color-border);
}
.target-pictogram__row:first-child { border-top: 0; padding-top: 0; }
.target-pictogram__dot {
  flex: none;
  width: 11px;
  height: 11px;
  margin-top: 5px;
  border-radius: 2px;
  background: var(--dot-color);
}
.target-pictogram__text { min-width: 0; }
.target-pictogram__count {
  display: block;
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 1.125rem;
  line-height: 1;
  color: var(--color-text);
}
.target-pictogram__pct {
  margin-left: var(--space-2);
  font-weight: 400;
  font-size: var(--fs-xs);
  color: var(--color-text-muted);
}
.target-pictogram__label {
  display: block;
  margin-top: 2px;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  line-height: 1.25;
  color: var(--color-text-muted);
}
@media (max-width: 640px) {
  .target-pictogram__body { flex-direction: column; }
  .target-pictogram__legend { flex-direction: row; flex-wrap: wrap; width: 100%; gap: var(--space-4); }
  .target-pictogram__row { flex: 1 1 160px; border-top: 0; padding: 0; }
}

/* --- Operation cards (re-derived flat card; old was a pinned per-operation
   slide with an inline --op-color accent) ------------------------------------ */
.findings-op-card {
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--op-color, var(--phr-red));
  border-radius: var(--radius);
  background: var(--white);
  display: flex;
  flex-direction: column;
}
.findings-op-card .chart { margin-bottom: var(--space-2); order: 2; }
.findings-op-card figcaption { margin-bottom: var(--space-4); order: 3; }
.ops-head { margin-top: 0; margin-bottom: var(--space-4); order: 1; }

/* --- Operation card carousel: the 4 named-operation cards regrouped into one
   click-through unit (see initOperationCarousel() in main.js) so a reader
   picks an operation instead of scrolling past 4 stacked cards. ------------- */
.op-carousel { margin: var(--space-5) 0; }
.op-carousel__tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}
.op-carousel__tab {
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  font-weight: 700;
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--color-border);
  border-bottom: 3px solid var(--tab-color, var(--color-border));
  border-radius: var(--radius);
  background: var(--color-bg-muted);
  color: var(--color-text-muted);
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.op-carousel__tab:hover { background: var(--white); color: var(--color-text); }
.op-carousel__tab[aria-selected="true"] {
  background: var(--white);
  color: var(--tab-color, var(--phr-red));
  border-color: var(--tab-color, var(--color-border));
}
.op-carousel__panel[hidden] { display: none; }

/* --- Per-operation body-part/subject toggle (dailyStackedChart layers) ----- */
.op-chart__toggle {
  display: flex;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}
.op-chart__btn {
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.02em;
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  background: var(--color-bg-muted);
  color: var(--color-text-muted);
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.op-chart__btn:hover { background: var(--white); color: var(--color-text); }
.op-chart__btn.is-active {
  background: var(--phr-navy);
  border-color: var(--phr-navy);
  color: var(--white);
}
.op-chart__layer { display: none; }
.op-chart__layer.is-active { display: block; }
.pattern-text__eyebrow {
  font-family: var(--font-sans);
  font-size: var(--fs-xs); font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--phr-red);
  margin-bottom: var(--space-2);
}

/* --- Recommendation eyebrows (Conclusions) --------------------------------
   Numbered labels ("01 — Crowd-control weapons") ahead of each of the three
   `h4` recommendation groups. A thin red rule + generous margin-top gives
   each group its own beat without introducing boxed/shadowed cards, which
   this flat redesign deliberately dropped (see file header). */
.recommendation-eyebrow {
  font-family: var(--font-sans);
  font-size: var(--fs-xs); font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--phr-red);
  margin-top: var(--space-6);
  padding-top: var(--space-4);
  border-top: 2px solid var(--phr-red);
  margin-bottom: var(--space-2);
}
.ops-head__name {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: var(--fs-xl);
  line-height: var(--lh-tight);
  color: var(--op-color, var(--phr-red));
  margin: 0 0 var(--space-1);
}
.ops-head__meta {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-text-muted);
  margin: 0 0 var(--space-2);
}
.ops-head__desc {
  font-size: var(--fs-sm);
  margin: 0;
  max-width: 78ch;
}
.ops-head__note {
  display: block;
  margin-top: var(--space-2);
  color: var(--color-text-muted);
}

/* =============================================================================
   CITY VIDEO GALLERY — the 4 city clips as one tabbed full-bleed gallery
   -----------------------------------------------------------------------------
   Built by main.js's initCityVideoGallery(): it regroups the 4 already
   CSV-positioned `.findings-video[data-city-label]` blocks (each still
   followed by its own CSV-driven eyebrow + paragraph) into one
   `.video-gallery`, so a reader picks a city instead of scrolling past 4
   stacked clips. Tab switching itself is nav.js's generic initFolderTabs()
   (same [role=tablist]/[role=tab]/aria-controls wiring used anywhere else on
   the page) — no gallery-specific JS beyond the one-time DOM regroup.
   ============================================================================ */
.video-gallery__top {
  position: absolute;
  top: 0; left: 0; right: 0;
  z-index: 2;
  padding: var(--space-5) var(--space-4) var(--space-4);
  background: linear-gradient(to bottom, rgba(0, 0, 0, 0.76), rgba(0, 0, 0, 0));
}

.video-gallery__title {
  margin: 0;
  font-family: var(--font-sans);
  font-size: clamp(2.25rem, 6vw, 5.25rem);
  line-height: 0.95;
  color: var(--white);
  text-shadow: 0 2px 16px rgba(0, 0, 0, 0.65);
}

.video-gallery__tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-3);
}
.video-gallery__tab {
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  font-weight: 700;
  padding: var(--space-1) var(--space-3);
  border: 1px solid rgba(255, 255, 255, 0.8);
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.6);
  color: var(--white);
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.video-gallery__tab:hover { background: rgba(0, 0, 0, 0.8); }
.video-gallery__tab[aria-selected="true"] {
  background: var(--phr-red);
  border-color: var(--phr-red);
}

.video-gallery__body { position: relative; width: 100%; height: 100%; }
.video-gallery__panel { position: absolute; inset: 0; }
.video-gallery__panel[hidden] { display: none; }

/* Caption (the CSV eyebrow + paragraph moved out of normal flow) reads as a
   cinematic lower-third over the clip rather than plain text below it. A
   solid-ish translucent panel behind the whole block (not just a gradient
   fading from the very bottom edge) keeps the text readable regardless of
   how bright the frame underneath it is. */
.video-gallery__caption {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: 1;
  padding: var(--space-6) var(--space-4) var(--space-4);
  background: linear-gradient(to top, rgba(0, 0, 0, 0.82) 40%, rgba(0, 0, 0, 0.55) 80%, rgba(0, 0, 0, 0));
}
.video-gallery__caption p {
  max-width: var(--measure);
  color: var(--white);
}
.video-gallery__caption .pattern-text__eyebrow { opacity: 0.85; }
.video-gallery__caption a {
  color: var(--phr-red);
  text-decoration: underline;
  text-decoration-thickness: 0.08em;
  text-underline-offset: 0.16em;
}

/* =============================================================================
   THE CANISTER — full-bleed video/model cluster + flat feature cards/table
   ============================================================================ */

/* --- Full-bleed video/model wrappers ---------------------------------------
   `.section--full-bleed` (breakout mechanics in layout.css) plus the media
   sizing rules for the two things it can contain: a background video and,
   for the canister cluster, an overlaid <model-viewer>. Also reused, nested
   one level deeper, by the city video gallery above (`.video-gallery__panel`
   > `.findings-video`) — its own width/height:100% chain resolves the same
   way either place. */
.findings-video {
  position: relative;
  width: 100%;
  height: 100%;
}
/* The canister cluster's own wrapper carries `.section--full-bleed` directly
   (rather than nesting inside a `.video-gallery__body` like the city clips),
   so its explicit `height: clamp(...)` needs to win over the generic 100%
   above despite loading later in the cascade — bumped via the two-class
   selector instead of reordering the whole file. Without this the model
   viewer/video rendered at 0×0 and simply never showed up. */
.findings-video.section--full-bleed {
  height: clamp(60vh, 90vh, 900px);
}
.findings-video .scene-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: #000;
}
.findings-video--canister .scene-video { object-fit: cover; opacity: 0.55; }
.findings-video--canister .canister-model {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(70%, 640px);
  height: 90%;
  z-index: 1;
}
.canister-model__fallback {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%;
  font-family: var(--font-sans); font-size: var(--fs-sm);
  color: var(--color-text-muted);
  background: var(--color-bg-muted);
}

/* --- Canister feature cards (re-derived flat card grid) --------------------
   Old .canister-cards was a column of scroll-choreographed callouts beside a
   3D model. Re-derived here as a normal responsive card grid. */
.canister-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--space-4);
  margin: var(--space-5) 0;
}
.canister-cards__eyebrow {
  grid-column: 1 / -1;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--phr-red);
  margin: 0;
}
.canister-card {
  background: var(--white);
  border: 1px solid var(--color-border);
  border-top: 4px solid var(--phr-navy);
  border-radius: var(--radius);
  padding: var(--space-4);
  font-size: var(--fs-sm);
}
.canister-card p { margin: 0; max-width: none; }
.canister-card__title {
  display: block;
  font-family: var(--font-sans);
  font-weight: 700;
  color: var(--phr-red);
  margin-bottom: var(--space-1) !important;
}
/* Each callout gets its own accent color, echoing the map's category-color
   convention rather than repeating one color across all three. */
.canister-card--trigger { border-top-color: var(--phr-red); }
.canister-card--trigger .canister-card__title { color: var(--phr-red); }
.canister-card--capacity { border-top-color: var(--phr-orange); }
.canister-card--capacity .canister-card__title { color: var(--phr-orange); }
.canister-card--reach { border-top-color: var(--phr-sage); }
.canister-card--reach .canister-card__title { color: var(--phr-sage); }
.canister-card--conclusion {
  grid-column: 1 / -1;
  background: var(--color-bg-muted);
  border-color: var(--color-border);
  border-top: none;
  border-left: 4px solid var(--phr-red);
  font-size: var(--fs-base);
  font-family: var(--font-sans);
}

/* --- Comparison table (canister-compare-table embed): a modifier on the
   generic .data-table, not a bespoke old-style component. --------------------- */
.compare-table th, .compare-table td { vertical-align: top; }
.compare-table td ul,
.compare-table td p { max-width: none; }
.compare-table td p + p { margin-top: var(--space-2); }
.compare-table td ul { margin: 0; padding-left: 1.1em; list-style: disc; }
.compare-table td ul li { padding-left: 0.2em; }
.compare-table td ul li::before { content: none; }

/* --- Donut charts ----------------------------------------------------------- */
.chart-svg--donut { max-width: 860px; }
.chart--donut,
.chart-svg--donut { overflow: visible; }
.findings-figure .chart--weapon-donut,
.findings-figure .chart--agency-donut,
.findings-figure .chart--city-donut,
.chart--weapon-donut .chart-svg--donut,
.chart--agency-donut .chart-svg--donut,
.chart--city-donut .chart-svg--donut {
  max-width: 960px;
}
.donut-seg { cursor: default; stroke: var(--white); stroke-width: 1.5; }
.donut-seg:hover { filter: brightness(1.12); }
.donut-callout-line {
  fill: none;
  stroke: var(--color-border);
  stroke-width: 1.2;
  transition: opacity 0.12s var(--ease);
}
.donut-label {
  font-family: var(--font-sans);
  font-weight: 700;
  pointer-events: none;
  transition: opacity 0.12s var(--ease);
}
.donut-label--inside {
  fill: var(--white);
  font-size: 12px;
}
.donut-label--outside {
  fill: var(--color-text-muted);
  font-size: 11px;
}
.donut-total {
  font-family: var(--font-sans); font-weight: 700; font-size: 40px;
  fill: var(--color-text);
}
.donut-sub { font-family: var(--font-sans); font-size: 13px; fill: var(--color-text-muted); }
.donut-legend {
  display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4);
  margin-top: var(--space-3);
  font-family: var(--font-sans); font-size: var(--fs-xs);
  color: var(--color-text-muted);
}
.donut-legend--compact {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-1) var(--space-3);
  max-width: 860px;
  margin-top: var(--space-2);
  font-size: clamp(0.56rem, 0.52rem + 0.1vw, 0.66rem);
  line-height: 1.25;
}
.donut-legend--compact .legend-item {
  min-width: 0;
  align-items: flex-start;
}
.donut-legend--compact .swatch {
  flex: 0 0 auto;
  margin-top: 0.2em;
}
.donut-legend .swatch {
  display: inline-block; width: 10px; height: 10px; border-radius: 2px;
  margin-right: 6px;
}
.legend-item { display: inline-flex; align-items: center; gap: var(--space-1); }
.legend-item .swatch { width: 0.8em; height: 0.8em; border-radius: 50%; }
@media (max-width: 720px) {
  .donut-legend--compact { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 460px) {
  .donut-legend--compact { grid-template-columns: 1fr; }
}

/* --- Heatmap table (weapon × city) ------------------------------------------ */
.heatmap__title {
  font-family: var(--font-serif, var(--font-sans)); font-weight: 700;
  font-size: var(--fs-base); text-align: center; margin-bottom: var(--space-3);
}
.heatmap__title-sep { color: var(--color-text-muted); }
.heatmap__layout { display: flex; align-items: stretch; gap: var(--space-4); }
.heatmap__scroll { overflow-x: auto; flex: 1 1 auto; }
.heatmap {
  border-collapse: collapse; width: 100%; max-width: 860px;
  font-family: var(--font-sans); font-size: var(--fs-sm);
}
.heatmap th { text-align: center; padding: var(--space-2); font-size: var(--fs-xs); }
.heatmap thead th { vertical-align: bottom; color: var(--color-text-muted); }
.heatmap tbody th { white-space: nowrap; text-align: right; }
.heatmap__n, .heatmap__sublabel { font-weight: 400; color: var(--color-text-muted); }
.heatmap td {
  padding: var(--space-3); text-align: center;
  border: 2px solid var(--color-bg-muted);
}
.heatmap td strong { display: block; font-size: var(--fs-base); }
.heatmap td span { font-size: var(--fs-xs); color: inherit; opacity: 0.8; }
.heatmap__cell--dark { color: var(--white); }
.heatmap__total-col { border-left: 2px solid var(--color-text); border-right: 2px solid var(--color-text); }
.heatmap thead .heatmap__total-col { border-top: 2px solid var(--color-text); }
.heatmap tbody tr:last-child .heatmap__total-col { border-bottom: 2px solid var(--color-text); }
.heatmap thead th.heatmap__total-col,
.heatmap td.heatmap__total-col strong { font-weight: 700; }

.heatmap__legend {
  flex: 0 0 auto; display: flex; flex-direction: column; align-items: center;
  gap: var(--space-1); padding-top: var(--space-6);
}
.heatmap__legend-bar {
  width: 14px; height: 160px; border-radius: 3px;
  background: linear-gradient(to top, rgba(214,0,28,0.90), rgba(214,0,28,0.04));
}
.heatmap__legend-ticks {
  display: flex; flex-direction: column; justify-content: space-between;
  height: 160px; font-size: var(--fs-xs); color: var(--color-text-muted);
}
.heatmap__legend-label {
  writing-mode: vertical-rl; transform: rotate(180deg);
  font-size: var(--fs-xs); color: var(--color-text-muted); margin-top: var(--space-2);
}
@media (max-width: 640px) {
  .heatmap__layout { flex-direction: column; }
  .heatmap__legend { flex-direction: row; padding-top: 0; }
  .heatmap__legend-bar { width: 160px; height: 14px; background: linear-gradient(to right, rgba(214,0,28,0.04), rgba(214,0,28,0.90)); }
  .heatmap__legend-ticks { flex-direction: row; width: 160px; height: auto; }
  .heatmap__legend-ticks span:not(:first-child):not(:last-child) { display: none; }
  .heatmap__legend-ticks { flex-direction: row-reverse; }
  .heatmap__legend-label { writing-mode: horizontal-tb; transform: none; margin-top: 0; }
}

/* --- Weapon-use statistical-analysis modal (native <dialog>) ---------------
   Triggered by the "See the statistical analysis of weapon use" button ahead
   of the MK-9 "Learn more" dropdown; see js/main.js's initStatsModal(). As a
   direct child of .findings-chapter's grid, it would otherwise stretch to
   fill the full grid-column width like any other grid item; size it to its
   own text instead. */
#weapon-stats-btn { justify-self: start; width: fit-content; }
.stats-modal {
  /* Native <dialog> centers itself via `margin: auto` in the UA stylesheet,
     but base.css's `* { margin: 0; }` reset wipes that out — restore it here
     so the modal opens centered instead of pinned to the top-left corner. */
  margin: auto;
  padding: 0;
  border: none;
  border-radius: var(--radius);
  max-width: min(960px, 92vw);
  max-height: 88vh;
  background: var(--white);
}
.stats-modal::backdrop { background: rgba(43, 38, 34, 0.6); }
.stats-modal__panel { position: relative; }
.stats-modal__body {
  padding: var(--space-5) var(--space-4);
  max-height: 88vh;
  overflow-y: auto;
}
.stats-modal__body h3 {
  font-family: var(--font-sans); color: var(--phr-navy);
  margin: 0;
}
.stats-modal__body p { max-width: var(--measure); }
.stats-modal__body .chart--wide { max-width: 920px; }
.stats-modal__close {
  position: sticky; top: var(--space-2); float: right;
  margin: var(--space-2) var(--space-2) 0 0;
  width: 32px; height: 32px;
  border: 1px solid var(--color-border); border-radius: 50%;
  background: var(--white); color: var(--color-text-muted);
  font-size: 1.25rem; line-height: 1; cursor: pointer;
}
.stats-modal__close:hover { color: var(--phr-red); border-color: var(--phr-red); }

/* --- Weapon-stats SVG figure (js/charts.js weaponStatsChart) --------------- */
.chart-svg--stats { min-width: 640px; }
.stats-title  { font-family: var(--font-sans); font-size: 17px; font-weight: 700; fill: var(--phr-navy); }
.stats-subtitle { font-family: var(--font-sans); font-size: 12px; fill: var(--color-text-muted); }
.stats-heading { font-family: var(--font-sans); font-size: 13px; font-weight: 700; fill: var(--color-text); }
.stats-section-label {
  font-family: var(--font-sans); font-size: 12px; font-weight: 700;
  letter-spacing: 0.03em; fill: var(--phr-navy);
}
.stats-note { font-family: var(--font-sans); font-size: 12px; fill: var(--color-text-muted); }
.stats-note--italic { font-style: italic; }
.stats-big { font-family: var(--font-sans); font-size: 26px; font-weight: 700; fill: var(--phr-red); }
.stats-col-header { font-family: var(--font-sans); font-size: 12px; font-weight: 700; fill: var(--color-text-muted); }
.stats-row-header { font-family: var(--font-sans); font-size: 13px; font-weight: 700; fill: var(--color-text); }
.stats-cell-value { font-family: var(--font-sans); font-size: 14px; font-weight: 700; }
.stats-cell-stars { font-family: var(--font-sans); font-size: 11px; }
.stats-footnote { font-family: var(--font-sans); font-size: 11px; fill: var(--color-text-muted); }
.stats-cell { cursor: default; }
.stats-cell rect { transition: filter 0.12s ease; }
.stats-cell:hover rect,
.stats-cell:focus rect { filter: brightness(1.08); }

/* --- Generic data tables (definitions, canister comparison) ----------------- */
.table-scroll { overflow-x: auto; max-width: var(--content-max); }
.data-table {
  border-collapse: collapse; width: 100%;
  font-size: var(--fs-sm);
}
.data-table caption {
  text-align: left; font-family: var(--font-sans); font-weight: 700;
  padding-bottom: var(--space-2);
}
.data-table th, .data-table td {
  text-align: left; vertical-align: top;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border);
}
.data-table td p {
  max-width: none;
  margin: 0;
}
.data-table td p + p { margin-top: var(--space-2); }
.data-table thead th {
  font-family: var(--font-sans); background: var(--color-bg-muted);
}
.data-table tbody th {
  font-family: var(--font-sans); white-space: normal; min-width: 9em;
  background: var(--color-bg-muted);
}

/* --- Conclusions summary table (conclusions-summary-table embed) ----------- */
.conclusions-table {
  table-layout: fixed;
  border: none;
}
.conclusions-table__label-col { width: 13em; }
.conclusions-table th, .conclusions-table td { border: none; border-bottom: 1px solid var(--color-border); }
.conclusions-table tbody th {
  width: 13em; min-width: 0;
  padding-top: var(--space-3);
  font-size: var(--fs-sm); font-weight: 700; color: var(--phr-navy);
  background: none;
  border-top: 2px solid var(--phr-red);
}
.conclusions-table td {
  padding-top: var(--space-3); padding-bottom: var(--space-3);
}
.conclusions-table td p { max-width: none; margin: 0; }
.conclusions-table td p + p { margin-top: var(--space-2); }
.conclusions-table tbody tr:last-child th,
.conclusions-table tbody tr:last-child td { border-bottom: none; }
.conclusions-table tbody tr:hover th,
.conclusions-table tbody tr:hover td { background: var(--color-bg-muted); }

@media (max-width: 640px) {
  .conclusions-table { table-layout: auto; }
  .conclusions-table__label-col { width: auto; }
  .conclusions-table tbody th { width: auto; }
}

/* --- Body-part map (Findings § Who was harmed) ------------------------------ */
.body-map {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(300px, 0.75fr);
  gap: var(--space-5);
  align-items: stretch;
  min-height: clamp(360px, min(42vw, 64svh), 540px);
  margin-top: var(--space-5);
  padding: var(--space-4);
  border-top: 3px solid var(--phr-red);
  border-bottom: 1px solid var(--color-border);
  background: var(--color-bg-muted);
}

.body-map__visual {
  position: relative;
  min-height: 0;
  background: var(--white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  overflow: hidden;
}

.body-map__visual img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.body-map__overlay {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.body-map__region {
  --body-alpha: 0.18;
  --body-size: 34px;
  --body-rgb: 0, 60, 113;
  --body-stroke: var(--phr-navy);
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--body-size);
  height: var(--body-size);
  margin: calc(var(--body-size) / -2) 0 0 calc(var(--body-size) / -2);
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  outline: none;
  transition: transform 0.15s;
}

.body-map__region::before {
  content: "";
  position: absolute;
  inset: 0;
  border: 1.5px solid var(--body-stroke);
  border-radius: 50%;
  background: rgba(var(--body-rgb), calc(var(--body-alpha) * 0.45));
}

.body-map__region::after {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--body-stroke);
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.9);
  z-index: 1;
}

.body-map__region span {
  position: absolute;
  inset: -4px;
  border: 1px solid rgba(var(--body-rgb), 0.14);
  border-radius: 50%;
}

.body-map__region span::after {
  content: attr(data-label);
  position: absolute;
  left: 50%;
  bottom: calc(100% + 10px);
  transform: translateX(-50%) translateY(4px);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius);
  background: var(--color-text);
  color: var(--white);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: 700;
  line-height: 1.2;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s, transform 0.15s;
}

.body-map__region span::before {
  content: "";
  position: absolute;
  left: 50%;
  bottom: calc(100% + 5px);
  transform: translateX(-50%) translateY(4px);
  border: 5px solid transparent;
  border-top-color: var(--color-text);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s, transform 0.15s;
}

.body-map__region--contusion span::after,
.body-map__region--tbi span::after,
.body-map__region--ocular span::after,
.body-map__region--hearing-loss span::after {
  top: calc(100% + 10px);
  bottom: auto;
  transform: translateX(-50%) translateY(-4px);
}

.body-map__region--contusion span::before,
.body-map__region--tbi span::before,
.body-map__region--ocular span::before,
.body-map__region--hearing-loss span::before {
  top: calc(100% + 5px);
  bottom: auto;
  transform: translateX(-50%) translateY(-4px);
  border-top-color: transparent;
  border-bottom-color: var(--color-text);
}

.body-map__region:hover span::after,
.body-map__region:focus span::after,
.body-map__region:hover span::before,
.body-map__region:focus span::before {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* Illustrative anatomical placement for each injury type — not a diagnostic
   claim about exact injury sites, just a legible spot in the relevant area
   (head cluster, shoulder/neck, torso, arms/hands, leg). */
.body-map__region--contusion { left: 47%; top: 8%; }
.body-map__region--tbi { left: 53%; top: 8%; }
.body-map__region--ocular { left: 45%; top: 13%; }
.body-map__region--hearing-loss { left: 55%; top: 13%; }
.body-map__region--burn { left: 42%; top: 26%; }
.body-map__region--puncture { left: 50%; top: 31%; }
.body-map__region--laceration { left: 46%; top: 36%; }
.body-map__region--embedded-foreign-body { left: 54%; top: 36%; }
.body-map__region--permanent-disability { left: 50%; top: 48%; }
.body-map__region--fracture { left: 63%; top: 45%; }
.body-map__region--avulsion { left: 38%; top: 52%; }
.body-map__region--amputation { left: 62%; top: 53%; }
.body-map__region--abrasion { left: 45%; top: 67%; }

.body-map__region:hover,
.body-map__region:focus,
.body-map__region.is-active {
  transform: scale(1.08);
}

.body-map__region:hover::before,
.body-map__region:focus::before,
.body-map__region.is-active::before {
  border-width: 2px;
  background: rgba(var(--body-rgb), calc(var(--body-alpha) * 0.75));
}

.body-map__region:hover::before,
.body-map__region:focus::before {
  animation: body-hotspot-pulse 1.15s ease-in-out infinite;
  transform-origin: center;
}

.body-map__region.is-active::after {
  width: 11px;
  height: 11px;
}

@keyframes body-hotspot-pulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.28); opacity: 0.72; }
}

@media (prefers-reduced-motion: reduce) {
  .body-map__region:hover::before,
  .body-map__region:focus::before {
    animation: none;
  }
}

.body-map__panel {
  align-self: stretch;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(0.55rem, 1.1vw, var(--space-3));
  min-height: 0;
  overflow: visible;
  padding: clamp(0.85rem, 1.8vw, var(--space-4));
  background: var(--white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  font-size: clamp(0.8rem, 0.7rem + 0.25vw, 0.95rem);
}

.body-map__eyebrow {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--phr-red);
}

.body-map__panel h3 {
  margin: 0;
  font-size: clamp(1.05rem, 0.92rem + 0.45vw, 1.32rem);
  line-height: 1.12;
}
.body-map__panel p {
  margin: 0;
  color: var(--color-text-muted);
  line-height: 1.35;
}

.body-map__stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: var(--space-2);
}

.body-map__stats div {
  padding: var(--space-2);
  background: var(--color-bg-muted);
}

.body-map__stats strong {
  display: block;
  font-family: var(--font-sans);
  font-size: clamp(1.1rem, 0.92rem + 0.5vw, var(--fs-lg));
  line-height: 1;
}

.body-map__stats span {
  display: block;
  margin-top: var(--space-1);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  color: var(--color-text-muted);
}

.body-map__bars {
  display: grid;
  gap: clamp(0.35rem, 0.8vw, var(--space-2));
}

.body-map__bar {
  display: grid;
  grid-template-columns: minmax(120px, 1fr) minmax(100px, 1.2fr) auto;
  gap: clamp(0.45rem, 0.8vw, var(--space-2));
  align-items: center;
  font-family: var(--font-sans);
  font-size: clamp(0.68rem, 0.62rem + 0.16vw, var(--fs-xs));
  line-height: 1.2;
}

.body-map__bar-track {
  height: clamp(8px, 1.05vw, 12px);
  background: var(--color-border);
  border-radius: 100px;
  overflow: hidden;
}

.body-map__bar-fill {
  display: block;
  height: 100%;
}

@media (max-width: 600px) {
  .body-map {
    grid-template-columns: 1fr;
    height: auto;
    padding: var(--space-3);
  }
  .body-map__visual { aspect-ratio: 2816 / 1536; }
  .body-map__panel { max-height: none; overflow: visible; }
  .body-map__bar { grid-template-columns: 1fr auto; }
  .body-map__bar-track { grid-column: 1 / -1; }
}

/* =============================================================================
   METHODS
   ============================================================================ */

/* --- Methods overview grid --------------------------------------------------- */
.methods-overview { display: grid; gap: var(--space-3); margin: var(--space-5) 0; }
.mo-row {
  display: grid; gap: var(--space-3);
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}
.mo-card {
  background: var(--white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
}
.mo-card h4 {
  font-family: var(--font-sans); font-size: var(--fs-xs);
  letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--phr-red); margin-bottom: var(--space-2);
}
.mo-card p, .mo-card li { font-size: var(--fs-sm); }
.mo-card ul { margin: 0; }
.mo-card li { margin: 0.3em 0; }
.mo-card li ul { margin-top: 0.3em; padding-left: 1.1em; }
.mo-card--sampling { background: var(--white); border: 1px solid var(--color-border); border-radius: var(--radius); padding: var(--space-3) var(--space-4); }
.mo-card__cols { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.mo-card__cols ul { font-size: var(--fs-sm); }
.mo-card--question {
  background: #EDF2F7;
  border-left: 4px solid var(--phr-navy);
}
.mo-card--question p { font-size: var(--fs-base); max-width: none; }

/* --- Detailed methods: native <details>/<summary> ---------------------------
   Old build used JS-dependent folder tabs; the new markup is a plain native
   <details class="methods-detail"><summary>…</summary>…</details>, styled
   simply here (no JS-driven tab mechanism to port). */
.methods-detail {
  margin-top: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--white);
  max-width: var(--content-max);
}
.methods-detail summary {
  cursor: pointer;
  padding: var(--space-3) var(--space-4);
  font-family: var(--font-sans); font-weight: 700;
  color: var(--phr-navy);
  list-style-position: inside;
}
.methods-detail summary:hover { color: var(--phr-red); }
.methods-detail summary::-webkit-details-marker { color: var(--phr-navy); }
.methods-detail__body {
  padding: var(--space-2) var(--space-4) var(--space-5);
  border-top: 1px solid var(--color-border);
}
.methods-detail__body > p,
.methods-detail__body > ul,
.methods-detail__body > ol {
  max-width: none;
}

/* --- Definition-style blocks (dt/dd, deflist) -------------------------------- */
.deflist { display: grid; gap: var(--space-4); max-width: var(--content-max); }
.deflist dt { font-family: var(--font-sans); font-weight: 700; color: var(--color-text); }
.deflist dd { margin: var(--space-1) 0 0; max-width: var(--measure); }

/* =============================================================================
   LEGAL
   ============================================================================ */

/* --- Six principles (before / during / after) cards -------------------------- */
.principles { display: grid; gap: var(--space-4); max-width: var(--content-max); }
.principles__when {
  font-family: var(--font-sans); font-size: var(--fs-xs); font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--color-text-muted);
  margin-bottom: var(--space-2);
}
.principles__cards {
  display: grid; gap: var(--space-3);
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.principle-card {
  background: var(--white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
}
.principle-card h4 { font-family: var(--font-sans); margin-bottom: var(--space-1); }
.principles-cards .principle-card h4 { color: var(--phr-red); }
.principle-card p { font-size: var(--fs-sm); }

/* --- Six principles: scroll-driven converging illustrations -----------------
   PORTED VERBATIM (with the one-level-deeper asset-path fix below). This is
   the Legal section's OWN separate scrolly widget — explicitly out of scope
   for the Findings-scrolly removal per PLAN.md ("keep its own
   principles-scrolly ... leave alone unless later asked"). report-v2/index.html
   still contains the exact same principles-scrolly/principles-stage/
   principles-slide markup, driven by nav.js's initPrinciplesScroll. */
/* .principles-stage's `position: sticky` needs scroll room below it — this is
   the one generic .scrolly rule Step 5 should not have dropped (it read as
   dead weight because the multi-slide Findings engine was gone, but
   principles-scrolly still needs it). Height is set by nav.js's trimmed
   scroll-progress engine via --scrolly-height. */
.scrolly { position: relative; height: var(--scrolly-height, calc(5 * 100vh)); }

.principles-scrolly { margin-top: var(--space-5); }

.principles-stage {
  position: sticky;
  top: var(--top-chrome-height);
  height: calc(100vh - var(--top-chrome-height));
  overflow: hidden;
  background: var(--color-bg-muted);
  border-top: 3px solid var(--phr-red);
  max-width: var(--content-max);
  margin: 0 auto;
}

/* This single-slide stage doesn't use the two-column chart/text grid. */
.principles-slide {
  position: relative;
  display: block;
  height: 100%;
  padding: 0;
  max-width: none;
}

.principles-img {
  position: absolute;
  top: 50%;
  left: 50%;
  width: clamp(190px, 22vw, 300px);
  height: auto;
  /* transform is set per-frame in JS; this is the resting value */
  transform: translate(-50%, -50%);
  will-change: transform, opacity;
  z-index: 1;
}
.principles-img--after {
  top: 45%;
  width: clamp(180px, 23vw, 310px);
  opacity: 0;
  z-index: 2;
}

/* Card stack pinned to the top of the stage; the three phases are layered and
   crossfaded by JS. */
.principles-cards {
  position: absolute;
  top: clamp(var(--space-5), 8vh, var(--space-7));
  left: 50%;
  transform: translateX(-50%);
  width: min(820px, 90%);
  z-index: 3;
}
.principles-phase {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  opacity: 0;
}
.principles-phase[data-phase="before"] { opacity: 1; }
.principles-phase[data-phase="after"] {
  left: 50%;
  right: auto;
  width: min(560px, 100%);
  transform: translateX(-50%);
}
.principles-phase[data-phase="after"] .principles__cards {
  grid-template-columns: 1fr;
}
/* Tighten the card grid so it sits comfortably above the illustration. */
.principles-cards .principles__cards { gap: var(--space-2); }
.principles-cards .principle-card { padding: var(--space-2) var(--space-3); }
.principles-cards .principle-card p { font-size: var(--fs-xs); }

/* Mobile: no pinning/animation — illustrations and all three card phases flow
   normally. Placed after the base rules above so it wins the cascade. */
@media (max-width: 820px) {
  .scrolly { height: auto !important; }
  .principles-stage {
    position: static;
    height: auto;
    border-top: none;
    background: transparent;
    overflow: visible;
  }
  .principles-slide { position: static; height: auto; }
  .principles-img {
    position: static;
    transform: none !important;
    opacity: 1 !important;
    display: block;
    width: min(420px, 100%);
    margin: var(--space-3) auto;
  }
  .principles-img--after { width: min(280px, 100%); }
  .principles-cards {
    position: static;
    transform: none;
    width: 100%;
  }
  .principles-phase {
    position: static;
    opacity: 1 !important;
    margin-bottom: var(--space-4);
  }
}

/* --- Legal claims table (federal claims relevant to CCW misuse) ------------- */
.claims-table {
  min-width: 1100px;
  table-layout: fixed;
}
.claims-table th, .claims-table td { vertical-align: top; }
.claims-table thead th {
  font-size: var(--fs-xs);
  text-transform: uppercase; letter-spacing: 0.03em;
  color: var(--color-text-muted);
}
.claims-table tbody th {
  min-width: 0; width: 15%;
  background: var(--color-bg-muted);
  border-top: 3px solid var(--phr-navy);
}
.claims-table tbody th p, .claims-table tbody td p {
  font-size: var(--fs-xs);
  margin: 0 0 var(--space-2);
}
.claims-table tbody th p:last-child, .claims-table tbody td p:last-child { margin-bottom: 0; }
.claims-table tbody td { width: 21.25%; }

/* --- Misuse standards table (international standards vs. protocols) -------- */
.misuse-table { min-width: 900px; }
.misuse-table tbody th { width: 14%; }
.misuse-table__group th, .misuse-table__group td {
  background: var(--color-bg-muted);
  border-top: 3px solid var(--phr-navy);
}
.misuse-table td p, .misuse-table th p { font-size: var(--fs-xs); }

/* =============================================================================
   LOADING SCREEN — full-screen overlay shown while the app boots
   ============================================================================ */
.loading-screen {
  position: fixed;
  inset: 0;
  z-index: 10000;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  background: var(--white);
  color: var(--color-text);
  font-family: var(--font-sans);
  text-align: center;
  transition: opacity 0.4s var(--ease), visibility 0.4s var(--ease);
}
.loading-screen__spinner {
  width: 48px;
  height: 48px;
  border: 4px solid var(--color-border);
  border-top-color: var(--phr-red);
  border-radius: 50%;
  animation: loading-spin 1s linear infinite;
}
@keyframes loading-spin {
  to { transform: rotate(360deg); }
}
.loading-screen__text {
  font-size: var(--fs-sm);
  color: var(--color-text-muted);
  margin: 0;
  max-width: none;
}
.loading-screen.is-hidden {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .loading-screen { transition: none; }
  .loading-screen__spinner { animation: none; border-color: var(--phr-red); }
}

/* --- No-JS notice (noscript fallback) ---------------------------------------- */
.noscript-notice p { max-width: 40ch; margin: 0 auto; }
