// FartBet — Board (activity feed), Rating, Profile, History, Admin
const { useState: useStateS2, useEffect: useEffectS2, useMemo: useMemoS2 } = React;

// Countdown timer — local copy (Babel standalone doesn’t guarantee cross-file order)
function CountdownS2({ closesAt, fallback }) {
  const [left, setLeft] = useStateS2('');
  useEffectS2(() => {
    if (!closesAt) { setLeft(''); return; }
    const target = new Date(closesAt).getTime();
    const tick = () => {
      const diff = target - Date.now();
      if (diff <= 0) { setLeft('⏱ Время вышло'); return; }
      const h = Math.floor(diff / 3600000);
      const m = Math.floor((diff % 3600000) / 60000);
      const s = Math.floor((diff % 60000) / 1000);
      const pad = n => String(n).padStart(2, '0');
      setLeft(`⏱ ${h > 0 ? h + ':' : ''}${pad(m)}:${pad(s)}`);
    };
    tick();
    const id = setInterval(tick, 1000);
    return () => clearInterval(id);
  }, [closesAt]);
  if (!closesAt) return fallback || null;
  return <span className={cx('countdown', left.includes('Время вышло') && 'countdown-expired')}>{left}</span>;
}

// ── BOARD: Twitter-style activity feed ──────────────────────────────────────
function BoardScreen({ data, recentBets, setRoute, user }) {
  const [filter, setFilter] = useStateS2('all'); // all | live | won | lost | mine
  const [reactState, setReactState] = useStateS2({});

  const filtered = recentBets.filter(b => {
    if (filter === 'all') return true;
    if (filter === 'mine') return user && b.userId === user.id;
    return b.status === filter;
  });

  const totalStaked = recentBets.reduce((a, b) => a + b.stake, 0);
  const totalLive = recentBets.filter(b => b.status === 'live').length;

  const react = (id, emoji) => {
    setReactState(s => ({
      ...s,
      [id]: { ...(s[id] || {}), [emoji]: ((s[id] || {})[emoji] || 0) + 1, mine: emoji }
    }));
  };

  return (
    <div className="board">
      <div className="board-hd">
        <div>
          <h1 className="page-h">Board</h1>
          <p className="page-sub">Лента активности · кто на что поставил. Без анонимности.</p>
        </div>
        <div className="board-stats">
          <div className="stat-mini">
            <div className="stat-mini-v">{totalLive}</div>
            <div className="stat-mini-l">активных ставок</div>
          </div>
          <div className="stat-mini">
            <div className="stat-mini-v"><CoinIcon size={16}/> {formatPC(totalStaked)}</div>
            <div className="stat-mini-l">общий оборот PC</div>
          </div>
          <div className="stat-mini">
            <div className="stat-mini-v">{new Set(recentBets.map(b => b.userId)).size}</div>
            <div className="stat-mini-l">игроков сегодня</div>
          </div>
        </div>
      </div>

      <div className="board-tabs">
        {[
          { k: 'all',  l: 'Вся лента', n: recentBets.length },
          { k: 'live', l: '⚡ В игре',  n: recentBets.filter(b => b.status === 'live').length },
          { k: 'won',  l: '✓ Выигрыши', n: recentBets.filter(b => b.status === 'won').length },
          { k: 'lost', l: '✗ Проигрыши', n: recentBets.filter(b => b.status === 'lost').length },
          { k: 'mine', l: 'Только мои',  n: user ? recentBets.filter(b => b.userId === user.id).length : 0 },
        ].map(t => (
          <button key={t.k} className={cx('board-tab', filter === t.k && 'active')} onClick={() => setFilter(t.k)}>
            {t.l} <span className="board-tab-n">{t.n}</span>
          </button>
        ))}
      </div>

      <div className="board-feed">
        {filtered.map(b => {
          const u = data.byId(b.userId);
          const e = data.EVENTS.find(x => x.id === b.eventId);
          if (!u || !e) return null;
          const out = e.outcomes.find(o => o.id === b.outcome);
          const isMe = user && b.userId === user.id;
          const r = reactState[b.id] || {};
          return (
            <article key={b.id} className={cx('board-card', `board-${b.status}`, isMe && 'board-mine')}>
              <Avatar user={u} size={42} ring={isMe} />
              <div className="board-body">
                <div className="board-line1">
                  <b className="board-name">{u.name}</b>
                  <span className="board-handle">{u.handle}</span>
                  {isMe && <span className="board-you">ты</span>}
                  <span className="board-dot">·</span>
                  <span className="board-ts">{b.ts}</span>
                  <div className="board-status-wrap">
                    {b.status === 'live' && <span className="board-status board-live">⚡ в игре</span>}
                    {b.status === 'won'  && <span className="board-status board-won">✓ выигрыш +{formatPC(b.payout || 0)} PC</span>}
                    {b.status === 'lost' && <span className="board-status board-lost">✗ проигрыш −{formatPC(b.stake)} PC</span>}
                  </div>
                </div>

                <div className="board-action">
                  поставил <CoinIcon size={13}/> <b>{formatPC(b.stake)} PC</b>{' '}
                  на <span className={`board-pick board-pick-${b.outcome}`}>{out?.label}</span>{' '}
                  с коэф. <b>{b.coef.toFixed(2)}</b>{' · '}
                  возможный выигрыш <b>{formatPC(b.stake * b.coef)} PC</b>
                </div>

                <button className="board-evt" onClick={() => setRoute({ name: 'event', id: e.id })}>
                  <CategoryTag cat={e.cat} data={data} />
                  <span className="board-evt-title">{e.title}</span>
                  <span className="board-evt-cta">К событию →</span>
                </button>

                {b.comment && <div className="board-cmt">«{b.comment}»</div>}

                <div className="board-react">
                  {['🔥', '💀', '🤝', '🤡'].map(em => (
                    <button key={em} className={cx('react-btn', r.mine === em && 'react-mine')} onClick={() => react(b.id, em)}>
                      <span>{em}</span>
                      {r[em] > 0 && <span className="react-n">{r[em]}</span>}
                    </button>
                  ))}
                  <button className="react-btn react-share">Поделиться</button>
                </div>
              </div>
            </article>
          );
        })}

        {filtered.length === 0 && <div className="empty-state">Пока пусто в этой ленте</div>}
      </div>
    </div>
  );
}

