/* ═══════════════════════════════════════════════════════════════════
   SHADOW PANEL · right rail
   Shadow AI status + thought stream + top movers + market context mini
   ═══════════════════════════════════════════════════════════════════ */

function ShadowPanel({ thoughts, movers, intel }) {
  return (
    <aside style={{
      width: 380, flexShrink: 0,
      borderLeft: `1px solid ${ST.border}`,
      background: ST.bg,
      display: 'flex', flexDirection: 'column',
      minHeight: 0, overflowY: 'auto', overflowX: 'hidden',
    }}>
      <ShadowAIStatus />
      <ThoughtStream events={thoughts} />
      <TopMoversCard movers={movers} />
      <MyHoldingsPanel />
    </aside>
  );
}

/* ═══════════════════════════════════════════════════════════════════
   MY HOLDINGS · real portfolio overview (replaces the duplicate market
   context — that data already lives in the top Intel Bar)
   ═══════════════════════════════════════════════════════════════════ */
function MyHoldingsPanel() {
  const [data, setData] = React.useState(null);
  React.useEffect(() => {
    ST_fetch('/market/assets').then(setData).catch(() => setData({ holdings: [] }));
  }, []);
  const holdings = data?.holdings || [];
  const total  = data?.total_value;
  const pnlPct = data?.total_pnl_pct;
  const pnlUsd = data?.total_pnl;

  return (
    <section style={{ padding: '14px 16px 20px', borderTop: `1px solid ${ST.border}` }}>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 10 }}>
        <span className="eyebrow">MY HOLDINGS</span>
        <span className="mono" style={{ fontSize: 9, color: ST.ink4 }}>{holdings.length} coins</span>
      </div>

      <div style={{ display: 'flex', alignItems: 'baseline', gap: 9, marginBottom: 12 }}>
        <span className="num" style={{ fontSize: 23, fontWeight: 600, color: ST.ink, letterSpacing: '-0.02em' }}>
          {total != null ? `$${total.toLocaleString('en-US', { maximumFractionDigits: 0 })}` : '—'}
        </span>
        {pnlPct != null && (
          <span className="num" style={{ fontSize: 12, fontWeight: 600, color: pnlPct >= 0 ? ST.green : ST.red }}>
            {pnlPct >= 0 ? '+' : ''}{pnlPct.toFixed(2)}%
            {pnlUsd != null && ` (${pnlUsd >= 0 ? '+' : '-'}$${Math.abs(pnlUsd).toLocaleString('en-US', { maximumFractionDigits: 0 })})`}
          </span>
        )}
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
        {holdings.length === 0 && (
          <div className="mono" style={{ fontSize: 10, color: ST.ink4, padding: '8px 0' }}>
            {data === null ? 'Loading…' : 'No holdings detected'}
          </div>
        )}
        {holdings.slice(0, 12).map((h, i) => (
          <a key={i} href={`../coin/?symbol=${h.symbol}`} className="fx-row" style={{
            display: 'grid', gridTemplateColumns: 'auto 1fr auto 50px', gap: 8, alignItems: 'center',
            padding: '7px 6px', borderRadius: 6, textDecoration: 'none',
          }}>
            <CoinGlyph sym={h.symbol} size={20} />
            <div style={{ minWidth: 0 }}>
              <span className="mono" style={{ fontSize: 11, fontWeight: 600, color: ST.ink2 }}>{h.symbol}</span>
              <div className="mono" style={{ fontSize: 9, color: ST.ink4 }}>
                {ST_fmt.price(h.qty)}{h.avg_cost ? ` · avg $${ST_fmt.price(h.avg_cost)}` : ''}
              </div>
            </div>
            <span className="num" style={{ fontSize: 11, color: ST.ink, textAlign: 'right' }}>
              ${h.value.toLocaleString('en-US', { maximumFractionDigits: 0 })}
            </span>
            <span className="num" style={{ fontSize: 10, fontWeight: 600, textAlign: 'right',
              color: h.pnl_pct == null ? ST.ink4 : h.pnl_pct >= 0 ? ST.green : ST.red }}>
              {h.pnl_pct == null ? '—' : `${h.pnl_pct >= 0 ? '+' : ''}${h.pnl_pct.toFixed(1)}%`}
            </span>
          </a>
        ))}
      </div>
    </section>
  );
}
window.MyHoldingsPanel = MyHoldingsPanel;

