// dashboard-pages.jsx — All dashboard pages (real API, no mock data)
const { useState, useEffect, useRef, useCallback, useMemo } = React;

// ─── API CLIENT ───────────────────────────────────────────────────────────────
const API_BASE = 'https://api.rostealth.site';

async function apiRequest(method, path, body) {
  const token = await window.clerk?.session?.getToken();
  const res = await fetch(`${API_BASE}${path}`, {
    method,
    headers: {
      'Content-Type': 'application/json',
      ...(token ? { Authorization: `Bearer ${token}` } : {}),
    },
    ...(body !== undefined ? { body: JSON.stringify(body) } : {}),
  });
  if (!res.ok) {
    const text = await res.text();
    throw new Error(text || `HTTP ${res.status}`);
  }
  return res.json();
}

// ─── HOOKS ───────────────────────────────────────────────────────────────────
function useStaggerIn(deps = []) {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const rows = Array.from(el.children);
    rows.forEach((r, i) => {
      r.style.opacity = '0';
      r.style.transform = 'translateY(8px)';
      r.style.transition = `opacity 0.4s var(--ease-out-expo) ${i * 40}ms, transform 0.4s var(--ease-out-expo) ${i * 40}ms`;
    });
    const raf = requestAnimationFrame(() => {
      rows.forEach(r => { r.style.opacity = '1'; r.style.transform = 'none'; });
    });
    return () => cancelAnimationFrame(raf);
  }, deps);
  return ref;
}

function useCountUp(target, duration = 800) {
  const [val, setVal] = useState(0);
  useEffect(() => {
    let start = null;
    const step = (ts) => {
      if (!start) start = ts;
      const prog = Math.min((ts - start) / duration, 1);
      const ease = 1 - Math.pow(1 - prog, 4);
      setVal(Math.round(ease * target));
      if (prog < 1) requestAnimationFrame(step);
    };
    requestAnimationFrame(step);
  }, [target]);
  return val;
}

// ─── CHARTS ──────────────────────────────────────────────────────────────────
const BarChart = ({ data, height = 130 }) => {
  const [ready, setReady] = useState(false);
  const [hov, setHov] = useState(null);
  useEffect(() => { const t = setTimeout(() => setReady(true), 60); return () => clearTimeout(t); }, []);
  if (!data || !data.length) return (
    <div style={{ height, display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--t4)', fontSize: 12 }}>No data yet</div>
  );
  const max = Math.max(...data.map(d => d.sessions || d.count || 0)) || 1;
  const barW = 22, gap = 12;
  const totalW = data.length * (barW + gap) - gap;

  return (
    <svg viewBox={`0 0 ${totalW} ${height + 28}`} style={{ width: '100%', height: height + 28, overflow: 'visible' }}>
      <defs>
        <linearGradient id="barGrad" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="#06B6D4" stopOpacity="0.95"/>
          <stop offset="100%" stopColor="#0E7490" stopOpacity="0.5"/>
        </linearGradient>
        <linearGradient id="barGradHov" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="#67E8F9" stopOpacity="1"/>
          <stop offset="100%" stopColor="#0891B2" stopOpacity="0.85"/>
        </linearGradient>
        <filter id="barGlow"><feGaussianBlur stdDeviation="3" result="blur"/><feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
      </defs>
      <line x1="0" y1={height} x2={totalW} y2={height} stroke="rgba(255,255,255,0.05)" strokeWidth="1"/>
      {data.map((d, i) => {
        const val = d.sessions || d.count || 0;
        const bh = (val / max) * height;
        const x = i * (barW + gap);
        const active = hov === i;
        const label = d.day || (d.hour ? new Date(d.hour).getHours() + 'h' : i);
        return (
          <g key={i} onMouseEnter={() => setHov(i)} onMouseLeave={() => setHov(null)} style={{ cursor: 'default' }}>
            <rect x={x} y={0} width={barW} height={height} rx="3" fill="rgba(255,255,255,0.02)"/>
            <rect x={x} y={ready ? height - bh : height} width={barW} height={ready ? bh : 0} rx="3"
              fill={active ? 'url(#barGradHov)' : 'url(#barGrad)'}
              filter={active ? 'url(#barGlow)' : 'none'}
              style={{ transition: `y 0.55s var(--ease-out-expo) ${i * 45}ms, height 0.55s var(--ease-out-expo) ${i * 45}ms` }}/>
            {active && (
              <g>
                <rect x={x - 6} y={height - bh - 30} width={barW + 12} height={22} rx="5" fill="var(--bg4)" stroke="var(--border-bright)" strokeWidth="1"/>
                <text x={x + barW / 2} y={height - bh - 14} textAnchor="middle" fontSize="11" fill="var(--t1)" fontFamily="JetBrains Mono,monospace" fontWeight="600">{val}</text>
              </g>
            )}
            <text x={x + barW / 2} y={height + 18} textAnchor="middle" fontSize="9" fill="var(--t4)" fontFamily="JetBrains Mono,monospace">{label}</text>
          </g>
        );
      })}
    </svg>
  );
};

const LineChart = ({ data, height = 120 }) => {
  const [progress, setProgress] = useState(0);
  const pathRef = useRef(null);
  const [len, setLen] = useState(999);
  const [hov, setHov] = useState(null);
  useEffect(() => { const t = setTimeout(() => setProgress(1), 100); return () => clearTimeout(t); }, []);
  useEffect(() => { if (pathRef.current) setLen(pathRef.current.getTotalLength() || 999); }, []);

  if (!data || data.length < 2) return (
    <div style={{ height, display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--t4)', fontSize: 12 }}>No data yet</div>
  );

  const max = Math.max(...data.map(d => d.sessions || d.count || 0)) * 1.1 || 1;
  const W = 320, padX = 10, padY = 10;
  const pts = data.map((d, i) => ({
    x: padX + (i / (data.length - 1)) * (W - padX * 2),
    y: height - padY - ((d.sessions || d.count || 0) / max) * (height - padY * 2),
    val: d.sessions || d.count || 0,
    label: d.day || d.hour,
  }));
  const smooth = (pts) => {
    let d = `M ${pts[0].x} ${pts[0].y}`;
    for (let i = 1; i < pts.length; i++) {
      const cp1x = pts[i-1].x + (pts[i].x - pts[i-1].x) * 0.42;
      const cp2x = pts[i].x - (pts[i].x - pts[i-1].x) * 0.42;
      d += ` C ${cp1x} ${pts[i-1].y} ${cp2x} ${pts[i].y} ${pts[i].x} ${pts[i].y}`;
    }
    return d;
  };
  const linePath = smooth(pts);
  const areaPath = `${linePath} L ${pts[pts.length-1].x} ${height} L ${pts[0].x} ${height} Z`;

  return (
    <svg viewBox={`0 0 ${W} ${height}`} style={{ width: '100%', height, overflow: 'visible' }}>
      <defs>
        <linearGradient id="lineAreaGrad" x1="0" y1="0" x2="0" y2="1"><stop offset="0%" stopColor="#06B6D4" stopOpacity="0.2"/><stop offset="100%" stopColor="#06B6D4" stopOpacity="0"/></linearGradient>
        <clipPath id="lineClip"><rect x="0" y="0" width={W * progress} height={height} style={{ transition: 'width 1s var(--ease-out-expo) 0.1s' }}/></clipPath>
        <filter id="lineGlow"><feGaussianBlur stdDeviation="2" result="blur"/><feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
      </defs>
      {[0.25, 0.5, 0.75].map(p => <line key={p} x1={padX} y1={padY + (1-p)*(height-padY*2)} x2={W-padX} y2={padY + (1-p)*(height-padY*2)} stroke="rgba(255,255,255,0.035)" strokeWidth="1" strokeDasharray="3 4"/>)}
      <path d={areaPath} fill="url(#lineAreaGrad)" clipPath="url(#lineClip)"/>
      <path ref={pathRef} d={linePath} fill="none" stroke="#06B6D4" strokeWidth="1.8" strokeLinejoin="round" strokeLinecap="round" filter="url(#lineGlow)"
        style={{ strokeDasharray: len, strokeDashoffset: len * (1 - progress), transition: 'stroke-dashoffset 1s var(--ease-out-expo) 0.1s' }}/>
      {pts.map((p, i) => (
        <g key={i} onMouseEnter={() => setHov(i)} onMouseLeave={() => setHov(null)} style={{ cursor: 'default' }}>
          <circle cx={p.x} cy={p.y} r={12} fill="transparent"/>
          <circle cx={p.x} cy={p.y} r={hov === i ? 5 : 3} fill={hov === i ? '#67E8F9' : '#22D3EE'} stroke="var(--bg2)" strokeWidth="1.5" style={{ transition: 'r 0.15s', clipPath: 'url(#lineClip)' }}/>
          {hov === i && (
            <g>
              <rect x={p.x - 18} y={p.y - 30} width={36} height={22} rx="5" fill="var(--bg4)" stroke="var(--border-bright)" strokeWidth="1"/>
              <text x={p.x} y={p.y - 14} textAnchor="middle" fontSize="11" fill="var(--t1)" fontFamily="JetBrains Mono,monospace" fontWeight="600">{p.val}</text>
            </g>
          )}
        </g>
      ))}
    </svg>
  );
};

// ─── USER DRAWER ─────────────────────────────────────────────────────────────
const UserDrawer = ({ user: u, open, onClose, onFlag, onRemove, addToast }) => {
  const [tab, setTab] = useState('overview');
  const [history, setHistory] = useState([]);
  const [loadingHistory, setLoadingHistory] = useState(false);

  useEffect(() => {
    if (!u || !open) return;
    setLoadingHistory(true);
    apiRequest('GET', `/api/users/${encodeURIComponent(u.roblox_username || u.username)}/history`)
      .then(rows => setHistory(rows || []))
      .catch(() => setHistory([]))
      .finally(() => setLoadingHistory(false));
  }, [u?.roblox_username || u?.username, open]);

  if (!u) return null;

  const username = u.roblox_username || u.username;
  const robloxId = u.roblox_user_id || u.robloxId;
  const status = u.status || 'offline';
  const game = u.game || null;
  const placeId = u.root_place_id || u.rootPlaceId || u.place_id || u.placeId || null;

  const handleFlag = () => {
    apiRequest('PATCH', `/api/users/${encodeURIComponent(username)}/flag`)
      .then(() => { onFlag(u.id); addToast({ type: 'info', msg: `${username} ${u.flagged ? 'unflagged' : 'flagged'}` }); })
      .catch(err => addToast({ type: 'error', msg: err.message }));
  };
  const handleRemove = () => {
    apiRequest('DELETE', `/api/users/${encodeURIComponent(username)}`)
      .then(() => { onRemove(u.id); addToast({ type: 'success', msg: `Removed ${username}` }); onClose(); })
      .catch(err => addToast({ type: 'error', msg: err.message }));
  };

  const handleJoinGame = () => {
    if (placeId) {
      window.open(`roblox://experiences/start?placeId=${placeId}`, '_self');
    } else {
      window.open(`https://www.roblox.com/users/${robloxId}/profile`, '_blank');
    }
    addToast({ type: 'info', msg: `Opening Roblox to join ${game || 'game'}...` });
  };

  // Derive game history from status snapshots
  const gameHistory = history.filter(h => h.status === 'in-game' && h.game).slice(0, 10);
  const sessionHistory = history.slice(0, 10);

  return (
    <Drawer open={open} onClose={onClose} width={420}>
      {/* header */}
      <div style={{ padding: '20px 22px', borderBottom: '1px solid var(--border)', flexShrink: 0 }}>
        <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', marginBottom: 16 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 13 }}>
            <Avatar name={username} size={44} status={status} robloxId={robloxId} />
            <div>
              <div style={{ fontSize: 16, fontWeight: 700, color: 'var(--t1)', letterSpacing: '-0.025em' }}>{username}</div>
              <div style={{ fontSize: 11, color: 'var(--t4)', fontFamily: 'var(--mono)', marginTop: 3 }}>ID: {robloxId || '—'}</div>
            </div>
          </div>
          <button onClick={onClose} style={{ background: 'none', border: 'none', color: 'var(--t3)', cursor: 'pointer', padding: 4 }}><Icon.Close /></button>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
          <StatusPill status={status} />
          {game && <span style={{ fontSize: 11.5, color: 'var(--t3)', display: 'flex', alignItems: 'center', gap: 5 }}><Icon.Game />{game}</span>}
          {u.flagged && <Badge color="amber">Flagged</Badge>}
          {/* JOIN GAME button */}
          {status === 'in-game' && (
            <button onClick={handleJoinGame} style={{ display: 'flex', alignItems: 'center', gap: 5, padding: '4px 11px', background: 'rgba(251,191,36,0.1)', border: '1px solid rgba(251,191,36,0.3)', borderRadius: 20, color: 'var(--amber)', fontSize: 11, fontWeight: 600, cursor: 'pointer', fontFamily: 'var(--font)', transition: 'all 0.15s' }}
              onMouseEnter={e => e.currentTarget.style.background='rgba(251,191,36,0.18)'}
              onMouseLeave={e => e.currentTarget.style.background='rgba(251,191,36,0.1)'}>
              <Icon.Game /> Join game
            </button>
          )}
        </div>
      </div>

      {/* tabs */}
      <div style={{ display: 'flex', gap: 2, padding: '10px 12px', borderBottom: '1px solid var(--border)', flexShrink: 0 }}>
        {['overview','sessions','games'].map(t => (
          <button key={t} onClick={() => setTab(t)} style={{ padding: '6px 13px', borderRadius: 6, border: 'none', cursor: 'pointer', background: tab === t ? 'var(--p-dim)' : 'transparent', color: tab === t ? 'var(--p3)' : 'var(--t3)', fontSize: 12, fontWeight: 600, fontFamily: 'var(--font)', transition: 'all 0.15s', borderBottom: tab === t ? '1px solid rgba(6,182,212,0.3)' : '1px solid transparent' }}>
            {t.charAt(0).toUpperCase() + t.slice(1)}
          </button>
        ))}
      </div>

      {/* content */}
      <div style={{ flex: 1, overflowY: 'auto', padding: 22 }}>
        {tab === 'overview' && (
          <div style={{ animation: 'fadein 0.3s var(--ease-out-expo) both' }}>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 1, background: 'var(--bg3)', border: '1px solid var(--border)', borderRadius: 10, overflow: 'hidden', marginBottom: 20 }}>
              {[
                { label: 'Status',    value: status },
                { label: 'Game',      value: game || (status === 'in-game' ? 'Private game' : '—') },
                { label: 'Roblox ID', value: robloxId || '—' },
                { label: 'Added',     value: u.added_at ? new Date(u.added_at).toLocaleDateString() : '—' },
              ].map((row, i) => (
                <div key={row.label} style={{ display: 'flex', justifyContent: 'space-between', padding: '11px 14px', borderBottom: i < 3 ? '1px solid rgba(255,255,255,0.04)' : 'none' }}>
                  <span style={{ fontSize: 12, color: 'var(--t3)' }}>{row.label}</span>
                  <span style={{ fontSize: 12, fontWeight: 600, color: 'var(--t1)', fontFamily: 'var(--mono)' }}>{row.value}</span>
                </div>
              ))}
            </div>
            {status === 'in-game' && (
              <button onClick={handleJoinGame} style={{ width: '100%', padding: '11px', background: 'rgba(251,191,36,0.08)', border: '1px solid rgba(251,191,36,0.25)', borderRadius: 10, color: 'var(--amber)', fontSize: 13, fontWeight: 600, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8, fontFamily: 'var(--font)', transition: 'all 0.15s', marginBottom: 16 }}
                onMouseEnter={e => e.currentTarget.style.background='rgba(251,191,36,0.15)'}
                onMouseLeave={e => e.currentTarget.style.background='rgba(251,191,36,0.08)'}>
                <Icon.Game /> Join {game || 'their game'} now
              </button>
            )}
            <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--t3)', marginBottom: 10, fontFamily: 'var(--mono)', textTransform: 'uppercase', letterSpacing: '0.08em' }}>Recent events ({history.length})</div>
            {loadingHistory ? (
              <div style={{ fontSize: 12, color: 'var(--t4)', textAlign: 'center', padding: 20 }}>Loading...</div>
            ) : history.length === 0 ? (
              <div style={{ fontSize: 12, color: 'var(--t4)', textAlign: 'center', padding: 20 }}>No history yet — check back after a poll cycle.</div>
            ) : history.slice(0, 6).map((h, i) => (
              <div key={h.id || i} style={{ display: 'flex', gap: 10, padding: '9px 0', borderBottom: i < 5 ? '1px solid rgba(255,255,255,0.04)' : 'none' }}>
                <div style={{ width: 7, height: 7, borderRadius: '50%', background: h.status === 'in-game' ? 'var(--amber)' : h.status === 'online' ? 'var(--green)' : 'var(--t4)', flexShrink: 0, marginTop: 4 }} />
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: 12.5, color: 'var(--t1)' }}>{h.status === 'in-game' ? `Joined ${h.game || 'a private game'}` : h.status === 'online' ? 'Came online' : 'Went offline'}</div>
                  <div style={{ fontSize: 10, color: 'var(--t4)', fontFamily: 'var(--mono)', marginTop: 2 }}>{new Date(h.recorded_at).toLocaleString()}</div>
                </div>
              </div>
            ))}
          </div>
        )}

        {tab === 'sessions' && (
          <div style={{ animation: 'fadein 0.3s var(--ease-out-expo) both' }}>
            <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--t3)', marginBottom: 14, fontFamily: 'var(--mono)', textTransform: 'uppercase', letterSpacing: '0.08em' }}>Session history</div>
            {loadingHistory ? <div style={{ fontSize: 12, color: 'var(--t4)', textAlign: 'center', padding: 20 }}>Loading...</div>
            : sessionHistory.length === 0 ? <div style={{ fontSize: 12, color: 'var(--t4)', textAlign: 'center', padding: 20 }}>No sessions yet.</div>
            : sessionHistory.map((h, i) => (
              <div key={h.id || i} style={{ display: 'flex', gap: 12, padding: '11px 0', borderBottom: i < sessionHistory.length - 1 ? '1px solid rgba(255,255,255,0.04)' : 'none', animation: `fadein 0.3s var(--ease-out-expo) ${i * 35}ms both` }}>
                <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 0, flexShrink: 0 }}>
                  <div style={{ width: 8, height: 8, borderRadius: '50%', background: h.status === 'in-game' ? 'var(--amber)' : h.status === 'online' ? 'var(--green)' : 'var(--t4)', flexShrink: 0, marginTop: 3 }} />
                  {i < sessionHistory.length - 1 && <div style={{ width: 1, flex: 1, background: 'rgba(255,255,255,0.06)', minHeight: 18 }} />}
                </div>
                <div style={{ flex: 1, paddingBottom: 4 }}>
                  <div style={{ fontSize: 12.5, color: 'var(--t1)', fontWeight: 500 }}>{h.status === 'in-game' ? `In ${h.game || 'a private game'}` : h.status}</div>
                  <div style={{ fontSize: 10.5, color: 'var(--t4)', fontFamily: 'var(--mono)', marginTop: 2 }}>{new Date(h.recorded_at).toLocaleString()}</div>
                </div>
              </div>
            ))}
          </div>
        )}

        {tab === 'games' && (
          <div style={{ animation: 'fadein 0.3s var(--ease-out-expo) both' }}>
            <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--t3)', marginBottom: 14, fontFamily: 'var(--mono)', textTransform: 'uppercase', letterSpacing: '0.08em' }}>Game history</div>
            {loadingHistory ? <div style={{ fontSize: 12, color: 'var(--t4)', textAlign: 'center', padding: 20 }}>Loading...</div>
            : gameHistory.length === 0 ? <div style={{ fontSize: 12, color: 'var(--t4)', textAlign: 'center', padding: 20 }}>No game sessions recorded yet.</div>
            : gameHistory.map((g, i) => (
              <div key={g.id || i} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '12px 14px', background: 'var(--bg3)', border: '1px solid var(--border)', borderRadius: 10, marginBottom: 8, animation: `fadein 0.3s var(--ease-out-expo) ${i * 45}ms both` }}>
                <div style={{ width: 34, height: 34, borderRadius: 8, background: 'var(--bg4)', border: '1px solid var(--border)', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--amber)', flexShrink: 0 }}><Icon.Game /></div>
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--t1)' }}>{g.game}</div>
                  <div style={{ fontSize: 10.5, color: 'var(--t3)', fontFamily: 'var(--mono)', marginTop: 2 }}>{new Date(g.recorded_at).toLocaleString()}</div>
                </div>
                {g.place_id && (
                  <button onClick={() => { window.open(`roblox://experiences/start?placeId=${g.place_id}`, '_self'); }} style={{ padding: '5px 10px', background: 'rgba(251,191,36,0.08)', border: '1px solid rgba(251,191,36,0.2)', borderRadius: 6, color: 'var(--amber)', fontSize: 11, cursor: 'pointer', fontFamily: 'var(--font)' }}>Join</button>
                )}
              </div>
            ))}
          </div>
        )}
      </div>

      {/* actions */}
      <div style={{ padding: '14px 22px', borderTop: '1px solid var(--border)', display: 'flex', gap: 8, flexShrink: 0 }}>
        <Btn size="sm" variant="ghost" onClick={handleFlag} icon={<Icon.Flag />} style={{ flex: 1, justifyContent: 'center', color: u.flagged ? 'var(--amber)' : 'var(--t2)', borderColor: u.flagged ? 'rgba(251,191,36,0.3)' : 'var(--border)', background: u.flagged ? 'var(--amber-dim)' : 'transparent' }}>
          {u.flagged ? 'Unflag' : 'Flag'}
        </Btn>
        <Btn size="sm" variant="danger" onClick={handleRemove} icon={<Icon.Trash />} style={{ flex: 1, justifyContent: 'center' }}>Remove</Btn>
      </div>
    </Drawer>
  );
};