// ── RATING / LEADERBOARD ─────────────────────────────────────────────────────
function RatingScreen({ data, user, setRoute }) {
  const [scope, setScope] = useStateS2('all'); // all | day | week

  const players = useMemoS2(() => {
    return data.USERS.map(u => {
        const spark = data.SPARK[u.id] || [u.balance];
        const start = spark[0];
        const delta = u.balance - start;
        const deltaPct = start ? (delta / start) * 100 : 0;
        const myBets = data.BETS.filter(b => b.userId === u.id);
        const won = myBets.filter(b => b.status === 'won').length;
        const total = myBets.length || 1;
        return { ...u, delta, deltaPct, winrate: won / total, betsCount: myBets.length, spark };
      })
      .sort((a, b) => b.balance - a.balance);
  }, [data.USERS, data.BETS, data.SPARK]);

  const podium = players.slice(0, 3);
  const rest = players.slice(3);
  const myRank = user ? players.findIndex(p => p.id === user.id) + 1 : null;

  return (
    <div className="rating">
      <div className="rating-hd">
        <div>
          <h1 className="page-h">Рейтинг по PCOIN</h1>
          <p className="page-sub">Король корпоратива определяется здесь.</p>
        </div>
        <div className="board-tabs board-tabs-inline">
          {[{ k: 'all', l: 'Всё время' }, { k: 'week', l: 'Неделя' }, { k: 'day', l: 'Сегодня' }].map(t => (
            <button key={t.k} className={cx('board-tab', scope === t.k && 'active')} onClick={() => setScope(t.k)}>{t.l}</button>
          ))}
        </div>
      </div>

      {/* Podium */}
      <div className="podium">
        {[1, 0, 2].map(idx => {
          const p = podium[idx];
          if (!p) return <div key={idx} className="podium-slot empty"></div>;
          const place = idx + 1;
          return (
            <div key={p.id} className={cx('podium-slot', `podium-${place}`)}>
              <div className="podium-medal">{place === 1 ? '🥇' : place === 2 ? '🥈' : '🥉'}</div>
              <Avatar user={p} size={64} ring />
              <div className="podium-name">{p.name}</div>
              <div className="podium-bal"><CoinIcon size={18}/> {formatPC(p.balance)} PC</div>
              <div className={cx('podium-delta', p.delta >= 0 ? 'up' : 'down')}>
                {p.delta >= 0 ? '▲' : '▼'} {formatPC(Math.abs(p.delta))} PC · {p.deltaPct.toFixed(1)}%
              </div>
              <div className="podium-step" style={{ height: place === 1 ? 92 : place === 2 ? 64 : 44 }}>
                <span>{place}</span>
              </div>
            </div>
          );
        })}
      </div>

      {/* Your card */}
      {user && myRank && (
        <div className="my-rank">
          <div className="my-rank-l">
            <div className="my-rank-place">#{myRank}</div>
            <Avatar user={user} size={42} ring />
            <div>
              <div className="my-rank-n">{user.name} · твоё место</div>
              <div className="my-rank-s">{myRank === 1 ? 'Ты на вершине — удержи лидерство!' : `Победи ${players[0].name.split(' ')[0]} — он впереди на ${formatPC(players[0].balance - user.balance)} PC`}</div>
            </div>
          </div>
          <div className="my-rank-r">
            <PCoin amount={user.balance} big />
          </div>
        </div>
      )}

      {/* Table */}
      <div className="lb-table">
        <div className="lb-head">
          <span>#</span>
          <span>Игрок</span>
          <span>Динамика</span>
          <span>Винрейт</span>
          <span>Ставок</span>
          <span>Баланс</span>
        </div>
        {players.map((p, i) => (
          <div key={p.id} className={cx('lb-row', user && p.id === user.id && 'lb-mine')}>
            <span className="lb-rank">
              {i < 3 ? (i === 0 ? '🥇' : i === 1 ? '🥈' : '🥉') : `#${i + 1}`}
            </span>
            <div className="lb-player">
              <Avatar user={p} size={32} />
              <div>
                <div className="lb-name">{p.name}{user && p.id === user.id && <span className="lb-you">ты</span>}</div>
                <div className="lb-handle">{p.handle}</div>
              </div>
            </div>
            <div className="lb-spark">
              <Spark data={p.spark} />
              <span className={cx('lb-delta', p.delta >= 0 ? 'up' : 'down')}>
                {p.delta >= 0 ? '+' : '−'}{formatPC(Math.abs(p.delta))}
              </span>
            </div>
            <div className="lb-winrate">
              <div className="lb-wr-bar">
                <div className="lb-wr-fill" style={{ width: `${Math.round(p.winrate * 100)}%` }}></div>
              </div>
              <span>{Math.round(p.winrate * 100)}%</span>
            </div>
            <span className="lb-bets">{p.betsCount}</span>
            <span className="lb-bal"><CoinIcon size={14}/> {formatPC(p.balance)} PC</span>
          </div>
        ))}
      </div>
    </div>
  );
}

