/* Phase 3a: shares the record/instrument type stack (Literata/Public Sans/
   IBM Plex Mono) with the rest of Pheme instead of the Inter fallback this
   shell used before the atlas theater existed. --serif is reserved for the
   scenario title only (see .story-head h1); everything else in the theater
   still speaks --sans/--mono, per the approved prototypes.
   This page has no <link> to the record shell's tokens.css (different
   surface, different token set), so the specific weights actually used here
   are self-hosted directly — copied from pheme-backend/site/tokens.css,
   which is the canonical source for all three families. */
@font-face {
  font-family: "Literata";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/assets/fonts/literata-600-sub5dcdda.woff2) format("woff2");
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
@font-face {
  font-family: "Literata";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/assets/fonts/literata-600-cyrillic-ext.woff2) format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "Literata";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/assets/fonts/literata-600-greek-ext.woff2) format("woff2");
  unicode-range: U+1F00-1FFF;
}
@font-face {
  font-family: "Literata";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/assets/fonts/literata-600-greek.woff2) format("woff2");
  unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
@font-face {
  font-family: "Literata";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/assets/fonts/literata-600-vietnamese.woff2) format("woff2");
  unicode-range:
    U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301,
    U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
@font-face {
  font-family: "Literata";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/assets/fonts/literata-600-latin-ext.woff2) format("woff2");
  unicode-range:
    U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329,
    U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,
    U+A720-A7FF;
}
@font-face {
  font-family: "Literata";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/assets/fonts/literata-600-latin.woff2) format("woff2");
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Public Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/assets/fonts/public-sans-400-vietnamese.woff2) format("woff2");
  unicode-range:
    U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301,
    U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
@font-face {
  font-family: "Public Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/assets/fonts/public-sans-400-latin-ext.woff2) format("woff2");
  unicode-range:
    U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329,
    U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,
    U+A720-A7FF;
}
@font-face {
  font-family: "Public Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/assets/fonts/public-sans-400-latin.woff2) format("woff2");
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Public Sans";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/assets/fonts/public-sans-600-vietnamese.woff2) format("woff2");
  unicode-range:
    U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301,
    U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
@font-face {
  font-family: "Public Sans";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/assets/fonts/public-sans-600-latin-ext.woff2) format("woff2");
  unicode-range:
    U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329,
    U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,
    U+A720-A7FF;
}
@font-face {
  font-family: "Public Sans";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/assets/fonts/public-sans-600-latin.woff2) format("woff2");
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/assets/fonts/plex-mono-400-sub5dcdda.woff2) format("woff2");
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/assets/fonts/plex-mono-400-cyrillic-ext.woff2) format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/assets/fonts/plex-mono-400-vietnamese.woff2) format("woff2");
  unicode-range:
    U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301,
    U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/assets/fonts/plex-mono-400-latin-ext.woff2) format("woff2");
  unicode-range:
    U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329,
    U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,
    U+A720-A7FF;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/assets/fonts/plex-mono-400-latin.woff2) format("woff2");
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  color-scheme: dark;
  --ink: #f5f1e7;
  --muted: #a8b2bb;
  --dim: #71808d;
  --night: #071018;
  --panel: #0a141d;
  --line: rgba(229, 222, 202, 0.16);
  --gold: #d4b46f;
  --gold-bright: #f2d894;
  --cyan: #6fc8cf;
  --red: #ed765f;
  --safe: #70c49a;
  --ev-modeled-night: #a48ae8;
  --shadow: 0 18px 40px rgba(0, 0, 0, 0.34);
  --serif: "Literata", "Literata-fallback", "Iowan Old Style", Georgia, serif;
  --sans: "Public Sans", "PublicSans-fallback", -apple-system, "Helvetica Neue", Arial, sans-serif;
  --mono: "IBM Plex Mono", "PlexMono-fallback", ui-monospace, "SF Mono", Menlo, monospace;
  font-family: var(--sans);
}

/* Metric-matched local fallbacks so swapped text never shifts layout (same
   technique + calibrated values as site/tokens.css; see there for the full
   rationale). Backed by Times New Roman / Arial / Courier New — Linux's
   Liberation fonts clone those metrics, so one set of overrides matches on
   every platform. */
@font-face {
  font-family: "Literata-fallback";
  src: local("Times New Roman"), local("Liberation Serif");
  size-adjust: 112.66%;
  ascent-override: 104.5%;
  descent-override: 27.3%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "PublicSans-fallback";
  src: local("Arial"), local("Liberation Sans");
  size-adjust: 103.45%;
  ascent-override: 91.8%;
  descent-override: 21.7%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "PlexMono-fallback";
  src: local("Courier New"), local("Liberation Mono");
  size-adjust: 99.98%;
  ascent-override: 102.5%;
  descent-override: 27.5%;
  line-gap-override: 0%;
}

* {
  box-sizing: border-box;
}
[hidden] {
  display: none !important;
}
html,
body {
  height: 100%;
  margin: 0;
  overflow: hidden;
  background: var(--night);
  color: var(--ink);
  /* The room darkens/lightens on the browse↔running transition (data-mode
     flips in sim-shell.mjs). prefers-reduced-motion further down caps every
     transition-duration to ~0, giving an instant swap instead. */
  transition:
    background-color 0.35s ease,
    color 0.35s ease;
}
body {
  min-width: 320px;
}
button,
input,
textarea,
select {
  font: inherit;
}
button,
a {
  -webkit-tap-highlight-color: transparent;
}
button {
  color: inherit;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.skip-link {
  position: fixed;
  top: 8px;
  left: 8px;
  z-index: 100;
  padding: 12px 16px;
  min-height: 44px;
  border-radius: 8px;
  background: #fff;
  color: #071018;
  transform: translateY(-150%);
}
.skip-link:focus {
  transform: none;
}

.sim-app {
  width: 100%;
  height: 100%;
  min-width: 0;
  display: grid;
  grid-template-rows: auto 1fr;
  background: var(--night);
  transition: background-color 0.35s ease;
}
.topbar {
  position: relative;
  z-index: 20;
  min-width: 0;
  background: #050d14;
  border-bottom: 1px solid var(--line);
  transition:
    background-color 0.35s ease,
    border-color 0.35s ease;
}

/* Masthead: brand + 5-item nav + disclosure, generated by site/render.mjs's
   header() at build time (scripts/build-site.mjs) — one source of chrome
   markup for the whole site, not a second bespoke topbar. This page doesn't
   load signal-room.css, so the shared .signal-* classes get their own
   compact styling here, themed through the same --ink/--muted/--line/--panel
   variables the night↔browse swap below already drives. */
.signal-header {
  min-width: 0;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 14px;
  padding: 4px clamp(14px, 3vw, 24px) 2px;
}
.signal-brand {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--ink);
  text-decoration: none;
  font-family: var(--serif);
  font-size: 18px;
  letter-spacing: 0.01em;
}
.signal-brand-mark {
  display: none;
}
.signal-ask {
  display: none;
}
.signal-nav {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 2px;
}
.signal-nav a {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  padding: 0 11px;
  color: var(--muted);
  text-decoration: none;
  font-family: var(--sans);
  font-size: 12.5px;
  font-weight: 600;
}
.signal-nav a:hover {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 4px;
}
.signal-nav a[aria-current="page"] {
  color: var(--ink);
  box-shadow: inset 0 -2px 0 0 var(--ink);
}
.signal-menu-button {
  display: none;
}
.signal-context {
  position: relative;
  min-height: 44px;
  color: var(--dim);
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  white-space: nowrap;
}
.signal-context summary {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  cursor: pointer;
  list-style: none;
}
.signal-context summary::-webkit-details-marker {
  display: none;
}
.signal-context summary::after {
  content: "＋";
  margin-left: 5px;
}
.signal-context[open] summary::after {
  content: "−";
}
/* same fix as site/styles.css: <details>'s native content-hiding doesn't
   reliably suppress an absolutely-positioned child when closed, so the
   popover stays laid out off-viewport at high zoom and forces a horizontal
   scrollbar. This page doesn't load evidence.css/styles.css, so it needs
   its own copy of the override. */
.signal-context:not([open]) .signal-context-popover {
  display: none;
}
.signal-context-popover {
  position: absolute;
  z-index: 25;
  top: calc(100% + 4px);
  right: 0;
  width: min(320px, calc(100vw - 24px));
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--panel);
  color: var(--muted);
  letter-spacing: normal;
  text-transform: none;
  white-space: normal;
  box-shadow: var(--shadow);
}
.signal-context-popover strong {
  display: block;
  color: var(--ink);
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 700;
}
.signal-context-popover p {
  margin: 6px 0 10px;
  font-family: var(--sans);
  font-size: 13px;
  line-height: 1.5;
}
.signal-context-popover a {
  color: inherit;
  font-weight: 700;
}

