/* ═══════════════════════════════════════════════════════════════
   Screens — Dashboard, Signaux, Volatile, Charts, Journal
   ═══════════════════════════════════════════════════════════════ */

const { useEffect: useEffectS, useState: useStateS, useRef: useRefS, useMemo: useMemoS } = React;

/* ────────────────────────────────────────────────────────────────
   DASHBOARD
   ──────────────────────────────────────────────────────────────── */
function DashboardScreen({ onAction }) {
  const { KPI, POSITIONS, ACTIVITY, EQUITY, SIGNALS } = window.MOCK;
  const top3 = [...SIGNALS].filter(s => s.state === "active").sort((a,b)=>b.score-a.score).slice(0, 3);

  return (
    <div className="page">
      <div className="page-header">
        <div>
          <h2>Dashboard</h2>
          <div className="sub mono">{new Date().toLocaleDateString("fr-FR",{weekday:"long",day:"numeric",month:"long",year:"numeric"})} · <span className="bull">Connecté OKX</span></div>
        </div>
        <div style={{ display: "flex", gap: 8 }}>
          <button className="btn ghost"><Icon.Refresh size={14}/> Actualiser</button>
          <button className="btn primary"><Icon.Zap size={14}/> Lancer un scan</button>
        </div>
      </div>

      {/* KPI row */}
      <div className="kpi-grid">
        <KpiCard
          label="P&L TOTAL"
          accent
          main={<PnLDisplay value={KPI.pnlTotal.eur} pct={KPI.pnlTotal.pct} variant="md" />}
          foot={<span className="caption">SUR {KPI.pnlTotal.period} · CAPITAL €{KPI.pnlTotal.capital || 200}</span>}
          sparkline={EQUITY.map(p => p.v).slice(-30)}
        />
        <KpiCard
          label="WIN RATE"
          main={<WinRateGauge value={KPI.winRate.val} />}
          foot={<span className="mono muted">{KPI.winRate.wins}W · {KPI.winRate.losses}L · {KPI.winRate.trades} trades</span>}
        />
        <KpiCard
          label="TRADES"
          main={
            <div style={{ display:"flex", alignItems:"baseline", gap:14 }}>
              <span className="mono primary" style={{ fontSize:34, fontWeight:600, letterSpacing:"-0.03em" }}>{KPI.trades.d}</span>
              <span className="muted" style={{ fontSize:11 }}>aujourd'hui</span>
            </div>
          }
          foot={
            <div className="trades-foot">
              <span className="mono"><span className="muted">7J</span> {KPI.trades.w}</span>
              <span className="mono"><span className="muted">30J</span> {KPI.trades.m}</span>
            </div>
          }
        />
        <KpiCard
          label="DRAWDOWN"
          main={
            <div style={{ display:"flex", alignItems:"baseline", gap:10 }}>
              <span className="mono bear" style={{ fontSize:30, fontWeight:600, letterSpacing:"-0.03em" }}>
                {fmtPct(KPI.drawdown.current)}
              </span>
            </div>
          }
          foot={
            <div style={{ display:"flex", gap:12, fontSize:11 }}>
              <span><span className="caption">MAX</span> <span className="mono bear">{fmtPct(KPI.drawdown.max)}</span></span>
              <span className="dim">·</span>
              <span><span className="caption">SEUIL</span> <span className="mono">−15%</span></span>
            </div>
          }
        />
      </div>

      {/* Crypto price chart full-width */}
      <CryptoChartCard/>


      {/* Positions + Top signals */}
      <div className="dash-split">
        <div className="card">
          <div className="card-header">
            <h3 style={{ textTransform:"none", fontSize:13, color:"var(--text-primary)", letterSpacing:0 }}>Positions ouvertes <span className="muted mono" style={{ fontSize:11, fontWeight:400, marginLeft:6 }}>{POSITIONS.length}</span></h3>
            <button className="btn ghost sm"><Icon.ExternalLink size={12}/> Voir tout</button>
          </div>
          <PositionsTable positions={POSITIONS} />
        </div>

        <div className="card">
          <div className="card-header">
            <h3 style={{ textTransform:"none", fontSize:13, color:"var(--text-primary)", letterSpacing:0 }}>Top signaux actifs</h3>
            <span className="caption">TOP 3</span>
          </div>
          <div style={{ display:"flex", flexDirection:"column" }}>
            {top3.map(s => <TopSignalRow key={s.id} signal={s} />)}
          </div>
        </div>
      </div>

      {/* Activity timeline */}
      <div className="card">
        <div className="card-header">
          <h3 style={{ textTransform:"none", fontSize:13, color:"var(--text-primary)", letterSpacing:0 }}>Activité récente</h3>
          <span className="caption">RÉCENTS</span>
        </div>
        <div className="timeline">
          {ACTIVITY.map((a, i) => <ActivityRow key={i} item={a} />)}
        </div>
      </div>
    </div>
  );
}

