/* Exploitation Observatory site styles. All colors/sizes come from
   design/tokens/tokens.css via var(--obs-*). No opacity on text anywhere:
   dimmed states use a muted token that passes 4.5:1 on its own. */

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

body {
  margin: 0;
  background: var(--obs-color-bg);
  color: var(--obs-color-text);
  font-family: var(--obs-font-sans);
  font-size: var(--obs-text-md);
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}

.mono { font-family: var(--obs-font-mono); }
a { color: var(--obs-color-primary-text); }
a:hover { color: var(--obs-color-primary-text-hover); }

:focus-visible {
  outline: 2px solid var(--obs-color-signal);
  outline-offset: 2px;
  border-radius: var(--obs-radius-sm);
}

.visually-hidden {
  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: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: var(--obs-space-3) var(--obs-space-4);
  background: var(--obs-color-surface-2);
  color: var(--obs-color-text);
  border: 1px solid var(--obs-color-signal);
  border-radius: 0 0 var(--obs-radius) 0;
  text-decoration: none;
}
.skip-link:focus { left: 0; color: var(--obs-color-text); }

.page { min-height: 100vh; display: flex; flex-direction: column; }

/* ---------- Header ---------- */
.hdr {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--obs-space-2) var(--obs-space-6);
  padding: var(--obs-space-2) var(--obs-gutter);
  min-height: var(--obs-header-h);
  border-bottom: 1px solid var(--obs-color-border);
  box-shadow: var(--obs-hairline-signal);
}
.brand {
  display: flex;
  align-items: center;
  gap: var(--obs-space-3);
  text-decoration: none;
  color: var(--obs-color-text);
  min-height: var(--obs-touch-min);
}
.brand:hover { color: var(--obs-color-text); }
.brand-mark {
  width: 22px;
  height: 22px;
  border: 2px solid var(--obs-color-signal);
  border-radius: 50%;
  position: relative;
  display: inline-block;
  box-shadow: var(--obs-glow-signal);
}
.brand-mark span {
  position: absolute;
  left: 5px;
  top: 5px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--obs-color-primary);
}
.brand-word { font-weight: 700; letter-spacing: .14em; font-size: var(--obs-text-base); }

.nav {
  display: flex;
  gap: var(--obs-space-1);
  overflow-x: auto;
  flex: 1 1 auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.nav::-webkit-scrollbar { display: none; }
.nav a {
  white-space: nowrap;
  flex: 0 0 auto;
  padding: var(--obs-space-2) var(--obs-space-3);
  border-radius: var(--obs-radius);
  font-size: var(--obs-text-md);
  color: var(--obs-color-text-secondary);
  text-decoration: none;
  min-height: var(--obs-touch-min);
  display: inline-flex;
  align-items: center;
}
.nav a:hover { color: var(--obs-color-text); }
.nav a[aria-current="page"] {
  color: var(--obs-color-text);
  background: var(--obs-color-surface-2);
}

.hdr-side {
  display: flex;
  align-items: center;
  gap: var(--obs-space-3);
  margin-left: auto;
}
.live-chip {
  font-size: var(--obs-text-sm);
  color: var(--obs-color-signal);
  display: inline-flex;
  align-items: center;
  gap: var(--obs-space-2);
}
.live-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--obs-color-signal);
  box-shadow: var(--obs-glow-signal);
}

/* ---------- Buttons ---------- */
.btn {
  font: inherit;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--obs-touch-min);
  padding: 0 var(--obs-space-4);
  border-radius: var(--obs-radius);
  font-size: var(--obs-text-md);
  font-weight: 500;
  text-decoration: none;
  border: 1px solid transparent;
  white-space: nowrap;
}
.btn-primary {
  background: var(--obs-color-primary);
  color: #fff;
  font-weight: 600;
}
.btn-primary:hover { color: #fff; }
.btn-ghost {
  background: var(--obs-color-surface);
  border-color: var(--obs-color-border);
  color: var(--obs-color-text);
}
.btn-ghost:hover { color: var(--obs-color-text); border-color: var(--obs-color-text-muted); }
.btn-outline-primary { border-color: var(--obs-color-primary-text); color: var(--obs-color-primary-text-hover); }
.btn-outline-primary:hover { color: var(--obs-color-primary-text-hover); }
.btn-outline-signal { border-color: var(--obs-color-signal); color: var(--obs-color-signal); }
.btn-outline-signal:hover { color: var(--obs-color-signal); }

/* ---------- Main / sections ---------- */
main {
  width: 100%;
  max-width: var(--obs-page-max);
  margin: 0 auto;
  padding: var(--obs-space-6) var(--obs-gutter) var(--obs-space-8);
  display: flex;
  flex-direction: column;
  gap: var(--obs-space-5);
  flex: 1;
}
main > section, main > article { margin: 0; }

.grid-4 { display: grid; gap: var(--obs-space-4); grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid-3 { display: grid; gap: var(--obs-space-4); grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* ---------- Cards ---------- */
.card {
  background: var(--obs-color-surface);
  border: 1px solid var(--obs-color-border);
  border-radius: var(--obs-radius-lg);
}

.eyebrow {
  font-size: var(--obs-text-xs);
  letter-spacing: var(--obs-tracking-tag);
}
.tone-poc { color: var(--obs-tier-poc-validated); }
.tone-signal { color: var(--obs-color-signal); }
.tone-primary { color: var(--obs-color-primary-text); }
.tone-attempts { color: var(--obs-tier-attempts); }

.section-label {
  font-size: var(--obs-text-sm);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--obs-color-text-secondary);
  font-weight: 600;
  margin: 0;
}

/* ---------- Stat line (catalog orientation) ---------- */
/* One line of label: value pairs under the incident banner, plus the single
   quiet link to the Why page where the signature cards used to sit. It wraps
   on a phone instead of overflowing. */
.stats-line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--obs-space-1) var(--obs-space-4);
  margin: 0;
  font-size: var(--obs-text-xs);
  color: var(--obs-color-text-secondary);
}
.stat-amber { color: var(--obs-tier-attempts); }
.stats-why { margin-left: auto; }

