/*
 * dashboards/shared/css/shared.css — v1.4.18e (Reactive container)
 *
 * Single source of truth for all dashboard CSS. Replaces the four
 * files tokens.css (45) + layout.css (175) + components.css (397)
 * + charts.css (40) = 657 LOC with one ~360-LOC file.
 *
 * Section order (top → bottom):
 *   1. :root tokens         (theme + wallets + timer)
 *   2. base + grid          (#root, .sidebar, .main, .main-content,
 *                             .tier-grid, .hud, headings)
 *   3. KPI / section widgets (.kpi-card, .section-rule, hover help)
 *   4. fetch-timer widget   (circular countdown)
 *   5. wallets-grid         (connected wallets card grid)
 *   6. section header       (h3 + help pill + fullscreen button)
 *   7. plotly chart mount   (.plotly-chart + fullscreen + resize)
 *
 * v1.4.18e REACTIVE-CONTAINER FIX:
 *   - Added .main-content (single-column responsive grid; replaces
 *     the missing page-level wrapper).
 *   - Added .tier-grid (auto-fit minmax(220px, 1fr); replaces the
 *     inline `grid-template-columns:repeat(N,1fr)` rows that clipped
 *     on narrow viewports).
 *   - .section-header is now flex-wrap:nowrap with .chart-fullscreen-
 *     btn forced to flex-shrink:0; white-space:nowrap; (was wrap +
 *     no shrink, so the button drew off-screen below ~768px).
 *   - .plotly-chart height is now `aspect-ratio: 16/9` with
 *     min-height:280px / max-height:600px (was
 *     `clamp(280px, 50vh, 600px)` — `vh` ties to WINDOW, not
 *     container). lib.js:lib.chart() now attaches a ResizeObserver
 *     to every mount so Plotly reflows when the container resizes
 *     (fullscreen toggle, sidebar collapse, viewport rotation).
 *
 * Drift ladder is unchanged: PALETTE dict in game_engine/quant/app.py
 * is the canonical source; this file mirrors it line-for-line.
 */

/* ─── 1. Tokens ─────────────────────────────────────────────── */
:root {
  --paper:           #1A1A1F;
  --bg:              #1F1F24;
  --surface:         #25252A;
  --warm:            #2C2C32;

  --text:            #E8E6E1;
  --text_secondary:  #A9A7A1;
  --text_tertiary:   #7A7872;

  --line:            #6A6A72;
  --line_light:      #4A4A52;
  --line_faint:      #3E3E44;

  --accent_live:     #8B9A80;
  --accent_warn:     #C9A96E;
  --accent_alert:    #B85C5C;
  --accent_info:     #6A8FA8;
  --accent_demo:     #8B7AA8;

  --mono:            ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --timer-size:    36px;
  --timer-stroke:  4px;
  --timer-fg:      var(--accent_live);
  --timer-bg:      var(--line_faint);

  --wallet-bg-connected:    #1f3a24;
  --wallet-fg-connected:    #cfe2cf;
  --wallet-bg-disconnected: #4a1f1f;
  --wallet-fg-disconnected: #f4cfcf;
}

/* ─── 2. Base + grid ────────────────────────────────────────── */
* { box-sizing: border-box; }

html, body {
  margin: 0; padding: 0;
  background: var(--paper);
  color: var(--text);
  font-family: 'Helvetica Neue', sans-serif;
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

#root {
  min-height: 100vh;
  display: grid;
  grid-template-columns: 260px 1fr;
}

