/* Factor Engine — refined minimalism, token-based theming, bright default
   (owner preference 2026-07-11). */

:root {
  --font-display: 'Fraunces', ui-serif, Georgia, serif;
  --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  /* ---- Bright (default) ---- */
  --bg: #FAFAF8;
  --bg-alt: #F2F1ED;
  --ink: #1A1A1A;
  --ink-soft: #555;
  --ink-faint: #888;
  --rule: #E5E3DE;
  --accent: #2A5D61;      /* teal — positive */
  --accent-rgb: 42, 93, 97;
  --accent-contrast: #FFFFFF; /* text on accent-filled surfaces (selected chips,
                                 primary buttons) — white on the dark teal;
                                 dark theme overrides to near-black since its
                                 accent is light (~7:1 contrast both ways) */
  --warn: #B0523E;        /* coral — negative */
  --warn-rgb: 176, 82, 62;
  --heat-0: #F5F3EE;
  --heat-5: #9EB8A4;
  /* Categorical series palette — CVD-validated set + ordering (dataviz
     validator: worst adjacent ΔE 24.2 on this surface). The ordering IS the
     colorblind-safety mechanism; don't reshuffle without re-validating. */
  --series-1: #2A78D6;   /* blue */
  --series-2: #1BAF7A;   /* aqua */
  --series-3: #EDA100;   /* yellow */
  --series-4: #008300;   /* green */
  --series-5: #4A3AA7;   /* violet */
  --series-6: #E34948;   /* red */
  --series-7: #E87BA4;   /* magenta */
  --series-8: #EB6834;   /* orange */
}

:root[data-theme="dark"] {
  --bg: #15171B;
  --bg-alt: #1D2025;
  --ink: #F1EFE9;
  --ink-soft: #B4B0A6;
  --ink-faint: #7B7870;
  --rule: #2B2E33;
  --accent: #57B3A9;
  --accent-rgb: 87, 179, 169;
  --accent-contrast: #10221f;
  --warn: #E3806A;
  --warn-rgb: 227, 128, 106;
  --heat-0: #23262B;
  --heat-5: #3F8A82;
  /* Same eight hues stepped for the dark surface (validated as a set;
     ≥3:1 contrast on #15171B). */
  --series-1: #3987E5;
  --series-2: #199E70;
  --series-3: #C98500;
  --series-4: #008300;
  --series-5: #9085E9;
  --series-6: #E66767;
  --series-7: #D55181;
  --series-8: #D95926;
}

/* No prefers-color-scheme auto-switch: the product default is bright
   regardless of OS setting. The header toggle (persisted in localStorage,
   see theme.js) is the only way to switch to :root[data-theme="dark"]. */

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 15px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  transition: background-color 0.2s ease, color 0.2s ease;
}

/* ---------- Topbar ---------- */
.topbar {
  display: flex;
  align-items: baseline;
  gap: 24px;
  padding: 20px 40px 16px;
  border-bottom: 1px solid var(--rule);
}
.topbar .spacer { flex: 1; }
.brand {
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink);
  text-decoration: none;
}
.crumbs {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-faint);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.crumbs a { color: var(--ink-soft); text-decoration: none; }
.crumbs a:hover { color: var(--ink); }
.crumbs .sep { margin: 0 8px; color: var(--ink-faint); }

.theme-toggle {
  align-self: center;
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 999px;
  color: var(--ink);
  width: 32px;
  height: 32px;
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}
.theme-toggle:hover { border-color: var(--ink-faint); }

/* ---------- Main ---------- */
main {
  max-width: 1400px;
  margin: 0 auto;
  padding: 40px;
}

h1 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 34px;
  letter-spacing: -0.02em;
  margin: 0 0 8px;
}
h2 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 20px;
  letter-spacing: -0.01em;
  margin: 32px 0 16px;
}
h3 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 16px;
  letter-spacing: -0.01em;
  margin: 24px 0 12px;
}
h2 .hint, h3 .hint, .identity-fact-label .hint {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 400;
  color: var(--ink-faint);
  text-transform: none;
  letter-spacing: 0;
}
.subtitle {
  color: var(--ink-soft);
  font-size: 15px;
  margin-bottom: 24px;
}
.ticker {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--ink-faint);
  font-weight: 400;
}

.view-links {
  display: flex;
  gap: 20px;
  font-family: var(--font-mono);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: 8px;
}
.view-links a { color: var(--ink-soft); text-decoration: none; }
.view-links a:hover { color: var(--accent); }

/* ---------- Region picker ---------- */
.region-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 12px;
}
.region-tile-card {
  display: flex;
  flex-direction: column;
}
.region-tile-strat {
  margin-top: 6px;
  align-self: flex-end;
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ink-faint);
  text-decoration: none;
}
.region-tile-strat:hover { color: var(--accent); }
.region-tile {
  padding: 20px 22px;
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 2px;
  cursor: pointer;
  transition: background-color 0.18s ease, border-color 0.18s ease;
  text-decoration: none;
  color: inherit;
  display: block;
}
.region-tile:hover {
  background: var(--bg-alt);
  border-color: var(--ink-faint);
}
.region-tile[aria-disabled="true"] {
  opacity: 0.4;
  cursor: not-allowed;
}
.region-tile .region {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-faint);
  margin-bottom: 4px;
}
.region-tile .label {
  font-size: 18px;
  font-weight: 500;
  letter-spacing: -0.01em;
}
.region-tile .meta {
  margin-top: 12px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-faint);
}

/* ---------- Loading / empty states ---------- */
.state {
  padding: 60px 0;
  text-align: center;
  color: var(--ink-faint);
  font-family: var(--font-mono);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}

