/* Vector + BRYPTOS — crypto workbench
   Sections: Overview (crypto KPIs + chart) · Greeks · Macro · Glossary · Sandbox
   Glossary terms are also linkable inline. */

const { useState, useMemo, useEffect } = React;

/* ---------- ICONS ---------- */
const ICONS = {
  chart:    'M3 3v18h18M7 14l3-3 4 4 5-6',
  bitcoin:  'M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20zM8 8h5a3 3 0 0 1 0 6M8 14h6a3 3 0 0 1 0 6H8M8 4v4M8 16v4',
  sigma:    'M19 4H5l7 8-7 8h14',
  layers:   'M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5',
  book:     'M4 19.5A2.5 2.5 0 0 1 6.5 17H20V2H6.5A2.5 2.5 0 0 0 4 4.5v15zM4 19.5V21h16',
  beaker:   'M9 2v4l-5 9a4 4 0 0 0 4 6h8a4 4 0 0 0 4-6L15 6V2M9 2h6',
  brain:    'M9.5 2A2.5 2.5 0 0 1 12 4.5v15a2.5 2.5 0 0 1-4.96.44 2.5 2.5 0 0 1-2.96-3.08 3 3 0 0 1-.34-5.58 2.5 2.5 0 0 1 1.32-4.24 2.5 2.5 0 0 1 1.98-3A2.5 2.5 0 0 1 9.5 2zM14.5 2A2.5 2.5 0 0 0 12 4.5v15a2.5 2.5 0 0 0 4.96.44 2.5 2.5 0 0 0 2.96-3.08 3 3 0 0 0 .34-5.58 2.5 2.5 0 0 0-1.32-4.24 2.5 2.5 0 0 0-1.98-3A2.5 2.5 0 0 0 14.5 2z',
  play:     'M5 3l14 9-14 9V3z',
  search:   'M21 21l-4.35-4.35M10 17a7 7 0 1 1 0-14 7 7 0 0 1 0 14z',
};
const Icon = ({ name, color = 'currentColor', size = 14 }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
    <path d={ICONS[name] || ICONS.chart} />
  </svg>
);

/* ---------- DATA ---------- */
// Mock 90-day BTC price (deterministic so it doesn't flicker)
function genSeries(seed, n, base, vol) {
  let v = base;
  const out = [];
  for (let i = 0; i < n; i++) {
    const r = Math.sin(seed + i * 0.31) * 0.5 + Math.cos(seed * 1.3 + i * 0.07);
    v = v * (1 + (r / 200) * vol);
    out.push(+v.toFixed(2));
  }
  return out;
}
const BTC_SERIES = genSeries(3, 90, 62000, 3.5);
const ETH_SERIES = genSeries(7, 90, 3400, 4.0);

// Generate then rescale so the last value of each series matches the canonical spot price
function rescaleTo(series, target) {
  const last = series[series.length - 1];
  const f = target / last;
  return series.map((v) => +(v * f).toFixed(2));
}
const BTC_PRICE = 71248.50;
const ETH_PRICE =  3812.74;
const BTC_SCALED = rescaleTo(BTC_SERIES, BTC_PRICE);
const ETH_SCALED = rescaleTo(ETH_SERIES, ETH_PRICE);

const CRYPTO_TABLE = [
  { sym: 'BTC',  name: 'Bitcoin',     px: BTC_PRICE, ch1d: 2.13, ch7d: 5.84, vol: '32.4B', mcap: '1.41T' },
  { sym: 'ETH',  name: 'Ethereum',    px: ETH_PRICE, ch1d: 1.82, ch7d: 3.12, vol: '14.2B', mcap: '460B' },
  { sym: 'SOL',  name: 'Solana',      px:   183.42, ch1d: 4.21, ch7d: 8.91, vol: '3.8B',  mcap: '88B' },
  { sym: 'AVAX', name: 'Avalanche',   px:    42.13, ch1d: -1.42, ch7d: 2.10, vol: '480M',  mcap: '16B' },
  { sym: 'LINK', name: 'Chainlink',   px:    18.92, ch1d: 0.83, ch7d: 1.92, vol: '320M',  mcap: '11B' },
  { sym: 'ARB',  name: 'Arbitrum',    px:     1.13, ch1d: -3.21, ch7d: -1.21, vol: '180M', mcap: '4.5B' },
];