.sidebar {
  background: var(--surface);
  border-right: 1px solid var(--line_light);
  padding: 18px 16px;
  position: sticky; top: 0;
  align-self: start;
  height: 100vh;
  overflow-y: auto;
}
.sidebar h1 {
  font-size: 16px;
  color: var(--text);
  margin: 0 0 12px 0;
  letter-spacing: 0.02em;
}
.sidebar .db-path {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text_secondary);
  margin: 0 0 18px 0;
  padding: 6px 8px;
  background: var(--bg);
  border: 1px solid var(--line_light);
  border-radius: 4px;
  word-break: break-all;
}
.sidebar input.sidebar-textbox {
  width: 100%;
  display: block;
  box-sizing: border-box;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--line_light);
  border-radius: 4px;
  padding: 6px 8px;
  margin: 4px 0 8px 0;
  white-space: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  cursor: default;
}
.sidebar input.sidebar-textbox:focus {
  outline: none;
  border-color: var(--accent_live);
}
.sidebar nav {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.sidebar .nav-link {
  display: block;
  padding: 8px 10px;
  border-radius: 4px;
  font-size: 13px;
  color: var(--text_secondary);
  text-decoration: none;
  border: 1px solid transparent;
}
.sidebar .nav-link:hover {
  color: var(--text);
  background: var(--bg);
}
.sidebar .nav-link.is-active {
  color: var(--text);
  background: var(--bg);
  border-color: var(--accent_live);
}

.main {
  background: var(--bg);
  padding: 24px 28px 80px 28px;
  min-height: 100vh;
}
.main h1 { font-size: 20px; color: var(--text); margin: 0 0 18px 0; font-weight: 600; }
.main h2 { font-size: 16px; color: var(--text); margin: 24px 0 12px 0; font-weight: 600; }
.main h3 { font-size: 14px; color: var(--text); margin: 14px 0 8px 0; font-weight: 600; display: inline-block; }
.main p, .main label, .main span, .main div { color: var(--text); }

/* ─── 2a. Reactive page-container primitives (v1.4.18e) ────────
   Every page MUST wrap its body in <div class="main-content"> and
   use <div class="tier-grid"> for any row of N KPI/tier cells. See
   dashboards/AGENTS.md §"Reactive page-container rule" for the
   full contract (auto-fit minmax, no vh, no inline grid styles). */
.main-content {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 16px;
  align-content: start;
  width: 100%;
  min-width: 0;
}
.main-content > .section { min-width: 0; }

.tier-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 8px;
  width: 100%;
  min-width: 0;
}
.tier-grid > .kpi-card { min-width: 0; }