function KpiCard({ label, main, foot, accent, sparkline }) {
  return (
    <div className={`card pad kpi-card ${accent ? "kpi-accent" : ""}`}>
      <div className="kpi-label">
        <span className="caption">{label}</span>
        {accent && <span className="kpi-accent-dot"></span>}
      </div>
      <div className="kpi-main">{main}</div>
      {sparkline && (
        <div className="kpi-spark">
          <Sparkline data={sparkline} width={260} height={36} color="var(--bull)" />
        </div>
      )}
      <div className="kpi-foot">{foot}</div>
    </div>
  );
}

function WinRateGauge({ value }) {
  const r = 26;
  const c = 2 * Math.PI * r;
  const offset = c * (1 - value / 100);
  const animated = useCountUp(value, 900);
  return (
    <div style={{ display:"flex", alignItems:"center", gap:14 }}>
      <svg width="72" height="72" style={{ transform:"rotate(-90deg)" }}>
        <circle cx="36" cy="36" r={r} stroke="var(--bg-surface)" strokeWidth="6" fill="none" />
        <circle
          cx="36" cy="36" r={r}
          stroke="url(#wr-grad)" strokeWidth="6" fill="none"
          strokeDasharray={c}
          strokeDashoffset={c * (1 - animated/100)}
          strokeLinecap="round"
          style={{ transition: "stroke-dashoffset 220ms ease-out", filter: "drop-shadow(0 0 6px var(--accent-glow))" }}
        />
        <defs>
          <linearGradient id="wr-grad" x1="0" y1="0" x2="1" y2="1">
            <stop offset="0%" stopColor="var(--accent-500)" />
            <stop offset="100%" stopColor="var(--accent-mag)" />
          </linearGradient>
        </defs>
      </svg>
      <div style={{ display:"flex", flexDirection:"column" }}>
        <span className="mono primary" style={{ fontSize:30, fontWeight:600, letterSpacing:"-0.03em", lineHeight:1 }}>
          {animated.toFixed(1)}<span style={{ fontSize:14, color:"var(--text-muted)", marginLeft:2 }}>%</span>
        </span>
        <span className="caption" style={{ marginTop:4 }}>RATIO W/L</span>
      </div>
    </div>
  );
}

function EquityCurve({ data }) {
  const ref = useRefS(null);
  const [hover, setHover] = useStateS(null);
  const w = 1200; const h = 220;

  const path = useMemoS(() => {
    if (!data || !data.length) return { line:"", area:"" };
    const vs = data.map(d=>d.v); const min=Math.min(...vs); const max=Math.max(...vs);
    const range = max - min || 1;
    const pad = 12;
    const px = (i) => (i / (data.length - 1)) * (w - 2*pad) + pad;
    const py = (v) => h - pad - ((v - min) / range) * (h - 2*pad);
    let line = ""; data.forEach((d, i) => { line += (i===0?"M":"L") + px(i) + "," + py(d.v) + " "; });
    const area = line + ` L${w-pad},${h} L${pad},${h} Z`;
    return { line, area, px, py, min, max };
  }, [data]);

  const isPositive = data[data.length-1].v > data[0].v;
  const color = isPositive ? "var(--bull)" : "var(--bear)";

  function onMove(e) {
    const r = ref.current.getBoundingClientRect();
    const x = (e.clientX - r.left) / r.width * w;
    const i = Math.round((x - 12) / (w - 24) * (data.length - 1));
    if (i >= 0 && i < data.length) setHover({ i, x: path.px(i), y: path.py(data[i].v), v: data[i].v });
  }

  return (
    <div className="equity-wrap" ref={ref} onMouseMove={onMove} onMouseLeave={()=>setHover(null)}>
      <svg viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none" width="100%" height={h}>
        <defs>
          <linearGradient id="eq-grad" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor="var(--accent-500)" stopOpacity="0.35"/>
            <stop offset="100%" stopColor="var(--accent-500)" stopOpacity="0"/>
          </linearGradient>
          <linearGradient id="eq-stroke" x1="0" y1="0" x2="1" y2="0">
            <stop offset="0%" stopColor="var(--accent-500)"/>
            <stop offset="100%" stopColor="var(--accent-mag)"/>
          </linearGradient>
        </defs>
        {/* gridlines */}
        {[0.25, 0.5, 0.75].map(g => (
          <line key={g} x1="0" x2={w} y1={h*g} y2={h*g} stroke="var(--border-subtle)" strokeDasharray="2 4" />
        ))}
        <path d={path.area} fill="url(#eq-grad)" />
        <path d={path.line} stroke="url(#eq-stroke)" strokeWidth="2" fill="none" style={{ filter:"drop-shadow(0 0 8px var(--accent-glow))" }} />
        {/* trade markers */}
        {[15, 38, 62, 88, 110, 135, 158].map(i => (
          <g key={i}>
            <circle cx={path.px(i)} cy={path.py(data[i]?.v || 0)} r="3" fill="var(--accent-400)" opacity="0.7" />
          </g>
        ))}
        {hover && (
          <g>
            <line x1={hover.x} x2={hover.x} y1="0" y2={h} stroke="var(--accent-400)" strokeOpacity="0.4" strokeDasharray="2 3" />
            <circle cx={hover.x} cy={hover.y} r="5" fill="var(--accent-400)" stroke="var(--bg-elevated)" strokeWidth="2" />
          </g>
        )}
      </svg>
      {hover && (
        <div className="equity-tip" style={{ left: `${(hover.x/w)*100}%` }}>
          <span className="caption">JOUR {hover.i}</span>
          <span className="mono primary">€{hover.v.toLocaleString("fr-FR", { maximumFractionDigits:0 })}</span>
        </div>
      )}
    </div>
  );
}