/* Instrument row: scope switch · status line · Run button · sound · menu —
   every control below keeps its pre-Phase-3a id/data-track. */
.instrument-row {
  min-width: 0;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 14px;
  padding: 8px clamp(14px, 3vw, 24px);
  border-top: 1px solid var(--line);
}
.browse-status {
  margin: 0;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.scope-switch {
  display: flex;
  align-items: center;
  padding: 4px;
  border: 1px solid var(--line);
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.035);
}
.scope-switch a {
  min-height: 44px;
  display: flex;
  align-items: center;
  padding: 0 18px;
  border-radius: 0;
  color: var(--muted);
  font-size: 13px;
  font-weight: 700;
  text-decoration: none;
}
.scope-switch a.active {
  background: rgba(212, 180, 111, 0.16);
  color: var(--gold-bright);
  box-shadow: inset 0 0 0 1px rgba(212, 180, 111, 0.18);
}
.top-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
}
.site-menu {
  position: relative;
}
.site-menu summary {
  min-width: 44px;
  min-height: 44px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  list-style: none;
}
.site-menu summary::-webkit-details-marker {
  display: none;
}
.site-menu nav {
  position: absolute;
  top: calc(100% + 9px);
  right: 0;
  width: 210px;
  display: grid;
  padding: 8px;
  border: 1px solid var(--line);
  border-radius: 13px;
  background: rgba(7, 16, 24, 0.98);
  box-shadow: var(--shadow);
}
.site-menu nav a {
  min-height: 44px;
  display: flex;
  align-items: center;
  padding: 0 12px;
  border-radius: 8px;
  color: var(--muted);
  font-size: 13px;
  font-weight: 700;
  text-decoration: none;
}
.site-menu nav a:hover,
.site-menu nav a[aria-current="page"] {
  background: rgba(212, 180, 111, 0.1);
  color: var(--gold-bright);
}
.icon-button,
.primary,
.secondary,
.dialog-close,
.panel-close,
.transport-button,
.map-inspector {
  min-height: 44px;
  border-radius: 10px;
  cursor: pointer;
}
.icon-button {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 0 12px;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--muted);
}
/* Run is a hypothetical-INPUT action: flat amber per the evidence grammar
   (amber = your input), no gradient, no glow. */
.primary {
  padding: 0 18px;
  border: 1px solid #e2b13c;
  background: #e2b13c;
  color: #12120f;
  font-weight: 700;
}
.primary:hover {
  background: #edc35c;
  border-color: #edc35c;
}
.primary.compact {
  min-height: 44px;
}
.secondary {
  padding: 0 16px;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.055);
  color: var(--ink);
  font-weight: 700;
}
a.secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
}
button:focus-visible,
a:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
summary:focus-visible {
  outline: 3px solid var(--cyan);
  outline-offset: 3px;
}
/* On the paper surfaces (browse mode + the scenario sheet) the focus ring is
   violet — the product's interactive/hypothetical color — not the theater's
   cyan, which reads as off-identity on paper. */
html[data-mode="browse"] :is(button, a, input, textarea, select, summary):focus-visible,
.scenario-dialog :is(button, a, input, textarea, select, summary):focus-visible {
  outline-color: var(--ev-modeled);
}

.stage {
  position: relative;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  isolation: isolate;
}
/* Phase 3d: the no-WebGL Run path's plate — same modeled outcome the theater
   shows, drawn on plain SVG in place of the empty stage the fallback used to
   leave behind. Sits where .renderer would be; the vignette above still
   darkens it top/bottom like it does the 3D map. This is its own instance
   (see js/sim/sim-fallback-plate.mjs), not js/atlas/browse.mjs's demographic
   plate, so its stroke colors are night tokens rather than that plate's
   paper-mode ones — the two never share a theme. */
.fallback-plate-host {
  position: absolute;
  inset: 0;
  z-index: 1;
  overflow: hidden;
}
.fallback-plate-host .atlas-plate-svg {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}
/* The result panel is an overlay pinned to the right of the stage (see
   .result-panel: right:20px, width:min(440px,...)), so it sat on top of the
   eastern third of the plate. Measured at the result state: Florida was 208px
   wide and 208px of it was behind the panel at 1440, 182/182 at 1280 — the
   scenario's own origin state, fully hidden by a panel captioned "MODELED
   ORIGIN: Florida". Inset the plate host past the panel while it is open; the
   SVG is preserveAspectRatio="xMidYMid meet", so it rescales and re-centres
   into the remaining space instead of being cropped. Below 721px the panel is
   a bottom sheet and takes no horizontal room, so this must not apply there. */
@media (min-width: 721px) {
  .stage--result-open .fallback-plate-host {
    right: calc(min(440px, 100vw - 40px) + 32px);
    transition: right 0.35s cubic-bezier(0.2, 0.8, 0.2, 1);
  }
}
@media (min-width: 721px) and (prefers-reduced-motion: reduce) {
  .stage--result-open .fallback-plate-host {
    transition: none;
  }
}
.fallback-plate-host .atlas-plate-svg .ap {
  /* Same mid-dark hairline as the browse plate, so states stay separated under
     the violet run fill too (see .atlas-plate-svg .ap for the rationale). */
  stroke: var(--paper-ink-soft);
  stroke-width: 0.7;
  cursor: pointer;
  /* Each state resolves from the unresolved tone to its deviation color as the
     reveal reaches it (js/sim/reaction-stage.mjs), so the choropleth fills in
     with the model rather than appearing all at once. */
  transition: fill 0.4s ease;
}
@media (prefers-reduced-motion: reduce) {
  .fallback-plate-host .atlas-plate-svg .ap,
  .rx-bubble,
  .rx-smalldot {
    transition: none;
  }
}
.fallback-plate-host .atlas-plate-svg .ap:hover {
  stroke: var(--ink);
  stroke-width: 1.2;
}
.fallback-plate-host .atlas-plate-svg .ap.selected {
  stroke: var(--ev-modeled-night);
  stroke-width: 1.8;
}
.fallback-plate-host .atlas-plate-svg .ap:focus-visible {
  outline: 2px solid var(--ev-modeled-night);
  outline-offset: 1px;
}
/* Reaction-bubble overlay (js/sim/reaction-stage.mjs): SVG markers in the
   plate's own coordinate space. Text carries a paper halo (paint-order) so it
   reads over any map fill. Non-partisan categorical dots, shown with a legend. */
.rx-overlay {
  pointer-events: none;
}
.rx-bubble,
.rx-smalldot {
  transition: opacity 0.28s ease;
}
.rx-dot {
  stroke: var(--paper);
  stroke-width: 1.4;
}
.rx-smalldot {
  stroke: var(--paper);
  stroke-width: 1;
}
.rx-label {
  font: 700 12px var(--sans);
  fill: var(--paper-ink);
  paint-order: stroke;
  stroke: var(--paper);
  stroke-width: 3px;
  stroke-linejoin: round;
}
.rx-sub {
  font: 600 10px var(--mono);
  fill: var(--paper-ink-soft);
  paint-order: stroke;
  stroke: var(--paper);
  stroke-width: 3px;
  stroke-linejoin: round;
  letter-spacing: 0.02em;
}
.loading {
  position: absolute;
  inset: 0;
  z-index: 30;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 9px;
  background: #071018;
  color: var(--muted);
  text-align: center;
  transition: opacity 0.35s ease;
}
.loading strong {
  color: var(--ink);
  font-family: var(--sans);
  font-size: 22px;
  font-weight: 500;
}
.loading-orbit {
  width: 52px;
  height: 52px;
  margin-bottom: 10px;
  border: 1px solid rgba(212, 180, 111, 0.2);
  border-top-color: var(--gold-bright);
  border-radius: 50%;
  animation: spin 0.9s linear infinite;
}
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