// ─── STATUS PILL ─────────────────────────────────────────────────────────────
const StatusPill = ({ status }) => {
  const map = {
    online:    { color: 'var(--green)',  bg: 'rgba(52,211,153,0.08)',   border: 'rgba(52,211,153,0.18)',  label: 'Online',    anim: 'pulse-dot 2.2s ease-in-out infinite' },
    'in-game': { color: 'var(--amber)',  bg: 'rgba(251,191,36,0.08)',   border: 'rgba(251,191,36,0.18)',  label: 'In-game',   anim: 'pulse-amber 2.2s ease-in-out infinite' },
    invisible: { color: 'var(--blue)',   bg: 'rgba(96,165,250,0.08)',   border: 'rgba(96,165,250,0.18)',  label: 'Invisible', anim: 'none' },
    offline:   { color: 'var(--t4)',     bg: 'rgba(255,255,255,0.035)', border: 'rgba(255,255,255,0.07)', label: 'Offline',   anim: 'none' },
  };
  const s = map[status] || map.offline;
  return (
    <div style={{ display: 'inline-flex', alignItems: 'center', gap: 6, padding: '3px 9px', background: s.bg, border: `1px solid ${s.border}`, borderRadius: 20, boxShadow: status !== 'offline' ? `0 0 12px ${s.bg}` : 'none' }}>
      <span style={{ width: 5, height: 5, borderRadius: '50%', background: s.color, flexShrink: 0, animation: s.anim }}/>
      <span style={{ fontSize: 11, fontWeight: 500, color: s.color, fontFamily: 'var(--mono)', letterSpacing: '0.04em' }}>{s.label}</span>
    </div>
  );
};

// ─── SHARED LAYOUT ATOMS ─────────────────────────────────────────────────────
const Panel = ({ children, style = {}, noPad, glow }) => (
  <div className={`panel-base${glow ? ' panel-live' : ''}`} style={{ ...(noPad ? {} : { padding: 22 }), ...style }}>
    {children}
  </div>
);

const PanelHeader = ({ title, sub, right }) => (
  <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', marginBottom: 18 }}>
    <div>
      <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--t1)' }}>{title}</div>
      {sub && <div style={{ fontSize: 11, color: 'var(--t3)', marginTop: 3 }}>{sub}</div>}
    </div>
    {right && <div style={{ flexShrink: 0 }}>{right}</div>}
  </div>
);

const SectionLabel = ({ children, style = {} }) => (
  <div style={{ fontSize: 9.5, fontWeight: 600, color: 'var(--t4)', textTransform: 'uppercase', letterSpacing: '0.12em', fontFamily: 'var(--mono)', marginBottom: 14, ...style }}>{children}</div>
);

const Toggle = ({ on, setOn }) => (
  <button onClick={() => setOn(!on)} style={{ width: 40, height: 22, borderRadius: 11, border: 'none', cursor: 'pointer', background: on ? 'var(--p6)' : 'var(--bg4)', position: 'relative', transition: 'background 0.25s var(--ease-out-expo)', flexShrink: 0, boxShadow: on ? '0 0 12px rgba(6,182,212,0.45)' : 'none' }}>
    <span style={{ position: 'absolute', top: 3, left: on ? 21 : 3, width: 16, height: 16, borderRadius: '50%', background: '#fff', transition: 'left 0.25s var(--ease-out-expo)', display: 'block', boxShadow: '0 1px 4px rgba(0,0,0,0.3)' }}/>
  </button>
);

const PageHeader = ({ title, sub, right, badge }) => (
  <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', marginBottom: 28, gap: 16 }}>
    <div style={{ animation: 'fadein 0.4s var(--ease-out-expo) both' }}>
      <h1 style={{ fontSize: 21, fontWeight: 700, letterSpacing: '-0.04em', color: 'var(--t1)', lineHeight: 1 }}>{title}</h1>
      {sub && <p style={{ fontSize: 13, color: 'var(--t3)', marginTop: 6 }}>{sub}</p>}
    </div>
    <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexShrink: 0, animation: 'fadein 0.4s var(--ease-out-expo) 0.08s both' }}>
      {badge}{right}
    </div>
  </div>
);

const LiveBadge = () => (
  <div style={{ display: 'inline-flex', alignItems: 'center', gap: 6, padding: '4px 11px 4px 8px', background: 'rgba(52,211,153,0.07)', border: '1px solid rgba(52,211,153,0.14)', borderRadius: 40, boxShadow: '0 0 12px rgba(52,211,153,0.08)' }}>
    <span style={{ width: 6, height: 6, borderRadius: '50%', background: 'var(--green)', animation: 'pulse-dot 2.2s ease-in-out infinite' }}/>
    <span style={{ fontSize: 10, color: 'var(--green)', fontFamily: 'var(--mono)', letterSpacing: '0.08em' }}>LIVE</span>
  </div>
);