function PositionsTable({ positions }) {
  const isMobile = typeof window !== "undefined" && window.innerWidth < 880;
  if (positions.length === 0) {
    return <div className="muted" style={{ padding:20, textAlign:"center", fontSize:13 }}>Aucune position ouverte</div>;
  }
  if (isMobile) {
    return (
      <div style={{ display:"flex", flexDirection:"column" }}>
        {positions.map(p => <PositionCardMobile key={p.id} p={p}/>)}
      </div>
    );
  }
  return (
    <table className="ptable">
      <thead>
        <tr>
          <th>PAIR</th><th>DIR</th><th>ENTRY</th><th>CURRENT</th><th style={{textAlign:"right"}}>P&L</th><th>SL/TP</th><th></th>
        </tr>
      </thead>
      <tbody>
        {positions.map(p => <PositionRow key={p.id} p={p}/>)}
      </tbody>
    </table>
  );
}

function PositionCardMobile({ p }) {
  const animPnl = useCountUp(p.pnlEur);
  const animPct = useCountUp(p.pnlPct);
  const up = p.pnlEur >= 0;
  return (
    <div style={{ padding:"12px 14px", borderBottom:"1px solid var(--border-subtle)", display:"flex", flexDirection:"column", gap:8 }}>
      <div style={{ display:"flex", alignItems:"center", justifyContent:"space-between", gap:8 }}>
        <div style={{ display:"flex", alignItems:"center", gap:10, minWidth:0 }}>
          <PairLogo pair={p.pair} size={28}/>
          <div style={{ display:"flex", flexDirection:"column", lineHeight:1.1, minWidth:0 }}>
            <div style={{ display:"flex", alignItems:"center", gap:6 }}>
              <span style={{ fontSize:13, fontWeight:600, color:"var(--text-primary)" }}>{p.pair}</span>
              <DirBadge dir={p.direction}/>
            </div>
            <span className="muted mono" style={{ fontSize:10 }}>x{p.lev} · {p.isReal?"RÉEL":"PAPER"}</span>
          </div>
        </div>
        <div style={{ display:"flex", flexDirection:"column", alignItems:"flex-end", gap:1 }}>
          <span className="mono" style={{ color: up?"var(--bull)":"var(--bear)", fontWeight:600, fontSize:16 }}>
            {up?"+":"−"}€{Math.abs(animPnl).toFixed(2)}
          </span>
          <span className="mono" style={{ fontSize:10, color: up?"var(--bull)":"var(--bear)", opacity:0.75 }}>
            {fmtPct(animPct)}
          </span>
        </div>
      </div>
      <div style={{ display:"grid", gridTemplateColumns:"1fr 1fr 1fr", gap:6, fontSize:11 }}>
        <div><span className="caption" style={{ fontSize:9 }}>ENTRY</span><div className="mono">{fmtNum(p.entry)}</div></div>
        <div><span className="caption" style={{ fontSize:9 }}>NOW</span><div className="mono primary">{fmtNum(p.current)}</div></div>
        <div><span className="caption" style={{ fontSize:9 }}>SL/TP1</span><div className="mono"><span className="bear">{fmtNum(p.sl)}</span><br/><span className="bull">{fmtNum(p.tp1)}</span></div></div>
      </div>
      <div style={{ display:"flex", gap:6 }}>
        <button className="btn ghost" style={{ flex:1, fontSize:11, padding:"8px" }} onClick={()=>{
          emitToast({
            type:"info",
            msg: `${p.pair} ${p.direction} x${p.lev}`,
            sub: `Entry ${fmtNum(p.entry)} | SL ${fmtNum(p.sl)} | TP1 ${fmtNum(p.tp1)} | TP2 ${fmtNum(p.tp2)}`,
          });
        }}><Icon.Eye size={12}/> Détails</button>
        <button className="btn" style={{ flex:1, fontSize:11, padding:"8px", background:"var(--bear)", color:"white", border:"1px solid var(--bear)" }} onClick={()=>{
          if (confirm(`Fermer ${p.pair} ${p.direction} ?`)) window.fbClosePos(p).then(()=>emitToast({type:"success",msg:"Fermé"}));
        }}><Icon.X size={12}/> Fermer</button>
      </div>
    </div>
  );
}
function PositionRow({ p }) {
  const animPnl = useCountUp(p.pnlEur);
  const animPct = useCountUp(p.pnlPct);
  const up = p.pnlEur >= 0;
  return (
    <tr className="prow">
      <td>
        <div style={{ display:"flex", alignItems:"center", gap:8 }}>
          <PairLogo pair={p.pair} size={22}/>
          <div style={{ display:"flex", flexDirection:"column", lineHeight:1.05 }}>
            <span style={{ fontSize:12, fontWeight:500, color:"var(--text-primary)" }}>{p.pair}</span>
            <span className="muted mono" style={{ fontSize:10 }}>x{p.lev} · {p.opened}</span>
          </div>
        </div>
      </td>
      <td><DirBadge dir={p.direction}/></td>
      <td className="mono muted">{fmtNum(p.entry)}</td>
      <td className="mono primary">{fmtNum(p.current)}</td>
      <td style={{ textAlign:"right" }}>
        <div style={{ display:"flex", flexDirection:"column", alignItems:"flex-end", gap:1 }}>
          <span className="mono" style={{ color: up?"var(--bull)":"var(--bear)", fontWeight:600 }}>
            {up?"+":"−"}€{Math.abs(animPnl).toFixed(2)}
          </span>
          <span className="mono" style={{ fontSize:10, color: up?"var(--bull)":"var(--bear)", opacity:0.7 }}>
            {fmtPct(animPct)}
          </span>
        </div>
      </td>
      <td className="mono muted" style={{ fontSize:11 }}>
        <div style={{ display:"flex", flexDirection:"column", gap:1 }}>
          <span><span className="bear">↓</span> {fmtNum(p.sl)}</span>
          <span><span className="bull">↑</span> {fmtNum(p.tp1)}</span>
        </div>
      </td>
      <td>
        <div style={{ display:"flex", gap:4, justifyContent:"flex-end" }}>
          <button className="icon-btn" data-tip="Détails" onClick={()=>{
            emitToast({
              type:"info",
              msg: `${p.pair} ${p.direction} x${p.lev} · ${p.isReal ? "RÉEL" : "PAPER"}`,
              sub: `Entry ${fmtNum(p.entry)} → ${fmtNum(p.current)} | SL ${fmtNum(p.sl)} | TP1 ${fmtNum(p.tp1)} | TP2 ${fmtNum(p.tp2)}`,
            });
          }}><Icon.Eye size={13}/></button>
          <button className="icon-btn" data-tip="Fermer position" onClick={()=>{
            if (confirm(`Fermer la position ${p.pair} ${p.direction} ?`)) {
              window.fbClosePos(p).then(()=>emitToast({ type:"success", msg:`Position ${p.pair} fermée` }));
            }
          }}><Icon.X size={13}/></button>
        </div>
      </td>
    </tr>
  );
}