/* ---------- Incident banner: the only sanctioned gradient ---------- */
.incident {
  display: flex;
  flex-wrap: wrap;
  gap: var(--obs-space-4);
  align-items: center;
  border: 1px solid var(--obs-tier-poc-panel-border);
  background: linear-gradient(90deg, #2A1230 0%, var(--obs-color-surface) 60%);
  border-radius: var(--obs-radius-lg);
  padding: var(--obs-space-4) var(--obs-space-5);
  position: relative;
  overflow: hidden;
}
.incident::after {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 2px;
  background: var(--obs-tier-poc-validated);
}
.tag-incident {
  font-size: var(--obs-text-xs);
  letter-spacing: var(--obs-tracking-tag);
  color: var(--obs-tier-poc-validated);
  border: 1px solid var(--obs-tier-poc-validated);
  border-radius: var(--obs-radius-sm);
  padding: var(--obs-space-1) var(--obs-space-2);
}
.incident-main { flex: 1 1 360px; min-width: 0; }
.incident-title { font-weight: 600; font-size: var(--obs-text-lg); }
.incident-sub { font-size: var(--obs-text-base); color: var(--obs-color-text-secondary); margin-top: var(--obs-space-1); }
.incident-actions { display: flex; gap: var(--obs-space-2); flex-wrap: wrap; }

/* Live community pulse on the incident tag. The steady state is a flatline;
   the trace only draws a QRS sweep when a real, newly counted response
   arrives (one sweep per response, driven by data/<CVE>/pulse.json). The
   count is tabular-nums mono so digits do not reflow as it changes. */
.tag-incident { display: inline-flex; align-items: center; gap: var(--obs-space-2); }
.pulse-live { display: inline-flex; align-items: baseline; gap: var(--obs-space-2); }
.pulse-ekg { width: 28px; height: 12px; display: inline-block; flex: 0 0 auto; }
.pulse-flatline, .pulse-qrs {
  fill: none;
  stroke: var(--obs-color-signal);
  stroke-width: 1.5;
  stroke-linecap: round;
}
/* At rest the QRS path is fully dash-offset away: only the flatline shows. */
.pulse-qrs { stroke-dasharray: 100; stroke-dashoffset: 100; }
.pulse-count {
  font-size: var(--obs-text-xs);
  font-weight: 600;
  color: var(--obs-color-signal);
  font-variant-numeric: tabular-nums;
}
.pulse-window { font-size: var(--obs-text-xs); color: var(--obs-color-text-muted); }

/* ---------- Filters ---------- */
.filters { display: flex; flex-wrap: wrap; gap: var(--obs-space-3); align-items: center; }
.field { display: flex; }
.field-grow { flex: 1 1 280px; min-width: 0; }
input[type="search"], select {
  font: inherit;
  color: var(--obs-color-text);
  background: var(--obs-color-surface);
  border: 1px solid var(--obs-color-border);
  border-radius: var(--obs-radius);
  padding: 9px var(--obs-space-3);
  height: 44px;
  width: 100%;
}
input[type="search"]::placeholder { color: var(--obs-color-text-muted); }
select { width: auto; }
.field select { width: 100%; }
.filters .btn { height: 44px; }
.filters-status {
  font-size: var(--obs-text-xs);
  color: var(--obs-color-text-muted);
  /* Tucks the reserved status line into the whitespace around it so an empty
     filter status costs no height above the table. */
  margin: calc(-1 * var(--obs-space-3)) 0 calc(-1 * var(--obs-space-4));
  min-height: 1em;
}

/* ---------- Tables ---------- */
.table-card { overflow: hidden; }
/* position:relative makes this the containing block for the absolutely
   positioned .visually-hidden spans in the cells. Without it they resolve
   against the initial containing block, escape overflow-x and stretch the
   document, so the whole page scrolls sideways on a phone. */
.table-scroll { overflow-x: auto; position: relative; }
table { border-collapse: collapse; width: 100%; }
.data-table { min-width: 1100px; }
.data-table th {
  font-size: var(--obs-text-xs);
  letter-spacing: var(--obs-tracking-label);
  text-transform: uppercase;
  color: var(--obs-color-text-secondary);
  font-weight: 600;
  text-align: left;
  padding: 10px 14px;
  border-bottom: 1px solid var(--obs-color-border);
  white-space: nowrap;
}
.data-table td {
  padding: 14px;
  border-bottom: 1px solid var(--obs-color-border-soft);
  font-size: var(--obs-text-md);
  vertical-align: middle;
}
.data-table tbody tr:hover td { background: var(--obs-color-surface); }
.data-table tbody tr:last-child td { border-bottom: 0; }
.cve-cell a { color: var(--obs-color-text); text-decoration: none; font-weight: 600; }
.cve-cell a:hover { color: var(--obs-color-primary-text-hover); }
.alias-cell { color: var(--obs-color-text-secondary); }
.muted { color: var(--obs-color-text-muted); }
.stale-word { font-size: var(--obs-text-xs); color: var(--obs-color-text-muted); margin-left: var(--obs-space-2); }
.no-sightings { color: var(--obs-color-text-muted); font-size: var(--obs-text-base); }
.fp-cell { min-width: 220px; }
.fp-name { font-size: var(--obs-text-xs); color: var(--obs-color-text-muted); margin: 0 var(--obs-space-2) 0 2px; }
.fp-config { color: var(--obs-color-text-secondary); }
.fp-note { color: var(--obs-color-text-muted); font-size: var(--obs-text-xs); white-space: nowrap; }
tr.row-hidden { display: none; }

/* ---------- Pulse summary ---------- */
.pulse-grid { display: flex; flex-wrap: wrap; gap: var(--obs-space-4); align-items: stretch; }
.pulse-main { flex: 1 1 520px; min-width: 0; padding: 18px 20px; }
.pulse-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--obs-space-3); }
.pulse-meta { font-size: var(--obs-text-xs); color: var(--obs-color-text-muted); }
.pulse-q { font-size: var(--obs-text-sm); color: var(--obs-color-text-secondary); }
.pulse-mean { font-size: 26px; font-weight: 600; margin-top: var(--obs-space-1); color: var(--obs-tier-attempts); font-variant-numeric: tabular-nums; }
.pulse-mean-den { font-size: var(--obs-text-base); color: var(--obs-color-text-muted); font-weight: 400; }
.pulse-bar { display: flex; gap: 3px; margin-top: var(--obs-space-2); height: 8px; }
.pulse-seg { background: var(--obs-color-border); border-radius: var(--obs-radius-sm); flex-basis: 0; }
.pulse-seg.hot-3 { background: var(--obs-tier-attempts-strong); }
.pulse-seg.hot-4 { background: var(--obs-tier-attempts); }
.pulse-seg.hot-5 { background: var(--obs-tier-poc-validated); }
.pulse-sub { font-size: var(--obs-text-xs); color: var(--obs-color-text-muted); margin-top: var(--obs-space-1); }
.pulse-a { font-size: var(--obs-text-lg); font-weight: 600; margin-top: var(--obs-space-1); }
.pulse-a-num { color: var(--obs-tier-poc-validated); }
.pulse-quotes { flex: 1 1 360px; min-width: 0; padding: 18px 20px; display: flex; flex-direction: column; gap: 10px; }
.pulse-quote {
  margin: 0;
  padding: 10px var(--obs-space-3);
  border-left: 2px solid var(--obs-color-signal);
  background: var(--obs-color-bg);
  font-size: var(--obs-text-base);
  line-height: 1.5;
}
.pulse-quote-attr { display: block; margin-top: var(--obs-space-1); font-size: var(--obs-text-xs); color: var(--obs-color-text-muted); }
.pulse-cta { margin-top: auto; font-size: var(--obs-text-base); font-weight: 500; }

/* ---------- Footer ---------- */
.ftr {
  padding: var(--obs-space-5) var(--obs-gutter);
  border-top: 1px solid var(--obs-color-border);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--obs-space-2) var(--obs-space-6);
  font-size: var(--obs-text-sm);
  color: var(--obs-color-text-muted);
}
.ftr-links { margin-left: auto; }

/* ---------- Why page (rendered from docs/WHY.md) ---------- */
.why { max-width: 880px; }
.why h1 { font-size: var(--obs-text-3xl); margin: 0 0 var(--obs-space-4); letter-spacing: -.01em; }
.why h2 {
  font-size: var(--obs-text-xl);
  margin: var(--obs-space-8) 0 var(--obs-space-3);
  padding-top: var(--obs-space-6);
  border-top: 1px solid var(--obs-color-border-soft);
}
.why h3 { font-size: var(--obs-text-lg); margin: var(--obs-space-6) 0 var(--obs-space-2); }
.why p { margin: 0 0 var(--obs-space-4); color: var(--obs-color-text-secondary); line-height: 1.65; font-size: var(--obs-text-lg); }
.why p strong, .why li strong { color: var(--obs-color-text); }
.why ul, .why ol { margin: 0 0 var(--obs-space-4); padding-left: var(--obs-space-6); color: var(--obs-color-text-secondary); line-height: 1.65; font-size: var(--obs-text-lg); }
.why li { margin-bottom: var(--obs-space-2); }
.why li:last-child { margin-bottom: 0; }
/* Reading measure: about 70 characters. Tables and code keep the full column. */
.why p, .why ul, .why ol, .why h2, .why h3 { max-width: 66ch; }
.why .docs-toc ul { max-width: none; font-size: var(--obs-text-md); }
.why h1 + p { line-height: 1.65; color: var(--obs-color-text); margin-bottom: var(--obs-space-6); }
.why li::marker { color: var(--obs-color-signal); }
.why hr { border: 0; border-top: 1px solid var(--obs-color-border-soft); margin: var(--obs-space-8) 0; }
.why code {
  font-family: var(--obs-font-mono);
  font-size: .92em;
  background: var(--obs-color-surface-2);
  padding: 1px 5px;
  border-radius: var(--obs-radius-sm);
}
.why pre.md-code {
  font-family: var(--obs-font-mono);
  font-size: var(--obs-text-sm);
  background: var(--obs-color-surface-2);
  border: 1px solid var(--obs-color-border);
  border-radius: var(--obs-radius-lg);
  padding: var(--obs-space-3) var(--obs-space-4);
  overflow-x: auto;
  margin: 0 0 var(--obs-space-4);
}
.why pre.md-code code { background: none; padding: 0; }
.why .table-scroll { margin: 0 0 var(--obs-space-6); border: 1px solid var(--obs-color-border); border-radius: var(--obs-radius-lg); }
.why table { min-width: 760px; }
.why .md-table th {
  font-size: var(--obs-text-xs);
  letter-spacing: var(--obs-tracking-label);
  text-transform: uppercase;
  color: var(--obs-color-text-secondary);
  text-align: left;
  padding: 10px 14px;
  border-bottom: 1px solid var(--obs-color-border);
}
.why .md-table td, .why .md-table th[scope="row"] {
  padding: var(--obs-space-3) 14px;
  border-bottom: 1px solid var(--obs-color-border-soft);
  font-size: var(--obs-text-base);
  vertical-align: top;
  line-height: 1.55;
}
.why .md-table tbody tr:last-child th, .why .md-table tbody tr:last-child td { border-bottom: 0; }
.why .md-rowhead { color: var(--obs-color-text); font-weight: 600; text-align: left; min-width: 180px; }

/* ---------- Mermaid figure (shared with screens 02/03) ---------- */
.mermaid-figure {
  margin: 0;
  padding: var(--obs-space-4);
  border-radius: var(--obs-radius);
  background: var(--obs-color-bg);
  border: 1px solid var(--obs-color-border);
}
.mermaid-figure figcaption {
  font-size: var(--obs-text-sm);
  color: var(--obs-color-text-secondary);
  margin-bottom: var(--obs-space-3);
}
.mermaid-src { color: var(--obs-color-signal); }
.mermaid-host .mermaid-fallback { font-size: var(--obs-text-sm); color: var(--obs-color-text-muted); }
/* Enlarged nodes must never be clipped at the diagram's edge: the host and
   the SVG both let the scaled node paint past the original viewport. */
.mermaid-host, .mermaid-figure { overflow: visible; }
.mermaid-host svg, .timeline-chart svg { overflow: visible; }
/* Diagram node hover/focus feedback. Mermaid positions each node with a
   transform="translate(x,y)" attribute on the outer <g>, which any CSS
   transform would override and collapse the diagram; the scale lives on an
   inner group instead, growing from its own middle. The scale itself is
   applied by assets/node-hover.mjs through the motion helper, so
   prefers-reduced-motion drops it entirely; the stroke bump stays, is
   instant, and carries the same signal without movement. */