/* ---------- Banners (loader errors / schema warnings) ---------- */
.fe-banners {
  position: fixed;
  top: 12px;
  right: 12px;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: 420px;
}
.fe-banner {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  border-radius: 3px;
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.4;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);
}
.fe-banner--error { background: var(--warn); color: #1A1A1A; }
.fe-banner--warn { background: var(--series-3, #D9B85C); color: #1A1A1A; }
.fe-banner__close {
  background: transparent;
  border: none;
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
  color: inherit;
  opacity: 0.7;
}
.fe-banner__close:hover { opacity: 1; }

/* ---------- Chips (view mode / column-set / metric pickers) ---------- */
.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 16px;
}
.chip {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 6px 12px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
}
.chip:hover { border-color: var(--ink-faint); color: var(--ink); }
.chip.active { background: var(--accent); border-color: var(--accent); color: var(--accent-contrast); }

.btn {
  font-family: var(--font-mono);
  font-size: 12px;
  padding: 7px 14px;
  border: 1px solid var(--rule);
  border-radius: 2px;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
}
.btn:hover { border-color: var(--ink-faint); background: var(--bg-alt); }

/* ---------- Screener toolbar ---------- */
.toolbar {
  display: flex;
  gap: 16px;
  align-items: center;
  padding: 16px 0;
  border-bottom: 1px solid var(--rule);
  margin-bottom: 0;
  flex-wrap: wrap;
}
.toolbar input, .toolbar select {
  font-family: var(--font-mono);
  font-size: 12px;
  padding: 6px 10px;
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 2px;
  color: var(--ink);
  outline: none;
}
.toolbar input:focus, .toolbar select:focus { border-color: var(--ink); }
.toolbar .spacer { flex: 1; }
.toolbar .count {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-faint);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

/* ---------- Data table ---------- */
.data-table-wrap {
  overflow-x: auto;
  max-height: 70vh;
  overflow-y: auto;
  border-bottom: 1px solid var(--rule);
}
table.data {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-mono);
  font-size: 12px;
  margin-top: 8px;
}
table.data thead th {
  text-align: right;
  padding: 10px 12px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-size: 10px;
  color: var(--ink-soft);
  border-bottom: 1px solid var(--rule);
  background: var(--bg);
  position: sticky;
  top: 0;
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  z-index: 1;
}
table.data thead th:first-child,
table.data thead th.text { text-align: left; }
table.data thead th:hover { color: var(--ink); }
table.data thead th .sort-ind {
  display: inline-block;
  margin-left: 4px;
  color: var(--ink-faint);
}
table.data thead th.sorted .sort-ind { color: var(--ink); }

/* ---------- Column header filter affordance ---------- */
.th-flex {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
table.data thead th.text .th-flex { justify-content: flex-start; }
.th-label { display: inline-flex; align-items: center; }
.th-filter-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  padding: 0;
  border: none;
  border-radius: 2px;
  background: transparent;
  color: var(--ink-faint);
  cursor: pointer;
}
.th-filter-btn:hover { color: var(--ink); background: var(--bg-alt); }
.th-filter-btn.active { color: var(--accent); }

/* ---------- Excel-style per-column filter panel ---------- */
.filter-panel {
  position: fixed;
  z-index: 2000;
  min-width: 230px;
  max-width: 320px;
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: 3px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
  padding: 10px;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink);
}
:root[data-theme="dark"] .filter-panel { box-shadow: 0 8px 24px rgba(0, 0, 0, 0.55); }
.filter-panel-search { margin-bottom: 8px; }
.filter-panel-search input,
.filter-panel-cond input,
.filter-panel-cond select {
  width: 100%;
  box-sizing: border-box;
  font-family: var(--font-mono);
  font-size: 12px;
  padding: 5px 8px;
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 2px;
  color: var(--ink);
  outline: none;
}
.filter-panel-search input:focus,
.filter-panel-cond input:focus,
.filter-panel-cond select:focus { border-color: var(--ink); }
.filter-panel-quick { display: flex; gap: 6px; margin-bottom: 8px; }
.filter-panel-list {
  max-height: 220px;
  overflow-y: auto;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  padding: 4px 2px;
}
.filter-panel-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 2px;
  cursor: pointer;
}
.filter-panel-row input[type="checkbox"] { accent-color: var(--accent); cursor: pointer; flex: 0 0 auto; }
.filter-panel-row .fp-label {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.filter-panel-count { color: var(--ink-faint); flex: 0 0 auto; }
.filter-panel-empty { color: var(--ink-faint); padding: 8px 2px; }
.filter-panel-cond { display: flex; gap: 6px; margin-bottom: 6px; }
.filter-panel-cond select { flex: 0 0 58px; }
.filter-panel-and {
  text-align: center;
  color: var(--ink-faint);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: 6px;
}
.filter-panel-presets { display: flex; gap: 6px; margin-bottom: 8px; }
.filter-panel-blanks {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 8px 0 2px;
  cursor: pointer;
  color: var(--ink-soft);
}
.filter-panel-blanks input { accent-color: var(--accent); cursor: pointer; }
.filter-panel-actions { display: flex; gap: 6px; justify-content: flex-end; margin-top: 8px; }
.btn-mini {
  font-family: var(--font-mono);
  font-size: 11px;
  padding: 4px 9px;
  border: 1px solid var(--rule);
  border-radius: 2px;
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
}
.btn-mini:hover { border-color: var(--ink-faint); color: var(--ink); }
.btn-mini--primary { background: var(--accent); border-color: var(--accent); color: var(--accent-contrast); }
.btn-mini--primary:hover { opacity: 0.9; color: var(--accent-contrast); }

/* ---------- Active filter chips ---------- */
.filter-chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  padding: 12px 0 0;
}
.filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  padding: 5px 6px 5px 10px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--bg-alt);
  color: var(--ink);
}
.filter-chip-x {
  background: transparent;
  border: none;
  cursor: pointer;
  color: var(--ink-faint);
  font-size: 13px;
  line-height: 1;
  padding: 0 2px;
}
.filter-chip-x:hover { color: var(--warn); }
.filter-clear-all { margin-left: 2px; }

table.data tbody td {
  padding: 9px 12px;
  border-bottom: 1px solid var(--rule);
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
table.data tbody td:first-child,
table.data tbody td.text {
  text-align: left;
  font-family: var(--font-display);
  font-size: 13px;
}
table.data tbody tr { cursor: pointer; }
/* Rows with no drill-in destination — e.g. the benchmark row in Pulse's factor
   table, which has no holdings page. Same cursor:default idiom as
   thead th.unsortable. The :hover band is deliberately kept: it's a row-tracking
   reading aid, not solely an interactivity cue. */
table.data tbody tr.row-inert { cursor: default; }
table.data tbody tr:hover td { background: var(--bg-alt); }
.num-pos { color: var(--accent); }
.num-neg { color: var(--warn); }
.num-na  { color: var(--ink-faint); }

/* ---------- Percentile chips (label-driven; must look distinct) ---------- */
.pct-chip {
  display: inline-block;
  font-variant-numeric: tabular-nums;
}
.pct-chip--rank {
  padding: 1px 7px;
  border-radius: 999px;
  background: rgba(var(--accent-rgb), 0.2);
  color: var(--accent);
  font-weight: 500;
}
.pct-chip--hist {
  text-decoration: underline dotted;
  text-underline-offset: 3px;
  color: var(--ink);
}

/* ---------- Stock header ---------- */
.stock-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 20px;
  padding-bottom: 20px;
  border-bottom: 1px solid var(--rule);
  margin-bottom: 8px;
}
.stat-row { display: flex; gap: 20px; }
.stat { text-align: right; }
.stat-label {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-faint);
  margin-bottom: 4px;
}
.stat-value {
  font-family: var(--font-mono);
  font-size: 18px;
  font-variant-numeric: tabular-nums;
}

/* ---------- Stock hero band (owner-approved layout, 2026-07-22) ----------
   Two-column grid: left = stock-header + "What changed — visuals"; right
   (the corner) = an identity card (Factor profile radar + a few identity
   facts). minmax() on the side column keeps it from getting squeezed
   arbitrarily narrow on medium widths while the main column absorbs any
   extra space; collapses to one column (radar card falls below the header,
   above the visuals) under ~900px. No fixed heights on the row itself, so
   the radar box is never clipped regardless of how tall the left column's
   visuals section grows. */
.stock-hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(260px, 320px);
  gap: 32px;
  align-items: start;
}
.stock-hero-main { min-width: 0; }
.stock-hero-side { min-width: 0; }
@media (max-width: 900px) {
  .stock-hero { grid-template-columns: 1fr; }
  .stock-hero-side { order: -1; }
}