const ONCHAIN = [
  { name: 'Active addresses',     val: '1.12M',     ch: '+4.2%', good: true },
  { name: 'Hash rate (EH/s)',     val: '628',       ch: '+1.8%', good: true },
  { name: 'Miners revenue (24h)', val: '$54.2M',    ch: '+2.1%', good: true },
  { name: 'Mempool size',         val: '124k',      ch: '-8.4%', good: false },
  { name: 'NVT ratio',            val: '42.3',      ch: '+2.0%', good: null  },
  { name: 'MVRV-Z',               val: '2.41',      ch: '+0.12', good: null  },
];

// Greeks heatmap: 7 strikes × 4 greeks. BTC at ~71k.
const STRIKES = [64000, 67000, 70000, 71000, 72000, 75000, 80000];
const GREEKS = {
  Δ: [0.92, 0.78, 0.58, 0.50, 0.42, 0.24, 0.10],
  Γ: [0.0001, 0.00018, 0.00024, 0.00026, 0.00024, 0.00018, 0.0001],
  Θ: [-32.4, -41.2, -48.7, -49.1, -48.3, -42.8, -33.6],
  ν: [82, 124, 158, 168, 158, 124, 82],
};

// Macro FRED series
const MACRO = [
  { id: 'GDP',     name: 'US Real GDP YoY',         val: '2.81%',  ch: '+0.04', spark: genSeries(11, 30, 2.7, 0.4) },
  { id: 'CPIAUCSL',name: 'CPI inflation YoY',       val: '3.20%',  ch: '-0.02', spark: genSeries(13, 30, 3.4, 0.6) },
  { id: 'UNRATE',  name: 'Unemployment rate',       val: '3.92%',  ch: '+0.01', spark: genSeries(17, 30, 3.85, 0.3) },
  { id: 'FEDFUNDS',name: 'Federal funds rate',      val: '5.33%',  ch: '0.00',  spark: genSeries(19, 30, 5.33, 0.05) },
  { id: 'DGS10',   name: '10-year treasury yield',  val: '4.31%',  ch: '+0.03', spark: genSeries(23, 30, 4.3, 0.8) },
  { id: 'M2SL',    name: 'M2 money supply',         val: '21.0T',  ch: '+0.1%', spark: genSeries(29, 30, 21.0, 0.2) },
  { id: 'DCOILWTICO', name: 'WTI crude oil',         val: '$78.42',ch: '+1.8%', spark: genSeries(31, 30, 76, 2.2) },
  { id: 'DEXUSEU', name: 'USD / EUR',               val: '1.08',   ch: '-0.2%', spark: genSeries(37, 30, 1.08, 0.4) },
];

const GLOSSARY = [
  { term: 'Hebbian routing',   def: 'Adaptive agent ranking where successful routes reinforce their weights (fire-together-wire-together).' },
  { term: 'ATP envelope',      def: 'Artemis Transmission Protocol — versioned wrapper {agent, intent, payload, governance, trust_decay}.' },
  { term: 'Trust decay',       def: 'Per-agent score that drops on policy violation. Below trust_min, the agent is unrouted.' },
  { term: 'NVT ratio',         def: 'Network Value to Transactions — market cap divided by daily transaction volume.' },
  { term: 'MVRV-Z',            def: 'Z-score of market cap vs realized cap. >3 = euphoria, <0 = capitulation.' },
  { term: 'Hash rate',         def: 'Total computational power securing the network (EH/s for Bitcoin).' },
  { term: 'Mempool',           def: 'Queue of unconfirmed transactions waiting for block inclusion.' },
  { term: 'Miners revenue',    def: 'Block reward + fees collected per 24h. Proxy for network security cost.' },
  { term: 'Implied volatility', def: 'Market-derived expected volatility; the only unknown in Black-Scholes.' },
  { term: 'Delta (Δ)',         def: 'First-order price sensitivity. 0.50 ≈ at-the-money; 1.0 = deep ITM.' },
  { term: 'Gamma (Γ)',         def: 'Second-order: rate of change of delta. Peaks at-the-money near expiry.' },
  { term: 'Theta (Θ)',         def: 'Time decay; option value erosion per day. Negative for long options.' },
  { term: 'Vega (ν)',          def: 'Sensitivity to a 1% change in implied volatility.' },
  { term: 'Sharpe of quality', def: 'Risk-adjusted measure where "return" is task quality, not P&L.' },
];