// ── PROFILE ─────────────────────────────────────────────────────────────────
function ProfileScreen({ user, data, recentBets, setRoute, onLogout, onRequestCoins }) {
  if (!user) return <div className="empty-state">Войди, чтобы увидеть профиль</div>;

  const [requesting, setRequesting] = useStateS2(false);
  const [reqMsg, setReqMsg] = useStateS2('');

  const handleRequestCoins = async () => {
    setRequesting(true);
    setReqMsg('');
    try {
      const res = await api.requestCoins();
      if (res.ok) {
        setReqMsg('✅ Заявка отправлена!');
      } else {
        setReqMsg('⚠️ ' + (res.error || 'Ошибка'));
      }
    } catch (e) {
      setReqMsg('⚠️ ' + (e.message || 'Ошибка'));
    }
    setRequesting(false);
  };

  const myBets = recentBets.filter(b => b.userId === user.id);
  const won = myBets.filter(b => b.status === 'won');
  const lost = myBets.filter(b => b.status === 'lost');
  const live = myBets.filter(b => b.status === 'live');
  const winrate = (won.length + lost.length) > 0 ? won.length / (won.length + lost.length) : 0;
  const totalStaked = myBets.reduce((a, b) => a + b.stake, 0);
  const totalWon = won.reduce((a, b) => a + (b.payout || 0), 0);
  const profit = totalWon - lost.reduce((a, b) => a + b.stake, 0) - won.reduce((a, b) => a + b.stake, 0);

  return (
    <div className="profile">
      <div className="profile-cover"></div>
      <div className="profile-card">
        <Avatar user={user} size={96} ring />
        <div className="profile-info">
          <h1 className="profile-name">{user.name}</h1>
          <div className="profile-handle">{user.handle}</div>
          <div className="profile-meta">
            <span>Регистрация: {user.joined}</span>
            <span className="dot-sep">·</span>
            <span>Роль: {user.role === 'admin' ? 'Админ лиги' : 'Игрок'}</span>
          </div>
        </div>
        <div className="profile-actions">
          <button className="btn btn-ghost" onClick={() => setRoute({ name: 'history' })}>История ставок</button>
          <button className="btn btn-ghost" onClick={onLogout}>Выйти</button>
        </div>
      </div>

      <div className="profile-balcard">
        <div>
          <div className="balcard-l">Баланс</div>
          <div className="balcard-v"><CoinIcon size={32}/> {formatPC(user.balance)} <span>PC</span></div>
          <div className="balcard-meta">≈ внутренняя валюта · реальные деньги не используются</div>
        </div>
        <button className="btn btn-primary balcard-btn" onClick={handleRequestCoins} disabled={requesting}>
          {requesting ? 'Отправка...' : 'Запросить +100 PC у админа'}
        </button>
        {reqMsg && <div className="balcard-msg">{reqMsg}</div>}
      </div>

      <div className="profile-stats">
        <div className="pstat">
          <div className="pstat-l">Ставок всего</div>
          <div className="pstat-v">{myBets.length}</div>
        </div>
        <div className="pstat">
          <div className="pstat-l">В игре</div>
          <div className="pstat-v live">{live.length}</div>
        </div>
        <div className="pstat">
          <div className="pstat-l">Винрейт</div>
          <div className="pstat-v">{Math.round(winrate * 100)}%</div>
        </div>
        <div className="pstat">
          <div className="pstat-l">Оборот</div>
          <div className="pstat-v"><CoinIcon size={14}/> {formatPC(totalStaked)}</div>
        </div>
        <div className="pstat">
          <div className="pstat-l">Прибыль</div>
          <div className={cx('pstat-v', profit >= 0 ? 'up' : 'down')}>
            {profit >= 0 ? '+' : '−'}{formatPC(Math.abs(profit))} PC
          </div>
        </div>
      </div>

      <div className="profile-recent">
        <div className="sect-hd"><h2>Последние ставки</h2>
          <button className="sect-link" onClick={() => setRoute({ name: 'history' })}>Все ставки →</button>
        </div>
        <HistoryList bets={myBets.slice(0, 6)} data={data} setRoute={setRoute} />
      </div>
    </div>
  );
}