.obs-node-inner { transform-box: fill-box; transform-origin: center; }
.mermaid-host svg g.node:focus { outline: none; }
.mermaid-host svg g.node:focus-visible { outline: 2px solid var(--obs-color-signal); outline-offset: 2px; border-radius: var(--obs-radius-sm); }
.mermaid-host svg g.node:hover .obs-node-inner rect, .mermaid-host svg g.node:hover .obs-node-inner polygon,
.mermaid-host svg g.node:hover .obs-node-inner circle, .mermaid-host svg g.node:hover .obs-node-inner ellipse,
.mermaid-host svg g.node:focus .obs-node-inner rect, .mermaid-host svg g.node:focus .obs-node-inner polygon,
.mermaid-host svg g.node:focus .obs-node-inner circle, .mermaid-host svg g.node:focus .obs-node-inner ellipse {
  /* Mermaid injects #id-scoped rules inside the SVG; !important is the only
     way to win, same as the g-path rules above. :focus (not only
     :focus-visible) so the instant stroke feedback always reaches keyboard
     users; the enlarged outline itself is scoped to :focus-visible. */
  stroke-width: 2.5px !important;
}
/* Sighting timeline markers: same treatment, scaled element is the marker
   group itself (markers carry no positioning transform). */
.timeline-chart .tl-marker { transform-box: fill-box; transform-origin: center; cursor: pointer; }
.timeline-chart .tl-marker:focus { outline: none; }
.timeline-chart .tl-marker:focus-visible { outline: 2px solid var(--obs-color-signal); outline-offset: 2px; border-radius: var(--obs-radius-sm); }
.timeline-chart .tl-marker:hover .tl-marker-shape, .timeline-chart .tl-marker:focus .tl-marker-shape, .timeline-chart .tl-marker:focus-visible .tl-marker-shape {
  stroke: var(--obs-color-text);
  stroke-width: 1.5px;
}
/* Edge labels sit on the background surface so they are not drawn directly
   on top of an edge line. Mermaid 11 renders them as a foreignObject div and
   injects a per-diagram #id .labelBkg rule (ID specificity) inside the SVG,
   so an ordinary class selector loses; !important is required to win. */
.mermaid-host svg .labelBkg {
  background-color: var(--obs-color-bg) !important;
  border-radius: var(--obs-radius-sm);
  padding: 0 3px;
  opacity: 1;
}

/* ---------- Radio tiles (shared with screens 02/03) ---------- */
.radio-tile {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px var(--obs-space-3);
  border: 1px solid var(--obs-color-border);
  border-radius: var(--obs-radius);
  background: var(--obs-color-bg);
  min-height: var(--obs-touch-min);
  font-size: var(--obs-text-base);
  cursor: pointer;
}
.radio-tile:has(:checked) {
  border-color: var(--obs-color-signal);
  background: var(--obs-signal-bg);
}
.radio-tile input[type="radio"] { width: 18px; height: 18px; margin: 0; accent-color: var(--obs-color-signal); }
.radio-sub { color: var(--obs-color-text-muted); font-size: var(--obs-text-sm); }

.export-row { display: flex; flex-wrap: wrap; gap: var(--obs-space-2); }

/* ---------- Character (illustration + alt text only) ---------- */
/* Fills the title column, which otherwise runs empty beside the taller tier
   card. max-height keeps it from outgrowing that column on a wide viewport and
   turning the illustration into the loudest thing on a page about evidence. */
.character-hero { margin-top: var(--obs-space-4); }
.character-hero img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 340px;
  object-fit: cover;
  object-position: center;
  border-radius: var(--obs-radius-lg);
  border: 1px solid var(--obs-color-border);
}
.row-character { width: 28px; height: 28px; border-radius: var(--obs-radius-sm); vertical-align: middle; margin-right: var(--obs-space-2); border: 1px solid var(--obs-color-border); }

/* ---------- IOC feeds page ---------- */
/* .card supplies chrome only, never padding, because the table cards need their
   tables flush to the edge. Every other card pairs it with a class that pads;
   this one was missing its pair and the text sat against the border. */
.ioc-feeds-lead { padding: 18px 20px; }
.ioc-feeds-lead p { margin: 0; color: var(--obs-color-text-secondary); }
.ioc-feeds-lead p + p { margin-top: var(--obs-space-2); }

.single-source { font-size: var(--obs-text-xs); color: var(--obs-color-text-muted); }
.checkbox-field { display: flex; align-items: center; gap: var(--obs-space-2); height: 44px; color: var(--obs-color-text-secondary); }
.entry-export-links { list-style: none; margin: 0; padding: 0; columns: 2; column-gap: var(--obs-space-6); }
.entry-export-links li { margin-bottom: var(--obs-space-2); break-inside: avoid; }

/* ---------- Reveal motion (disabled under reduced motion) ---------- */
@keyframes obs-reveal { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes obs-pulse { 0% { box-shadow: 0 0 0 0 rgba(62, 232, 216, .5); } 100% { box-shadow: 0 0 0 10px rgba(62, 232, 216, 0); } }
@keyframes obs-sweep { from { transform: translateX(-100%); } to { transform: translateX(220%); } }

[data-reveal] { opacity: 0; }
[data-reveal].is-revealed { animation: obs-reveal .28s ease-out both; }
.incident.is-revealed::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 45%;
  background: linear-gradient(90deg, transparent, rgba(62, 232, 216, .07), transparent);
  animation: obs-sweep .9s ease-out 1 both;
  pointer-events: none;
}
.live-dot.is-live { animation: obs-pulse 1.6s ease-out 1 both; }

@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1; }
  [data-reveal].is-revealed, .incident.is-revealed::before, .live-dot.is-live {
    animation: none;
  }
  .incident.is-revealed::before { display: none; }
  *, *::before, *::after { scroll-behavior: auto; }
}

/* ---------- Responsive ---------- */
@media (min-width: 721px) and (max-width: 1024px) {
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 720px) {
  .hdr { padding: var(--obs-space-2) var(--obs-gutter-mobile) 0; gap: 0 var(--obs-space-3); }
  /* Brand block left, call to action right, nav on its own row below. The
     byline drops under the wordmark so the two never compete for width. */
  .hdr-side { margin-left: auto; width: auto; }
  .live-chip { display: none; }
  .btn-sighting { padding: 0 var(--obs-space-3); font-size: var(--obs-text-base); }
  .nav { order: 3; width: 100%; flex-basis: 100%; margin-inline: calc(-1 * var(--obs-gutter-mobile)); padding-inline: var(--obs-gutter-mobile); scroll-padding-inline: var(--obs-gutter-mobile);
    /* Fade the clipped edge so a cut-off link reads as scrollable. */
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - var(--obs-gutter-mobile)), transparent);
    mask-image: linear-gradient(90deg, #000 calc(100% - var(--obs-gutter-mobile)), transparent); }
  main { padding: var(--obs-space-4) var(--obs-gutter-mobile) var(--obs-space-6); }
  .grid-4, .grid-3 { grid-template-columns: 1fr; }
  .ftr { padding: var(--obs-space-4) var(--obs-gutter-mobile); }
  .ftr-links { margin-left: 0; }

  /* Comparison table reflows into stacked cards at phone width. */
  .why .table-scroll { border: 0; overflow: visible; }
  .why table, .why .md-table thead, .why .md-table tbody, .why .md-table tr, .why .md-table td { display: block; min-width: 0; width: 100%; }
  .why .md-table thead { position: absolute; left: -9999px; }
  .why .md-table tr {
    border: 1px solid var(--obs-color-border);
    border-radius: var(--obs-radius-lg);
    background: var(--obs-color-surface);
    margin-bottom: var(--obs-space-3);
    padding: var(--obs-space-3) var(--obs-space-4);
  }
  .why .md-table th[scope="row"] {
    display: block;
    border-bottom: 1px solid var(--obs-color-border-soft);
    padding: 0 0 var(--obs-space-2);
    margin-bottom: var(--obs-space-2);
    min-width: 0;
  }
  .why .md-table td { border-bottom: 0; padding: var(--obs-space-2) 0; }
  .why .md-table td + td { border-top: 1px solid var(--obs-color-border-soft); }
  .why .md-table td::before {
    content: attr(data-label);
    display: block;
    font-size: var(--obs-text-xs);
    letter-spacing: var(--obs-tracking-label);
    text-transform: uppercase;
    color: var(--obs-color-text-secondary);
    margin-bottom: var(--obs-space-1);
  }
}

/* ---------- Shared bits for screens 02-04 ---------- */
.h2-like {
  font-size: var(--obs-text-sm);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--obs-color-text-secondary);
  font-weight: 600;
  margin: 0;
}
.card-head {
  padding: var(--obs-space-4) 20px;
  border-bottom: 1px solid var(--obs-color-border);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--obs-space-3);
}
.crumbs { font-size: var(--obs-text-md); color: var(--obs-color-text-muted); }
.crumbs a { color: var(--obs-color-text-muted); text-decoration: none; }
.crumbs a:hover { color: var(--obs-color-text); }
.chip-static {
  font-size: var(--obs-text-xs);
  padding: 3px var(--obs-space-2);
  border-radius: var(--obs-radius-sm);
  background: var(--obs-color-surface-2);
  color: var(--obs-color-text-secondary);
  display: inline-block;
}
.mono[data-tier], .data-table td > .mono[data-tier] { font-weight: 600; }
.mono[data-tier="none"] { color: var(--obs-tier-none-text); }
.mono[data-tier="scanning"] { color: var(--obs-tier-scanning); }
.mono[data-tier="attempts"] { color: var(--obs-tier-attempts); }
.mono[data-tier="poc-validated"] { color: var(--obs-tier-poc-validated); }
.mono[data-tier="confirmed"] { color: var(--obs-tier-confirmed); }