/* ═══════════════════════════════════════════════════════════════════
   Shadow AI Status
   ═══════════════════════════════════════════════════════════════════ */
/* CSS-only scan animation — eliminates the 420ms JS re-render loop */
(function injectScanCSS() {
  if (document.getElementById('st-scan-anim')) return;
  const s = document.createElement('style');
  s.id = 'st-scan-anim';
  s.textContent = `
    @keyframes st-scan-pulse {
      0%,100% { opacity:0.3 }
      50%     { opacity:1; box-shadow:0 0 6px #F7A600 }
    }
    .st-scan-bar { height:8px; border-radius:1px; background:#1E2130; animation:st-scan-pulse 2s ease-in-out infinite; }
    .st-scan-bar:nth-child(1){animation-delay:0s} .st-scan-bar:nth-child(2){animation-delay:.08s}
    .st-scan-bar:nth-child(3){animation-delay:.16s} .st-scan-bar:nth-child(4){animation-delay:.24s}
    .st-scan-bar:nth-child(5){animation-delay:.32s} .st-scan-bar:nth-child(6){animation-delay:.40s}
    .st-scan-bar:nth-child(7){animation-delay:.48s} .st-scan-bar:nth-child(8){animation-delay:.56s}
    .st-scan-bar:nth-child(9){animation-delay:.64s} .st-scan-bar:nth-child(10){animation-delay:.72s}
    .st-scan-bar:nth-child(11){animation-delay:.80s} .st-scan-bar:nth-child(12){animation-delay:.88s}
    .st-scan-bar:nth-child(13){animation-delay:.96s} .st-scan-bar:nth-child(14){animation-delay:1.04s}
    .st-scan-bar:nth-child(15){animation-delay:1.12s} .st-scan-bar:nth-child(16){animation-delay:1.20s}
    .st-scan-bar:nth-child(17){animation-delay:1.28s} .st-scan-bar:nth-child(18){animation-delay:1.36s}
    .st-scan-bar:nth-child(19){animation-delay:1.44s} .st-scan-bar:nth-child(20){animation-delay:1.52s}
    .st-scan-bar:nth-child(21){animation-delay:1.60s} .st-scan-bar:nth-child(22){animation-delay:1.68s}
    .st-scan-bar:nth-child(23){animation-delay:1.76s} .st-scan-bar:nth-child(24){animation-delay:1.84s}
  `;
  document.head.appendChild(s);
})();