/* ---------- CHARTS ---------- */
function SeriesChart({ series, color = '#fbbf24', height = 260, label, unit = '$' }) {
  const w = 800, h = height;
  const pad = { l: 36, r: 8, t: 12, b: 24 };
  const min = Math.min(...series), max = Math.max(...series);
  const range = max - min || 1;
  const xs = series.length;
  const x = (i) => pad.l + (i / (xs - 1)) * (w - pad.l - pad.r);
  const y = (v) => pad.t + (h - pad.t - pad.b) * (1 - (v - min) / range);
  const path = series.map((v, i) => (i === 0 ? 'M' : 'L') + x(i) + ',' + y(v)).join(' ');
  const area = path + ` L${x(xs - 1)},${h - pad.b} L${x(0)},${h - pad.b} Z`;

  return (
    <svg viewBox={`0 0 ${w} ${h}`} style={{ width: '100%', height, display: 'block' }}>
      <defs>
        <linearGradient id={`fill-${color}`} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%"  stopColor={color} stopOpacity="0.30" />
          <stop offset="100%" stopColor={color} stopOpacity="0.00" />
        </linearGradient>
      </defs>
      {/* Y gridlines */}
      {[0.25, 0.5, 0.75].map((p, i) => (
        <line key={i} x1={pad.l} y1={pad.t + (h - pad.t - pad.b) * p} x2={w - pad.r} y2={pad.t + (h - pad.t - pad.b) * p}
              stroke="rgba(139,148,158,0.10)" strokeDasharray="2 4" />
      ))}
      {/* Y labels */}
      {[max, min + range / 2, min].map((v, i) => (
        <text key={i} x={pad.l - 6} y={pad.t + (h - pad.t - pad.b) * (i * 0.5) + 4} fill="#6e7681" fontSize="10" fontFamily="JetBrains Mono" textAnchor="end">
          {fmt(v, unit)}
        </text>
      ))}
      <path d={area} fill={`url(#fill-${color})`} />
      <path d={path} fill="none" stroke={color} strokeWidth="1.6" />
      <text x={pad.l} y={pad.t + 2} fontSize="10" fontFamily="JetBrains Mono" fill="#8b949e" letterSpacing="0.10em">{label}</text>
    </svg>
  );
}
function fmt(v, unit = '$') {
  if (unit === '%') return v.toFixed(2) + '%';
  if (unit === '')  return v.toFixed(2);
  if (v >= 1000) return '$' + Math.round(v).toLocaleString();
  if (v >= 100)  return '$' + v.toFixed(1);
  return '$' + v.toFixed(2);
}
function Spark({ series, color }) {
  const w = 80, h = 22;
  const min = Math.min(...series), max = Math.max(...series), r = max - min || 1;
  const pts = series.map((v, i) => `${(i / (series.length - 1)) * w},${h - ((v - min) / r) * h}`).join(' ');
  return (
    <svg className="macro-spark" viewBox={`0 0 ${w} ${h}`}>
      <polyline points={pts} fill="none" stroke={color} strokeWidth="1.4" />
    </svg>
  );
}