.eyebrow-signal { color: var(--obs-color-signal); }
.field-labeled { display: flex; flex-direction: column; gap: 6px; }
.field-labeled > label { font-size: var(--obs-text-sm); color: var(--obs-color-text-secondary); }
.field-labeled textarea {
  font: inherit;
  color: var(--obs-color-text);
  background: var(--obs-color-bg);
  border: 1px solid var(--obs-color-border);
  border-radius: var(--obs-radius);
  padding: 10px var(--obs-space-3);
  width: 100%;
  resize: vertical;
}
.field-labeled textarea::placeholder { color: var(--obs-color-text-muted); }
.split-row { display: flex; flex-wrap: wrap; gap: var(--obs-space-5); align-items: flex-start; }
.split-row > section { min-width: 0; }
.btn-disabled, .btn-disabled:hover {
  background: var(--obs-color-surface-2);
  border-color: var(--obs-color-border);
  color: var(--obs-color-text-muted);
  cursor: not-allowed;
}
.btn-disabled-reason { font-size: var(--obs-text-xs); margin-left: var(--obs-space-1); }
.btn[disabled] { cursor: not-allowed; }

/* ---------- Screen 02: Entry ---------- */
.entry-head { display: flex; flex-direction: column; gap: var(--obs-space-3); }
.entry-head-row { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--obs-space-5); }
.entry-head-main { flex: 1 1 480px; min-width: 0; }
.entry-h1 { margin: 0; font-size: var(--obs-text-3xl); font-weight: 600; letter-spacing: -.01em; overflow-wrap: anywhere; }
.entry-sub { margin-top: var(--obs-space-2); font-size: var(--obs-text-lg); color: var(--obs-color-text-secondary); }
.entry-chips { margin-top: var(--obs-space-3); display: flex; flex-wrap: wrap; gap: var(--obs-space-2); }

.tier-card { flex: 0 1 380px; min-width: 300px; padding: var(--obs-space-5); border-color: var(--obs-tier-poc-panel-border); box-shadow: var(--obs-glow-tier-poc); }
.tier-card-top { display: flex; align-items: baseline; gap: var(--obs-space-3); margin-top: var(--obs-space-2); }
.tier-word { font-size: var(--obs-text-2xl); font-weight: 600; color: var(--obs-tier-poc-validated); }
.tier-word[data-tier="none"] { color: var(--obs-tier-none-text); }
.tier-word[data-tier="scanning"] { color: var(--obs-tier-scanning); }
.tier-word[data-tier="attempts"] { color: var(--obs-tier-attempts); }
.tier-word[data-tier="confirmed"] { color: var(--obs-tier-confirmed); }
.tier-rank { font-size: var(--obs-text-sm); color: var(--obs-color-text-secondary); }
.tier-card-counts { margin-top: var(--obs-space-2); font-size: var(--obs-text-base); color: var(--obs-color-text-secondary); }
.tier-card-chips { margin-top: var(--obs-space-3); display: flex; gap: var(--obs-space-2); }
.state-chip { font-size: var(--obs-text-xs); padding: 3px var(--obs-space-2); border-radius: var(--obs-radius-sm); border: 1px solid var(--obs-color-border); color: var(--obs-color-text-secondary); }
.tier-card-why { margin-top: var(--obs-space-3); padding-top: var(--obs-space-3); border-top: 1px solid var(--obs-color-border); }
.tier-why-list { margin: var(--obs-space-2) 0 0; padding-left: var(--obs-space-5); font-size: var(--obs-text-sm); line-height: 1.6; color: var(--obs-color-text-secondary); }
.tier-why-list b { color: var(--obs-tier-attempts); font-weight: 600; }

.tier-scale { padding: var(--obs-space-4) var(--obs-space-5); display: grid; gap: var(--obs-space-2); grid-template-columns: repeat(5, minmax(0, 1fr)); }
.tier-step { padding: var(--obs-space-3); border-radius: var(--obs-radius); background: var(--obs-color-bg); border: 1px solid var(--obs-color-border); }
.tier-step-name { font-size: var(--obs-text-sm); color: var(--obs-color-text-secondary); }
.tier-step[data-tier-step="none"] .tier-step-name { color: var(--obs-tier-none-text); }
.tier-step[data-tier-step="scanning"] .tier-step-name { color: var(--obs-tier-scanning); }
.tier-step[data-tier-step="attempts"] .tier-step-name { color: var(--obs-tier-attempts); }
.tier-step[data-tier-step="poc-validated"] .tier-step-name { color: var(--obs-tier-poc-validated); }
.tier-step[data-tier-step="confirmed"] .tier-step-name { color: var(--obs-tier-confirmed); }
.tier-step-desc { font-size: var(--obs-text-sm); color: var(--obs-color-text-muted); margin-top: var(--obs-space-1); }
.tier-step.is-now { background: var(--obs-tier-poc-active-bg); border-color: var(--obs-tier-poc-border); }
.tier-step.is-now .tier-step-name { font-weight: 600; }
.tier-step.is-now .tier-step-desc { color: var(--obs-color-primary-text-hover); }

.fp-card { flex: 3 1 560px; }
.fp-card .data-table { min-width: 560px; }
.fp-card .data-table th, .fp-card .data-table td { padding-left: var(--obs-space-3); padding-right: var(--obs-space-3); }
.fp-card .data-table th { white-space: normal; vertical-align: bottom; }
.fp-card .data-table td { font-size: var(--obs-text-base); }
.means-panel { flex: 1 1 360px; padding: var(--obs-space-5); border-color: var(--obs-signal-panel-border); }
.h2-signal { color: var(--obs-color-signal); }
.means-form { margin-top: var(--obs-space-3); }
.means-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--obs-space-3); }
.means-form .btn { margin-top: var(--obs-space-4); width: 100%; }
.means-result { margin-top: var(--obs-space-4); padding: var(--obs-space-4); border-radius: var(--obs-radius); background: var(--obs-color-bg); border: 1px solid var(--obs-signal-panel-border); }
.means-result-body { margin-top: var(--obs-space-2); font-size: var(--obs-text-md); line-height: 1.5; }
.means-result-body p { margin: 0; }
.means-actions { margin-top: var(--obs-space-3); display: flex; gap: var(--obs-space-2); flex-wrap: wrap; }

.pulse-section { overflow: hidden; }
.pulse-section-head { padding: var(--obs-space-4) var(--obs-space-5); border-bottom: 1px solid var(--obs-color-border); display: flex; flex-wrap: wrap; align-items: center; gap: var(--obs-space-3); }
.pulse-section-sub { font-size: var(--obs-text-md); color: var(--obs-color-text-secondary); }
.pulse-section-head .pulse-meta { margin-left: auto; }
.pulse-split { display: flex; flex-wrap: wrap; }
.pulse-form { flex: 1 1 440px; min-width: 0; padding: var(--obs-space-5); display: flex; flex-direction: column; gap: var(--obs-space-5); border-right: 1px solid var(--obs-color-border); }
.pulse-fieldset { border: 0; margin: 0; padding: 0; }
.pulse-fieldset legend { font-size: var(--obs-text-md); font-weight: 600; margin-bottom: var(--obs-space-3); }
.pulse-qnum, .g-num { color: var(--obs-color-signal); margin-right: var(--obs-space-2); font-weight: 600; }
.pulse-difficulty { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--obs-space-2); }
.radio-tile-col { flex-direction: column; gap: 4px; padding: 10px 6px; text-align: center; }
.radio-num { font-size: var(--obs-text-md); }
.radio-tile:has(:checked) .radio-sub { color: var(--obs-color-text-secondary); }
.pulse-options { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--obs-space-2); }
.pulse-options-flow { display: flex; flex-wrap: wrap; }
.pulse-options-flow .radio-tile { flex: 1 1 auto; }
.opt-note { font-weight: 400; color: var(--obs-color-text-muted); font-size: var(--obs-text-sm); }
.pulse-submit-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--obs-space-3); }
.pulse-privacy { flex: 1 1 260px; font-size: var(--obs-text-sm); color: var(--obs-color-text-muted); margin: 0; line-height: 1.5; }
.pulse-status { min-height: 1em; font-size: var(--obs-text-sm); color: var(--obs-color-signal); margin: 0; }
.pulse-status.is-error { color: var(--obs-tier-attempts); }
.pulse-readout { flex: 1 1 360px; min-width: 0; padding: var(--obs-space-5); display: flex; flex-direction: column; gap: var(--obs-space-5); background: var(--obs-color-surface-3); }
.pulse-readout-head { display: flex; justify-content: space-between; align-items: baseline; font-size: var(--obs-text-sm); color: var(--obs-color-text-secondary); }
.pulse-bars { display: flex; flex-direction: column; gap: var(--obs-space-2); margin-top: var(--obs-space-2); }
.pulse-bar-row { display: grid; grid-template-columns: 7rem 1fr 3rem; gap: var(--obs-space-2); align-items: center; font-size: var(--obs-text-sm); }
.pulse-bar-label { color: var(--obs-color-text-muted); }
.pulse-track { height: 10px; background: var(--obs-color-border); border-radius: var(--obs-radius-sm); overflow: hidden; display: block; }
.pulse-fill { display: block; height: 100%; }
.pulse-fill[data-tier="none"] { background: var(--obs-color-text-muted); }
.pulse-fill[data-tier="attempts"] { background: var(--obs-tier-attempts); }
.pulse-fill[data-tier="poc-validated"] { background: var(--obs-tier-poc-validated); }
.pulse-bar-pct { text-align: right;  font-variant-numeric: tabular-nums; }
/* Standalone display figure: proportional digits. The shared .pulse-mean sets tabular-nums for the catalog hero. */
.pulse-readout-head .pulse-mean { font-size: var(--obs-text-2xl); font-variant-numeric: normal; margin-top: 0; }
.pulse-readout-cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--obs-space-4); }
.pulse-stat-list { margin-top: var(--obs-space-2); font-size: var(--obs-text-base); line-height: 1.8; }
.pulse-stat-n { color: var(--obs-color-text-secondary); }
.pulse-stat-hot { color: var(--obs-tier-poc-validated); }
.pulse-stat-cool { color: var(--obs-color-signal); }
.pulse-reviewed-note { color: var(--obs-color-text-muted); font-size: var(--obs-text-xs); text-transform: none; letter-spacing: 0; }
.pulse-readout-note { font-size: var(--obs-text-sm); color: var(--obs-color-text-muted); margin: var(--obs-space-2) 0 0; line-height: 1.5; }