// ─── DASHBOARD PAGE ───────────────────────────────────────────────────────────
const DashboardPage = ({ user, setPage, trackedUsers, firedAlerts, onOpenUser, addToast, onRefresh, refreshing, syncAge }) => {
  const rowsRef = useStaggerIn([trackedUsers.length]);

  const onlineCount  = trackedUsers.filter(u => u.status === 'online' || u.status === 'in-game').length;
  const flaggedCount = trackedUsers.filter(u => u.flagged).length;
  const countOnline  = useCountUp(onlineCount);
  const countTracked = useCountUp(trackedUsers.length);

  // Live feed from real fired alerts
  const liveEvents = firedAlerts.slice(0, 5).map((a, i) => ({
    id: a.id,
    user: a.roblox_username,
    event: a.event,
    type: a.type,
    age: a.fired_at ? new Date(a.fired_at).toLocaleTimeString() : 'recent',
    fresh: i === 0,
  }));

  const typeColor = (t) => t === 'online' ? 'var(--green)' : t === 'game' ? 'var(--amber)' : 'var(--t4)';

  return (
    <div className="page-enter" style={{ padding: '26px 28px', maxWidth: 1200, margin: '0 auto' }}>
      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', marginBottom: 20, gap: 16, animation: 'fadein 0.4s var(--ease-out-expo) both' }}>
        <div>
          <h1 style={{ fontSize: 21, fontWeight: 700, letterSpacing: '-0.04em', color: 'var(--t1)', lineHeight: 1 }}>{user.username}</h1>
          <p style={{ fontSize: 13, color: 'var(--t3)', marginTop: 5 }}>
            {onlineCount > 0
              ? <><span style={{ color: 'var(--green)', fontWeight: 600 }}>{onlineCount} member{onlineCount !== 1 ? 's' : ''}</span> online right now</>
              : trackedUsers.length === 0 ? 'No members tracked yet' : 'All members offline'}
          </p>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, animation: 'fadein 0.4s var(--ease-out-expo) 0.08s both' }}>
          <LiveBadge />
          <button onClick={onRefresh} style={{ display: 'flex', alignItems: 'center', gap: 5, padding: '5px 11px', background: 'var(--bg3)', border: '1px solid var(--border)', borderRadius: 7, cursor: 'pointer', color: 'var(--t3)', fontSize: 11, fontFamily: 'var(--mono)', transition: 'all 0.15s' }}
            onMouseEnter={e => { e.currentTarget.style.borderColor='var(--border-bright)'; e.currentTarget.style.color='var(--t1)'; }}
            onMouseLeave={e => { e.currentTarget.style.borderColor='var(--border)'; e.currentTarget.style.color='var(--t3)'; }}>
            <span style={{ animation: refreshing ? 'spin 0.8s linear infinite' : 'none', display: 'flex' }}><Icon.Refresh /></span>
            {syncAge}s ago
          </button>
        </div>
      </div>

      {/* quick actions */}
      <div style={{ display: 'flex', gap: 8, marginBottom: 18, animation: 'fadein 0.4s var(--ease-out-expo) 0.05s both' }}>
        {[
          { label: '+ Track user', icon: <Icon.User />,     action: () => setPage('tracking'),  color: 'var(--p4)',   bg: 'var(--p-dim)',          border: 'rgba(6,182,212,0.22)' },
          { label: '+ Alert rule', icon: <Icon.Bolt />,     action: () => setPage('alerts'),    color: 'var(--amber)',bg: 'rgba(251,191,36,0.08)', border: 'rgba(251,191,36,0.2)'  },
          { label: 'Analytics',    icon: <Icon.Analytics />,action: () => setPage('analytics'), color: 'var(--t2)',   bg: 'var(--bg3)',             border: 'var(--border)'         },
        ].map(a => (
          <button key={a.label} onClick={a.action} style={{ display: 'flex', alignItems: 'center', gap: 7, padding: '7px 14px', background: a.bg, border: `1px solid ${a.border}`, borderRadius: 8, cursor: 'pointer', color: a.color, fontSize: 12.5, fontWeight: 600, fontFamily: 'var(--font)', transition: 'all 0.18s var(--ease-out-expo)', whiteSpace: 'nowrap' }}
            onMouseEnter={e => e.currentTarget.style.filter='brightness(1.15)'}
            onMouseLeave={e => e.currentTarget.style.filter='none'}>
            <span style={{ opacity: 0.8 }}>{a.icon}</span>{a.label}
          </button>
        ))}
      </div>

      {/* live pulse strip */}
      {liveEvents.length > 0 && (
        <div style={{ display: 'flex', gap: 6, marginBottom: 18, overflow: 'hidden', animation: 'fadein 0.4s var(--ease-out-expo) 0.1s both' }}>
          {liveEvents.map((ev, i) => {
            const col = typeColor(ev.type);
            const bg  = ev.type === 'online' ? 'rgba(52,211,153,0.09)' : ev.type === 'game' ? 'rgba(251,191,36,0.09)' : 'rgba(255,255,255,0.04)';
            const bdr = ev.type === 'online' ? 'rgba(52,211,153,0.2)' : ev.type === 'game' ? 'rgba(251,191,36,0.2)' : 'var(--border)';
            return (
              <div key={ev.id} style={{ display: 'flex', alignItems: 'center', gap: 6, padding: '5px 11px', background: bg, border: `1px solid ${bdr}`, borderRadius: 20, fontSize: 11.5, color: col, whiteSpace: 'nowrap', animation: ev.fresh ? 'feed-enter 0.3s var(--ease-out-expo) both' : 'none', opacity: Math.max(0.3, 1 - i * 0.14) }}>
                <GlowDot status={ev.type === 'online' ? 'online' : ev.type === 'game' ? 'in-game' : 'offline'} size={5} />
                <span style={{ fontWeight: 600 }}>{ev.user}</span>
                <span style={{ opacity: 0.7, color: 'var(--t3)' }}>{ev.event}</span>
                <span style={{ fontSize: 9.5, color: 'var(--t4)', fontFamily: 'var(--mono)' }}>{ev.age}</span>
              </div>
            );
          })}
        </div>
      )}

      {/* main grid */}
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 280px', gap: 14, marginBottom: 14 }}>
        {/* member grid */}
        <Panel style={{ animation: 'fadein 0.45s var(--ease-out-expo) 0.12s both' }} glow>
          <PanelHeader
            title="Members"
            sub={`${onlineCount} of ${trackedUsers.length} active`}
            right={<Btn size="sm" variant="ghost" onClick={() => setPage('tracking')}>Manage →</Btn>}
          />
          {trackedUsers.length === 0 ? (
            <div style={{ padding: '32px 0', textAlign: 'center' }}>
              <div style={{ fontSize: 13, color: 'var(--t3)', marginBottom: 12 }}>No members tracked yet</div>
              <Btn size="sm" icon={<Icon.Plus />} onClick={() => setPage('tracking')}>Add your first user</Btn>
            </div>
          ) : (
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(76px, 1fr))', gap: 10 }}>
              {trackedUsers.map(u => (
                <button key={u.id} onClick={() => onOpenUser(u)} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6, padding: '12px 8px', borderRadius: 10, border: `1px solid ${u.status !== 'offline' ? (u.status === 'online' ? 'rgba(52,211,153,0.18)' : 'rgba(251,191,36,0.18)') : 'var(--border)'}`, background: u.status === 'online' ? 'rgba(52,211,153,0.04)' : u.status === 'in-game' ? 'rgba(251,191,36,0.04)' : 'var(--bg3)', cursor: 'pointer', transition: 'all 0.18s var(--ease-out-expo)', position: 'relative' }}
                  onMouseEnter={e => { e.currentTarget.style.transform='translateY(-2px)'; e.currentTarget.style.boxShadow='0 4px 16px rgba(6,182,212,0.15)'; }}
                  onMouseLeave={e => { e.currentTarget.style.transform='none'; e.currentTarget.style.boxShadow='none'; }}>
                  {u.flagged && <span style={{ position: 'absolute', top: 6, right: 6, width: 6, height: 6, borderRadius: '50%', background: 'var(--amber)', boxShadow: '0 0 6px rgba(251,191,36,0.6)' }}/>}
                  <Avatar name={u.roblox_username || u.username} size={36} status={u.status} robloxId={u.roblox_user_id} />
                  <div style={{ textAlign: 'center' }}>
                    <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--t1)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: 64 }}>{(u.roblox_username || u.username || '').split('_')[0]}</div>
                    <div style={{ fontSize: 9.5, color: u.status === 'online' ? 'var(--green)' : u.status === 'in-game' ? 'var(--amber)' : 'var(--t4)', fontFamily: 'var(--mono)', marginTop: 2 }}>{u.status === 'in-game' ? (u.game?.split(' ')[0] || 'private') : u.status}</div>
                  </div>
                </button>
              ))}
              <button onClick={() => setPage('tracking')} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 6, padding: '12px 8px', borderRadius: 10, border: '1.5px dashed var(--border)', background: 'transparent', cursor: 'pointer', transition: 'all 0.18s', color: 'var(--t4)', minHeight: 80 }}
                onMouseEnter={e => { e.currentTarget.style.borderColor='var(--border-bright)'; e.currentTarget.style.color='var(--p4)'; }}
                onMouseLeave={e => { e.currentTarget.style.borderColor='var(--border)'; e.currentTarget.style.color='var(--t4)'; }}>
                <Icon.Plus /><span style={{ fontSize: 10, fontFamily: 'var(--mono)' }}>ADD</span>
              </button>
            </div>
          )}
        </Panel>

        {/* right sidebar */}
        <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8, animation: 'fadein 0.45s var(--ease-out-expo) 0.14s both' }}>
            {[
              { label: 'Online now',    value: countOnline,  max: trackedUsers.length || 1, color: 'var(--green)',  glow: 'rgba(52,211,153,0.3)',  bg: 'rgba(52,211,153,0.06)',  border: 'rgba(52,211,153,0.15)'  },
              { label: 'Tracked total', value: countTracked, max: 50,                        color: 'var(--p4)',    glow: 'rgba(6,182,212,0.3)',   bg: 'var(--p-dim)',            border: 'rgba(6,182,212,0.18)'  },
              { label: 'Flagged',       value: flaggedCount, max: Math.max(trackedUsers.length,1), color: flaggedCount ? 'var(--amber)' : 'var(--t4)', glow: flaggedCount?'rgba(251,191,36,0.3)':null, bg: flaggedCount?'rgba(251,191,36,0.06)':'var(--bg3)', border: flaggedCount?'rgba(251,191,36,0.18)':'var(--border)' },
            ].map(s => {
              const pct = Math.min(1, s.value / s.max);
              const r = 16, circ = 2 * Math.PI * r;
              return (
                <div key={s.label} style={{ display:'flex', alignItems:'center', gap:12, padding:'11px 13px', background:s.bg, border:`1px solid ${s.border}`, borderRadius:10, boxShadow: s.glow ? `0 0 18px ${s.glow}` : 'none', transition:'all 0.3s' }}>
                  <svg width="38" height="38" viewBox="0 0 38 38" style={{ flexShrink:0 }}>
                    <circle cx="19" cy="19" r={r} fill="none" stroke="rgba(255,255,255,0.06)" strokeWidth="3"/>
                    <circle cx="19" cy="19" r={r} fill="none" stroke={s.color} strokeWidth="3"
                      strokeDasharray={`${pct * circ} ${circ}`} strokeDashoffset={circ * 0.25} strokeLinecap="round"
                      style={{ transition:'stroke-dasharray 0.9s var(--ease-out-expo)', filter: s.glow ? `drop-shadow(0 0 3px ${s.color})` : 'none' }}/>
                    <text x="19" y="23" textAnchor="middle" fontSize="11" fontWeight="700" fill={s.color} fontFamily="JetBrains Mono,monospace">{s.value}</text>
                  </svg>
                  <div>
                    <div style={{ fontSize:12, fontWeight:600, color:'var(--t1)' }}>{s.label}</div>
                    <div style={{ fontSize:9.5, color:'var(--t3)', fontFamily:'var(--mono)', marginTop:2 }}>{Math.round(pct*100)}% of total</div>
                  </div>
                </div>
              );
            })}
          </div>

          {/* live feed */}
          <Panel noPad style={{ animation:'fadein 0.45s var(--ease-out-expo) 0.22s both', overflow:'hidden', flex:1 }}>
            <div style={{ display:'flex', alignItems:'center', gap:7, padding:'11px 13px', borderBottom:'1px solid var(--border)' }}>
              <span style={{ width:5, height:5, borderRadius:'50%', background:'var(--green)', animation:'pulse-dot 2.2s ease-in-out infinite' }}/>
              <span style={{ fontSize:12, fontWeight:600, color:'var(--t1)' }}>Live events</span>
              <button onClick={() => setPage('alerts')} style={{ marginLeft:'auto', fontSize:10, color:'var(--p4)', background:'none', border:'none', cursor:'pointer', fontFamily:'var(--mono)' }}>Alerts →</button>
            </div>
            {firedAlerts.length === 0 ? (
              <div style={{ padding:'20px 13px', fontSize:11, color:'var(--t4)', textAlign:'center' }}>No events yet — alerts will appear here.</div>
            ) : firedAlerts.slice(0, 5).map((ev, i) => (
              <div key={ev.id} style={{ display:'flex', alignItems:'center', gap:8, padding:'8px 13px', borderBottom: i<4?'1px solid rgba(255,255,255,0.03)':'none', opacity:Math.max(0.18, 1-i*0.16), animation:'feed-enter 0.3s var(--ease-out-expo) both', transition:'opacity 0.4s' }}>
                <GlowDot status={ev.type==='online'?'online':ev.type==='game'?'in-game':'offline'} size={5}/>
                <div style={{ flex:1, minWidth:0, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>
                  <span style={{ fontSize:11, fontWeight:600, color:'var(--t1)' }}>{(ev.roblox_username||'').split('_')[0]}</span>
                  <span style={{ fontSize:11, color:'var(--t3)' }}> {ev.event}</span>
                </div>
                <span style={{ fontSize:9, color:'var(--t4)', fontFamily:'var(--mono)', flexShrink:0 }}>{ev.fired_at ? new Date(ev.fired_at).toLocaleTimeString([], {hour:'2-digit',minute:'2-digit'}) : ''}</span>
              </div>
            ))}
          </Panel>
        </div>
      </div>
    </div>
  );
};

// ─── TRACKING PAGE ────────────────────────────────────────────────────────────
const TrackingPage = ({ user, trackedUsers, setTrackedUsers, onOpenUser, addToast }) => {
  const [addType, setAddType]   = useState('user');
  const [inputVal, setInputVal] = useState('');
  const [loading, setLoading]   = useState(false);
  const [search, setSearch]     = useState('');
  const [statusFilter, setStatusFilter] = useState('all');
  const [sortCol, setSortCol]   = useState('roblox_username');
  const [sortDir, setSortDir]   = useState('asc');

  const handleAdd = async () => {
    if (!inputVal.trim()) { addToast({ type: 'error', msg: 'Enter a Roblox username.' }); return; }
    setLoading(true);
    try {
      const result = await apiRequest('POST', '/api/users', { username: inputVal.trim() });
      if (result.error) { addToast({ type: 'error', msg: result.error }); return; }
      setTrackedUsers(prev => [{ ...result, status: 'offline', game: null }, ...prev]);
      addToast({ type: 'success', msg: `Now tracking ${result.roblox_username}.` });
      setInputVal('');
    } catch (err) {
      addToast({ type: 'error', msg: err.message });
    } finally {
      setLoading(false);
    }
  };

  const handleRemove = async (u) => {
    try {
      await apiRequest('DELETE', `/api/users/${encodeURIComponent(u.roblox_username || u.username)}`);
      setTrackedUsers(prev => prev.filter(x => x.id !== u.id));
      addToast({ type: 'info', msg: `Removed ${u.roblox_username || u.username}` });
    } catch (err) {
      addToast({ type: 'error', msg: err.message });
    }
  };

  const handleFlag = async (u) => {
    try {
      const updated = await apiRequest('PATCH', `/api/users/${encodeURIComponent(u.roblox_username || u.username)}/flag`);
      setTrackedUsers(prev => prev.map(x => x.id === u.id ? { ...x, flagged: updated.flagged } : x));
    } catch (err) {
      addToast({ type: 'error', msg: err.message });
    }
  };

  const toggleSort = (col) => {
    if (sortCol === col) setSortDir(d => d === 'asc' ? 'desc' : 'asc');
    else { setSortCol(col); setSortDir('asc'); }
  };

  const filtered = useMemo(() => {
    let list = [...trackedUsers];
    const q = search.toLowerCase();
    if (q) list = list.filter(u => (u.roblox_username||u.username||'').toLowerCase().includes(q) || String(u.roblox_user_id||'').includes(q));
    if (statusFilter !== 'all') list = statusFilter === 'flagged' ? list.filter(u => u.flagged) : list.filter(u => u.status === statusFilter);
    list.sort((a, b) => {
      let av = a[sortCol] || '', bv = b[sortCol] || '';
      if (typeof av === 'string') av = av.toLowerCase();
      if (typeof bv === 'string') bv = bv.toLowerCase();
      return sortDir === 'asc' ? (av > bv ? 1 : -1) : (av < bv ? 1 : -1);
    });
    return list;
  }, [trackedUsers, search, statusFilter, sortCol, sortDir]);

  const rowsRef = useStaggerIn([filtered.length, search, statusFilter]);

  const SortBtn = ({ col, label }) => {
    const active = sortCol === col;
    return (
      <button onClick={() => toggleSort(col)} style={{ display: 'flex', alignItems: 'center', gap: 3, background: 'none', border: 'none', cursor: 'pointer', color: active ? 'var(--p4)' : 'var(--t4)', fontSize: 9.5, fontFamily: 'var(--mono)', fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.1em', padding: 0, transition: 'color 0.15s' }}>
        {label}{active ? (sortDir === 'asc' ? <Icon.SortUp /> : <Icon.SortDown />) : <Icon.Sort />}
      </button>
    );
  };

  const statusTabs = [
    { id: 'all',     label: `All (${trackedUsers.length})` },
    { id: 'online',  label: `Online (${trackedUsers.filter(u => u.status === 'online').length})` },
    { id: 'in-game', label: `In-game (${trackedUsers.filter(u => u.status === 'in-game').length})` },
    { id: 'offline', label: `Offline (${trackedUsers.filter(u => u.status === 'offline').length})` },
    { id: 'flagged', label: `Flagged (${trackedUsers.filter(u => u.flagged).length})` },
  ];

  return (
    <div className="page-enter" style={{ padding: '28px 30px', maxWidth: 1040, margin: '0 auto' }}>
      <PageHeader title="Tracking" sub={`${trackedUsers.length} users monitored`} badge={<LiveBadge />} />

      <Panel style={{ marginBottom: 14, animation: 'fadein 0.4s var(--ease-out-expo) both' }}>
        <SectionLabel>Add to tracking</SectionLabel>
        <div style={{ display: 'flex', gap: 9 }}>
          <div style={{ flex: 1 }}>
            <Input value={inputVal} onChange={setInputVal} placeholder="Roblox username" icon={<Icon.User />} onKeyDown={e => e.key === 'Enter' && handleAdd()} />
          </div>
          <Btn onClick={handleAdd} disabled={loading} icon={loading ? null : <Icon.Plus />}>{loading ? 'Adding...' : 'Add'}</Btn>
        </div>
      </Panel>

      <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 10, animation: 'fadein 0.4s var(--ease-out-expo) 0.07s both' }}>
        <div style={{ flex: 1 }}>
          <Input value={search} onChange={setSearch} placeholder="Filter by username or ID..." icon={<Icon.Search />} />
        </div>
        <div style={{ display: 'flex', gap: 3 }}>
          {statusTabs.map(t => (
            <button key={t.id} onClick={() => setStatusFilter(t.id)} style={{ padding: '6px 11px', borderRadius: 6, cursor: 'pointer', background: statusFilter === t.id ? 'var(--p-dim)' : 'transparent', border: statusFilter === t.id ? '1px solid rgba(6,182,212,0.25)' : '1px solid transparent', color: statusFilter === t.id ? 'var(--p3)' : 'var(--t3)', fontSize: 11.5, fontFamily: 'var(--font)', fontWeight: 500, transition: 'all 0.15s', whiteSpace: 'nowrap' }}>
              {t.label}
            </button>
          ))}
        </div>
      </div>

      <Panel noPad style={{ overflow: 'hidden', animation: 'fadein 0.4s var(--ease-out-expo) 0.12s both' }}>
        <div style={{ display: 'grid', gridTemplateColumns: '2.2fr 1fr 1.2fr 0.85fr 80px', padding: '8px 18px', background: 'rgba(255,255,255,0.018)', borderBottom: '1px solid var(--border)' }}>
          {[['roblox_username','User'], ['status','Status'], ['game','Game'], ['added_at','Added'], ['','']].map(([col, label]) => (
            <div key={col+label}>{col ? <SortBtn col={col} label={label} /> : null}</div>
          ))}
        </div>

        {filtered.length === 0 ? (
          <div style={{ padding: '48px 40px', textAlign: 'center', animation: 'fadein 0.35s var(--ease-out-expo) both' }}>
            <div style={{ width: 36, height: 36, borderRadius: '50%', border: '1px solid var(--border)', display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '0 auto 13px', color: 'var(--t4)' }}><Icon.Tracking /></div>
            <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--t2)', marginBottom: 5 }}>{search || statusFilter !== 'all' ? 'No matches' : 'Nothing tracked yet'}</div>
            <div style={{ fontSize: 12, color: 'var(--t3)' }}>{search || statusFilter !== 'all' ? 'Try a different filter.' : 'Add a Roblox username above.'}</div>
          </div>
        ) : (
          <div ref={rowsRef}>
            {filtered.map((u, i) => {
              const name = u.roblox_username || u.username || '';
              return (
                <div key={u.id} style={{ display: 'grid', gridTemplateColumns: '2.2fr 1fr 1.2fr 0.85fr 80px', padding: '11px 18px', alignItems: 'center', borderBottom: i < filtered.length - 1 ? '1px solid rgba(255,255,255,0.035)' : 'none', transition: 'background 0.15s', cursor: 'pointer', background: u.flagged ? 'rgba(251,191,36,0.025)' : 'transparent' }}
                  onClick={() => onOpenUser(u)}
                  onMouseEnter={e => e.currentTarget.style.background = 'rgba(6,182,212,0.05)'}
                  onMouseLeave={e => e.currentTarget.style.background = u.flagged ? 'rgba(251,191,36,0.025)' : 'transparent'}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                    <Avatar name={name} size={30} status={u.status} robloxId={u.roblox_user_id} />
                    <div>
                      <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                        <span style={{ fontSize: 12.5, fontWeight: 600, color: 'var(--t1)' }}>{name}</span>
                        {u.flagged && <Badge color="amber" size="xs">Flagged</Badge>}
                      </div>
                      <div style={{ fontSize: 9.5, color: 'var(--t4)', fontFamily: 'var(--mono)', marginTop: 1 }}>{u.roblox_user_id || '—'}</div>
                    </div>
                  </div>
                  <div onClick={e => e.stopPropagation()}><StatusPill status={u.status || 'offline'} /></div>
                  <div style={{ fontSize: 11.5, color: u.game ? 'var(--t2)' : u.status === 'in-game' ? 'var(--t3)' : 'var(--t4)', fontFamily: 'var(--mono)', fontStyle: !u.game && u.status === 'in-game' ? 'italic' : 'normal' }}>
                    {u.game || (u.status === 'in-game' ? 'Private game' : '—')}
                    {u.status === 'in-game' && u.place_id && (
                      <button onClick={e => { e.stopPropagation(); window.open(`roblox://experiences/start?placeId=${u.place_id}`, '_self'); }} style={{ marginLeft: 6, padding: '2px 7px', background: 'rgba(251,191,36,0.1)', border: '1px solid rgba(251,191,36,0.25)', borderRadius: 4, color: 'var(--amber)', fontSize: 10, cursor: 'pointer', fontFamily: 'var(--font)' }}>Join</button>
                    )}
                  </div>
                  <div style={{ fontSize: 11, color: 'var(--t3)', fontFamily: 'var(--mono)' }}>{u.added_at ? new Date(u.added_at).toLocaleDateString() : '—'}</div>
                  <div style={{ display: 'flex', gap: 3, justifyContent: 'flex-end' }} onClick={e => e.stopPropagation()}>
                    <button onClick={() => handleFlag(u)} title="Flag" style={{ background: u.flagged ? 'var(--amber-dim)' : 'transparent', border: `1px solid ${u.flagged ? 'rgba(251,191,36,0.25)' : 'var(--border)'}`, color: u.flagged ? 'var(--amber)' : 'var(--t4)', borderRadius: 5, cursor: 'pointer', padding: '4px 7px', fontSize: 11, transition: 'all 0.15s' }}>⚑</button>
                    <button onClick={() => handleRemove(u)} title="Remove" style={{ background: 'transparent', border: '1px solid var(--border)', color: 'var(--t4)', borderRadius: 5, cursor: 'pointer', padding: '4px 6px', display: 'flex', alignItems: 'center', transition: 'all 0.15s' }}
                      onMouseEnter={e => { e.currentTarget.style.color='var(--red)'; e.currentTarget.style.background='var(--red-dim)'; }}
                      onMouseLeave={e => { e.currentTarget.style.color='var(--t4)'; e.currentTarget.style.background='transparent'; }}><Icon.Trash /></button>
                  </div>
                </div>
              );
            })}
          </div>
        )}
      </Panel>
      <div style={{ marginTop: 12, fontSize: 11, color: 'var(--t4)', lineHeight: 1.6, padding: '10px 14px', background: 'var(--bg2)', borderRadius: 8, border: '1px solid var(--border)' }}>
        RoStealth only accesses publicly available Roblox data. Not affiliated with Roblox Corporation.
      </div>
    </div>
  );
};