function TopSignalRow({ signal }) {
  return (
    <div className="top-sig-row">
      <PairLogo pair={signal.pair} size={26}/>
      <div style={{ display:"flex", flexDirection:"column", flex:1, minWidth:0, gap:2 }}>
        <div style={{ display:"flex", alignItems:"center", gap:8 }}>
          <span style={{ fontSize:13, fontWeight:500, color:"var(--text-primary)" }}>{signal.pair}/USDT</span>
          <DirBadge dir={signal.direction}/>
        </div>
        <span className="muted" style={{ fontSize:11 }}>{signal.note}</span>
      </div>
      <Sparkline data={signal.sparkline} width={60} height={22} color="auto" fill={false}/>
      <ScoreBadge score={signal.score}/>
    </div>
  );
}

function ActivityRow({ item }) {
  const colorMap = { bull:"var(--bull)", bear:"var(--bear)", accent:"var(--accent-400)", muted:"var(--text-muted)" };
  const iconMap = { "trend-up": Icon.TrendUp, "trend-down": Icon.TrendDown, "zap": Icon.Zap, "shield": Icon.Shield, "x": Icon.X };
  const Ic = iconMap[item.icon] || Icon.Dot;
  return (
    <div className="act-row">
      <div className="act-time mono">{item.t}</div>
      <div className="act-dot" style={{ background: colorMap[item.color] || "var(--text-muted)" }}>
        <Ic size={11} style={{ color:"white" }}/>
      </div>
      <div style={{ display:"flex", flexDirection:"column", gap:2, minWidth:0 }}>
        <span style={{ fontSize:13, color:"var(--text-primary)", fontWeight:500 }}>{item.title}</span>
        <span className="muted" style={{ fontSize:12 }}>{item.desc}</span>
      </div>
    </div>
  );
}

