/* LabPage — "Weekly Lab". The standing trade-data examination, OPTIONS world. Every Friday
   after the close the bot replays EVERY taped trade through the live strategy's current exit
   rules (src/weekly_lab.py, the real engine) and stores one report per ISO week in
   `lab_reports`. This page renders those reports in full detail: trade anatomy, streak
   statistics, weekday/month/hour seasonality, adaptive-sizing simulations and the week-by-week
   trend — so patterns ("Tuesday is poison", "August is a small-size month") firm up as the
   data grows over months and years. Older reports stay selectable to see how verdicts evolved. */
function LabPage() {
  const NT = window.NitroTraderDesignSystem_95e598;
  const [reports, setReports] = React.useState(null);   // [{week_start, created_at, report}] newest first
  const [sel, setSel] = React.useState(null);           // selected week_start
  const [err, setErr] = React.useState("");

  const load = React.useCallback(async () => {
    const c = window.NT_CLIENT;
    if (!c) { setErr("not connected"); setReports([]); return; }
    setReports(null); setErr("");
    try {
      const r = await c.from("lab_reports").select("week_start,created_at,report")
        .order("week_start", { ascending: false }).limit(120);
      if (r.error) throw r.error;
      setReports(r.data || []);
      if ((r.data || []).length) setSel((s) => s || r.data[0].week_start);
    } catch (e) { setErr(e.message || String(e)); setReports([]); }
  }, []);
  React.useEffect(() => { load(); }, [load]);

  /* Data coverage — the "visual database" (Gianni, 5 Sep): every ENTRY alert ever, matched
     against the recorded tapes, so missing data is visible at a glance. No P&L — pure
     inventory. Live from the DB on page load, not from the weekly report. */
  const [cov, setCov] = React.useState(null);
  const [covSrc, setCovSrc] = React.useState("all");
  React.useEffect(() => {
    const c = window.NT_CLIENT;
    if (!c) { setCov([]); return; }
    (async () => {
      try {
        const [alR, poolR, srcR] = await Promise.all([
          c.from("alerts").select("ts,ticker,source_id,raw").eq("type", "ENTRY").order("ts", { ascending: false }).limit(1000),
          c.from("replay_pool_cache").select("ticker,strike,side,entry_ts,ticks,entry_price,peak_price,low_price,tape_first,tape_last"),
          c.from("sources").select("id,name,type,category"),
        ]);
        const pool = poolR.data || [];
        const srcName = {}, srcCat = {};
        (srcR.data || []).forEach((s2) => { srcName[s2.id] = s2.name || s2.type || ("source " + s2.id); srcCat[s2.id] = s2.category; });
        // OPTIONS world only (Gianni, 5 Sep): drop alerts from sources of any other
        // category (futures channels share the alerts table); no source = legacy options.
        const optionsOnly = (alR.data || []).filter((a) => a.source_id == null || srcCat[a.source_id] == null || srcCat[a.source_id] === "options");
        const rows = optionsOnly.map((a) => {
          const t0 = new Date(a.ts).getTime();
          let best = null;
          pool.forEach((p2) => {
            if (p2.ticker !== a.ticker) return;
            const dt = new Date(p2.entry_ts).getTime() - t0;
            if (dt < -3 * 60000 || dt > 15 * 60000) return;
            if (!best || Math.abs(dt) < Math.abs(best.dt)) best = { ...p2, dt };
          });
          const ep = best ? Number(best.entry_price) : 0;
          const pk = (best && best.peak_price != null && ep) ? (Number(best.peak_price) / ep - 1) * 100 : null;
          const dd = (best && best.low_price != null && ep) ? (Number(best.low_price) / ep - 1) * 100 : null;
          const mins = (best && best.tape_first && best.tape_last)
            ? Math.round((new Date(best.tape_last) - new Date(best.tape_first)) / 60000) : null;
          return { ts: a.ts, ticker: a.ticker, source: srcName[a.source_id] || (a.source_id == null ? "\u2014" : "src " + a.source_id),
                   contract: best ? (String(Number(best.strike)) + (best.side || "")) : null,
                   ticks: best ? Number(best.ticks) : 0, taped: !!best,
                   peak: pk, dd: dd, mins: mins };
        });
        setCov(rows);
      } catch (e) { setCov([]); }
    })();
  }, []);

  const cur = (reports || []).find((r) => r.week_start === sel) || (reports || [])[0] || null;
  const R = cur ? cur.report : null;

  const pct = (n) => (n == null ? "—" : (n > 0 ? "+" : n < 0 ? "−" : "") + Math.abs(n).toFixed(1) + "%");
  const pct0 = (n) => (n == null ? "—" : (n > 0 ? "+" : n < 0 ? "−" : "") + Math.abs(n).toFixed(0) + "%");
  const money = (n) => (n > 0 ? "+$" : n < 0 ? "−$" : "$") + Math.abs(Math.round(n)).toLocaleString("en-US");
  const tone = (n) => (n == null ? "var(--text-tertiary)" : n > 0 ? "var(--profit)" : n < 0 ? "var(--loss)" : "var(--text-secondary)");
  const th = { font: "var(--w-medium) var(--t-2xs)/1 var(--font-sans)", letterSpacing: "var(--ls-wide)", textTransform: "uppercase", color: "var(--text-tertiary)", padding: "10px 0", textAlign: "right", whiteSpace: "nowrap" };
  const thL = { ...th, textAlign: "left" };
  const td = { font: "var(--w-regular) var(--t-sm)/1 var(--font-mono)", fontVariantNumeric: "tabular-nums", padding: "10px 0", borderTop: "1px solid var(--row-line)", textAlign: "right", color: "var(--text-primary)", whiteSpace: "nowrap" };
  const tdL = { ...td, textAlign: "left", font: "var(--w-regular) var(--t-sm)/1 var(--font-sans)" };
  const MONTH_LABEL = (ym) => { try { const [y, m] = ym.split("-"); return new Date(Date.UTC(+y, +m - 1, 1)).toLocaleDateString("en-GB", { month: "short", year: "numeric", timeZone: "UTC" }); } catch (e) { return ym; } };
  const winRate = (r) => (r.n ? Math.round(100 * r.wins / r.n) + "%" : "—");

  /* stat tile inside the headline card */
  const Tile = ({ label, value, sub, color }) => (
    <div style={{ display: "flex", flexDirection: "column", gap: 7, padding: "4px 0" }}>
      <span style={{ font: "var(--w-medium) var(--t-2xs)/1 var(--font-sans)", letterSpacing: "var(--ls-wide)", textTransform: "uppercase", color: "var(--text-tertiary)" }}>{label}</span>
      <span style={{ font: "var(--w-light) var(--t-2xl)/1 var(--font-mono)", fontVariantNumeric: "tabular-nums", color: color || "var(--text-primary)" }}>{value}</span>
      {sub ? <span style={{ font: "var(--w-regular) var(--t-xs)/1.4 var(--font-sans)", color: "var(--text-secondary)" }}>{sub}</span> : null}
    </div>
  );

  /* small seasonality table (weekday / month / hour / nth share one shape) */
  const MiniTable = ({ rows, keyLabel, labelOf }) => (
    <table style={{ width: "100%", borderCollapse: "collapse" }}>
      <thead><tr><th style={thL}>{keyLabel}</th><th style={th}>trades</th><th style={th}>wins</th><th style={th}>p&l</th></tr></thead>
      <tbody>
        {rows.map((r) => (
          <tr key={r.k}>
            <td style={tdL}>{labelOf ? labelOf(r.k) : r.k}</td>
            <td style={{ ...td, color: "var(--text-secondary)" }}>{r.n}</td>
            <td style={{ ...td, color: "var(--text-secondary)" }}>{winRate(r)}</td>
            <td style={{ ...td, color: tone(r.pnl), fontWeight: "var(--w-medium)" }}>{money(r.pnl)}</td>
          </tr>
        ))}
      </tbody>
    </table>
  );

  const CLS = { win: { label: "WIN", c: "var(--profit)" }, loss: { label: "LOSS", c: "var(--loss)" }, breakeven: { label: "BREAKEVEN", c: "var(--text-tertiary)" }, scratch: { label: "BREAKEVEN", c: "var(--text-tertiary)" } };

  const picker = reports && reports.length > 1 ? (
    <NT_Select value={sel || ""} onChange={setSel}
      options={reports.map((r) => ({ value: r.week_start, label: "week of " + r.week_start }))} />
  ) : null;

  if (reports == null) return (
    <div style={{ display: "flex", flexDirection: "column", gap: "var(--gap-grid)" }}>
      <PageHead title="Weekly Lab" subtitle="The standing examination of all trade data — recomputed after every trading week" />
      <NT.Card padding={20}><div style={{ padding: "30px 0", textAlign: "center", color: "var(--text-tertiary)", font: "var(--w-medium) var(--t-sm)/1 var(--font-sans)" }}>Loading…</div></NT.Card>
    </div>
  );
  if (!R) return (
    <div style={{ display: "flex", flexDirection: "column", gap: "var(--gap-grid)" }}>
      <PageHead title="Weekly Lab" subtitle="The standing examination of all trade data — recomputed after every trading week" />
      <NT.Card padding={20}>
        <div style={{ padding: "40px 20px", textAlign: "center", display: "flex", flexDirection: "column", gap: 8, alignItems: "center", color: "var(--text-tertiary)" }}>
          <Ico name="microscope" size={26} />
          <span style={{ font: "var(--w-medium) var(--t-sm)/1 var(--font-sans)", color: "var(--text-secondary)" }}>No lab reports yet</span>
          <span style={{ font: "var(--w-regular) var(--t-xs)/1.5 var(--font-sans)" }}>The first report is generated after Friday's close. {err ? "(" + err + ")" : ""}</span>
        </div>
      </NT.Card>
    </div>
  );

  const a = R.anatomy, base = (R.streaks || [])[0] || { n: 0, wins: 0 };
  const S = R.strategy || {};
  const rules = [
    S.stop_pct != null ? "stop −" + Math.round(S.stop_pct * 100) + "%" : null,
    S.be_pct != null ? "BE at +" + Math.round(S.be_pct * 100) + "%" : null,
    S.trail ? "trail from +" + Math.round((S.trail.at || 0) * 100) + "% give " + Math.round((S.trail.trail || 0) * 100) + "%" : null,
    S.hold_min ? S.hold_min + "m max hold" : null,
  ].filter(Boolean).join(" · ");
  const weeks = R.weeks || [];
  const wMax = Math.max(1, ...weeks.map((w) => Math.abs(w.pnl)));
  const fixedPnl = ((R.overlays || [])[0] || {}).pnl || a.fixed_pnl;

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: "var(--gap-grid)" }}>
      <PageHead title="Weekly Lab"
        subtitle={"All " + ((R.pool || {}).affordable || 0) + " taped trades " + ((R.pool || {}).first || "") + " → " + ((R.pool || {}).last || "") + ", replayed under the live rules (" + (S.name || "live strategy") + ": " + rules + ")"}
        right={<span style={{ display: "inline-flex", alignItems: "center", gap: 10 }}>{picker}<NT.Button variant="ghost" size="md" onClick={load}>Refresh</NT.Button></span>} />

      {/* headline anatomy — one card, 4 aligned columns */}
      <NT.Card title="Trade anatomy" padding={20}
        action={<span style={{ font: "var(--w-regular) var(--t-xs)/1 var(--font-sans)", color: "var(--text-tertiary)" }}>fixed ${Math.round(S.budget || 0)} per trade · report {cur.week_start}</span>}>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(5, 1fr)", gap: 18 }}>
          <Tile label="All-time p&l" value={money(a.fixed_pnl)} color={tone(a.fixed_pnl)} sub={"worst drawdown " + money(a.worst_dd)} />
          <Tile label="Wins" value={a.wins.n} color="var(--profit)" sub={"avg " + pct0(a.wins.avg_pct) + " (≥ +5%)"} />
          <Tile label="Losses" value={a.losses.n} color="var(--loss)" sub={"avg " + pct0(a.losses.avg_pct) + " (≤ −5%)"} />
          <Tile label="Breakevens" value={(a.breakeven || a.scratch || {}).n} sub="between −5% and +5%" />
          <Tile label="Green trades" value={base.n ? Math.round(100 * base.wins / base.n) + "%" : "—"} sub={base.wins + " of " + base.n + " ended positive"} />
        </div>
      </NT.Card>

      {/* data coverage — the visual database: every entry alert vs recorded tape, live */}
      {(() => {
        if (cov == null) return (
          <NT.Card title="Data coverage — every alerted entry vs recorded tape" padding={20}>
            <div style={{ padding: "24px 0", textAlign: "center", color: "var(--text-tertiary)", font: "var(--w-medium) var(--t-sm)/1 var(--font-sans)" }}>Loading coverage…</div>
          </NT.Card>
        );
        const channels = Array.from(new Set(cov.map((r) => r.source)));
        const shown = covSrc === "all" ? cov : cov.filter((r) => r.source === covSrc);
        const total = shown.length, taped = shown.filter((r) => r.taped).length;
        const CUT = "2026-08-24";
        const recent = shown.filter((r) => r.ts >= CUT);
        const recentTaped = recent.filter((r) => r.taped).length;
        const dOf = (iso) => { try { return new Intl.DateTimeFormat("en-GB", { timeZone: "Europe/Amsterdam", day: "2-digit", month: "short" }).format(new Date(iso)); } catch (e) { return "\u2014"; } };
        const tmOf = (iso) => { try { return new Intl.DateTimeFormat("nl-NL", { timeZone: "Europe/Amsterdam", hour: "2-digit", minute: "2-digit", hour12: false }).format(new Date(iso)); } catch (e) { return "\u2014"; } };
        return (
          <NT.Card title="Data coverage — every alerted entry vs recorded tape" padding={20}
            action={<span style={{ display: "inline-flex", alignItems: "center", gap: 12 }}>
              <span style={{ font: "var(--w-regular) var(--t-xs)/1 var(--font-sans)", color: "var(--text-tertiary)" }}>
                live from the database · {taped} of {total} alerts taped · since 24 Aug {recentTaped}/{recent.length}</span>
              {channels.length > 1 && <NT_Select value={covSrc} onChange={setCovSrc}
                options={[{ value: "all", label: "All channels" }].concat(channels.map((c2) => ({ value: c2, label: c2 })))} />}
            </span>}>
            <div style={{ overflowX: "auto", maxHeight: 430, overflowY: "auto" }}>
              <table style={{ width: "100%", borderCollapse: "collapse", tableLayout: "fixed", minWidth: 820 }}>
                <thead><tr><th style={thL}>date</th><th style={thL}>time</th><th style={thL}>source</th>
                  <th style={thL}>ticker</th><th style={thL}>contract</th><th style={th}>peak</th><th style={th}>drawdown</th>
                  <th style={th}>tape</th><th style={th}>ticks</th><th style={{ ...th, textAlign: "left", paddingLeft: 18 }}>data</th></tr></thead>
                <tbody>
                  {shown.map((r, i) => (
                    <tr key={i}>
                      <td style={{ ...tdL, color: "var(--text-secondary)" }}>{dOf(r.ts)}</td>
                      <td style={{ ...tdL, color: "var(--text-secondary)" }}>{tmOf(r.ts)}</td>
                      <td style={{ ...tdL, color: "var(--text-secondary)", overflow: "hidden", textOverflow: "ellipsis" }}>{r.source}</td>
                      <td style={{ ...tdL, fontWeight: "var(--w-medium)" }}>{r.ticker}</td>
                      <td style={{ ...tdL, color: "var(--text-secondary)" }}>{r.contract || "\u2014"}</td>
                      <td style={{ ...td, color: r.peak == null ? "var(--text-tertiary)" : "var(--profit)" }}>{r.peak == null ? "\u2014" : pct(r.peak)}</td>
                      <td style={{ ...td, color: r.dd == null ? "var(--text-tertiary)" : "var(--loss)" }}>{r.dd == null ? "\u2014" : pct(r.dd)}</td>
                      <td style={{ ...td, color: r.mins == null ? "var(--text-tertiary)" : (r.mins >= 28 ? "var(--text-secondary)" : "var(--dryrun)") }}>{r.mins == null ? "\u2014" : r.mins + "m"}</td>
                      <td style={{ ...td, color: r.taped ? "var(--text-secondary)" : "var(--text-tertiary)" }}>{r.taped ? r.ticks.toLocaleString("en-US") : "\u2014"}</td>
                      <td style={{ ...tdL, paddingLeft: 18 }}><span style={{ font: "var(--w-semibold) var(--t-2xs)/1 var(--font-sans)", letterSpacing: "var(--ls-wide)", color: r.taped ? "var(--profit)" : "var(--loss)" }}>{r.taped ? "TAPED" : "NO TAPE"}</span></td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </NT.Card>
        );
      })()}

      {/* what the data says */}
      <NT.Card title="What the data says" padding={20}
        action={<span style={{ font: "var(--w-regular) var(--t-xs)/1 var(--font-sans)", color: "var(--text-tertiary)" }}>rule-based conclusions, recomputed weekly</span>}>
        <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
          {(R.conclusions || []).map((c, i) => (
            <div key={i} style={{ display: "flex", gap: 10, alignItems: "flex-start" }}>
              <span style={{ marginTop: 5, width: 6, height: 6, borderRadius: 3, background: "var(--accent)", flex: "0 0 auto" }} />
              <span style={{ font: "var(--w-regular) var(--t-sm)/1.55 var(--font-sans)", color: "var(--text-primary)" }}>{c}</span>
            </div>
          ))}
        </div>
      </NT.Card>

      {/* week-by-week trend */}
      <NT.Card title="Week by week" padding={20}
        action={<span style={{ font: "var(--w-regular) var(--t-xs)/1 var(--font-sans)", color: "var(--text-tertiary)" }}>{weeks.length} trading weeks · fixed sizing</span>}>
        <div style={{ display: "flex", alignItems: "center", gap: 6, height: 130, padding: "6px 2px 0" }}>
          {weeks.map((w) => {
            const h = Math.max(3, Math.round(Math.abs(w.pnl) / wMax * 55));
            return (
              <div key={w.week} title={"week of " + w.week + " · " + w.n + " trades · " + money(w.pnl)}
                style={{ flex: 1, display: "flex", flexDirection: "column", alignItems: "center", gap: 4, minWidth: 0 }}>
                <div style={{ width: "100%", maxWidth: 34, height: 116, display: "flex", flexDirection: "column", justifyContent: "center" }}>
                  <div style={{ height: 55, display: "flex", alignItems: "flex-end" }}>{w.pnl > 0 ? <div style={{ width: "100%", height: h, background: "var(--profit)", borderRadius: "3px 3px 0 0", opacity: 0.85 }} /> : null}</div>
                  <div style={{ height: 1, background: "var(--row-line)" }} />
                  <div style={{ height: 55, display: "flex", alignItems: "flex-start" }}>{w.pnl < 0 ? <div style={{ width: "100%", height: h, background: "var(--loss)", borderRadius: "0 0 3px 3px", opacity: 0.85 }} /> : null}</div>
                </div>
                <span style={{ font: "var(--w-regular) var(--t-2xs)/1 var(--font-mono)", color: "var(--text-tertiary)", whiteSpace: "nowrap" }}>{w.week.slice(5)}</span>
              </div>
            );
          })}
        </div>
      </NT.Card>

      {/* seasonality — 2 + 2 columns, aligned to the grid above */}
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "var(--gap-grid)" }}>
        <NT.Card title="By weekday" padding={20}><MiniTable rows={R.weekday || []} keyLabel="weekday" /></NT.Card>
        <NT.Card title="By month" padding={20}
          action={<span style={{ font: "var(--w-regular) var(--t-xs)/1 var(--font-sans)", color: "var(--text-tertiary)" }}>seasonality builds over the years</span>}>
          <MiniTable rows={R.month || []} keyLabel="month" labelOf={MONTH_LABEL} /></NT.Card>
        <NT.Card title="By entry hour (ET)" padding={20}><MiniTable rows={R.hour || []} keyLabel="hour" /></NT.Card>
        <NT.Card title="By trade # of the day" padding={20}><MiniTable rows={R.nth || []} keyLabel="trade of day" /></NT.Card>
      </div>

      {/* streaks + day sequence */}
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "var(--gap-grid)" }}>
        <NT.Card title="Streaks — does the last result predict the next?" padding={20}>
          <table style={{ width: "100%", borderCollapse: "collapse" }}>
            <thead><tr><th style={thL}>situation</th><th style={th}>samples</th><th style={th}>next trade green</th></tr></thead>
            <tbody>
              {(R.streaks || []).map((s) => (
                <tr key={s.label}>
                  <td style={tdL}>{s.label}</td>
                  <td style={{ ...td, color: "var(--text-secondary)" }}>{s.n}</td>
                  <td style={{ ...td, fontWeight: s.label === "baseline" ? "var(--w-medium)" : "var(--w-regular)" }}>{winRate(s)}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </NT.Card>
        <NT.Card title="Days" padding={20}>
          {(() => { const d = R.days || {}; const ag = d.after_green || {}, ar = d.after_red || {}; return (
            <table style={{ width: "100%", borderCollapse: "collapse" }}>
              <thead><tr><th style={thL}>situation</th><th style={th}>samples</th><th style={th}>day ends green</th></tr></thead>
              <tbody>
                <tr><td style={tdL}>all trading days</td><td style={{ ...td, color: "var(--text-secondary)" }}>{d.n || 0}</td><td style={{ ...td, fontWeight: "var(--w-medium)" }}>{d.n ? Math.round(100 * d.green / d.n) + "%" : "—"}</td></tr>
                <tr><td style={tdL}>day after a green day</td><td style={{ ...td, color: "var(--text-secondary)" }}>{ag.n || 0}</td><td style={td}>{ag.n ? Math.round(100 * ag.green / ag.n) + "%" : "—"}</td></tr>
                <tr><td style={tdL}>day after a red day</td><td style={{ ...td, color: "var(--text-secondary)" }}>{ar.n || 0}</td><td style={td}>{ar.n ? Math.round(100 * ar.green / ar.n) + "%" : "—"}</td></tr>
              </tbody>
            </table>
          ); })()}
        </NT.Card>
      </div>

      {/* sizing simulations */}
      <NT.Card title="Sizing simulations — same trades, size adapted" padding={20}
        action={<span style={{ font: "var(--w-regular) var(--t-xs)/1 var(--font-sans)", color: "var(--text-tertiary)" }}>what adaptive sizing WOULD have done over the whole history</span>}>
        <div style={{ overflowX: "auto" }}>
          <table style={{ width: "100%", borderCollapse: "collapse", minWidth: 560 }}>
            <thead><tr><th style={thL}>sizing rule</th><th style={th}>total p&l</th><th style={th}>vs fixed</th><th style={th}>worst drawdown</th></tr></thead>
            <tbody>
              {(R.overlays || []).map((o, i) => (
                <tr key={o.name}>
                  <td style={{ ...tdL, fontWeight: i === 0 ? "var(--w-medium)" : "var(--w-regular)" }}>{o.name}</td>
                  <td style={{ ...td, color: tone(o.pnl), fontWeight: "var(--w-medium)" }}>{money(o.pnl)}</td>
                  <td style={{ ...td, color: i === 0 ? "var(--text-tertiary)" : tone(o.pnl - fixedPnl) }}>{i === 0 ? "—" : money(o.pnl - fixedPnl)}</td>
                  <td style={{ ...td, color: "var(--loss)" }}>{money(o.dd)}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </NT.Card>

      {/* every trade in the pool */}
      <NT.Card title="Every trade in the pool" padding={20}
        action={<span style={{ font: "var(--w-regular) var(--t-xs)/1 var(--font-sans)", color: "var(--text-tertiary)" }}>replayed under today's live rules — not the historic broker fills</span>}>
        <div style={{ overflowX: "auto", maxHeight: 430, overflowY: "auto" }}>
          <table style={{ width: "100%", borderCollapse: "collapse", minWidth: 620 }}>
            <thead><tr><th style={thL}>date</th><th style={thL}>ticker</th><th style={thL}>result</th><th style={th}>qty</th><th style={th}>return</th><th style={th}>peak</th><th style={th}>p&l</th></tr></thead>
            <tbody>
              {(R.trades || []).slice().reverse().map((t, i) => {
                const c = CLS[t.cls] || CLS.breakeven;
                return (
                  <tr key={i}>
                    <td style={{ ...tdL, color: "var(--text-secondary)" }}>{t.date}</td>
                    <td style={{ ...tdL, fontWeight: "var(--w-medium)" }}>{t.ticker}</td>
                    <td style={tdL}><span style={{ font: "var(--w-semibold) var(--t-2xs)/1 var(--font-sans)", letterSpacing: "var(--ls-wide)", color: c.c }}>{c.label}</span></td>
                    <td style={{ ...td, color: "var(--text-secondary)" }}>×{t.qty}</td>
                    <td style={{ ...td, color: tone(t.ret_pct) }}>{pct(t.ret_pct)}</td>
                    <td style={{ ...td, color: "var(--text-secondary)" }}>{pct(t.peak_pct)}</td>
                    <td style={{ ...td, color: tone(t.pnl), fontWeight: "var(--w-medium)" }}>{money(t.pnl)}</td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </NT.Card>

    </div>
  );
}