// ─── ANALYTICS PAGE ───────────────────────────────────────────────────────────
const AnalyticsPage = ({ user, trackedUsers, onOpenUser }) => {
  const [range, setRange]     = useState('7d');
  const [hovUser, setHovUser] = useState(null);
  const [chartData, setChartData] = useState([]);
  const [loadingChart, setLoadingChart] = useState(true);

  const online  = trackedUsers.filter(u => u.status === 'online').length;
  const inGame  = trackedUsers.filter(u => u.status === 'in-game').length;
  const offline = trackedUsers.filter(u => u.status === 'offline').length;
  const total   = trackedUsers.length || 1;

  useEffect(() => {
    setLoadingChart(true);
    apiRequest('GET', '/api/analytics')
      .then(rows => {
        // Format for chart: group by day label
        const byDay = {};
        rows.forEach(r => {
          const day = new Date(r.day).toLocaleDateString('en', { weekday: 'short' });
          byDay[day] = (byDay[day] || 0) + parseInt(r.sessions || 0);
        });
        setChartData(Object.entries(byDay).map(([day, sessions]) => ({ day, sessions })));
      })
      .catch(() => setChartData([]))
      .finally(() => setLoadingChart(false));
  }, [range]);

  const rowsRef = useStaggerIn([trackedUsers.length]);

  return (
    <div className="page-enter" style={{ padding: '28px 30px', maxWidth: 1040, margin: '0 auto' }}>
      <PageHeader title="Analytics" sub={`${trackedUsers.length} tracked users`}
        right={
          <div style={{ display: 'flex', gap: 3 }}>
            {['7d'].map(r => (
              <button key={r} onClick={() => setRange(r)} style={{ padding: '5px 11px', borderRadius: 6, cursor: 'pointer', background: range === r ? 'var(--p-dim)' : 'transparent', border: range === r ? '1px solid rgba(6,182,212,0.28)' : '1px solid var(--border)', color: range === r ? 'var(--p3)' : 'var(--t3)', fontSize: 11, fontFamily: 'var(--mono)', transition: 'all 0.15s' }}>{r}</button>
            ))}
          </div>
        }
      />

      <Panel style={{ marginBottom: 14, animation: 'fadein 0.4s var(--ease-out-expo) 0.05s both' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 12 }}>
          {[{ label: 'Online', count: online, color: 'var(--green)' }, { label: 'In-game', count: inGame, color: 'var(--amber)' }, { label: 'Offline', count: offline, color: 'var(--t4)' }].map(s => (
            <div key={s.label} style={{ display: 'flex', alignItems: 'center', gap: 7 }}>
              <span style={{ width: 8, height: 8, borderRadius: 2, background: s.color, flexShrink: 0 }}/>
              <span style={{ fontSize: 13, fontWeight: 700, color: s.color }}>{s.count}</span>
              <span style={{ fontSize: 12, color: 'var(--t3)' }}>{s.label}</span>
            </div>
          ))}
        </div>
        <div style={{ height: 6, borderRadius: 4, background: 'var(--bg4)', overflow: 'hidden', display: 'flex' }}>
          {[{ pct: online/total, color: 'var(--green)' }, { pct: inGame/total, color: 'var(--amber)' }, { pct: offline/total, color: 'var(--bg4)' }].map((s,i) => (
            <div key={i} style={{ height: '100%', background: s.color, width: `${s.pct*100}%`, transition: 'width 0.85s var(--ease-out-expo)' }}/>
          ))}
        </div>
      </Panel>

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14, marginBottom: 14 }}>
        <Panel style={{ animation: 'fadein 0.4s var(--ease-out-expo) 0.1s both' }}>
          <PanelHeader title="Game sessions / day" sub="Last 7 days"/>
          {loadingChart ? <div style={{ height: 110, display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--t4)', fontSize: 12 }}>Loading...</div> : <BarChart data={chartData} height={110} />}
        </Panel>
        <Panel style={{ animation: 'fadein 0.4s var(--ease-out-expo) 0.16s both' }}>
          <PanelHeader title="Session trend" sub="Activity over time"/>
          {loadingChart ? <div style={{ height: 110, display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--t4)', fontSize: 12 }}>Loading...</div> : <LineChart data={chartData} height={110} />}
        </Panel>
      </div>

      <Panel noPad style={{ overflow: 'hidden', animation: 'fadein 0.4s var(--ease-out-expo) 0.24s both' }}>
        <div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr 1.4fr', padding: '8px 18px', background: 'rgba(255,255,255,0.018)', borderBottom: '1px solid var(--border)' }}>
          {['User','Status','Added'].map(h => (
            <div key={h} style={{ fontSize: 9.5, fontWeight: 600, color: 'var(--t4)', textTransform: 'uppercase', letterSpacing: '0.1em', fontFamily: 'var(--mono)' }}>{h}</div>
          ))}
        </div>
        <div ref={rowsRef}>
          {trackedUsers.map((u, i) => (
            <div key={u.id} onClick={() => onOpenUser(u)} style={{ display: 'grid', gridTemplateColumns: '2fr 1fr 1.4fr', padding: '12px 18px', borderBottom: i < trackedUsers.length - 1 ? '1px solid rgba(255,255,255,0.035)' : 'none', transition: 'background 0.15s', alignItems: 'center', cursor: 'pointer' }}
              onMouseEnter={e => { e.currentTarget.style.background = 'rgba(6,182,212,0.05)'; setHovUser(u.id); }}
              onMouseLeave={e => { e.currentTarget.style.background = 'transparent'; setHovUser(null); }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                <Avatar name={u.roblox_username||u.username} size={28} status={u.status} robloxId={u.roblox_user_id} />
                <span style={{ fontSize: 12.5, fontWeight: 600, color: 'var(--t1)' }}>{u.roblox_username||u.username}</span>
              </div>
              <StatusPill status={u.status || 'offline'} />
              <div style={{ fontSize: 11, color: 'var(--t3)', fontFamily: 'var(--mono)' }}>{u.added_at ? new Date(u.added_at).toLocaleDateString() : '—'}</div>
            </div>
          ))}
        </div>
      </Panel>
    </div>
  );
};

// ─── ALERTS PAGE ─────────────────────────────────────────────────────────────
const RULE_TRIGGERS = ['goes online', 'goes offline', 'joins any game', 'joins a specific game'];

const TriggerSVG = {
  online:  <svg width="16" height="16" viewBox="0 0 16 16" fill="none"><circle cx="8" cy="8" r="3.5" stroke="currentColor" strokeWidth="1.4"/><circle cx="8" cy="8" r="1.5" fill="currentColor"/><path d="M8 1v1.8M8 13.2V15M1 8h1.8M13.2 8H15" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" opacity="0.55"/></svg>,
  game:    <svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="1.5" y="5" width="13" height="7.5" rx="2" stroke="currentColor" strokeWidth="1.3"/><path d="M5 8.5H7M6 7.5V9.5" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round"/><circle cx="10" cy="8" r=".8" fill="currentColor"/><circle cx="11.5" cy="9.3" r=".8" fill="currentColor"/></svg>,
  offline: <svg width="16" height="16" viewBox="0 0 16 16" fill="none"><circle cx="8" cy="8" r="5.5" stroke="currentColor" strokeWidth="1.3" opacity="0.4"/><path d="M5 8h6" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>,
  bolt:    <svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M9 1.5L4 9h5l-1.5 5.5L14.5 7H9.5L9 1.5z" stroke="currentColor" strokeWidth="1.2" strokeLinejoin="round" fill="none"/></svg>,
};

const triggerIcon = (trigger) => {
  if (trigger.includes('online'))  return { svg: TriggerSVG.online,  color:'var(--green)', bg:'rgba(52,211,153,0.08)',  border:'rgba(52,211,153,0.2)'  };
  if (trigger.includes('game'))    return { svg: TriggerSVG.game,    color:'var(--amber)', bg:'rgba(251,191,36,0.08)',  border:'rgba(251,191,36,0.2)'  };
  if (trigger.includes('offline')) return { svg: TriggerSVG.offline, color:'var(--t3)',    bg:'rgba(255,255,255,0.04)', border:'var(--border)'          };
  return                                   { svg: TriggerSVG.bolt,   color:'var(--p4)',    bg:'var(--p-dim)',           border:'rgba(6,182,212,0.2)'   };
};

const AlertsPage = ({ user, trackedUsers, alertRules, setAlertRules, firedAlerts, addToast }) => {
  const [showAdd, setShowAdd]         = useState(false);
  const [ruleUser, setRuleUser]       = useState('');
  const [ruleTrigger, setRuleTrigger] = useState(RULE_TRIGGERS[0]);
  const [ruleGame, setRuleGame]       = useState('');
  const [preview, setPreview]         = useState(null);
  const [saving, setSaving]           = useState(false);

  const handleAddRule = async () => {
    if (!ruleUser) { addToast({ type: 'error', msg: 'Select a user for this rule.' }); return; }
    setSaving(true);
    try {
      const rule = await apiRequest('POST', '/api/alerts', {
        roblox_username: ruleUser,
        trigger: ruleTrigger,
        game: ruleTrigger === 'joins a specific game' ? ruleGame : null,
      });
      setAlertRules(prev => [{ ...rule, user: rule.roblox_username, firedCount: 0 }, ...prev]);
      addToast({ type: 'success', msg: 'Alert rule created.' });
      setShowAdd(false); setRuleUser(''); setRuleTrigger(RULE_TRIGGERS[0]); setRuleGame('');
    } catch (err) {
      addToast({ type: 'error', msg: err.message });
    } finally {
      setSaving(false);
    }
  };

  const toggleRule = async (rule) => {
    try {
      await apiRequest('PATCH', `/api/alerts/${rule.id}`, { enabled: !rule.enabled });
      setAlertRules(prev => prev.map(r => r.id === rule.id ? { ...r, enabled: !r.enabled } : r));
    } catch (err) {
      addToast({ type: 'error', msg: err.message });
    }
  };

  const deleteRule = async (id) => {
    try {
      await apiRequest('DELETE', `/api/alerts/${id}`);
      setAlertRules(prev => prev.filter(r => r.id !== id));
      addToast({ type: 'info', msg: 'Rule deleted.' });
    } catch (err) {
      addToast({ type: 'error', msg: err.message });
    }
  };

  const firedToday = firedAlerts.length;
  const activeCount = alertRules.filter(r => r.enabled).length;

  return (
    <div className="page-enter" style={{ padding: '28px 30px', maxWidth: 900, margin: '0 auto' }}>
      <div style={{ display:'flex', alignItems:'flex-start', justifyContent:'space-between', marginBottom:22, animation:'fadein 0.4s var(--ease-out-expo) both' }}>
        <div>
          <h1 style={{ fontSize:21, fontWeight:700, letterSpacing:'-0.04em', color:'var(--t1)', lineHeight:1 }}>Alerts</h1>
          <div style={{ display:'flex', gap:16, marginTop:6 }}>
            {[
              { v: alertRules.length, l: 'rules total' },
              { v: activeCount,       l: 'active',      c:'var(--green)' },
              { v: firedToday,        l: 'fired today',  c: firedToday?'var(--amber)':null },
            ].map(s => (
              <span key={s.l} style={{ fontSize:12.5, color:'var(--t3)' }}>
                <span style={{ fontWeight:600, color: s.c || 'var(--t1)' }}>{s.v}</span> {s.l}
              </span>
            ))}
          </div>
        </div>
        <Btn size="sm" icon={showAdd ? <Icon.Minus /> : <Icon.Plus />} onClick={() => setShowAdd(v => !v)}>
          {showAdd ? 'Cancel' : 'New rule'}
        </Btn>
      </div>

      {showAdd && (
        <div style={{ marginBottom:16, animation:'cmdk-in 0.28s var(--ease-out-expo) both' }}>
          <Panel style={{ borderColor:'rgba(6,182,212,0.3)', boxShadow:'0 0 28px rgba(6,182,212,0.1)' }}>
            <SectionLabel>New rule</SectionLabel>
            <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:10, marginBottom:12 }}>
              <div>
                <div style={{ fontSize:11, color:'var(--t3)', marginBottom:6 }}>When this user...</div>
                <select value={ruleUser} onChange={e => setRuleUser(e.target.value)} style={{ width:'100%', padding:'8px 10px', background:'var(--bg3)', border:`1px solid ${ruleUser?'var(--border-bright)':'var(--border)'}`, borderRadius:6, color:ruleUser?'var(--t1)':'var(--t3)', fontSize:13, fontFamily:'var(--font)', outline:'none', cursor:'pointer' }}>
                  <option value="">Select user...</option>
                  {trackedUsers.map(u => <option key={u.id} value={u.roblox_username||u.username}>{u.roblox_username||u.username}</option>)}
                </select>
              </div>
              <div>
                <div style={{ fontSize:11, color:'var(--t3)', marginBottom:6 }}>...does this:</div>
                <select value={ruleTrigger} onChange={e => setRuleTrigger(e.target.value)} style={{ width:'100%', padding:'8px 10px', background:'var(--bg3)', border:'1px solid var(--border-bright)', borderRadius:6, color:'var(--t1)', fontSize:13, fontFamily:'var(--font)', outline:'none', cursor:'pointer' }}>
                  {RULE_TRIGGERS.map(t => <option key={t} value={t}>{t}</option>)}
                </select>
              </div>
            </div>
            {ruleTrigger === 'joins a specific game' && (
              <div style={{ marginBottom:12 }}>
                <div style={{ fontSize:11, color:'var(--t3)', marginBottom:6 }}>Game name:</div>
                <Input value={ruleGame} onChange={setRuleGame} placeholder="e.g. Da Hood" icon={<Icon.Game />} />
              </div>
            )}
            {ruleUser && (
              <div style={{ background:'#313338', borderRadius:10, padding:'12px 14px', marginBottom:14, animation:'fadein 0.3s var(--ease-out-expo) both' }}>
                <div style={{ fontSize:10, color:'#949ba4', fontFamily:'var(--mono)', marginBottom:8, textTransform:'uppercase', letterSpacing:'0.06em' }}>Discord preview</div>
                <div style={{ display:'flex', gap:10 }}>
                  <div style={{ width:32, height:32, borderRadius:'50%', background:'var(--p6)', flexShrink:0, display:'flex', alignItems:'center', justifyContent:'center', fontSize:13, fontWeight:700, color:'#fff' }}>R</div>
                  <div>
                    <div style={{ display:'flex', alignItems:'baseline', gap:7, marginBottom:3 }}>
                      <span style={{ fontSize:13, fontWeight:700, color:'#fff' }}>RoStealth</span>
                      <span style={{ fontSize:10, background:'#5865F2', color:'#fff', padding:'1px 5px', borderRadius:3, fontWeight:600 }}>BOT</span>
                    </div>
                    <div style={{ fontSize:12.5, color:'#dbdee1' }}>
                      <span style={{ color:'#67E8F9', fontWeight:600 }}>{ruleUser}</span>{' '}
                      {ruleTrigger === 'goes online' && <span style={{ color:'#34D399' }}>is now online</span>}
                      {ruleTrigger === 'goes offline' && <span style={{ color:'#9ca3af' }}>went offline</span>}
                      {ruleTrigger === 'joins any game' && <span style={{ color:'#FBBF24' }}>started a game session</span>}
                      {ruleTrigger === 'joins a specific game' && <span style={{ color:'#FBBF24' }}>joined <b style={{ color:'#fff' }}>{ruleGame||'...'}</b></span>}
                    </div>
                  </div>
                </div>
              </div>
            )}
            <div style={{ display:'flex', gap:8 }}>
              <Btn size="sm" onClick={handleAddRule} disabled={saving} icon={<Icon.Check />}>{saving ? 'Creating...' : 'Create rule'}</Btn>
              <Btn size="sm" variant="ghost" onClick={() => setShowAdd(false)}>Cancel</Btn>
            </div>
          </Panel>
        </div>
      )}

      <div style={{ display:'flex', flexDirection:'column', gap:10, marginBottom:16 }}>
        {alertRules.length === 0 ? (
          <Panel style={{ animation:'fadein 0.4s var(--ease-out-expo) both' }}>
            <div style={{ textAlign:'center', padding:'24px 0' }}>
              <div style={{ width:44, height:44, borderRadius:'50%', background:'var(--bg3)', border:'1px solid var(--border)', display:'flex', alignItems:'center', justifyContent:'center', margin:'0 auto 14px', color:'var(--t4)' }}><Icon.Bolt /></div>
              <div style={{ fontSize:14, fontWeight:600, color:'var(--t2)', marginBottom:6 }}>No rules yet</div>
              <div style={{ fontSize:12.5, color:'var(--t3)', marginBottom:16 }}>Create rules to get alerted when tracked members go online, join a game, or go offline.</div>
              <Btn size="sm" icon={<Icon.Plus />} onClick={() => setShowAdd(true)}>Create your first rule</Btn>
            </div>
          </Panel>
        ) : alertRules.map((rule, i) => {
          const ti = triggerIcon(rule.trigger);
          const isOpen = preview === rule.id;
          const username = rule.roblox_username || rule.user || '';
          return (
            <div key={rule.id} style={{ animation:`fadein 0.38s var(--ease-out-expo) ${i*50}ms both` }}>
              <Panel noPad style={{ overflow:'hidden', borderColor: rule.enabled ? ti.border : 'var(--border)', boxShadow: rule.enabled ? `0 0 20px ${ti.bg}` : 'none', opacity: rule.enabled ? 1 : 0.5, transition:'all 0.25s var(--ease-out-expo)' }}>
                <div style={{ display:'flex', alignItems:'center', gap:13, padding:'14px 18px' }}>
                  <div style={{ width:40, height:40, borderRadius:10, background: rule.enabled ? ti.bg : 'var(--bg3)', border:`1px solid ${rule.enabled ? ti.border : 'var(--border)'}`, display:'flex', alignItems:'center', justifyContent:'center', color: rule.enabled ? ti.color : 'var(--t4)', flexShrink:0, transition:'all 0.25s' }}>
                    {ti.svg}
                  </div>
                  <div style={{ flex:1, minWidth:0 }}>
                    <div style={{ fontSize:14, fontWeight:600, color:'var(--t1)', lineHeight:1.2 }}>
                      <span style={{ color: rule.enabled ? ti.color : 'var(--t3)' }}>{username}</span>
                      {' '}<span style={{ color:'var(--t2)' }}>{rule.trigger}</span>
                      {rule.game && <span style={{ color:'var(--amber)' }}> "{rule.game}"</span>}
                    </div>
                    <div style={{ display:'flex', alignItems:'center', gap:10, marginTop:5 }}>
                      <span style={{ display:'flex', alignItems:'center', gap:5 }}>
                        <span style={{ width:5, height:5, borderRadius:'50%', background: rule.enabled ? 'var(--green)' : 'var(--t4)', animation: rule.enabled ? 'pulse-dot 2.2s ease-in-out infinite' : 'none' }}/>
                        <span style={{ fontSize:10.5, color: rule.enabled ? 'var(--green)' : 'var(--t4)', fontFamily:'var(--mono)' }}>{rule.enabled ? 'Active' : 'Paused'}</span>
                      </span>
                      <span style={{ fontSize:10.5, color:'var(--t4)', fontFamily:'var(--mono)' }}>· {rule.fired_count || 0} fired</span>
                    </div>
                  </div>
                  <div style={{ display:'flex', alignItems:'center', gap:8, flexShrink:0 }}>
                    <button onClick={() => setPreview(isOpen ? null : rule.id)} style={{ padding:'5px 10px', background: isOpen ? 'var(--p-dim)' : 'transparent', border:`1px solid ${isOpen ? 'rgba(6,182,212,0.25)' : 'var(--border)'}`, borderRadius:6, cursor:'pointer', color: isOpen ? 'var(--p4)' : 'var(--t4)', fontSize:11, fontFamily:'var(--mono)', transition:'all 0.15s' }}>
                      {isOpen ? 'Hide' : 'Preview'}
                    </button>
                    <Toggle on={rule.enabled} setOn={() => toggleRule(rule)} />
                    <button onClick={() => deleteRule(rule.id)} style={{ background:'none', border:'1px solid transparent', color:'var(--t4)', borderRadius:6, cursor:'pointer', padding:'5px 6px', display:'flex', alignItems:'center', transition:'all 0.15s' }}
                      onMouseEnter={e => { e.currentTarget.style.color='var(--red)'; e.currentTarget.style.background='var(--red-dim)'; e.currentTarget.style.borderColor='rgba(248,113,113,0.2)'; }}
                      onMouseLeave={e => { e.currentTarget.style.color='var(--t4)'; e.currentTarget.style.background='none'; e.currentTarget.style.borderColor='transparent'; }}><Icon.Trash /></button>
                  </div>
                </div>
                {isOpen && (
                  <div style={{ padding:'0 18px 16px', animation:'fadein 0.25s var(--ease-out-expo) both' }}>
                    <div style={{ background:'#313338', borderRadius:10, padding:'12px 14px' }}>
                      <div style={{ fontSize:10, color:'#949ba4', fontFamily:'var(--mono)', marginBottom:8, textTransform:'uppercase', letterSpacing:'0.06em' }}>Discord message preview</div>
                      <div style={{ display:'flex', gap:10 }}>
                        <div style={{ width:32, height:32, borderRadius:'50%', background:'var(--p6)', flexShrink:0, display:'flex', alignItems:'center', justifyContent:'center', fontSize:13, fontWeight:700, color:'#fff' }}>R</div>
                        <div>
                          <div style={{ display:'flex', alignItems:'baseline', gap:7, marginBottom:3 }}>
                            <span style={{ fontSize:13, fontWeight:700, color:'#fff' }}>RoStealth</span>
                            <span style={{ fontSize:10, background:'#5865F2', color:'#fff', padding:'1px 5px', borderRadius:3, fontWeight:600 }}>BOT</span>
                            <span style={{ fontSize:11, color:'#949ba4' }}>Today at {new Date().getHours()}:{String(new Date().getMinutes()).padStart(2,'0')}</span>
                          </div>
                          <div style={{ fontSize:12.5, color:'#dbdee1', lineHeight:1.5 }}>
                            <span style={{ color: ti.color, fontWeight:600 }}>{username}</span>{' '}
                            {rule.trigger === 'goes online'           && <span>is now <span style={{ color:'#34D399' }}>online</span></span>}
                            {rule.trigger === 'goes offline'          && <span>went <span style={{ color:'#9ca3af' }}>offline</span></span>}
                            {rule.trigger === 'joins any game'        && <span><span style={{ color:'#FBBF24' }}>started a session</span></span>}
                            {rule.trigger === 'joins a specific game' && <span>joined <span style={{ color:'#FBBF24', fontWeight:600 }}>{rule.game || '...'}</span></span>}
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                )}
              </Panel>
            </div>
          );
        })}
      </div>

      <Panel noPad style={{ overflow:'hidden', animation:'fadein 0.4s var(--ease-out-expo) 0.12s both' }}>
        <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', padding:'13px 18px', borderBottom:'1px solid var(--border)' }}>
          <div style={{ display:'flex', alignItems:'center', gap:8 }}>
            <GlowDot status="online" size={6}/>
            <span style={{ fontSize:13, fontWeight:600, color:'var(--t1)' }}>Recent triggers</span>
          </div>
          <span style={{ fontSize:10.5, fontFamily:'var(--mono)', color:'var(--t4)' }}>{firedAlerts.length} total</span>
        </div>
        {firedAlerts.length === 0 ? (
          <div style={{ padding:'28px 24px', textAlign:'center', fontSize:12, color:'var(--t3)' }}>No alerts fired yet. Create a rule and enable it above.</div>
        ) : (
          <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr' }}>
            {firedAlerts.slice(0, 10).map((a, i) => {
              const col = a.type==='online'?'var(--green)':a.type==='game'?'var(--amber)':'var(--t4)';
              const bg  = a.type==='online'?'rgba(52,211,153,0.04)':a.type==='game'?'rgba(251,191,36,0.04)':'transparent';
              return (
                <div key={a.id} style={{ display:'flex', gap:10, padding:'10px 18px', borderBottom:'1px solid rgba(255,255,255,0.03)', borderRight: i%2===0?'1px solid rgba(255,255,255,0.03)':'none', background:bg, animation:`fadein 0.3s var(--ease-out-expo) ${i*25}ms both` }}>
                  <GlowDot status={a.type==='online'?'online':a.type==='game'?'in-game':'offline'} size={6}/>
                  <div style={{ flex:1, minWidth:0 }}>
                    <div style={{ fontSize:12, color:'var(--t1)' }}><b style={{ color:col }}>{a.roblox_username}</b> {a.event}</div>
                    <div style={{ fontSize:9.5, color:'var(--t4)', fontFamily:'var(--mono)', marginTop:2 }}>{a.fired_at ? new Date(a.fired_at).toLocaleString() : ''}</div>
                  </div>
                </div>
              );
            })}
          </div>
        )}
      </Panel>
    </div>
  );
};

// ─── SETTINGS PAGE ────────────────────────────────────────────────────────────
const SettingsPage = ({ user, addToast }) => {
  const [copied, setCopied]                 = useState(false);
  const [discordWebhook, setDiscordWebhook] = useState('');
  const [webhookTested, setWebhookTested]   = useState(false);
  const [notifOnline, setNotifOnline]       = useState(true);
  const [notifGame, setNotifGame]           = useState(false);
  const [notifOffline, setNotifOffline]     = useState(false);
  const [saved, setSaved]                   = useState(false);

  const handleCopy = () => {
    try { navigator.clipboard.writeText(user.id || ''); } catch(e) {}
    setCopied(true); setTimeout(() => setCopied(false), 2000);
  };
  const handleSave = () => { setSaved(true); setTimeout(() => setSaved(false), 2200); };

  const SettingRow = ({ label, sub, control }) => (
    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '13px 0', borderBottom: '1px solid rgba(255,255,255,0.05)' }}>
      <div><div style={{ fontSize: 13, fontWeight: 600, color: 'var(--t1)' }}>{label}</div>{sub && <div style={{ fontSize: 11.5, color: 'var(--t3)', marginTop: 3 }}>{sub}</div>}</div>
      {control}
    </div>
  );

  return (
    <div className="page-enter" style={{ padding: '28px 30px', maxWidth: 640, margin: '0 auto' }}>
      <PageHeader title="Settings" sub="Account, notifications, integrations." />

      <Panel style={{ marginBottom: 12, animation: 'fadein 0.4s var(--ease-out-expo) both' }}>
        <SectionLabel>Account</SectionLabel>
        <div style={{ display: 'flex', alignItems: 'center', gap: 14, padding: '13px 15px', background: 'var(--bg3)', borderRadius: 10, border: '1px solid var(--border)' }}>
          <Avatar name={user.username} size={44} />
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 14, fontWeight: 700, color: 'var(--t1)', letterSpacing: '-0.02em' }}>{user.username}</div>
            <div style={{ fontSize: 12, color: 'var(--t3)', marginTop: 3 }}>{user.email}</div>
          </div>
          <Badge color={user.plan === 'Pro' ? 'purple' : 'blue'}>{user.plan}</Badge>
        </div>
      </Panel>

      <Panel style={{ marginBottom: 12, animation: 'fadein 0.4s var(--ease-out-expo) 0.06s both' }}>
        <SectionLabel>Notifications</SectionLabel>
        <SettingRow label="Member comes online" sub="Fire when any tracked user goes online" control={<Toggle on={notifOnline} setOn={setNotifOnline} />} />
        <SettingRow label="Member joins a game" sub="Fire when a tracked user starts a session" control={<Toggle on={notifGame} setOn={setNotifGame} />} />
        <SettingRow label="Member goes offline" sub="Fire when a tracked user disconnects" control={<Toggle on={notifOffline} setOn={setNotifOffline} />} />
        <div style={{ marginTop: 16 }}>
          <Btn size="sm" onClick={handleSave} variant={saved ? 'secondary' : 'primary'}>{saved ? 'Saved' : 'Save changes'}</Btn>
        </div>
      </Panel>

      <Panel style={{ marginBottom: 12, animation: 'fadein 0.4s var(--ease-out-expo) 0.12s both' }}>
        <SectionLabel>Discord Webhook</SectionLabel>
        <p style={{ fontSize: 12.5, color: 'var(--t3)', marginBottom: 13, lineHeight: 1.65 }}>Status events fire as messages into your Discord channel. Paste a webhook URL from Discord's channel settings.</p>
        <Input value={discordWebhook} onChange={setDiscordWebhook} placeholder="https://discord.com/api/webhooks/..." icon={<Icon.Discord />} />
        <div style={{ display: 'flex', gap: 8, marginTop: 11 }}>
          <Btn size="sm" onClick={handleSave}>{saved ? 'Saved' : 'Save webhook'}</Btn>
          {discordWebhook && <Btn size="sm" variant="ghost" onClick={() => { setWebhookTested(true); setTimeout(() => setWebhookTested(false), 2500); }}>{webhookTested ? 'Sent!' : 'Test'}</Btn>}
        </div>
      </Panel>

      <div style={{ fontSize: 11, color: 'var(--t4)', lineHeight: 1.65, padding: '11px 14px', background: 'var(--bg2)', borderRadius: 8, border: '1px solid var(--border)', animation: 'fadein 0.4s var(--ease-out-expo) 0.24s both' }}>
        This service uses only publicly available Roblox data. Not affiliated with Roblox Corporation.
      </div>
    </div>
  );
};