.identity-card {
  border: 1px solid var(--rule);
  border-radius: 6px;
  padding: 16px;
  background: var(--bg-alt);
}
.identity-card h2 { margin-top: 0; }
.identity-card .chart-box { height: 300px; }
.identity-facts {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--rule);
}
.identity-fact {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
}
.identity-fact-label {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-faint);
}
.identity-fact-value {
  font-family: var(--font-mono);
  font-size: 14px;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

/* Standout traits (owner request, 2026-07-22) — two chip rows under the
   identity card's facts, built from the same oriented dimension values that
   feed the Factor profile radar. Reuses .chip/.num-pos/.num-neg wholesale;
   only the row layout + a non-interactive chip variant are new (these chips
   aren't buttons — no click handler — so .chip's pointer cursor/hover-invert
   are overridden). */
.standout-traits {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--rule);
}
.standout-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
}
.standout-row-label {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-faint);
  margin-right: 2px;
}
.trait-chip {
  padding: 3px 9px;
  font-size: 10px;
  text-transform: none;
  letter-spacing: 0;
  cursor: default;
}
.trait-chip.num-pos { border-color: var(--accent); }
.trait-chip.num-neg { border-color: var(--warn); }
.trait-chip.num-pos:hover { border-color: var(--accent); color: var(--accent); }
.trait-chip.num-neg:hover { border-color: var(--warn); color: var(--warn); }

/* "vs sector" radar toggle (owner request, 2026-07-22) — reuses .chip-row/
   .chip/.chip--disabled wholesale (same disabled-chip idiom as landing.js's
   Δ6m horizon chip); only trims the row's default 16px bottom margin so the
   toggle sits snug between the "Factor profile" h2 and its hint line. */
.identity-card .radar-scope-row { margin-bottom: 8px; }

/* Rich/cheap valuation strip (owner request, 2026-07-22; extended to all
   nine FE_UTIL.fund fundamentals, grouped Valuation/Growth/Returns on
   capital) — a second .identity-card under the Factor profile card: one row
   per metric, a slim own-history (p5-p95) track with a dot at today's
   reading, and the 10y percentile as colored text (direction — low or high
   percentile is "green" — varies per metric, see RICH_CHEAP_LOW_GOOD in
   stock.js). DOM bars, not SVG/ECharts — colors are plain CSS custom
   properties so a theme toggle repaints for free, same idiom as .fe-spark's
   inline `var(--accent)` strokes. */
.richcheap-card { margin-top: 16px; }
/* Group subhead divider between Valuation/Growth/Returns-on-capital rows —
   a lighter idiom than table.data's .group-row (this card is a div-row list,
   not a table), matching .standout-row-label's typography. */
.richcheap-group-head {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-faint);
  margin-top: 12px;
  padding-bottom: 4px;
}
.richcheap-group-head:first-child { margin-top: 0; }
.richcheap-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 0;
}
.richcheap-row + .richcheap-row { border-top: 1px solid var(--rule); }
.richcheap-label {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-soft);
  flex: 0 0 80px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.richcheap-track-wrap { flex: 1 1 auto; min-width: 0; }
.richcheap-track {
  position: relative;
  height: 4px;
  border-radius: 2px;
  background: var(--rule);
}
.richcheap-dot {
  position: absolute;
  top: 50%;
  width: 8px;
  height: 8px;
  margin-left: -4px;
  border-radius: 50%;
  background: var(--accent);
  border: 1.5px solid var(--bg-alt);
  transform: translateY(-50%);
}
.richcheap-row--na .richcheap-track { opacity: 0.4; }
.richcheap-pct {
  font-family: var(--font-mono);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  flex: 0 0 38px;
  text-align: right;
}

/* Stock detail — "What changed?" thesis-delta scorecard (owner request,
   2026-07-19). Reuses .data-table-wrap/table.data/.hint-line/.num-pos/
   .num-neg wholesale; the one new bit is a bold subheader row dividing the
   Expectations/Growth/Profitability/Valuation/Market blocks — table.data has
   a `thead tr.group-row` (grouped header band, WAVE-3) but no tbody-level
   equivalent, so this is new, scoped to tbody to avoid any clash, and kept
   generic enough for other table.data bodies to reuse later. */
table.data tbody tr.group-row td {
  background: var(--bg-alt);
  font-weight: 600;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
  cursor: default;
}
table.data tbody tr.group-row:hover td { background: var(--bg-alt); }

/* Generic pinned summary row (e.g. pulse.js's "what changed" sub-sections:
   the Index row atop the sector table, the Benchmark row atop the factor
   table) — a subtle accent tint, distinct from an ordinary data row but not
   tied to the GLOBAL-specific styling below. */
tr.row-pinned td { background: rgba(var(--accent-rgb), 0.05); }
tr.row-pinned:hover td { background: rgba(var(--accent-rgb), 0.09); }

/* ---------- Charts ---------- */
.chart-box {
  width: 100%;
  height: 340px;
  margin-bottom: 8px;
}
.chart-box--tall { height: 520px; }
.chart-grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 32px;
}
@media (max-width: 900px) {
  .chart-grid-2 { grid-template-columns: 1fr; }
}

/* ---------- Compare / factors pickers ---------- */
.compare-pickers, .axis-pickers {
  display: flex;
  gap: 16px;
  align-items: center;
  margin-bottom: 16px;
  flex-wrap: wrap;
}
.compare-pickers input, .compare-pickers select, .axis-pickers select {
  font-family: var(--font-mono);
  font-size: 12px;
  padding: 7px 10px;
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 2px;
  color: var(--ink);
  min-width: 200px;
}
.axis-pickers label {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-faint);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  display: flex;
  align-items: center;
  gap: 8px;
}
.axis-pickers select { min-width: 160px; }

/* ---------- Risk / ideas panel ---------- */
.risk-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
  margin-bottom: 8px;
}
@media (max-width: 1100px) {
  .risk-grid { grid-template-columns: 1fr; }
}
.risk-card h2 { margin-top: 0; }
.risk-row {
  display: block;
  padding: 10px 0;
  border-bottom: 1px solid var(--rule);
  text-decoration: none;
  color: inherit;
}
.risk-row:hover .risk-row-name { color: var(--accent); }
.risk-row-name { font-size: 14px; margin-bottom: 4px; }
.risk-row-extras { display: flex; gap: 10px; flex-wrap: wrap; }
.risk-extra {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-soft);
}

/* ---------- Strategies view ---------- */
.strat-layout {
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: 32px;
  align-items: start;
}
@media (max-width: 900px) {
  .strat-layout { grid-template-columns: 1fr; }
}
.strat-rail {
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: 16px;
  position: sticky;
  top: 16px;
}
.strat-rail-section { margin-bottom: 18px; }
.strat-rail-section:last-child { margin-bottom: 0; }
.strat-rail-title {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-faint);
  margin-bottom: 8px;
}
.strat-check {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  padding: 5px 0;
  cursor: pointer;
  color: var(--ink);
}
.strat-check input { accent-color: var(--accent); cursor: pointer; }
.strat-toolbar {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 4px;
}
.strat-toggle {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-soft);
  display: flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
}
.strat-toggle input { accent-color: var(--accent); cursor: pointer; }
.tc-note {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--warn);
  padding: 4px 10px;
  border: 1px solid var(--rule);
  border-radius: 999px;
}

/* ============================================================
   WAVE-1 additions — cohorts / structure views + FX saved screens
   (agent B). Reuses .chip-row/.chip, .strat-layout/.strat-rail*,
   .data-table-wrap/table.data, .btn-mini(--primary) wherever the
   existing component already fit; only genuinely new bits below.
   ============================================================ */

/* Landing tile quicklinks row (Strategies / Cohorts / Structure) —
   .region-tile-strat keeps its font styling; this wrapper takes over
   the flex-row + bottom alignment so multiple links sit side by side. */