function ShadowAIStatus() {
  /* Removed 420ms pulse interval — replaced with CSS animation */

  /* ── live status from API ── */
  /* API: {scan_count, last_scan_ts(ms), last_regime, is_scanning, coins_tracked, log_stats} */
  const [status, setStatus] = React.useState(null);
  React.useEffect(() => {
    const load = () => ST_fetch('/shadow/status').then(d => setStatus(d)).catch(() => {});
    load();
    const id = setInterval(load, 60000);
    return () => clearInterval(id);
  }, []);

  /* ── countdown: last_scan_ts is milliseconds from API ── */
  const [secs, setSecs] = React.useState(347);
  React.useEffect(() => {
    if (status?.last_scan_ts) {
      const tsMs = status.last_scan_ts > 1e12
        ? status.last_scan_ts            /* already ms */
        : status.last_scan_ts * 1000;    /* was seconds */
      const elapsed = Math.floor((Date.now() - tsMs) / 1000);
      setSecs(Math.max(0, 600 - (elapsed % 600)));
    }
  }, [status]);
  React.useEffect(() => {
    const id = setInterval(() => setSecs(s => (s <= 0 ? 600 : s - 1)), 1000);
    return () => clearInterval(id);
  }, []);
  const mm = Math.floor(secs / 60);
  const ss_str = String(secs % 60).padStart(2, '0');
  const scanning = secs <= 1;

  /* API fields: last_regime (not regime), scan_count, log_stats.by_type.SIGNAL */
  const regime     = status?.last_regime || status?.regime || 'BEARISH';
  const scanCount  = status?.scan_count != null ? Number(status.scan_count).toLocaleString('en-US') : '—';
  const sigCount   = status?.log_stats?.by_type?.SIGNAL ?? status?.active_signals ?? 0;
  const signals    = sigCount;
  const winRate    = 0;   /* win_rate comes from /shadow/accuracy, not /shadow/status */
  const winRatePct = 0;

  /* re-use mm/ss names expected below */
  const mm_disp = mm;
  const ss_disp = ss_str;

  return (
    <section style={{
      padding: '16px 16px 14px',
      borderBottom: `1px solid ${ST.border}`,
      background: `
        radial-gradient(ellipse 280px 140px at 50% 0%, rgba(247,166,0,0.10) 0%, transparent 70%),
        ${ST.bg2}
      `,
      position: 'relative',
    }}>
      {/* header */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12 }}>
        <ShadowMark size={20} />
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 13, fontWeight: 600, color: ST.ink, letterSpacing: '-0.01em' }}>
            Shadow AI
          </div>
          <div className="mono" style={{ fontSize: 9, color: ST.amber, letterSpacing: '0.12em', marginTop: 1 }}>
            SCANNING · 24 COINS
          </div>
        </div>
        <div style={{ textAlign: 'right', marginRight: 9 }}>
          <div className="eyebrow" style={{ fontSize: 7.5, color: ST.ink4 }}>NEXT SCAN</div>
          <div className="num" style={{ fontSize: 12, fontWeight: 600, lineHeight: 1.1,
            color: scanning ? ST.amber : ST.ink2, letterSpacing: '0.02em' }}>
            {scanning ? 'NOW' : `${mm_disp}:${ss_disp}`}
          </div>
        </div>
        <span className="st-live-dot" />
      </div>

      {/* scan progress visualizer — CSS animation, no JS re-renders */}
      <div style={{ display: 'flex', gap: 2, marginBottom: 14 }}>
        {Array.from({ length: 24 }).map((_, i) => (
          <div key={i} className="st-scan-bar" style={{ flex: 1 }} />
        ))}
      </div>

      {/* stats grid */}
      <div style={{
        display: 'grid',
        gridTemplateColumns: '1fr 1fr 1fr',
        gap: 8,
        marginBottom: 12,
      }}>
        <StatTile label="REGIME" value={regime} valueColor={regime==='BULLISH'?ST.green:regime==='NEUTRAL'?ST.ink3:ST.amber} subtitle="live" />
        <StatTile label="SCANS · 24H" value={scanCount} valueColor={ST.ink} subtitle="every 10m" />
        <StatTile label="SIGNALS" value={String(signals)} valueColor={ST.violet} subtitle="learning" />
      </div>

      {/* win rate meter */}
      <div>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 5 }}>
          <span className="eyebrow">WIN RATE · TARGET 90%</span>
          <span className="mono" style={{
            fontSize: 9, fontWeight: 700, letterSpacing: '0.08em',
            color: ST.violet, background: `${ST.violet}14`,
            padding: '2px 5px', borderRadius: 2,
            border: `1px solid ${ST.violet}40`,
          }}>LEARNING</span>
        </div>
        <div style={{
          position: 'relative', height: 8,
          background: ST.panel, borderRadius: 4,
          border: `1px solid ${ST.border}`,
          overflow: 'visible',
        }}>
          {/* target zone (above 70%) */}
          <div style={{
            position: 'absolute', left: '70%', top: 0, bottom: 0, right: 0,
            background: ST.green, opacity: 0.10,
          }} />
          {/* target line at 90% */}
          <div style={{
            position: 'absolute', left: '90%', top: -3, bottom: -3,
            width: 1, background: ST.green, opacity: 0.6,
          }} />
          <div style={{
            position: 'absolute', left: 0, top: 0, bottom: 0,
            width: `${Math.min(100, winRatePct)}%`,
            background: `linear-gradient(90deg, ${ST.violet}, ${ST.green})`,
            borderRadius: 4,
          }} />
        </div>
        <div style={{
          display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 4,
        }}>
          <span className="mono" style={{ fontSize: 9, color: ST.ink4 }}>
            0/1 signals scored
          </span>
          <span className="mono" style={{ fontSize: 9, color: ST.ink4 }}>
            need <span style={{ color: ST.ink2 }}>30+</span> to grade
          </span>
        </div>
      </div>

      {/* Bot status */}
      <div style={{
        marginTop: 12, padding: '8px 10px',
        background: ST.bg,
        border: `1px solid ${ST.border}`,
        borderRadius: 6,
        display: 'flex', alignItems: 'center', gap: 8,
      }}>
        <div style={{
          width: 6, height: 6, borderRadius: 3,
          background: ST.green, boxShadow: `0 0 6px ${ST.green}`,
        }} />
        <div style={{ flex: 1, minWidth: 0 }}>
          <span className="mono" style={{ fontSize: 10, color: ST.ink2, fontWeight: 600 }}>
            BOT-2 · PAPER
          </span>
          <span className="mono" style={{ fontSize: 9, color: ST.ink4, marginLeft: 6 }}>
            NEAR · DOT · LINK
          </span>
        </div>
        <span className="mono" style={{ fontSize: 9, color: ST.green, letterSpacing: '0.08em', fontWeight: 600 }}>
          ORACLE · 24/7
        </span>
      </div>
    </section>
  );
}