.explainer-section { padding: var(--obs-space-5); }
.explainer-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--obs-space-3); }
.audience-toggle { margin-left: auto; display: flex; flex-wrap: wrap; border: 1px solid var(--obs-color-border); border-radius: var(--obs-radius); overflow: hidden; }
.audience-btn { padding: 8px 14px; border: 0; background: var(--obs-color-surface); color: var(--obs-color-text-secondary); font: inherit; font-size: var(--obs-text-md); cursor: pointer; min-height: var(--obs-touch-min); }
.audience-btn:hover { color: var(--obs-color-text); }
.audience-btn[aria-pressed="true"] { background: var(--obs-color-primary); color: #fff; font-weight: 600; }
.audience-btn[disabled] { color: var(--obs-color-text-muted); cursor: not-allowed; }
.audience-reason { font-size: var(--obs-text-xs); }
.explainer-split { display: flex; flex-wrap: wrap; gap: var(--obs-space-6); margin-top: var(--obs-space-4); }
.explainer-text { flex: 1 1 420px; min-width: 0; }
.explainer-text p { margin: 0; max-width: 60ch; font-size: var(--obs-text-lg); line-height: 1.6; }
.explainer-text .explainer-cites { margin-top: var(--obs-space-3); font-size: var(--obs-text-sm); color: var(--obs-color-text-muted); }
.explainer-split .mermaid-figure { flex: 1 1 420px; }

.timeline-section { flex: 1 1 100%; padding: var(--obs-space-5); }
.timeline-head { display: flex; align-items: center; gap: var(--obs-space-3); flex-wrap: wrap; }
.timeline-chart { margin-top: var(--obs-space-4); overflow-x: auto; }
.tl-tick { fill: var(--obs-color-text-muted); font-size: 10px; font-family: var(--obs-font-mono); }
.tl-label { font-size: 11px; fill: var(--obs-color-text); font-family: var(--obs-font-sans); }
.tl-label-title { font-weight: 600; }
.tl-tier { font-family: var(--obs-font-mono); font-weight: 600; }
.tl-date { fill: var(--obs-color-text-secondary); font-size: 10px; font-family: var(--obs-font-mono); }

.ioc-section { flex: 1 1 100%; padding: var(--obs-space-5); }
.ioc-head { margin-bottom: var(--obs-space-4); }
.ioc-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--obs-space-3); }
.curl-snippet { margin: var(--obs-space-3) 0 0; padding: var(--obs-space-3); border-radius: var(--obs-radius); background: var(--obs-color-bg); border: 1px solid var(--obs-color-border); font-size: var(--obs-text-sm); color: var(--obs-color-text-secondary); overflow-x: auto; white-space: nowrap; }
.ioc-table { min-width: 560px; margin-top: var(--obs-space-4); }
.ioc-type { color: var(--obs-color-text-secondary); }
.ioc-table { min-width: 880px; }
.ioc-value { overflow-wrap: anywhere; min-width: 240px; }
.ioc-expires { color: var(--obs-color-text-muted); }
.conf-low { color: var(--obs-color-text-muted); }
.conf-medium { color: var(--obs-conf-medium); }
.conf-high { color: var(--obs-conf-high); }

.grading-log { overflow: hidden; }
.grading-log-head { padding: var(--obs-space-4) var(--obs-space-5); border-bottom: 1px solid var(--obs-color-border); display: flex; align-items: center; gap: var(--obs-space-3); flex-wrap: wrap; }
.grading-log-head .pulse-meta { color: var(--obs-color-text-muted); }
.grading-table { min-width: 880px; }
.fp-card .data-table th:first-child, .fp-card .data-table td:first-child,
.grading-table th:first-child, .grading-table td:first-child { padding-left: var(--obs-space-5); }
.fp-card .data-table th:last-child, .fp-card .data-table td:last-child,
.grading-table th:last-child, .grading-table td:last-child { padding-right: var(--obs-space-5); }
.ioc-table th:first-child, .ioc-table td:first-child { padding-left: 0; }
.ioc-table th:last-child, .ioc-table td:last-child { padding-right: 0; }
/* Counts line up on the right with tabular figures; IDs and dates stay left. */
.fp-card .data-table th:nth-child(5), .fp-card .data-table td:nth-child(5),
.ioc-table th:nth-child(4), .ioc-table td:nth-child(4) { text-align: right; font-variant-numeric: tabular-nums; }
.log-when, .ioc-expires { font-variant-numeric: tabular-nums; }
.grading-table td:nth-child(4) { white-space: nowrap; }
.fp-card .obs-tier { white-space: nowrap; }
.log-when { color: var(--obs-color-text-secondary); white-space: nowrap; }
.log-claimed { color: var(--obs-color-text-muted); font-size: var(--obs-text-xs); }
.log-rationale { color: var(--obs-color-text-secondary); }
.log-recusal { display: block; color: var(--obs-color-text-muted); font-size: var(--obs-text-xs); }

/* ---------- Screen 03: Guidance ---------- */
.g-h1 { margin: 8px 0 0; font-size: var(--obs-text-2xl); font-weight: 600; letter-spacing: -.01em; }
.g-lede { margin: 8px 0 0; font-size: var(--obs-text-lg); color: var(--obs-color-text-secondary); max-width: 760px; line-height: 1.5; }
.guidance-split { display: flex; flex-wrap: wrap; gap: var(--obs-space-5); align-items: flex-start; }
.guidance-wizard { flex: 1 1 380px; min-width: 0; padding: 20px; display: flex; flex-direction: column; gap: 20px; }
#guidance-form { display: flex; flex-direction: column; gap: var(--obs-space-6); }
.g-fieldset { border: 0; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.g-fieldset legend { font-size: var(--obs-text-md); font-weight: 600; margin-bottom: 6px; }
.g-options { display: flex; flex-direction: column; gap: 8px; }
.g-options-2col { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.g-downtime { margin-top: var(--obs-space-2); }
.g-submit { width: 100%; }
.g-note { font-size: var(--obs-text-sm); color: var(--obs-color-text-muted); margin: 0; line-height: 1.5; }
.guidance-result { flex: 1 1 520px; min-width: 0; overflow: hidden; }
.guidance-result-head { padding: var(--obs-space-4) 20px; border-bottom: 1px solid var(--obs-color-border); background: var(--obs-color-surface-2); display: flex; flex-wrap: wrap; align-items: center; gap: var(--obs-space-3); }
.your-branch-tag { font-size: var(--obs-text-xs); letter-spacing: var(--obs-tracking-tag); color: var(--obs-tier-poc-validated); border: 1px solid var(--obs-tier-poc-validated); border-radius: var(--obs-radius-sm); padding: 3px var(--obs-space-2); }
#your-branch-summary { font-size: var(--obs-text-md); color: var(--obs-color-text-secondary); }
.guidance-output { padding: 20px; display: flex; flex-direction: column; gap: 20px; }
.g-placeholder { color: var(--obs-color-text-muted); margin: 0; }
.g-verdict { font-size: var(--obs-text-xl); font-weight: 600; line-height: 1.3; }
.g-options-list { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 10px; }
.g-option { display: grid; grid-template-columns: 28px 1fr; gap: var(--obs-space-3); padding: 14px; border: 1px solid var(--obs-color-border); border-radius: var(--obs-radius); background: var(--obs-color-bg); }
.g-option-hot { border-color: var(--obs-tier-poc-border); background: var(--obs-tier-poc-wash); }
.g-option-letter { color: var(--obs-color-signal); font-weight: 600; }
.g-option-letter[data-tier="poc-validated"] { color: var(--obs-tier-poc-validated); }
.g-option-title { font-weight: 600; font-size: var(--obs-text-md); }
.g-option-trade { font-size: var(--obs-text-base); color: var(--obs-color-text-secondary); margin-top: 4px; line-height: 1.5; }
.g-option-prov { font-size: var(--obs-text-xs); color: var(--obs-color-text-muted); margin-top: 6px; }
.g-option-link { display: inline-block; margin-top: 8px; font-size: var(--obs-text-base); font-weight: 500; }
.g-migrate { padding: 14px; border-radius: var(--obs-radius); border: 1px solid var(--obs-color-border); background: var(--obs-color-bg); }
.g-migrate p { margin: 8px 0 0; font-size: var(--obs-text-base); color: var(--obs-color-text-secondary); line-height: 1.5; }
#guidance-tree-host-wrap { padding: 0 20px 20px; }

/* Mermaid node-kind and path highlighting. The .mmd classDefs give decision
   nodes a deeper surface than action/leaf nodes; the visitor's route (g-path)
   and terminal (g-terminal) are the only places the signal/tier colours
   appear. Both hosts are scoped explicitly so these override Mermaid's
   #id .<class> { ... !important } rules inside the rendered SVG. */
#guidance-tree-host-wrap .mermaid-host svg .g-path rect, #guidance-tree-host-wrap .mermaid-host svg .g-path polygon,
#exposure-host-wrap .mermaid-host svg .g-path rect, #exposure-host-wrap .mermaid-host svg .g-path polygon {
  stroke: var(--obs-color-signal) !important;
  stroke-width: 2.5px !important;
}
#guidance-tree-host-wrap .mermaid-host svg .g-terminal rect, #guidance-tree-host-wrap .mermaid-host svg .g-terminal polygon,
#exposure-host-wrap .mermaid-host svg .g-terminal rect, #exposure-host-wrap .mermaid-host svg .g-terminal polygon {
  stroke: var(--obs-tier-poc-validated) !important;
  stroke-width: 3px !important;
}
.mermaid-host svg .g-you-are-here {
  fill: var(--obs-tier-poc-validated);
  font-family: var(--obs-font-mono);
  font-size: 11px;
  font-weight: 600;
}

