/* ============================================================
   WalletTracker — components (React, via Babel)
   exports to window: WT.{ Icon, StatusBar, AddRow, WalletCard, Leaderboard }
   ============================================================ */
const { useState, useRef, useEffect } = React;
const D = window.WT_DATA;

/* ---------- inline icon set ---------- */
function Icon({ name, ...p }) {
  const paths = {
    logo: <path d="M3 12c3-5 6-5 9 0s6 5 9 0" />,
    users: <><circle cx="9" cy="8" r="3" /><path d="M3 20c0-3 3-5 6-5s6 2 6 5" /><path d="M16 6a3 3 0 0 1 0 6" /><path d="M21 20c0-2.5-1.6-4.2-4-4.8" /></>,
    chevron: <path d="M6 9l6 6 6-6" />,
    x: <path d="M6 6l12 12M18 6 6 18" />,
    edit: <><path d="M4 20h4L19 9l-4-4L4 16z" /><path d="M14 6l4 4" /></>,
    copy: <><rect x="9" y="9" width="11" height="11" rx="2" /><path d="M5 15V5a2 2 0 0 1 2-2h10" /></>,
    check: <path d="M5 12l5 5L20 6" />,
    refresh: <><path d="M20 11a8.1 8.1 0 0 0-15.5-2M4 4v5h5" /><path d="M4 13a8.1 8.1 0 0 0 15.5 2M20 20v-5h-5" /></>,
    trophy: <><path d="M8 4h8v4a4 4 0 0 1-8 0z" /><path d="M8 6H5v1a3 3 0 0 0 3 3M16 6h3v1a3 3 0 0 1-3 3" /><path d="M12 12v4M9 20h6M10 20v-2h4v2" /></>,
    pulse: <path d="M3 12h4l2-6 4 12 2-6h6" />,
    wallet: <><rect x="3" y="6" width="18" height="13" rx="2.5" /><path d="M3 10h18" /><circle cx="16.5" cy="13.5" r="1.2" /></>,
  };
  return (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7"
      strokeLinecap="round" strokeLinejoin="round" {...p}>
      {paths[name]}
    </svg>
  );
}

/* ---------- sparkline svg ---------- */
function Spark({ data, positive }) {
  const w = 280, h = 46;
  if (!data || !data.length) return null;
  const step = w / (data.length - 1);
  const pts = data.map((v, i) => [i * step, h - v * h]);
  const line = pts.map(p => `${p[0].toFixed(1)},${p[1].toFixed(1)}`).join(' ');
  const area = `0,${h} ` + line + ` ${w},${h}`;
  const col = positive ? 'var(--pos)' : 'var(--neg)';
  const id = 'g' + (positive ? 'p' : 'n');
  return (
    <svg className="spark" viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none">
      <defs>
        <linearGradient id={id} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor={col} stopOpacity="0.22" />
          <stop offset="100%" stopColor={col} stopOpacity="0" />
        </linearGradient>
      </defs>
      <polygon points={area} fill={`url(#${id})`} />
      <polyline points={line} fill="none" stroke={col} strokeWidth="1.6"
        vectorEffect="non-scaling-stroke" strokeLinejoin="round" strokeLinecap="round" />
    </svg>
  );
}

function formatPercent(value) {
  return value === null || value === undefined || Number.isNaN(Number(value)) ? '—' : Number(value).toFixed(0) + '%';
}

function pctWidth(value) {
  if (value === null || value === undefined || Number.isNaN(Number(value))) return 0;
  return Math.max(0, Math.min(100, Number(value)));
}

function moneyClass(value) {
  return D.numeric(value) >= 0 ? 'pos' : 'neg';
}

function AvatarBadge({ avatar, emoji, color, className, style }) {
  return (
    <div className={className || 'avatar'} style={Object.assign({ background: color }, style || {})}>
      {avatar ? <img src={avatar} alt="" loading="lazy" /> : emoji}
    </div>
  );
}