.region-tile-links {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  align-self: flex-end;
  margin-top: 6px;
}
.region-tile-links .region-tile-strat {
  margin-top: 0;
  align-self: auto;
}

/* Small caption label used ahead of the FX saved-screen buttons in the
   screener toolbar. */
.toolbar-label {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-faint);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  white-space: nowrap;
}

/* ---------- Strategies — empty state ---------- */
.strategies-empty code {
  display: inline-block;
  margin-top: 12px;
  padding: 8px 14px;
  background: var(--bg-alt);
  border: 1px solid var(--rule);
  border-radius: 2px;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink);
  text-transform: none;
  letter-spacing: 0;
}

/* ============================================================
   WAVE-2 additions (agents A + C) — strategies tab strip (Annual
   Returns / Valuation Drift / Return Drivers panels), the driver-entity
   <select>, and the stock-detail own-history sparkline. cohorts.js also
   reuses .strat-main for its rail+content layout, so keep it generic
   (not strategies-specific).
   ============================================================ */

/* .strat-layout's right-hand grid track (see "Strategies view" above) —
   min-width: 0 so its charts can shrink inside the fixed 220px rail
   track instead of overflowing the grid. */
.strat-main { min-width: 0; }

/* Underlined tab strip above the strategies panels. */
.strat-tabs {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  border-bottom: 1px solid var(--rule);
  margin-bottom: 20px;
}
.strat-tab {
  font-family: var(--font-mono);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 10px 16px;
  margin-bottom: -1px;
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  color: var(--ink-soft);
  cursor: pointer;
}
.strat-tab:hover { color: var(--ink); }
.strat-tab.active { color: var(--ink); border-bottom-color: var(--accent); }

/* Each tab's content area. Panels are toggled via the `hidden` attribute
   rather than a display class, so this rule only needs to supply spacing. */
.strat-panel { margin-top: 4px; }

/* Return Drivers entity picker — same look as .compare-pickers/.axis-pickers
   selects, reused here since strat-toolbar isn't wrapped in either. */
.strat-select {
  font-family: var(--font-mono);
  font-size: 12px;
  padding: 7px 10px;
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 2px;
  color: var(--ink);
  min-width: 200px;
}
.strat-select:focus { border-color: var(--ink); }

/* Stock detail — compact own-history sparkline beneath the metric-vs-sector
   chart. .stk-spark overrides .chart-box's default 340px height; the label
   above it explains the green/red shading convention. */
.stk-spark-block { margin-bottom: 24px; }
.stk-spark-label {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-faint);
  margin-bottom: 6px;
}
.chart-box.stk-spark { height: 120px; margin-bottom: 0; }

/* Stock detail — "What changed — visuals" fundamentals sparkline grid (owner
   request, 2026-07-21). Reuses .chip-row/.chip (shared horizon toggle),
   .chart-box/.state (return bridge + factor dumbbells panels), .num-pos/
   .num-neg/.num-na and .fe-spark (FE_UTIL.sparklineSVG) wholesale — only the
   grid/tile chrome below is new. */
.spark-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
  margin-bottom: 8px;
}
@media (max-width: 760px) {
  .spark-grid { grid-template-columns: 1fr; }
}
.spark-cell {
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: 10px 12px;
}
.spark-cell--empty { display: flex; align-items: center; justify-content: space-between; }
.spark-cell-label {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ink-faint);
  margin-bottom: 4px;
}
.spark-cell-value {
  font-family: var(--font-mono);
  font-size: 14px;
  font-variant-numeric: tabular-nums;
  margin-bottom: 4px;
}
.spark-cell-nospark {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-faint);
  margin: 8px 0 0;
}

/* ============================================================
   WAVE-3 additions — screener Excel parity: 'Full screen' column set,
   row virtualization, frozen ID/Name panes, grouped header band, density
   modes, and percentile conditional-formatting shading. All scoped to
   #table-wrap (the screener's own .data-table-wrap) so cohorts.js's
   reuse of the same table.data/.data-table-wrap component elsewhere is
   untouched.
   ============================================================ */

/* ---------- Grouped header band (2nd row above column names) ---------- */
table.data thead tr.group-row th {
  height: 22px;
  padding: 3px 12px;
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.1em;
  color: var(--ink-faint);
  text-align: left;
  cursor: default;
  border-bottom: 1px solid var(--rule);
}
/* Column-name row sits below the group band; both rows are sticky (see
   generic `table.data thead th { position:sticky; top:0 }` above), so the
   column row needs its own top offset equal to the group row's height. */
table.data thead tr.col-row th { top: 23px; }

/* ---------- Frozen panes: ID + Name stay pinned while scrolling
   horizontally. Fixed pixel widths keep the sticky `left` offsets (and the
   table's auto column sizing) consistent between the header and body. ---- */
table.data th.col-frozen-1, table.data td.col-frozen-1 {
  position: sticky;
  left: 0;
  z-index: 2;
  background: var(--bg);
  width: 110px;
  min-width: 110px;
  max-width: 110px;
}
table.data th.col-frozen-2, table.data td.col-frozen-2 {
  position: sticky;
  left: 110px;
  z-index: 2;
  background: var(--bg);
  width: 190px;
  min-width: 190px;
  max-width: 190px;
}
/* Header frozen cells (both the group band's merged corner cell and the
   column row's ID/Name cells) must sit above scrolled body content AND
   above plain (non-frozen) header cells at the top+left intersection. */
table.data thead th.col-frozen-1,
table.data thead th.col-frozen-2,
table.data thead th.group-frozen {
  z-index: 3;
}
table.data thead th.group-frozen {
  position: sticky;
  left: 0;
  background: var(--bg);
}

/* ---------- Density modes (Compact default, Comfortable alternative) ---- */
#table-wrap.density-compact table.data tbody td { padding: 4px 8px; }
#table-wrap.density-compact table.data tbody tr.data-row { height: 26px; }
#table-wrap.density-comfortable table.data tbody td { padding: 9px 12px; }
#table-wrap.density-comfortable table.data tbody tr.data-row { height: 34px; }

/* Subtle zebra striping keyed to each row's position in the full filtered
   result set (not DOM position), so it doesn't flicker as the virtualized
   window scrolls. Higher specificity than .col-frozen-*'s own background so
   frozen cells stay in sync with the stripe instead of looking cut out. */
#table-wrap tbody tr.row-alt td { background: var(--bg-alt); }

/* ---------- Percentile / rank conditional formatting ---------- */
/* Neutralize the shared .pct-chip--rank pill's own accent tint + colored
   text inside the screener only (cohorts.js reuses the same class on a
   different table — see .pct-chip--rank in the base stylesheet — and must
   keep its own look). The per-cell background ramp below (applied inline
   via FE_UTIL.rankShadeStyle) carries the color now; text stays on an ink
   token so it reads clearly against either tint. */
#table-wrap .pct-chip--rank { background: transparent; color: var(--ink); }
.cf-cell { text-align: right; }

/* ============================================================
   WAVE-4 additions — unified Compare series builder, stock.js metric-pair
   preset chips, and the new Pulse view. Reuses .chip-row/.chip, .btn,
   .compare-pickers/.axis-pickers, .data-table-wrap/table.data, .cf-cell and
   FE_UTIL.rankShadeStyle wherever the existing component already fit; only
   genuinely new bits below.
   ============================================================ */