function StatTile({ label, value, valueColor, subtitle }) {
  return (
    <div style={{
      padding: '8px 9px',
      background: ST.bg,
      border: `1px solid ${ST.border}`,
      borderRadius: 6,
      display: 'flex', flexDirection: 'column', gap: 2,
      minWidth: 0,
    }}>
      <span className="eyebrow" style={{ fontSize: 8 }}>{label}</span>
      <span className="num" style={{
        fontSize: 14, fontWeight: 600, color: valueColor,
        letterSpacing: '-0.01em', lineHeight: 1.1,
        whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
      }}>{value}</span>
      <span className="mono" style={{ fontSize: 9, color: ST.ink4 }}>{subtitle}</span>
    </div>
  );
}

/* ═══════════════════════════════════════════════════════════════════
   Thought stream — pill + mono message per event
   ═══════════════════════════════════════════════════════════════════ */
const EVENT_COLORS = {
  SCAN:       ST.blue,
  HYPOTHESIS: ST.violet,
  SIGNAL:     ST.amber,
  LEARN:      ST.green,
  VETO:       ST.red,
};

function ThoughtStream({ events = [] }) {
  return (
    <section style={{
      padding: '14px 16px',
      borderBottom: `1px solid ${ST.border}`,
    }}>
      <div style={{
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        marginBottom: 12,
      }}>
        <span className="eyebrow">THOUGHT STREAM</span>
        <span className="mono" style={{ fontSize: 9, color: ST.ink4, letterSpacing: '0.08em' }}>
          <span className="st-live-dot" style={{ marginRight: 6, transform: 'translateY(-1px)' }} />
          LAST 8 · LIVE
        </span>
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 11 }}>
        {events.map((e, i) => <ThoughtRow key={i} {...e} fresh={i === 0} />)}
      </div>
    </section>
  );
}

function ThoughtRow({ time, type, message, meta, fresh }) {
  const c = EVENT_COLORS[type] || ST.ink3;
  return (
    <div style={{
      display: 'grid',
      gridTemplateColumns: '46px 62px 1fr',
      alignItems: 'baseline',
      gap: 8,
    }}>
      <span className="mono" style={{ fontSize: 9, color: ST.ink4, letterSpacing: '0.02em' }}>
        {time}
      </span>
      <span className="mono" style={{
        fontSize: 9, fontWeight: 700, letterSpacing: '0.1em',
        color: c, background: `${c}14`,
        padding: '2px 4px', borderRadius: 2,
        border: `1px solid ${c}30`,
        textAlign: 'center',
        justifySelf: 'start',
      }}>{type}</span>
      <div style={{ minWidth: 0 }}>
        {fresh && <span className="mono" style={{ fontSize: 11, color: ST.amber, fontWeight: 700, marginRight: 4 }}>{'\u203A'}</span>}
        <span className={`mono${fresh ? ' fx-caret' : ''}`} style={{
          fontSize: 11, color: fresh ? ST.ink : ST.ink2, lineHeight: 1.4,
          letterSpacing: '-0.005em',
        }}>{message}</span>
        {meta && (
          <div className="mono" style={{ fontSize: 9, color: ST.ink4, marginTop: 2 }}>
            {meta}
          </div>
        )}
      </div>
    </div>
  );
}

/* ═══════════════════════════════════════════════════════════════════
   Top Movers
   ═══════════════════════════════════════════════════════════════════ */