// ── HISTORY (reused list) ───────────────────────────────────────────────────
function HistoryList({ bets, data, setRoute }) {
  return (
    <div className="hist-list">
      {bets.length === 0 && <div className="empty-state">Здесь будут твои ставки</div>}
      {bets.map(b => {
        const e = data.EVENTS.find(x => x.id === b.eventId);
        const out = e?.outcomes.find(o => o.id === b.outcome);
        if (!e) return null;
        return (
          <div key={b.id} className={cx('hist-row', `hist-${b.status}`)}>
            <div className="hist-status">
              {b.status === 'live' && <span className="hist-pill hist-pill-live">⚡ В игре</span>}
              {b.status === 'won'  && <span className="hist-pill hist-pill-won">✓ Выигрыш</span>}
              {b.status === 'lost' && <span className="hist-pill hist-pill-lost">✗ Проигрыш</span>}
            </div>
            <button className="hist-evt" onClick={() => setRoute({ name: 'event', id: e.id })}>
              <CategoryTag cat={e.cat} data={data}/>
              <span>{e.title}</span>
            </button>
            <div className="hist-pick"><span>{out?.label}</span><b>{b.coef.toFixed(2)}</b></div>
            <div className="hist-stake"><CoinIcon size={12}/> {formatPC(b.stake)} PC</div>
            <div className={cx('hist-result', b.status === 'won' && 'up', b.status === 'lost' && 'down')}>
              {b.status === 'won'  && <>+{formatPC(b.payout - b.stake)} PC</>}
              {b.status === 'lost' && <>−{formatPC(b.stake)} PC</>}
              {b.status === 'live' && <>возм. +{formatPC(b.stake * b.coef - b.stake)} PC</>}
            </div>
            <div className="hist-ts">{b.ts}</div>
          </div>
        );
      })}
    </div>
  );
}