/* ---------- Compare: series builder ---------- */
.compare-add-row {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.compare-add-row input {
  font-family: var(--font-mono);
  font-size: 12px;
  padding: 7px 10px;
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 2px;
  color: var(--ink);
  min-width: 220px;
  flex: 1 1 220px;
}
.index-median-toggle {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-soft);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  display: flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
}
.index-median-toggle input { accent-color: var(--accent); cursor: pointer; }
.index-median-toggle.is-disabled { opacity: 0.45; cursor: default; }
.index-median-toggle.is-disabled input { cursor: default; }

.series-chip-row { margin-bottom: 6px; }
.series-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: default;
}
.series-chip:hover { border-color: var(--rule); color: var(--ink-soft); } /* not a mode toggle — undo .chip:hover */
.series-chip__kind {
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.06em;
  opacity: 0.7;
}
.series-chip--sector .series-chip__kind { color: var(--accent); }
.series-chip--stock .series-chip__kind { color: var(--ink-faint); }
.series-chip--index-median .series-chip__kind { color: var(--warn); }
.series-chip__remove {
  border: none;
  background: transparent;
  color: inherit;
  opacity: 0.6;
  font-size: 13px;
  line-height: 1;
  padding: 0 0 0 2px;
  cursor: pointer;
}
.series-chip__remove:hover { opacity: 1; }

.hint-line {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-faint);
  margin: -8px 0 16px;
}

/* Compact stat strip — e.g. Structure view's terminal-growth index/dist
   summary between a toolbar and its table. Same voice as .hint-line, stacked
   as multiple lines instead of one. */
.stat-strip {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-faint);
  line-height: 1.7;
  padding: 10px 0 14px;
}

/* ---------- Pulse view ---------- */
#pulse-sector-panel, #pulse-factor-panel { margin-bottom: 8px; }
#pulse-factor-panel .chart-box { height: 260px; margin-bottom: 16px; }

/* ============================================================
   Terminal growth reference panel (Structure view, sectors.js v4
   `terminal` block). Pins the (0,'Index') reference row visually at
   the top of #tg-table regardless of the active sort column.
   ============================================================ */
table.data tr.tg-index-row td {
  background: var(--bg-alt);
  font-weight: 600;
  border-bottom: 1px solid var(--rule);
}
table.data tr.tg-index-row:hover td { background: var(--bg-alt); }

/* Growth-map scatter, sits between the stat strip and #tg-table. Slightly
   shorter than .chart-box--tall so the panel keeps table + chart both above
   the fold on a typical laptop viewport. */
.chart-box--growth-map { height: 420px; }

/* Click-a-dot -> scroll-and-flash the matching #tg-table row (data-group
   attribute set in structure.js). Runs once (~1.2s) then structure.js
   removes the class; the accent outline is drawn per-cell via inset
   box-shadow since table.data uses border-collapse (an outline on <tr>
   itself won't paint reliably across browsers on a collapsed table). */
@keyframes tg-row-flash {
  0%, 100% { box-shadow: none; background-color: transparent; }
  12%, 78% { box-shadow: inset 0 0 0 2px var(--accent); background-color: rgba(var(--accent-rgb), 0.16); }
}
table.data tr.tg-row-flash td { animation: tg-row-flash 1.2s ease-out; }

/* ============================================================
   WAVE-5 additions — Pulse as the single-index home, data-rich landing
   tiles, screener workbench trim (owner decisions, 2026-07-13). Reuses
   .region-tile-card/.region-tile, .num-pos/.num-neg, .hint, .state,
   .chip-row wherever the existing component already fit; only genuinely
   new bits below.
   ============================================================ */

/* ---------- Shared inline sparkline (landing tiles + Pulse header) ---------- */
.fe-spark { display: block; overflow: visible; }

/* ---------- Landing tile: data-rich body (spark + returns + sectors + chip) ---------- */
.tile-body { margin-top: 12px; }
.tile-spark { margin-bottom: 8px; }
.tile-line {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-soft);
  line-height: 1.6;
}
.tile-sectors { color: var(--ink-faint); }
.tile-chip {
  display: inline-block;
  margin-top: 8px;
  padding: 3px 9px;
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  text-decoration: none;
}
.tile-chip--accent { background: rgba(var(--accent-rgb), 0.16); color: var(--accent); }
.tile-chip--warn { background: rgba(var(--warn-rgb), 0.16); color: var(--warn); }

/* ---------- Pulse: index header (spark + trailing returns + meta line) ---------- */
.pulse-header {
  display: flex;
  align-items: center;
  gap: 24px;
  padding: 16px 0 20px;
  border-bottom: 1px solid var(--rule);
  margin-bottom: 20px;
  flex-wrap: wrap;
}
.phdr-spark-wrap { flex: 0 0 auto; }
.phdr-body { flex: 1 1 auto; min-width: 240px; }
.phdr-rets { display: flex; gap: 20px; flex-wrap: wrap; }
.phdr-ret {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--ink-faint);
}
.phdr-meta {
  margin-top: 8px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-faint);
}

/* ---------- Pulse: Ideas triggers row (replaces the old screener movers strip) ---------- */
.ideas-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
  margin-bottom: 12px;
}
@media (max-width: 900px) {
  .ideas-cols { grid-template-columns: 1fr; }
}
.ideas-col-title {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-faint);
  margin-bottom: 8px;
}
.idea-card {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--rule);
  text-decoration: none;
  color: inherit;
}
.idea-card:hover .idea-card-name { color: var(--accent); }
.idea-card-name {
  font-size: 13px;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.idea-card-sector {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--ink-faint);
  flex: 0 0 auto;
}
.idea-card-chg {
  font-family: var(--font-mono);
  font-size: 11px;
  flex: 0 0 auto;
  white-space: nowrap;
}
.ideas-chip-row { display: flex; gap: 10px; margin-bottom: 24px; }

/* ============================================================
   Cross-market compare (#/xcompare). Reuses .chip-row/.chip, .btn/
   .btn-mini, .compare-add-row/.series-chip*/.hint-line (from the WAVE-4
   block above), .data-table-wrap/table.data and FE_UTIL.rankShadeStyle
   wherever the existing component already fit; only genuinely new bits
   below. One small index-code badge (.index-chip) is shared across the
   suggestion dropdown, series chips and the peer table header.
   ============================================================ */
.landing-view-links { margin: -8px 0 20px; }

.index-chip {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 1px 6px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  color: var(--ink-soft);
}

/* Sector-mode add flow (#/xcompare): Index -> GICS level -> Group, 3
   labeled steps stacked vertically — replaces the old flat free-text
   sector search (see xcompare.js's renderSectorAddUI). */
.xc-sector-step { margin-bottom: 14px; }
.xc-sector-step:last-child { margin-bottom: 0; }
.xc-sector-step-label {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-faint);
  margin-bottom: 8px;
}
#xc-sector-picker-row select {
  font-family: var(--font-mono);
  font-size: 12px;
  padding: 7px 10px;
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 2px;
  color: var(--ink);
  min-width: 220px;
}

.xc-suggestions {
  display: flex;
  flex-direction: column;
  max-height: 260px;
  overflow-y: auto;
  border: 1px solid var(--rule);
  border-radius: 2px;
  margin: -8px 0 12px;
  background: var(--bg-alt);
}
.xc-suggestion {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  text-align: left;
  padding: 7px 10px;
  border: none;
  border-bottom: 1px solid var(--rule);
  background: transparent;
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: 12px;
  cursor: pointer;
}
.xc-suggestion:last-child { border-bottom: none; }
.xc-suggestion:hover { background: var(--bg); color: var(--accent); }
.xc-suggestion-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.xc-suggestion-id { flex: 0 0 auto; color: var(--ink-faint); font-size: 11px; }