// ─── ADMIN PAGE ──────────────────────────────────────────────────────────────
const AdminPage = ({ user }) => {
  const [stats, setStats] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const [refreshing, setRefreshing] = useState(false);

  const load = async () => {
    setRefreshing(true);
    try {
      const data = await apiRequest('GET', '/api/admin/stats');
      setStats(data);
      setError(null);
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
      setRefreshing(false);
    }
  };

  useEffect(() => { load(); }, []);

  const StatCard = ({ label, value, color = 'var(--t1)', sub }) => (
    <div style={{ background: 'var(--bg2)', border: '1px solid var(--border)', borderRadius: 12, padding: '16px 18px' }}>
      <div style={{ fontSize: 10, fontWeight: 600, color: 'var(--t4)', fontFamily: 'var(--mono)', textTransform: 'uppercase', letterSpacing: '0.1em', marginBottom: 8 }}>{label}</div>
      <div style={{ fontSize: 28, fontWeight: 700, color, letterSpacing: '-0.04em', lineHeight: 1 }}>{value ?? '—'}</div>
      {sub && <div style={{ fontSize: 10.5, color: 'var(--t3)', marginTop: 6 }}>{sub}</div>}
    </div>
  );

  const ServiceDot = ({ ok, label }) => (
    <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '10px 14px', background: ok ? 'rgba(52,211,153,0.05)' : 'rgba(248,113,113,0.05)', border: `1px solid ${ok ? 'rgba(52,211,153,0.15)' : 'rgba(248,113,113,0.15)'}`, borderRadius: 8 }}>
      <span style={{ width: 7, height: 7, borderRadius: '50%', background: ok ? 'var(--green)' : 'var(--red)', animation: ok ? 'pulse-dot 2.2s ease-in-out infinite' : 'none', flexShrink: 0 }} />
      <span style={{ fontSize: 12, fontWeight: 600, color: 'var(--t1)' }}>{label}</span>
      <span style={{ marginLeft: 'auto', fontSize: 10, fontFamily: 'var(--mono)', color: ok ? 'var(--green)' : 'var(--red)' }}>{ok ? 'healthy' : 'down'}</span>
    </div>
  );

  if (loading) return (
    <div style={{ padding: '80px 30px', textAlign: 'center', color: 'var(--t4)', fontSize: 13 }}>
      <div style={{ animation: 'spin 1s linear infinite', display: 'inline-block', width: 20, height: 20, border: '2px solid var(--border)', borderTopColor: 'var(--p4)', borderRadius: '50%', marginBottom: 12 }} />
      <div>Loading admin stats...</div>
    </div>
  );

  if (error) return (
    <div style={{ padding: '28px 30px', maxWidth: 700, margin: '0 auto' }}>
      <PageHeader title="Admin" sub="System monitoring" />
      <Panel style={{ borderColor: 'rgba(248,113,113,0.2)', background: 'rgba(248,113,113,0.04)' }}>
        <div style={{ fontSize: 13, color: 'var(--red)', marginBottom: 8, fontWeight: 600 }}>Access denied or API error</div>
        <div style={{ fontSize: 12, color: 'var(--t3)', fontFamily: 'var(--mono)' }}>{error}</div>
      </Panel>
    </div>
  );

  const s = stats;
  const memPct = s?.system?.memPct || 0;
  const load1 = s?.system?.loadAvg?.[0]?.toFixed(2) || '—';
  const uptimeH = s ? Math.floor(s.system.uptime / 3600) : 0;

  return (
    <div className="page-enter" style={{ padding: '28px 30px', maxWidth: 1100, margin: '0 auto' }}>
      <PageHeader title="Admin" sub="System health and platform overview"
        right={
          <button onClick={load} style={{ display: 'flex', alignItems: 'center', gap: 5, padding: '5px 12px', background: 'var(--bg3)', border: '1px solid var(--border)', borderRadius: 7, cursor: 'pointer', color: 'var(--t3)', fontSize: 11, fontFamily: 'var(--mono)', transition: 'all 0.15s' }}
            onMouseEnter={e => { e.currentTarget.style.borderColor='var(--border-bright)'; e.currentTarget.style.color='var(--t1)'; }}
            onMouseLeave={e => { e.currentTarget.style.borderColor='var(--border)'; e.currentTarget.style.color='var(--t3)'; }}>
            <span style={{ animation: refreshing ? 'spin 0.8s linear infinite' : 'none', display: 'flex' }}><Icon.Refresh /></span>
            Refresh
          </button>
        }
      />

      {/* service health */}
      <Panel style={{ marginBottom: 14, animation: 'fadein 0.4s var(--ease-out-expo) both' }}>
        <SectionLabel>Service health</SectionLabel>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 8 }}>
          <ServiceDot ok={true} label="API server" />
          <ServiceDot ok={s?.db?.ok} label="PostgreSQL" />
          <ServiceDot ok={s?.redis?.ok} label="Redis cache" />
        </div>
      </Panel>

      {/* stat cards */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(5, 1fr)', gap: 10, marginBottom: 14, animation: 'fadein 0.4s var(--ease-out-expo) 0.07s both' }}>
        <StatCard label="Registered users" value={s?.counts?.registeredUsers} color="var(--p4)" />
        <StatCard label="Tracked members" value={s?.counts?.trackedUsers} color="var(--t1)" />
        <StatCard label="Active alert rules" value={s?.counts?.activeAlerts} color="var(--green)" />
        <StatCard label="Snapshots today" value={s?.counts?.snapshotsToday} color="var(--amber)" />
        <StatCard label="Alerts fired today" value={s?.counts?.alertsFiredToday} color={s?.counts?.alertsFiredToday > 0 ? 'var(--amber)' : 'var(--t4)'} />
      </div>

      {/* system metrics */}
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14, marginBottom: 14 }}>
        <Panel style={{ animation: 'fadein 0.4s var(--ease-out-expo) 0.12s both' }}>
          <SectionLabel>System</SectionLabel>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 1, background: 'var(--bg3)', border: '1px solid var(--border)', borderRadius: 10, overflow: 'hidden' }}>
            {[
              { label: 'Memory used', value: `${memPct}% (${Math.round((s?.system?.memUsed||0)/1024/1024)}MB)` },
              { label: 'Load avg (1m)', value: load1 },
              { label: 'Server uptime', value: `${uptimeH}h` },
              { label: 'Node.js', value: s?.system?.nodeVersion },
              { label: 'Platform', value: s?.system?.platform },
            ].map((row, i) => (
              <div key={row.label} style={{ display: 'flex', justifyContent: 'space-between', padding: '10px 14px', borderBottom: i < 4 ? '1px solid rgba(255,255,255,0.04)' : 'none' }}>
                <span style={{ fontSize: 12, color: 'var(--t3)' }}>{row.label}</span>
                <span style={{ fontSize: 12, fontWeight: 600, color: 'var(--t1)', fontFamily: 'var(--mono)' }}>{row.value || '—'}</span>
              </div>
            ))}
          </div>
          {/* memory bar */}
          <div style={{ marginTop: 14 }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 10, color: 'var(--t4)', fontFamily: 'var(--mono)', marginBottom: 5 }}>
              <span>Memory</span><span>{memPct}%</span>
            </div>
            <div style={{ height: 5, background: 'var(--bg4)', borderRadius: 4, overflow: 'hidden' }}>
              <div style={{ height: '100%', width: `${memPct}%`, background: memPct > 80 ? 'var(--red)' : memPct > 60 ? 'var(--amber)' : 'var(--green)', borderRadius: 4, transition: 'width 0.9s var(--ease-out-expo)' }} />
            </div>
          </div>
        </Panel>

        <Panel style={{ animation: 'fadein 0.4s var(--ease-out-expo) 0.16s both' }}>
          <SectionLabel>Top tracked users</SectionLabel>
          {(s?.topTracked || []).length === 0 ? (
            <div style={{ fontSize: 12, color: 'var(--t4)', textAlign: 'center', padding: '20px 0' }}>No tracking data yet.</div>
          ) : (s?.topTracked || []).map((u, i) => (
            <div key={u.roblox_username} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '8px 0', borderBottom: i < (s.topTracked.length - 1) ? '1px solid rgba(255,255,255,0.04)' : 'none' }}>
              <span style={{ fontSize: 10, color: 'var(--t4)', fontFamily: 'var(--mono)', width: 16, textAlign: 'right', flexShrink: 0 }}>{i+1}</span>
              <Avatar name={u.roblox_username} size={24} />
              <span style={{ flex: 1, fontSize: 12, fontWeight: 600, color: 'var(--t1)' }}>{u.roblox_username}</span>
              <Badge color="blue">{u.tracker_count} trackers</Badge>
            </div>
          ))}
        </Panel>
      </div>

      {/* recent users */}
      <Panel noPad style={{ overflow: 'hidden', animation: 'fadein 0.4s var(--ease-out-expo) 0.2s both' }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '13px 18px', borderBottom: '1px solid var(--border)' }}>
          <span style={{ fontSize: 13, fontWeight: 600, color: 'var(--t1)' }}>Recent signups</span>
          <span style={{ fontSize: 10.5, color: 'var(--t4)', fontFamily: 'var(--mono)' }}>{s?.counts?.registeredUsers} total</span>
        </div>
        {(s?.recentUsers || []).length === 0 ? (
          <div style={{ padding: '24px', textAlign: 'center', fontSize: 12, color: 'var(--t4)' }}>No users yet.</div>
        ) : (s?.recentUsers || []).map((u, i) => (
          <div key={u.clerk_user_id} style={{ display: 'grid', gridTemplateColumns: '2fr 1fr 1fr', padding: '10px 18px', borderBottom: i < s.recentUsers.length - 1 ? '1px solid rgba(255,255,255,0.035)' : 'none', alignItems: 'center' }}>
            <div style={{ fontSize: 11, color: 'var(--t2)', fontFamily: 'var(--mono)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{u.clerk_user_id}</div>
            <div style={{ fontSize: 11, color: 'var(--t3)', fontFamily: 'var(--mono)' }}>{new Date(u.joined).toLocaleDateString()}</div>
            <div style={{ fontSize: 11, color: 'var(--p4)', fontFamily: 'var(--mono)' }}>{u.tracked_count} tracked</div>
          </div>
        ))}
      </Panel>

      <div style={{ marginTop: 12, padding: '10px 14px', background: 'rgba(248,113,113,0.04)', border: '1px solid rgba(248,113,113,0.12)', borderRadius: 8, fontSize: 11, color: 'var(--red)', animation: 'fadein 0.4s var(--ease-out-expo) 0.28s both' }}>
        Admin access only. This page is visible only to the account owner.
      </div>
    </div>
  );
};