function TopMoversCard({ movers }) {
  return (
    <section style={{
      padding: '14px 16px',
      borderBottom: `1px solid ${ST.border}`,
    }}>
      <div style={{
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        marginBottom: 10,
      }}>
        <span className="eyebrow">TOP MOVERS · 24H</span>
        <span className="mono" style={{ fontSize: 9, color: ST.ink4 }}>{movers.length}</span>
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
        {movers.map((m, i) => <MoverRow key={i} {...m} />)}
      </div>
    </section>
  );
}

function MoverRow({ sym, price, chg, signal, conf, group }) {
  const up = chg >= 0;
  const sigColor = signal === 'LONG' ? ST.green : signal === 'SHORT' ? ST.red : null;
  return (
    <div className="fx-lift" style={{
      padding: '10px 11px',
      background: ST.bg2,
      border: `1px solid ${ST.border}`,
      borderRadius: 8,
      display: 'flex', flexDirection: 'column', gap: 8,
    }}>
      {/* row 1 — coin + price + change */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 9 }}>
        <CoinGlyph sym={sym} size={26} />
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 6 }}>
            <span className="mono" style={{ fontSize: 12, fontWeight: 600, color: ST.ink, letterSpacing: '-0.01em' }}>{sym}</span>
            {group && <span className="mono" style={{ fontSize: 9, color: ST.ink4 }}>{ST_GROUP[group].label}</span>}
          </div>
          <div className="mono" style={{ fontSize: 10, color: ST.ink3, marginTop: 1 }}>
            ${ST_fmt.price(price)}
          </div>
        </div>
        <span className="num" style={{
          fontSize: 13, fontWeight: 600,
          color: up ? ST.green : ST.red,
        }}>{ST_fmt.pct(chg, 2)}</span>
      </div>

      {/* row 2 — Shadow signal or empty state */}
      {signal ? (
        <div style={{
          display: 'flex', alignItems: 'center', gap: 6,
          padding: '6px 8px',
          background: `${sigColor}0d`,
          border: `1px solid ${sigColor}30`,
          borderRadius: 5,
        }}>
          <span className="mono" style={{
            fontSize: 9, fontWeight: 700, letterSpacing: '0.1em',
            color: sigColor, background: `${sigColor}24`,
            padding: '2px 5px', borderRadius: 2,
          }}>{signal} · PAPER</span>
          <span className="mono" style={{ fontSize: 9, color: ST.ink3 }}>
            conf <span className="num" style={{ color: sigColor, fontWeight: 600 }}>{conf}</span>
          </span>
          <div style={{ marginLeft: 'auto', display: 'flex', gap: 4 }}>
            <button className="mono" style={{
              fontSize: 9, fontWeight: 700, letterSpacing: '0.08em',
              padding: '3px 8px', borderRadius: 3,
              background: ST.amber, color: '#0B0D14',
              border: 'none', cursor: 'pointer',
            }}>FOLLOW</button>
            <button className="mono" style={{
              fontSize: 9, fontWeight: 600, letterSpacing: '0.08em',
              padding: '3px 8px', borderRadius: 3,
              background: 'transparent', color: ST.ink3,
              border: `1px solid ${ST.border}`, cursor: 'pointer',
            }}>SKIP</button>
          </div>
        </div>
      ) : (
        <div className="mono" style={{
          fontSize: 9, color: ST.ink4, letterSpacing: '0.06em',
          padding: '4px 8px',
          background: ST.bg,
          border: `1px dashed ${ST.border}`,
          borderRadius: 5,
          textAlign: 'center',
        }}>NO SIGNAL · WATCHING</div>
      )}
    </div>
  );
}

/* ═══════════════════════════════════════════════════════════════════
   Market context mini
   ═══════════════════════════════════════════════════════════════════ */
