// Verdict — live user positions panel.
// Subscribes to VDLive (which fans out HL's webData2 push) and renders perp positions,
// open outcome contracts, and resting limit orders with live MTM.

(function () {
  const { useState, useEffect } = React;
  const FlashNum  = window.VDFlash.FlashNum;
  const TickArrow = window.VDFlash.TickArrow;

  function fmtUsd0(v) { if (v == null) return '—'; const n = Math.round(v); return (n < 0 ? '-$' : '$') + Math.abs(n).toLocaleString(); }
  function fmtUsd2(v) { if (v == null) return '—'; return (v < 0 ? '-$' : '$') + Math.abs(v).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }); }
  function fmtCents(p) { return p == null ? '—' : (p * 100).toFixed(1) + '¢'; }
  function fmtSize(sz) {
    if (sz == null) return '—';
    if (Math.abs(sz) >= 1000) return (sz / 1000).toFixed(2) + 'k';
    return Math.abs(sz) >= 1 ? (+sz).toFixed(2) : (+sz).toFixed(4);
  }
  function fmtTimeAgo(ms) {
    if (!ms) return '—';
    const d = Date.now() - ms;
    if (d < 60_000) return Math.floor(d / 1000) + 's ago';
    if (d < 3_600_000) return Math.floor(d / 60_000) + 'm ago';
    if (d < 86_400_000) return Math.floor(d / 3_600_000) + 'h ago';
    return Math.floor(d / 86_400_000) + 'd ago';
  }

  // ───────── Outcome position card row ─────────
  function OutcomePositionRow({ pos }) {
    const sym = pos.outcome && pos.outcome.parsed && pos.outcome.parsed.underlying;
    const target = pos.outcome && pos.outcome.parsed && pos.outcome.parsed.targetPriceNum;
    const bucket = pos.outcome && pos.outcome.bucketLabel;
    const sideColor = pos.sideName === 'YES' ? 'var(--mint)' : 'var(--coral)';
    // Per-contract avg entry: sum of dollars paid / contracts. HL exposes entryNtl on spot
    // balances, expressed as USDC notional spent. Guard against null/zero.
    const avgEntry = (pos.entryNtl != null && pos.sz > 0) ? pos.entryNtl / pos.sz : null;
    const mtm      = (pos.mark != null && avgEntry != null) ? (pos.mark - avgEntry) * pos.sz : null;
    const mtmPct   = (mtm != null && pos.entryNtl) ? (mtm / pos.entryNtl) * 100 : null;
    const description = bucket
      ? `${sym} settles ${bucket}`
      : (sym && target ? `${sym} > $${target.toLocaleString()}` : pos.outcome?.name || pos.coin);

    return (
      <div style={{
        display: 'grid', gridTemplateColumns: '1.6fr 70px 1fr 1fr 1fr',
        padding: '12px 16px', alignItems: 'center', gap: 12,
        borderBottom: '1px solid var(--line-subtle)',
      }}>
        <div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <span className="cap-sm" style={{
              padding: '2px 6px', color: sideColor,
              border: `1px solid ${sideColor}`, fontWeight: 700, letterSpacing: '0.06em',
            }}>{pos.sideName}</span>
            <span style={{ fontSize: 12.5, fontWeight: 600 }}>{description}</span>
          </div>
          <div className="cap-sm" style={{ marginTop: 4, color: 'var(--text-3)', fontSize: 9.5 }}>
            outcome #{pos.outcome && pos.outcome.outcome} · {pos.coin}
          </div>
        </div>
        <div className="num" style={{ textAlign: 'right', fontSize: 13, fontWeight: 600 }}>{fmtSize(pos.sz)}</div>
        <div className="num" style={{ textAlign: 'right', fontSize: 12 }}>
          <div className="cap-sm" style={{ fontSize: 9 }}>Entry</div>
          {avgEntry != null ? fmtCents(avgEntry) : '—'}
        </div>
        <div className="num" style={{ textAlign: 'right', fontSize: 12 }}>
          <div className="cap-sm" style={{ fontSize: 9, display: 'inline-flex', alignItems: 'center', gap: 4, justifyContent: 'flex-end' }}>
            Mark <TickArrow value={pos.mark} />
          </div>
          <FlashNum value={pos.mark}>{fmtCents(pos.mark)}</FlashNum>
        </div>
        <div className="num" style={{
          textAlign: 'right', fontSize: 13, fontWeight: 700,
          color: mtm == null ? 'var(--text-3)' : (mtm >= 0 ? 'var(--mint)' : 'var(--coral)'),
        }}>
          <div className="cap-sm" style={{ fontSize: 9, color: 'var(--text-3)' }}>MTM</div>
          {mtm == null ? '—' :
            <>
              <FlashNum value={mtm}>{(mtm >= 0 ? '+' : '') + fmtUsd2(mtm)}</FlashNum>
              {mtmPct != null && (
                <div className="cap-sm" style={{ fontSize: 9, marginTop: 1, color: 'inherit', opacity: 0.7 }}>
                  {(mtmPct >= 0 ? '+' : '') + mtmPct.toFixed(2)}%
                </div>
              )}
            </>
          }
        </div>
      </div>
    );
  }

  function PerpPositionRow({ pos }) {
    const isLong = +pos.szi > 0;
    const sideColor = isLong ? 'var(--mint)' : 'var(--coral)';
    const upnl = +pos.unrealizedPnl;
    const roe = pos.returnOnEquity != null ? +pos.returnOnEquity * 100 : null;
    return (
      <div style={{
        display: 'grid', gridTemplateColumns: '1.6fr 70px 1fr 1fr 1fr',
        padding: '12px 16px', alignItems: 'center', gap: 12,
        borderBottom: '1px solid var(--line-subtle)',
      }}>
        <div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <span className="cap-sm" style={{
              padding: '2px 6px', color: sideColor,
              border: `1px solid ${sideColor}`, fontWeight: 700, letterSpacing: '0.06em',
            }}>{isLong ? 'LONG' : 'SHORT'}</span>
            <span style={{ fontSize: 12.5, fontWeight: 600 }}>{pos.coin} perp</span>
          </div>
          <div className="cap-sm" style={{ marginTop: 4, color: 'var(--text-3)', fontSize: 9.5 }}>
            {pos.leverage ? `${pos.leverage.value}× ${pos.leverage.type}` : 'cross'}
            {pos.liquidationPx ? ` · liq @ $${(+pos.liquidationPx).toLocaleString()}` : ''}
          </div>
        </div>
        <div className="num" style={{ textAlign: 'right', fontSize: 13, fontWeight: 600 }}>{Math.abs(+pos.szi).toFixed(4)}</div>
        <div className="num" style={{ textAlign: 'right', fontSize: 12 }}>
          <div className="cap-sm" style={{ fontSize: 9 }}>Entry</div>
          ${(+pos.entryPx).toLocaleString()}
        </div>
        <div className="num" style={{ textAlign: 'right', fontSize: 12 }}>
          <div className="cap-sm" style={{ fontSize: 9 }}>Notional</div>
          {fmtUsd0(+pos.positionValue)}
        </div>
        <div className="num" style={{
          textAlign: 'right', fontSize: 13, fontWeight: 700,
          color: upnl >= 0 ? 'var(--mint)' : 'var(--coral)',
        }}>
          <div className="cap-sm" style={{ fontSize: 9, color: 'var(--text-3)' }}>uPnL</div>
          <FlashNum value={upnl}>{(upnl >= 0 ? '+' : '') + fmtUsd2(upnl)}</FlashNum>
          {roe != null && (
            <div className="cap-sm" style={{ fontSize: 9, marginTop: 1, color: 'inherit', opacity: 0.7 }}>
              {(roe >= 0 ? '+' : '') + roe.toFixed(2)}%
            </div>
          )}
        </div>
      </div>
    );
  }

  function OrderRow({ order }) {
    const isBuy = order.side === 'B';
    const tone = isBuy ? 'var(--mint)' : 'var(--coral)';
    const px = +order.limitPx;
    const sz = +order.sz;
    const isOutcome = order.isOutcome;
    return (
      <div style={{
        display: 'grid', gridTemplateColumns: '1.6fr 70px 1fr 1fr 1fr',
        padding: '12px 16px', alignItems: 'center', gap: 12,
        borderBottom: '1px solid var(--line-subtle)',
      }}>
        <div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <span className="cap-sm" style={{
              padding: '2px 6px', color: tone,
              border: `1px solid ${tone}`, fontWeight: 700, letterSpacing: '0.06em',
            }}>{isBuy ? 'BUY' : 'SELL'}</span>
            <span style={{ fontSize: 12.5, fontWeight: 600 }}>{order.marketLabel}</span>
          </div>
          <div className="cap-sm" style={{ marginTop: 4, color: 'var(--text-3)', fontSize: 9.5 }}>
            oid {order.oid} · {order.tif || 'Gtc'}
          </div>
        </div>
        <div className="num" style={{ textAlign: 'right', fontSize: 13, fontWeight: 600 }}>{fmtSize(sz)}</div>
        <div className="num" style={{ textAlign: 'right', fontSize: 12 }}>
          <div className="cap-sm" style={{ fontSize: 9 }}>Limit</div>
          {isOutcome ? fmtCents(px) : '$' + px.toLocaleString()}
        </div>
        <div className="num" style={{ textAlign: 'right', fontSize: 12 }}>
          <div className="cap-sm" style={{ fontSize: 9 }}>Size·Px</div>
          {isOutcome ? fmtUsd0(sz * px) : fmtUsd0(sz * px)}
        </div>
        <div className="cap-sm" style={{ textAlign: 'right', fontSize: 10, color: 'var(--text-3)' }}>
          {fmtTimeAgo(order.timestamp)}
        </div>
      </div>
    );
  }

  function PositionsPanel() {
    const [snap, setSnap] = useState(window.VDLive ? window.VDLive.state : null);

    useEffect(() => {
      if (!window.VDLive) return;
      return window.VDLive.subscribe((s) => setSnap({
        ...s,
        user: s.user ? { ...s.user,
          perpPositions: s.user.perpPositions.slice(),
          outcomePositions: s.user.outcomePositions.slice(),
          openOrders: s.user.openOrders.slice(),
        } : null,
        wallet: { ...s.wallet },
      }));
    }, []);

    if (!snap) return null;
    const wallet = snap.wallet || {};
    const u = snap.user || {};

    if (!wallet.address) {
      return (
        <div style={{ marginTop: 32 }}>
          <div className="cap" style={{ color: 'var(--text-2)', marginBottom: 14 }}>↳ Your positions</div>
          <div className="card" style={{ padding: 28, textAlign: 'center', color: 'var(--text-3)' }}>
            <div style={{ fontSize: 13, marginBottom: 8 }}>Connect your wallet to see your live HIP-4 outcome positions, perp positions, and resting orders.</div>
            <div className="cap-sm">Use the wallet pill in the top right.</div>
          </div>
        </div>
      );
    }

    if (!u.isLoaded) {
      return (
        <div style={{ marginTop: 32 }}>
          <div className="cap" style={{ color: 'var(--text-2)', marginBottom: 14 }}>↳ Your positions</div>
          <div className="card" style={{ padding: 28, textAlign: 'center', color: 'var(--text-3)' }}>
            <div className="skel" style={{ height: 16, width: '40%', margin: '0 auto 8px' }} />
            <div className="cap-sm">Loading account from Hyperliquid…</div>
          </div>
        </div>
      );
    }

    const ms = u.marginSummary || {};
    const accountValue = ms.accountValue ? +ms.accountValue : null;
    const totalNtlPos  = ms.totalNtlPos  ? +ms.totalNtlPos : null;
    const withdrawable = u.withdrawable ? +u.withdrawable : null;

    // Aggregate outcome MTM
    const outcomeMtm = u.outcomePositions.reduce((s, p) => {
      const avg = (p.entryNtl != null && p.sz > 0) ? p.entryNtl / p.sz : null;
      if (avg == null || p.mark == null) return s;
      return s + (p.mark - avg) * p.sz;
    }, 0);
    // Aggregate perp uPnL
    const perpUpnl = u.perpPositions.reduce((s, p) => s + (+p.unrealizedPnl || 0), 0);

    const totalPositions = u.perpPositions.length + u.outcomePositions.length;
    const totalOrders    = u.openOrders.length;

    return (
      <div style={{ marginTop: 32 }}>
        <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 14, gap: 12 }}>
          <span className="cap" style={{ color: 'var(--text-2)' }}>↳ Your positions on Hyperliquid</span>
          <span className="cap-sm" style={{ color: 'var(--text-3)' }}>
            <span className="live-dot" style={{ display: 'inline-block', width: 6, height: 6, borderRadius: '50%', background: 'var(--mint)', marginRight: 6 }} />
            live · webData2
          </span>
        </div>

        {/* Account summary strip */}
        <div className="card" style={{ padding: 0, marginBottom: 12 }}>
          <div style={{
            display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)',
            padding: '14px 18px',
          }}>
            <div>
              <div className="cap-sm" style={{ marginBottom: 4 }}>Account value</div>
              <div className="num" style={{ fontSize: 22, fontWeight: 600, letterSpacing: '-0.02em' }}>
                <FlashNum value={accountValue}>{fmtUsd2(accountValue)}</FlashNum>
              </div>
            </div>
            <div>
              <div className="cap-sm" style={{ marginBottom: 4 }}>Open notional</div>
              <div className="num" style={{ fontSize: 16, fontWeight: 500 }}>{fmtUsd0(totalNtlPos)}</div>
            </div>
            <div>
              <div className="cap-sm" style={{ marginBottom: 4 }}>Withdrawable</div>
              <div className="num" style={{ fontSize: 16, fontWeight: 500 }}>{fmtUsd0(withdrawable)}</div>
            </div>
            <div>
              <div className="cap-sm" style={{ marginBottom: 4 }}>Open MTM (perp+outcome)</div>
              <div className="num" style={{
                fontSize: 16, fontWeight: 600,
                color: (perpUpnl + outcomeMtm) >= 0 ? 'var(--mint)' : 'var(--coral)',
              }}>
                <FlashNum value={perpUpnl + outcomeMtm}>
                  {((perpUpnl + outcomeMtm) >= 0 ? '+' : '') + fmtUsd2(perpUpnl + outcomeMtm)}
                </FlashNum>
              </div>
            </div>
          </div>
        </div>

        {/* Trading stats strip — derived from lifetime userFills */}
        <StatsStrip stats={u.stats} />

        {/* Historical P&L chart — drawn from lifetime fills */}
        <div style={{ marginBottom: 24 }}>
          <HistoricalPnlChart fills={u.fills} />
        </div>

        {/* OPEN BOOK — your resting orders, surfaced first because they're "what you're trying to do" */}
        <SectionHeader label={`Your open book · ${totalOrders} resting`} />
        <div className="card" style={{ borderTop: 'none', borderRadius: 0, marginBottom: 24 }}>
          {totalOrders === 0 ? (
            <div style={{ padding: 24, textAlign: 'center', color: 'var(--text-3)', fontSize: 12 }}>
              No resting orders. Place a limit order to see it here.
            </div>
          ) : (
            <div>
              <div className="cap" style={{
                display: 'grid', gridTemplateColumns: '1.6fr 70px 1fr 1fr 1fr',
                padding: '10px 16px', borderBottom: '1px solid var(--line-subtle)',
                color: 'var(--text-3)', gap: 12,
              }}>
                <div>Order</div>
                <div style={{ textAlign: 'right' }}>Size</div>
                <div style={{ textAlign: 'right' }}>Limit</div>
                <div style={{ textAlign: 'right' }}>Notional</div>
                <div style={{ textAlign: 'right' }}>Placed</div>
              </div>
              {u.openOrders.slice(0, 50).map(o => (
                <OrderRow key={o.oid} order={o} />
              ))}
              {u.openOrders.length > 50 && (
                <div className="cap-sm" style={{ padding: 10, textAlign: 'center', color: 'var(--text-3)' }}>
                  Showing first 50 of {u.openOrders.length} resting orders.
                </div>
              )}
            </div>
          )}
        </div>

        {/* OPEN POSITIONS — what's actually risked in the market */}
        <SectionHeader label={`Open positions · ${totalPositions}`} />
        <div className="card" style={{ borderTop: 'none', borderRadius: 0 }}>
          {totalPositions === 0 ? (
            <div style={{ padding: 24, textAlign: 'center', color: 'var(--text-3)', fontSize: 12 }}>
              No open positions. Once an order fills, the position appears here.
            </div>
          ) : (
            <div>
              <div className="cap" style={{
                display: 'grid', gridTemplateColumns: '1.6fr 70px 1fr 1fr 1fr',
                padding: '10px 16px', borderBottom: '1px solid var(--line-subtle)',
                color: 'var(--text-3)', gap: 12,
              }}>
                <div>Market</div>
                <div style={{ textAlign: 'right' }}>Size</div>
                <div style={{ textAlign: 'right' }}>Entry</div>
                <div style={{ textAlign: 'right' }}>Mark / Notional</div>
                <div style={{ textAlign: 'right' }}>P&amp;L</div>
              </div>
              {u.outcomePositions.map(p => (
                <OutcomePositionRow key={p.coin} pos={p} />
              ))}
              {u.perpPositions.map(p => (
                <PerpPositionRow key={p.coin} pos={p} />
              ))}
            </div>
          )}
        </div>
      </div>
    );
  }

  // ─────────── Historical P&L chart ───────────
  // Cumulative realized P&L over time, computed from userFills.
  function HistoricalPnlChart({ fills }) {
    const [rangeKey, setRangeKey] = useState('ALL');
    const wrapRef = React.useRef(null);
    const [size, setSize] = useState({ w: 800, h: 200 });
    const [hover, setHover] = useState(null);

    useEffect(() => {
      if (!wrapRef.current) return;
      const ro = new ResizeObserver((es) => {
        const cr = es[0].contentRect;
        setSize({ w: Math.max(320, Math.floor(cr.width)), h: 200 });
      });
      ro.observe(wrapRef.current);
      return () => ro.disconnect();
    }, []);

    const ranges = [
      { key: '24H',  ms: 24 * 3600 * 1000 },
      { key: '7D',   ms: 7 * 24 * 3600 * 1000 },
      { key: '30D',  ms: 30 * 24 * 3600 * 1000 },
      { key: 'ALL',  ms: null },
    ];
    const range = ranges.find(r => r.key === rangeKey) || ranges[3];
    const now = Date.now();
    const cutoff = range.ms != null ? now - range.ms : 0;

    // Sort fills oldest → newest, compute cumulative realized PnL through time
    const series = React.useMemo(() => {
      const sorted = (fills || []).slice().sort((a, b) => a.time - b.time);
      let cum = 0;
      const pts = [];
      for (const f of sorted) {
        cum += +f.closedPnl || 0;
        pts.push({ t: f.time, p: cum, fill: f });
      }
      return pts;
    }, [fills]);

    // For range-filtering, we want the cumulative P&L delta over the period — i.e. start from
    // whatever the cumulative was at the cutoff, then plot relative motion from there.
    const filtered = React.useMemo(() => {
      if (!series.length) return [];
      if (cutoff === 0) return series;
      // Find the first point >= cutoff; baseline = last cum before cutoff
      let baseline = 0;
      let startIdx = 0;
      for (let i = 0; i < series.length; i++) {
        if (series[i].t < cutoff) baseline = series[i].p;
        else { startIdx = i; break; }
      }
      // Also include a synthetic anchor at cutoff with cumulative = baseline
      const out = series.slice(startIdx).map(p => ({ ...p, p: p.p - baseline }));
      return [{ t: cutoff, p: 0 }].concat(out);
    }, [series, cutoff]);

    const M = { l: 10, r: 56, t: 12, b: 24 };
    const W = size.w, H = size.h;
    const innerW = Math.max(10, W - M.l - M.r);
    const innerH = Math.max(10, H - M.t - M.b);

    if (!filtered.length || filtered.length === 1) {
      return (
        <div ref={wrapRef} style={{ width: '100%' }}>
          <ChartHeader rangeKey={rangeKey} setRangeKey={setRangeKey} ranges={ranges} />
          <div style={{ height: H, display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--text-3)', fontSize: 12, border: '1px solid var(--line-subtle)', borderTop: 'none' }}>
            No fills in this range yet.
          </div>
        </div>
      );
    }

    const tMin = filtered[0].t;
    const tMax = filtered[filtered.length - 1].t || (tMin + 1);
    const ys = filtered.map(p => p.p);
    const yMinR = Math.min(0, ...ys);
    const yMaxR = Math.max(0, ...ys);
    const yPad = Math.max((yMaxR - yMinR) * 0.10, Math.abs(yMaxR + yMinR) * 0.001 || 1);
    const yMin = yMinR - yPad;
    const yMax = yMaxR + yPad;

    const xScale = (t) => M.l + ((t - tMin) / (tMax - tMin || 1)) * innerW;
    const yScale = (p) => M.t + (1 - (p - yMin) / (yMax - yMin || 1)) * innerH;

    const last = filtered[filtered.length - 1];
    const totalPnl = last.p;
    const tone = totalPnl >= 0 ? 'mint' : 'coral';
    const toneColor = totalPnl >= 0 ? 'var(--mint)' : 'var(--coral)';

    const linePath = filtered.map((p, i) => `${i === 0 ? 'M' : 'L'} ${xScale(p.t).toFixed(2)} ${yScale(p.p).toFixed(2)}`).join(' ');
    const zeroY = yScale(0);

    function onMove(e) {
      const r = e.currentTarget.getBoundingClientRect();
      const mx = e.clientX - r.left;
      let best = 0, bestDist = Infinity;
      for (let i = 0; i < filtered.length; i++) {
        const sx = xScale(filtered[i].t);
        const d = Math.abs(sx - mx);
        if (d < bestDist) { best = i; bestDist = d; }
      }
      const p = filtered[best];
      setHover({ x: xScale(p.t), y: yScale(p.p), t: p.t, pnl: p.p });
    }
    function onLeave() { setHover(null); }

    return (
      <div ref={wrapRef} style={{ width: '100%' }}>
        <ChartHeader rangeKey={rangeKey} setRangeKey={setRangeKey} ranges={ranges}
          right={
            <div className="num" style={{ fontSize: 16, fontWeight: 700, color: toneColor }}>
              {(totalPnl >= 0 ? '+' : '') + fmtUsd2(totalPnl)}
              <span className="cap-sm" style={{ marginLeft: 6, color: 'var(--text-3)', fontSize: 9 }}>
                {filtered.length - 1} fills
              </span>
            </div>
          } />
        <div style={{ position: 'relative', width: '100%', height: H, border: '1px solid var(--line-subtle)', borderTop: 'none', overflow: 'hidden' }}>
          <svg width={W} height={H} style={{ display: 'block' }}>
            <defs>
              <linearGradient id="vd-pnl-grad-pos" x1="0" y1="0" x2="0" y2="1">
                <stop offset="0%"   stopColor="#6BE5C1" stopOpacity="0.20" />
                <stop offset="100%" stopColor="#6BE5C1" stopOpacity="0" />
              </linearGradient>
              <linearGradient id="vd-pnl-grad-neg" x1="0" y1="1" x2="0" y2="0">
                <stop offset="0%"   stopColor="#FF5C6E" stopOpacity="0.20" />
                <stop offset="100%" stopColor="#FF5C6E" stopOpacity="0" />
              </linearGradient>
            </defs>
            {/* Zero line */}
            <line x1={M.l} y1={zeroY} x2={M.l + innerW} y2={zeroY}
                  stroke="var(--text-3)" strokeOpacity="0.4" strokeDasharray="3 3" />
            {/* Area fill via path-to-zero-line */}
            <path d={`${linePath} L ${xScale(last.t).toFixed(2)} ${zeroY} L ${xScale(filtered[0].t).toFixed(2)} ${zeroY} Z`}
                  fill={totalPnl >= 0 ? 'url(#vd-pnl-grad-pos)' : 'url(#vd-pnl-grad-neg)'} />
            {/* Line */}
            <path d={linePath} fill="none" stroke={toneColor} strokeWidth="1.6" strokeLinejoin="round" />

            {/* Y-axis labels */}
            <text x={M.l + innerW + 6} y={yScale(yMaxR)} dy="0.32em" style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 10, fill: 'var(--mint)' }}>{fmtUsd0(yMaxR)}</text>
            <text x={M.l + innerW + 6} y={yScale(yMinR)} dy="0.32em" style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 10, fill: 'var(--coral)' }}>{fmtUsd0(yMinR)}</text>
            <text x={M.l + innerW + 6} y={zeroY}        dy="0.32em" style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 10, fill: 'var(--text-3)' }}>$0</text>

            {/* Hover */}
            {hover && (
              <g pointerEvents="none">
                <line x1={hover.x} y1={M.t} x2={hover.x} y2={M.t + innerH}
                      stroke="var(--text-2)" strokeOpacity="0.4" strokeDasharray="3 3" />
                <circle cx={hover.x} cy={hover.y} r="4" fill="var(--bg-base)"
                        stroke={hover.pnl >= 0 ? 'var(--mint)' : 'var(--coral)'} strokeWidth="1.5" />
              </g>
            )}

            {/* Mouse capture */}
            <rect x={M.l} y={M.t} width={innerW} height={innerH} fill="transparent"
                  onMouseMove={onMove} onMouseLeave={onLeave} style={{ cursor: 'crosshair' }} />
          </svg>

          {hover && (
            <div style={{
              position: 'absolute',
              left: Math.max(8, Math.min(W - 180, hover.x + 12)),
              top:  Math.max(8, hover.y - 56),
              padding: '8px 10px',
              background: 'var(--bg-elev-3)',
              border: '1px solid var(--line)',
              borderRadius: 'var(--r)',
              pointerEvents: 'none',
              minWidth: 160,
            }}>
              <div className="cap-sm">{new Date(hover.t).toLocaleString(undefined, { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })}</div>
              <div className="num" style={{ fontSize: 14, fontWeight: 700, color: hover.pnl >= 0 ? 'var(--mint)' : 'var(--coral)' }}>
                {(hover.pnl >= 0 ? '+' : '') + fmtUsd2(hover.pnl)}
              </div>
            </div>
          )}
        </div>
      </div>
    );
  }
  function ChartHeader({ rangeKey, setRangeKey, ranges, right }) {
    return (
      <div style={{
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        padding: '10px 14px', border: '1px solid var(--line-subtle)',
        background: 'var(--bg-elev-2)',
      }}>
        <span className="cap-sm" style={{ color: 'var(--text)', fontWeight: 600, letterSpacing: '0.08em' }}>
          Cumulative realized P&amp;L
        </span>
        <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
          {right}
          <div style={{ display: 'flex', border: '1px solid var(--line-subtle)' }}>
            {ranges.map(r => {
              const active = r.key === rangeKey;
              return (
                <button key={r.key} onClick={() => setRangeKey(r.key)} className="cap-sm" style={{
                  padding: '4px 10px',
                  background: active ? 'var(--acid-bg10)' : 'transparent',
                  color: active ? 'var(--acid)' : 'var(--text-3)',
                  borderRight: '1px solid var(--line-subtle)',
                }}>{r.key}</button>
              );
            })}
          </div>
        </div>
      </div>
    );
  }

  // Section header that pairs with a borderless card below — visually one block
  function SectionHeader({ label }) {
    return (
      <div style={{
        display: 'flex', alignItems: 'center',
        padding: '10px 18px',
        background: 'var(--bg-elev-2)',
        border: '1px solid var(--line-subtle)',
        borderBottom: 'none',
        borderRadius: 0,
      }}>
        <span className="cap-sm" style={{ color: 'var(--text)', fontWeight: 600, letterSpacing: '0.08em' }}>{label}</span>
      </div>
    );
  }

  // Lifetime trading stats — fills-derived (volume, realized P&L, fees, win rate, etc.)
  function StatsStrip({ stats }) {
    const s = stats || { count: 0, volume: 0, fees: 0, realizedPnl: 0, last24hPnl: 0, last7dPnl: 0, winRate: null, byCoin: {} };
    // Find top market by volume (filter perp + outcome separately can come later)
    const topCoin = Object.entries(s.byCoin || {}).sort((a, b) => b[1] - a[1])[0];
    return (
      <div className="card" style={{ padding: 0, marginBottom: 24 }}>
        <div style={{ padding: '8px 18px', borderBottom: '1px solid var(--line-subtle)' }}>
          <span className="cap-sm" style={{ color: 'var(--text-3)' }}>↳ Trading stats · all-time on Hyperliquid</span>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(6, 1fr)', padding: '14px 18px', gap: 0 }}>
          <Cell label="Trades" value={s.count.toLocaleString()} />
          <Cell label="Volume"
                value={s.volume >= 1_000_000 ? '$' + (s.volume / 1_000_000).toFixed(2) + 'M' :
                       s.volume >= 1_000     ? '$' + (s.volume / 1_000).toFixed(1)     + 'k' :
                                                fmtUsd0(s.volume)} />
          <Cell label="Realized P&L"
                value={(s.realizedPnl >= 0 ? '+' : '') + fmtUsd2(s.realizedPnl)}
                tone={s.realizedPnl >= 0 ? 'mint' : 'coral'} />
          <Cell label="P&L · 24h"
                value={(s.last24hPnl >= 0 ? '+' : '') + fmtUsd2(s.last24hPnl)}
                tone={s.last24hPnl >= 0 ? 'mint' : 'coral'} />
          <Cell label="Fees paid" value={fmtUsd2(s.fees)} muted />
          <Cell label="Win rate"
                value={s.winRate != null ? (s.winRate * 100).toFixed(1) + '%' : '—'}
                sub={s.winRate != null ? `${s.winners}W · ${s.losers}L` : ''} />
        </div>
        {topCoin && (
          <div className="cap-sm" style={{ padding: '6px 18px 12px', color: 'var(--text-3)', fontSize: 9.5 }}>
            Most-traded: <span style={{ color: 'var(--text-2)' }}>{topCoin[0]}</span> · {fmtUsd0(topCoin[1])} volume
          </div>
        )}
      </div>
    );
  }
  function Cell({ label, value, sub, tone, muted }) {
    const color = tone === 'mint' ? 'var(--mint)' : tone === 'coral' ? 'var(--coral)' : (muted ? 'var(--text-2)' : 'var(--text)');
    return (
      <div>
        <div className="cap-sm" style={{ marginBottom: 4 }}>{label}</div>
        <div className="num" style={{ fontSize: 15, fontWeight: 600, color }}>{value}</div>
        {sub && <div className="cap-sm" style={{ fontSize: 9, color: 'var(--text-3)', marginTop: 2 }}>{sub}</div>}
      </div>
    );
  }

  window.VDLivePositions = { PositionsPanel };
})();