// ─── PRICING PAGE ─────────────────────────────────────────────────────────────
const FullPricingPage = ({ user }) => {
  const [loading, setLoading] = useState(false);
  const [error, setError]     = useState('');
  const isPro = user?.plan === 'Pro';

  const FEATURES = [
    'Real-time online / in-game / offline status',
    'Join game links — one click to jump in',
    'Smart alerts when members join specific games',
    'Full activity history & playtime analytics',
    'Unlimited members tracked',
    'Stealth mode — no bots, no Roblox passwords',
  ];

  const PORTAL_FALLBACK = 'https://billing.stripe.com/p/login/5kQbJ27DF12Ph1N8wx1RC00';

  const openPortal = async () => {
    setLoading(true); setError('');
    try {
      const token = await window.clerk?.session?.getToken();
      const res = await fetch(`${API_BASE}/api/billing/portal`, {
        method: 'POST',
        headers: { Authorization: `Bearer ${token}` },
      });
      const data = await res.json();
      if (data.url) { window.location.href = data.url; }
      else { window.location.href = PORTAL_FALLBACK; }
    } catch { window.location.href = PORTAL_FALLBACK; }
  };

  const openCheckout = () => { window.location.href = 'https://buy.stripe.com/5kQbJ27DF12Ph1N8wx1RC00'; };

  return (
    <div className="page-enter" style={{ padding: '28px 30px', maxWidth: 640, margin: '0 auto' }}>
      <PageHeader title="Subscription" sub="Manage your RoStealth Pro plan." />

      {/* Plan card */}
      <div style={{ background: 'var(--bg1)', border: `1px solid ${isPro ? 'rgba(52,211,153,0.25)' : 'var(--border)'}`, borderRadius: 14, padding: '24px 24px 20px', marginBottom: 16 }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 20 }}>
          <div>
            <div style={{ fontSize: 13, color: 'var(--t3)', marginBottom: 4 }}>Current plan</div>
            <div style={{ fontSize: 22, fontWeight: 700, letterSpacing: '-0.03em', color: 'var(--t1)' }}>
              RoStealth {isPro ? 'Pro' : 'Free'}
            </div>
          </div>
          <div style={{ padding: '5px 12px', borderRadius: 20, background: isPro ? 'rgba(52,211,153,0.1)' : 'var(--bg3)', border: `1px solid ${isPro ? 'rgba(52,211,153,0.3)' : 'var(--border)'}`, fontSize: 12, fontWeight: 600, color: isPro ? 'var(--green)' : 'var(--t3)', letterSpacing: '0.02em' }}>
            {isPro ? '● Active' : '○ Free'}
          </div>
        </div>

        {isPro ? (
          <>
            <div style={{ fontSize: 13.5, color: 'var(--t2)', marginBottom: 20, lineHeight: 1.6 }}>
              Your Pro plan is active. You have full access to all features below.
              To cancel or update payment details, use the billing portal.
            </div>
            <div style={{ display: 'flex', gap: 10 }}>
              <button onClick={openPortal} disabled={loading} style={{ padding: '10px 20px', background: loading ? 'var(--bg3)' : 'var(--bg3)', border: '1px solid var(--border2)', borderRadius: 9, color: loading ? 'var(--t4)' : 'var(--t1)', fontFamily: 'var(--font)', fontSize: 13.5, fontWeight: 600, cursor: loading ? 'not-allowed' : 'pointer', transition: 'all .15s' }}
                onMouseEnter={e => { if (!loading) e.currentTarget.style.borderColor = 'var(--p5)'; }}
                onMouseLeave={e => { e.currentTarget.style.borderColor = 'var(--border2)'; }}>
                {loading ? '↻ Loading…' : 'Manage / Cancel subscription →'}
              </button>
            </div>
            {error && <div style={{ marginTop: 10, fontSize: 13, color: 'var(--red)' }}>{error}</div>}
          </>
        ) : (
          <>
            <div style={{ fontSize: 13.5, color: 'var(--t2)', marginBottom: 20, lineHeight: 1.6 }}>
              Upgrade to Pro for <strong style={{ color: 'var(--t1)' }}>$5/month</strong> and unlock full community tracking.
            </div>
            <button onClick={openCheckout} style={{ padding: '11px 24px', background: '#06B6D4', border: 'none', borderRadius: 9, color: '#000', fontFamily: 'var(--font)', fontSize: 14, fontWeight: 700, cursor: 'pointer', transition: 'all .15s', boxShadow: '0 4px 16px rgba(6,182,212,0.3)' }}
              onMouseEnter={e => e.currentTarget.style.filter = 'brightness(1.1)'}
              onMouseLeave={e => e.currentTarget.style.filter = 'none'}>
              Upgrade to Pro — $5/mo
            </button>
          </>
        )}
      </div>

      {/* Features */}
      <div style={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 14, padding: '20px 24px' }}>
        <div style={{ fontSize: 12, fontWeight: 600, color: 'var(--t3)', letterSpacing: '0.06em', textTransform: 'uppercase', marginBottom: 14 }}>What's included</div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
          {FEATURES.map((f, i) => (
            <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10, fontSize: 13.5, color: 'var(--t2)' }}>
              <span style={{ color: 'var(--green)', fontSize: 14, flexShrink: 0 }}>✓</span>
              {f}
            </div>
          ))}
        </div>
      </div>

      <div style={{ marginTop: 14, fontSize: 11.5, color: 'var(--t4)', lineHeight: 1.7 }}>
        Billing managed securely by Stripe. Not affiliated with Roblox Corporation.
      </div>
    </div>
  );
};