.series-chip--pending { opacity: 0.6; }
.series-chip--failed { border-color: var(--warn); }
.series-chip__status {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ink-faint);
}
.series-chip__status--failed { color: var(--warn); }
.series-chip__asof {
  font-size: 9px;
  color: var(--ink-faint);
  white-space: nowrap;
}

.metric-ccy-badge {
  display: inline-block;
  margin-left: 6px;
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--warn);
  border: 1px solid var(--warn);
  border-radius: 999px;
  padding: 1px 5px;
  vertical-align: middle;
}

.peer-table-wrap { max-height: none; }
table.peer-table thead th { text-align: center; vertical-align: bottom; }
table.peer-table thead th.text { text-align: left; }
.peer-col-name { font-size: 12px; font-weight: 600; color: var(--ink); }
.peer-col-link { color: inherit; text-decoration: none; }
.peer-col-link:hover { color: var(--accent); text-decoration: underline; }
.peer-col-meta { margin-top: 2px; }
.peer-col-asof { margin-top: 2px; font-family: var(--font-mono); font-size: 9px; color: var(--ink-faint); }
table.peer-table tbody td { text-align: center; }
table.peer-table tbody td.text { text-align: left; }

.xc-set-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 0;
  border-bottom: 1px solid var(--rule);
  font-family: var(--font-mono);
  font-size: 12px;
}
.xc-set-name { flex: 1 1 auto; min-width: 0; }
.xc-set-meta { color: var(--ink-faint); font-size: 11px; flex: 0 0 auto; }
.xc-set-builtin-badge {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--accent);
  border: 1px solid var(--accent);
  border-radius: 999px;
  padding: 1px 6px;
  margin-left: 6px;
}

/* ============================================================
   WAVE-6 — Landing v2: tile grid replaced by the Index Monitor table +
   Factor x Region matrix + Global Ideas strip (owner decision 2026-07-13,
   "tiles die, table wins"). Reuses table.data/.data-table-wrap, .chip-row/
   .chip, .num-pos/.num-neg/.num-na, .state, .hint-line, .idea-card/
   .idea-card-name/.idea-card-sector/.idea-card-chg/.ideas-cols/.ideas-col/
   .ideas-col-title, .fe-spark wherever the existing component already fit;
   only genuinely new bits below.
   ============================================================ */

/* ---------- Index Monitor / Matrix shared identity cell (1st column) ---- */
.index-cell-label { font-size: 13px; }
.index-cell-meta {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--ink-faint);
  margin-top: 2px;
  white-space: nowrap;
}
.index-cell-sector { white-space: normal; }
.index-cell-refresh { font-family: var(--font-mono); font-size: 11px; color: var(--ink-soft); }

/* ---------- Index Monitor table ---------- */
.monitor-table-wrap { max-height: none; }
.monitor-spark { display: block; }
table.monitor-table thead th.unsortable { cursor: default; }
table.monitor-table thead th.unsortable:hover { color: var(--ink-soft); }

/* ---------- Fundamentals — what changed (2026-07-20) ---------------------
   Reuses table.data/.data-table-wrap/.monitor-table-wrap (row styling, GLOBAL
   pin, scroll behavior) and the screener's grouped-header band (.group-row/
   .group-th/.col-row — see screen.js) for the Valuation/Growth/Returns-on-
   capital column groups; no new table chrome needed. */
.fund-table-wrap { max-height: none; }

/* ---------- Shared "what changed" table (FE_UTIL.fund.renderWhatChangedTable,
   2026-07-21 unification round) — one renderer for the index/sector/factor
   "what changed" surfaces. Legend line spells out the Return attribution
   bar's fixed hue-per-driver mapping (P/E = accent, Earnings = warn, always
   — never opacity variants, see attribBarSVG). "No history" rows (a preset
   with no return data over the window) render dimmed instead of a
   live-looking fundamental next to an em-dash return. */
.fund-legend {
  display: flex;
  align-items: center;
  gap: 4px;
}
.fund-legend-swatch {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 2px;
  margin-left: 10px;
}
.fund-legend-swatch:first-child { margin-left: 0; }
.fund-legend-swatch--accent { background: var(--accent); }
.fund-legend-swatch--warn { background: var(--warn); }
tr.fund-row-dim td { color: var(--ink-faint); font-style: italic; }
tr.fund-row-dim:hover td { background: var(--bg-alt); }

/* Selected-row highlight for a "what changed" table whose rows drive an
   adjacent visual panel instead of navigating away (pulse.js's sector panel
   click-to-select, 2026-07-21) — a persistent tint (not just :hover) so the
   panel's current selection stays legible after the pointer moves off.
   Also used by sector.js's industry scoreboard to mark the sub-industry a
   deep link arrived focused on. Selector deliberately NOT scoped to
   .monitor-row: it was, and the sector page's rows are plain table.data rows,
   so the class applied and tested green while painting nothing at all. */
tr.wc-vis-selected td { background: rgba(var(--accent-rgb), 0.10); }

/* ---------- Landing "What changed — across markets" small-multiples grid
   (owner request, 2026-07-21) — auto-fit ~5x2 for the usual 10 index tiles,
   collapsing to fewer columns on narrower viewports without a fixed
   breakpoint list. Cards are plain links (href carries the navigation, no
   click JS needed) styled to read as tiles, not table rows. */
.wc-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px;
  margin-bottom: 8px;
}
.wc-grid-card {
  display: block;
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: 10px 12px;
  text-decoration: none;
  color: inherit;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.wc-grid-card:hover { border-color: var(--ink-faint); background: var(--bg-alt); }
.wc-grid-card-label {
  font-size: 12.5px;
  font-weight: 600;
  margin-bottom: 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.wc-grid-card-tr {
  font-family: var(--font-mono);
  font-size: 16px;
  font-variant-numeric: tabular-nums;
  margin-bottom: 6px;
}
.wc-grid-card-bridge { margin-bottom: 6px; line-height: 0; }
.wc-grid-card-bridge--na {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--ink-faint);
  line-height: normal;
}
.wc-grid-card-callout {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-soft);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.chip.chip--disabled { opacity: 0.4; cursor: not-allowed; }
.chip.chip--disabled:hover { color: inherit; border-color: var(--rule); }

/* ---------- Unavailable indices — dim, non-interactive strip ---------- */
.unavailable-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 12px 0 4px;
  color: var(--ink-faint);
}
.unavailable-title {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.unavailable-chip {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-faint);
  padding: 3px 9px;
  border: 1px solid var(--rule);
  border-radius: 999px;
}
.unavailable-code { color: var(--ink-faint); }

/* ---------- Factor x Region matrix ---------- */
/* Edge-fade scroll affordance: on narrow windows the matrix's rightmost
   columns (Stability, Benchmark) clip behind overflow-x scroll with no
   visual hint (macOS hides scrollbars until touched) — these scroll-linked
   gradient shadows (background-attachment local vs scroll) appear exactly
   when content is cut off on that side, in both themes via --bg/--rule. */