.story-head {
  position: absolute;
  z-index: 5;
  top: 6.5%;
  left: clamp(22px, 4.5vw, 74px);
  max-width: min(690px, 57vw);
  pointer-events: none;
  text-shadow: 0 2px 16px rgba(0, 0, 0, 0.75);
}
.eyebrow {
  color: #a48ae8; /* modeled/violet voice — story kickers label modeled content */
  font-size: 11px;
  font-weight: 850;
  letter-spacing: 0.19em;
  text-transform: uppercase;
}
.story-head h1 {
  /* The one serif moment in the theater — everything else here speaks
     --sans/--mono. This is the scenario's own title, so it earns the same
     Literata 600 the approved night prototype gives it. */
  margin: 10px 0 8px;
  max-width: 19ch;
  font-family: var(--serif);
  font-size: clamp(30px, 4vw, 62px);
  font-weight: 600;
  line-height: 1.02;
  letter-spacing: -0.01em;
  text-wrap: balance;
}
.story-head p {
  margin: 0;
  color: var(--muted);
  font-size: clamp(13px, 1.2vw, 16px);
}
.phase-card {
  position: absolute;
  z-index: 5;
  left: clamp(22px, 4.5vw, 74px);
  bottom: 94px;
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: 360px;
  padding: 11px 15px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: #071019;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.24);
}
.phase-pip {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--gold-bright);
  box-shadow: 0 0 18px var(--gold-bright);
}
.phase-card div {
  display: grid;
  gap: 2px;
}
.phase-card span {
  color: var(--gold-bright);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.phase-card strong {
  font-size: 13px;
  font-weight: 650;
}
.origin-label {
  /* The origin marker follows the night/modeled-violet palette, not the
     event-accent warm tones VFX sprites keep (those are presentation
     accents for the effect itself, not the data marker). */
  position: absolute;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 11px;
  border: 1px solid rgba(164, 138, 232, 0.28);
  border-radius: 9px;
  background: rgba(5, 12, 18, 0.78);
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.28);
  pointer-events: none;
  transform: translate(-50%, -158%);
}
.origin-label span:last-child {
  display: flex;
  flex-direction: column;
}
.origin-label small {
  color: var(--ev-modeled-night);
  font-size: 8px;
  font-weight: 800;
  letter-spacing: 0.15em;
  text-transform: uppercase;
}
.origin-label strong {
  max-width: 140px;
  overflow: hidden;
  font-size: 12px;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.origin-pulse {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--ev-modeled-night);
  box-shadow:
    0 0 0 5px rgba(164, 138, 232, 0.16),
    0 0 18px var(--ev-modeled-night);
}
.map-inspector {
  position: absolute;
  z-index: 8;
  display: grid;
  gap: 2px;
  min-width: 150px;
  padding: 9px 12px;
  border: 1px solid var(--line);
  background: rgba(6, 14, 21, 0.92);
  box-shadow: var(--shadow);
  text-align: left;
  pointer-events: none;
  transform: translate(14px, 14px);
}
.map-inspector strong {
  font-size: 13px;
}
.map-inspector span {
  color: var(--muted);
  font-size: 11px;
}