function HistoryScreen({ user, data, recentBets, setRoute }) {
  const [tab, setTab] = useStateS2('all');
  if (!user) return <div className="empty-state">Войди, чтобы увидеть историю</div>;
  const my = recentBets.filter(b => b.userId === user.id);
  const filtered = my.filter(b => tab === 'all' ? true : b.status === tab);
  return (
    <div className="history">
      <h1 className="page-h">История моих ставок</h1>
      <p className="page-sub">Все ставки, выигрыши и обидные промахи.</p>

      <div className="board-tabs">
        {[
          { k: 'all',  l: 'Все', n: my.length },
          { k: 'live', l: 'В игре', n: my.filter(b => b.status === 'live').length },
          { k: 'won',  l: 'Выигранные', n: my.filter(b => b.status === 'won').length },
          { k: 'lost', l: 'Проигранные', n: my.filter(b => b.status === 'lost').length },
        ].map(t => (
          <button key={t.k} className={cx('board-tab', tab === t.k && 'active')} onClick={() => setTab(t.k)}>
            {t.l} <span className="board-tab-n">{t.n}</span>
          </button>
        ))}
      </div>

      <HistoryList bets={filtered} data={data} setRoute={setRoute} />
    </div>
  );
}

// ── ADMIN ───────────────────────────────────────────────────────────────────
function AdminScreen({ user, data, recentBets, setRoute, onCreateEvent, onSettle, onRefreshUsers }) {
  const [form, setForm] = useStateS2({
    title: '', subjectUserId: '', cat: '',
    outA: 'ДА', coefA: '1.85', outB: 'НЕТ', coefB: '2.10',
    closesNum: '3', closesUnit: 'ч',
  });
  const [inviteCopied, setInviteCopied] = useStateS2(null);
  const [roleLoading, setRoleLoading] = useStateS2(null);
  const [userSearch, setUserSearch] = useStateS2('');
  const [catForm, setCatForm] = useStateS2({ id: '', label: '', short: '' });
  const [catEdit, setCatEdit] = useStateS2(null); // { id, label, short } being edited
  const [coinReqs, setCoinReqs] = useStateS2([]);
  const [coinLoading, setCoinLoading] = useStateS2(null);

  // Load coin requests
  useEffectS2(() => {
    if (user && user.role === 'admin') {
      api.getCoinRequests().then(r => { if (Array.isArray(r)) setCoinReqs(r); });
    }
  }, [user]);

  // Refresh coin requests periodically
  useEffectS2(() => {
    if (!user || user.role !== 'admin') return;
    const iv = setInterval(() => {
      api.getCoinRequests().then(r => { if (Array.isArray(r)) setCoinReqs(r); });
    }, 5000);
    return () => clearInterval(iv);
  }, [user]);

  const decideCoinReq = async (id, decision) => {
    setCoinLoading(id);
    try {
      await api.decideCoinRequest(id, decision);
      const r = await api.getCoinRequests();
      if (Array.isArray(r)) setCoinReqs(r);
      if (onRefreshUsers) onRefreshUsers();
    } catch (e) { console.error(e); }
    setCoinLoading(null);
  };

  if (!user || user.role !== 'admin') {
    return (
      <div className="admin-locked">
        <div className="admin-locked-icon">🔒</div>
        <h2>Доступ только для админов</h2>
        <p>Зайди под профилем «Админ», чтобы создавать события и закрывать итоги.</p>
        <button className="btn btn-primary" onClick={() => setRoute({ name: 'home' })}>На главную</button>
      </div>
    );
  }

  const pending = data.EVENTS.filter(e => e.status === 'closed');
  const live = data.EVENTS.filter(e => e.status === 'live' || e.status === 'open');

  const createInvite = async (uid) => {
    try {
      const res = await api.createInvite(uid);
      if (res.ok) {
        await navigator.clipboard.writeText(res.url);
        setInviteCopied(uid);
        setTimeout(() => setInviteCopied(null), 3000);
      }
    } catch (e) {
      console.error('createInvite error', e);
    }
  };

  const toggleRole = async (u) => {
    const newRole = u.role === 'admin' ? 'user' : 'admin';
    setRoleLoading(u.id);
    try {
      const res = await api.setRole(u.id, newRole);
      if (res.ok && onRefreshUsers) await onRefreshUsers();
    } catch (e) {
      console.error('setRole error', e);
    }
    setRoleLoading(null);
  };

  const submit = () => {
    if (!form.title.trim()) return;
    if (!form.cat) return;
    const num = parseInt(form.closesNum, 10) || 2;
    const unitMap = { 'мин': 'мин', 'ч': 'час', 'д': 'дн' };
    const closesIn = `${num} ${unitMap[form.closesUnit] || form.closesUnit}`;
    onCreateEvent({
      title: form.title,
      subject_user_id: form.subjectUserId ? Number(form.subjectUserId) : null,
      cat: form.cat,
      closes_in: closesIn,
      starts_at: 'Сегодня',
      outcomes: [
        { id: 'yes', label: form.outA, coef: parseFloat(form.coefA) || 2, popularity: 0.5 },
        { id: 'no',  label: form.outB, coef: parseFloat(form.coefB) || 2, popularity: 0.5 },
      ],
    });
    setForm({ ...form, title: '', subjectUserId: '' });
  };

  const addCategory = async () => {
    if (!catForm.id || !catForm.label || !catForm.short) return;
    const res = await api.createCategory(catForm.id, catForm.label, catForm.short);
    if (res.ok) {
      setCatForm({ id: '', label: '', short: '' });
      if (onRefreshUsers) await onRefreshUsers(); // refreshes config too
    }
  };

  const saveCategory = async () => {
    if (!catEdit) return;
    const res = await api.updateCategory(catEdit.id, catEdit.label, catEdit.short);
    if (res.ok) {
      setCatEdit(null);
      if (onRefreshUsers) await onRefreshUsers();
    }
  };

  const removeCategory = async (id) => {
    if (!confirm('Удалить категорию ' + id + '?')) return;
    const res = await api.deleteCategory(id);
    if (res.ok && onRefreshUsers) await onRefreshUsers();
  };

  const filteredUsers = (data.USERS || []).filter(u =>
    !userSearch || u.name.toLowerCase().includes(userSearch.toLowerCase()) ||
    (u.handle && u.handle.toLowerCase().includes(userSearch.toLowerCase()))
  );

  return (
    <div className="admin">
      <div className="admin-hd">
        <h1 className="page-h"><span className="admin-pill">АДМИН</span> Управление событиями</h1>
        <p className="page-sub">Создавай события, закрывай ставки, объявляй победителей.</p>
      </div>

      <div className="admin-grid">
        {/* Create event form */}
        <div className="admin-card">
          <h2 className="admin-card-h">⚡ Создать событие</h2>
          <div className="admin-form">
            <label className="adm-l">Заголовок
              <input className="adm-input" placeholder="Например: «Опоздает ли Игорь на дейли?»"
                value={form.title} onChange={e => setForm({ ...form, title: e.target.value })} />
            </label>

            <div className="adm-row2">
              <label className="adm-l">Объект (пользователь)
                <select className="adm-input" value={form.subjectUserId} onChange={e => setForm({ ...form, subjectUserId: e.target.value })}>
                  <option value="">— не выбран —</option>
                  {(data.USERS || []).map(u => (
                    <option key={u.id} value={u.id}>{u.name}{u.handle ? ' (' + u.handle + ')' : ''}</option>
                  ))}
                </select>
              </label>
              <label className="adm-l">Категория
                <select className="adm-input" value={form.cat} onChange={e => setForm({ ...form, cat: e.target.value })}>
                  <option value="">— выбери —</option>
                  {Object.entries(data.CATEGORIES).map(([k, c]) => (
                    <option key={k} value={k}>{c.label}</option>
                  ))}
                </select>
              </label>
            </div>

            <div className="adm-row2">
              <label className="adm-l">Исход A
                <div className="adm-out">
                  <input className="adm-input" value={form.outA} onChange={e => setForm({ ...form, outA: e.target.value })} />
                  <input className="adm-input adm-coef" type="number" step="0.05" value={form.coefA}
                    onChange={e => setForm({ ...form, coefA: e.target.value })} />
                </div>
              </label>
              <label className="adm-l">Исход B
                <div className="adm-out">
                  <input className="adm-input" value={form.outB} onChange={e => setForm({ ...form, outB: e.target.value })} />
                  <input className="adm-input adm-coef" type="number" step="0.05" value={form.coefB}
                    onChange={e => setForm({ ...form, coefB: e.target.value })} />
                </div>
              </label>
            </div>

            <label className="adm-l">Таймер приёма ставок
              <div className="adm-timer-row">
                <input className="adm-input" type="number" min="1" max="999" style={{width: 70}}
                  value={form.closesNum} onChange={e => setForm({ ...form, closesNum: e.target.value })} />
                <select className="adm-input" style={{width: 90}} value={form.closesUnit} onChange={e => setForm({ ...form, closesUnit: e.target.value })}>
                  <option value="мин">минут</option>
                  <option value="ч">часов</option>
                  <option value="д">дней</option>
                </select>
              </div>
            </label>

            <button className="btn btn-primary btn-full" onClick={submit}>Опубликовать событие</button>
            <div className="adm-note">Событие сразу попадёт в общую линию. После таймера приём закроется автоматически.</div>
          </div>
        </div>

        {/* Pending settlement */}
        <div className="admin-card">
          <h2 className="admin-card-h">⏱ Ждут итога ({pending.length})</h2>
          {pending.length === 0 && <div className="empty-state">Все события расчитаны</div>}
          {pending.map(e => (
            <div key={e.id} className="adm-pending">
              <div className="adm-pending-t">{e.title}</div>
              <div className="adm-pending-m">
                <CategoryTag cat={e.cat} data={data}/>
                <span>{e.bettors} ставок · пул {formatPC(e.pool)} PC</span>
              </div>
              <div className="adm-pending-actions">
                {e.outcomes.map(o => (
                  <button key={o.id} className="btn btn-ghost-sm" onClick={() => onSettle(e.id, o.id)}>
                    Победил «{o.label}» ({o.coef.toFixed(2)})
                  </button>
                ))}
                <button className="btn btn-danger-sm" onClick={() => onSettle(e.id, '__cancel')}>Отменить · вернуть PC</button>
              </div>
            </div>
          ))}
        </div>

        {/* Active events */}
        <div className="admin-card admin-card-wide">
          <h2 className="admin-card-h">🔴 Активные события ({live.length})</h2>
          <div className="adm-live-grid">
            {live.map(e => (
              <div key={e.id} className="adm-live">
                <div className="adm-live-hd">
                  <CategoryTag cat={e.cat} data={data}/>
                  <StatusDot status={e.status}/>
                </div>
                <div className="adm-live-t">{e.title}</div>
                <div className="adm-live-m">
                  {e.bettors} ставок · пул {formatPC(e.pool)} PC · <CountdownS2 closesAt={e.closesAt} fallback={<span>{e.closesIn}</span>} />
                </div>
                <div className="adm-live-actions">
                  <button className="btn btn-ghost-sm" onClick={() => setRoute({ name: 'event', id: e.id })}>Открыть</button>
                  <button className="btn btn-ghost-sm" onClick={() => onSettle(e.id, '__close')}>Закрыть приём</button>
                </div>
              </div>
            ))}
          </div>
        </div>

        {/* Users — invites + admin roles */}
        <div className="admin-card admin-card-wide">
          <h2 className="admin-card-h">� Категории</h2>
          <div className="adm-cats-list">
            {Object.entries(data.CATEGORIES).map(([k, c]) => (
              <div key={k} className="adm-cat-row">
                {catEdit && catEdit.id === k ? (
                  <>
                    <input className="adm-input adm-cat-inp" value={catEdit.label}
                      onChange={e => setCatEdit({...catEdit, label: e.target.value})} placeholder="Название" />
                    <input className="adm-input adm-cat-inp adm-cat-short" value={catEdit.short}
                      onChange={e => setCatEdit({...catEdit, short: e.target.value})} placeholder="Кр." />
                    <button className="btn btn-ghost-sm btn-ok-sm" onClick={saveCategory}>✓</button>
                    <button className="btn btn-ghost-sm" onClick={() => setCatEdit(null)}>✕</button>
                  </>
                ) : (
                  <>
                    <span className="cat-tag">{c.short}</span>
                    <span className="adm-cat-label">{c.label}</span>
                    <span className="adm-cat-id">({k})</span>
                    <button className="btn btn-ghost-sm" onClick={() => setCatEdit({ id: k, label: c.label, short: c.short })}>✏️</button>
                    <button className="btn btn-ghost-sm btn-danger-sm" onClick={() => removeCategory(k)}>🗑</button>
                  </>
                )}
              </div>
            ))}
          </div>
          <div className="adm-cat-add">
            <input className="adm-input adm-cat-inp" placeholder="id (латиница)" value={catForm.id}
              onChange={e => setCatForm({...catForm, id: e.target.value.toLowerCase().replace(/[^a-z0-9_-]/g, '')})} />
            <input className="adm-input adm-cat-inp" placeholder="Название" value={catForm.label}
              onChange={e => setCatForm({...catForm, label: e.target.value})} />
            <input className="adm-input adm-cat-inp adm-cat-short" placeholder="Кр." value={catForm.short}
              onChange={e => setCatForm({...catForm, short: e.target.value})} />
            <button className="btn btn-primary btn-sm" onClick={addCategory}>+ Добавить</button>
          </div>
        </div>

        {/* Users — invites + admin roles */}
        <div className="admin-card admin-card-wide">
          <h2 className="admin-card-h">💰 Заявки на монеты {coinReqs.filter(r => r.status === 'pending').length > 0 && <span className="adm-badge-count">{coinReqs.filter(r => r.status === 'pending').length}</span>}</h2>
          <div className="adm-coinreqs">
            {coinReqs.filter(r => r.status === 'pending').length === 0 && (
              <div className="adm-coinreqs-empty">Нет активных заявок</div>
            )}
            {coinReqs.filter(r => r.status === 'pending').map(r => (
              <div key={r.id} className="adm-coinreq-row">
                <Avatar user={{name: r.user_name, avatarUrl: r.avatar_url, color: '#FFD600'}} size={30} />
                <div className="adm-coinreq-info">
                  <span className="adm-coinreq-name">{r.user_name}</span>
                  <span className="adm-coinreq-amount">+{r.amount} PC</span>
                  <span className="adm-coinreq-bal">текущий баланс: {formatPC(r.balance)} PC</span>
                </div>
                <div className="adm-coinreq-actions">
                  <button className="btn btn-primary btn-sm" onClick={() => decideCoinReq(r.id, 'approved')} disabled={coinLoading === r.id}>✓ Выдать</button>
                  <button className="btn btn-ghost-sm btn-danger-sm" onClick={() => decideCoinReq(r.id, 'rejected')} disabled={coinLoading === r.id}>✕</button>
                </div>
              </div>
            ))}
            {coinReqs.filter(r => r.status !== 'pending').length > 0 && (
              <details className="adm-coinreqs-history">
                <summary>История ({coinReqs.filter(r => r.status !== 'pending').length})</summary>
                {coinReqs.filter(r => r.status !== 'pending').slice(0, 20).map(r => (
                  <div key={r.id} className="adm-coinreq-row adm-coinreq-done">
                    <span className="adm-coinreq-name">{r.user_name}</span>
                    <span className="adm-coinreq-amount">+{r.amount} PC</span>
                    <span className={cx('adm-coinreq-status', r.status === 'approved' ? 'approved' : 'rejected')}>
                      {r.status === 'approved' ? '✓ выдано' : '✕ отклонено'}
                    </span>
                  </div>
                ))}
              </details>
            )}
          </div>
        </div>

        {/* Users — invites + admin roles */}
        <div className="admin-card admin-card-wide">
          <h2 className="admin-card-h">👤 Пользователи</h2>
          <div style={{marginBottom: 10}}>
            <input className="adm-input" placeholder="Поиск по имени или @handle…"
              value={userSearch} onChange={e => setUserSearch(e.target.value)} style={{maxWidth: 280}} />
          </div>
          <div className="adm-users-list">
            {filteredUsers.map(u => (
              <div key={u.id} className="adm-user-row">
                <Avatar user={u} size={30} />
                <div className="adm-user-info">
                  <span className="adm-user-name">
                    {u.name}
                    {u.role === 'admin' && <span className="adm-role-badge">ADMIN</span>}
                  </span>
                  <span className="adm-user-handle">{u.handle ? '@' + u.handle : ''}</span>
                </div>
                <div style={{display:'flex', gap: 6}}>
                  <button
                    className={cx('btn btn-ghost-sm', inviteCopied === u.id && 'btn-ok-sm')}
                    onClick={() => createInvite(u.id)}
                    title="Создать ссылку для входа без Telegram"
                  >
                    {inviteCopied === u.id ? '✓ Скопировано' : '🔗 Ссылка'}
                  </button>
                  {u.id !== user.id && (
                    <button
                      className={cx('btn btn-ghost-sm', u.role === 'admin' && 'btn-danger-sm')}
                      onClick={() => toggleRole(u)}
                      disabled={roleLoading === u.id}
                      title={u.role === 'admin' ? 'Снять роль администратора' : 'Выдать права администратора'}
                    >
                      {roleLoading === u.id ? '…' : u.role === 'admin' ? '✕ Снять админа' : '⭐ Сделать админом'}
                    </button>
                  )}
                </div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { BoardScreen, RatingScreen, ProfileScreen, HistoryScreen, HistoryList, AdminScreen });