/* ---------- Responsive: screens 02-04 ---------- */
@media (min-width: 721px) and (max-width: 1024px) {
  .tier-scale { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 720px) {
  .entry-head-row { flex-direction: column; }
  .tier-card { min-width: 0; width: 100%; flex: 1 1 auto; }
  .tier-scale { grid-template-columns: 1fr; }
  .pulse-form { border-right: 0; border-bottom: 1px solid var(--obs-color-border); }
  .pulse-difficulty { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 4px; }
  .radio-tile-col { padding: 8px 2px; }
  .pulse-options { grid-template-columns: 1fr; }
  .pulse-readout-cols { grid-template-columns: 1fr; }
  .means-grid { grid-template-columns: 1fr; }
  .audience-toggle { margin-left: 0; }
  .g-options-2col { grid-template-columns: 1fr 1fr; }
  .g-h1 { font-size: 24px; }
  .timeline-chart { overflow-x: auto; }
}

/* Candidate list in the "what this means for you" result */
.means-candidates-label { margin: var(--obs-space-3) 0 var(--obs-space-1); font-size: var(--obs-text-sm); color: var(--obs-color-text-secondary); }
.means-candidates { margin: 0; padding-left: var(--obs-space-5); font-size: var(--obs-text-md); line-height: 1.7; }
.means-flags { color: var(--obs-color-text-secondary); }
.means-note { color: var(--obs-color-text-muted); font-size: var(--obs-text-xs); }

/* ======================================================================
   Branding block: sponsor byline, legal footer, consent dialog, feedback.
   Appended as one block so it merges cleanly with other work on this file.
   ====================================================================== */
.lockup { display: flex; align-items: center; gap: var(--obs-space-3); }
.byline { font-size: var(--obs-text-xs); line-height: 1; padding-top: var(--obs-space-1); }
@media (max-width: 720px) {
  .lockup { flex-direction: column; align-items: flex-start; gap: 0; flex: 1 1 auto; }
  .brand { min-height: var(--obs-space-8); }
  .byline { padding: 0 0 0 calc(22px + var(--obs-space-3)); }
}
.byline a, .ftr-legal a, .ftr a {
  color: var(--obs-color-text-secondary);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  min-height: 24px;
}
.byline a:hover, .ftr-legal a:hover, .ftr a:hover { color: var(--obs-color-text); text-decoration: underline; }
.ext { margin-left: 2px; font-size: .9em; }
.ftr-legal { flex-basis: 100%; padding-top: var(--obs-space-3); border-top: 1px solid var(--obs-color-border-soft); }
.ftr-legal ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--obs-space-1) var(--obs-space-6); }
.ftr-btn {
  font: inherit;
  color: var(--obs-color-text-secondary);
  background: none;
  border: 0;
  padding: 0;
  min-height: 24px;
  cursor: pointer;
  text-decoration: underline;
}
.ftr-btn:hover { color: var(--obs-color-text); }

dialog.consent, dialog.fb {
  background: var(--obs-color-surface);
  color: var(--obs-color-text);
  border: 1px solid var(--obs-color-border);
  border-radius: var(--obs-radius-lg);
  padding: var(--obs-space-5);
  max-width: min(480px, calc(100vw - 2 * var(--obs-gutter-mobile)));
  max-height: calc(100vh - 2 * var(--obs-gutter-mobile));
  overflow-y: auto;
  box-shadow: var(--obs-glow-signal);
}
dialog.consent::backdrop, dialog.fb::backdrop { background: rgba(15, 14, 23, .72); }
dialog.consent h2, dialog.fb h2 { margin: 0 0 var(--obs-space-3); font-size: var(--obs-text-xl); }
dialog.consent h2:focus, dialog.fb h2:focus { outline: none; }
dialog.consent p { margin: 0 0 var(--obs-space-4); font-size: var(--obs-text-md); line-height: 1.6; color: var(--obs-color-text-secondary); }
dialog.consent p a { color: var(--obs-color-primary-text); }
.consent-actions, .fb-actions { display: flex; gap: var(--obs-space-3); flex-wrap: wrap; }
.consent-btn { flex: 1 1 140px; }

.fb-fab {
  position: fixed;
  right: var(--obs-space-4);
  bottom: var(--obs-space-4);
  z-index: 50;
  min-height: var(--obs-touch-min);
  padding: 0 var(--obs-space-4);
  font: inherit;
  font-size: var(--obs-text-md);
  font-weight: 500;
  color: var(--obs-color-text);
  background: var(--obs-color-surface-2);
  border: 1px solid var(--obs-color-primary-text);
  border-radius: var(--obs-radius);
  cursor: pointer;
}
.fb-fab:hover { border-color: var(--obs-color-signal); }
.fb-form { display: grid; gap: var(--obs-space-2); min-width: min(380px, 100%); }
.fb-form label, .fb-form legend { font-size: var(--obs-text-md); color: var(--obs-color-text-secondary); }
.fb-form select, .fb-form textarea, .fb-form input[type="text"] {
  font: inherit;
  font-size: var(--obs-text-md);
  color: var(--obs-color-text);
  background: var(--obs-color-surface-3);
  border: 1px solid var(--obs-color-border);
  border-radius: var(--obs-radius);
  padding: var(--obs-space-2) var(--obs-space-3);
  min-height: var(--obs-touch-min);
}
.fb-form textarea { min-height: 96px; }
.fb-scale { border: 0; padding: 0; margin: 0; display: grid; gap: var(--obs-space-1); }
.fb-opt { display: flex; align-items: center; gap: var(--obs-space-2); min-height: 32px; cursor: pointer; }
.fb-num { color: var(--obs-color-text-muted); font-family: var(--obs-font-mono, monospace); }
.fb-status { margin: 0; min-height: 1.2em; font-size: var(--obs-text-md); color: var(--obs-color-text-secondary); }
.fb-actions { margin-top: var(--obs-space-2); }
.fb-actions .btn { flex: 1 1 120px; }
.fb-actions .btn:disabled { opacity: .5; cursor: not-allowed; }

/* ---------- Docs page (generated from the schemas) ---------- */
.docs .docs-toc { margin: 0 0 var(--obs-space-4); }
.docs .docs-toc ul { display: flex; flex-wrap: wrap; gap: var(--obs-space-1) var(--obs-space-4); list-style: none; padding: 0; margin: 0; }
.docs .docs-toc li { margin: 0; }
.docs .docs-toc li::marker { content: ""; }
.docs .md-table td { color: var(--obs-color-text-secondary); }
.docs .md-table td:first-child { color: var(--obs-color-text); }
.docs .docs-constraint { font-family: var(--obs-font-mono); font-size: var(--obs-text-xs); color: var(--obs-color-text-muted); }
.docs td code { white-space: normal; overflow-wrap: anywhere; }
.docs pre.md-code { max-height: 560px; overflow: auto; }


/* ======================================================================
   Days since last vulnpocalypse finding. The one hero figure on the page.

   Proportional figures, not tabular: tabular-nums gives every digit the
   width of a zero, which reads loose at display size. Tabular belongs in
   the columns of the tables below, not here.

   The colour carries the meaning. A large number in the signal colour is
   the good reading, and zero means a confirmed compromise landed today,
   so it turns red rather than just getting shorter.
   ====================================================================== */
.vp-card {
  position: relative;
  overflow: hidden;
  display: grid;
  /* Both columns size to their content and the pair is centred, rather than
     the text column taking the remaining width. With 1fr the sub-line ended
     around 60% and the rest of a 1280px card was empty, which reads as a
     layout accident rather than a decision. */
  grid-template-columns: auto auto;
  grid-template-areas: "num label" "num sub";
  align-content: center;
  justify-content: center;
  column-gap: var(--obs-space-8);
  row-gap: var(--obs-space-2);
  padding: var(--obs-space-6) var(--obs-space-8);
  text-align: left;
}
/* 60ch split "2026-10-17" across two lines. The sentence is 78 characters, so
   the cap sits above it: wide enough to keep one line here, tight enough that
   a longer sub-line later still gets a readable measure. */