.transport {
  position: absolute;
  z-index: 8;
  right: clamp(18px, 3vw, 45px);
  bottom: 23px;
  left: clamp(18px, 3vw, 45px);
  display: grid;
  grid-template-columns: 44px 1fr auto 44px;
  align-items: center;
  gap: 12px;
  max-width: 920px;
  margin: auto;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: #050d14;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.25);
}
.transport-button {
  width: 44px;
  padding: 0;
  border: 0;
  background: rgba(255, 255, 255, 0.08);
  font-size: 17px;
}
.timeline-label {
  display: flex;
  min-width: 0;
  min-height: 44px;
  align-items: center;
}
.timeline-label input {
  width: 100%;
  min-height: 44px;
  accent-color: var(--gold-bright);
  cursor: pointer;
}
.timecode {
  min-width: 82px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  text-align: center;
}
.quality-badge {
  position: absolute;
  z-index: 5;
  top: 16px;
  right: 18px;
  padding: 6px 9px;
  border-radius: 2px;
  background: rgba(6, 14, 21, 0.62);
  color: var(--dim);
  font-size: 9px;
  font-weight: 750;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* The standing legend: present from the first playback frame through result
   close (both playback and result hide/show it explicitly in sim-shell.mjs).
   On wide viewports the result panel is a right-hand column the full height
   of the stage (top:20/bottom:20, width up to 440px) — the legend's `right`
   offset below is computed from that same width so its right edge always
   sits just left of the panel, never underneath it, whether or not the
   panel happens to be open yet. Anchored to the bottom (just above the
   transport, itself hidden once a result opens) rather than the top, so it
   never competes with the scenario title for the same vertical band. */
.theater-legend {
  position: absolute;
  z-index: 7;
  /* Top-right, matching the phone override below. At bottom-right this 320x201
     card sat squarely on the south-east: measured against the rendered plate it
     covered 35,976px of US landmass — Florida, Georgia, Alabama, Mississippi,
     South Carolina — including 100% of the origin state for any Gulf/Atlantic
     scenario. Measuring all four corners on both plates: top-right covers
     7,167px (US, Maine/NH edges) + 14,924px (world, northern Russia) = 22k
     total, against 51k for bottom-right — the least-occluding corner on the US
     plate by 5x and within 10% of the best on the world plate. */
  top: 16px;
  bottom: auto;
  right: calc(40px + min(440px, 100vw - 40px));
  max-width: min(320px, calc(100vw - 480px - 28px));
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 7px 11px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: rgba(6, 14, 21, 0.82);
  color: var(--muted);
  font: 500 10.5px var(--mono);
  letter-spacing: 0.03em;
  box-shadow: var(--shadow);
}
.theater-legend .legend-ramp {
  display: inline-flex;
  height: 10px;
}
.theater-legend .legend-ramp i {
  width: 14px;
  height: 10px;
  display: inline-block;
  /* the swatch fill IS the key that explains the atlas plate's colors;
     forced-colors mode collapses every inline background to white, so
     leave this one element exempt (see site/evidence.css for the same
     rule and the full rationale) while the rest of the badge stays
     forced-color-aware. */
  forced-color-adjust: none;
}
.theater-legend .lname {
  color: var(--ink);
  font-weight: 650;
  white-space: nowrap;
}
.theater-legend-badge b {
  color: var(--ev-modeled-night);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
@media (max-width: 760px) {
  /* The result panel becomes a bottom sheet at this width instead of a
     right-hand column (see the ≤720px rule further down), so the legend
     moves to the top — clear of the sheet regardless of how tall it opens.
     The scenario title starts at ~4.5% of the stage's own height (see
     .story-head below) with no reserved band above it, so the phone legend
     drops its prose (still on desktop, still in the aria-label) down to a
     single compact swatches+badge line short enough to live in that gap
     instead of racing a variable-height title for the same space. */
  /* Measured, not guessed: the compact phone legend still renders 96px tall
     (swatches wrap to a second row at 390px), while .story-head sat 30px below
     the stage top — a 70px overlap that buried the eyebrow and the first line
     of the scenario title behind the legend card on BOTH simulate routes. The
     comment above hoped the compact legend was "short enough to live in that
     gap". It was not. The title now starts below the legend's real height
     instead of racing it for the same band. */
  .theater-legend {
    top: 4px;
    right: 8px;
    bottom: auto;
    max-width: calc(100vw - 16px);
    padding: 3px 8px;
    gap: 6px;
    font-size: 9.5px;
  }
  /* .legend-reactions needs the descendant selector its two siblings already
     have. On its own it is (0,1,0), and .legend-reactions further down this
     file is also (0,1,0) and later — so it won, and the reaction key this rule
     has always claimed to hide was on screen the whole time: 79px of the phone
     legend's 109px at 320px, 66px of 96px at 390px. That is the real reason the
     "single compact swatches+badge line" above measured 96px. It was never the
     swatches wrapping. The labeled key is in the result panel's reaction bars,
     which is where this comment always said phone readers would find it. */
  .theater-legend .lname,
  .theater-legend #theater-legend-meta,
  .theater-legend .legend-reactions {
    display: none;
  }
}

/* The same collision, one breakpoint up, and it was live on every window
   between 761px and 1180px until this rule existed.
   .theater-legend is pinned 480px in from the right so it clears the result
   panel's 440px column; .story-head runs from the left. Below ~1180px those two
   claims meet, and the legend — an opaque card — wins, because it is drawn
   later and sits at z-index 7 against the title's 5. Measured on both routes at
   640px AND 900px tall, so this was never the short-viewport case first
   recorded: the legend covered 12px of the h1's glyphs at 1180px, 116px at
   1024px, and 292px at 860px, where "A nationwide clean-energy transition
   accelerates over five years" reads as "A nationwid... energy trans...".
   Two things are wrong below 1180px, and both need fixing:
   1. The 320px cap makes the legend a tower — 201px tall, on a plate only
      ~580px wide at 1024px. It has the panel gutter's whole width available,
      so let the prose run sideways instead of down.
   2. Even short, it still owns the band the title wants. Stack them, the way
      the phone breakpoint above already does.
   max() keeps the no-script and browse-mode paths on their original 6.5%:
   --legend-bottom is published by showTheaterLegend() in js/sim/sim-shell.mjs
   and removed when the legend hides, so with no legend on screen there is
   nothing to clear.
   The .story-head half of this lives further down the file, immediately after
   the (max-height: 670px) block — see the comment there for why it cannot
   live here. */
@media (min-width: 761px) and (max-width: 1180px) {
  .theater-legend {
    max-width: calc(100vw - 508px);
  }
}

/* Under ~900px widening buys nothing — the gutter is only 253px at 761px, so
   the legend stays the 201px tower and the stage runs out of room: 201 legend +
   18 clearance + ~150 title + the 156px the briefing card holds at the bottom
   is 525px of demand against a 477px stage at 640px tall. Measured, that landed
   the subtitle's descenders 3px inside the briefing card on /us/simulate.
   Something has to fold, and the reaction key is the same thing the phone
   breakpoint folds, for the same reason and into the same place — the result
   panel's labeled reaction bars. The ramp, its gloss and the MODELED badge all
   stay, which is the part phones lose. */
@media (min-width: 761px) and (max-width: 900px) {
  .theater-legend .legend-reactions {
    display: none;
  }
}

/* Reaction color key (the second language on the map): the violet fill ramp
   above explains deviation intensity; this explains the categorical color each
   place's bubble/dot carries. Sits as a wrapped second row of the legend chip on
   desktop; hidden on phones, where the legend is a tiny top strip and the full
   labeled key lives in the result panel's reaction bars. */
.legend-reactions {
  flex-basis: 100%;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  margin-top: 3px;
  padding-top: 5px;
  border-top: 1px solid var(--paper-rule);
}
.legend-reaction {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  white-space: nowrap;
  color: var(--paper-ink-soft);
}
.legend-reaction i {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  forced-color-adjust: none;
}
/* One-line gloss under the reaction swatches: what the dots and the bubble ±
   numbers mean, so neither is a mystery without opening the result panel. */
.legend-reaction-note {
  flex-basis: 100%;
  color: var(--paper-ink-soft);
  opacity: 0.85;
}

.result-panel {
  position: absolute;
  z-index: 15;
  top: 20px;
  right: 20px;
  bottom: 20px;
  width: min(440px, calc(100vw - 40px));
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--panel);
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: panel-in 0.35s cubic-bezier(0.2, 0.8, 0.2, 1) both;
}
.result-panel:not([hidden]) ~ .transport {
  visibility: hidden;
}
@keyframes panel-in {
  from {
    opacity: 0;
  }
}
.panel-close {
  position: absolute;
  z-index: 2;
  top: 12px;
  right: 12px;
  width: 44px;
  padding: 0;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.04);
  font-size: 23px;
}
.result-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  padding: 30px 27px;
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
  -webkit-overflow-scrolling: touch;
}
.result-scroll h2 {
  margin: 8px 48px 7px 0;
  font-family: var(--sans);
  font-size: 34px;
  font-weight: 600;
  letter-spacing: -0.025em;
}
.result-lead {
  margin: 0 0 20px;
  color: var(--muted);
  line-height: 1.5;
}
.reaction-bars {
  display: grid;
  gap: 10px;
}
.reaction-row {
  display: grid;
  grid-template-columns: 92px 1fr 36px;
  align-items: center;
  gap: 9px;
  font-size: 12px;
}
.reaction-row > span:first-child {
  color: #dfe5e8;
}
.bar-track {
  height: 7px;
  overflow: hidden;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.08);
}
.bar-fill {
  height: 100%;
  border-radius: inherit;
  background: var(--bar, var(--cyan));
  transform-origin: left;
  animation: bar-in 0.65s ease both;
  /* each reaction's own color is the only thing that visually separates its
     bar from the others at a glance; under forced-colors both this fill and
     its .bar-track would collapse to the same system color, erasing the
     comparison a bar chart exists to show (the percentage text stays
     readable either way). */
  forced-color-adjust: none;
}
@keyframes bar-in {
  from {
    transform: scaleX(0);
  }
}
.reaction-row b {
  color: var(--muted);
  font-size: 11px;
  text-align: right;
}
.reaction-legend-note {
  margin: 8px 0 0;
  color: var(--dim);
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.02em;
}
.result-callouts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 9px;
  margin: 21px 0;
}
.callout {
  padding: 13px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.035);
}
.callout--focus {
  grid-column: 1 / -1;
}
.callout small {
  display: block;
  margin-bottom: 5px;
  color: var(--dim);
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.callout strong {
  display: block;
  font-size: 13px;
  line-height: 1.3;
}
.fallback-result {
  margin: 20px 0;
  padding: 15px;
  border: 1px solid rgba(104, 169, 176, 0.34);
  border-radius: 13px;
  background: rgba(104, 169, 176, 0.07);
}
.fallback-note h3 {
  margin: 6px 0;
  font-family: var(--sans);
  font-size: 21px;
  font-weight: 600;
}
.fallback-note p {
  margin: 0 0 13px;
  color: var(--muted);
  font-size: 14px;
  line-height: 1.55;
}
.modeled-data-details > summary {
  min-height: 44px;
  display: flex;
  align-items: center;
  color: var(--ink);
  font-size: 14px;
  font-weight: 750;
  cursor: pointer;
}
.modeled-data-details > p {
  margin: 0 0 12px;
  color: var(--muted);
  font-size: 14px;
  line-height: 1.5;
}
.fallback-table-scroll {
  max-height: 290px;
  overflow: auto;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: rgba(4, 11, 17, 0.48);
}
.fallback-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  line-height: 1.4;
}
.fallback-table caption {
  padding: 10px;
  color: var(--muted);
  text-align: left;
}
.fallback-table th,
.fallback-table td {
  padding: 9px 10px;
  border-top: 1px solid rgba(178, 207, 211, 0.12);
  text-align: left;
}
.fallback-table thead th {
  position: sticky;
  z-index: 1;
  top: 0;
  background: #0a1821;
  color: var(--muted);
  font: 800 10px/1.4 var(--mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.fallback-table tbody th {
  color: var(--ink);
  font-weight: 650;
}
.fallback-table td:last-child {
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.fallback-explore {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  margin-top: 12px;
  text-decoration: none;
}
.why-details {
  margin: 18px 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.why-details summary {
  min-height: 48px;
  display: flex;
  align-items: center;
  cursor: pointer;
  font-size: 13px;
  font-weight: 750;
}
.why-details > div,
.why-details > dl {
  padding: 0 0 16px;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.55;
}
.provenance-grid {
  margin: 0;
}
.provenance-grid > div {
  display: grid;
  grid-template-columns: minmax(92px, 0.38fr) 1fr;
  gap: 10px;
  padding: 8px 0;
  border-top: 1px solid rgba(178, 207, 211, 0.12);
}
.provenance-grid dt {
  color: var(--muted);
  font: 800 9px/1.4 var(--mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.provenance-grid dd {
  margin: 0;
  color: var(--text);
  overflow-wrap: anywhere;
}
.maat-card {
  display: grid;
  gap: 12px;
  margin: 18px 0;
  padding: 15px;
  border: 1px solid rgba(212, 180, 111, 0.28);
  border-radius: 13px;
  background: rgba(212, 180, 111, 0.055);
}
.maat-card strong {
  display: block;
  margin-top: 5px;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 19px;
}
.maat-card p {
  margin: 4px 0 0;
  color: var(--muted);
  font-size: 11px;
  line-height: 1.45;
}
.maat-output {
  font-size: 12px;
  line-height: 1.45;
}
/* Night variant of the claim-kind badge (see site/styles.css for why the kind
   leads the block). The instrument shell renders Ma'at on the dark surface. */
.maat-kind {
  margin: 0 0 8px;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
}
.maat-kind-badge {
  padding: 2px 8px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--panel);
  color: var(--text);
  font: 700 10px var(--mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
}
.maat-kind-what {
  max-width: 60ch;
  color: var(--muted);
  font: 12px/1.5 var(--sans);
}
html[data-mode="browse"] .maat-output .maat-kind-badge {
  border-color: var(--paper-rule);
  background: var(--paper-deep);
  color: var(--paper-ink);
}
html[data-mode="browse"] .maat-output .maat-kind-what {
  color: var(--paper-ink-soft);
}
.maat-claim {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
}
.maat-status {
  display: inline-block;
  margin-bottom: 5px;
  color: var(--gold-bright);
  font-size: 10px;
  font-weight: 800;
  text-transform: uppercase;
}
.maat-explain {
  color: var(--muted);
}
.maat-sources a {
  color: var(--cyan);
}
.comparison {
  margin: 16px 0;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
}
.comparison h3 {
  margin: 0 0 10px;
  font-family: var(--sans);
  font-weight: 600;
}
.compare-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.compare-grid div {
  padding: 10px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.04);
}
.compare-grid small {
  display: block;
  color: var(--dim);
}
.compare-grid strong {
  display: block;
  margin-top: 3px;
  font-size: 12px;
}
.disclosure {
  margin: 18px 0;
  color: var(--dim);
  font-size: 10px;
  line-height: 1.5;
}
.disclosure strong {
  color: var(--muted);
}
.result-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.scenario-dialog {
  width: min(920px, calc(100vw - 28px));
  max-height: min(850px, calc(100dvh - 28px));
  padding: 0;
  overflow: hidden;
  /* Newspaper scenario-desk: a paper sheet with a strong ink frame, so the
     scenario picker reads as a printed clipping laid over the atlas rather
     than a dark dashboard modal dropped on top of it. The dialog opens while
     the page is still in browse (paper) mode; it declares the paper token set
     on itself — the same self-scoping the old navy version used, flipped to
     the light surface — so every descendant (.preset-card, tabs, foot)
     inherits correct dark-on-paper contrast regardless of the page's mode. */
  --ink: var(--paper-ink);
  --muted: var(--paper-ink-soft);
  --dim: var(--paper-ink-faint);
  --line: var(--paper-rule);
  border: 2px solid var(--paper-rule-strong);
  border-radius: 2px;
  background: var(--paper);
  color: var(--paper-ink);
  box-shadow: 0 26px 70px rgba(33, 28, 20, 0.26);
}
.scenario-dialog::backdrop {
  /* Warm, light scrim — the atlas stays dimly visible behind the sheet, so
     picking a scenario never feels like leaving the map. */
  background: rgba(28, 22, 12, 0.32);
}
.dialog-shell {
  display: grid;
  max-height: inherit;
  padding: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.dialog-head {
  display: flex;
  justify-content: space-between;
  gap: 20px;
  padding: 24px 27px 17px;
  border-bottom: 2px solid var(--paper-rule-strong);
}
.dialog-head .eyebrow {
  color: var(--ev-modeled);
}
.dialog-head h2 {
  margin: 7px 0 4px;
  font-family: var(--serif);
  font-size: clamp(28px, 4vw, 42px);
  font-weight: 500;
  letter-spacing: -0.035em;
}
.dialog-head p {
  max-width: 650px;
  margin: 0;
  color: var(--muted);
  font-size: 15px;
  line-height: 1.45;
}
.dialog-close {
  flex: 0 0 44px;
  width: 44px;
  padding: 0;
  border: 1px solid var(--line);
  background: transparent;
  font-size: 24px;
}
.mode-tabs {
  display: flex;
  gap: 4px;
  padding: 14px 27px 0;
  border-bottom: 1px solid var(--paper-rule);
}
.mode-tabs button {
  min-height: 44px;
  padding: 0 15px;
  border: 0;
  border-bottom: 2px solid transparent;
  background: transparent;
  color: var(--paper-ink-soft);
  font-weight: 700;
  cursor: pointer;
}
.mode-tabs button[aria-selected="true"] {
  border-color: var(--paper-ink);
  color: var(--paper-ink);
}
[role="tabpanel"] {
  min-height: 0;
  max-height: 295px;
  overflow: auto;
  padding: 14px 27px;
}
.preset-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 9px;
}
/* A scenario reads as a bordered newspaper clipping: a full hairline rule plus
   a heavier ink rule down the left edge give real separation from the paper
   sheet behind it (paper-deep alone was only ~1.1:1 and blended). Selecting
   one turns the rules violet — the product's "hypothetical" color. */
.preset-card {
  min-height: 92px;
  display: grid;
  align-content: start;
  gap: 5px;
  padding: 13px 15px;
  border: 1px solid var(--paper-rule);
  border-left: 3px solid var(--paper-ink);
  border-radius: 2px;
  background: var(--paper);
  color: var(--paper-ink);
  text-align: left;
  cursor: pointer;
  transition:
    border-color 0.12s ease,
    background-color 0.12s ease;
}
.preset-card:hover,
.preset-card.selected {
  border-color: var(--ev-modeled);
  border-left-color: var(--ev-modeled);
  background: rgba(91, 63, 174, 0.07);
}
/* The category is now a newspaper section kicker above the headline; the old
   cryptic 2-letter code chip (.preset-icon) is gone from the markup. */
.preset-card small {
  color: var(--paper-ink-soft);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}
.preset-card strong {
  font-family: var(--serif);
  font-size: 15px;
  font-weight: 500;
  line-height: 1.32;
  color: var(--paper-ink);
}
.lab-note {
  margin: 0 0 12px;
  color: var(--muted);
  font-size: 15px;
  line-height: 1.45;
}
.category-label,
.custom-label {
  display: block;
  color: var(--muted);
  font-size: 12px;
  font-weight: 750;
}
#lab-category {
  min-height: 44px;
  margin: 6px 0 12px;
  padding: 0 12px;
  border: 1px solid var(--paper-rule);
  border-radius: 2px;
  background: var(--paper);
  color: var(--paper-ink);
}
.lab-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.custom-label {
  position: relative;
  z-index: 2;
  padding: 12px 27px 7px;
  border-top: 1px solid var(--paper-rule);
  background: var(--paper);
}
#scenario-input {
  width: calc(100% - 54px);
  min-height: 78px;
  margin: 0 27px;
  padding: 12px 14px;
  resize: vertical;
  border: 1px solid var(--paper-rule);
  border-radius: 2px;
  background: var(--paper);
  color: var(--paper-ink);
  font-size: 15px;
  line-height: 1.45;
}
#scenario-input::placeholder {
  color: var(--paper-ink-faint);
}
/* Why an empty submit did nothing. Same margins and left-rule shape as
   .setup-origin below so the two read as one column under the textarea, but in
   --paper-correction rather than --ev-input: this is a correction addressed to
   the reader, not a provenance note about the run, and borrowing an evidence
   token for it would say something about the data that isn't true. The border
   is redundant with the sentence, never the signal — the message reads the
   same in forced colors. */
.setup-error {
  margin: 12px 27px 0;
  padding: 11px 13px;
  border: 1px solid var(--paper-rule);
  border-left: 3px solid var(--paper-correction);
  border-radius: 2px;
  background: rgba(163, 74, 42, 0.07);
  color: var(--paper-ink);
  font-size: 14px;
  line-height: 1.4;
}
.setup-error[hidden] {
  display: none;
}

.setup-origin {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 3px 10px;
  margin: 12px 27px 0;
  padding: 11px 13px;
  border: 1px solid var(--paper-rule);
  border-left: 3px solid var(--ev-input);
  border-radius: 2px;
  background: rgba(138, 93, 0, 0.06);
  color: var(--paper-ink-soft);
  font-size: 14px;
  line-height: 1.4;
}
.setup-origin[hidden] {
  display: none;
}
.setup-origin span {
  color: var(--dim);
}
.setup-origin strong {
  color: var(--ink);
}
.setup-origin small {
  grid-column: 1 / -1;
  color: var(--dim);
  font-size: 13px;
}
.dialog-foot {
  position: sticky;
  z-index: 4;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: 17px;
  padding: 16px 27px 22px;
  border-top: 2px solid var(--paper-rule-strong);
  background: var(--paper);
}
.dialog-foot p {
  margin: 0;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.4;
}
.dialog-foot p strong {
  color: var(--muted);
}
.run-button {
  min-height: 50px;
}

@media (max-width: 760px) {
  .signal-header {
    padding: 4px 10px 2px;
    gap: 8px;
  }
  /* The 5-item nav and the "Simulation · not a poll" disclosure both
     duplicate wayfinding/messaging that .instrument-row's own site-menu
     dropdown and #stage-disclosure already carry on this page — hide them
     at phone widths rather than fight them for the same compact row. */
  .signal-nav,
  .signal-context {
    display: none;
  }
  .instrument-row {
    padding: 6px 10px;
    gap: 8px;
  }
  .wide-label {
    display: none;
  }
  .scope-switch a {
    min-height: 44px;
    padding: 0 11px;
    font-size: 11px;
  }
  .top-actions {
    margin-left: auto;
    gap: 5px;
  }
  .icon-button {
    width: 44px;
    justify-content: center;
    padding: 0;
  }
  /* The label stays. This collapsed to a 44px square with font-size:0 and a
     bare "+", which left every sighted phone and tablet visitor with no visual
     cue to the only action this screen exists for — while the accessible name
     survived, so nothing automated flagged it. Progressive disclosure may hide
     supporting detail; it may not hide the primary action. The plus is kept as
     an affordance and the text sits beside it. */
  .primary.compact {
    width: auto;
    min-height: 44px;
    padding: 0 13px;
    gap: 7px;
    font-size: 14px;
    white-space: nowrap;
  }
  .primary.compact::before {
    content: "+";
    font-size: 18px;
    line-height: 1;
  }
  .story-head {
    /* Was a hard-coded 118px: the measured clearance for a 96px legend that was
       only 96px because of the specificity bug fixed above. With the key
       actually hidden the legend is ~34px to its bottom edge, and holding 118px
       would spend 66px of a 568px-tall phone on empty space — which is where
       the title was running off the bottom into the briefing card (40px of the
       h1 and the whole "over five years" line, at 320x568, on both routes).
       Same shape as the 761-1180px rule now: clear the legend's real bottom,
       and fall back to the pre-legend 4.5% when there is no legend to clear. */
    top: max(4.5%, calc(var(--legend-bottom, 0px) + 18px));
    left: 17px;
    max-width: calc(100vw - 34px);
  }
  .story-head h1 {
    max-width: 15ch;
    margin-top: 7px;
    font-size: clamp(28px, 8.6vw, 42px);
    line-height: 1.01;
  }
  .story-head p {
    max-width: 290px;
    font-size: 12px;
  }
  .phase-card {
    left: 14px;
    bottom: 83px;
    max-width: calc(100vw - 28px);
  }
  .transport {
    right: 10px;
    bottom: max(10px, env(safe-area-inset-bottom));
    left: 10px;
    grid-template-columns: 44px 1fr 44px;
    gap: 7px;
  }
  .timecode {
    display: none;
  }
  .result-panel {
    top: auto;
    right: 8px;
    bottom: 8px;
    left: 8px;
    width: auto;
    height: min(73dvh, 680px);
    max-height: min(73dvh, 680px);
    border-radius: 18px;
  }
  .result-scroll {
    padding: 25px 20px calc(22px + env(safe-area-inset-bottom));
  }
  .result-scroll h2 {
    font-size: 30px;
  }
  .result-actions > button,
  .result-actions > a {
    flex: 1 1 130px;
  }
  .quality-badge {
    display: none !important;
  }
  .scenario-dialog {
    width: calc(100vw - 12px);
    max-height: calc(100dvh - 12px);
    border-radius: 2px;
  }
  .dialog-head {
    padding: 18px 17px 14px;
  }
  .dialog-head h2 {
    font-size: 30px;
  }
  .dialog-head p {
    font-size: 15px;
  }
  .mode-tabs {
    padding: 8px 17px 0;
  }
  [role="tabpanel"] {
    max-height: 31dvh;
    padding: 10px 17px;
  }
  .preset-grid,
  .lab-grid {
    grid-template-columns: 1fr;
  }
  .preset-card {
    min-height: 76px;
  }
  .custom-label {
    padding: 10px 17px 7px;
  }
  #scenario-input {
    width: calc(100% - 34px);
    min-height: 76px;
    margin: 0 17px;
    font-size: 16px;
  }
  .setup-origin {
    margin: 10px 17px 0;
    font-size: 15px;
  }
  .setup-origin small {
    font-size: 14px;
  }
  .dialog-foot {
    margin-top: 12px;
    padding: 12px 17px calc(15px + env(safe-area-inset-bottom));
  }
  .dialog-foot p {
    display: none;
  }
  .run-button {
    width: 100%;
  }
}

/* At true phone widths the result opens as a bottom sheet over the visible,
   dimmed map rather than a near-full-screen cover — the map stays legible
   behind it. Since Phase 3d the accessible 2D fallback has its own plate to
   show through too (js/sim/sim-fallback-plate.mjs), so it gets the same
   partial sheet as the WebGL theater instead of the taller/auto-height panel
   this used to reserve for it back when there was nothing behind it. */
@media (max-width: 720px) {
  .result-panel {
    top: auto;
    right: 0;
    bottom: 0;
    left: 0;
    width: 100%;
    height: min(55vh, 560px);
    max-height: min(55vh, 560px);
    border-radius: 18px 18px 0 0;
  }
  .result-scroll {
    padding-bottom: calc(22px + env(safe-area-inset-bottom));
  }
}

@media (max-width: 360px) {
  #sound-toggle {
    display: none;
  }
}