/* ---------- status bar ---------- */
function StatusBar({ secondsAgo, walletCount, totalEquity, refreshing, lastUpdated, onRefresh }) {
  const refreshSeconds = Math.round(D.REFRESH_MS / 1000);
  const nextText = walletCount ? Math.max(0, refreshSeconds - (secondsAgo % refreshSeconds)) + 's' : '—';
  const updatedText = refreshing ? 'refreshing' : lastUpdated ? secondsAgo + 's ago' : 'not fetched';
  return (
    <div className="statusbar">
      <div className="sb-item"><span className="lbl">Tracked Equity</span><b>{D.fmtUSD(totalEquity, { compact: true })}</b></div>
      <div className="sb-sep" />
      <div className="sb-item"><span className="lbl">Wallets</span><b>{walletCount}</b></div>
      <div className="sb-sep" />
      <div className="sb-item">
        <span className="sb-pulse" />
        <span className="lbl">Updated</span><b>{updatedText}</b>
      </div>
      <div className="sb-sep" />
      <div className="sb-item"><span className="lbl">Source</span><b>Hyperliquid</b></div>
      <div className="sb-sep" />
      <div className="sb-item"><span className="lbl">Next</span><b>{nextText}</b></div>
      <div className="sb-spacer" />
      <button className={'sb-refresh' + (refreshing ? ' spinning' : '')} onClick={onRefresh} disabled={!walletCount || refreshing} title="Refresh live wallet data">
        <Icon name="refresh" /> Refresh
      </button>
    </div>
  );
}

/* ---------- Hypurr avatar + color picker popover ---------- */
function Picker({ avatar, color, onPick, onClose }) {
  const ref = useRef(null);
  useEffect(() => {
    function h(e) { if (ref.current && !ref.current.contains(e.target)) onClose(); }
    document.addEventListener('mousedown', h);
    return () => document.removeEventListener('mousedown', h);
  }, [onClose]);
  return (
    <div className="picker" ref={ref}>
      <div className="ttl">Hypurr NFT</div>
      <div className="hypurr-grid">
        {D.HYPURR_AVATARS.map(a => (
          <button key={a.id} className={a.src === avatar ? 'sel' : ''} onClick={() => onPick({ avatar: a.src })} title={a.label}>
            <img src={a.src} alt="" loading="lazy" />
          </button>
        ))}
      </div>
      <div className="ttl">Color</div>
      <div className="color-grid">
        {D.COLORS.map(c => (
          <button key={c} className={c === color ? 'sel' : ''} style={{ background: c }} onClick={() => onPick({ color: c })} />
        ))}
      </div>
    </div>
  );
}

/* ---------- inline add-wallet row ---------- */
function AddRow({ onAdd }) {
  const [name, setName] = useState('');
  const [addr, setAddr] = useState('');
  const [emoji, setEmoji] = useState(D.EMOJIS[Math.floor(Math.random() * 8)]);
  const [color, setColor] = useState(D.pick(D.COLORS));
  const [avatar, setAvatar] = useState(D.pick(D.HYPURR_AVATARS).src);
  const [open, setOpen] = useState(false);
  const [busy, setBusy] = useState(false);

  const valid = D.isAddress(addr.trim());

  async function submit() {
    if (!valid || busy) return;
    setBusy(true);
    try {
      const added = await onAdd({ name: name.trim(), address: addr.trim(), emoji, color, avatar });
      if (added !== false) {
        setName(''); setAddr('');
        setEmoji(D.EMOJIS[Math.floor(Math.random() * 8)]);
        setColor(D.pick(D.COLORS));
        setAvatar(D.pick(D.HYPURR_AVATARS).src);
      }
    } finally {
      setBusy(false);
    }
  }

  return (
    <div className="addrow" style={{ position: 'relative' }}>
      <div style={{ position: 'relative' }}>
        <button className="swatch-btn" style={{ background: color }} onClick={() => setOpen(o => !o)} title="Choose Hypurr NFT">
          {avatar ? <img src={avatar} alt="" loading="lazy" /> : emoji}
        </button>
        {open && <Picker avatar={avatar} color={color} onClose={() => setOpen(false)}
          onPick={(p) => { if (p.avatar) setAvatar(p.avatar); if (p.color) setColor(p.color); }} />}
      </div>
      <input className="name-in" placeholder="Name this trader…" value={name}
        onChange={e => setName(e.target.value)} onKeyDown={e => e.key === 'Enter' && submit()} />
      <div className="divider" />
      <span className="ic"><Icon name="wallet" /></span>
      <input className="addr-in" placeholder="Paste 0x… wallet address, hit Enter" value={addr}
        onChange={e => setAddr(e.target.value)} onKeyDown={e => e.key === 'Enter' && submit()} spellCheck="false" />
      <button className="add-btn" onClick={submit} disabled={!valid || busy}>
        {busy ? 'Fetching…' : '+ Track'}
      </button>
    </div>
  );
}