function MarketContextMini({ intel }) {
  /* Live values from /market/intel (normalized in app.jsx), with safe fallback */
  const fg   = Number(intel && intel.fear_greed    != null ? intel.fear_greed    : 25)   || 25;
  const btcd = Number(intel && intel.btc_dominance != null ? intel.btc_dominance : 58.2) || 58.2;
  const mr   = Number(intel && intel.macro_risk    != null ? intel.macro_risk    : 42)   || 42;
  const eqUp = (intel && intel.equity_outlook) ? String(intel.equity_outlook).toUpperCase().startsWith('BULL') : true;
  const regime = (intel && intel.regime) ? String(intel.regime) : 'BEARISH';

  const fgC = fg <= 25 ? ST.red : fg <= 45 ? ST.amber : fg <= 55 ? ST.ink3 : ST.green;
  const fgL = fg <= 25 ? 'EXTREME FEAR' : fg <= 45 ? 'FEAR' : fg <= 55 ? 'NEUTRAL' : fg <= 75 ? 'GREED' : 'EXTREME GREED';
  const mrC = mr >= 60 ? ST.red : mr >= 40 ? ST.amber : ST.green;
  const mrL = mr >= 60 ? 'HIGH' : mr >= 40 ? 'ELEVATED' : 'LOW';

  const tiles = [
    { label: 'FEAR & GREED', valueStr: String(Math.round(fg)),     tag: fgL,                       c: fgC,      bar: fg,   max: 100 },
    { label: 'BTC.D',        valueStr: `${btcd.toFixed(1)}%`,       tag: btcd > 56 ? 'RISING' : 'FALLING', c: ST.amber, bar: btcd, max: 100 },
    { label: 'MACRO RISK',   valueStr: String(Math.round(mr)),     tag: mrL,                       c: mrC,      bar: mr,   max: 100 },
    { label: 'EQUITY',       valueStr: eqUp ? 'BULLISH' : 'BEARISH', tag: 'vs crypto',             c: eqUp ? ST.green : ST.red, bar: eqUp ? 72 : 30, max: 100 },
  ];

  const fgWord  = fg <= 25 ? 'extreme fear' : fg <= 45 ? 'fear' : fg <= 55 ? 'neutral sentiment' : 'greed';
  const domWord = btcd > 56 ? 'rising' : 'easing';
  const reg     = regime.toUpperCase();

  return (
    <section style={{
      padding: '14px 16px 18px',
    }}>
      <div style={{
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        marginBottom: 10,
      }}>
        <span className="eyebrow">MARKET CONTEXT</span>
        <span className="mono" style={{ fontSize: 9, color: ST.ink4 }}>
          <span className="st-live-dot" style={{ marginRight: 6, transform: 'translateY(-1px)' }} />
          shadow.thesis
        </span>
      </div>

      <div style={{
        display: 'grid',
        gridTemplateColumns: '1fr 1fr',
        gap: 8,
      }}>
        {tiles.map((t, i) => <ContextTile key={i} {...t} />)}
      </div>

      <p style={{
        margin: '12px 0 0', fontSize: 11, lineHeight: 1.5,
        color: ST.ink3, textWrap: 'pretty',
      }}>
        BTC dominance {domWord} into <span style={{ color: fgC, fontWeight: 600 }}>{fgWord}</span> · alt risk{' '}
        {mr >= 40 ? 'elevated' : 'contained'}. Shadow holds the{' '}
        <span style={{ color: reg.startsWith('BULL') ? ST.green : ST.amber, fontWeight: 600 }}>{reg.replace('_', ' ')}</span> regime
        and gates momentum entries on a BTC structure flip.
      </p>
    </section>
  );
}

function ContextTile({ label, valueStr, tag, c, bar, max }) {
  return (
    <div style={{
      padding: '10px 10px',
      background: ST.bg2,
      border: `1px solid ${ST.border}`,
      borderRadius: 8,
      display: 'flex', flexDirection: 'column', gap: 6,
      minWidth: 0,
    }}>
      <span className="eyebrow" style={{ fontSize: 8 }}>{label}</span>
      <span className="num" style={{
        fontSize: 17, fontWeight: 600, color: c,
        letterSpacing: '-0.01em', lineHeight: 1,
      }}>{valueStr}</span>
      <div style={{
        height: 3, background: ST.panel, borderRadius: 2, overflow: 'hidden',
        marginTop: 2,
      }}>
        <div style={{
          width: `${(bar / max) * 100}%`, height: '100%',
          background: c, opacity: 0.8,
          boxShadow: `0 0 4px ${c}80`,
        }} />
      </div>
      <span className="mono" style={{
        fontSize: 9, fontWeight: 700, letterSpacing: '0.08em',
        color: c,
      }}>{tag}</span>
    </div>
  );
}

window.ShadowPanel = ShadowPanel;