@media (max-height: 670px) and (min-width: 761px) {
  .story-head {
    top: 4%;
  }
  .story-head h1 {
    font-size: 38px;
  }
  [role="tabpanel"] {
    max-height: 220px;
  }
}

/* Placement is load-bearing, and the first attempt at this got it wrong.
   This is the .story-head half of the 761–1180px legend fix declared up beside
   .theater-legend — but the block directly above sets .story-head { top } at
   the same specificity, so at any height under 670px it simply took the
   property back and the title went on being covered. Only re-measuring at both
   640px and 900px caught it: the fix appeared to work, because at 900px it did.
   Sitting after that block is what makes it win.
   Losing the 4% on short screens costs nothing here — in this band the title is
   below the legend either way, and 4% of a ~477px stage is 19px against the
   ~131px of legend there is to clear. */
@media (min-width: 761px) and (max-width: 1180px) {
  .story-head {
    top: max(6.5%, calc(var(--legend-bottom, 0px) + 18px));
  }
}

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

/* ============================================================
   Browse mode — the atlas (paper), rule-bounded, no glow/blur/pill radii.
   The theater above stays night/gold; browse re-themes the same shared
   chrome vars (--ink, --muted, --night, --panel, --line) to their paper
   equivalents under [data-mode="browse"], so the topbar/buttons keep one
   set of rules instead of a second parallel theme. Ramp and evidence colors
   are new tokens read live by js/atlas/scales.mjs via getComputedStyle.
   ============================================================ */
