const { useState, useEffect, useRef, useMemo, useCallback } = React;
/* Snipe.Run — views part 4: Market Detail (Polymarket-style + comments), Activity */

/* ============ MARKET DETAIL ============ */
function MarketDetail({ ctx }) {
  const { marketId, onBackMarket, authed, onRequireConnect, onOpenTrader } = ctx;
  const real = sniIsReal();
  const [tf, setTf] = useState('1W');

  // Real: marketId is the market slug (the markets list sets id===slug). Hook
  // no-ops to null/loading=false when not on the platform so the demo branch runs.
  const { data: rm, loading: rmLoading } = useMarket(real ? marketId : null);

  // Demo market — also the fallback while a real market is still loading.
  const demoM = MARKETS.find((x) => x.id === marketId) || MARKETS[0];

  // Map the real market detail into the shape the view renders. YES price comes
  // from the live book of the first clob token (Polymarket: tokens[0] = YES).
  const m = useMemo(() => {
    if (!real || !rm) return demoM;
    const yesTok = (rm.tokens && rm.tokens[0]) || null;
    const px = (rm.prices && yesTok && rm.prices[yesTok]) || null;
    // mid of bid/ask, fall back to bid, then 50%.
    let yes = 50;
    if (px) {
      const bid = +px.bid || 0, ask = +px.ask || 0;
      const mid = (bid && ask) ? (bid + ask) / 2 : (bid || ask);
      if (mid) yes = Math.round(mid * 100);
    }
    yes = Math.max(1, Math.min(99, yes));
    return {
      id: rm.slug || marketId,
      slug: rm.slug || marketId,
      q: rm.q || 'Polymarket market',
      cat: rm.cat || 'Markets',
      desc: rm.desc || null,
      ico: '◈',
      yes,
      chg: 0,
      vol: +rm.vol || 0,
      liq: +rm.liq || 0,
      close: rm.end ? new Date(rm.end).toLocaleDateString('en-US', { month: 'short', day: '2-digit' }) : '—',
      end: rm.end || null,
      tokens: rm.tokens || [],
      prices: rm.prices || {},
      condition_id: rm.condition_id || null,
    };
  }, [real, rm, demoM, marketId]);

  const series = useMemo(() => {
    const r = seedRand('mk' + (m.id || marketId) + tf); let v = m.yes; const out = [];
    for (let i = 0; i < 60; i++) { v += (r() - 0.5) * 6; v = Math.max(8, Math.min(92, v)); out.push(v); }
    out[out.length - 1] = m.yes; return out;
  }, [m.id, m.yes, tf, marketId]);

  // Top holders / "copy traders here" have no real source yet — demo only.
  const holders = useMemo(() => {
    if (real) return [];
    const r = seedRand('hold' + m.id);
    return TRADERS.slice().sort(() => r() - 0.5).slice(0, 6).map((t, i) => ({ name: t.name, id: t.id, side: r() > 0.3 ? 'YES' : 'NO', shares: Math.floor(r() * 80000 + 8000), avg: Math.floor(r() * 30 + 40) }));
  }, [m.id, real]);
  const inMarketTraders = holders.filter((h) => h.side === 'YES').slice(0, 3);

  // Loading shell for the first real fetch (keeps hook order stable above).
  if (real && rmLoading && !rm) {
    return (
      <div className="content-inner" style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
        <button className="b b-ghost b-sm" style={{ alignSelf: 'flex-start' }} onClick={onBackMarket}><Icon name="chevron" size={14} style={{ transform: 'rotate(180deg)' }} /> Back to markets</button>
        <div className="card card-pad"><div className="empty" style={{ padding: '48px 20px' }}>Loading market…</div></div>
      </div>
    );
  }
  if (real && !rm) {
    return (
      <div className="content-inner" style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
        <button className="b b-ghost b-sm" style={{ alignSelf: 'flex-start' }} onClick={onBackMarket}><Icon name="chevron" size={14} style={{ transform: 'rotate(180deg)' }} /> Back to markets</button>
        <div className="card card-pad"><div className="empty" style={{ padding: '48px 20px' }}>Market unavailable. <button className="b b-ghost b-sm" onClick={onBackMarket}>Back to markets</button></div></div>
      </div>
    );
  }

  return (
    <div className="content-inner" style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      <button className="b b-ghost b-sm" style={{ alignSelf: 'flex-start' }} onClick={onBackMarket}><Icon name="chevron" size={14} style={{ transform: 'rotate(180deg)' }} /> Back to markets</button>

      {/* header */}
      <div className="card card-pad">
        <div style={{ display: 'flex', gap: 16, alignItems: 'flex-start', flexWrap: 'wrap' }}>
          <div style={{ width: 54, height: 54, borderRadius: 13, background: 'var(--bg-2)', border: '1px solid var(--line)', display: 'grid', placeItems: 'center', fontSize: 27, flexShrink: 0 }}>{m.ico}</div>
          <div style={{ flex: 1, minWidth: 240 }}>
            <div style={{ display: 'flex', gap: 8, marginBottom: 8 }}>
              <span className="chip" style={{ background: 'var(--bg-2)', color: 'var(--tx-2)' }}>{m.cat}</span>
              <span className="chip chip-up" style={{ display: 'inline-flex', alignItems: 'center', gap: 5 }}><span className="live-dot" /> Live</span>
            </div>
            <h2 style={{ fontFamily: 'var(--display)', fontSize: 25, margin: 0, lineHeight: 1.2 }}>{m.q}</h2>
            <div className="mono tiny" style={{ marginTop: 8, display: 'flex', gap: 16, flexWrap: 'wrap' }}>
              <span>{moneyShort(m.vol)} Vol</span><span>{moneyShort(real ? (m.liq || 0) : m.vol * 0.4)} Liquidity</span><span>Closes {m.close}{real ? '' : ', 2026'}</span>{!real && <span>{(holders.length * 318).toLocaleString()} holders</span>}
            </div>
          </div>
          <div style={{ textAlign: 'right' }}>
            <div className="tiny mono" style={{ textTransform: 'uppercase' }}>Chance (YES)</div>
            <div className="up" style={{ fontFamily: 'var(--display)', fontWeight: 700, fontSize: 45, lineHeight: 1 }}>{m.yes}%</div>
            {real
              ? <span className="chip chip-up" style={{ display: 'inline-flex', alignItems: 'center', gap: 5 }}><span className="live-dot" /> Live price</span>
              : <Chip kind={m.chg >= 0 ? 'up' : 'down'}>{m.chg >= 0 ? '▲' : '▼'} {Math.abs(m.chg)}¢ 24h</Chip>}
          </div>
        </div>
      </div>

      <div className="grid g-split">
        {/* LEFT */}
        <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
          <div className="card card-pad">
            <div className="between" style={{ marginBottom: 12 }}>
              <div className="sec-title">Probability history</div>
              <div className="seg">{['1H', '1D', '1W', '1M', 'ALL'].map((t) => <button key={t} className={tf === t ? 'on' : ''} onClick={() => setTf(t)}>{t}</button>)}</div>
            </div>
            <Sparkline data={series} h={220} />
            {real && <div className="tiny" style={{ marginTop: 10, color: 'var(--tx-3)' }}>Live YES probability {m.yes}% · price history chart coming soon.</div>}
          </div>

          {/* top holders — demo only; no real holder source yet */}
          {real ? (
            <div className="card">
              <div className="card-pad" style={{ paddingBottom: 8 }}><div className="sec-title">Top holders</div></div>
              <div className="empty" style={{ padding: '28px 20px' }}>On-chain holder breakdown coming soon.</div>
            </div>
          ) : (
            <div className="card">
              <div className="card-pad" style={{ paddingBottom: 8 }} ><div className="sec-title">Top holders</div></div>
              <table className="tbl">
                <thead><tr><th>Trader</th><th>Position</th><th className="th-num">Shares</th><th className="th-num">Avg</th><th style={{ width: 80 }}></th></tr></thead>
                <tbody>
                  {holders.map((h, i) => (
                    <tr key={i} style={{ cursor: 'pointer' }} onClick={() => onOpenTrader(h.id)}>
                      <td><div style={{ display: 'flex', alignItems: 'center', gap: 10 }}><Avatar name={h.name} size={30} /><span style={{ fontWeight: 600 }}>{h.name}</span></div></td>
                      <td><span className={`chip ${h.side === 'YES' ? 'chip-up' : 'chip-down'}`}>{h.side}</span></td>
                      <td className="td-num">{h.shares.toLocaleString()}</td>
                      <td className="td-num muted">{h.avg}¢</td>
                      <td onClick={(e) => e.stopPropagation()}><button className="b b-ghost b-sm" onClick={() => authed ? onOpenTrader(h.id) : onRequireConnect()}>Copy</button></td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}

          {/* comments — demo only; real comment feed not available yet */}
          {real ? (
            <div className="card">
              <div className="between card-pad" style={{ paddingBottom: 12 }}>
                <div className="sec-title" style={{ display: 'flex', alignItems: 'center', gap: 8 }}><Icon name="message" size={17} /> Comments</div>
              </div>
              <div className="empty" style={{ padding: '28px 20px' }}>Market comments are coming soon.</div>
            </div>
          ) : (
            <CommentsSection market={m} authed={authed} onRequireConnect={onRequireConnect} />
          )}
        </div>

        {/* RIGHT */}
        <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
          <OrderPanel market={m} real={real} authed={authed} onRequireConnect={onRequireConnect} />
          {real ? (
            <div className="card card-pad">
              <div className="sec-title" style={{ marginBottom: 12 }}>Copy traders here</div>
              <div className="tiny" style={{ color: 'var(--tx-3)' }}>Per-market copyable traders coming soon. Browse the leaderboard to copy a trader across all their positions.</div>
            </div>
          ) : (
            <div className="card card-pad">
              <div className="between" style={{ marginBottom: 12 }}><div className="sec-title">Copy traders here</div><span className="chip chip-up">{inMarketTraders.length}</span></div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
                {inMarketTraders.map((h) => {
                  const t = TRADERS.find((x) => x.id === h.id);
                  return (
                    <div key={h.id} className="between" style={{ padding: '4px 0' }}>
                      <div style={{ display: 'flex', alignItems: 'center', gap: 10, cursor: 'pointer' }} onClick={() => onOpenTrader(h.id)}>
                        <Avatar name={h.name} size={34} />
                        <div><div style={{ fontWeight: 700, fontSize: 14.5 }}>{h.name}</div><div className="mono tiny up">{pct(t.roi)} · {t.win}% win</div></div>
                      </div>
                      <button className="b b-green b-sm" onClick={() => authed ? onOpenTrader(h.id) : onRequireConnect()}>Copy</button>
                    </div>
                  );
                })}
              </div>
            </div>
          )}
          <div className="card card-pad">
            <div className="sec-title" style={{ marginBottom: 12 }}>Resolution</div>
            <div className="tiny" style={{ lineHeight: 1.7, color: 'var(--tx-2)' }}>
              {real && m.desc
                ? m.desc
                : <>This market resolves <strong style={{ color: 'var(--tx)' }}>YES</strong> if the outcome is officially confirmed by the listed source on or before {m.close}{real ? '' : ', 2026'}. Resolves <strong style={{ color: 'var(--tx)' }}>NO</strong> otherwise.</>}
            </div>
            <div className="between" style={{ marginTop: 14, paddingTop: 14, borderTop: '1px solid var(--line)' }}>
              <span className="tiny mono">Resolver</span><span className="mono tiny" style={{ color: 'var(--green)' }}>UMA Oracle ↗</span>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

function OrderPanel({ market, real, authed, onRequireConnect }) {
  const [side, setSide] = useState('YES');
  const [amt, setAmt] = useState(100);
  const [done, setDone] = useState(false);
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState(null);
  const price = side === 'YES' ? market.yes : 100 - market.yes;
  const shares = (amt / (price / 100)).toFixed(0);

  // Real token ids — Polymarket clobTokenIds: [0]=YES, [1]=NO.
  const tokens = (real && market.tokens) || [];
  const tokenId = side === 'YES' ? (tokens[0] || null) : (tokens[1] || null);

  const buy = () => {
    if (!authed) return onRequireConnect();
    setErr(null);
    if (real) {
      if (!tokenId) { setErr('Market not tradable right now.'); return; }
      if (!amt || amt <= 0) { setErr('Enter an amount.'); return; }
      setBusy(true);
      sniApi('market/order', { method: 'POST', body: JSON.stringify({ token_id: tokenId, side: 'BUY', usdc: amt }) })
        .then((r) => {
          setBusy(false);
          if (r && r.ok) { setDone(true); setTimeout(() => setDone(false), 2600); }
          else setErr((r && (r.message || r.code)) || 'Order failed.');
        })
        .catch(() => { setBusy(false); setErr('Order failed.'); });
      return;
    }
    // demo: instant optimistic fill
    setDone(true); setTimeout(() => setDone(false), 2200);
  };

  return (
    <div className="card card-pad" style={{ position: 'sticky', top: 0 }}>
      <div className="seg" style={{ display: 'flex', marginBottom: 16 }}>
        <button className={side === 'YES' ? 'on' : ''} style={{ flex: 1, color: side === 'YES' ? 'var(--green)' : undefined }} onClick={() => { setSide('YES'); setErr(null); }}>Buy Yes · {market.yes}¢</button>
        <button className={side === 'NO' ? 'on' : ''} style={{ flex: 1, color: side === 'NO' ? 'var(--red)' : undefined }} onClick={() => { setSide('NO'); setErr(null); }}>Buy No · {100 - market.yes}¢</button>
      </div>
      <div className="field"><label>Amount (USDC)</label>
        <input className="inp mono" type="number" value={amt} onChange={(e) => setAmt(+e.target.value || 0)} />
        <div style={{ display: 'flex', gap: 8, marginTop: 8 }}>{[50, 100, 500, 1000].map((a) => <button key={a} className="b b-ghost b-sm" onClick={() => setAmt(a)}>${a}</button>)}</div>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8, padding: '12px 0', borderTop: '1px solid var(--line)', margin: '4px 0 14px' }}>
        <Row k="Avg price" v={price + '¢'} />
        <Row k="Shares" v={shares} />
        <Row k="Potential payout" v={money(shares * 1)} accent />
        <Row k="Copy latency" v={real ? 'paper' : '9ms'} accent />
      </div>
      {err && <div className="tiny" style={{ color: 'var(--red)', marginBottom: 10 }}>{err}</div>}
      {done
        ? <button className="b b-block b-lg" style={{ background: 'rgba(22,255,122,0.15)', color: 'var(--green)', justifyContent: 'center' }}><Icon name="check" size={16} /> {real ? 'Paper order placed' : 'Filled in 7ms'}</button>
        : <button className={`b ${side === 'YES' ? 'b-green' : 'b-red'} b-block b-lg`} disabled={busy} onClick={buy}><Icon name="bolt" size={16} /> {busy ? 'Placing…' : (authed ? `Buy ${side} · ${money(amt, 0)}` : 'Connect to trade')}</button>}
      <div className="tiny" style={{ textAlign: 'center', marginTop: 10 }}>{real ? 'Paper order — simulated against the live book' : 'Or auto-mirror this via a copied trader'}</div>
    </div>
  );
}

function CommentsSection({ market, authed, onRequireConnect }) {
  const seeded = useMemo(() => {
    const r = seedRand('cm' + market.id);
    const base = COMMENTS.slice().sort(() => r() - 0.5).slice(0, 5);
    return base.map((c, i) => ({ ...c, id: 'c' + i }));
  }, [market.id]);
  const [list, setList] = useState(seeded);
  const [text, setText] = useState('');
  const [sort, setSort] = useState('top');
  useEffect(() => { setList(seeded); }, [seeded]);
  const post = () => {
    if (!authed) return onRequireConnect();
    if (!text.trim()) return;
    setList((l) => [{ id: 'me' + Date.now(), name: 'degen_whale', side: 'YES', text: text.trim(), likes: 0, time: 'now', badge: 'You', mine: true }, ...l]);
    setText('');
  };
  const shown = sort === 'top' ? [...list].sort((a, b) => b.likes - a.likes) : list;
  return (
    <div className="card">
      <div className="between card-pad" style={{ paddingBottom: 12 }}>
        <div className="sec-title" style={{ display: 'flex', alignItems: 'center', gap: 8 }}><Icon name="message" size={17} /> Comments <span className="tiny" style={{ color: 'var(--tx-3)' }}>{list.length}</span></div>
        <div className="seg"><button className={sort === 'top' ? 'on' : ''} onClick={() => setSort('top')}>Top</button><button className={sort === 'new' ? 'on' : ''} onClick={() => setSort('new')}>Newest</button></div>
      </div>
      <div style={{ padding: '0 20px 16px' }}>
        <div style={{ display: 'flex', gap: 10 }}>
          <Avatar name={authed ? 'degen_whale' : 'guest'} size={36} />
          <div style={{ flex: 1, display: 'flex', gap: 8 }}>
            <input className="inp" placeholder={authed ? 'Add a comment…' : 'Connect your wallet to comment'} value={text} onChange={(e) => setText(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && post()} onFocus={() => !authed && onRequireConnect()} />
            <button className="b b-green" onClick={post}><Icon name="send" size={15} /></button>
          </div>
        </div>
      </div>
      <div style={{ borderTop: '1px solid var(--line)' }}>
        {shown.map((c) => <Comment key={c.id} c={c} />)}
      </div>
    </div>
  );
}
function Comment({ c }) {
  const [likes, setLikes] = useState(c.likes);
  const [liked, setLiked] = useState(false);
  return (
    <div style={{ display: 'flex', gap: 12, padding: '16px 20px', borderBottom: '1px solid var(--line)' }}>
      <Avatar name={c.name} size={38} />
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
          <span style={{ fontWeight: 700, fontSize: 15 }}>{c.name}</span>
          <span className={`chip ${c.side === 'YES' ? 'chip-up' : 'chip-down'}`} style={{ fontSize: 11 }}>{c.side} holder</span>
          {c.badge && <span className="chip" style={{ background: 'var(--bg-2)', color: 'var(--tx-3)', fontSize: 11 }}>{c.badge}</span>}
          <span className="tiny" style={{ marginLeft: 'auto' }}>{c.time}</span>
        </div>
        <p style={{ margin: '7px 0 9px', fontSize: 15, color: 'var(--tx-2)', lineHeight: 1.55 }}>{c.text}</p>
        <div style={{ display: 'flex', gap: 18 }}>
          <button onClick={() => { setLiked(!liked); setLikes((n) => n + (liked ? -1 : 1)); }} style={{ background: 'none', border: 'none', cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 6, color: liked ? 'var(--green)' : 'var(--tx-3)', fontFamily: 'var(--ui)', fontWeight: 600, fontSize: 13.5 }}>
            <Icon name="heart" size={15} fill={liked ? 'currentColor' : 'none'} /> {likes}
          </button>
          <button style={{ background: 'none', border: 'none', cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 6, color: 'var(--tx-3)', fontFamily: 'var(--ui)', fontWeight: 600, fontSize: 13.5 }}><Icon name="message" size={15} /> Reply</button>
        </div>
      </div>
    </div>
  );
}

/* ============ ACTIVITY ============ */
function Activity({ ctx }) {
  const live = useLiveData();
  const real = sniIsReal();
  const [filter, setFilter] = useState('all');
  const [rows, setRows] = useState(() => ACTIVITY.map((a, i) => ({ ...a, id: i })));
  const filters = [['all', 'All'], ['fill', 'Copies'], ['tp', 'Profits'], ['deposit', 'Wallet'], ['rank', 'System']];
  useInterval(() => {
    if (real) return;
    const tr = TRADERS[Math.floor(Math.random() * TRADERS.length)];
    const mk = MARKETS[Math.floor(Math.random() * MARKETS.length)];
    setRows((r) => [{ id: Date.now(), type: 'fill', side: Math.random() > 0.4 ? 'BUY' : 'SELL', trader: tr.name, market: mk.q, amt: Math.floor(Math.random() * 12000 + 500), price: mk.yes, ms: Math.floor(Math.random() * 14 + 7), t: 'just now', fresh: true }, ...r].slice(0, 40));
  }, 2600);
  // Real: live fills + closes from the worker (no demo fallback). Demo otherwise.
  const baseRows = real ? sniMapActivity(live) : rows;
  const stats = sniStats(live);
  const realizedReal = +stats.realized_pnl || 0;
  const tradesReal = +stats.trades || 0;
  const shown = filter === 'all' ? baseRows : baseRows.filter((r) => filter === 'tp' ? (r.type === 'tp' || r.type === 'sl') : filter === 'rank' ? (r.type === 'rank' || r.type === 'resolve') : r.type === filter);
  return (
    <div className="content-inner" style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
      <div className="grid g-4">
        <StatMini k="Events (24h)" v={real ? baseRows.length : '8,412'} icon="pulse" />
        <StatMini k="Copies filled today" v={real ? tradesReal : '319'} icon="check" accent />
        <StatMini k="Realized today" v={real ? ((realizedReal >= 0 ? '+' : '') + moneyShort(realizedReal)) : '+$18.4k'} icon="award" accent={realizedReal >= 0} />
        <StatMini k="Avg fill latency" v={<LiveMs />} icon="gauge" accent />
      </div>
      <div className="card">
        <div className="between card-pad" style={{ paddingBottom: 12, flexWrap: 'wrap', gap: 10 }}>
          <div>
            <div className="sec-title" style={{ display: 'flex', alignItems: 'center', gap: 8 }}><span className="live-dot" /> Activity</div>
            <div className="tiny" style={{ marginTop: 2 }}>Every copy, fill and payout across your wallets · for raw engine telemetry see <strong style={{ color: 'var(--tx-2)' }}>Bot Logs</strong></div>
          </div>
          <div className="seg">{filters.map(([id, l]) => <button key={id} className={filter === id ? 'on' : ''} onClick={() => setFilter(id)}>{l}</button>)}</div>
        </div>
        <div>
          {shown.map((a) => <ActivityRow key={a.id} a={a} onOpenTrader={ctx.onOpenTrader} />)}
          {!shown.length && <div className="empty">{real ? 'No activity yet — start the bot to copy live fills.' : 'No activity in this category yet.'}</div>}
        </div>
      </div>
    </div>
  );
}
function ActivityRow({ a, onOpenTrader }) {
  const cfg = {
    fill: { ico: a.side === 'BUY' ? 'arrowUp' : 'arrowDown', col: a.side === 'BUY' ? 'var(--green)' : 'var(--red)', bg: a.side === 'BUY' ? 'rgba(22,255,122,0.1)' : 'rgba(255,77,94,0.1)' },
    tp: { ico: 'award', col: 'var(--green)', bg: 'rgba(22,255,122,0.1)' },
    sl: { ico: 'arrowDown', col: 'var(--red)', bg: 'rgba(255,77,94,0.1)' },
    rank: { ico: 'trophy', col: 'var(--amber)', bg: 'rgba(255,194,75,0.1)' },
    deposit: { ico: 'arrowDownC', col: 'var(--cyan)', bg: 'rgba(63,224,255,0.1)' },
    resolve: { ico: 'flag', col: 'var(--violet)', bg: 'rgba(154,140,255,0.1)' },
  }[a.type] || { ico: 'pulse', col: 'var(--tx-2)', bg: 'var(--bg-2)' };
  return (
    <div style={{ display: 'flex', gap: 14, padding: '14px 20px', borderBottom: '1px solid var(--line)', alignItems: 'center', animation: a.fresh ? 'slideIn .3s ease' : 'none' }}>
      <span style={{ width: 38, height: 38, borderRadius: 10, flexShrink: 0, display: 'grid', placeItems: 'center', background: cfg.bg, color: cfg.col }}><Icon name={cfg.ico} size={18} /></span>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 15, fontWeight: 600 }}>
          {a.type === 'fill' && <>Copied <b style={{ cursor: 'pointer' }} onClick={() => onOpenTrader && onOpenTrader()}>{a.trader}</b> · {a.side} <span className="muted">{a.market}</span></>}
          {a.type === 'tp' && <>Take-profit hit on <b>{a.trader}</b>'s <span className="muted">{a.market}</span></>}
          {a.type === 'sl' && <>Stop-loss triggered on <b>{a.trader}</b>'s <span className="muted">{a.market}</span></>}
          {a.type === 'rank' && <><b>{a.trader}</b> {a.detail}</>}
          {a.type === 'deposit' && <>{a.detail}</>}
          {a.type === 'resolve' && <>Market <span className="muted">{a.market}</span> {a.detail}</>}
        </div>
        <div className="mono tiny" style={{ marginTop: 3 }}>
          {a.type === 'fill' && <>{moneyShort(a.amt)} @ {a.price}¢{a.ms ? <> · filled in <span className="up">{a.ms}ms</span></> : null}</>}
          {(a.type === 'tp' || a.type === 'sl') && <span style={{ color: a.pnl >= 0 ? 'var(--green)' : 'var(--red)' }}>{a.pnl >= 0 ? '+' : ''}{money(a.pnl)} realized</span>}
        </div>
      </div>
      <span className="tiny" style={{ flexShrink: 0 }}>{a.t}</span>
    </div>
  );
}

Object.assign(window, { MarketDetail, Activity });
