/* ──────────────────────────────────────────────────────────────
   intelligence.css - Smart-money intelligence page styles
   ──────────────────────────────────────────────────────────────
   Reuses global CSS vars from assets/style.css:
     --bg, --bg-card, --bg-input, --border, --text-hi, --text-mid
     --flow-in, --flow-out  (admin-customisable inflow/outflow tints)
   Card grid + drill panel + signals table - purely page-scoped.
   ────────────────────────────────────────────────────────────── */

/* Iter 19.44 - the rest of this file (and intelligence-detail.css) was
   written against `--text-mid`, but the real design-system token in
   style.css is `--text-md`. The undefined custom prop fell through to
   inheritance for `color:` (still readable) but to `fill: black` for SVG
   `<text>` - which is why the price chart's tick labels disappeared on
   the dark theme. Aliasing both names at :root fixes every offender
   (133 in this page) in one line. */
:root { --text-mid: var(--text-md); }

.intel-main {
  max-width: 1480px;
  margin: 0 auto;
  padding: 18px 20px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* Iter 19.34 - 2-col layout: narratives left, raw signals right rail.
   Right rail is sticky so the operator can keep eyes on live raw signal
   activity while scrolling through narrative cards. Stacks to single
   column below 1100px so the table doesn't get crushed. */
.intel-cols {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(380px, 1fr);
  gap: 18px;
  align-items: start;
}
.intel-col-signals {
  position: sticky;
  top: 16px;
  max-height: calc(100vh - 32px);
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.intel-col-signals .signals-wrap {
  overflow: auto;
  flex: 1;
  min-height: 0;
}
@media (max-width: 1100px) {
  .intel-cols { grid-template-columns: 1fr; }
  .intel-col-signals {
    position: static;
    max-height: none;
  }
  .intel-col-signals .signals-wrap { overflow: visible; }
}

/* ── Header ─────────────────────────────────────────────────── */
/* Iter 19.43 - title + filter row fused into one compact header line. */
.intel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}
.intel-title {
  margin: 0;
  font-size: 18px;
  letter-spacing: -.01em;
  color: var(--text-hi);
  font-weight: 600;
}
.intel-stats {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
}
.intel-stat {
  display: flex;
  flex-direction: column;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 10px 14px;
  min-width: 88px;
}
.intel-stat-num {
  font-size: 22px;
  font-weight: 600;
  color: var(--text-hi);
  font-variant-numeric: tabular-nums;
}
.intel-stat-label {
  font-size: 11px;
  color: var(--text-mid);
  letter-spacing: .3px;
}

/* ── Filter row ─────────────────────────────────────────────── */
.intel-filters {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}
.intel-seg {
  display: inline-flex;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 2px;
}
.intel-seg-btn {
  background: transparent;
  border: 0;
  color: var(--text-mid);
  padding: 6px 14px;
  border-radius: 4px;
  font-size: 13px;
  cursor: pointer;
  letter-spacing: .2px;
}
.intel-seg-btn.active {
  background: var(--bg-input);
  color: var(--text-hi);
}
.intel-asset {
  color: var(--text-mid);
  font-size: 13px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.intel-asset select {
  background: var(--bg-input);
  border: 1px solid var(--border);
  color: var(--text-hi);
  padding: 6px 10px;
  border-radius: 4px;
  font-size: 13px;
}

/* ── Section heads ──────────────────────────────────────────── */
.intel-section {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
/* Iter 19.43 - compact section heads (used by the signals rail).
   Just the title button, no subtitle. */
.intel-section-head-compact { margin-bottom: 8px; }
.intel-section-head-compact h2 { font-size: 12px; letter-spacing: 1px; text-transform: uppercase; color: var(--text-mid); margin: 0; }
.intel-section-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
}
.intel-section-head h2 {
  margin: 0;
  font-size: 16px;
  color: var(--text-hi);
  letter-spacing: -.005em;
}
.intel-section-sub {
  color: var(--text-mid);
  font-size: 12px;
}
.intel-section-toggle {
  background: transparent;
  border: 0;
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  color: var(--text-hi);
  cursor: pointer;
  padding: 0;
}
.intel-section-toggle .caret {
  color: var(--text-mid);
  font-size: 12px;
}

/* ── Narrative card grid ────────────────────────────────────── */
.narratives-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 10px;
}

.narr-card {
  position: relative;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-left: 4px solid var(--border);
  border-radius: 8px;
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  cursor: pointer;
  transition: border-color .15s, transform .12s, box-shadow .15s, background .15s;
  /* NOTE: no overflow:hidden - the per-field info tooltips need to escape the
     card. The ::before glow stays inside via border-radius:inherit + width:60%
     instead of clipping. */
}
.narr-card::before {
  /* faint directional glow on the left edge, only visible on hover */
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 60%;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(90deg, color-mix(in srgb, var(--border) 18%, transparent), transparent);
  opacity: 0;
  transition: opacity .2s;
}
.narr-card:hover {
  border-color: var(--text-mid);
  transform: translateY(-1px);
  box-shadow: 0 4px 14px -8px rgba(0, 0, 0, .5);
}
.narr-card:hover::before { opacity: 1; }
.narr-card.bull { border-left-color: var(--flow-in,  #00d17a); }
.narr-card.bear { border-left-color: var(--flow-out, #ff4d4d); }
.narr-card.bull::before { background: linear-gradient(90deg, color-mix(in srgb, var(--flow-in,  #00d17a) 12%, transparent), transparent); }
.narr-card.bear::before { background: linear-gradient(90deg, color-mix(in srgb, var(--flow-out, #ff4d4d) 12%, transparent), transparent); }

/* "Show all / Show top N" toggle below the grid. */
.narratives-toggle {
  margin-top: 12px;
  display: flex;
  justify-content: center;
}
.narratives-toggle:empty { display: none; }
.narr-toggle {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--text-hi);
  font-size: 12px;
  letter-spacing: .3px;
  padding: 7px 18px;
  cursor: pointer;
  transition: border-color .15s, background .15s, transform .1s;
}
.narr-toggle:hover {
  border-color: var(--text-mid);
  background: var(--bg-input);
}
.narr-toggle:active { transform: scale(.98); }

.narr-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.narr-card-name {
  font-size: 15px;
  font-weight: 600;
  color: var(--text-hi);
}
.narr-dir-chip {
  font-size: 10px;
  letter-spacing: .5px;
  padding: 2px 8px;
  border-radius: 3px;
  background: var(--bg-input);
  color: var(--text-mid);
}
.narr-dir-chip.bull { background: color-mix(in srgb, var(--flow-in,  #00d17a) 18%, transparent); color: var(--flow-in,  #00d17a); }
.narr-dir-chip.bear { background: color-mix(in srgb, var(--flow-out, #ff4d4d) 18%, transparent); color: var(--flow-out, #ff4d4d); }
/* Iter 19.20 - neutral fallback chip (sideways_range and future neutral
   narratives). Muted treatment so it reads as background state, not a
   directional setup the operator should act on. */
.narr-dir-chip.neutral { background: var(--bg-input); color: var(--text-mid); }
.narr-card.neutral { border-left-color: var(--text-mid); opacity: .92; }
.narr-card.neutral::before { background: linear-gradient(90deg, color-mix(in srgb, var(--text-mid) 8%, transparent), transparent); }
.narr-card.neutral .narr-score-num.conv-high { color: var(--text-hi); }
.narr-card.neutral .narr-score-bar i { background: linear-gradient(90deg, color-mix(in srgb, var(--text-mid) 50%, transparent), var(--text-mid)); }
.drill-head.neutral { border-bottom-color: color-mix(in srgb, var(--text-mid) 30%, var(--border)); }
.drill-score-card.neutral::before { background: linear-gradient(135deg, color-mix(in srgb, var(--text-mid) 10%, transparent), transparent 60%); }
.drill-score-card.neutral .drill-score-bar i { background: linear-gradient(90deg, color-mix(in srgb, var(--text-mid) 50%, transparent), var(--text-mid)); }
.sig-row.neutral { /* inherits default; no directional accent */ }

/* ── Iter 19.22 - group badge + earlier-confirmations timeline ─── */
.narr-group-badge {
  display: inline-block;
  margin-left: 8px;
  padding: 2px 8px;
  border-radius: 10px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .4px;
  text-transform: uppercase;
  background: var(--bg-input);
  color: var(--text-mid);
  border: 1px solid var(--border);
  font-variant-numeric: tabular-nums;
  vertical-align: middle;
}
.narr-card.grouped .narr-group-badge { background: color-mix(in srgb, var(--text-hi) 8%, var(--bg-input)); color: var(--text-hi); }
.narr-card.bull.grouped    .narr-group-badge { background: color-mix(in srgb, var(--flow-in,  #00d17a) 12%, var(--bg-input)); color: var(--flow-in,  #00d17a); border-color: color-mix(in srgb, var(--flow-in,  #00d17a) 30%, var(--border)); }
.narr-card.bear.grouped    .narr-group-badge { background: color-mix(in srgb, var(--flow-out, #ff4d4d) 12%, var(--bg-input)); color: var(--flow-out, #ff4d4d); border-color: color-mix(in srgb, var(--flow-out, #ff4d4d) 30%, var(--border)); }
.narr-card.neutral.grouped .narr-group-badge { background: var(--bg-input); color: var(--text-mid); }

/* Earlier-confirmations timeline inside the drill panel */
.drill-earlier-block { margin-top: 12px; }
.drill-earlier-list {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.drill-earlier-row {
  display: grid;
  grid-template-columns: 60px 1fr 16px;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  background: var(--bg-input);
  border-radius: 4px;
  font-size: 12px;
  cursor: pointer;
  transition: background .15s;
}
.drill-earlier-row:hover { background: color-mix(in srgb, var(--text-hi) 8%, var(--bg-input)); }
.drill-earlier-time { color: var(--text-mid); font-variant-numeric: tabular-nums; }
.drill-earlier-conv { color: var(--text-hi); font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; }
.drill-earlier-arrow { color: var(--text-mid); text-align: right; }
.drill-earlier-mult  { color: var(--text-mid); font-size: 10px; font-weight: 500; }
.drill-earlier-help  { color: var(--text-mid); font-size: 12px; margin: 6px 0; }

/* Iter 19.23 - confirmation count + chain badges */
.narr-chain-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 2px 7px;
  border-radius: 10px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .4px;
  text-transform: uppercase;
  background: var(--bg-input);
  color: var(--text-mid);
  border: 1px solid var(--border);
  vertical-align: middle;
}
.narr-chain-badge:hover { color: var(--text-hi); }
.drill-conf-badge {
  display: inline-block;
  margin-left: 8px;
  padding: 3px 9px;
  border-radius: 4px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .3px;
  background: color-mix(in srgb, var(--text-hi) 10%, var(--bg-input));
  color: var(--text-hi);
  border: 1px solid var(--border);
  vertical-align: middle;
  font-variant-numeric: tabular-nums;
}
.drill-head.bull .drill-conf-badge { color: var(--flow-in,  #00d17a); background: color-mix(in srgb, var(--flow-in,  #00d17a) 12%, var(--bg-input)); border-color: color-mix(in srgb, var(--flow-in,  #00d17a) 30%, var(--border)); }
.drill-head.bear .drill-conf-badge { color: var(--flow-out, #ff4d4d); background: color-mix(in srgb, var(--flow-out, #ff4d4d) 12%, var(--bg-input)); border-color: color-mix(in srgb, var(--flow-out, #ff4d4d) 30%, var(--border)); }

.narr-card-asset {
  font-size: 13px;
  color: var(--text-mid);
}
.narr-card-asset .narr-chain {
  font-size: 12px;
  opacity: .75;
}

/* Score + confidence - two stacked metrics. Score is the big number,
   confidence sits on the right as a coloured pill so operators can spot
   high-conf cards in the grid at a glance. */
/* Iter 19.15 - primary number on the card is now CONVICTION (score × conf).
   Layout: hero conviction number on top, score×conf breakdown row beside it,
   bar at the bottom spanning the full width. Tier-coloured by conviction. */
.narr-card-score {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.narr-score-num {
  font-size: 38px;
  font-weight: 700;
  color: var(--text-hi);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  letter-spacing: -.5px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
/* Conviction tier - primary visual cue. ≥60 strong (direction-tinted),
   ≥30 moderate (neutral highlight), <30 weak (muted). */
.narr-score-num.conv-low  { color: var(--text-mid); opacity: .85; }
.narr-score-num.conv-mid  { color: var(--text-hi); }
.narr-score-num.conv-high { color: var(--text-hi); }
.narr-card.bull .narr-score-num.conv-high { color: var(--flow-in,  #00d17a); }
.narr-card.bear .narr-score-num.conv-high { color: var(--flow-out, #ff4d4d); }

/* Breakdown row: "score 91 × 22%" - secondary, explains the conviction. */
.narr-score-breakdown {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  font-size: 12px;
  color: var(--text-mid);
  font-variant-numeric: tabular-nums;
}
.narr-score-raw,
.narr-score-conf {
  display: inline-flex;
  align-items: center;
  gap: 2px;
}
.narr-score-mul { opacity: .5; font-size: 10px; }

.narr-score-bar {
  height: 4px;
  background: var(--bg-input);
  border-radius: 2px;
  overflow: hidden;
}
.narr-score-bar i {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--text-mid), var(--text-hi));
  transition: width .3s ease;
}
.narr-card.bull .narr-score-bar i { background: linear-gradient(90deg, color-mix(in srgb, var(--flow-in,  #00d17a) 50%, transparent), var(--flow-in,  #00d17a)); }
.narr-card.bear .narr-score-bar i { background: linear-gradient(90deg, color-mix(in srgb, var(--flow-out, #ff4d4d) 50%, transparent), var(--flow-out, #ff4d4d)); }

/* Legacy .narr-conf pill styles kept for backward compat (any old reference
   that still uses them, drill panel etc). Score-card layout above no longer
   uses the pill - it's an inline 'score × conf' breakdown now. */
.narr-conf {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .3px;
  text-transform: uppercase;
  padding: 5px 10px;
  border-radius: 999px;
  background: var(--bg-input);
  color: var(--text-mid);
  border: 1px solid var(--border);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.narr-conf-label { opacity: .65; margin-right: 4px; font-weight: 500; }
.narr-conf.low  { color: var(--text-mid); }
.narr-conf.mid  { background: color-mix(in srgb, var(--text-hi) 8%, var(--bg-input)); color: var(--text-hi); border-color: color-mix(in srgb, var(--text-hi) 25%, var(--border)); }
.narr-conf.high { background: color-mix(in srgb, var(--flow-in,  #00d17a) 14%, var(--bg-input)); color: var(--flow-in,  #00d17a); border-color: color-mix(in srgb, var(--flow-in,  #00d17a) 40%, var(--border)); }
.narr-card.bear .narr-conf.high { background: color-mix(in srgb, var(--flow-out, #ff4d4d) 14%, var(--bg-input)); color: var(--flow-out, #ff4d4d); border-color: color-mix(in srgb, var(--flow-out, #ff4d4d) 40%, var(--border)); }

.narr-members {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
}
.narr-chip {
  font-size: 11px;
  background: var(--bg-input);
  color: var(--text-mid);
  padding: 2px 7px;
  border-radius: 3px;
  letter-spacing: .2px;
}

.narr-detail {
  font-size: 12px;
  color: var(--text-mid);
  line-height: 1.4;
}

.narr-members-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: var(--text-mid);
  margin-right: 6px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

/* ── Info markers (ⓘ) - hover or click to reveal per-field tooltip ──
   Tooltip text lives in [data-tip]. CSS draws a popover via ::after on
   hover/focus; click (mobile) toggles [data-tip-open] which the JS in
   intelligence.js sets - same visual treatment in both cases. */
.narr-info {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  margin-left: 5px;
  font-size: 10px;
  line-height: 1;
  color: var(--text-mid);
  cursor: help;
  opacity: .55;
  border-radius: 50%;
  vertical-align: middle;
  transition: opacity .15s, color .15s;
  position: relative;
  outline: none;
  user-select: none;
}
.narr-info:hover,
.narr-info:focus,
.narr-info[data-tip-open] {
  opacity: 1;
  color: var(--text-hi);
}
/* When the tooltip is active we lift the marker itself into a high
   stacking context, so the popover wins over EVERY adjacent card / row,
   even if a sibling later creates its own context via z-index. */
.narr-info:hover,
.narr-info:focus,
.narr-info[data-tip-open] { z-index: 200; }

.narr-info::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  width: max-content;
  max-width: 280px;
  background: var(--bg-card);
  color: var(--text-hi);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 9px 11px;
  font-size: 11px;
  font-weight: 400;
  line-height: 1.45;
  letter-spacing: 0;
  text-transform: none;
  white-space: pre-line;        /* honours \n in TIP strings */
  box-shadow: 0 8px 24px -10px rgba(0, 0, 0, .7), 0 0 0 1px rgba(0, 0, 0, .15);
  pointer-events: none;
  opacity: 0;
  z-index: 200;
  transition: opacity .12s ease-out, transform .12s ease-out;
}
/* Small arrow under the tooltip, pointing at the ⓘ marker. Visual anchor
   makes it clear which field the popover is describing. */
.narr-info::before {
  content: "";
  position: absolute;
  bottom: calc(100% + 2px);
  left: 50%;
  transform: translateX(-50%) rotate(45deg);
  width: 8px;
  height: 8px;
  background: var(--bg-card);
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  pointer-events: none;
  opacity: 0;
  z-index: 201;
  transition: opacity .12s ease-out;
}
.narr-info:hover::before,
.narr-info:focus::before,
.narr-info[data-tip-open]::before { opacity: 1; }
.narr-info:hover::after,
.narr-info:focus::after,
.narr-info[data-tip-open]::after {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
/* Tooltips near the right/left edges of the card can clip - these helpers
   let us bias the popover. For now we let max-width + word-wrap handle it;
   leaving the hooks in CSS for a later refinement if cards crowd the edge. */

.narr-card-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-top: 1px solid var(--border);
  padding-top: 8px;
  margin-top: 2px;
}
.narr-time {
  font-size: 11px;
  color: var(--text-mid);
}
.narr-expand {
  background: transparent;
  border: 0;
  color: var(--text-hi);
  font-size: 12px;
  cursor: pointer;
  padding: 2px 0;
}
.narr-expand:hover { text-decoration: underline; }

/* ── Drill panel (Iter 19.7 redesign) ────────────────────────────
   Right-side aside that opens when you click "Expand →" on a narrative
   card. Goal: scan preview in 3 seconds, NOT a deep-dive. Score block
   first, narrative gist second, member rows (compact, no charts) third,
   quick stats fourth, single CTA to /intelligence/narrative/:id last.
   The old design (full member-cards stacked inside) put every chart and
   evidence table in this 540px column → unreadable. */
.intel-drill {
  position: fixed;
  top: 0;
  right: 0;
  width: min(520px, 100vw);
  height: 100vh;
  background: var(--bg-card);
  border-left: 1px solid var(--border);
  z-index: 100;
  padding: 22px 24px;
  overflow-y: auto;
  box-shadow: -10px 0 32px rgba(0, 0, 0, .4);
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.intel-drill[hidden] { display: none; }
.intel-drill-close {
  position: absolute;
  top: 12px;
  right: 14px;
  background: transparent;
  border: 0;
  font-size: 22px;
  color: var(--text-mid);
  cursor: pointer;
  line-height: 1;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  transition: background .12s, color .12s;
}
.intel-drill-close:hover { background: var(--bg-input); color: var(--text-hi); }
.intel-drill-loading {
  color: var(--text-mid);
  font-size: 13px;
  padding-top: 20px;
}

/* Header */
.drill-head {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--border);
  padding-right: 30px;             /* leave room for the close × */
}
.drill-head.bull { border-bottom-color: color-mix(in srgb, var(--flow-in,  #00d17a) 30%, var(--border)); }
.drill-head.bear { border-bottom-color: color-mix(in srgb, var(--flow-out, #ff4d4d) 30%, var(--border)); }
.drill-head-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.drill-title {
  margin: 0;
  font-size: 19px;
  font-weight: 600;
  color: var(--text-hi);
  letter-spacing: -.01em;
}
.drill-asset-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  font-size: 12px;
}
.drill-asset-pill, .drill-chain-pill, .drill-time-pill {
  display: inline-block;
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--bg-input);
  border: 1px solid var(--border);
  color: var(--text-mid);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .2px;
}
.drill-asset-pill { color: var(--text-hi); }

/* Score card - hero, but more compact than the detail-page one */
.drill-score-card {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 16px;
  padding: 14px 16px;
  background: var(--bg-input);
  border: 1px solid var(--border);
  border-radius: 8px;
  position: relative;
  overflow: hidden;
}
.drill-score-card.bull::before,
.drill-score-card.bear::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.drill-score-card.bull::before { background: linear-gradient(135deg, color-mix(in srgb, var(--flow-in,  #00d17a) 12%, transparent), transparent 60%); }
.drill-score-card.bear::before { background: linear-gradient(135deg, color-mix(in srgb, var(--flow-out, #ff4d4d) 12%, transparent), transparent 60%); }
.drill-score-num-block { position: relative; z-index: 1; display: flex; flex-direction: column; gap: 6px; }
.drill-score-num {
  font-size: 42px;
  font-weight: 700;
  color: var(--text-hi);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  letter-spacing: -.02em;
}
.drill-score-denom {
  font-size: 16px;
  color: var(--text-mid);
  font-weight: 500;
  margin-left: 2px;
}
.drill-score-bar {
  height: 5px;
  background: var(--bg-card);
  border-radius: 3px;
  overflow: hidden;
}
.drill-score-bar i {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--text-mid), var(--text-hi));
}
.drill-score-card.bull .drill-score-bar i { background: linear-gradient(90deg, color-mix(in srgb, var(--flow-in,  #00d17a) 50%, transparent), var(--flow-in,  #00d17a)); }
.drill-score-card.bear .drill-score-bar i { background: linear-gradient(90deg, color-mix(in srgb, var(--flow-out, #ff4d4d) 50%, transparent), var(--flow-out, #ff4d4d)); }
.drill-conf-block { position: relative; z-index: 1; display: flex; flex-direction: column; gap: 6px; align-items: flex-end; }
.drill-conf-label {
  font-size: 10px;
  color: var(--text-mid);
  letter-spacing: .12em;
  text-transform: uppercase;
}
.drill-conf-pill {
  font-size: 14px;
  font-weight: 700;
  padding: 5px 12px;
  border-radius: 999px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  color: var(--text-mid);
  font-variant-numeric: tabular-nums;
}
.drill-conf-pill.conf-mid  { background: color-mix(in srgb, var(--text-hi) 10%, var(--bg-card)); color: var(--text-hi); border-color: color-mix(in srgb, var(--text-hi) 25%, var(--border)); }
.drill-conf-pill.conf-high { background: color-mix(in srgb, var(--flow-in,  #00d17a) 16%, var(--bg-card)); color: var(--flow-in,  #00d17a); border-color: color-mix(in srgb, var(--flow-in,  #00d17a) 40%, var(--border)); }
.drill-score-card.bear .drill-conf-pill.conf-high { background: color-mix(in srgb, var(--flow-out, #ff4d4d) 16%, var(--bg-card)); color: var(--flow-out, #ff4d4d); border-color: color-mix(in srgb, var(--flow-out, #ff4d4d) 40%, var(--border)); }

/* Section headers shared across gist / trigger / members */
.drill-section-h {
  margin: 0 0 8px;
  font-size: 10px;
  color: var(--text-mid);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .12em;
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.drill-section-count {
  font-size: 10px;
  color: var(--text-mid);
  background: var(--bg-input);
  border-radius: 999px;
  padding: 1px 7px;
  font-weight: 500;
  letter-spacing: 0;
}

/* Gist + trigger blocks - narrative-meaning prose + the engine's
   one-sentence "why now" - both styled as quiet card sections. */
.drill-gist,
.drill-trigger {
  padding: 12px 14px;
  background: var(--bg-input);
  border: 1px solid var(--border);
  border-radius: 6px;
}
.drill-gist p,
.drill-trigger p {
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--text-hi);
}
.drill-trigger p { color: var(--text-mid); font-style: italic; }

/* Member rows - one row per detector. Score + bar + the engine's detail
   sentence. No evidence-bars; detail page owns the deep view. */
.drill-members-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.drill-member-row {
  background: var(--bg-input);
  border: 1px solid var(--border);
  border-left: 3px solid var(--border);
  border-radius: 6px;
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  transition: background .15s, transform .1s;
}
.drill-member-row.bull { border-left-color: var(--flow-in,  #00d17a); }
.drill-member-row.bear { border-left-color: var(--flow-out, #ff4d4d); }
.drill-member-row.accent-purple { box-shadow: inset 4px 0 0 -1px #a78bfa; }
.drill-member-row.accent-blue   { box-shadow: inset 4px 0 0 -1px #60a5fa; }
.drill-member-row.accent-green  { box-shadow: inset 4px 0 0 -1px var(--flow-in,  #00d17a); }
.drill-member-row.accent-orange { box-shadow: inset 4px 0 0 -1px #fb923c; }
.drill-member-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
}
.drill-member-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-hi);
}
.drill-member-score {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-hi);
  font-variant-numeric: tabular-nums;
}
.drill-member-bar {
  height: 3px;
  background: var(--bg-card);
  border-radius: 2px;
  overflow: hidden;
}
.drill-member-bar i {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--text-mid), var(--text-hi));
}
.drill-member-row.bull .drill-member-bar i { background: linear-gradient(90deg, color-mix(in srgb, var(--flow-in,  #00d17a) 55%, transparent), var(--flow-in,  #00d17a)); }
.drill-member-row.bear .drill-member-bar i { background: linear-gradient(90deg, color-mix(in srgb, var(--flow-out, #ff4d4d) 55%, transparent), var(--flow-out, #ff4d4d)); }
.drill-member-detail {
  margin: 2px 0 0;
  font-size: 11px;
  color: var(--text-mid);
  line-height: 1.45;
}

/* Quick stats - 3 columns: tx count, address count, rule window */
.drill-stats-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  padding: 10px 12px;
  background: var(--bg-input);
  border: 1px solid var(--border);
  border-radius: 6px;
}
.drill-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}
.drill-stat-v {
  font-size: 18px;
  font-weight: 700;
  color: var(--text-hi);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.drill-stat-l {
  font-size: 10px;
  color: var(--text-mid);
  letter-spacing: .3px;
  text-transform: uppercase;
}

/* Footer CTA - single prominent button to the detail page */
.drill-footer {
  margin-top: auto;       /* pin to bottom of the scroll container */
  padding-top: 14px;
  border-top: 1px solid var(--border);
}
.drill-breakdown-cta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  padding: 11px 16px;
  background: var(--bg-input);
  border: 1px solid var(--text-mid);
  color: var(--text-hi);
  text-decoration: none;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .2px;
  border-radius: 6px;
  transition: background .15s, transform .1s, border-color .15s;
}
.drill-breakdown-cta:hover {
  background: color-mix(in srgb, var(--text-hi) 8%, var(--bg-input));
  border-color: var(--text-hi);
}
.drill-breakdown-cta:active { transform: scale(.99); }
.drill-cta-arrow { transition: transform .15s; }
.drill-breakdown-cta:hover .drill-cta-arrow { transform: translateX(3px); }

/* ── Signals table ──────────────────────────────────────────── */
.signals-wrap {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 6px;
  /* overflow: visible - needed so the per-column ⓘ tooltips can escape the
     wrapper. Previously overflow:hidden clipped them. The rounded-corner
     concern (thead's lighter background poking past the wrap's radius) is
     covered by giving the corner cells their own border-radius below. */
  overflow: visible;
  transition: max-height .2s;
}
.signals-wrap.collapsed { display: none; }
.signals-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
.signals-table thead th {
  text-align: left;
  background: var(--bg-input);
  color: var(--text-mid);
  font-weight: 500;
  letter-spacing: .3px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  font-size: 11px;
  text-transform: uppercase;
}
.signals-table thead th:first-child { border-top-left-radius:  6px; }
.signals-table thead th:last-child  { border-top-right-radius: 6px; }
.signals-table th.num,
.signals-table td.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.signals-table tbody td {
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  color: var(--text-hi);
  vertical-align: top;
}
.signals-table tbody tr:last-child td { border-bottom: 0; }
.sig-time {
  color: var(--text-mid);
  font-size: 12px;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.sig-detail {
  color: var(--text-mid);
  font-size: 12px;
  max-width: 380px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sig-narr-link {
  color: var(--text-hi);
  background: var(--bg-input);
  padding: 1px 6px;
  border-radius: 3px;
  font-size: 10px;
  margin-left: 6px;
  cursor: pointer;
  white-space: nowrap;
}
.sig-narr-link:hover { text-decoration: underline; }

/* Iter 19.16 - conviction + DQ columns in the raw signals table. The
   conviction value is the primary number to act on; score becomes a small
   secondary cell, DQ surfaces "how much do we trust the inputs" so an
   operator can quickly skip e.g. high-conv low-DQ rows. */
.sig-conv         { font-variant-numeric: tabular-nums; }
.sig-conv.conv-high { color: var(--text-hi); }
.sig-conv.conv-mid  { color: var(--text-mid); }
.sig-conv.conv-low  { color: var(--text-mid); opacity: .7; }
.sig-row.bull .sig-conv.conv-high { color: var(--flow-in,  #00d17a); }
.sig-row.bear .sig-conv.conv-high { color: var(--flow-out, #ff4d4d); }
.sig-score-sub    { color: var(--text-mid); font-size: 12px; font-variant-numeric: tabular-nums; }
.sig-dq           { font-size: 11px; padding: 1px 6px; border-radius: 3px; background: var(--bg-input); font-variant-numeric: tabular-nums; }
.sig-dq-high      { color: var(--text-hi); }
.sig-dq-mid       { color: var(--text-mid); }
.sig-dq-low       { color: var(--text-mid); opacity: .65; }

/* ── Empty states ───────────────────────────────────────────── */
.intel-empty {
  background: var(--bg-card);
  border: 1px dashed var(--border);
  border-radius: 6px;
  padding: 20px;
  color: var(--text-mid);
  font-size: 13px;
  text-align: center;
}

/* ── Mobile ─────────────────────────────────────────────────── */
@media (max-width: 860px) {
  /* ── Page chrome ─────────────────────────────────────────── */
  .intel-main { padding: 12px; gap: 14px; }
  .intel-header { flex-direction: column; align-items: flex-start; gap: 10px; }
  .intel-title { font-size: 19px; }
  .intel-sub   { font-size: 12px; max-width: none; }

  /* Stats strip: horizontal-scroll instead of wrapping into tiny rows.
     2-finger swipe to see all 4 metrics. Snap-points keep them aligned. */
  .intel-stats {
    flex-wrap: nowrap;
    overflow-x: auto;
    width: 100%;
    gap: 8px;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    /* Hide scrollbars on iOS Safari but keep functionality */
    scrollbar-width: thin;
  }
  .intel-stat {
    min-width: 110px;
    flex-shrink: 0;
    padding: 8px 12px;
    scroll-snap-align: start;
  }
  .intel-stat-num { font-size: 18px; }

  /* Filter bar: wrap to 2 rows with the direction segment full-width on
     top, then the two dropdowns side-by-side underneath. */
  .intel-filters { gap: 8px; }
  .intel-seg     { width: 100%; justify-content: stretch; }
  .intel-seg-btn { flex: 1; padding: 7px 0; font-size: 12px; }
  .intel-asset   { flex: 1; font-size: 12px; min-width: 0; }
  .intel-asset select {
    width: 100%;
    padding: 6px 8px;
    font-size: 12px;
  }

  /* "Forming" section: tighter padding, label/subtitle stack. */
  .pending-section { padding: 10px; }
  .pending-head    { flex-direction: column; align-items: flex-start; gap: 2px; }

  /* Narrative grid: single column. Already declared in the legacy rule
     below but explicit here for clarity. */
  .narratives-grid { grid-template-columns: 1fr; }

  /* Hero card: keep the conviction-asset row side-by-side (still readable
     at 360px) but trim sizes. Title can wrap. */
  .narr-card.hero { padding: 10px 12px 9px; gap: 8px; }
  .narr-card.hero .narr-title { font-size: 13px; }
  .narr-card.hero .narr-conv-num { font-size: 22px; }
  .narr-card.hero .narr-conv-box { padding: 4px 9px; min-width: 56px; }
  .narr-card.hero .narr-asset { font-size: 15px; }

  /* Pending readiness panel - same trim as conviction box */
  .pending-readiness { padding: 4px 9px; min-width: 84px; }
  .pending-readiness-num { font-size: 21px; }

  /* Drill panel already full-width via min(520px, 100vw); just ensure the
     close button + body have breathing room. */
  .intel-drill { padding: 18px 18px; }

  /* Legacy table rule kept for back-compat with any non-compact-5 surface
     elsewhere. The new .sig-list / .sig-row layout is already responsive. */
  .signals-table thead { display: none; }
  .signals-table, .signals-table tbody, .signals-table tr, .signals-table td {
    display: block;
    width: 100%;
  }
  .signals-table tr {
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 6px;
    margin-bottom: 8px;
  }
}

/* Extra-narrow phones (iPhone SE, older Android). Hero card stacks the
   conviction box ABOVE the asset block instead of side-by-side so neither
   gets crushed below 280px effective width. */
@media (max-width: 480px) {
  .narr-card.hero .narr-hero-mid { flex-direction: column; align-items: flex-start; gap: 8px; }
  .narr-card.hero .narr-conv-box { width: 100%; justify-content: flex-start; }
  .pending-readiness             { width: 100%; }
  .intel-filters .intel-asset    { flex: 1 1 100%; }      /* dropdowns full-width below segment */
  .intel-title { font-size: 17px; }
  .narr-card.hero .narr-asset { font-size: 14px; }
  .signals-table td { border-bottom: 0; padding: 4px 8px; }
  .sig-detail { white-space: normal; max-width: none; }
  .intel-drill { width: 100vw; }
}

/* Iter 19.44 - drill modal redesign. Score card is now [number + grade
   chip + bar] on the LEFT, plain-English summary sentence on the RIGHT.
   The old "conviction = score × conf" formula breakdown is gone - the
   single number plus the WEAK/MODERATE/STRONG word does the job. */
.drill-score-card {
  /* Flip the layout: 1.1fr 1fr so the summary has equal-ish room. */
  grid-template-columns: minmax(120px, auto) 1fr;
}
.drill-score-num.conv-low  { color: var(--text-md); opacity: .9; }
.drill-score-num.conv-mid  { color: var(--text-hi); }
.drill-score-num.conv-high { color: var(--text-hi); }
.drill-score-card.bull .drill-score-num.conv-high { color: var(--flow-in,  #00d17a); }
.drill-score-card.bear .drill-score-num.conv-high { color: var(--flow-out, #ff4d4d); }

.drill-score-grade {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-md);
  padding: 3px 8px;
  border-radius: 3px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  align-self: flex-start;
  width: fit-content;
}
.drill-score-card.bull .drill-score-grade.conv-high { color: var(--flow-in,  #00d17a); border-color: color-mix(in srgb, var(--flow-in,  #00d17a) 40%, var(--border)); background: color-mix(in srgb, var(--flow-in,  #00d17a) 12%, var(--bg-card)); }
.drill-score-card.bear .drill-score-grade.conv-high { color: var(--flow-out, #ff4d4d); border-color: color-mix(in srgb, var(--flow-out, #ff4d4d) 40%, var(--border)); background: color-mix(in srgb, var(--flow-out, #ff4d4d) 12%, var(--bg-card)); }

.drill-score-summary {
  position: relative;
  z-index: 1;
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--text-hi);
  align-self: center;
}

/* Detector chips - one per detector, replaces the verbose per-member rows.
   Same shape as a small pill with icon + name + arrow. */
.drill-det-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.drill-det-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--bg-input);
  border: 1px solid var(--border);
  color: var(--text-hi);
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
}
.drill-det-chip.bull { border-color: color-mix(in srgb, var(--flow-in,  #00d17a) 35%, var(--border)); }
.drill-det-chip.bear { border-color: color-mix(in srgb, var(--flow-out, #ff4d4d) 35%, var(--border)); }
.drill-det-icon {
  font-size: 14px !important;
  color: var(--text-md);
}
.drill-det-chip.bull .drill-det-icon { color: var(--flow-in,  #00d17a); }
.drill-det-chip.bear .drill-det-icon { color: var(--flow-out, #ff4d4d); }
.drill-det-name { font-weight: 500; }
.drill-det-arrow {
  font-size: 11px;
  color: var(--text-md);
  font-variant-numeric: tabular-nums;
}
.drill-det-chip.bull .drill-det-arrow { color: var(--flow-in,  #00d17a); }
.drill-det-chip.bear .drill-det-arrow { color: var(--flow-out, #ff4d4d); }

/* Single muted footer line - replaces the old 3-tile stats row. */
.drill-foot-meta {
  font-size: 11px;
  color: var(--text-md);
  letter-spacing: .2px;
  padding-bottom: 10px;
  font-variant-numeric: tabular-nums;
}

/* ══════════════════════════════════════════════════════════════
   Iter 19.38 - "Forming" pending narratives section
   ══════════════════════════════════════════════════════════════ */
/* Iter 19.43 - tighter forming section. No outer box (it competed with the
   card border-style: dashed). Header is one short label. */
.pending-section {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 10px;
}
.pending-head {
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.pending-label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: #f5b400;
}
.pending-sub { display: none; }
.pending-grid { /* uses .narratives-grid base styles */ }

/* Pending hero card: same shape as a real narrative card, but visually
   marked as not-yet-active. Dashed border, slightly muted, "forming" pill
   in the title. The conviction box is replaced by a readiness % + bar. */
.narr-card.hero.pending {
  border-style: dashed;
  background: color-mix(in srgb, var(--text-mid) 3%, var(--bg-card));
  /* Iter 19.39 - gentle "breathing" pulse on the dashed border so the
     operator sees the card is alive and updating, not static. Uses the
     per-type accent so each card breathes in its own colour. */
  animation: pending-breathe 2.6s ease-in-out infinite;
}
.narr-card.hero.pending:hover {
  border-color: var(--text-mid);
  transform: none;        /* don't lift - pending cards aren't clickable yet */
  cursor: default;
  animation-play-state: paused;
}
.pending-pill {
  display: inline-block;
  margin-left: 8px;
  padding: 1px 7px;
  border-radius: 10px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: .6px;
  text-transform: uppercase;
  background: color-mix(in srgb, #f5b400 22%, var(--bg-input));
  color: #f5b400;
  vertical-align: middle;
  /* Subtle pulse on the FORMING pill - confirms the system is monitoring. */
  animation: pending-pill-pulse 1.8s ease-in-out infinite;
}

@keyframes pending-breathe {
  0%, 100% { border-color: var(--border); }
  50%      { border-color: color-mix(in srgb, var(--narr-accent, var(--text-mid)) 65%, var(--border)); }
}
@keyframes pending-pill-pulse {
  0%, 100% { opacity: 0.7; }
  50%      { opacity: 1.0; }
}
/* Respect operator's reduced-motion preference - animations off entirely. */
@media (prefers-reduced-motion: reduce) {
  .narr-card.hero.pending,
  .pending-pill,
  .pending-readiness-bar i { animation: none !important; }
}

/* ── Iter 19.40 - completion animation ─────────────────────────
   When a pending narrative composes into a real one, the WS handler adds
   .completing to the pending DOM element BEFORE re-rendering. This runs
   an ~800ms sequence:
     0%   normal pending state
     20%  border solidifies + glows in the type accent, card scales 1.04
     45%  readiness bar snaps to 100% in the accent colour
     70%  card holds at full glow
     100% card shrinks + fades out as the real card is inserted below

   The .completing class also OVERRIDES the breathing pulse and the bar's
   shimmer animation so they don't fight the completion sequence. */
.narr-card.hero.pending.completing {
  animation: card-complete 800ms ease-out forwards !important;
  border-style: solid !important;
}
.narr-card.hero.pending.completing .pending-pill {
  animation: pill-complete 700ms ease-out forwards !important;
  background: color-mix(in srgb, var(--narr-accent, var(--text-mid)) 28%, var(--bg-input)) !important;
  color: var(--narr-accent, var(--text-mid)) !important;
}
.narr-card.hero.pending.completing .pending-readiness-num {
  animation: ready-num-pulse 600ms ease-out forwards !important;
}
.narr-card.hero.pending.completing .pending-readiness-bar i {
  width: 100% !important;
  background: var(--narr-accent, var(--text-mid)) !important;
  animation: none !important;
  transition: width 400ms ease-out !important;
}
.narr-card.hero.pending.completing .pending-member.missing {
  opacity: 0;
  transition: opacity 300ms ease-out;
}
.narr-card.hero.pending.completing .pending-member.met {
  transform: scale(1.05);
  transition: transform 300ms ease-out;
}

@keyframes card-complete {
  0% {
    transform: scale(1);
    border-color: var(--border);
    box-shadow: inset 0 -2px 0 -1px color-mix(in srgb, var(--narr-accent, transparent) 35%, transparent);
  }
  20% {
    transform: scale(1.04);
    border-color: var(--narr-accent, var(--text-mid));
    box-shadow:
      0 0 0 2px color-mix(in srgb, var(--narr-accent, transparent) 40%, transparent),
      0 0 36px -4px color-mix(in srgb, var(--narr-accent, transparent) 70%, transparent);
  }
  70% {
    transform: scale(1.01);
    opacity: 1;
    border-color: var(--narr-accent, var(--text-mid));
    box-shadow:
      0 0 0 2px color-mix(in srgb, var(--narr-accent, transparent) 30%, transparent),
      0 0 24px -6px color-mix(in srgb, var(--narr-accent, transparent) 55%, transparent);
  }
  100% {
    transform: scale(0.94);
    opacity: 0;
    border-color: var(--narr-accent, var(--text-mid));
    box-shadow: none;
  }
}
@keyframes pill-complete {
  0%   { transform: scale(1); opacity: 1; }
  25%  { transform: scale(1.18); opacity: 1; }
  100% { transform: scale(1);   opacity: 0; }
}
@keyframes ready-num-pulse {
  0%   { transform: scale(1); color: #f5b400; }
  40%  { transform: scale(1.12); color: var(--narr-accent, #00d17a); }
  100% { transform: scale(1); color: var(--narr-accent, #00d17a); }
}

/* Readiness block replaces the conviction box on pending cards. The number
   shows %; the bar visualises the gap to 100% so the eye reads "how close". */
.pending-readiness {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  padding: 4px 11px;
  border-radius: 6px;
  background: var(--bg-input);
  border: 1px solid var(--border);
  min-width: 96px;
}
.pending-readiness-num {
  font-size: 24px;
  font-weight: 700;
  line-height: 1;
  color: #f5b400;
  font-variant-numeric: tabular-nums;
}
.pending-readiness-suffix {
  font-size: 13px;
  color: var(--text-mid);
  margin-left: 1px;
  font-weight: 600;
}
.pending-readiness-bar {
  width: 100%;
  height: 4px;
  background: var(--border);
  border-radius: 2px;
  overflow: hidden;
  position: relative;
}
.pending-readiness-bar i {
  display: block;
  height: 100%;
  /* 3-stop gradient + 200% width drives the shimmer: the visible 100%
     viewport reveals different colour bands as background-position cycles.
     Stops chosen so the wash moves from base amber → bright amber → tinted
     green and back, mimicking "approaching ready". */
  background: linear-gradient(
    90deg,
    #f5b400,
    color-mix(in srgb, #f5b400 50%, var(--flow-in, #00d17a)),
    #f5b400
  );
  background-size: 200% 100%;
  border-radius: inherit;
  transition: width .35s ease;
  animation: pending-bar-shimmer 2.2s linear infinite;
}
@keyframes pending-bar-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* Member checklist: one row per required detector. Met = green check,
   missing = the detector's normal icon greyed out. Direction arrow shown
   only on missing rows so the operator knows what they're waiting for
   ("waiting for bullish stablecoin_loading ↑"). */
.pending-members {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding-top: 2px;
}
.pending-member {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
}
.pending-member-icon {
  font-size: 17px;
  line-height: 1;
  flex-shrink: 0;
}
.pending-member-name {
  flex: 1;
  min-width: 0;
}
.pending-member.met .pending-member-icon  { color: var(--flow-in, #00d17a); }
.pending-member.met .pending-member-name  { color: var(--text-hi); }
.pending-member.missing .pending-member-icon { color: var(--text-mid); opacity: .55; }
.pending-member.missing .pending-member-name { color: var(--text-mid); opacity: .75; }
.pending-member-arrow {
  font-size: 12px;
  color: var(--text-mid);
  opacity: .55;
}

/* ══════════════════════════════════════════════════════════════
   Iter 19.30 - hero narrative card + compact 5-col signals table
   ══════════════════════════════════════════════════════════════ */

/* ── Hero narrative card ───────────────────────────────────────
   Layout (top to bottom):
     hero-top:   title (+ badges)         right-aligned dir chip
     hero-mid:   [BIG CONVICTION BOX]  ASSET / chain
     meta-row:   detector dots · "N detectors · ×K confirmations"
     foot:       time                            → expand button

   The colored left border (set in older .narr-card rules above) does
   the direction-encoding work; no info icons clutter the card. */
.narr-card.hero {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 11px 13px 9px;
  border-left-width: 3px;
}
.narr-card.hero .narr-hero-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.narr-card.hero .narr-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-hi);
  letter-spacing: .2px;
  line-height: 1.2;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

/* Iter 19.39 - per-narrative-type glyph + accent. Each narrative type
   carries its own colour via --narr-accent (set inline from the
   IntelExplain.NARRATIVES catalog) so two cards of the same direction
   can still be told apart at a glance. Glyph is a Material Symbol from
   the same catalog. */
.narr-card.hero .narr-type-glyph {
  font-size: 16px;
  line-height: 1;
  color: var(--narr-accent, var(--text-mid));
  flex-shrink: 0;
}
/* Subtle tint on the card header's bottom edge - one thin coloured line
   reinforces the type without overpowering the direction-coloured left
   stripe. Painted via inset shadow so it doesn't fight the existing border. */
.narr-card.hero[data-narr-type] {
  box-shadow: inset 0 -2px 0 -1px color-mix(in srgb, var(--narr-accent, transparent) 55%, transparent);
}
.narr-card.hero[data-narr-type]:hover {
  box-shadow:
    inset 0 -2px 0 -1px color-mix(in srgb, var(--narr-accent, transparent) 70%, transparent),
    0 4px 14px -8px rgba(0, 0, 0, .5);
}
.narr-card.hero.pending[data-narr-type] {
  box-shadow: inset 0 -2px 0 -1px color-mix(in srgb, var(--narr-accent, transparent) 35%, transparent);
}
.narr-card.hero.pending[data-narr-type]:hover {
  box-shadow: inset 0 -2px 0 -1px color-mix(in srgb, var(--narr-accent, transparent) 45%, transparent);
}
.narr-card.hero .narr-hero-mid {
  display: flex;
  align-items: center;
  gap: 12px;
}
.narr-card.hero .narr-conv-box {
  display: inline-flex;
  align-items: baseline;
  gap: 1px;
  padding: 5px 11px;
  border-radius: 6px;
  background: var(--bg-input);
  border: 1px solid var(--border);
  min-width: 64px;
  justify-content: center;
  font-variant-numeric: tabular-nums;
  transition: background .2s, border-color .2s;
}
.narr-card.hero .narr-conv-num {
  font-size: 26px;
  font-weight: 700;
  line-height: 1;
  color: var(--text-hi);
  transition: color .2s;
}
/* Denom (/100) is hidden to declutter; class kept in markup for backward-compat. */
.narr-card.hero .narr-conv-denom { display: none; }

/* Iter 19.36 - 5-step heat gradient on the conviction box. As conviction
   climbs the box gets visually warmer:
     cold  (0-19)  muted grey         ← "ignore unless context"
     cool  (20-39) neutral, brighter  ← "interesting but verify"
     warm  (40-59) amber/yellow tint  ← "moderate, worth watching"
     hot   (60-79) directional tint   ← "act-worthy"
     blaze (80+)   full direction     ← "do not miss"
   Yellow stage is identical for bull/bear (intensity, not direction); hot+
   and above splits by direction so the operator gets BOTH the intensity
   (saturation) AND the direction (hue) at a glance. */
.narr-card.hero .narr-conv-box.conv-cold {
  background: var(--bg-input);
  border-color: var(--border);
}
.narr-card.hero .narr-conv-box.conv-cold .narr-conv-num { color: var(--text-mid); }

.narr-card.hero .narr-conv-box.conv-cool {
  background: color-mix(in srgb, var(--text-hi) 6%, var(--bg-input));
  border-color: color-mix(in srgb, var(--text-hi) 18%, var(--border));
}
.narr-card.hero .narr-conv-box.conv-cool .narr-conv-num { color: var(--text-hi); }

/* Yellow / amber: same for bull, bear, neutral. Pure intensity step. */
.narr-card.hero .narr-conv-box.conv-warm {
  background: color-mix(in srgb, #f5b400 18%, var(--bg-input));
  border-color: color-mix(in srgb, #f5b400 45%, var(--border));
}
.narr-card.hero .narr-conv-box.conv-warm .narr-conv-num { color: #f5b400; }

/* Hot: directional hue, soft saturation. Bull green, bear red, neutral
   amber (slightly hotter than warm but stays warm-grey). */
.narr-card.hero.bull .narr-conv-box.conv-hot {
  background: color-mix(in srgb, var(--flow-in,  #00d17a) 18%, var(--bg-input));
  border-color: color-mix(in srgb, var(--flow-in,  #00d17a) 50%, var(--border));
}
.narr-card.hero.bull .narr-conv-box.conv-hot .narr-conv-num { color: var(--flow-in,  #00d17a); }
.narr-card.hero.bear .narr-conv-box.conv-hot {
  background: color-mix(in srgb, var(--flow-out, #ff4d4d) 18%, var(--bg-input));
  border-color: color-mix(in srgb, var(--flow-out, #ff4d4d) 50%, var(--border));
}
.narr-card.hero.bear .narr-conv-box.conv-hot .narr-conv-num { color: var(--flow-out, #ff4d4d); }
.narr-card.hero.neutral .narr-conv-box.conv-hot {
  background: color-mix(in srgb, #f5b400 26%, var(--bg-input));
  border-color: color-mix(in srgb, #f5b400 55%, var(--border));
}
.narr-card.hero.neutral .narr-conv-box.conv-hot .narr-conv-num { color: #f5b400; }

/* Blaze: full directional saturation. Card is visually unmistakable. */
.narr-card.hero.bull .narr-conv-box.conv-blaze {
  background: color-mix(in srgb, var(--flow-in,  #00d17a) 34%, var(--bg-input));
  border-color: var(--flow-in,  #00d17a);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--flow-in,  #00d17a) 40%, transparent),
              0 0 12px -3px color-mix(in srgb, var(--flow-in, #00d17a) 60%, transparent);
}
.narr-card.hero.bull .narr-conv-box.conv-blaze .narr-conv-num { color: var(--flow-in,  #00d17a); }
.narr-card.hero.bear .narr-conv-box.conv-blaze {
  background: color-mix(in srgb, var(--flow-out, #ff4d4d) 34%, var(--bg-input));
  border-color: var(--flow-out, #ff4d4d);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--flow-out, #ff4d4d) 40%, transparent),
              0 0 12px -3px color-mix(in srgb, var(--flow-out, #ff4d4d) 60%, transparent);
}
.narr-card.hero.bear .narr-conv-box.conv-blaze .narr-conv-num { color: var(--flow-out, #ff4d4d); }
.narr-card.hero.neutral .narr-conv-box.conv-blaze {
  background: color-mix(in srgb, #f5b400 40%, var(--bg-input));
  border-color: #f5b400;
}
.narr-card.hero.neutral .narr-conv-box.conv-blaze .narr-conv-num { color: #f5b400; }

/* Iter 19.36 - asset coin icon next to symbol */
.narr-card.hero .narr-asset { display: inline-flex; align-items: center; gap: 6px; }
.narr-card.hero .narr-asset img {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  flex-shrink: 0;
  /* override the inline margin-right AssetIcons adds since the gap covers it */
  margin: 0 !important;
  vertical-align: middle;
}
.narr-card.hero .narr-asset-sym { line-height: 1.15; }
/* Old 3-tier conviction colours (conv-low/mid/high) were replaced by the
   5-step heat gradient defined above. Class names changed, so the rules
   below are dead - kept removed to avoid cascade conflicts. */

.narr-card.hero .narr-asset-block {
  display: flex;
  flex-direction: column;
  gap: 0;
  line-height: 1.1;
}
.narr-card.hero .narr-asset {
  font-size: 16px;
  font-weight: 700;
  color: var(--text-hi);
  letter-spacing: .2px;
  line-height: 1.15;
}
.narr-card.hero .narr-asset-block .narr-chain {
  font-size: 10px;
  color: var(--text-mid);
  line-height: 1.2;
}

.narr-card.hero .narr-meta-row {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 10px;
  color: var(--text-mid);
  line-height: 1;
}
.narr-card.hero .narr-dots {
  display: inline-flex;
  gap: 2px;
}
.narr-card.hero .narr-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--text-mid);
}
.narr-card.hero .narr-dot.accent-blue   { background: #58a6ff; }
.narr-card.hero .narr-dot.accent-green  { background: var(--flow-in,  #00d17a); }
.narr-card.hero .narr-dot.accent-red    { background: var(--flow-out, #ff4d4d); }
.narr-card.hero .narr-dot.accent-orange { background: #f7a93d; }
.narr-card.hero .narr-dot.accent-purple { background: #c08cff; }

.narr-card.hero .narr-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  padding-top: 1px;
}
.narr-card.hero .narr-time { font-size: 10px; }
.narr-card.hero .narr-expand {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-mid);
  border-radius: 4px;
  padding: 1px 9px;
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
  transition: border-color .15s, color .15s;
}
.narr-card.hero .narr-expand:hover {
  border-color: var(--text-hi);
  color: var(--text-hi);
}

/* Small tag styles inside the title row (group + chain badges). The
   existing .narr-group-badge / .narr-chain-badge styles still apply;
   tighten the chain icon for the hero layout. */
.narr-card.hero .narr-chain-badge {
  margin-left: 4px;
  padding: 1px 5px;
  font-size: 11px;
  line-height: 1;
}

/* ── Iter 19.35 - 2-line stacked raw signal rows ─────────────────
   Each signal renders as a flex column:
     line 1 (headline):  time · detector(icon + name + arrow) · asset · conv
     line 2 (context):   short detail text + narrative link
   Headline uses larger, scannable type; context line is slightly smaller
   and muted but still readable (no truncation, wraps if needed). The whole
   row gets a left border colored by direction (bull green, bear red, neutral
   grey) so the eye picks up direction even before reading. */
.sig-list {
  display: flex;
  flex-direction: column;
  gap: 0;
}
.sig-row {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 9px 12px;
  border-bottom: 1px solid var(--border);
  border-left: 3px solid transparent;
  transition: background .12s;
  cursor: default;
}
.sig-row:last-child { border-bottom: 0; }
.sig-row:hover { background: color-mix(in srgb, var(--text-hi) 4%, transparent); }
.sig-row.bull    { border-left-color: color-mix(in srgb, var(--flow-in,  #00d17a) 55%, transparent); }
.sig-row.bear    { border-left-color: color-mix(in srgb, var(--flow-out, #ff4d4d) 55%, transparent); }
.sig-row.neutral { border-left-color: var(--text-mid); }

.sig-row-1 {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  line-height: 1.2;
  color: var(--text-hi);
}
.sig-row .sig-time {
  color: var(--text-mid);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
  min-width: 38px;
  white-space: nowrap;
}
.sig-row .sig-det-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  line-height: 1;
  flex: 1;
  min-width: 0;
}
.sig-row .sig-det-icon {
  font-size: 18px;
  color: var(--text-mid);
  line-height: 1;
  flex-shrink: 0;
}
.sig-row.bull .sig-det-icon { color: color-mix(in srgb, var(--flow-in,  #00d17a) 70%, var(--text-mid)); }
.sig-row.bear .sig-det-icon { color: color-mix(in srgb, var(--flow-out, #ff4d4d) 70%, var(--text-mid)); }
.sig-row .sig-det-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-hi);
  white-space: nowrap;
}
.sig-row .sig-arrow {
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
}
.sig-row .sig-arrow.bull    { color: var(--flow-in,  #00d17a); }
.sig-row .sig-arrow.bear    { color: var(--flow-out, #ff4d4d); }
.sig-row .sig-arrow.neutral { color: var(--text-mid); }
.sig-row .sig-where {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 13px;
  font-weight: 700;
  color: var(--text-hi);
  white-space: nowrap;
  letter-spacing: .2px;
}
.sig-row .sig-where img {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  flex-shrink: 0;
  margin: 0 !important;   /* override AssetIcons' inline margin-right */
  vertical-align: middle;
}
.sig-row .sig-where-sym { line-height: 1.15; }
/* Iter 19.42 - sig-conv-block / sig-conv / sig-dq removed from the row
   markup. Conviction + DQ no longer surface to the operator; they're still
   computed server-side and used for sort order (sigConviction in the
   client). Asset (.sig-where) now flows naturally to the right with the
   detector pill flex:1, no margin-left:auto needed. */

.sig-row-2 {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  padding-left: 48px;   /* aligns with the start of the detector pill above */
  font-size: 12px;
  line-height: 1.35;
  color: var(--text-mid);
  flex-wrap: wrap;
}
.sig-row .sig-detail {
  flex: 1;
  min-width: 0;
  font-variant-numeric: tabular-nums;
}
.sig-row .sig-narr-link {
  color: var(--text-hi);
  background: var(--bg-input);
  padding: 1px 7px;
  border-radius: 10px;
  font-size: 10.5px;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: background .12s, color .12s;
}
.sig-row .sig-narr-link:hover {
  background: color-mix(in srgb, var(--flow-in, #00d17a) 18%, var(--bg-input));
  color: var(--flow-in, #00d17a);
}

/* Mobile: lose the leading padding on line 2 so it doesn't cause overflow. */
@media (max-width: 860px) {
  .sig-row { padding: 10px 12px; }
  .sig-row-2 { padding-left: 0; }
}


/* ══════════════════════════════════════════════════════════════
   Iter 19.45 - Forming-narratives block: 2 × 2 grid, bigger cards,
   sparkle animation ("magic happening"). Real-narrative cards get
   a detector-count chip in the footer.
   ══════════════════════════════════════════════════════════════ */

/* Pending grid - exactly 2 columns. The renderPending() function pads
   the list to 4 slots so the block always reads as one tight 2×2. */
.pending-grid {
  grid-template-columns: repeat(2, 1fr) !important;
  gap: 14px;
}

/* Bigger pending cards - more padding, larger conviction/readiness, more
   breathing room for the title and the member-rows underneath. Position:
   relative so the sparkles can absolute-position over the card. */
.narr-card.hero.pending {
  position: relative;
  padding: 16px 18px;
  gap: 12px;
  min-height: 220px;
  overflow: hidden;       /* sparkles can't escape the rounded corners */
}
.narr-card.hero.pending .narr-title       { font-size: 16px; }
.narr-card.hero.pending .narr-type-glyph  { font-size: 20px !important; }
.narr-card.hero.pending .pending-readiness {
  padding: 8px 14px;
  min-width: 110px;
}
.narr-card.hero.pending .pending-readiness-num { font-size: 30px; }
.narr-card.hero.pending .narr-asset       { font-size: 18px; }

/* Sparkles - three absolute-positioned dots that drift + pulse. Each has
   a different start delay so they don't all twinkle in sync. Filter +
   box-shadow give a soft glow that picks up the card's --narr-accent.
   pointer-events: none so they never block clicks on the card. */
.pending-sparkles {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
  border-radius: inherit;
  z-index: 0;
}
.pending-sparkle {
  position: absolute;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--narr-accent, var(--text-md));
  box-shadow:
    0 0 8px  var(--narr-accent, var(--text-md)),
    0 0 14px var(--narr-accent, var(--text-md));
  opacity: 0;
  filter: blur(0.4px);
}
.pending-sparkle:nth-child(1) { left: 18%; top: 28%; animation: sparkle-float 4.2s ease-in-out infinite;          }
.pending-sparkle:nth-child(2) { left: 72%; top: 22%; animation: sparkle-float 5.0s ease-in-out 1.4s infinite;     }
.pending-sparkle:nth-child(3) { left: 82%; top: 72%; animation: sparkle-float 4.6s ease-in-out 2.8s infinite;     }
@keyframes sparkle-float {
  0%   { opacity: 0;   transform: translate(0, 0)     scale(0.4); }
  30%  { opacity: 0.95; transform: translate(2px, -8px)  scale(1.1); }
  60%  { opacity: 0.6; transform: translate(-3px, -16px) scale(0.85); }
  100% { opacity: 0;   transform: translate(1px, -22px) scale(0.5); }
}

/* Card content sits above the sparkle layer */
.narr-card.hero.pending > :not(.pending-sparkles) {
  position: relative;
  z-index: 1;
}

/* Shimmer sweep across the card - a diagonal highlight that drifts left
   to right. Combined with the breathing border (already in place) +
   sparkles, this gives the "magic happening" feel without going overboard. */
.narr-card.hero.pending::after {
  content: "";
  position: absolute;
  top: -50%;
  left: -120%;
  width: 80%;
  height: 200%;
  background: linear-gradient(
    115deg,
    transparent          0%,
    color-mix(in srgb, var(--narr-accent, transparent) 12%, transparent) 45%,
    color-mix(in srgb, var(--narr-accent, transparent) 22%, transparent) 50%,
    color-mix(in srgb, var(--narr-accent, transparent) 12%, transparent) 55%,
    transparent          100%
  );
  pointer-events: none;
  z-index: 0;
  animation: pending-shimmer 5.5s ease-in-out infinite;
  border-radius: inherit;
}
@keyframes pending-shimmer {
  0%, 12%   { transform: translateX(0);    opacity: 0; }
  18%       { opacity: 1; }
  60%       { transform: translateX(250%); opacity: 1; }
  72%, 100% { transform: translateX(280%); opacity: 0; }
}

/* Placeholder - same shape as a real pending card but visibly empty.
   Used to keep the 2×2 grid filled. No interactivity. */
.narr-card.hero.pending.placeholder {
  background: color-mix(in srgb, var(--text-md) 2%, var(--bg-card));
  --narr-accent: var(--text-md);     /* sparkles fall back to muted grey */
  cursor: default;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 220px;
}
.pending-placeholder-body {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  color: var(--text-md);
  opacity: .8;
  z-index: 1;
  position: relative;
}
.pending-placeholder-icon {
  font-size: 30px !important;
  color: var(--text-md);
  opacity: .6;
  animation: pending-placeholder-pulse 3s ease-in-out infinite;
}
.pending-placeholder-text {
  font-size: 12px;
  letter-spacing: .2px;
}
@keyframes pending-placeholder-pulse {
  0%, 100% { opacity: 0.35; transform: scale(0.95); }
  50%      { opacity: 0.75; transform: scale(1.05); }
}

/* Reduced-motion: kill the moving parts but keep the static visuals. */
@media (prefers-reduced-motion: reduce) {
  .pending-sparkle,
  .narr-card.hero.pending::after,
  .pending-placeholder-icon { animation: none !important; }
  .pending-sparkle { opacity: 0.4; }
}

/* ── Detector-count chip on REAL narrative cards ────────── */
.narr-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  flex-wrap: wrap;
}
.narr-det-count {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  background: color-mix(in srgb, var(--narr-accent, var(--text-md)) 14%, var(--bg-input));
  border: 1px solid color-mix(in srgb, var(--narr-accent, var(--text-md)) 35%, var(--border));
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--text-hi);
  letter-spacing: .2px;
  line-height: 1.4;
}
.narr-det-count-icon {
  font-size: 12px !important;
  color: var(--narr-accent, var(--text-md));
}

/* Mobile: stack pending grid to one column at very narrow widths so the
   bigger cards don't get crushed below 360px effective width. */
@media (max-width: 720px) {
  .pending-grid {
    grid-template-columns: 1fr !important;
  }
  .narr-card.hero.pending { min-height: 200px; padding: 14px 14px; }
  .narr-card.hero.pending .narr-title       { font-size: 14px; }
  .narr-card.hero.pending .pending-readiness-num { font-size: 26px; }
}