:root {
  --paper: #f6f1e6;
  /* Kept in lockstep with site/tokens.css — the browse plate is the same paper
     environment, so its surfaces and rules have to clear the same perceptual
     floor (1.26:1 surface, 2.53:1 rule). See the note there. */
  --paper-deep: #e3d8ba;
  --paper-ink: #211c14;
  --paper-ink-soft: #57503f;
  /* Deepened with the surface, same as site/tokens.css's --ink-faint: at
     #6b6350 this fell to 4.19:1 on the new --paper-deep, which axe caught on
     the provenance source labels of both simulate routes. */
  --paper-ink-faint: #5f5846;
  --paper-rule: #a8977a;
  --paper-rule-strong: #211c14;

  --ev-observed: #211c14;
  --ev-modeled: #5b3fae;
  /* Kept in lockstep with site/tokens.css — re-certified against the deepened
     --paper-deep (see the note there). */
  --ev-input: #754e00;
  --ev-unknown: #5e594b;
  /* Form-correction rust, for the dialog's empty-submit message. This page
     does not load site/tokens.css, so --cost-more is not reachable here — the
     value is that token's, copied deliberately rather than referenced, because
     it is already certified at 6.48:1 on --paper and 5.14:1 on --paper-deep and
     this is the same paper environment. Not an evidence class: nothing about
     this message describes where a number came from. */
  --paper-correction: #7d4a24;

  --ramp-ink-1: #f0e8d9;
  --ramp-ink-2: #dccfb2;
  --ramp-ink-3: #c0a87e;
  --ramp-ink-4: #9d7f52;
  --ramp-ink-5: #6f5836;
  --ramp-ink-6: #463522;
  /* Bin 1 carries the lowest-deviation modeled states. The old #efe9fb sat at
     almost the same lightness as --paper (#f6f1e6), so those states read as
     blank cream on the run choropleth; nudged to a slightly more saturated pale
     violet so "modeled but low" is clearly distinct from unmodeled paper. */
  --ramp-violet-1: #e4d8f5;
  --ramp-violet-2: #cfc0f0;
  --ramp-violet-3: #a893dd;
  --ramp-violet-4: #8266c4;
  --ramp-violet-5: #5d43a0;
  --ramp-violet-6: #3a2a72;
  --ramp-lean-r3: #a63a30;
  --ramp-lean-r2: #c96a58;
  --ramp-lean-r1: #e2a58f;
  --ramp-lean-0: #efe6d4;
  --ramp-lean-d1: #9db8dd;
  --ramp-lean-d2: #5b86c4;
  --ramp-lean-d3: #2f5fa8;
  --ramp-no-record: #e8e0cf;
}