.matrix-table-wrap {
  max-height: none; margin-bottom: 4px;
  background:
    linear-gradient(90deg, var(--bg) 30%, transparent) left / 32px 100%,
    linear-gradient(270deg, var(--bg) 30%, transparent) right / 32px 100%,
    linear-gradient(90deg, var(--rule), transparent) left / 12px 100%,
    linear-gradient(270deg, var(--rule), transparent) right / 12px 100%;
  background-repeat: no-repeat;
  background-attachment: local, local, scroll, scroll;
}
table.matrix-table { background: transparent; }
table.matrix-table thead th { cursor: default; text-align: center; }
table.matrix-table thead th:hover { color: var(--ink-soft); }
table.matrix-table thead th.text { text-align: left; }
table.matrix-table tbody td.matrix-cell { text-align: center; }
.matrix-cell--bench { border-left: 1px solid var(--rule); }
.matrix-cell--blank { font-family: var(--font-mono); }

/* ---------- Global Ideas strip — pooled cross-index idea-card variant --- */
.global-idea-card .idea-card-main {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.idea-card-code {
  font-weight: 600;
  color: var(--accent);
  margin-right: 2px;
}

/* ============================================================
   GLOBAL virtual universe (factor_engine.core.global_universe) — 9-index
   union/dedupe surfaced across the landing Index Monitor + matrix and the
   screener. Reuses table.data/.data-table-wrap, .hint-line, .chip-row/.chip,
   .unavailable-chip's pill styling wherever it already fit; only genuinely
   new bits below.
   ============================================================ */

/* ---------- Landing: GLOBAL pinned row — visually distinct, not just first --- */
tr.monitor-row--global,
tr.matrix-row--global {
  background: rgba(var(--accent-rgb), 0.05);
}
tr.monitor-row--global:hover td,
tr.matrix-row--global:hover td {
  background: rgba(var(--accent-rgb), 0.09);
}
.global-row-badge {
  font-family: var(--font-mono);
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--accent);
  border: 1px solid rgba(var(--accent-rgb), 0.4);
  border-radius: 999px;
  padding: 1px 6px;
  margin-left: 6px;
  vertical-align: middle;
}

/* ---------- Screener: HOME identity chip (GLOBAL screen.js only) -------- */
/* A stock's HOME column value in the GLOBAL screen — pill-styled like
   .unavailable-chip so it reads as "this row belongs to another market's
   page", not a normal text cell; row click still routes there (screen.js). */
.home-chip {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--ink-soft);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 1px 7px;
}

/* ============================================================
   Portfolio (#/portfolio). Reuses .chip-row/.chip, .btn/.btn-mini,
   .compare-add-row, .hint-line/.state, .data-table-wrap/table.data,
   .index-chip and .xc-set-row/.xc-set-name/.xc-set-meta/.xc-set-builtin-badge
   (xcompare's saved-sets idiom) wherever the existing component already
   fit; only genuinely new bits below.
   ============================================================ */
.pf-textarea {
  display: block;
  width: 100%;
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.5;
  padding: 10px 12px;
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 2px;
  color: var(--ink);
  resize: vertical;
  margin-bottom: 8px;
}
.pf-textarea:focus { border-color: var(--ink); outline: none; }

.pf-holdings-table tbody td:last-child,
.pf-risk-table tbody td:nth-child(3) { text-align: right; }

.pf-unresolved {
  border: 1px solid var(--warn);
  border-radius: 2px;
  padding: 10px 14px;
  margin: 4px 0 16px;
}
.pf-unresolved-title {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--warn);
  margin-bottom: 6px;
}
.pf-unresolved-item {
  padding: 6px 0;
  border-top: 1px solid var(--rule);
  font-size: 13px;
}
.pf-unresolved-item:first-child { border-top: none; }
.pf-unresolved-raw { font-family: var(--font-mono); color: var(--ink); }
.pf-unresolved-reason { color: var(--ink-faint); font-size: 11px; }
.pf-unresolved-suggestions {
  margin-top: 3px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-soft);
}

.pf-flag-chip {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.03em;
  color: var(--warn);
  border: 1px solid var(--warn);
  border-radius: 999px;
  padding: 2px 8px;
  margin: 0 4px 4px 0;
}
.pf-flag-chip--muted {
  color: var(--ink-faint);
  border-color: var(--rule);
  font-weight: 400;
}

/* ============================================================
   Strategy holdings drill-down (#/strategy/:IDX/:KEY) + drill-link
   affordances added to the Strategies stats table / rail and the Pulse
   factor-leadership table. Reuses .chip-row/.chip, .strat-layout/
   .strat-rail*, .chart-box(--tall), .data-table-wrap/table.data,
   .hint-line/.hint/.state, .tile-chip(--accent/--warn), .num-pos/.num-neg,
   .cf-cell and FE_UTIL.rankShadeStyle wherever the existing component
   already fit; only genuinely new bits below.
   ============================================================ */

/* ---------- Drill links: strategies.js rail + stats table, pulse.js table --- */
.strat-rail-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.strat-rail-row .strat-check { flex: 1 1 auto; min-width: 0; }
.strat-rail-link,
.strat-link-icon {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-faint);
  text-decoration: none;
  white-space: nowrap;
  flex: 0 0 auto;
}
.strat-rail-link:hover,
.strat-link-icon:hover { color: var(--accent); }

/* Whole strategy name is the drill-in link (owner: icon-only target too
   small). Ink-colored for table legibility; hover reveals affordance. */
.strat-name-link {
  color: var(--ink);
  text-decoration: none;
}
.strat-name-link:hover { color: var(--accent); text-decoration: underline; }
.strat-name-link:hover .strat-link-icon { color: var(--accent); }

/* Sub-sector ideas tables (landing + pulse). These sit INSIDE the mover-chart
   ideas section, whose stock names are 12px mono chart labels — so their
   name/market cells read the same way (mono, ink), NOT in the serif display
   face the analytics tables use; side by side the two looked like different
   products (owner, 2026-07-24). Link styling comes from the app-wide
   table.data rule below. */
table.data.subsec tbody td:first-child,
table.data.subsec tbody td.text { font-family: var(--font-mono); font-size: 12px; }

/* Drill-in links inside ANY data table — the .strat-name-link idiom made
   app-wide (owner, 2026-07-24: the sector pages' GICS tree and constituent
   table rendered as walls of browser-default blue underline, drowning the
   bold/indent hierarchy that carries the structure; same disease previously
   fixed piecemeal on the sub-sector tables). Quiet ink, hover reveals the
   affordance — tables that want the pointer already advertise it row-wide. */
table.data td a { color: var(--ink); text-decoration: none; }
table.data td a:hover { color: var(--accent); text-decoration: underline; }

/* The GICS ladder in a node page's subtitle is a NAV PATH, not content —
   ink-soft like .crumbs/.view-links, so "Energy › Energy › Oil, Gas &
   Consumable Fuels" reads as a quiet trail (that doubling is real GICS:
   sector and industry group share the name) instead of a row of loud blue
   stutters. */
.subtitle a { color: var(--ink-soft); text-decoration: none; }
.subtitle a:hover { color: var(--accent); text-decoration: underline; }

/* ---------- Strategy holdings — header stat tiles ---------- */
.stgy-stats-row {
  display: flex;
  gap: 28px;
  flex-wrap: wrap;
  margin: 8px 0 4px;
}
.stgy-stat { display: flex; flex-direction: column; gap: 2px; }
.stgy-stat-label {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-faint);
}
.stgy-stat-val {
  font-family: var(--font-mono);
  font-size: 18px;
  color: var(--ink);
}