// ─── FREE GATE FLOW ───────────────────────────────────────────────────────────
const FreeGateFlow = ({ user, onComplete }) => {
  const alreadyPro = user?.plan === 'Pro';
  const checkoutSuccess = new URLSearchParams(window.location.search).get('checkout') === 'success';
  const [step, setStep]         = useState(alreadyPro || checkoutSuccess ? 'subscribed' : 'search');
  const [query, setQuery]       = useState('');
  const [robloxUser, setRoblox] = useState(null);
  const [searching, setSearch]  = useState(false);
  const [error, setError]       = useState('');
  const [activeStep, setActive] = useState(-1);
  const [doneSteps, setDone]    = useState([]);
  const pricingRef = useRef(null);

  // clean ?checkout=success from URL without reloading
  useEffect(() => {
    if (checkoutSuccess) {
      const url = new URL(window.location.href);
      url.searchParams.delete('checkout');
      window.history.replaceState({}, '', url.toString());
    }
  }, []);

  const PROCESS_STEPS = [
    { label: 'Finding your member',          detail: 'Querying Roblox servers…'         },
    { label: 'Loading their Roblox profile', detail: 'Fetching avatar & account info…'  },
    { label: 'Setting up real-time tracker', detail: 'Connecting status polling…'        },
    { label: 'Configuring smart alerts',     detail: 'Preparing notification system…'   },
    { label: 'Your dashboard is ready',      detail: 'Unlock Pro to start tracking'      },
  ];

  const FEATURES = [
    { icon:'⚡', title:'Real-time status',   desc:'Online, in-game, offline — updated every 30s'    },
    { icon:'🎮', title:'Join game link',     desc:'One click to jump into their active session'      },
    { icon:'🔔', title:'Smart alerts',       desc:'Notify me when they join Arsenal, Da Hood…'      },
    { icon:'📊', title:'Activity history',   desc:'Full session timeline and playtime analytics'     },
    { icon:'♾️', title:'Unlimited tracking', desc:'Monitor your entire community, no cap'           },
    { icon:'👁️', title:'Stealth mode',      desc:'Zero bots, no Roblox passwords required'         },
  ];

  const lookup = async (e) => {
    e?.preventDefault();
    const q = query.trim();
    if (!q) return;
    setSearch(true); setError('');
    try {
      const res = await fetch(`${API_BASE}/api/roblox/lookup?username=${encodeURIComponent(q)}`);
      if (!res.ok) { setError('User not found. Check the username and try again.'); setSearch(false); return; }
      const data = await res.json();
      setRoblox(data);
      setStep('confirm');
    } catch { setError('Search failed. Check your connection and try again.'); }
    setSearch(false);
  };

  const confirm = () => {
    setStep('processing');
    setActive(0); setDone([]);
    PROCESS_STEPS.forEach((_, i) => {
      setTimeout(() => setActive(i), i * 820);
      setTimeout(() => setDone(p => [...p, i]), i * 820 + 640);
    });
    setTimeout(() => setStep('paywall'), PROCESS_STEPS.length * 820 + 300);
  };

  const [pricingTableMounted, setPricingTableMounted] = useState(false);
  const [pricingTableHasContent, setPricingTableHasContent] = useState(false);

  useEffect(() => {
    if (step !== 'paywall' || !pricingRef.current || !window.clerk) return;
    const el = pricingRef.current;
    try {
      window.clerk.mountPricingTable(el, {});
      setPricingTableMounted(true);
      // Check after 1.5s if anything was injected
      setTimeout(() => {
        if (el && el.children.length > 0) setPricingTableHasContent(true);
      }, 1500);
    } catch(e) { console.warn('clerk mountPricingTable:', e); }
    return () => { try { window.clerk.unmountPricingTable?.(el); } catch {} };
  }, [step]);

  const [checkingOut, setCheckingOut] = useState(false);
  const STRIPE_LINK = 'https://buy.stripe.com/5kQbJ27DF12Ph1N8wx1RC00';

  const triggerCheckout = () => {
    window.location.href = STRIPE_LINK;
  };

  const BG = { minHeight:'100vh', background:'#020408', display:'flex', alignItems:'center', justifyContent:'center', flexDirection:'column', position:'relative', overflow:'hidden' };

  // ── ALREADY SUBSCRIBED ───────────────────────────────────────────────────────
  if (step === 'subscribed') return (
    <div style={{ minHeight:'100vh', background:'#020408', display:'flex', alignItems:'center', justifyContent:'center', flexDirection:'column', position:'relative', overflow:'hidden' }}>
      <div style={{ position:'absolute', top:'-10%', left:'50%', transform:'translateX(-50%)', width:500, height:420, borderRadius:'50%', background:'rgba(6,182,212,0.07)', filter:'blur(80px)', pointerEvents:'none' }} />
      <div style={{ position:'relative', zIndex:1, width:'100%', maxWidth:400, padding:'0 24px', textAlign:'center', animation:'fadein 0.4s var(--ease-out-expo) both' }}>
        <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:44, justifyContent:'center' }}>
          <LogoMark size={28} />
          <span style={{ fontSize:16, fontWeight:700, letterSpacing:'-0.025em', color:'var(--t1)' }}>RoStealth</span>
        </div>
        <div style={{ width:60, height:60, borderRadius:'50%', background:'rgba(52,211,153,0.1)', border:'1.5px solid rgba(52,211,153,0.3)', display:'flex', alignItems:'center', justifyContent:'center', margin:'0 auto 24px', fontSize:26 }}>✓</div>
        <h1 style={{ fontSize:24, fontWeight:700, letterSpacing:'-0.03em', color:'var(--t1)', marginBottom:10 }}>You're already subscribed</h1>
        <p style={{ fontSize:14, color:'var(--t3)', lineHeight:1.65, marginBottom:32 }}>
          Your RoStealth Pro plan is active. You don't need to subscribe again.
        </p>
        <button onClick={() => onComplete?.()} style={{ width:'100%', padding:'13px 0', background:'#06B6D4', border:'none', borderRadius:11, color:'#000', fontFamily:'var(--font)', fontSize:14.5, fontWeight:700, letterSpacing:'-0.01em', cursor:'pointer', transition:'all .15s' }}
          onMouseEnter={e => e.currentTarget.style.filter='brightness(1.1)'}
          onMouseLeave={e => e.currentTarget.style.filter='none'}>
          Continue to dashboard →
        </button>
      </div>
    </div>
  );

  // ── SEARCH ──────────────────────────────────────────────────────────────────
  if (step === 'search') return (
    <div style={BG}>
      <style>{`
        @keyframes g-pulse{0%,100%{opacity:.5}50%{opacity:.85}}
        .g-input{width:100%;padding:13px 14px 13px 40px;background:rgba(255,255,255,0.04);border:1px solid rgba(255,255,255,0.08);border-radius:11px;color:var(--t1);font-size:14px;font-family:var(--font);outline:none;transition:border-color .15s,box-shadow .15s,background .15s;box-sizing:border-box;}
        .g-input:focus{border-color:rgba(6,182,212,0.5);box-shadow:0 0 0 3px rgba(6,182,212,0.1);background:rgba(6,182,212,0.03);}
        .g-input::placeholder{color:var(--t4);}
        .g-btn{padding:13px;border:none;border-radius:11px;font-size:14px;font-weight:600;font-family:var(--font);cursor:pointer;transition:all .15s;letter-spacing:-.01em;width:100%;}
        .g-btn-active{background:#06B6D4;color:#000;box-shadow:0 4px 20px rgba(6,182,212,0.35);}
        .g-btn-active:hover{filter:brightness(1.08);box-shadow:0 6px 26px rgba(6,182,212,0.5);}
        .g-btn-disabled{background:rgba(255,255,255,0.05);color:var(--t4);cursor:default;}
      `}</style>
      <div style={{ position:'absolute', top:'-10%', left:'50%', transform:'translateX(-50%)', width:600, height:480, borderRadius:'50%', background:'rgba(6,182,212,0.07)', filter:'blur(80px)', pointerEvents:'none', animation:'g-pulse 6s ease-in-out infinite' }} />

      <div style={{ position:'relative', zIndex:1, width:'100%', maxWidth:400, padding:'0 24px', animation:'fadein 0.4s var(--ease-out-expo) both' }}>
        {/* Logo */}
        <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:44, justifyContent:'center' }}>
          <LogoMark size={28} />
          <span style={{ fontSize:16, fontWeight:700, letterSpacing:'-0.025em', color:'var(--t1)' }}>RoStealth</span>
        </div>

        {/* Headline */}
        <div style={{ marginBottom:32 }}>
          <h1 style={{ fontSize:26, fontWeight:700, letterSpacing:'-0.035em', color:'var(--t1)', marginBottom:8, lineHeight:1.2 }}>
            Who do you want to track?
          </h1>
          <p style={{ fontSize:14, color:'var(--t3)', lineHeight:1.6 }}>
            Enter their Roblox username to get started.
          </p>
        </div>

        {/* Form */}
        <form onSubmit={lookup} style={{ display:'flex', flexDirection:'column', gap:10 }}>
          <div style={{ position:'relative' }}>
            <svg width="14" height="14" viewBox="0 0 16 16" fill="none" style={{ position:'absolute', left:13, top:'50%', transform:'translateY(-50%)', color:'var(--t4)', pointerEvents:'none' }}>
              <circle cx="7" cy="7" r="4.5" stroke="currentColor" strokeWidth="1.4"/>
              <path d="M10.5 10.5l2.5 2.5" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round"/>
            </svg>
            <input autoFocus className="g-input" value={query} onChange={e => setQuery(e.target.value)}
              placeholder="Username" onKeyDown={e => e.key === 'Enter' && lookup()} />
          </div>
          {error && (
            <div style={{ fontSize:12, color:'var(--red)', padding:'8px 12px', background:'rgba(248,113,113,0.07)', borderRadius:8, border:'1px solid rgba(248,113,113,0.18)' }}>
              {error}
            </div>
          )}
          <button type="submit" disabled={searching || !query.trim()}
            className={`g-btn ${!searching && query.trim() ? 'g-btn-active' : 'g-btn-disabled'}`}>
            {searching
              ? <span style={{ display:'flex', alignItems:'center', justifyContent:'center', gap:7 }}>
                  <span style={{ animation:'spin .65s linear infinite', display:'inline-block', fontSize:13 }}>↻</span> Searching…
                </span>
              : 'Search →'}
          </button>
        </form>

        <p style={{ marginTop:24, fontSize:11, color:'var(--t4)', textAlign:'center', lineHeight:1.7 }}>
          Public data only · No Roblox login required
        </p>
      </div>
    </div>
  );

  // ── CONFIRM ──────────────────────────────────────────────────────────────────
  if (step === 'confirm') return (
    <div style={BG}>
      <div style={{ position:'absolute', top:'10%', left:'50%', transform:'translateX(-50%)', width:400, height:400, borderRadius:'50%', background:'rgba(6,182,212,0.06)', filter:'blur(70px)', pointerEvents:'none' }} />
      <div style={{ position:'relative', zIndex:1, width:'100%', maxWidth:380, padding:'0 24px', animation:'fadein 0.4s var(--ease-out-expo) both' }}>
        <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:40, justifyContent:'center' }}>
          <LogoMark size={24} />
          <span style={{ fontSize:15, fontWeight:700, letterSpacing:'-0.025em', color:'var(--t1)' }}>RoStealth</span>
        </div>

        {/* Profile card */}
        <div style={{ background:'rgba(255,255,255,0.025)', border:'1px solid rgba(255,255,255,0.07)', borderRadius:16, padding:'28px 24px 24px', marginBottom:16, textAlign:'center' }}>
          {robloxUser?.avatarUrl
            ? <img src={robloxUser.avatarUrl} alt="" style={{ width:72, height:72, borderRadius:'50%', display:'block', margin:'0 auto 14px', border:'2px solid rgba(255,255,255,0.1)' }} />
            : <div style={{ width:72, height:72, borderRadius:'50%', background:'rgba(255,255,255,0.06)', margin:'0 auto 14px', display:'flex', alignItems:'center', justifyContent:'center', fontSize:28, color:'var(--t4)' }}>?</div>
          }
          <div style={{ fontSize:18, fontWeight:700, color:'var(--t1)', letterSpacing:'-0.02em', marginBottom:3 }}>
            {robloxUser?.displayName || robloxUser?.username}
          </div>
          {robloxUser?.displayName && robloxUser.displayName !== robloxUser.username && (
            <div style={{ fontSize:12, color:'var(--t3)', fontFamily:'var(--mono)' }}>@{robloxUser.username}</div>
          )}
          <div style={{ fontSize:11, color:'var(--t4)', fontFamily:'var(--mono)', marginTop:8, padding:'4px 10px', background:'rgba(255,255,255,0.04)', borderRadius:6, display:'inline-block' }}>
            ID {robloxUser?.id}
          </div>
        </div>

        <p style={{ fontSize:12, color:'var(--t3)', textAlign:'center', marginBottom:16 }}>Is this the right person?</p>

        <div style={{ display:'flex', gap:8 }}>
          <button onClick={() => { setStep('search'); setRoblox(null); setQuery(''); }}
            style={{ flex:1, padding:'12px', background:'transparent', border:'1px solid rgba(255,255,255,0.09)', borderRadius:10, color:'var(--t3)', fontSize:13, fontWeight:600, fontFamily:'var(--font)', cursor:'pointer', transition:'all .15s' }}
            onMouseEnter={e => { e.currentTarget.style.borderColor='rgba(255,255,255,0.18)'; e.currentTarget.style.color='var(--t2)'; }}
            onMouseLeave={e => { e.currentTarget.style.borderColor='rgba(255,255,255,0.09)'; e.currentTarget.style.color='var(--t3)'; }}>
            Not them
          </button>
          <button onClick={confirm}
            style={{ flex:2, padding:'12px', background:'#06B6D4', border:'none', borderRadius:10, color:'#000', fontSize:13, fontWeight:700, fontFamily:'var(--font)', cursor:'pointer', transition:'all .15s', letterSpacing:'-.01em' }}
            onMouseEnter={e => { e.currentTarget.style.filter='brightness(1.08)'; }}
            onMouseLeave={e => { e.currentTarget.style.filter='none'; }}>
            Yes, track them →
          </button>
        </div>
      </div>
    </div>
  );

  // ── PROCESSING ───────────────────────────────────────────────────────────────
  if (step === 'processing') return (
    <div style={BG}>
      <div style={{ position:'absolute', top:'5%', right:'-5%', width:500, height:500, borderRadius:'50%', background:'rgba(6,182,212,0.07)', filter:'blur(80px)', pointerEvents:'none' }} />
      <div style={{ position:'relative', zIndex:1, width:'100%', maxWidth:460, padding:'0 24px' }}>

        <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:36, justifyContent:'center' }}>
          <LogoMark size={24} />
          <span style={{ fontSize:15, fontWeight:700, letterSpacing:'-0.025em', color:'var(--t1)' }}>RoStealth</span>
        </div>

        {/* Who we're setting up */}
        <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:28, padding:'10px 14px', background:'rgba(255,255,255,0.025)', border:'1px solid rgba(255,255,255,0.06)', borderRadius:10 }}>
          {robloxUser?.avatarUrl && <img src={robloxUser.avatarUrl} alt="" style={{ width:28, height:28, borderRadius:'50%', border:'1.5px solid rgba(255,255,255,0.1)' }} />}
          <span style={{ fontSize:13, color:'var(--t2)', fontWeight:500 }}>Setting up <strong style={{ color:'var(--t1)' }}>{robloxUser?.username}</strong></span>
          <div style={{ marginLeft:'auto', width:14, height:14, border:'2px solid rgba(6,182,212,0.2)', borderTopColor:'var(--p5)', borderRadius:'50%', animation:'spin .7s linear infinite', flexShrink:0 }} />
        </div>

        {/* Step cards */}
        <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
          {PROCESS_STEPS.map((s, i) => {
            const done   = doneSteps.includes(i);
            const active = activeStep === i && !done;
            const future = i > activeStep && !done;
            return (
              <div key={i} style={{
                padding:'14px 16px',
                borderRadius:12,
                background: done ? 'rgba(52,211,153,0.04)' : active ? 'rgba(6,182,212,0.06)' : 'rgba(255,255,255,0.02)',
                border:`1px solid ${done ? 'rgba(52,211,153,0.2)' : active ? 'rgba(6,182,212,0.35)' : 'rgba(255,255,255,0.05)'}`,
                display:'flex', alignItems:'center', gap:12,
                opacity: future ? 0.25 : 1,
                transition:'all 0.4s var(--ease-out-expo)',
              }}>
                {/* Icon */}
                <div style={{ width:28, height:28, borderRadius:8, flexShrink:0, transition:'all 0.3s',
                  background: done ? 'rgba(52,211,153,0.12)' : active ? 'rgba(6,182,212,0.1)' : 'rgba(255,255,255,0.04)',
                  border:`1px solid ${done ? 'rgba(52,211,153,0.25)' : active ? 'rgba(6,182,212,0.3)' : 'rgba(255,255,255,0.07)'}`,
                  display:'flex', alignItems:'center', justifyContent:'center' }}>
                  {done
                    ? <svg width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M2 6l2.5 2.5 5.5-5" stroke="#34D399" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/></svg>
                    : active
                    ? <div style={{ width:7, height:7, borderRadius:'50%', background:'var(--p5)', animation:'pulse-dot 1.1s ease-in-out infinite' }} />
                    : <div style={{ width:5, height:5, borderRadius:'50%', background:'rgba(255,255,255,0.1)' }} />
                  }
                </div>
                <div style={{ flex:1, minWidth:0 }}>
                  <div style={{ fontSize:13, fontWeight:600, letterSpacing:'-.01em', color: done ? '#34D399' : active ? 'var(--t1)' : 'var(--t4)', transition:'color 0.3s' }}>{s.label}</div>
                  {active && <div style={{ fontSize:11, color:'var(--t3)', marginTop:2 }}>{s.detail}</div>}
                </div>
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );

  // ── PAYWALL ──────────────────────────────────────────────────────────────────
  const PERKS = [
    'Live online / in-game / offline status',
    'One-click join their active game session',
    'Alerts when they join specific games',
    'Full session history and playtime stats',
    'Track unlimited community members',
    'No bots — 100% public Roblox data',
  ];
  const IconStatus = () => (
    <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
      <circle cx="7" cy="7" r="2.5" fill="#34D399"/>
      <circle cx="7" cy="7" r="5.5" stroke="#34D399" strokeWidth="1" opacity="0.3"/>
    </svg>
  );
  const IconGame = () => (
    <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
      <rect x="1.5" y="3.5" width="11" height="7" rx="2" stroke="currentColor" strokeWidth="1.2"/>
      <path d="M5 7h2m-1-1v2" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round"/>
      <circle cx="9.5" cy="6.5" r=".7" fill="currentColor"/><circle cx="9.5" cy="7.5" r=".7" fill="currentColor"/>
    </svg>
  );
  const IconBell = () => (
    <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
      <path d="M7 1.5a4 4 0 014 4v2.5l1 1.5H2L3 8V5.5a4 4 0 014-4z" stroke="currentColor" strokeWidth="1.2"/>
      <path d="M5.5 11a1.5 1.5 0 003 0" stroke="currentColor" strokeWidth="1.2"/>
    </svg>
  );
  const IconHistory = () => (
    <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
      <circle cx="7" cy="7" r="5.5" stroke="currentColor" strokeWidth="1.2"/>
      <path d="M7 4v3l2 1.5" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round"/>
    </svg>
  );
  const IconShield = () => (
    <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
      <path d="M7 1.5L2 3.5v4c0 2.5 2 4.5 5 5 3-0.5 5-2.5 5-5v-4L7 1.5z" stroke="currentColor" strokeWidth="1.2"/>
      <path d="M4.5 7l1.5 1.5L9.5 5" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round"/>
    </svg>
  );
  const IconUsers = () => (
    <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
      <circle cx="5" cy="5" r="2.5" stroke="currentColor" strokeWidth="1.2"/>
      <path d="M1 12c0-2.2 1.8-4 4-4s4 1.8 4 4" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round"/>
      <path d="M10 6.5c1.1 0 2 .9 2 2.5s-1 3.5-3 3.5" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round"/>
      <circle cx="10" cy="4" r="1.5" stroke="currentColor" strokeWidth="1.2"/>
    </svg>
  );

  const ROWS = [
    { Icon:IconStatus,  label:'Live status',          sub:'Online · In-game · Offline, updated every 30s',    },
    { Icon:IconGame,    label:'Join game',             sub:'Jump straight into their active session',          },
    { Icon:IconBell,    label:'Custom alerts',         sub:'Get notified when they join specific games',       },
    { Icon:IconHistory, label:'Session history',       sub:'Full timeline of when they played and for how long'},
    { Icon:IconUsers,   label:'Unlimited members',     sub:'Track your whole group — no per-member cap',       },
    { Icon:IconShield,  label:'No bots, no passwords', sub:'Works entirely off public Roblox data',            },
  ];

  return (
    <div style={{ minHeight:'100vh', background:'#020408', display:'flex', alignItems:'center', justifyContent:'center', padding:'48px 24px', overflowY:'auto' }}>
      <style>{`
        @keyframes pw-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
        .pw-cta{transition:filter .15s,box-shadow .15s;}
        .pw-cta:hover{filter:brightness(1.09);box-shadow:0 8px 30px rgba(6,182,212,0.5)!important;}
      `}</style>

      <div style={{ width:'100%', maxWidth:820, display:'grid', gridTemplateColumns:'1fr 1fr', gap:40, alignItems:'start', animation:'pw-in .4s var(--ease-out-expo) both' }}>

        {/* ── LEFT: What's included ─────────────────────── */}
        <div>
          {/* Tracked user chip */}
          <div style={{ display:'flex', alignItems:'center', gap:10, padding:'10px 12px', background:'rgba(255,255,255,0.025)', border:'1px solid rgba(255,255,255,0.07)', borderRadius:10, marginBottom:28 }}>
            {robloxUser?.avatarUrl && <img src={robloxUser.avatarUrl} alt="" style={{ width:32, height:32, borderRadius:'50%', border:'1.5px solid rgba(255,255,255,0.1)', flexShrink:0 }} />}
            <div style={{ minWidth:0, flex:1 }}>
              <div style={{ fontSize:13, fontWeight:600, color:'var(--t1)', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{robloxUser?.username}</div>
              <div style={{ fontSize:11, color:'var(--t4)', fontFamily:'var(--mono)' }}>ID {robloxUser?.id}</div>
            </div>
            <div style={{ display:'flex', alignItems:'center', gap:5, fontSize:11, color:'#34D399', background:'rgba(52,211,153,0.07)', border:'1px solid rgba(52,211,153,0.15)', borderRadius:20, padding:'3px 9px', flexShrink:0 }}>
              <div style={{ width:5, height:5, borderRadius:'50%', background:'#34D399' }} />
              Ready
            </div>
          </div>

          <div style={{ fontSize:11, fontWeight:600, letterSpacing:'.08em', textTransform:'uppercase', color:'var(--t4)', marginBottom:12 }}>What's included</div>

          <div style={{ display:'flex', flexDirection:'column', gap:1 }}>
            {PERKS.map((p, i) => (
              <div key={i} style={{ display:'flex', alignItems:'center', gap:10, padding:'9px 8px', borderRadius:8, animation:`pw-in .3s var(--ease-out-expo) ${60+i*40}ms both` }}>
                <svg width="13" height="13" viewBox="0 0 13 13" fill="none" style={{ flexShrink:0 }}>
                  <path d="M2 6.5l2.8 2.8 5.7-5.6" stroke="#34D399" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" opacity=".75"/>
                </svg>
                <span style={{ fontSize:13, color:'var(--t2)', lineHeight:1.4 }}>{p}</span>
              </div>
            ))}
          </div>

          <div style={{ marginTop:24, paddingTop:20, borderTop:'1px solid rgba(255,255,255,0.06)', fontSize:11, color:'var(--t4)', lineHeight:1.7 }}>
            Not affiliated with Roblox Corporation.<br/>Uses only public Roblox data — no passwords required.
          </div>
        </div>

        {/* ── RIGHT: Checkout ───────────────────────────── */}
        <div style={{ animation:'pw-in .4s var(--ease-out-expo) 80ms both' }}>
          <div style={{ display:'flex', alignItems:'center', gap:9, marginBottom:20 }}>
            <LogoMark size={22} />
            <span style={{ fontSize:15, fontWeight:700, letterSpacing:'-0.025em', color:'var(--t1)' }}>RoStealth</span>
          </div>

          <h2 style={{ fontSize:22, fontWeight:700, letterSpacing:'-0.035em', color:'var(--t1)', lineHeight:1.2, marginBottom:6 }}>
            Unlock tracking
          </h2>
          <p style={{ fontSize:13, color:'var(--t3)', lineHeight:1.6, marginBottom:20 }}>
            $5/mo · Cancel anytime · Secure via Stripe
          </p>

          <div ref={pricingRef} style={{ display:'none' }} />

          {/* Subscribe button */}
          <button className="pw-cta" onClick={triggerCheckout} disabled={checkingOut}
            style={{ width:'100%', padding:'13px 0', background: checkingOut ? 'rgba(6,182,212,0.5)' : '#06B6D4', border:'none', borderRadius:10, color:'#000', fontSize:14, fontWeight:700, fontFamily:'var(--font)', cursor: checkingOut ? 'wait' : 'pointer', letterSpacing:'-.01em', boxShadow:'0 3px 20px rgba(6,182,212,0.38)', marginBottom:20 }}>
            {checkingOut
              ? <span style={{ display:'flex', alignItems:'center', justifyContent:'center', gap:8 }}><span style={{ animation:'spin .6s linear infinite', display:'inline-block' }}>↻</span> Opening checkout…</span>
              : 'Subscribe — $5/mo'}
          </button>

          {/* Trust */}
          <div style={{ display:'flex', flexDirection:'column', gap:7, marginTop:16 }}>
            {[['Stripe-secured','card info never touches our servers'],['Cancel anytime','one click in account settings'],['Instant access','start tracking immediately']].map(([a,b],i)=>(
              <div key={i} style={{ display:'flex', gap:8, alignItems:'flex-start', fontSize:12, color:'var(--t4)', lineHeight:1.45 }}>
                <svg width="12" height="12" viewBox="0 0 12 12" fill="none" style={{ flexShrink:0, marginTop:1 }}><path d="M1.5 6l2.8 2.8 5.7-5.6" stroke="rgba(52,211,153,0.5)" strokeWidth="1.3" strokeLinecap="round" strokeLinejoin="round"/></svg>
                <span><span style={{ color:'var(--t3)', fontWeight:500 }}>{a}</span> — {b}</span>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
};

Object.assign(window, { DashboardPage, TrackingPage, AnalyticsPage, AlertsPage, SettingsPage, AdminPage, FullPricingPage, FreeGateFlow, Panel, PanelHeader, SectionLabel, Toggle, StatusPill, LiveBadge, PageHeader, UserDrawer, apiRequest });