html[data-mode="browse"] {
  overflow-y: auto;
  --ink: var(--paper-ink);
  --muted: var(--paper-ink-soft);
  --dim: var(--paper-ink-faint);
  --night: var(--paper);
  --panel: var(--paper-deep);
  --line: var(--paper-rule);
}
html[data-mode="browse"] .sim-app {
  background: var(--paper);
}
html[data-mode="browse"] .topbar {
  background: var(--paper);
  border-bottom: 2px solid var(--paper-rule-strong);
}
html[data-mode="browse"] .scope-switch {
  background: transparent;
  border-color: var(--paper-rule-strong);
  border-radius: 2px;
}
html[data-mode="browse"] .scope-switch a.active {
  background: var(--paper-ink);
  color: var(--paper);
  box-shadow: none;
}
html[data-mode="browse"] .primary {
  background: var(--paper-ink);
  color: var(--paper);
  border: 1px solid var(--paper-ink);
  border-radius: 2px;
  box-shadow: none;
  font-weight: 600;
}
html[data-mode="browse"] .secondary {
  border-radius: 2px;
}
html[data-mode="browse"] .icon-button {
  border-radius: 2px;
}
html[data-mode="browse"] .site-menu summary {
  border-radius: 2px;
}
html[data-mode="browse"] .site-menu nav {
  background: var(--paper);
  border-color: var(--paper-rule);
  border-radius: 2px;
  box-shadow: 0 12px 28px rgba(33, 28, 20, 0.16);
}
html[data-mode="browse"] .site-menu nav a:hover,
html[data-mode="browse"] .site-menu nav a[aria-current="page"] {
  background: var(--paper-deep);
  color: var(--paper-ink);
}
html[data-mode="browse"] .stage {
  overflow: visible;
  height: auto;
  min-height: calc(100vh - 64px - 2rem);
}

/* The playback chrome (dispatch, transport, legend) and the result panel were
   authored for the night theater. The map-stage keeps the paper surface, so
   re-skin every hardcoded night color to the paper palette in browse mode —
   otherwise paper-ink text lands on leftover dark fills (1.13:1, an a11y fail). */
html[data-mode="browse"] .phase-card {
  background: var(--paper);
  border-color: var(--paper-rule-strong);
  box-shadow: 0 8px 24px rgba(33, 28, 20, 0.14);
}
html[data-mode="browse"] .phase-card span {
  color: var(--ev-modeled);
}
html[data-mode="browse"] .phase-pip {
  background: var(--ev-modeled);
  box-shadow: none;
}
html[data-mode="browse"] .phase-card strong {
  color: var(--paper-ink);
}
html[data-mode="browse"] .transport {
  background: var(--paper);
  border-color: var(--paper-rule-strong);
  box-shadow: 0 10px 30px rgba(33, 28, 20, 0.14);
}
html[data-mode="browse"] .transport-button {
  background: var(--paper-deep);
  color: var(--paper-ink);
}
html[data-mode="browse"] .timeline-label input {
  accent-color: var(--ev-modeled);
}
html[data-mode="browse"] .timecode {
  color: var(--paper-ink-soft);
}
html[data-mode="browse"] .theater-legend {
  background: var(--paper);
  border-color: var(--paper-rule);
  color: var(--paper-ink-soft);
  box-shadow: 0 8px 24px rgba(33, 28, 20, 0.12);
}
html[data-mode="browse"] .theater-legend .lname {
  color: var(--paper-ink);
}
html[data-mode="browse"] .theater-legend-badge b {
  color: var(--ev-modeled);
}
html[data-mode="browse"] .result-panel {
  background: var(--paper);
  border-color: var(--paper-rule-strong);
  box-shadow: 0 20px 60px rgba(33, 28, 20, 0.22);
}
html[data-mode="browse"] .panel-close {
  background: transparent;
  border-color: var(--paper-rule);
  color: var(--paper-ink);
}
html[data-mode="browse"] .reaction-row > span:first-child {
  color: var(--paper-ink);
}
html[data-mode="browse"] .bar-track {
  background: var(--paper-deep);
}
html[data-mode="browse"] .callout {
  background: var(--paper-deep);
  border-color: var(--paper-rule);
}
html[data-mode="browse"] .fallback-result {
  background: rgba(138, 93, 0, 0.06);
  border-color: var(--paper-rule);
}
html[data-mode="browse"] .fallback-table-scroll {
  background: var(--paper);
  border-color: var(--paper-rule);
}
html[data-mode="browse"] .fallback-table thead th {
  background: var(--paper-deep);
  color: var(--paper-ink-soft);
}
html[data-mode="browse"] .fallback-table th,
html[data-mode="browse"] .fallback-table td {
  border-top-color: var(--paper-rule);
}
html[data-mode="browse"] .compare-grid div,
html[data-mode="browse"] .maat-output .maat-claim {
  background: var(--paper-deep);
}
html[data-mode="browse"] .maat-status {
  color: var(--ev-input);
}
html[data-mode="browse"] .maat-sources a {
  color: var(--ev-modeled);
}
html[data-mode="browse"] .quality-badge {
  background: var(--paper-deep);
  color: var(--paper-ink-soft);
}
/* The small 9px bold metadata labels use --dim (paper-ink-faint), which clears
   4.5:1 on plain paper but not on the slightly darker paper-deep callouts —
   drop them one notch to paper-ink-soft so every label passes AA on both. */
html[data-mode="browse"] .callout small,
html[data-mode="browse"] .provenance-grid dt,
html[data-mode="browse"] .compare-grid small,
html[data-mode="browse"] .disclosure,
html[data-mode="browse"] .disclosure strong,
html[data-mode="browse"] .reaction-legend-note,
html[data-mode="browse"] .reaction-row b {
  color: var(--paper-ink-soft);
}
/* Story headline over the paper map: the night version used a big 62px title
   with a dark drop-shadow (built for light-on-dark). On paper that shadow reads
   as blur and the size blots out the north-west states' bubbles. Smaller, ink,
   with a paper halo so it stays legible over the choropleth without a heavy
   backdrop; the violet eyebrow goes to the darker --ev-modeled for AA. */
html[data-mode="browse"] .story-head {
  text-shadow:
    0 1px 12px var(--paper),
    0 1px 3px var(--paper);
}
html[data-mode="browse"] .story-head h1 {
  font-size: clamp(26px, 3vw, 40px);
  color: var(--paper-ink);
}
html[data-mode="browse"] .story-head p {
  color: var(--paper-ink-soft);
}
html[data-mode="browse"] .eyebrow {
  color: var(--ev-modeled);
}
/* Click-for-why: clicking a state fills the inspector with that place's reaction,
   share, and the engine's top demographic factors. Paper card, bottom-left, above
   the dispatch; pointer-events on so it's dismissable (the night default was
   pointer-events:none, purely a hover readout). */
html[data-mode="browse"] .map-inspector {
  top: auto;
  bottom: 100px;
  left: clamp(22px, 4.5vw, 74px);
  transform: none;
  max-width: min(360px, calc(100vw - 40px));
  padding: 12px 15px;
  pointer-events: auto;
  cursor: pointer;
  background: var(--paper);
  border: 1px solid var(--paper-rule-strong);
  border-radius: 2px;
  box-shadow: 0 12px 32px rgba(33, 28, 20, 0.2);
  color: var(--paper-ink);
  z-index: 9;
}
html[data-mode="browse"] .map-inspector strong {
  font: 600 16px var(--serif);
  color: var(--paper-ink);
}
html[data-mode="browse"] .map-inspector .inspect-reaction {
  font-family: var(--sans);
  font-weight: 800;
}
html[data-mode="browse"] .map-inspector .inspect-share {
  color: var(--paper-ink-soft);
  font-size: 12px;
}
html[data-mode="browse"] .map-inspector .inspect-why {
  display: block;
  margin-top: 5px;
  color: var(--paper-ink-soft);
  font-size: 12px;
  line-height: 1.45;
}
/* The clicked state gets a crisp violet outline (hypothetical color) so the
   click-for-why selection is obvious against the run fill. */
html[data-mode="browse"] .fallback-plate-host .atlas-plate-svg .ap.selected {
  stroke: var(--ev-modeled);
  stroke-width: 2;
}