/* ---------- Month snapshot (turnover timeline click target) ---------- */
.stgy-snapshot-title {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 16px;
  margin: 20px 0 10px;
}
.stgy-adddrop {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
  margin-bottom: 16px;
}
@media (max-width: 700px) {
  .stgy-adddrop { grid-template-columns: 1fr; }
}
.stgy-adddrop-title {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ink-faint);
  margin-bottom: 6px;
}

/* ============================================================
   WAVE-6 additions — Pulse horizon-chip row (shared factor + sector sort),
   filtered-improvers/stretched Ideas lists, and the stock-page H1
   click-to-search switcher (owner decisions, 2026-07-14). Reuses
   .chip-row/.chip, .hint-line, .ideas-cols/.ideas-col*/.idea-card*,
   .xc-suggestions/.xc-suggestion*, .index-chip, table.data thead th.sorted
   wherever the existing component already fit; only genuinely new bits
   below.
   ============================================================ */

/* ---------- Pulse: horizon-chip title line above the leadership bar ---------- */
.pulse-bar-title {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-faint);
  margin: 4px 0 6px;
}

/* Active-horizon column highlight — factor + sector leadership tables.
   Deliberately subtle (a faint accent wash), and independent of `.sorted`
   (which can point at a different column after a manual header-click). */
table.data thead th.col-hz-active {
  background: rgba(var(--accent-rgb), 0.08);
}

/* ---------- Stock page: H1 click-to-search switcher ---------- */
.stock-name-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.stock-name-row h1 { cursor: pointer; }
.stock-switch-btn {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  margin-bottom: 8px; /* align with h1's own bottom margin */
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: transparent;
  color: var(--ink-faint);
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
}
.stock-switch-btn:hover { color: var(--accent); border-color: var(--accent); }
.stock-switch-box {
  position: relative;
  flex: 1 1 320px;
  min-width: 240px;
  margin-bottom: 8px;
}
.stock-switch-box input {
  width: 100%;
  font-family: var(--font-mono);
  font-size: 18px;
  padding: 6px 10px;
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 2px;
  color: var(--ink);
}
.stock-switch-box input:focus { border-color: var(--accent); }
.stock-switch-hint {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--ink-faint);
  margin: 4px 0 0;
}
.stock-switch-box .xc-suggestions {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 20;
  margin-top: 4px;
}

/* ============================================================
   Global command line / jump palette (topbar, every page — search.js,
   "like a mini Bloomberg" per owner design addendum). Reuses
   .xc-suggestions/.xc-suggestion* (see the stock-switch-box override just
   above for the same "float it as an absolute dropdown" idiom); the topbar
   box itself, the idle "/" kbd hint, the stacked label/sub row layout, and
   the per-type color tags are new.
   ============================================================ */
.fe-search-box {
  position: relative;
  width: 420px;
  flex: 0 0 auto;
}
.fe-search-input {
  width: 100%;
  font-family: var(--font-mono);
  font-size: 13px;
  padding: 8px 30px 8px 12px; /* right-padded so the idle "/" chip has room */
  background: var(--bg-alt); /* terminal-panel tint — distinct from the plain topbar */
  border: 1px solid var(--rule);
  border-radius: 3px;
  color: var(--ink);
}
.fe-search-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px rgba(var(--accent-rgb), 0.18);
  outline: none;
}
.fe-search-input::placeholder { color: var(--ink-faint); }
/* Idle-state keyboard-shortcut affordance — visible only while the box is
   empty and unfocused (toggled via style.visibility in search.js, since
   there's no CSS selector for ":input is empty"). Disappears the instant
   you engage with it, same idiom as command-K launchers elsewhere. */
.fe-search-kbd {
  position: absolute;
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
  font-family: var(--font-mono);
  font-size: 10px;
  line-height: 1;
  padding: 2px 6px;
  border: 1px solid var(--rule);
  border-radius: 3px;
  color: var(--ink-faint);
  pointer-events: none;
}
.fe-search-box .xc-suggestions.fe-search-dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 500; /* above ordinary page content; below .fe-banners (1000) / .filter-panel (2000) */
  margin-top: 4px;
  max-height: 400px;
  background: var(--bg-alt);
}
.fe-search-item { align-items: center; }
.fe-search-item.active { background: var(--bg); color: var(--accent); }
/* Bloomberg-style yellow-key category tag — fixed width so every row's
   label column starts at the same x position regardless of tag text length. */
.fe-search-kind {
  flex: 0 0 54px;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 2px 0;
  border-radius: 2px;
  border: 1px solid currentColor;
}
/* Five entity types, five distinct existing tokens — no new colors, just
   assigned so the type reads at a glance across a mixed result list. */
.fe-search-kind--page { color: var(--ink-faint); }
.fe-search-kind--index { color: var(--accent); }
.fe-search-kind--sector { color: var(--ink-soft); }
.fe-search-kind--stock { color: var(--ink); }
.fe-search-kind--strategy { color: var(--warn); }
.fe-search-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1 1 auto;
}
.fe-search-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fe-search-sub {
  font-size: 11px;
  color: var(--ink-faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fe-search-loading { color: var(--ink-faint); cursor: default; }

@media (max-width: 1100px) {
  .fe-search-box { width: 280px; }
}

/* ============================================================
   Mobile (iPhone-width) pass — 2026-07-24. Additive, scoped to one new
   ~480px breakpoint (below every existing 700-1100px grid collapse, which
   are already inert by this width). iPhone audit found the topbar's
   search box overflowing the viewport on literally every route (it never
   shrinks — flex: 0 0 auto — so it alone forced page-wide horizontal
   scroll everywhere, independent of any per-page content); the rest here
   are the other cross-page findings from that same pass.
   ============================================================ */
@media (max-width: 480px) {
  /* ---------- Topbar: drop the jump-search box to its own full-width row
     below brand/crumbs/toggle instead of holding it to a fixed width wider
     than the viewport. Wrap the bar, then pull the search box after
     everything else (order) with a 100% basis so it's forced onto line 2;
     brand/crumbs/spacer/toggle keep their existing order and alignment on
     line 1 (spacer still pushes the toggle to the right edge). */
  .topbar {
    flex-wrap: wrap;
    padding: 14px 16px 12px;
    row-gap: 10px;
  }
  .fe-search-box {
    order: 5;
    width: auto;
    flex: 1 1 100%;
  }

  /* ---------- view-links row: with no wrap, a two/three-word link (e.g.
     "FACTOR SCATTER") was squeezed by flex instead of moving to its own
     line, breaking mid-phrase. Letting the row wrap keeps each link's
     phrase intact; long sector-node link labels still wrap internally
     (unchanged) once they're alone on a line. */
  .view-links { flex-wrap: wrap; row-gap: 8px; }

  /* ---------- Chips: a modest tap-target bump (6px -> 9px vertical
     padding) — 11px text in 6px padding is under any comfortable tap
     target. Kept small so dense chip rows (screener column-set picker,
     strategies rail) don't blow past a phone's height budget. */
  .chip { padding: 9px 14px; }

  /* ---------- iOS auto-zooms any focused input/select under 16px font —
     every text-entry control site-wide, not just the search box. */
  .fe-search-input,
  .toolbar input, .toolbar select,
  .compare-pickers input, .compare-pickers select, .axis-pickers select,
  .compare-add-row input,
  .filter-panel-search input, .filter-panel-cond input, .filter-panel-cond select,
  .strat-select,
  #xc-sector-picker-row select,
  .pf-textarea {
    font-size: 16px;
  }
}