/* ---------- VIEWS ---------- */
function Overview() {
  const [coin, setCoin] = useState('BTC');
  const series = coin === 'BTC' ? BTC_SCALED : ETH_SCALED;
  const last = series[series.length - 1], first = series[0];
  const ch = ((last - first) / first) * 100;
  return (
    <>
      <div className="kpis">
        <div className="kpi"><div className="lbl">BTC spot</div><div className="val">${BTC_PRICE.toLocaleString(undefined,{maximumFractionDigits:0})}</div><div className="delta pos">▲ 2.13% · 24h</div></div>
        <div className="kpi"><div className="lbl">ETH spot</div><div className="val">${ETH_PRICE.toLocaleString(undefined,{maximumFractionDigits:0})}</div><div className="delta pos">▲ 1.82% · 24h</div></div>
        <div className="kpi"><div className="lbl">BTC dominance</div><div className="val">52.1%</div><div className="delta pos">▲ 0.34pp · 7d</div></div>
        <div className="kpi"><div className="lbl">Crypto market cap</div><div className="val">$2.71T</div><div className="delta pos">▲ $84B · 7d</div></div>
      </div>

      <div className="grid-2">
        <div className="card">
          <div className="card-head">
            <h3>{coin}-USD · 90 day</h3>
            <div className="seg">
              <button className={coin === 'BTC' ? 'on' : ''} onClick={() => setCoin('BTC')}>BTC</button>
              <button className={coin === 'ETH' ? 'on' : ''} onClick={() => setCoin('ETH')}>ETH</button>
            </div>
          </div>
          <div className="chart-shell">
            <SeriesChart series={series} color={coin === 'BTC' ? '#f59e0b' : '#a855f7'} label={`90d · ${ch >= 0 ? '+' : ''}${ch.toFixed(1)}%`} />
          </div>
        </div>

        <div className="card">
          <div className="card-head">
            <h3>On-chain metrics</h3>
            <span className="tag">BTC · 24h</span>
          </div>
          <div>
            {ONCHAIN.map((m) => (
              <div key={m.name} className="macro-row" style={{ gridTemplateColumns: '1fr auto auto', padding: '12px 14px' }}>
                <span className="macro-name">{m.name}</span>
                <span style={{ color: '#f0f6fc' }}>{m.val}</span>
                <span className={m.good === null ? '' : m.good ? 'pos' : 'neg'} style={{ minWidth: 60, textAlign: 'right' }}>{m.ch}</span>
              </div>
            ))}
          </div>
        </div>
      </div>

      <div className="card">
        <div className="card-head"><h3>Top crypto · spot &amp; flow</h3><span className="tag">live · IEX + CMC</span></div>
        <table>
          <thead>
            <tr>
              <th>Symbol</th><th>Name</th><th>Price</th><th>24h</th><th>7d</th><th>Vol 24h</th><th>Market cap</th>
            </tr>
          </thead>
          <tbody>
            {CRYPTO_TABLE.map((r) => (
              <tr key={r.sym} className="hover-able">
                <td style={{ color: '#fcd34d', fontWeight: 600 }}>{r.sym}</td>
                <td style={{ color: '#cbd5e1' }}>{r.name}</td>
                <td>${r.px.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</td>
                <td className={r.ch1d >= 0 ? 'pos' : 'neg'}>{r.ch1d >= 0 ? '+' : ''}{r.ch1d.toFixed(2)}%</td>
                <td className={r.ch7d >= 0 ? 'pos' : 'neg'}>{r.ch7d >= 0 ? '+' : ''}{r.ch7d.toFixed(2)}%</td>
                <td>{r.vol}</td>
                <td>{r.mcap}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </>
  );
}

function Greeks() {
  // Heatmap cell color helper
  function cellColor(v, min, max) {
    const t = (v - min) / (max - min || 1);
    const r = Math.round(34 + (245 - 34) * Math.abs(t - 0.5) * 2);
    const g = Math.round(197 - (197 - 158) * Math.abs(t - 0.5) * 2);
    const b = Math.round(94  - (94  -  11) * Math.abs(t - 0.5) * 2);
    return `rgba(${r},${g},${b},${0.10 + Math.abs(t - 0.5) * 0.6})`;
  }
  return (
    <>
      <div className="kpis" style={{ gridTemplateColumns: 'repeat(4, 1fr)' }}>
        <div className="kpi"><div className="lbl">Implied vol · 30d ATM</div><div className="val">52.4%</div><div className="delta neg">▼ 1.8pp · 24h</div></div>
        <div className="kpi"><div className="lbl">Open interest</div><div className="val">$24.1B</div><div className="delta pos">▲ $1.2B</div></div>
        <div className="kpi"><div className="lbl">Put/Call ratio</div><div className="val">0.83</div><div className="delta neg">▼ 0.04</div></div>
        <div className="kpi"><div className="lbl">25d skew · 30d</div><div className="val">+3.2%</div><div className="delta pos">▲ 0.6pp</div></div>
      </div>

      <div className="grid-2">
        <div className="card">
          <div className="card-head"><h3>Greeks heatmap · BTC calls (Jun expiry)</h3><span className="tag">Δ · Γ · Θ · ν</span></div>
          <div className="greeks-grid">
            <div className="cell axis"></div>
            {STRIKES.map((s) => <div key={s} className="cell header">${(s/1000).toFixed(0)}k</div>)}
            {Object.entries(GREEKS).map(([g, vals]) => {
              const min = Math.min(...vals), max = Math.max(...vals);
              return (
                <React.Fragment key={g}>
                  <div className="cell axis">{g}</div>
                  {vals.map((v, i) => (
                    <div key={i} className="cell" style={{ background: cellColor(v, min, max), color: '#f0f6fc' }}>
                      {v >= 1 ? v.toFixed(1) : v.toFixed(4)}
                    </div>
                  ))}
                </React.Fragment>
              );
            })}
          </div>
        </div>

        <div className="card">
          <div className="card-head"><h3>Position book</h3><span className="tag">net Δ · 0.42</span></div>
          <table>
            <thead><tr><th>Side</th><th>Inst</th><th>Strike</th><th>Qty</th><th>Δ</th></tr></thead>
            <tbody>
              <tr><td style={{ color: '#86efac' }}>LONG</td><td>BTC-Jun-72000-C</td><td>$72k</td><td>+5</td><td>2.10</td></tr>
              <tr><td style={{ color: '#86efac' }}>LONG</td><td>BTC-Jun-75000-C</td><td>$75k</td><td>+3</td><td>0.72</td></tr>
              <tr><td style={{ color: '#fca5a5' }}>SHORT</td><td>BTC-Jun-80000-C</td><td>$80k</td><td>-2</td><td>-0.20</td></tr>
              <tr><td style={{ color: '#86efac' }}>LONG</td><td>BTC-Jun-67000-P</td><td>$67k</td><td>+4</td><td>-0.88</td></tr>
              <tr><td style={{ color: '#fca5a5' }}>SHORT</td><td>BTC-Jun-64000-P</td><td>$64k</td><td>-3</td><td>0.24</td></tr>
            </tbody>
          </table>
        </div>
      </div>

      <div className="grid-2">
        <div className="card">
          <div className="card-head"><h3>Delta surface</h3><span className="tag">strike × dte</span></div>
          <div className="chart-shell"><SeriesChart series={GREEKS.Δ.map((v) => v * 100)} color="#22d3ee" height={200} label="Δ × 100 across strikes" unit="" /></div>
        </div>
        <div className="card">
          <div className="card-head"><h3>Vega surface</h3><span className="tag">strike × dte</span></div>
          <div className="chart-shell"><SeriesChart series={GREEKS.ν} color="#a855f7" height={200} label="ν across strikes" unit="" /></div>
        </div>
      </div>
    </>
  );
}

function Macro() {
  return (
    <>
      <div className="kpis">
        <div className="kpi"><div className="lbl">DXY (USD index)</div><div className="val">104.21</div><div className="delta pos">▲ 0.32 · 1d</div></div>
        <div className="kpi"><div className="lbl">VIX</div><div className="val">14.83</div><div className="delta pos">▲ 0.42 · 1d</div></div>
        <div className="kpi"><div className="lbl">SPY</div><div className="val">$520.18</div><div className="delta pos">▲ 0.31% · 1d</div></div>
        <div className="kpi"><div className="lbl">Yield curve · 10y-2y</div><div className="val">+0.42</div><div className="delta pos">▲ 0.08bp</div></div>
      </div>
      <div className="card" style={{ marginBottom: 14 }}>
        <div className="card-head"><h3>FRED economic series</h3><span className="tag">linked · fred.stlouisfed.org</span></div>
        <div>
          {MACRO.map((m) => (
            <div key={m.id} className="macro-row hover-able" style={{ cursor: 'pointer' }}>
              <span className="macro-name">{m.name}<span className="id" style={{ marginLeft: 8 }}>· {m.id}</span></span>
              <Spark series={m.spark} color={m.ch.startsWith('-') ? '#ef4444' : '#22c55e'} />
              <span style={{ color: '#f0f6fc', textAlign: 'right' }}>{m.val}</span>
              <span className={m.ch.startsWith('-') ? 'neg' : 'pos'} style={{ textAlign: 'right' }}>{m.ch.startsWith('+') || m.ch.startsWith('-') ? m.ch : '+' + m.ch}</span>
            </div>
          ))}
        </div>
      </div>
      <div className="grid-2">
        <div className="card">
          <div className="card-head"><h3>Inflation vs FFR (24m)</h3><span className="tag">CPIAUCSL · FEDFUNDS</span></div>
          <div className="chart-shell"><SeriesChart series={MACRO[1].spark.concat(MACRO[1].spark)} color="#fbbf24" height={200} label="CPI YoY %" unit="%" /></div>
        </div>
        <div className="card">
          <div className="card-head"><h3>10y treasury yield</h3><span className="tag">DGS10</span></div>
          <div className="chart-shell"><SeriesChart series={MACRO[4].spark.concat(MACRO[4].spark)} color="#67e8f9" height={200} label="DGS10 %" unit="%" /></div>
        </div>
      </div>
    </>
  );
}

function Sandbox() {
  const [code, setCode] = useState(`# BRYPTOS sandbox · python · cached frames in scope
# 'btc' · 'macro' · 'greeks' available

import numpy as np
import pandas as pd

# Pull last 30 BTC daily closes
window = btc.tail(30)
returns = window.pct_change().dropna()

# Volatility-weighted z-score signal
sigma  = returns.rolling(7).std().iloc[-1]
z      = (returns.iloc[-1] - returns.mean()) / sigma
signal = "LONG" if z > 0.5 else "SHORT" if z < -0.5 else "FLAT"

# Render the close + signal markers
plot_signal(window, z=z, signal=signal)
print(f"z={z:.2f}  σ={sigma:.4f}  → {signal}")`);
  const [running, setRunning] = useState(false);
  const [done, setDone] = useState(false);
  const [out, setOut] = useState('');

  function run() {
    setRunning(true); setDone(false); setOut('');
    setTimeout(() => {
      setOut('z=0.83  σ=0.0421  → LONG\n[exec] 12.4ms · 0 warnings');
      setRunning(false); setDone(true);
    }, 900);
  }

  // colorize code
  function hl(text) {
    return text
      .replace(/&/g, '&amp;').replace(/</g, '&lt;')
      .replace(/(#[^\n]*)/g, '<span class="cm">$1</span>')
      .replace(/\b(import|from|as|def|return|if|elif|else|for|in|while|with|class|lambda|None|True|False)\b/g, '<span class="k">$1</span>')
      .replace(/(['"])([^'"]*)\1/g, '<span class="s">$1$2$1</span>')
      .replace(/\b(\d+\.?\d*)\b/g, '<span class="n">$1</span>')
      .replace(/\b([a-zA-Z_]+)\(/g, '<span class="fn">$1</span>(');
  }

  return (
    <>
      <div className="kpis" style={{ marginBottom: 14 }}>
        <div className="kpi"><div className="lbl">Runtime</div><div className="val" style={{ fontSize: 16 }}>python · 3.13</div><div className="delta" style={{ color: '#67e8f9' }}>● kernel-sandboxed</div></div>
        <div className="kpi"><div className="lbl">Frames in scope</div><div className="val" style={{ fontSize: 16 }}>btc · macro · greeks</div><div className="delta" style={{ color: '#8b949e' }}>cached · 24h ttl</div></div>
        <div className="kpi"><div className="lbl">Policy</div><div className="val" style={{ fontSize: 16, color: '#fcd34d' }}>review</div><div className="delta">no fs · no net</div></div>
        <div className="kpi"><div className="lbl">Last run</div><div className="val" style={{ fontSize: 16 }}>{done ? '12.4ms' : '—'}</div><div className="delta pos">{done ? '✓ success' : '—'}</div></div>
      </div>

      <div className="sandbox">
        <div className="card">
          <div className="card-head">
            <h3>Editor · strategy.py</h3>
            <button className="run-btn" onClick={run} disabled={running}>
              <Icon name="play" size={11} color="#052e16" /> {running ? 'Running…' : 'Run'}
            </button>
          </div>
          <div className="editor" dangerouslySetInnerHTML={{ __html: hl(code) }} />
        </div>
        <div className="card">
          <div className="card-head">
            <h3>Output</h3>
            <span className="tag">stdout · matplotlib</span>
          </div>
          <div className="output-chart">
            {!done && !running && <div style={{ color: '#8b949e', fontFamily: 'var(--font-mono)', fontSize: 12, letterSpacing: '0.12em', textTransform: 'uppercase' }}>● press run</div>}
            {running && <div style={{ color: '#fcd34d', fontFamily: 'var(--font-mono)', fontSize: 12 }}>● executing in sandbox …</div>}
            {done && (
              <>
                <SeriesChart series={BTC_SCALED.slice(-30)} color="#22c55e" height={200} label="BTC last 30d · signal: LONG" />
                <pre style={{ marginTop: 12, fontFamily: 'var(--font-mono)', fontSize: 12, color: '#86efac' }}>{out}</pre>
              </>
            )}
          </div>
        </div>
      </div>
    </>
  );
}

function GlossaryView() {
  const [q, setQ] = useState('');
  const filt = GLOSSARY.filter((g) => !q || (g.term + g.def).toLowerCase().includes(q.toLowerCase()));
  return (
    <>
      <div style={{ marginBottom: 14, maxWidth: 480 }}>
        <input style={{ width: '100%', padding: '10px 14px', background: '#161b22', border: '1px solid rgba(139,148,158,0.20)', borderRadius: 7, color: '#f0f6fc', fontFamily: 'var(--font-sans)', fontSize: 14, outline: 'none' }} placeholder="Search glossary…" value={q} onChange={(e) => setQ(e.target.value)} />
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
        {filt.map((g) => (
          <div key={g.term} className="card" style={{ padding: 14 }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 12 }}>
              <span style={{ color: '#fcd34d', fontWeight: 600, fontFamily: 'var(--font-mono)', letterSpacing: '0.04em' }}>{g.term}</span>
              <span style={{ fontFamily: 'var(--font-mono)', fontSize: 10, color: '#8b949e', letterSpacing: '0.10em', textTransform: 'uppercase' }}>def</span>
            </div>
            <p style={{ margin: '8px 0 0', color: '#cbd5e1', fontSize: 13, lineHeight: 1.55 }}>{g.def}</p>
          </div>
        ))}
      </div>
    </>
  );
}

/* ---------- ROOT ---------- */
function App() {
  const [view, setView] = useState('overview');

  return (
    <div className="app">
      <div className="topbar">
        <div className="brand">
          <span className="glyph"><Icon name="bitcoin" size={18} color="#1f2937" /></span>
          <div>
            <div className="name"><span className="b">B</span>RYPTOS <span style={{ color: '#8b949e', fontWeight: 400 }}>· on Vector</span></div>
            <div className="sub">CRYPTO · OPTIONS · MACRO</div>
          </div>
        </div>
        <div className="topbar-right">
          <span className="chip"><span className="dot"></span> Live · IEX + CMC + FRED</span>
          <span className="status-pill"><span style={{ width: 6, height: 6, borderRadius: '50%', background: '#22c55e', boxShadow: '0 0 8px #22c55e' }}></span> Descope · session valid</span>
          <div className="user-chip">
            <span className="av">PP</span>
            <span style={{ fontFamily: 'var(--font-sans)' }}>Prinston P.</span>
          </div>
        </div>
      </div>

      <aside className="sidebar">
        <div>
          <div className="nav-title">BRYPTOS</div>
          <div className={'nav-item ' + (view === 'overview' ? 'active' : '')} onClick={() => setView('overview')}>
            <Icon name="bitcoin" /> Crypto overview
            <span className="nav-badge">live</span>
          </div>
          <div className={'nav-item ' + (view === 'greeks' ? 'active' : '')} onClick={() => setView('greeks')}>
            <Icon name="sigma" /> Options · Greeks
          </div>
          <div className={'nav-item ' + (view === 'macro' ? 'active' : '')} onClick={() => setView('macro')}>
            <Icon name="layers" /> Macro · FRED
          </div>
          <div className={'nav-item ' + (view === 'sandbox' ? 'active' : '')} onClick={() => setView('sandbox')}>
            <Icon name="beaker" /> Strategy sandbox
          </div>
          <div className={'nav-item ' + (view === 'glossary' ? 'active' : '')} onClick={() => setView('glossary')}>
            <Icon name="book" /> Glossary
            <span className="nav-badge">{GLOSSARY.length}</span>
          </div>
        </div>

        <div>
          <div className="nav-title">Vector</div>
          <div className="nav-item"><Icon name="chart" /> Strategies</div>
          <div className="nav-item"><Icon name="layers" /> Portfolio</div>
          <div className="nav-item"><Icon name="brain" /> Signals</div>
        </div>

        <div className="glossary">
          <h5>● Quick lookup</h5>
          <input placeholder="lookup a term…" id="qlookup" />
          <div id="qlookup-result">
            {GLOSSARY.slice(0, 3).map((g) => (
              <div className="gl-item" key={g.term}>
                <span className="term">{g.term}</span>
                <div className="def">{g.def}</div>
              </div>
            ))}
          </div>
        </div>
      </aside>

      <main>
        <div className="page-head">
          <div>
            <span className="eb">● {view === 'overview' ? 'crypto desk' : view === 'greeks' ? 'options · greeks' : view === 'macro' ? 'macro · fred' : view === 'sandbox' ? 'strategy sandbox' : 'reference'}</span>
            <h1>{view === 'overview' ? 'Crypto Overview' : view === 'greeks' ? 'Options · Greeks' : view === 'macro' ? 'Macro · FRED' : view === 'sandbox' ? 'Strategy Sandbox' : 'Glossary'}</h1>
            <p>{
              view === 'overview' ? 'BTC/ETH spot, on-chain metrics, and the top-cap basket.' :
              view === 'greeks'   ? 'Live Greeks heatmap + position book. Net Δ updates every tick.' :
              view === 'macro'    ? 'Eight Fed/Treasury series with sparklines. Drill in for full charts.' :
              view === 'sandbox'  ? 'Run governed Python against cached frames. Output stays in this sandbox.' :
                                    'Hover any term to see the definition. Linked from every other view.'
            }</p>
          </div>
        </div>

        {view === 'overview' && <Overview />}
        {view === 'greeks' && <Greeks />}
        {view === 'macro' && <Macro />}
        {view === 'sandbox' && <Sandbox />}
        {view === 'glossary' && <GlossaryView />}
      </main>
    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