.stage-disclosure {
  margin: 0;
  padding: 6px 22px;
  font:
    500 11px/1.4 ui-monospace,
    "SF Mono",
    Menlo,
    monospace;
  letter-spacing: 0.04em;
  color: var(--paper-ink-soft, var(--muted));
  background: var(--paper, transparent);
}
html:not([data-mode="browse"]) body .stage-disclosure {
  display: none;
}

.browse-status {
  margin: 0;
  padding: 8px 22px;
  font:
    600 11px/1.4 ui-monospace,
    "SF Mono",
    Menlo,
    monospace;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--paper-ink-soft);
  background: var(--paper-deep);
  border-bottom: 1px solid var(--paper-rule);
}

.atlas-browse-host {
  position: relative;
  z-index: 1;
  padding: 20px 22px 40px;
  color: var(--paper-ink);
  font-family:
    "Public Sans",
    -apple-system,
    "Helvetica Neue",
    Arial,
    sans-serif;
}
.atlas-browse-error {
  font-size: 14px;
  color: var(--paper-ink-soft);
}
.atlas-browse-error a {
  color: var(--paper-ink);
}

.atlas-grid {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(280px, 3fr);
  gap: 28px;
  align-items: start;
  max-width: 1280px;
  margin: 0 auto;
}

.atlas-plate-section {
  min-width: 0;
}
.atlas-plate-wrap {
  position: relative;
}
.atlas-plate-wrap svg {
  width: 100%;
  height: auto;
  display: block;
}
.atlas-plate-svg .ap {
  /* A mid-dark hairline reads on BOTH ends of the sepia ramp: it is darker than
     the lightest fills (so adjacent light states separate) and lighter than the
     darkest fills (so it still shows there). A cream stroke — matching the page
     — left light states blurring into each other. */
  stroke: var(--paper-ink-soft);
  stroke-width: 0.7;
  cursor: pointer;
}
.atlas-plate-svg .ap:hover {
  stroke: var(--paper-ink);
  stroke-width: 1.4;
}
.atlas-plate-svg .ap.selected {
  stroke: var(--paper-ink);
  stroke-width: 1.8;
}
.atlas-plate-svg .ap:focus-visible {
  outline: 2px solid var(--ev-modeled);
  outline-offset: 1px;
}

.atlas-kbd-note {
  font-size: 12.5px;
  color: var(--paper-ink-soft);
  margin: 10px 0 0;
}
.atlas-kbd-note a {
  color: var(--paper-ink);
}

.atlas-rail-heading {
  font:
    600 11px ui-monospace,
    "SF Mono",
    Menlo,
    monospace;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--paper-ink-soft);
  margin: 0 0 8px;
}

.layer-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.chip {
  font:
    500 13px "Public Sans",
    sans-serif;
  border: 1px solid var(--paper-rule);
  background: transparent;
  color: var(--paper-ink);
  padding: 8px 12px;
  min-height: 44px;
  border-radius: 2px;
  cursor: pointer;
  text-align: left;
  width: 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  list-style: none;
}
.chip::-webkit-details-marker {
  display: none;
}
.chip[aria-pressed="true"] {
  border-color: var(--paper-ink);
  background: var(--paper-deep);
  font-weight: 700;
}
.chip:focus-visible {
  outline: 2px solid var(--ev-modeled);
  outline-offset: 2px;
}
.chip .src {
  font:
    400 10px ui-monospace,
    "SF Mono",
    Menlo,
    monospace;
  color: var(--paper-ink-faint);
  white-space: nowrap;
}
.layer-more {
  margin-top: 2px;
}
.layer-more > .layer-list {
  margin-top: 6px;
}

.legend-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  font:
    500 11.5px ui-monospace,
    "SF Mono",
    Menlo,
    monospace;
  color: var(--paper-ink-soft);
  border-top: 1px solid var(--paper-rule);
  border-bottom: 1px solid var(--paper-rule);
  padding: 8px 0;
  margin-top: 12px;
}
.legend-bar .lname {
  color: var(--paper-ink);
  font-weight: 600;
}
.legend-ramp {
  display: inline-flex;
  height: 12px;
}
/* same forced-color-adjust exemption as .theater-legend .legend-ramp i
   above and site/evidence.css's .legend-ramp i — this is the browse-mode
   inspector's own copy of the legend (this page never loads evidence.css). */
.legend-ramp i {
  width: 20px;
  height: 12px;
  display: inline-block;
  forced-color-adjust: none;
}

.inspector {
  border: 1px solid var(--paper-rule);
  border-top: 2px solid var(--paper-rule-strong);
  padding: 16px;
  font:
    400 14px "Public Sans",
    sans-serif;
  color: var(--paper-ink);
  border-radius: 2px;
}
.inspector:focus-visible {
  outline: 2px solid var(--ev-modeled);
  outline-offset: 2px;
}
.inspector h3 {
  margin: 8px 0 0;
  font: 600 19px var(--serif);
}
.inspector-empty {
  font-size: 13.5px;
  color: var(--paper-ink-soft);
  margin: 0;
}
.inspector dl {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 4px 16px;
  margin: 12px 0;
}
.inspector dt {
  color: var(--paper-ink-soft);
  font-size: 13px;
}
.inspector dd {
  margin: 0;
  font-variant-numeric: tabular-nums;
  text-align: right;
  font-weight: 600;
}
.inspector-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.inspector .btn,
.inspector-actions .btn {
  font:
    500 13px "Public Sans",
    sans-serif;
  border: 1px solid var(--paper-ink);
  background: transparent;
  color: var(--paper-ink);
  padding: 8px 12px;
  min-height: 44px;
  border-radius: 2px;
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
}
.inspector .prov {
  display: flex;
  gap: 8px;
  align-items: baseline;
  font:
    500 11px ui-monospace,
    "SF Mono",
    Menlo,
    monospace;
  letter-spacing: 0.05em;
  color: var(--paper-ink-soft);
  border-left: 3px solid var(--ev-observed);
  padding-left: 10px;
  margin: 0;
}
.inspector .prov b {
  color: var(--paper-ink);
  text-transform: uppercase;
  font-weight: 600;
}
/* derived (e.g. atlas density = population ÷ land area): same solid ink
   border-left as observed (it's computed FROM observed inputs, not a
   separate observation) but the class word prints in the modeled violet —
   mirrors evidence.css's .prov.derived for the "record" page family; this
   instrument surface keeps its own CSS copy (see .inspector .prov above),
   so the override lives here too rather than only in evidence.css, which
   this page never loads. */
.inspector .prov.derived b {
  color: var(--ev-modeled);
}
.legend-bar .prov.derived b {
  color: var(--ev-modeled);
}

@media (max-width: 1023px) {
  .atlas-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 760px) {
  html[data-mode="browse"] .stage {
    min-height: 0;
  }
  .atlas-browse-host {
    padding: 14px 16px 32px;
  }
  .atlas-plate-wrap {
    max-height: 60vh;
    overflow: hidden;
  }
  .inspector {
    position: sticky;
    bottom: 0;
    max-height: 45vh;
    overflow-y: auto;
    background: var(--paper);
    box-shadow: 0 -8px 20px rgba(33, 28, 20, 0.12);
  }
}

/* Mobile legibility floor for the simulation shell. These classes are also defined in
   site/styles.css, but the shell is separately authored and loads this file, so the
   floor has to exist in both or the simulate routes keep their 10px text.
   Measured at 390px before this: .disclosure 10px, .reaction-legend-note 10.5px,
   .browse-status / .stage-disclosure / .prov 11px. The disclosure is the sentence the
   whole product depends on ("This is a simulation, not a poll"), and it was the
   smallest text on the page. */
@media (max-width: 700px) {
  .prov,
  .browse-status,
  .stage-disclosure,
  .reaction-legend-note,
  .disclosure,
  .result-note p,
  .rx-legend p,
  .maat-card p {
    font-size: 12px;
  }
}

/* The JS-disabled state. Visible only inside <noscript>, so it costs scripted
   visitors nothing and gives unscripted ones a real answer instead of a
   spinner that never stops. */
.loading-noscript {
  max-width: 62ch;
  margin: 0;
  padding: 18px 20px;
  border: 1px solid var(--line, #2b3542);
  color: var(--bone, #e9e2d3);
  font: 15px/1.6 var(--sans, system-ui);
}
.loading-noscript b {
  display: block;
  margin-bottom: 6px;
}
.loading-noscript a {
  color: inherit;
}