/* ─── Crypto chart card (replaces equity curve) ───────────────── */
function CryptoChartCard() {
  const PAIR_OPTIONS = [
    { id: "BTC/USDT:USDT", sym: "BTC" },
    { id: "ETH/USDT:USDT", sym: "ETH" },
    { id: "SOL/USDT:USDT", sym: "SOL" },
    { id: "XAU/USDT:USDT", sym: "XAU" },
    { id: "DOGE/USDT:USDT", sym: "DOGE" },
  ];
  const TF_OPTIONS = [
    { id: "1D",  bar: "15m", limit: 96  },
    { id: "1W",  bar: "1H",  limit: 168 },
    { id: "1M",  bar: "4H",  limit: 180 },
    { id: "ALL", bar: "1D",  limit: 365 },
  ];
  const [pair, setPair]     = useStateS(PAIR_OPTIONS[0]);
  const [tf,   setTf]       = useStateS(TF_OPTIONS[1]);
  const [data, setData]     = useStateS([]);
  const [loading, setLoad]  = useStateS(true);

  useEffectS(() => {
    const key = new URLSearchParams(location.search).get("key");
    const refresh = (initial) => {
      if (initial) setLoad(true);
      fetch(`/api/candles?pair=${encodeURIComponent(pair.id)}&bar=${tf.bar}&limit=${tf.limit}`, { credentials: "include" })
        .then(r => r.json())
        .then(j => {
          const arr = (j.candles || []).map((c, i) => ({ t: c.t || i, v: parseFloat(c.close) }));
          setData(arr);
          if (initial) setLoad(false);
        })
        .catch(() => { if (initial) setLoad(false); });
    };
    refresh(true);
    const t = setInterval(() => refresh(false), 30000);  // refresh prix toutes les 30s
    return () => clearInterval(t);
  }, [pair.id, tf.id]);

  // Lit le prix LIVE depuis le WS si dispo (sinon last close)
  const store = window.useStore ? window.useStore() : {};
  const livePx = store.PRICES && store.PRICES[pair.sym];
  const last  = livePx || (data.length ? data[data.length - 1].v : 0);
  const first = data.length ? data[0].v : 0;
  const chg   = first > 0 ? ((last - first) / first) * 100 : 0;
  const up    = chg >= 0;

  return (
    <div className="card">
      <div className="card-header">
        <div style={{ display:"flex", flexDirection:"column", gap:2, minWidth:0 }}>
          <div style={{ display:"flex", alignItems:"center", gap:10 }}>
            <h3 style={{ textTransform:"none", fontSize:13, color:"var(--text-primary)", letterSpacing:0, margin:0 }}>{pair.sym}/USDT</h3>
            <span className="mono" style={{ fontSize:18, fontWeight:600, color:"var(--text-primary)", letterSpacing:"-0.02em" }}>
              {loading ? "—" : fmtNum(last)}
            </span>
            <span className={`mono ${up ? "bull" : "bear"}`} style={{ fontSize:12, fontWeight:500 }}>
              {fmtPct(chg)}
            </span>
          </div>
          <span className="caption">PRIX MARCHÉ · {tf.bar.toUpperCase()} · OKX</span>
        </div>
        <div style={{ display:"flex", gap:10, flexWrap:"wrap", justifyContent:"flex-end" }}>
          <div className="chips" style={{ flex:"none" }}>
            {PAIR_OPTIONS.map(p => (
              <div key={p.id} className={`chip ${pair.id===p.id?"active":""}`} onClick={()=>setPair(p)}>
                {p.sym}
              </div>
            ))}
          </div>
          <div className="chips" style={{ flex:"none" }}>
            {TF_OPTIONS.map(t => (
              <div key={t.id} className={`chip ${tf.id===t.id?"active":""}`} onClick={()=>setTf(t)}>
                {t.id}
              </div>
            ))}
          </div>
        </div>
      </div>
      {loading ? (
        <div style={{ height:220, display:"grid", placeItems:"center", color:"var(--text-muted)" }}>Chargement…</div>
      ) : data.length < 2 ? (
        <div style={{ height:220, display:"grid", placeItems:"center", color:"var(--text-muted)" }}>Pas de données</div>
      ) : (
        <PriceCurve data={data} up={up}/>
      )}
    </div>
  );
}