/* ---------- positions table ---------- */
function PositionsTable({ positions }) {
  if (!positions || !positions.length) {
    return <div className="table-empty">No open perp positions for this wallet.</div>;
  }

  return (
    <div className="table-wrap">
      <table className="ptable">
        <thead>
          <tr>
            <th>Token</th><th>Amount</th><th>Value</th><th>Avg Entry</th>
            <th>Mark</th><th>PNL / ROE</th><th>Funding</th><th>Dist. to Liq</th>
          </tr>
        </thead>
        <tbody>
          {positions.map((p, i) => {
            const long = p.side === 'long';
            const sideCol = long ? 'var(--pos)' : 'var(--neg)';
            const tint = D.TOKEN_TINT[p.token] || '#2a313b';
            const logo = D.tokenLogo ? D.tokenLogo(p.token) : '';
            const symbol = p.token.replace(/^k/, '').slice(0, 4);
            const hasLiq = p.liqPct !== null && p.liqPct !== undefined && Number.isFinite(Number(p.liqPct));
            const liqPct = hasLiq ? Number(p.liqPct) : null;
            const liqWarn = hasLiq && liqPct <= 12;
            const funding = p.funding === null || p.funding === undefined ? null : D.numeric(p.funding);
            return (
              <tr key={i}>
                <td>
                  <div className="tok">
                    <span className="sidebar-l" style={{ background: sideCol }} />
                    <span className={'ico ' + (logo ? 'has-logo' : '')} style={{ background: tint }}>
                      {logo && <img src={logo} alt={p.token + ' logo'} loading="lazy" onError={(e) => e.currentTarget.parentElement.classList.add('logo-error')} />}
                      <span className="fallback-symbol">{symbol}</span>
                    </span>
                    <span className="meta">
                      <div className="sym">{p.token}</div>
                      <div className="lev"><span className="x">{D.numeric(p.lev).toFixed(1)}x</span> {p.margin}</div>
                    </span>
                  </div>
                </td>
                <td className="tnum" style={{ color: long ? 'var(--pos)' : 'var(--neg)' }}>{D.fmtAmount(p.amount)}</td>
                <td className="tnum">{D.fmtUSD(p.value, { compact: p.value >= 1e6, dp: 2 })}</td>
                <td className="tnum muted">{D.fmtPrice(p.entry)}</td>
                <td className="tnum">{D.fmtPrice(p.mark)}</td>
                <td>
                  <div className="pnlcell">
                    <div className={'p ' + (p.pnl >= 0 ? 'pos' : 'neg')}>{D.fmtSigned(p.pnl)}</div>
                    <div className={'roe ' + (p.pnl >= 0 ? 'pos' : 'neg')}>{formatPercent(Math.abs(D.numeric(p.roe)))}</div>
                  </div>
                </td>
                <td className={'tnum ' + moneyClass(funding)}>{D.fmtSigned(funding)}</td>
                <td>
                  <div className="liqcell">
                    <div className="top">
                      <span className="pct" style={liqWarn ? { color: 'var(--neg)' } : null}>{formatPercent(liqPct)}</span>
                      <span className="price">{D.fmtPrice(p.liqPrice)}</span>
                    </div>
                    <div className="track">
                      {hasLiq && <i style={{ width: Math.max(4, Math.min(100, liqPct)) + '%', background: liqWarn ? 'var(--neg)' : 'var(--amber)' }} />}
                    </div>
                  </div>
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

/* ---------- one stat tile ---------- */
function Tile({ k, children, sub, bar }) {
  return (
    <div className="tile">
      <div className="tk">{k}</div>
      <div className="tv">{children}</div>
      {sub && <div className="tsub">{sub}</div>}
      {bar && <div className="bar"><i style={{ width: bar.pct + '%', background: bar.color }} /></div>}
    </div>
  );
}

/* ---------- wallet card ---------- */
function WalletCard({ w, expanded, onToggle, onEdit, onRemove, onRefresh }) {
  const [copied, setCopied] = useState(false);
  const [editing, setEditing] = useState(false);

  function copy(e) {
    e.stopPropagation();
    navigator.clipboard && navigator.clipboard.writeText(w.address);
    setCopied(true); setTimeout(() => setCopied(false), 1200);
  }

  function refresh(e) {
    e.stopPropagation();
    if (onRefresh) Promise.resolve(onRefresh(w)).catch(() => {});
  }

  const positions = Array.isArray(w.positions) ? w.positions : [];
  const status = w.status || 'live';
  const pos = D.numeric(w.pnl24h) >= 0;
  const longVal = positions.filter(p => p.side === 'long').reduce((s, p) => s + D.numeric(p.value), 0);
  const shortVal = positions.filter(p => p.side === 'short').reduce((s, p) => s + D.numeric(p.value), 0);
  const sumFunding = positions.reduce((s, p) => s + D.numeric(p.funding), 0);
  const sumPnl = positions.reduce((s, p) => s + D.numeric(p.pnl), 0);
  const statusText = status === 'loading' ? 'Fetching live account state…' : status === 'error' ? (w.error || 'Unable to fetch live account state.') : '';

  return (
    <div className={'card ' + status + (expanded ? ' expanded' : '')} onClick={() => !expanded && onToggle(w.id)}>
      <div className="card-head">
        <AvatarBadge avatar={w.avatar} emoji={w.emoji} color={w.color} />
        <div className="who">
          <div className="nm">
            {w.name}
            {w.tag && <span className="tag">{w.tag}</span>}
          </div>
          <div className="addr">
            {D.shortAddr(w.address)}
            <button className={'copy-btn' + (copied ? ' copied' : '')} onClick={copy} title="Copy address">
              <Icon name={copied ? 'check' : 'copy'} />
            </button>
            {w.ageDays != null && <span className="age">· {w.ageDays}d</span>}
          </div>
        </div>
        <div className="card-actions" onClick={e => e.stopPropagation()}>
          <button onClick={refresh} title="Refresh live data"><Icon name="refresh" /></button>
          <button onClick={() => setEditing(true)} title="Rename / avatar"><Icon name="edit" /></button>
          <button className="rm" onClick={() => onRemove(w.id)} title="Remove"><Icon name="x" /></button>
        </div>
      </div>

      {statusText && <div className={'card-msg ' + status}>{statusText}</div>}

      <div className="card-nums">
        <div className="numblock">
          <div className="k">Account Value</div>
          <div className="v tnum">{D.fmtUSD(w.equity, { compact: true })}</div>
        </div>
        <div className="numblock">
          <div className="k">24h PnL</div>
          <div className={'v sm tnum ' + (pos ? 'pos' : 'neg')}>{D.fmtSigned(w.pnl24h)}</div>
          <div className={'sub tnum ' + (pos ? 'pos' : 'neg')}>{D.fmtPctSigned(w.pnl24hPct)}</div>
        </div>
      </div>

      <Spark data={w.spark} positive={pos} />

      <div className="card-foot">
        <div className="chip"><span className="ck">Leverage</span><span className="cv amber tnum">{D.numeric(w.leverage).toFixed(2)}x</span></div>
        <div className="chip"><span className="ck">Positions</span><span className="cv tnum">{positions.length}</span></div>
        <div className="chip"><span className="ck">Win Rate</span><span className="cv tnum">{formatPercent(w.winRate)}</span></div>
        <button className="expand" onClick={(e) => { e.stopPropagation(); onToggle(w.id); }}>
          {expanded ? 'Collapse' : 'Positions'} <Icon name="chevron" />
        </button>
      </div>

      {expanded && (
        <div className="detail" onClick={e => e.stopPropagation()}>
          <div className="stat-tiles">
            <Tile k="Account Value">{D.fmtUSD(w.equity, { compact: true })}</Tile>
            <Tile k="24h PnL"><span className={pos ? 'pos' : 'neg'}>{D.fmtSigned(w.pnl24h)}</span></Tile>
            <Tile k="All-Time PnL"><span className={w.allTimePnl >= 0 ? 'pos' : 'neg'}>{D.fmtSigned(w.allTimePnl)}</span></Tile>
            <Tile k="Win Rate" bar={w.winRate == null ? null : { pct: pctWidth(w.winRate), color: 'var(--pos)' }}>{formatPercent(w.winRate)}</Tile>
            <Tile k="Leverage" sub={w.bias}><span className="amber">{D.numeric(w.leverage).toFixed(2)}x</span></Tile>
            <Tile k="Net Funding"><span className={moneyClass(w.netFunding)}>{D.fmtSigned(w.netFunding)}</span></Tile>
            <Tile k="Volume 30d">{D.fmtUSD(w.volume30d, { compact: true })}</Tile>
          </div>

          <div className="pos-head">
            <div className="lhs">
              <span>Long <b className="pos">{D.fmtUSD(longVal, { compact: true })}</b></span>
              <span>Short <b className="neg">{D.fmtUSD(shortVal, { compact: true })}</b></span>
              <span>Total <b>{D.fmtUSD(longVal + shortVal, { compact: true })}</b></span>
            </div>
            <div className="rhs">
              <span>Sum Funding <b className={sumFunding >= 0 ? 'pos' : 'neg'}>{D.fmtSigned(sumFunding)}</b></span>
              <span>Sum PnL <b className={sumPnl >= 0 ? 'pos' : 'neg'}>{D.fmtSigned(sumPnl)}</b></span>
            </div>
          </div>

          <PositionsTable positions={positions} />
        </div>
      )}

      {editing && <EditModal w={w} onClose={() => setEditing(false)} onSave={(patch) => { onEdit(w.id, patch); setEditing(false); }} />}
    </div>
  );
}

/* ---------- edit modal ---------- */
function EditModal({ w, onClose, onSave }) {
  const [name, setName] = useState(w.name);
  const [emoji, setEmoji] = useState(w.emoji);
  const [color, setColor] = useState(w.color);
  const [avatar, setAvatar] = useState(w.avatar);
  const [tag, setTag] = useState(w.tag || '');
  const ref = useRef(null);
  useEffect(() => {
    function h(e) { if (e.key === 'Escape') onClose(); }
    document.addEventListener('keydown', h);
    return () => document.removeEventListener('keydown', h);
  }, [onClose]);
  return (
    <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.6)', zIndex: 80, display: 'grid', placeItems: 'center' }}
      onClick={onClose}>
      <div ref={ref} onClick={e => e.stopPropagation()} style={{
        background: '#20302b', border: '1px solid var(--line-2)', borderRadius: 16, padding: 22, width: 360, boxShadow: '0 24px 60px rgba(0,0,0,.6)'
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 18 }}>
          <AvatarBadge avatar={avatar} emoji={emoji} color={color} style={{ width: 46, height: 46, fontSize: 23 }} />
          <div style={{ fontSize: 15, fontWeight: 600 }}>Edit Wallet</div>
          <button onClick={onClose} style={{ marginLeft: 'auto', color: 'var(--t3)' }}><Icon name="x" style={{ width: 18, height: 18 }} /></button>
        </div>
        <label style={{ fontSize: 10.5, color: 'var(--t3)', textTransform: 'uppercase', letterSpacing: '.06em' }}>Name</label>
        <input value={name} onChange={e => setName(e.target.value)} autoFocus style={inStyle} />
        <label style={{ fontSize: 10.5, color: 'var(--t3)', textTransform: 'uppercase', letterSpacing: '.06em', display: 'block', marginTop: 14 }}>Tag (optional)</label>
        <input value={tag} onChange={e => setTag(e.target.value)} placeholder="e.g. whale, scalper" style={inStyle} />
        <div style={{ fontSize: 10.5, color: 'var(--t3)', textTransform: 'uppercase', letterSpacing: '.06em', margin: '16px 0 8px' }}>Hypurr NFT</div>
        <div className="hypurr-grid modal-grid">
          {D.HYPURR_AVATARS.map(a => <button key={a.id} className={a.src === avatar ? 'sel' : ''} onClick={() => setAvatar(a.src)} title={a.label}>
            <img src={a.src} alt="" loading="lazy" />
          </button>)}
        </div>
        <div className="color-grid" style={{ display: 'flex', gap: 7, flexWrap: 'wrap' }}>
          {D.COLORS.map(c => <button key={c} onClick={() => setColor(c)} style={{ width: 26, height: 26, borderRadius: 7, background: c, border: c === color ? '2px solid #fff' : '2px solid transparent' }} />)}
        </div>
        <div style={{ display: 'flex', gap: 10, marginTop: 22 }}>
          <button onClick={onClose} style={{ flex: 1, padding: '10px', borderRadius: 9, border: '1px solid var(--line-2)', color: 'var(--t2)', fontSize: 13 }}>Cancel</button>
          <button onClick={() => onSave({ name: name.trim() || w.name, emoji, color, avatar, tag: tag.trim() })}
            style={{ flex: 1, padding: '10px', borderRadius: 9, background: 'var(--accent)', color: '#06241e', fontWeight: 600, fontSize: 13 }}>Save</button>
        </div>
      </div>
    </div>
  );
}
const inStyle = { width: '100%', marginTop: 6, background: 'var(--card-2)', border: '1px solid var(--line)', borderRadius: 9, padding: '10px 12px', color: 'var(--t1)', fontSize: 13.5, outline: 'none', fontFamily: 'var(--mono)' };

/* ---------- leaderboard ---------- */
function Leaderboard({ wallets, range, onRange, onJump }) {
  const key = range === '24h' ? 'pnl24h' : range === '7d' ? 'pnl7d' : 'pnl30d';
  const pctKey = range === '24h' ? 'pnl24hPct' : range === '7d' ? 'pnl7dPct' : 'pnl30dPct';
  const liveWallets = wallets.filter((wallet) => wallet.status === 'live');
  const sorted = [...liveWallets].sort((a, b) => D.numeric(b[key]) - D.numeric(a[key]));
  const max = Math.max(1, ...sorted.map(w => Math.abs(D.numeric(w[key]))));

  const totalPnl = liveWallets.reduce((s, w) => s + D.numeric(w[key]), 0);
  const totalEquity = liveWallets.reduce((s, w) => s + D.numeric(w.equity), 0);
  const winners = liveWallets.filter(w => D.numeric(w[key]) >= 0).length;

  return (
    <>
      <div className="panel">
        <div className="ph">
          <div className="t"><Icon name="trophy" /> Leaderboard</div>
          <div className="seg">
            {['24h', '7d', '30d'].map(r => (
              <button key={r} className={r === range ? 'on' : ''} onClick={() => onRange(r)}>{r}</button>
            ))}
          </div>
        </div>
        <div className="lb-list">
          {sorted.length === 0 && <div className="panel-empty">{wallets.length ? 'Waiting for live wallet data' : 'No wallets tracked yet'}</div>}
          {sorted.map((w, i) => {
            const pos = D.numeric(w[key]) >= 0;
            return (
              <div className="lb-row" key={w.id} onClick={() => onJump(w.id)}>
                <div className={'rank' + (i === 0 ? ' top1' : '')}>{i + 1}</div>
                <AvatarBadge className="lb-av" avatar={w.avatar} emoji={w.emoji} color={w.color} />
                <div className="lb-meta">
                  <div className="n">{w.name}</div>
                  <div className="bar"><i style={{ width: (Math.abs(D.numeric(w[key])) / max * 100) + '%', background: pos ? 'var(--pos)' : 'var(--neg)' }} /></div>
                </div>
                <div className="lb-val">
                  <div className={'v tnum ' + (pos ? 'pos' : 'neg')}>{D.fmtSigned(w[key])}</div>
                  <div className={'pc tnum ' + (pos ? 'pos' : 'neg')}>{D.fmtPctSigned(w[pctKey])}</div>
                </div>
              </div>
            );
          })}
        </div>
      </div>

      <div className="panel">
        <div className="ph"><div className="t"><Icon name="pulse" /> Aggregate</div></div>
        <div className="agg">
          <div className="row"><span className="k">Combined equity</span><span className="v tnum">{D.fmtUSD(totalEquity, { compact: true })}</span></div>
          <div className="row"><span className="k">Combined {range} PnL</span><span className={'v tnum ' + (totalPnl >= 0 ? 'pos' : 'neg')}>{D.fmtSigned(totalPnl)}</span></div>
          <div className="row"><span className="k">In profit ({range})</span><span className="v tnum">{winners}/{liveWallets.length}</span></div>
        </div>
      </div>
    </>
  );
}

window.WT = { Icon, StatusBar, AddRow, WalletCard, Leaderboard };