.vp-card .vp-sub { max-width: 82ch; text-wrap: pretty; }
.vp-card::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 2px;
  background: var(--obs-color-signal);
}
.vp-label {
  grid-area: label;
  align-self: end;
  margin: 0;
  font-size: var(--obs-text-sm);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--obs-color-text-secondary);
}
.vp-number {
  grid-area: num;
  display: flex;
  align-items: baseline;
  gap: var(--obs-space-3);
  margin: 0;
  font-size: clamp(4rem, 15vw, 6rem);
  line-height: 1;
  font-weight: 700;
  letter-spacing: -.02em;
  color: var(--obs-color-signal);
  text-shadow: 0 0 28px rgba(62, 232, 216, .34);
}
.vp-unit {
  font-size: var(--obs-text-base);
  font-weight: 500;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--obs-color-text-secondary);
  text-shadow: none;
}
.vp-rule { display: none; }
.vp-sub {
  grid-area: sub;
  align-self: start;
  margin: 0;
  font-size: var(--obs-text-md);
  color: var(--obs-color-text-secondary);
  max-width: 80ch;
}
@media (max-width: 720px) {
  .vp-card {
    grid-template-columns: 1fr;
    grid-template-areas: "label" "num" "sub";
    justify-items: center;
    text-align: center;
    padding: var(--obs-space-5) var(--obs-space-4);
  }
  .vp-number { font-size: 4rem; }
}
.vp-card[data-vp-state="unknown"] .vp-number {
  color: var(--obs-color-text-secondary);
  text-shadow: none;
}
.vp-card[data-vp-state="unknown"] .vp-rule {
  background: linear-gradient(90deg, transparent, var(--obs-color-border), transparent);
}
.vp-card[data-vp-state="zero"] .vp-number {
  color: var(--obs-tier-confirmed);
  text-shadow: 0 0 28px rgba(255, 77, 94, .34);
}
.vp-card[data-vp-state="zero"]::before { background: var(--obs-tier-confirmed); }
@media (prefers-reduced-motion: no-preference) {
  .vp-card[data-vp-state="zero"] .vp-number { animation: vp-pulse 2.4s ease-in-out infinite; }
}
@keyframes vp-pulse {
  0%, 100% { text-shadow: 0 0 28px rgba(255, 77, 94, .34); }
  50% { text-shadow: 0 0 40px rgba(255, 77, 94, .6); }
}

/* ======================================================================
   Click a diagram to enlarge it.
   ====================================================================== */
.mermaid-figure figcaption { display: flex; align-items: baseline; justify-content: space-between; gap: var(--obs-space-3); }
.mermaid-figure figcaption.figcaption-bare { justify-content: flex-end; }
.mermaid-host { cursor: zoom-in; }
.dz-open {
  flex: none;
  font: inherit;
  font-size: var(--obs-text-xs);
  color: var(--obs-color-text-secondary);
  background: none;
  border: 1px solid var(--obs-color-border);
  border-radius: var(--obs-radius-sm);
  padding: 3px 10px;
  min-height: 28px;
  cursor: pointer;
}
.dz-open:hover { color: var(--obs-color-text); }
.dz-open:focus-visible { outline: 2px solid var(--obs-color-focus, currentColor); outline-offset: 2px; }
dialog.diagram-zoom {
  width: min(96vw, 1200px);
  max-height: 92vh;
  background: var(--obs-color-surface);
  color: var(--obs-color-text);
  border: 1px solid var(--obs-color-border);
  border-radius: var(--obs-radius-lg);
  padding: var(--obs-space-4);
}
dialog.diagram-zoom::backdrop { background: rgb(0 0 0 / .62); }
.dz-head { display: flex; align-items: center; justify-content: space-between; gap: var(--obs-space-3); }
.dz-title { margin: 0; font-size: var(--obs-text-base); }
.dz-close {
  font: inherit;
  color: var(--obs-color-text-secondary);
  background: none;
  border: 1px solid var(--obs-color-border);
  border-radius: var(--obs-radius-sm);
  padding: 6px 12px;
  min-height: 32px;
  cursor: pointer;
}
.dz-close:hover { color: var(--obs-color-text); }
.dz-body { margin-top: var(--obs-space-3); overflow: auto; max-height: 78vh; }
.dz-body .dz-svg { width: 100%; height: auto; }

/* ======================================================================
   Development banner. Not dismissible: a disclaimer a reader can switch
   off is absent for everyone who switched it off.
   ====================================================================== */
.dev-banner {
  background: var(--obs-tier-attempts-bg);
  color: var(--obs-tier-attempts);
  border-bottom: 1px solid var(--obs-tier-attempts-border);
  padding: var(--obs-space-2) var(--obs-gutter);
  text-align: center;
}
.dev-banner p {
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--obs-space-2);
  font-size: var(--obs-text-sm);
  font-weight: 600;
  letter-spacing: .04em;
}
.dev-banner p::before {
  content: "";
  flex: none;
  width: var(--obs-space-2);
  height: var(--obs-space-2);
  border-radius: 50%;
  background: currentColor;
}
@media (max-width: 720px) {
  .dev-banner { padding-inline: var(--obs-gutter-mobile); }
}

/* ---- Sources section (context, not evidence) ---- */
.sources-section .src-body { padding: var(--obs-space-4) var(--obs-space-5) var(--obs-space-5); }
.src-group { margin: var(--obs-space-4) 0 var(--obs-space-2); font-size: var(--obs-text-xs); font-weight: 600; text-transform: uppercase; letter-spacing: var(--obs-tracking-label); color: var(--obs-color-text-muted); }
.src-group:first-child { margin-top: 0; }
.src-list { list-style: none; margin: 0; padding: 0; }
.src-list li { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--obs-space-1) var(--obs-space-3); padding: var(--obs-space-2) 0; overflow-wrap: anywhere; }
.src-meta { font-size: var(--obs-text-xs); color: var(--obs-color-text-muted); }
.src-kind { font-size: var(--obs-text-xs); }
.src-dead { font-size: var(--obs-text-xs); color: var(--obs-color-text-muted); }

/* ---------- Agent prompts (entry page) ----------
   Appended block. Panels show the full prompt text in place; long text
   scrolls inside the panel and wraps rather than overflowing. */
.prompts-lede, .prompts-for { margin: 0; padding: 0 var(--obs-space-5); max-width: calc(60ch + 2 * var(--obs-space-5)); color: var(--obs-color-text-secondary); }
.prompts-lede { margin-top: var(--obs-space-4); }
.prompts-for { margin-top: var(--obs-space-1); font-size: var(--obs-text-sm); color: var(--obs-color-text-muted); }
.prompt-panel { margin: var(--obs-space-5) var(--obs-space-5) 0; }
.prompt-panel:last-of-type { margin-bottom: var(--obs-space-5); }
.prompt-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--obs-space-3); }
.prompt-title { margin: 0; font-size: var(--obs-text-base); }
.prompt-copy { min-width: 14rem; }
.prompt-text {
  margin: var(--obs-space-3) 0 0;
  padding: var(--obs-space-4);
  max-height: 24rem;
  overflow: auto;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  user-select: text;
  font-size: var(--obs-text-sm);
  line-height: 1.5;
  color: var(--obs-color-text-secondary);
  background: var(--obs-color-bg);
  border: 1px solid var(--obs-color-border);
  border-radius: var(--obs-radius);
}

/* ======================================================================
   Indicators that cannot be searched for. Shown as unusable rather than
   printed next to a confidence rating that implies they are actionable.
   ====================================================================== */
/* No opacity on the row. The first version dimmed it to .72, which multiplies
   down the contrast of every cell including the ones that were fine, and took
   the page from 100 to 97 on four separate elements. The dashed tag carries
   the meaning; the text stays readable. These rows are informative, not
   disabled. */
.ioc-unusable-tag {
  font-size: var(--obs-text-xs);
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--obs-color-text-secondary);
  border: 1px dashed var(--obs-color-text-secondary);
  border-radius: var(--obs-radius-sm);
  padding: 1px 6px;
  white-space: nowrap;
}
.ioc-unusable-why { font-size: var(--obs-text-xs); color: var(--obs-color-text-secondary); }
.conf-none { color: var(--obs-color-text-secondary); }

/* ======================================================================
   Agent prompts: collapsed by default. Three prompts of forty-odd lines
   each pushed everything below them off the page, and the common action
   is to copy one rather than read it in place.
   ====================================================================== */
.prompt-reveal { margin: var(--obs-space-3) var(--obs-space-5) var(--obs-space-5); }
.prompt-summary {
  display: inline-flex;
  align-items: center;
  gap: var(--obs-space-2);
  cursor: pointer;
  font-size: var(--obs-text-sm);
  color: var(--obs-color-text-secondary);
  list-style: none;
  padding: 4px 0;
  min-height: 28px;
}
.prompt-summary::-webkit-details-marker { display: none; }
.prompt-summary::before {
  content: "";
  width: 0;
  height: 0;
  border-left: 5px solid currentColor;
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  transition: transform .15s ease;
}
@media (prefers-reduced-motion: reduce) {
  .prompt-summary::before { transition: none; }
}
.prompt-reveal[open] .prompt-summary::before { transform: rotate(90deg); }
.prompt-summary:hover { color: var(--obs-color-text); }
.prompt-summary:focus-visible { outline: 2px solid var(--obs-color-focus, currentColor); outline-offset: 3px; }
.prompt-reveal .prompt-text { margin-top: var(--obs-space-3); }