function PriceCurve({ data, up }) {
  const ref = useRefS(null);
  const [hover, setHover] = useStateS(null);
  const w = 1200, h = 220;
  const path = useMemoS(() => {
    if (!data || data.length < 2) return { line:"", area:"" };
    const vs = data.map(d=>d.v);
    const min = Math.min(...vs), max = Math.max(...vs);
    const range = max - min || 1;
    const pad = 12;
    const px = (i) => (i / (data.length - 1)) * (w - 2*pad) + pad;
    const py = (v) => h - pad - ((v - min) / range) * (h - 2*pad);
    let line = ""; data.forEach((d, i) => { line += (i===0?"M":"L") + px(i) + "," + py(d.v) + " "; });
    const area = line + ` L${w-pad},${h} L${pad},${h} Z`;
    return { line, area, px, py, min, max };
  }, [data]);

  function onMove(e) {
    const r = ref.current.getBoundingClientRect();
    const x = (e.clientX - r.left) / r.width * w;
    const i = Math.round((x - 12) / (w - 24) * (data.length - 1));
    if (i >= 0 && i < data.length) setHover({ i, x: path.px(i), y: path.py(data[i].v), v: data[i].v });
  }

  const stroke = up ? "var(--bull)" : "var(--bear)";
  const fill   = up ? "rgba(16,185,129,0.18)" : "rgba(239,68,68,0.18)";

  return (
    <div className="equity-wrap" ref={ref} onMouseMove={onMove} onMouseLeave={()=>setHover(null)}>
      <svg viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none" width="100%" height={h}>
        <defs>
          <linearGradient id="pc-grad" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor={stroke} stopOpacity="0.32"/>
            <stop offset="100%" stopColor={stroke} stopOpacity="0"/>
          </linearGradient>
        </defs>
        {[0.25, 0.5, 0.75].map(g => (
          <line key={g} x1="0" x2={w} y1={h*g} y2={h*g} stroke="var(--border-subtle)" strokeDasharray="2 4"/>
        ))}
        <path d={path.area} fill="url(#pc-grad)"/>
        <path d={path.line} stroke={stroke} strokeWidth="2" fill="none"
              style={{ filter:`drop-shadow(0 0 8px ${stroke})` }}/>
        {hover && (
          <g>
            <line x1={hover.x} x2={hover.x} y1="0" y2={h} stroke={stroke} strokeOpacity="0.4" strokeDasharray="2 3"/>
            <circle cx={hover.x} cy={hover.y} r="5" fill={stroke} stroke="var(--bg-elevated)" strokeWidth="2"/>
          </g>
        )}
      </svg>
      {hover && (
        <div className="equity-tip" style={{ left: `${(hover.x/w)*100}%` }}>
          <span className="caption">POINT {hover.i + 1}/{data.length}</span>
          <span className="mono primary">{fmtNum(hover.v)}</span>
        </div>
      )}
    </div>
  );
}

Object.assign(window, { DashboardScreen });
