/* ==========================================================================
   Backtest panel charts — presentation layer.
   Include via: <link rel="stylesheet" href="/backtest.css">
                <script src="/backtest.js"></script>
                Backtest.render(containerEl, data)

   Tokens mirror public/index.html's :root + dial.css's fallback pattern:
   every var() carries a literal fallback so this file (and the panel it
   renders into) looks right even if the host page never defines the
   token — see dial.css's own note on this. On the live homepage these
   resolve to the real design tokens (--live is server-set to the current
   phase colour); standalone (the __demo page) they fall back to the same
   literals index.html ships in :root.
   ========================================================================== */

.bt-panel {
  --bt-live:     var(--live, #22d3ee);
  --bt-ink:      var(--ink, #edeae4);
  --bt-ink-2:    var(--ink-2, #a8a49c);
  --bt-ink-3:    var(--ink-3, #7c7871);
  --bt-ink-4:    var(--ink-4, #7b7873);
  --bt-rule:     var(--rule, rgba(237, 234, 228, 0.13));
  --bt-rule-dim: var(--rule-dim, rgba(237, 234, 228, 0.06));
  --bt-mono:     var(--mono, 'Geist Mono', 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace);
  --bt-up:       #4ade80;   /* matches index.html .gates .up */
  --bt-down:     #ef4444;   /* matches index.html .gates .dn */
  --bt-tie:      #d4a72c;   /* tie band: 1.00x - CLEAR_WIN_THRESHOLD */

  display: grid;
  gap: 34px;
  color: var(--bt-ink-2);
  font-family: var(--prose, 'Geist', 'Archivo', system-ui, sans-serif);
  max-width: 100%;
}

.bt-block { min-width: 0; max-width: 100%; }

.bt-block-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 18px;
  margin: 0 0 12px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--bt-rule);
}

.bt-title {
  font-family: var(--bt-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--bt-ink);
  margin: 0;
  /* NOT nowrap — a flex item that cannot wrap has a min-content width equal
     to its full text run, which forced a 2px horizontal overflow at 340px
     (measured via CDP: .bt-title right edge at 342.2 against a 340 viewport).
     min-width: 0 lets it shrink below that intrinsic width and wrap instead. */
  min-width: 0;
  flex: 1 1 100%;
}

.bt-subtitle {
  font-size: 12px;
  color: var(--bt-ink-4);
  margin: 0;
  flex: 1 1 auto;
  min-width: 0;
}

.bt-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-left: auto;
  font-family: var(--bt-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--bt-ink-3);
}

.bt-legend span { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }

.bt-swatch {
  width: 9px;
  height: 9px;
  border-radius: 2px;
  display: inline-block;
  flex: none;
}

.bt-swatch.model {
  background: var(--bt-live);
  /* Flat fallback declared first — color-mix() alone vanished on iOS Safari
     when it was the only fill declaration (dial.css .core note, 2026-08-27). */
  background: color-mix(in oklab, var(--bt-live) 88%, white);
}
.bt-swatch.hodl { background: var(--bt-ink-4); opacity: 0.55; }
.bt-swatch.lose { background: var(--bt-down); }
.bt-swatch.tie  { background: var(--bt-tie); }
.bt-swatch.open {
  background: var(--bt-live);
  opacity: 0.4;
  outline: 1px dashed var(--bt-ink-3);
  outline-offset: 1px;
}

.bt-svg-wrap { width: 100%; max-width: 100%; overflow: hidden; }

.bt-svg {
  display: block;
  width: 100%;
  height: auto;
  max-width: 100%;
}

.bt-note {
  margin: 10px 0 0;
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--bt-ink-4);
  max-width: 78ch;
}
.bt-note b { color: var(--bt-ink-3); font-weight: 600; }

.bt-empty {
  padding: 34px 18px;
  text-align: center;
  font-family: var(--bt-mono);
  font-size: 11.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bt-ink-4);
  border: 1px dashed var(--bt-rule);
}

/* --- SVG-internal styling (kept simple; geometry does the real work) --- */
.bt-svg .bt-grid    { stroke: var(--bt-rule-dim); stroke-width: 1; }
.bt-svg .bt-baseline { stroke: var(--bt-rule); stroke-width: 1; stroke-dasharray: 2 3; }
.bt-svg .bt-axislabel {
  font-family: var(--bt-mono);
  font-size: 9.5px;
  fill: var(--bt-ink-4);
}
.bt-svg .bt-catlabel {
  font-family: var(--bt-mono);
  font-size: 10px;
  letter-spacing: 0.02em;
  fill: var(--bt-ink-3);
  text-anchor: middle;
}
.bt-svg .bt-catlabel.open { fill: var(--bt-ink); }
.bt-svg .bt-vallabel {
  font-family: var(--bt-mono);
  font-size: 9.5px;
  font-variant-numeric: tabular-nums;
  text-anchor: middle;
}
.bt-svg .bt-vallabel.model { fill: var(--bt-ink); }
.bt-svg .bt-vallabel.hodl  { fill: var(--bt-ink-4); }
.bt-svg .bt-vallabel.lose  { fill: var(--bt-down); }
.bt-svg .bt-vallabel.tie   { fill: var(--bt-tie); }

.bt-svg .bt-bar.model {
  fill: var(--bt-live);
  fill: color-mix(in oklab, var(--bt-live) 88%, white);
}
.bt-svg .bt-bar.model.lose {
  fill: var(--bt-down);
  fill: color-mix(in oklab, var(--bt-down) 82%, white);
}
/* TIE — 1.00x up to CLEAR_WIN_THRESHOLD (1.05). Calm amber, deliberately NOT the loss red:
   matching hold is not a failure, and this repo's own copy calls 1.06 a tie rather than a
   win, so a 1.02 rendered green would contradict the prose beside it. Flat fill declared
   first — a color-mix-only fill vanished on iOS Safari on 2026-08-27. */
.bt-svg .bt-bar.model.tie {
  fill: var(--bt-tie);
  fill: color-mix(in oklab, var(--bt-tie) 82%, white);
}
.bt-svg .bt-bar.hodl {
  fill: var(--bt-ink-4);
  fill: color-mix(in oklab, var(--bt-ink-4) 55%, transparent);
}
.bt-svg .bt-bar.open { stroke: var(--bt-ink-3); stroke-width: 1; stroke-dasharray: 3 2; opacity: 0.62; }
.bt-svg .bt-bar.dd-worse {
  fill: var(--bt-down);
  fill: color-mix(in oklab, var(--bt-down) 82%, white);
}

@media (max-width: 480px) {
  .bt-panel { gap: 26px; }
  .bt-legend { margin-left: 0; width: 100%; }
}