/* ======================================================================
   Mobile pass. Appended as one block so it merges cleanly. Everything here
   is measured against a real phone viewport at 320, 390, 414 and 768.
   ====================================================================== */

/* Scrollable tables say so. Edge shadows appear only on the side that still
   has content (background-attachment: local covers them at the scroll limit),
   so a table that fits shows nothing and one that overflows is never silent. */
.table-scroll { --ts-bg: var(--obs-color-surface); }
.why .table-scroll { --ts-bg: var(--obs-color-bg); }
.table-scroll {
  background:
    linear-gradient(90deg, var(--ts-bg) 30%, transparent) left center / 24px 100% no-repeat local,
    linear-gradient(270deg, var(--ts-bg) 30%, transparent) right center / 24px 100% no-repeat local,
    linear-gradient(90deg, var(--obs-color-border), transparent) left center / 12px 100% no-repeat scroll,
    linear-gradient(270deg, var(--obs-color-border), transparent) right center / 12px 100% no-repeat scroll;
}
.table-scroll:focus-visible { outline: 2px solid var(--obs-color-focus, currentColor); outline-offset: -2px; }

/* Feedback launcher: floats on a wide desktop; on phones and tablets it sits
   in the flow after the footer, so it can never cover the filter row, a table
   cell or a footer link. */
@media (max-width: 1024px) {
  .fb-fab {
    position: static;
    display: block;
    width: calc(100% - 2 * var(--obs-gutter-mobile));
    margin: var(--obs-space-4) var(--obs-gutter-mobile);
  }
}

/* Long disabled-button reasons wrap instead of pushing the page sideways. */
.btn-disabled { max-width: 100%; white-space: normal; text-align: left; height: auto; min-height: var(--obs-touch-min); }

@media (max-width: 720px) {
  /* Nav wraps into rows instead of scrolling. Five short items cost one extra
     row, the header is not sticky, and nothing is hidden off the edge. */
  .nav {
    flex-wrap: wrap;
    overflow-x: visible;
    -webkit-mask-image: none;
    mask-image: none;
    gap: 0 var(--obs-space-1);
  }
  .brand { min-height: var(--obs-touch-min); }
  .byline a { min-height: var(--obs-space-6); padding-inline: var(--obs-space-2); margin-inline: calc(-1 * var(--obs-space-2)); }
  .byline { padding-left: calc(22px + var(--obs-space-3)); padding-bottom: var(--obs-space-1); }

  /* Entry page: headline tier before the picture, so the answer is on the first
     screen and the illustration follows it. */
  .entry-head-row { gap: var(--obs-space-3); }
  .entry-head-main { display: contents; }
  .entry-head-main > .character-hero { order: 2; margin-top: 0; }
  .entry-head-row > .tier-card { order: 1; }
  .tier-card-top { flex-wrap: wrap; }
  .tier-card-chips { flex-wrap: wrap; }

  /* Home catalog: one card per entry instead of a ten-column table. */
  .entries-table, .entries-table tbody, .entries-table tr, .entries-table th, .entries-table td { display: block; min-width: 0; width: 100%; }
  .data-table.entries-table { min-width: 0; }
  .entries-table thead { position: absolute; left: -9999px; }
  .entries-table tbody tr {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--obs-space-2) var(--obs-space-4);
    padding: var(--obs-space-4);
    border-bottom: 1px solid var(--obs-color-border);
  }
  .entries-table tbody tr:last-child { border-bottom: 0; }
  .entries-table th.cve-cell { grid-column: 1 / -1; padding: 0; border: 0; display: flex; align-items: center; gap: var(--obs-space-3); font-size: var(--obs-text-lg); }
  .entries-table td { padding: 0; border: 0; min-width: 0; }
  .entries-table td::before {
    content: attr(data-label);
    display: block;
    font-size: var(--obs-text-xs);
    letter-spacing: var(--obs-tracking-label);
    text-transform: uppercase;
    color: var(--obs-color-text-secondary);
    margin-bottom: var(--obs-space-1);
  }
  .entries-table .alias-cell, .entries-table .fp-cell, .entries-table .open-cell { grid-column: 1 / -1; min-width: 0; }
  .entries-table .open-cell::before { display: none; }
  .entries-table .alias-cell { overflow-wrap: anywhere; }
  .entries-table .fp-cell { display: flex; flex-wrap: wrap; align-items: center; row-gap: var(--obs-space-1); }
  .entries-table .fp-cell::before { flex-basis: 100%; }
  .fp-pair { display: inline-flex; align-items: center; white-space: nowrap; margin-right: var(--obs-space-3); }
  .fp-pair .fp-name { margin: 0 0 0 var(--obs-space-2); }

  /* The incident tag stacks its label over the live count instead of wrapping inside the box. */
  .tag-incident { flex-wrap: wrap; row-gap: var(--obs-space-1); align-self: flex-start; max-width: 100%; }
  .pulse-live { flex-wrap: wrap; }
  .pulse-window { letter-spacing: 0; }
  .entries-table tbody tr:hover td { background: none; }

  /* Wide tables that stay tables keep a readable first column and show they scroll. */
  .table-scroll { -webkit-overflow-scrolling: touch; }
}

/* Touch targets: phones and tablets. */
@media (max-width: 1024px) {
  .dz-open { min-height: var(--obs-touch-min); min-width: var(--obs-touch-min); padding: var(--obs-space-2) var(--obs-space-4); }
  .prompt-summary { min-height: var(--obs-touch-min); padding: var(--obs-space-3) 0; }
  .fb-opt { min-height: var(--obs-touch-min); }
  .ftr-links a, .ftr-schema a, .ftr-legal a, .ftr-btn { min-height: var(--obs-touch-min); min-width: var(--obs-touch-min); justify-content: center; }
  .ftr-links { display: flex; flex-wrap: wrap; align-items: center; gap: 0 var(--obs-space-3); }
  .ftr-legal ul { gap: 0 var(--obs-space-6); }
  .ftr-btn { padding: 0 var(--obs-space-2); }
  .stats-why { display: inline-flex; align-items: center; min-height: var(--obs-touch-min); }
  .src-list li { padding: 0; }
  .src-title { display: inline-flex; align-items: center; min-height: var(--obs-touch-min); }
  .entry-export-links { columns: 1; padding: var(--obs-space-2) var(--obs-space-5) var(--obs-space-4); }
  .entry-export-links li { margin: 0; }
  .entry-export-links a { display: inline-flex; align-items: center; min-height: var(--obs-touch-min); }
  .open-cell a { display: flex; align-items: center; justify-content: center; min-height: var(--obs-touch-min); min-width: var(--obs-touch-min); }

  .pulse-cta { display: inline-flex; align-items: center; min-height: var(--obs-touch-min); }
  .crumbs a { display: inline-flex; align-items: center; min-height: var(--obs-touch-min); }
  .cve-cell a, .entries-table .cve-cell a { display: inline-flex; align-items: center; min-height: var(--obs-touch-min); }
  .docs .docs-toc ul { gap: 0 var(--obs-space-4); }
  .docs .docs-toc a { display: inline-flex; align-items: center; min-height: var(--obs-touch-min); }
  .ftr { row-gap: 0; }
}

/* Below 360px the brand and the call to action cannot share a row. Give the
   call to action the full row rather than leaving it stranded on the right. */
@media (max-width: 359px) {
  .hdr-side { width: 100%; margin-bottom: var(--obs-space-1); }
  .hdr-side .btn-sighting { width: 100%; justify-content: center; }
}
/* The status line is tucked up under the filters with a negative margin, so the
   table below would paint over it now that the scroll cue has a background. */
.filters-status { position: relative; z-index: 1; }

/* ======================================================================
   Edge labels must not be clipped.

   Mermaid sizes each label's foreignObject from its own text measurement,
   and that measurement comes up about one character short here, so every
   branch condition lost its last glyph: "8.2 to 8.5" read "8.2 to 8.",
   "My host controls PHP" read "PHF", and no read as "nc". An SVG
   foreignObject clips to its bounds whatever the inner element's overflow
   says, so the fix has to be on the foreignObject itself.

   On a decision tree the clipped part is the branch condition, which is
   the entire reason the label exists.
   ====================================================================== */
.mermaid-host svg foreignObject,
.diagram-zoom svg foreignObject {
  overflow: visible;
}
.mermaid-host svg .edgeLabel,
.diagram-zoom svg .edgeLabel {
  overflow: visible;
  white-space: nowrap;
}
.mermaid-host svg .edgeLabel > *,
.diagram-zoom svg .edgeLabel > * {
  overflow: visible;
  white-space: nowrap;
}


/* ======================================================================
   Reading measure on the two lines that were running long.

   The IOC page's lede ran 101 characters per line at 1280 and its feed
   intro 168, where comfortable prose is roughly 45 to 85. Both are single
   paragraphs in full-width cards, so nothing constrained them.
   ====================================================================== */
.g-lede,
.ioc-feeds-lead > p {
  /* 68ch, not 78: the CSS ch unit is the advance width of "0", which in this
     face is wider than the average character, so 78ch renders closer to 90
     characters of real text than to 78. */
  max-width: 68ch;
}


/* The combined-feed heading sat flush against its card edge at every width.
   The card delegates its inset to children, as the others do, and this head
   was the one that never got any. */
.ioc-head {
  padding: var(--obs-space-4) var(--obs-space-5) 0;
}