.hud {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 8px;
  margin-bottom: 14px;
}
@media (max-width: 1100px) { .hud { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 700px)  { .hud { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* ─── 3. KPI card + section rule + hover help ───────────────── */
.kpi-card {
  background: var(--surface);
  border: 1px solid var(--line_light);
  border-radius: 4px;
  padding: 12px 16px;
  margin-bottom: 8px;
  color: var(--text);
}
.kpi-label {
  color: var(--text_secondary);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.kpi-value {
  color: var(--text);
  font-size: 22px;
  font-weight: 500;
  margin-top: 4px;
}
.kpi-delta { color: var(--accent_warn); font-size: 11px; margin-top: 4px; }
.kpi-alert { color: var(--accent_alert); font-size: 11px; margin-top: 4px; }
.kpi-caption { color: var(--text_tertiary); font-size: 11px; margin-top: 4px; font-style: italic; }

/* ─── Phase C-1 cache hit-rate pill ─────────────────────────────
   Renders a compact pill in the sidebar showing both cache hit
   rates (dashboard KPI cache + figure cache). Color encodes
   health: green both≥50%, amber one<50%, red both<50%. */
.cache-hitrate-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border: 1px solid var(--line_light);
  border-radius: 12px;
  background: var(--surface);
  font: 600 10px/1 var(--mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text_secondary);
  margin: 6px 0 12px 0;
  cursor: help;
}
.cache-hitrate-pill .cache-hitrate-value {
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
.cache-hitrate-pill.is-good { border-color: var(--accent_live); color: var(--accent_live); }
.cache-hitrate-pill.is-warn { border-color: var(--accent_warn); color: var(--accent_warn); }
.cache-hitrate-pill.is-bad  { border-color: var(--accent_alert); color: var(--accent_alert); }

.section-rule {
  border-top: 1px solid var(--line_light);
  margin: 24px 0 12px 0;
}

.kpi-help {
  display: inline-block;
  margin-left: 6px;
  width: 14px; height: 14px;
  line-height: 13px;
  text-align: center;
  font-size: 10px; font-weight: 600;
  color: var(--text_secondary);
  background: var(--bg);
  border: 1px solid var(--line_light);
  border-radius: 50%;
  cursor: help;
  position: relative;
}
.kpi-help .kpi-tooltip-body {
  visibility: hidden; opacity: 0;
  transition: opacity 0.15s ease-in;
  position: absolute; z-index: 99;
  top: 18px; left: 50%;
  transform: translateX(-50%);
  width: 280px;
  padding: 10px 12px;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--line_light);
  border-radius: 4px;
  font-size: 12px;
  line-height: 1.4;
  box-shadow: 0 2px 8px rgba(0,0,0,0.4);
  text-align: left;
  text-transform: none; letter-spacing: 0; font-weight: 400;
}
.kpi-help:hover .kpi-tooltip-body,
.kpi-help:focus .kpi-tooltip-body {
  visibility: visible; opacity: 1;
}

.section-help {
  display: inline-block;
  margin-left: 8px;
  padding: 1px 8px;
  font-size: 11px;
  color: var(--text_secondary);
  background: var(--surface);
  border: 1px solid var(--line_light);
  border-radius: 10px;
  cursor: help;
  position: relative;
}
.section-help:hover,
.section-help:focus {
  color: var(--text);
  border-color: var(--accent_live);
}
.section-help .section-tooltip-body {
  visibility: hidden; opacity: 0;
  transition: opacity 0.15s ease-in;
  position: absolute; z-index: 99;
  top: 26px; left: 0;
  width: 420px;
  padding: 12px 14px;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--line_light);
  border-radius: 4px;
  font-size: 13px;
  line-height: 1.5;
  box-shadow: 0 2px 8px rgba(0,0,0,0.4);
  text-align: left;
}
.section-help:hover .section-tooltip-body,
.section-help:focus .section-tooltip-body {
  visibility: visible; opacity: 1;
}

/* ─── 4. Fetch-timer widget (top-right circular countdown) ──── */
.fetch-timer {
  position: fixed;
  top: 14px; right: 18px;
  width: var(--timer-size);
  height: var(--timer-size);
  z-index: 50;
  cursor: default;
  user-select: none;
}
.fetch-timer svg {
  width: 100%; height: 100%;
  display: block;
  transform: rotate(-90deg);
  transform-box: fill-box;
  transform-origin: center;
}
.fetch-timer circle { fill: none; }
.fetch-timer circle.bg { stroke: var(--timer-bg); stroke-width: var(--timer-stroke); }
.fetch-timer circle.fg {
  stroke: var(--timer-fg);
  stroke-width: var(--timer-stroke);
  stroke-linecap: round;
  transition: stroke-dashoffset 0.25s linear, stroke 0.25s linear;
}
.fetch-timer.is-fetching circle.fg { stroke: var(--accent_warn); }
.fetch-timer.is-off      circle.fg { stroke: var(--text_tertiary); }
.fetch-timer.is-off      { opacity: 0.85; }
.fetch-timer.is-error    circle.fg { stroke: var(--accent_alert); }
.fetch-timer.is-error    { opacity: 1; cursor: help; }
.fetch-timer text.label {
  transform: rotate(90deg);
  transform-origin: center;
  fill: var(--text);
  font: 700 14px var(--mono);
  text-anchor: middle;
  dominant-baseline: central;
  user-select: none;
  pointer-events: none;
}
.fetch-timer.is-fetching text.label { fill: var(--accent_warn); }
.fetch-timer.is-off      text.label { fill: var(--text_tertiary); }
.fetch-timer.is-error    text.label { fill: var(--accent_alert); }

/* ─── 4b. Lens toolbar (v1.4.20) ─────────────────────────────── */
.lens-toolbar {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 6px 0;
  border-top: 1px solid var(--line_faint);
  margin-top: 6px;
}
.lens-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.lens-chip {
  flex: 0 0 auto;
  padding: 4px 10px;
  background: var(--surface);
  border: 1px solid var(--line_faint);
  color: var(--text_secondary);
  font: 600 11px var(--mono);
  letter-spacing: 0.04em;
  border-radius: 999px;
  cursor: pointer;
  user-select: none;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.lens-chip:hover {
  background: var(--paper);
  border-color: var(--line_light);
  color: var(--text);
}
.lens-chip.is-active {
  background: var(--accent_live);
  border-color: var(--accent_live);
  color: var(--paper);
}
.lens-id-picker {
  font: 500 11px var(--mono);
  color: var(--text_tertiary);
  min-height: 16px;
  padding: 2px 0;
}
.lens-id-picker[data-id]:empty::before {
  content: "—" ;
}
.lens-toolbar.is-focused .lens-id-picker {
  color: var(--text);
}

/* ─── 5. Wallets grid (House Ops connected wallets) ─────────── */
.wallets-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 280px));
  gap: 8px;
  margin-bottom: 8px;
}
@media (max-width: 1100px) { .wallets-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 700px)  { .wallets-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.wallets-grid .wallet-card {
  background: var(--surface);
  border: 1px solid var(--line_light);
  border-radius: 4px;
  padding: 10px 12px;
  max-width: 280px;
  min-width: 0;
  align-self: start;
  display: flex;
  flex-direction: column;
  gap: 4px;
  box-sizing: border-box;
  overflow: hidden;
}
.wallets-grid .wallet-card.is-live {
  background: var(--wallet-bg-connected);
  border-color: var(--accent_live);
  color: var(--wallet-fg-connected);
}
.wallets-grid .wallet-card.is-disconnected {
  background: var(--wallet-bg-disconnected);
  border-color: var(--accent_alert);
  color: var(--wallet-fg-disconnected);
}
.wallets-grid .wallet-card .wallet-label {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text_secondary);
  letter-spacing: 0.04em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  width: 100%;
}
.wallets-grid .wallet-card .wallet-balance {
  font-size: 18px;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.wallets-grid .wallet-card .wallet-chip {
  font-size: 11px;
  color: var(--accent_info);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.wallets-grid .wallet-card .wallet-chip.is-disconnected {
  color: var(--text_secondary);
}

/* ─── 6. Section header (h3 + help pill + fullscreen button) ── */
.section { margin-bottom: 28px; min-width: 0; }
.section h3 { display: inline-block; margin-right: 6px; }

.section-header {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: nowrap;
}
.section-header h3 {
  margin: 0;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.section-header .section-help { margin-left: 0; flex-shrink: 0; white-space: nowrap; }
.section-header .chart-fullscreen-btn {
  margin-left: auto;
  flex-shrink: 0;
  white-space: nowrap;
}

.chart-fullscreen-btn {
  background: var(--surface);
  color: var(--text_secondary);
  border: 1px solid var(--line_light);
  border-radius: 4px;
  padding: 4px 10px;
  font-size: 11px;
  cursor: pointer;
  letter-spacing: 0.04em;
}
.chart-fullscreen-btn:hover {
  color: var(--text);
  border-color: var(--accent_live);
}

/* ─── 7. Plotly chart mount ─────────────────────────────────── */
/* v1.4.18e RESIZE FIX: height is `aspect-ratio: 16/9` with
   min-height:280px / max-height:600px. NO `vh` units — those tie
   the chart height to the WINDOW instead of the container, so the
   chart spills out of its card when the page is taller than the
   window. Width is 100% (fluid). lib.js:lib.chart() attaches a
   ResizeObserver to every mount, so Plotly.Plots.resize() fires
   on container resize (fullscreen toggle, sidebar collapse,
   viewport rotation), not just on window resize. */
.plotly-chart {
  width: 100%;
  min-width: 0;
  aspect-ratio: 16 / 9;
  min-height: 280px;
  max-height: 600px;
  background: var(--surface);
  border: 1px solid var(--line_light);
  border-radius: 4px;
  padding: 6px;
  margin-bottom: 8px;
}
.plotly-chart.is-collapsed { display: none; }
.plotly-chart:fullscreen {
  width: 100vw;
  height: 100vh;
  border-radius: 0;
  border: none;
  padding: 16px;
  background: var(--bg);
}

.collapsible-header {
  display: flex;
  align-items: center;
  gap: 8px;
}
.collapsible-toggle {
  background: transparent;
  color: var(--text_secondary);
  border: none;
  font-size: 13px;
  cursor: pointer;
  padding: 4px 6px;
  border-radius: 4px;
}
.collapsible-toggle:hover {
  color: var(--text);
  background: var(--bg);
}

/* ─── Empty state ───────────────────────────────────────────── */
.empty-state {
  background: var(--surface);
  border: 1px solid var(--line_light);
  border-radius: 4px;
  padding: 18px;
  color: var(--text_secondary);
  font-size: 13px;
}

/* ─── Error chip (v1.4.15) ───────────────────────────────────── */
.error-chip-wrap {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--surface);
  border: 1px solid var(--line_light);
  border-radius: 4px;
  padding: 12px 16px;
  font-size: 12px;
  font-family: var(--mono, "JetBrains Mono", monospace);
  margin: 8px 0;
}
.error-chip {
  display: inline-block;
  font-weight: 700;
  font-size: 11px;
  padding: 3px 8px;
  border-radius: 3px;
  letter-spacing: 0.04em;
}
.error-chip.is-404  { background: var(--accent_warn);  color: var(--paper); }
.error-chip.is-4xx  { background: var(--accent_warn);  color: var(--paper); }
.error-chip.is-5xx  { background: var(--accent_alert); color: var(--paper); }
.error-chip.is-net  { background: var(--accent_alert); color: var(--paper); }
.error-chip.is-error { background: var(--accent_alert); color: var(--paper); }
.error-chip-msg {
  color: var(--text);
  word-break: break-all;
  flex: 1;
  min-width: 0;
}

/* ─── Buttons (refresh + sidebar toggle) ─────────────────────── */
button.refresh-button {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--line_light);
  border-radius: 4px;
  padding: 6px 12px;
  font-size: 12px;
  cursor: pointer;
  margin-left: 8px;
}
button.refresh-button:hover {
  border-color: var(--accent_live);
}
