/* global React, ReactDOM */
const { useState, useEffect, useRef, useMemo, createContext, useContext, useCallback } = React;

// ───────────────────────────────────────────────────────────────
// Dropdown menu
// ───────────────────────────────────────────────────────────────
function Dropdown({ trigger, items, align = 'right', up = false }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useEffect(() => {
    if (!open) return;
    function onClick(e) { if (ref.current && !ref.current.contains(e.target)) setOpen(false); }
    function onKey(e) { if (e.key === 'Escape') setOpen(false); }
    document.addEventListener('mousedown', onClick);
    document.addEventListener('keydown', onKey);
    return () => { document.removeEventListener('mousedown', onClick); document.removeEventListener('keydown', onKey); };
  }, [open]);
  return (
    <span className="dd-wrap" ref={ref}>
      <span onClick={(e) => { e.stopPropagation(); setOpen(!open); }}>{trigger}</span>
      {open && (
        <div className={`dd-menu ${align === 'left' ? 'dd-left' : ''} ${up ? 'dd-up' : ''}`}>
          {items.map((it, i) => {
            if (it.sep) return <div key={i} className="dd-sep" />;
            if (it.label) return <div key={i} className="dd-label">{it.label}</div>;
            return (
              <button key={i} className={`dd-item ${it.danger ? 'is-danger' : ''}`} onClick={() => { it.onClick?.(); setOpen(false); }}>
                {it.icon ? <span className="dd-item-ico">{it.icon}</span> : null}
                <span>{it.text}</span>
                {it.shortcut ? <span className="dd-item-shortcut">{it.shortcut}</span> : null}
              </button>
            );
          })}
        </div>
      )}
    </span>
  );
}

// ───────────────────────────────────────────────────────────────
// Tooltip
// ───────────────────────────────────────────────────────────────
function Tip({ children, text, pos = 'top', kbd }) {
  return (
    <span className="tip-wrap">
      {children}
      <span className={`tip tip-${pos}`}>{text}{kbd ? <span className="tip-kbd">{kbd}</span> : null}</span>
    </span>
  );
}

// ───────────────────────────────────────────────────────────────
// Notification bell + inbox
// ───────────────────────────────────────────────────────────────
function NotificationBell() {
  const [open, setOpen] = useState(false);
  const [items, setItems] = useState([
    { id: 1, unread: true,  title: 'sign-off requested · w18 digest', sub: 'maya marked items #2 and #4 as ready', time: '12m ago' },
    { id: 2, unread: true,  title: 'deliberation held · repo/auth',   sub: 'race in renewSession() — 2/3 consensus failed', time: '1h ago' },
    { id: 3, unread: true,  title: 'opus rate-limited',                 sub: 'falling back to sonnet-4.5 for 3 tasks', time: '2h ago' },
    { id: 4, unread: false, title: 'pattern promoted · rotateRefresh', sub: 'sonnet-4.5 won 89% of n=412 attempts', time: 'yesterday' },
    { id: 5, unread: false, title: 'w17 digest shipped',                sub: '2,447 subs · est. read time 4 min', time: 'fri 09:00' },
  ]);
  const ref = useRef(null);
  const unread = items.filter((i) => i.unread).length;
  useEffect(() => {
    if (!open) return;
    function onClick(e) { if (ref.current && !ref.current.contains(e.target)) setOpen(false); }
    document.addEventListener('mousedown', onClick);
    return () => document.removeEventListener('mousedown', onClick);
  }, [open]);
  function markAll() { setItems((arr) => arr.map((i) => ({ ...i, unread: false }))); }
  function toggle(id) { setItems((arr) => arr.map((i) => i.id === id ? { ...i, unread: false } : i)); }
  return (
    <span className="bell-wrap" ref={ref}>
      <Tip text="notifications" pos="bottom" kbd="N">
        <button className="bell-btn" onClick={() => setOpen(!open)}>
          <svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
            <path d="M3 6a5 5 0 0 1 10 0v3l1.5 2H1.5L3 9V6z" /><path d="M6 13a2 2 0 0 0 4 0" />
          </svg>
          {unread > 0 ? <span className="bell-badge">{unread}</span> : null}
        </button>
      </Tip>
      {open && (
        <div className="inbox">
          <div className="inbox-head">
            <span className="inbox-title">inbox</span>
            {unread > 0 ? <span className="inbox-count">{unread} unread</span> : null}
            <span className="inbox-mark" onClick={markAll} style={{ marginLeft: unread > 0 ? 8 : 'auto' }}>mark all read</span>
          </div>
          <div className="inbox-body">
            {items.length === 0 ? <div className="inbox-empty">// no notifications</div> :
              items.map((i) => (
                <div key={i.id} className={`inbox-item ${i.unread ? 'is-unread' : ''}`} onClick={() => toggle(i.id)}>
                  <span className="inbox-item-dot" />
                  <div className="inbox-item-body">
                    <div className="inbox-item-title">{i.title}</div>
                    <div className="inbox-item-sub">{i.sub}</div>
                    <div className="inbox-item-time">{i.time}</div>
                  </div>
                </div>
              ))
            }
          </div>
          <div className="inbox-foot">view all activity</div>
        </div>
      )}
    </span>
  );
}

// ───────────────────────────────────────────────────────────────
// Keyboard shortcut help
// ───────────────────────────────────────────────────────────────
function ShortcutHelp({ open, onClose }) {
  if (!open) return null;
  const groups = [
    { label: 'navigate', items: [
      { l: 'open command palette', k: ['⌘', 'K'] },
      { l: 'open notifications',   k: ['N'] },
      { l: 'show shortcuts',       k: ['?'] },
      { l: 'go back',              k: ['⌘', '←'] },
      { l: 'go to dashboard',      k: ['G', 'D'] },
      { l: 'go to repos',          k: ['G', 'R'] },
    ]},
    { label: 'actions', items: [
      { l: 'dispatch task',      k: ['⌘', '⏎'] },
      { l: 'save',               k: ['⌘', 'S'] },
      { l: 'discard',            k: ['esc'] },
      { l: 'new repo',           k: ['C', 'R'] },
      { l: 'new bulletin item',  k: ['C', 'B'] },
      { l: 'run doctor',         k: ['⌘', 'D'] },
    ]},
  ];
  return (
    <div className="modal-back" onClick={onClose}>
      <div className="modal modal-lg" onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <div style={{ flex: 1 }}>
            <h3 className="modal-title">keyboard shortcuts</h3>
            <div className="modal-sub">// press ? anywhere to reopen</div>
          </div>
          <span className="modal-close" onClick={onClose}>{I.x}</span>
        </div>
        <div className="modal-body">
          <div className="kbd-grid">
            {groups.map((g) => (
              <div key={g.label}>
                <div className="kbd-col-label">// {g.label}</div>
                {g.items.map((it, i) => (
                  <div key={i} className="kbd-row">
                    <span className="kbd-row-label">{it.l}</span>
                    <span className="kbd-row-keys">{it.k.map((k, j) => <span key={j} className="kbd">{k}</span>)}</span>
                  </div>
                ))}
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

// ───────────────────────────────────────────────────────────────
// Pagination
// ───────────────────────────────────────────────────────────────
function Pagination({ page, total, onChange, pageSize = 10, onPageSize }) {
  const pages = Math.max(1, Math.ceil(total / pageSize));
  function nums() {
    if (pages <= 7) return Array.from({ length: pages }, (_, i) => i + 1);
    if (page <= 4) return [1, 2, 3, 4, 5, '...', pages];
    if (page >= pages - 3) return [1, '...', pages - 4, pages - 3, pages - 2, pages - 1, pages];
    return [1, '...', page - 1, page, page + 1, '...', pages];
  }
  return (
    <div className="pagi">
      <span className={`pagi-btn ${page === 1 ? 'is-disabled' : ''}`} onClick={() => page > 1 && onChange(1)}>«</span>
      <span className={`pagi-btn ${page === 1 ? 'is-disabled' : ''}`} onClick={() => page > 1 && onChange(page - 1)}>‹</span>
      {nums().map((n, i) => n === '...' ? <span key={i} className="pagi-ellipsis">…</span> : <span key={i} className={`pagi-btn ${n === page ? 'is-active' : ''}`} onClick={() => onChange(n)}>{n}</span>)}
      <span className={`pagi-btn ${page === pages ? 'is-disabled' : ''}`} onClick={() => page < pages && onChange(page + 1)}>›</span>
      <span className={`pagi-btn ${page === pages ? 'is-disabled' : ''}`} onClick={() => page < pages && onChange(pages)}>»</span>
      {onPageSize ? (
        <span className="pagi-size">
          <select value={pageSize} onChange={(e) => onPageSize(+e.target.value)}>
            <option value={10}>10</option><option value={25}>25</option><option value={50}>50</option><option value={100}>100</option>
          </select>
          <span>/ page</span>
        </span>
      ) : null}
    </div>
  );
}

// ───────────────────────────────────────────────────────────────
// Empty state
// ───────────────────────────────────────────────────────────────
function EmptyState({ icon, title, sub, actions, meta }) {
  return (
    <div className="empty">
      <div className="empty-illus">{icon}</div>
      <div className="empty-title">{title}</div>
      <div className="empty-sub">{sub}</div>
      {actions ? <div className="empty-actions">{actions}</div> : null}
      {meta ? <div className="empty-meta">{meta}</div> : null}
    </div>
  );
}

// ───────────────────────────────────────────────────────────────
// Tag input
// ───────────────────────────────────────────────────────────────
function TagInput({ tags, onChange, placeholder = 'type and press enter…' }) {
  const [draft, setDraft] = useState('');
  function add() {
    const v = draft.trim();
    if (v && !tags.includes(v)) onChange([...tags, v]);
    setDraft('');
  }
  function remove(t) { onChange(tags.filter((x) => x !== t)); }
  return (
    <div className="taginp">
      {tags.map((t) => (
        <span key={t} className="taginp-chip">
          {t}<span className="taginp-chip-x" onClick={() => remove(t)}>×</span>
        </span>
      ))}
      <input
        className="taginp-input"
        value={draft}
        placeholder={tags.length === 0 ? placeholder : ''}
        onChange={(e) => setDraft(e.target.value)}
        onKeyDown={(e) => {
          if (e.key === 'Enter' || e.key === ',') { e.preventDefault(); add(); }
          else if (e.key === 'Backspace' && !draft && tags.length) { onChange(tags.slice(0, -1)); }
        }}
        onBlur={add}
      />
    </div>
  );
}

// ───────────────────────────────────────────────────────────────
// Date range picker (lightweight)
// ───────────────────────────────────────────────────────────────
function DateRange({ value, onChange }) {
  const [open, setOpen] = useState(false);
  const [month, setMonth] = useState(() => new Date(2026, 3, 1));
  const ref = useRef(null);
  useEffect(() => {
    if (!open) return;
    function onClick(e) { if (ref.current && !ref.current.contains(e.target)) setOpen(false); }
    document.addEventListener('mousedown', onClick);
    return () => document.removeEventListener('mousedown', onClick);
  }, [open]);
  const presets = [
    { l: 'today',    days: 0 },
    { l: 'last 24h', days: 1 },
    { l: 'last 7d',  days: 7 },
    { l: 'last 30d', days: 30 },
    { l: 'this week',  days: -1 },
    { l: 'this month', days: -2 },
    { l: 'custom',     days: null },
  ];
  function applyPreset(p) {
    const end = new Date();
    const start = new Date(end);
    if (p.days > 0) start.setDate(end.getDate() - p.days);
    onChange({ label: p.l, start, end });
    setOpen(false);
  }
  function daysInMonth(d) {
    const first = new Date(d.getFullYear(), d.getMonth(), 1);
    const startDow = (first.getDay() + 6) % 7; // Mon=0
    const total = new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate();
    const cells = [];
    for (let i = 0; i < startDow; i++) cells.push({ out: true, n: new Date(d.getFullYear(), d.getMonth(), -startDow + i + 1).getDate() });
    for (let i = 1; i <= total; i++) cells.push({ n: i, day: new Date(d.getFullYear(), d.getMonth(), i) });
    while (cells.length % 7) cells.push({ out: true, n: cells.length - total - startDow + 1 });
    return cells;
  }
  return (
    <span className="dr-wrap" ref={ref}>
      <button className="dr-trigger" onClick={() => setOpen(!open)}>
        <span style={{ color: 'var(--fg-3)' }}>{I.doc}</span>
        <span>{value?.label || '7 days'}</span>
        <span style={{ color: 'var(--fg-4)' }}>{I.chevDown}</span>
      </button>
      {open && (
        <div className="dr-popover">
          <div className="dr-presets">
            {presets.map((p) => (
              <span key={p.l} className={`dr-preset ${value?.label === p.l ? 'is-active' : ''}`} onClick={() => applyPreset(p)}>{p.l}</span>
            ))}
          </div>
          <div className="dr-cal">
            <div className="dr-cal-head">
              <span className="dr-cal-nav" onClick={() => setMonth(new Date(month.getFullYear(), month.getMonth() - 1, 1))}>‹</span>
              <span className="dr-cal-month">{month.toLocaleString('en', { month: 'long', year: 'numeric' })}</span>
              <span className="dr-cal-nav" onClick={() => setMonth(new Date(month.getFullYear(), month.getMonth() + 1, 1))}>›</span>
            </div>
            <div className="dr-cal-grid">
              {['mo','tu','we','th','fr','sa','su'].map((d) => <span key={d} className="dr-cal-dow">{d}</span>)}
              {daysInMonth(month).map((c, i) => (
                <span key={i} className={`dr-cal-day ${c.out ? 'is-out' : ''} ${!c.out && c.n === 22 ? 'is-today' : ''} ${!c.out && c.n === 15 ? 'is-start' : ''} ${!c.out && c.n === 22 ? 'is-end' : ''} ${!c.out && c.n > 15 && c.n < 22 ? 'is-in-range' : ''}`}>{c.n}</span>
              ))}
            </div>
          </div>
        </div>
      )}
    </span>
  );
}

// ───────────────────────────────────────────────────────────────
// Stepper
// ───────────────────────────────────────────────────────────────
function Stepper({ steps, current }) {
  return (
    <div className="stepper">
      {steps.map((s, i) => {
        const done = i < current;
        const active = i === current;
        return (
          <React.Fragment key={i}>
            <div className={`stepper-step ${done ? 'is-done' : ''} ${active ? 'is-active' : ''}`}>
              <span className="stepper-dot">{done ? '✓' : i + 1}</span>
              <div className="stepper-info">
                <div className="stepper-info-label">step {String(i + 1).padStart(2, '0')}</div>
                <div className="stepper-info-title">{s}</div>
              </div>
            </div>
            {i < steps.length - 1 ? <div className={`stepper-line ${done ? 'is-done' : ''}`} /> : null}
          </React.Fragment>
        );
      })}
    </div>
  );
}

// ───────────────────────────────────────────────────────────────
// Diff viewer (split view)
// ───────────────────────────────────────────────────────────────
function DiffViewer({ path, lhs, rhs }) {
  // lhs/rhs are arrays of { kind: 'eq'|'add'|'del'|'empty', text, num }
  const adds = rhs.filter((l) => l.kind === 'add').length;
  const dels = lhs.filter((l) => l.kind === 'del').length;
  function renderCol(lines, side) {
    return (
      <div className="diff-split-col">
        <div className="diff-col-head">// {side}</div>
        {lines.map((l, i) => (
          <div key={i} className={`diff-line ${l.kind === 'add' ? 'is-add' : l.kind === 'del' ? 'is-del' : l.kind === 'empty' ? 'is-empty' : ''}`}>
            <span className="diff-line-num">{l.num || ''}</span>
            <span className="diff-line-text">
              <span className="diff-line-marker">{l.kind === 'add' ? '+' : l.kind === 'del' ? '−' : ' '}</span>
              {l.text}
            </span>
          </div>
        ))}
      </div>
    );
  }
  return (
    <div className="diff">
      <div className="diff-head">
        <span className="diff-path">{path}</span>
        <span className="diff-stats">
          <span className="diff-add">+{adds}</span>{' '}<span className="diff-del">−{dels}</span>
        </span>
      </div>
      <div className="diff-body">
        {renderCol(lhs, 'proposed')}
        {renderCol(rhs, 'after 0dai review')}
      </div>
    </div>
  );
}

// ───────────────────────────────────────────────────────────────
// Skeleton row (for loading demos)
// ───────────────────────────────────────────────────────────────
function SkeletonRow({ avatar = true, lines = 2 }) {
  return (
    <div className="skel-row">
      {avatar ? <span className="skel skel-circle" /> : null}
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 6 }}>
        {Array.from({ length: lines }).map((_, i) => (
          <span key={i} className="skel skel-line" style={{ width: `${60 + Math.random() * 35}%` }} />
        ))}
      </div>
    </div>
  );
}

// ───────────────────────────────────────────────────────────────
// Page: Deliberation queue (held patches)
// ───────────────────────────────────────────────────────────────
const HELD = [
  {
    id: 'h-001',
    title: 'race in renewSession() during refresh storm',
    repo: 'repo/auth',
    file: 'src/session/renew.ts',
    when: '14m ago',
    votes: { opus: 'no', sonnet: 'yes', gemini: 'no' },
    reason: 'opus and gemini flagged a re-entry path that bypasses the mutex when refresh is triggered concurrently from two browser tabs. sonnet did not reproduce the race in its harness.',
    diff: {
      lhs: [
        { kind: 'eq',  num: 12, text: 'export async function renewSession(token: string) {' },
        { kind: 'eq',  num: 13, text: '  if (cache.has(token)) return cache.get(token);' },
        { kind: 'del', num: 14, text: '  const fresh = await api.refresh(token);' },
        { kind: 'del', num: 15, text: '  cache.set(token, fresh);' },
        { kind: 'eq',  num: 16, text: '  return fresh;' },
        { kind: 'eq',  num: 17, text: '}' },
      ],
      rhs: [
        { kind: 'eq',  num: 12, text: 'export async function renewSession(token: string) {' },
        { kind: 'eq',  num: 13, text: '  if (cache.has(token)) return cache.get(token);' },
        { kind: 'add', num: 14, text: '  return mutex.run(token, async () => {' },
        { kind: 'add', num: 15, text: '    if (cache.has(token)) return cache.get(token);' },
        { kind: 'add', num: 16, text: '    const fresh = await api.refresh(token);' },
        { kind: 'add', num: 17, text: '    cache.set(token, fresh); return fresh;' },
        { kind: 'add', num: 18, text: '  });' },
        { kind: 'eq',  num: 19, text: '}' },
      ],
    },
  },
  {
    id: 'h-002',
    title: 'conflicting locks on stripe webhook handler',
    repo: 'repo/payments',
    file: 'src/webhooks/stripe.ts',
    when: '1h ago',
    votes: { opus: 'yes', sonnet: 'no', gemini: 'no' },
    reason: 'sonnet and gemini converged on a simpler optimistic-update pattern that avoids the redis lock entirely. opus held to the pessimistic approach citing prior incident #1147.',
    diff: {
      lhs: [
        { kind: 'eq',  num: 8,  text: 'app.post("/webhook", async (req, res) => {' },
        { kind: 'del', num: 9,  text: '  const lock = await redis.lock(`evt:${req.id}`);' },
        { kind: 'del', num: 10, text: '  try { await handle(req.body); }' },
        { kind: 'del', num: 11, text: '  finally { await lock.release(); }' },
        { kind: 'eq',  num: 12, text: '  res.send("ok");' },
        { kind: 'eq',  num: 13, text: '});' },
      ],
      rhs: [
        { kind: 'eq',  num: 8,  text: 'app.post("/webhook", async (req, res) => {' },
        { kind: 'add', num: 9,  text: '  if (await processed.has(req.id)) return res.send("ok");' },
        { kind: 'add', num: 10, text: '  await handle(req.body);' },
        { kind: 'add', num: 11, text: '  await processed.add(req.id, { ttl: "7d" });' },
        { kind: 'eq',  num: 12, text: '  res.send("ok");' },
        { kind: 'eq',  num: 13, text: '});' },
      ],
    },
  },
];

function PageDeliberation() {
  const toast = useToast();
  const [activeId, setActiveId] = useState(HELD[0].id);
  const active = HELD.find((h) => h.id === activeId);
  function vote(action) {
    toast({ kind: action === 'accept' ? 'info' : 'warn', title: `${action}ed`, text: `${active.title.slice(0, 40)}…` });
  }
  return (
    <>
      <div className="page-head">
        <div className="page-head-left">
          <div className="page-kicker">// deliberation queue · {HELD.length} held · {HELD.length} need a human</div>
          <h1 className="page-title">held in <em>deliberation</em></h1>
          <p className="page-sub">when 2-of-3 consensus fails, the patch is held here. you decide what ships.</p>
        </div>
        <div className="page-actions">
          <DateRange />
          <button className="btn btn-secondary">filter</button>
        </div>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '320px 1fr', gap: 20 }}>
        <div className="card">
          <div className="card-head">
            <div className="card-head-title">// queue</div>
            <div className="card-head-sub">{HELD.length} items</div>
          </div>
          <div style={{ padding: 8 }}>
            {HELD.map((h) => (
              <div
                key={h.id}
                onClick={() => setActiveId(h.id)}
                style={{
                  padding: '12px',
                  borderRadius: 6,
                  cursor: 'pointer',
                  background: activeId === h.id ? 'var(--bg-hover)' : 'transparent',
                  borderLeft: `2px solid ${activeId === h.id ? 'var(--warn)' : 'transparent'}`,
                  marginBottom: 4,
                }}
              >
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 6 }}>
                  <span className="mono" style={{ fontSize: 10, color: 'var(--fg-4)' }}>{h.id}</span>
                  <span className="badge badge-warn"><span className="badge-dot" />held</span>
                </div>
                <div style={{ fontSize: 13, color: 'var(--fg)', lineHeight: 1.35, marginBottom: 4 }}>{h.title}</div>
                <div className="mono" style={{ fontSize: 11, color: 'var(--fg-3)' }}>{h.repo} · {h.when}</div>
              </div>
            ))}
          </div>
        </div>

        {active && (
          <div className="card delib-card">
            <div className="delib-head">
              <span className="delib-head-icon">{I.warn}</span>
              <div style={{ flex: 1 }}>
                <div className="delib-head-title">{active.title}</div>
                <div className="delib-head-sub">{active.repo} · {active.file} · held {active.when}</div>
              </div>
              <span className="badge badge-warn">consensus failed · 1-of-3</span>
            </div>
            <div className="delib-votes">
              <span className="mono" style={{ fontSize: 10, color: 'var(--fg-4)' }}>// model votes</span>
              {Object.entries(active.votes).map(([m, v]) => (
                <span key={m} className={`delib-vote ${v === 'yes' ? 'delib-vote-ok' : 'delib-vote-no'}`}>
                  <span className="delib-vote-mod">{m}</span>
                  <span className="delib-vote-mark">{v === 'yes' ? 'ship' : 'hold'}</span>
                </span>
              ))}
            </div>
            <div className="delib-reason">
              <strong>reason for hold · </strong>{active.reason}
            </div>
            <div style={{ padding: 18 }}>
              <DiffViewer path={active.file} lhs={active.diff.lhs} rhs={active.diff.rhs} />
            </div>
            <div className="modal-foot">
              <button className="btn btn-ghost" onClick={() => vote('discard')}>discard patch</button>
              <span style={{ flex: 1 }} />
              <button className="btn btn-secondary" onClick={() => vote('hold')}>hold for review</button>
              <button className="btn btn-primary" onClick={() => vote('accept')}><span>{I.check}</span>accept &amp; ship</button>
            </div>
          </div>
        )}
      </div>
    </>
  );
}

// ───────────────────────────────────────────────────────────────
// Page: API keys
// ───────────────────────────────────────────────────────────────
function PageKeys() {
  const toast = useToast();
  const [createOpen, setCreateOpen] = useState(false);
  const [revealId, setRevealId] = useState(null);
  const [keys, setKeys] = useState([
    { id: 'k-prod', name: 'production cli', sub: 'used by team-laptops · 4 hosts', mask: 'sk_live_••••••••••••8a2f', full: 'sk_live_4f9c2b7e1d6a8a2f', scopes: ['read:patterns','write:bulletins','read:routing'], last: '12m ago', created: '2026-01-04' },
    { id: 'k-ci',   name: 'ci · github actions', sub: 'used by 7 repos · scoped: read only', mask: 'sk_live_••••••••••••c41a', full: 'sk_live_8d3e1aa9f2cbc41a', scopes: ['read:patterns'], last: '2h ago', created: '2026-02-15' },
    { id: 'k-old',  name: 'legacy mobile sync',  sub: 'deprecated · scheduled rotation may 1', mask: 'sk_live_••••••••••••71b9', full: 'sk_live_001f9d4eee7771b9', scopes: ['read:patterns','read:bulletins'], last: '12d ago', created: '2025-08-22' },
  ]);
  function copy(k) {
    navigator.clipboard?.writeText(k.full);
    toast({ kind: 'info', title: 'copied to clipboard', text: 'paste this somewhere safe — you won\'t see it again' });
  }
  return (
    <>
      <div className="page-head">
        <div className="page-head-left">
          <div className="page-kicker">// api keys · {keys.length} active · rotation policy: 90d</div>
          <h1 className="page-title">api <em>keys</em></h1>
          <p className="page-sub">used by the cli, ci, and any service that calls the 0dai api. rotate often. revoke instantly.</p>
        </div>
        <div className="page-actions">
          <button className="btn btn-secondary"><span>{I.doc}</span>view docs</button>
          <button className="btn btn-primary" onClick={() => setCreateOpen(true)}><span>{I.plus}</span>create key</button>
        </div>
      </div>

      <div className="alert alert-warn" style={{ marginBottom: 20 }}>
        <span className="alert-ico">{I.warn}</span>
        <div className="alert-body">
          <div className="alert-title">never commit keys to git</div>
          <div className="alert-text">store in <span className="mono">.0dai/secrets</span> (gitignored) or your secret manager. revoke immediately if you suspect a leak.</div>
        </div>
      </div>

      <div className="card">
        <div className="card-head">
          <div className="card-head-title">// active keys</div>
          <div className="card-head-actions">
            <span className="badge badge-live"><span className="badge-dot" />ed25519 · v2</span>
          </div>
        </div>
        <div>
          <div className="key-row" style={{ borderBottom: '1px solid var(--line)', background: 'var(--bg-2)', padding: '8px 18px' }}>
            <span className="mono" style={{ fontSize: 10, color: 'var(--fg-4)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>name</span>
            <span className="mono" style={{ fontSize: 10, color: 'var(--fg-4)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>key</span>
            <span className="mono" style={{ fontSize: 10, color: 'var(--fg-4)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>scopes</span>
            <span className="mono" style={{ fontSize: 10, color: 'var(--fg-4)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>last used</span>
            <span></span>
          </div>
          {keys.map((k) => (
            <div key={k.id} className="key-row">
              <div>
                <div className="key-name">{k.name}</div>
                <div className="key-name-sub">{k.sub}</div>
              </div>
              <div className="key-mask">
                <span className="key-mask-val">{revealId === k.id ? k.full : k.mask}</span>
                <Tip text={revealId === k.id ? 'hide' : 'reveal'} pos="top">
                  <button className="btn btn-icon btn-ghost btn-sm" onClick={() => setRevealId(revealId === k.id ? null : k.id)}>{I.eye}</button>
                </Tip>
                <Tip text="copy" pos="top">
                  <button className="btn btn-icon btn-ghost btn-sm" onClick={() => copy(k)}>{I.copy}</button>
                </Tip>
              </div>
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: 4 }}>
                {k.scopes.map((s) => <span key={s} className="badge badge-square mono">{s}</span>)}
              </div>
              <div className="key-meta">{k.last}<br /><span style={{ fontSize: 10, color: 'var(--fg-4)' }}>created {k.created}</span></div>
              <div style={{ textAlign: 'right' }}>
                <Dropdown
                  align="right"
                  trigger={<button className="btn btn-icon btn-ghost btn-sm">{I.more}</button>}
                  items={[
                    { icon: I.edit, text: 'rename' },
                    { icon: I.refresh, text: 'rotate now' },
                    { icon: I.doc, text: 'view audit log' },
                    { sep: true },
                    { icon: I.trash, text: 'revoke', danger: true, onClick: () => toast({ kind: 'warn', title: 'pretend revoked', text: `${k.name} would be invalid in 30s` }) },
                  ]}
                />
              </div>
            </div>
          ))}
        </div>
      </div>

      {createOpen && (
        <div className="modal-back" onClick={() => setCreateOpen(false)}>
          <div className="modal modal-lg" onClick={(e) => e.stopPropagation()}>
            <div className="modal-head">
              <div style={{ flex: 1 }}>
                <h3 className="modal-title">create new key</h3>
                <div className="modal-sub">// you'll only see the secret once. copy it before leaving this dialog.</div>
              </div>
              <span className="modal-close" onClick={() => setCreateOpen(false)}>{I.x}</span>
            </div>
            <div className="modal-body">
              <div className="field">
                <span className="field-lbl">// name <span className="field-lbl-req">*</span></span>
                <input className="input" placeholder="e.g. ci · staging" />
                <div className="field-help">a human label. you'll see it in audit logs.</div>
              </div>
              <div className="field">
                <span className="field-lbl">// scopes</span>
                <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                  {['read:patterns','write:patterns','read:bulletins','write:bulletins','read:routing','write:routing','admin'].map((s) => (
                    <label key={s} className="check"><input type="checkbox" defaultChecked={s.startsWith('read:')} /><span className="check-box" /><span className="mono" style={{ fontSize: 12 }}>{s}</span></label>
                  ))}
                </div>
              </div>
              <div className="field">
                <span className="field-lbl">// expires</span>
                <select className="select"><option>30 days</option><option>90 days</option><option>1 year</option><option>never (not recommended)</option></select>
              </div>
            </div>
            <div className="modal-foot">
              <button className="btn btn-ghost" onClick={() => setCreateOpen(false)}>cancel</button>
              <button className="btn btn-primary" onClick={() => { setCreateOpen(false); toast({ kind: 'info', title: 'key created', text: 'reveal the secret in the row above' }); }}>create key</button>
            </div>
          </div>
        </div>
      )}
    </>
  );
}

// ───────────────────────────────────────────────────────────────
// Page: Audit log
// ───────────────────────────────────────────────────────────────
function PageAudit() {
  const [search, setSearch] = useState('');
  const [actorFilter, setActorFilter] = useState('all');
  const [page, setPage] = useState(1);
  const [pageSize, setPageSize] = useState(25);
  const rows = [
    { t: 'apr 29 · 09:34', u: 'erik',  a: 'pattern.promote', target: 'rotateRefresh',        ip: '10.0.4.21' },
    { t: 'apr 29 · 09:22', u: '0dai',  a: 'consensus.pass',  target: 'jest-30-migration',     ip: '—' },
    { t: 'apr 29 · 09:14', u: '0dai',  a: 'routing.fallback', target: 'opus → sonnet · 3',     ip: '—' },
    { t: 'apr 29 · 08:51', u: '0dai',  a: 'routing.update',  target: 'tag:tests-flaky',       ip: '—' },
    { t: 'apr 29 · 08:40', u: '0dai',  a: 'patch.hold',      target: 'repo/auth · h-001',     ip: '—' },
    { t: 'apr 29 · 08:22', u: 'erik',  a: 'bulletin.archive', target: 'w15',                  ip: '10.0.4.21' },
    { t: 'apr 28 · 18:22', u: 'erik',  a: 'bulletin.ship',   target: 'w17',                   ip: '10.0.4.21' },
    { t: 'apr 28 · 14:10', u: '0dai',  a: 'repo.sync',       target: 'repo/payments · +3',    ip: '—' },
    { t: 'apr 28 · 11:04', u: 'erik',  a: 'team.invite',     target: 'maya@dev.team',         ip: '10.0.4.21' },
    { t: 'apr 27 · 22:00', u: 'tom',   a: 'bulletin.sign',   target: 'w17 · ed25519',         ip: '47.182.3.118' },
    { t: 'apr 27 · 21:14', u: 'maya',  a: 'bulletin.sign',   target: 'w17 · item #3',         ip: '74.20.55.4' },
    { t: 'apr 27 · 09:00', u: 'erik',  a: 'key.rotate',      target: 'k-prod',                ip: '10.0.4.21' },
    { t: 'apr 26 · 16:42', u: 'erik',  a: 'team.role',       target: 'tom · editor',          ip: '10.0.4.21' },
    { t: 'apr 26 · 12:31', u: '0dai',  a: 'pattern.flag',    target: 'jest-30-config · anti', ip: '—' },
    { t: 'apr 25 · 17:11', u: 'erik',  a: 'auth.signin',     target: 'sso · google',          ip: '10.0.4.21' },
    { t: 'apr 25 · 09:00', u: 'erik',  a: 'bulletin.draft',  target: 'w17',                   ip: '10.0.4.21' },
  ];
  const filtered = rows.filter((r) =>
    (!search || r.target.toLowerCase().includes(search.toLowerCase()) || r.a.toLowerCase().includes(search.toLowerCase())) &&
    (actorFilter === 'all' || (actorFilter === 'human' ? r.u !== '0dai' : r.u === '0dai'))
  );
  const paged = filtered.slice((page - 1) * pageSize, page * pageSize);
  return (
    <>
      <div className="page-head">
        <div className="page-head-left">
          <div className="page-kicker">// audit log · every state change · immutable</div>
          <h1 className="page-title">audit log</h1>
          <p className="page-sub">who did what, when, from where. retention: 365 days. exports as csv or json.</p>
        </div>
        <div className="page-actions">
          <DateRange />
          <button className="btn btn-secondary"><span>{I.download}</span>export csv</button>
        </div>
      </div>

      <div className="card">
        <div className="tbl-toolbar">
          <div className="tbl-toolbar-search">
            <span className="tbl-toolbar-search-ico">{I.search}</span>
            <input placeholder="search by action or target…" value={search} onChange={(e) => setSearch(e.target.value)} />
          </div>
          <div className="seg">
            {['all','human','agent'].map((s) => (
              <span key={s} className={`seg-opt ${actorFilter === s ? 'is-active' : ''}`} onClick={() => setActorFilter(s)}>{s}</span>
            ))}
          </div>
          <div className="tbl-toolbar-count">{filtered.length} events</div>
        </div>
        <div className="audit-row" style={{ background: 'var(--bg-2)', borderBottom: '1px solid var(--line)' }}>
          <span className="mono" style={{ fontSize: 10, color: 'var(--fg-4)', textTransform: 'uppercase' }}>time</span>
          <span className="mono" style={{ fontSize: 10, color: 'var(--fg-4)', textTransform: 'uppercase' }}>actor</span>
          <span className="mono" style={{ fontSize: 10, color: 'var(--fg-4)', textTransform: 'uppercase' }}>action</span>
          <span className="mono" style={{ fontSize: 10, color: 'var(--fg-4)', textTransform: 'uppercase' }}>target</span>
          <span className="mono" style={{ fontSize: 10, color: 'var(--fg-4)', textTransform: 'uppercase', textAlign: 'right' }}>ip</span>
        </div>
        {paged.length === 0 ? (
          <EmptyState icon={I.search} title="no matching events" sub={`no audit events match "${search}". try widening the date range or clearing filters.`} meta="// audit retention: 365 days" />
        ) : paged.map((r, i) => (
          <div key={i} className="audit-row">
            <span className="audit-time">{r.t}</span>
            <span className="audit-actor">
              <span className="audit-actor-av" style={{ background: r.u === '0dai' ? 'var(--accent-bg)' : 'var(--bg-3)', color: r.u === '0dai' ? 'var(--accent)' : 'var(--fg-2)' }}>
                {r.u === '0dai' ? '0' : r.u.slice(0, 2).toUpperCase()}
              </span>
              <span style={{ fontSize: 12 }}>{r.u}</span>
            </span>
            <span><span className="audit-action">{r.a}</span></span>
            <span className="audit-target">{r.target}</span>
            <span className="audit-ip">{r.ip}</span>
          </div>
        ))}
        <div className="tbl-foot">
          <span>showing {paged.length} of {filtered.length}</span>
          <span style={{ marginLeft: 'auto' }}>
            <Pagination page={page} total={filtered.length} pageSize={pageSize} onChange={setPage} onPageSize={(n) => { setPageSize(n); setPage(1); }} />
          </span>
        </div>
      </div>
    </>
  );
}

// ───────────────────────────────────────────────────────────────
// Page: Onboarding wizard (modal-driven)
// ───────────────────────────────────────────────────────────────
function PageOnboarding() {
  const toast = useToast();
  const [step, setStep] = useState(0);
  const steps = ['install cli', 'connect repo', 'first sync', 'invite team'];
  const [cli, setCli] = useState('claude code');
  const [repoUrl, setRepoUrl] = useState('');
  const [tags, setTags] = useState(['typescript', 'auth']);
  const [emails, setEmails] = useState([]);
  function next() { setStep((s) => Math.min(s + 1, steps.length - 1)); }
  function prev() { setStep((s) => Math.max(s - 1, 0)); }
  function finish() { toast({ kind: 'info', title: 'workspace ready', text: 'you can dispatch your first task with ⌘⏎' }); }
  return (
    <>
      <div className="page-head">
        <div className="page-head-left">
          <div className="page-kicker">// onboarding · {step + 1} of {steps.length}</div>
          <h1 className="page-title">welcome to <em>0dai</em>.</h1>
          <p className="page-sub">4 steps. takes about 3 minutes. you can skip any step and come back later.</p>
        </div>
      </div>

      <div style={{ marginBottom: 32, padding: '20px 24px', background: 'var(--bg-1)', border: '1px solid var(--line)', borderRadius: 'var(--r-3)' }}>
        <Stepper steps={steps} current={step} />
      </div>

      <div className="card" style={{ maxWidth: 720 }}>
        <div className="card-body">
          {step === 0 && (
            <>
              <h2 style={{ fontFamily: 'var(--f-display)', fontSize: 24, fontWeight: 400, margin: '0 0 8px' }}>install the cli</h2>
              <p style={{ color: 'var(--fg-3)', marginTop: 0 }}>pick your preferred agent runner. you can switch later.</p>
              <div style={{ display: 'flex', gap: 12, marginBottom: 20, flexWrap: 'wrap' }}>
                {['claude code','codex','gemini cli','cursor cli','aider'].map((c) => (
                  <label key={c} className="radio" style={{
                    padding: 10, border: `1px solid ${cli === c ? 'var(--accent)' : 'var(--line)'}`,
                    borderRadius: 6, background: cli === c ? 'var(--accent-bg)' : 'var(--bg)',
                    minWidth: 130, justifyContent: 'flex-start'
                  }}>
                    <input type="radio" name="cli" checked={cli === c} onChange={() => setCli(c)} /><span className="radio-box" />
                    <span style={{ fontSize: 13 }}>{c}</span>
                  </label>
                ))}
              </div>
              <div className="code"><div>$ curl -fsSL 0dai.dev/install.sh | sh</div><div>$ 0dai init --runner "{cli}"</div></div>
              <div className="field-help" style={{ marginTop: 12 }}>verify with <span className="mono" style={{ color: 'var(--fg-2)' }}>0dai doctor</span></div>
            </>
          )}
          {step === 1 && (
            <>
              <h2 style={{ fontFamily: 'var(--f-display)', fontSize: 24, fontWeight: 400, margin: '0 0 8px' }}>connect a repo</h2>
              <p style={{ color: 'var(--fg-3)', marginTop: 0 }}>0dai watches your repos for patterns. pick one to start.</p>
              <div className="field">
                <span className="field-lbl">// git url or local path</span>
                <input className="input mono" value={repoUrl} placeholder="git@github.com:acme/repo.git" onChange={(e) => setRepoUrl(e.target.value)} />
              </div>
              <div className="field">
                <span className="field-lbl">// tags · helps with routing</span>
                <TagInput tags={tags} onChange={setTags} placeholder="add tag…" />
              </div>
            </>
          )}
          {step === 2 && (
            <>
              <h2 style={{ fontFamily: 'var(--f-display)', fontSize: 24, fontWeight: 400, margin: '0 0 8px' }}>first sync</h2>
              <p style={{ color: 'var(--fg-3)', marginTop: 0 }}>this is what 0dai will do right now:</p>
              <div className="feed">
                <div className="feed-item"><span className="feed-time">~10s</span><span className="feed-marker is-ok">✓</span><span className="feed-text">scan repo · build symbol index</span></div>
                <div className="feed-item"><span className="feed-time">~30s</span><span className="feed-marker is-ok">✓</span><span className="feed-text">extract initial pattern hypotheses</span></div>
                <div className="feed-item"><span className="feed-time">~5s</span><span className="feed-marker">·</span><span className="feed-text">cross-reference with the network</span></div>
                <div className="feed-item"><span className="feed-time">~3s</span><span className="feed-marker">·</span><span className="feed-text">create <span className="feed-mono">.0dai/</span> manifest</span></div>
              </div>
              <div className="alert alert-info" style={{ marginTop: 20 }}>
                <span className="alert-ico">{I.info}</span>
                <div className="alert-body">
                  <div className="alert-title">no code leaves your machine</div>
                  <div className="alert-text">only structural patterns (anonymized) — full opt-out at any time in settings.</div>
                </div>
              </div>
            </>
          )}
          {step === 3 && (
            <>
              <h2 style={{ fontFamily: 'var(--f-display)', fontSize: 24, fontWeight: 400, margin: '0 0 8px' }}>invite team</h2>
              <p style={{ color: 'var(--fg-3)', marginTop: 0 }}>optional. you can do this later from settings → team.</p>
              <div className="field">
                <span className="field-lbl">// emails</span>
                <TagInput tags={emails} onChange={setEmails} placeholder="add email and press enter…" />
              </div>
              <div className="alert alert-ok">
                <span className="alert-ico">{I.check}</span>
                <div className="alert-body">
                  <div className="alert-title">you're done</div>
                  <div className="alert-text">workspace is ready. friday digests start next week.</div>
                </div>
              </div>
            </>
          )}
        </div>
        <div className="modal-foot">
          <button className="btn btn-ghost" onClick={prev} disabled={step === 0}>back</button>
          <span style={{ flex: 1 }} />
          <button className="btn btn-ghost">skip</button>
          {step < steps.length - 1 ? (
            <button className="btn btn-primary" onClick={next}>continue<span>{I.arrow}</span></button>
          ) : (
            <button className="btn btn-primary" onClick={finish}><span>{I.check}</span>enter workspace</button>
          )}
        </div>
      </div>
    </>
  );
}

// ───────────────────────────────────────────────────────────────
// Icons — 1.5px stroke, 16x16 viewBox
// ───────────────────────────────────────────────────────────────
function Ico({ d, size = 16, fill, ...rest }) {
  return (
    <svg width={size} height={size} viewBox="0 0 16 16" fill={fill || 'none'} stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" {...rest}>
      {d}
    </svg>
  );
}
const I = {
  home:    <Ico d={<><path d="M2 7l6-5 6 5v7a1 1 0 0 1-1 1h-3v-5H6v5H3a1 1 0 0 1-1-1V7z"/></>} />,
  repos:   <Ico d={<><rect x="2" y="3" width="12" height="10" rx="1"/><path d="M2 6h12M5 9h2M5 11h4"/></>} />,
  bullets: <Ico d={<><path d="M3 3h8l3 3v7a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z"/><path d="M11 3v3h3M5 8h6M5 11h4"/></>} />,
  patterns:<Ico d={<><circle cx="4" cy="4" r="1.5"/><circle cx="12" cy="4" r="1.5"/><circle cx="8" cy="12" r="1.5"/><circle cx="8" cy="8" r="1.5"/><path d="M4 4l4 4 4-4M8 8v4"/></>} />,
  routing: <Ico d={<><path d="M2 4h4l3 8h5M2 12h4"/><circle cx="14" cy="4" r="1.5"/></>} />,
  billing: <Ico d={<><rect x="2" y="3" width="12" height="9" rx="1"/><path d="M2 6h12M5 9h2"/></>} />,
  team:    <Ico d={<><circle cx="6" cy="5" r="2"/><path d="M2 13c0-2 2-3 4-3s4 1 4 3"/><circle cx="12" cy="6" r="1.5"/><path d="M11 13c0-1.5 1-2.5 3-2.5"/></>} />,
  settings:<Ico d={<><circle cx="8" cy="8" r="2"/><path d="M8 1v2M8 13v2M1 8h2M13 8h2M3 3l1.5 1.5M11.5 11.5L13 13M3 13l1.5-1.5M11.5 4.5L13 3"/></>} />,
  search:  <Ico d={<><circle cx="7" cy="7" r="4.5"/><path d="M10.5 10.5L14 14"/></>} />,
  plus:    <Ico d={<><path d="M8 3v10M3 8h10"/></>} />,
  check:   <Ico d={<><path d="M3 8l3 3 7-7"/></>} />,
  x:       <Ico d={<><path d="M3 3l10 10M13 3L3 13"/></>} />,
  chev:    <Ico d={<><path d="M6 4l4 4-4 4"/></>} />,
  chevDown:<Ico d={<><path d="M3 6l5 4 5-4"/></>} />,
  arrow:   <Ico d={<><path d="M3 8h10M9 4l4 4-4 4"/></>} />,
  more:    <Ico d={<><circle cx="3" cy="8" r="0.8" fill="currentColor"/><circle cx="8" cy="8" r="0.8" fill="currentColor"/><circle cx="13" cy="8" r="0.8" fill="currentColor"/></>} />,
  filter:  <Ico d={<><path d="M2 3h12l-4 5v5l-4-2V8L2 3z"/></>} />,
  sortAZ:  <Ico d={<><path d="M3 4v9M3 4L1 6M3 4l2 2M8 4h5M8 8h4M8 12h3"/></>} />,
  alert:   <Ico d={<><path d="M8 1L1 14h14L8 1zM8 6v4M8 12v0.5"/></>} />,
  info:    <Ico d={<><circle cx="8" cy="8" r="6"/><path d="M8 7v4M8 5v0.5"/></>} />,
  warn:    <Ico d={<><circle cx="8" cy="8" r="6"/><path d="M8 5v4M8 11v0.5"/></>} />,
  err:     <Ico d={<><circle cx="8" cy="8" r="6"/><path d="M5 5l6 6M11 5L5 11"/></>} />,
  zap:     <Ico d={<><path d="M9 1L3 9h4l-1 6 6-8h-4l1-6z"/></>} />,
  doc:     <Ico d={<><path d="M3 2h7l3 3v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1z"/><path d="M10 2v3h3M5 8h6M5 11h4"/></>} />,
  upload:  <Ico d={<><path d="M8 2v9M5 5l3-3 3 3M2 13h12"/></>} />,
  trash:   <Ico d={<><path d="M3 4h10M5 4V2h6v2M5 4l1 10h4l1-10"/></>} />,
  edit:    <Ico d={<><path d="M11 2l3 3-9 9H2v-3l9-9z"/></>} />,
  link:    <Ico d={<><path d="M7 9l2-2M5 7l-2 2a2.5 2.5 0 0 0 3.5 3.5l2-2M9 7l2-2a2.5 2.5 0 0 0-3.5-3.5l-2 2"/></>} />,
  send:    <Ico d={<><path d="M14 2L2 7l5 2 2 5 5-12zM7 9l5-5"/></>} />,
  archive: <Ico d={<><rect x="2" y="3" width="12" height="3" rx="0.5"/><path d="M3 6v7a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V6M6 9h4"/></>} />,
  download:<Ico d={<><path d="M8 2v9M5 8l3 3 3-3M2 13h12"/></>} />,
  external:<Ico d={<><path d="M6 3H3v10h10v-3M9 3h4v4M13 3L8 8"/></>} />,
  refresh: <Ico d={<><path d="M3 8a5 5 0 0 1 9-3l1 1M13 4v3h-3M13 8a5 5 0 0 1-9 3l-1-1M3 12V9h3"/></>} />,
  eye:     <Ico d={<><path d="M1 8s2.5-5 7-5 7 5 7 5-2.5 5-7 5-7-5-7-5z"/><circle cx="8" cy="8" r="2"/></>} />,
  help:    <Ico d={<><circle cx="8" cy="8" r="6"/><path d="M6 6a2 2 0 0 1 4 0c0 1-2 1.5-2 2.5M8 11v0.5"/></>} />,
};

// ───────────────────────────────────────────────────────────────
// Toast host (context)
// ───────────────────────────────────────────────────────────────
const ToastCtx = createContext(null);
function useToast() { return useContext(ToastCtx); }

function ToastProvider({ children }) {
  const [toasts, setToasts] = useState([]);
  const push = useCallback((t) => {
    const id = Math.random().toString(36).slice(2);
    setToasts((arr) => [...arr, { id, kind: 'info', ...t }]);
    setTimeout(() => setToasts((arr) => arr.filter((x) => x.id !== id)), 4200);
  }, []);
  const dismiss = (id) => setToasts((arr) => arr.filter((x) => x.id !== id));
  return (
    <ToastCtx.Provider value={push}>
      {children}
      <div className="toast-host">
        {toasts.map((t) => (
          <div key={t.id} className={`toast toast-${t.kind}`}>
            <div className="toast-body">
              <div className="toast-title">{t.title}</div>
              {t.text ? <div className="toast-text">{t.text}</div> : null}
            </div>
            <span className="toast-close" onClick={() => dismiss(t.id)}>×</span>
          </div>
        ))}
      </div>
    </ToastCtx.Provider>
  );
}

// ───────────────────────────────────────────────────────────────
// Layout shell — sidebar + topbar
// ───────────────────────────────────────────────────────────────
function BrandSvg() {
  return (
    <svg viewBox="0 0 24 24" className="side-brand-svg" fill="none" strokeWidth="1.6">
      <ellipse cx="10" cy="11" rx="6" ry="7.5" stroke="currentColor" opacity="0.32" />
      <ellipse cx="11" cy="12" rx="6" ry="7.5" stroke="currentColor" opacity="0.62" />
      <ellipse cx="12.5" cy="13" rx="6" ry="7.5" stroke="var(--accent)" />
    </svg>
  );
}

function Sidebar({ page, setPage, collapsed }) {
  const groups = [
    { label: 'workspace', items: [
      { id: 'dashboard', icon: I.home, label: 'dashboard' },
      { id: 'repos', icon: I.repos, label: 'repos', meta: '7' },
      { id: 'patterns', icon: I.patterns, label: 'patterns', meta: '142' },
      { id: 'routing', icon: I.routing, label: 'routing' },
      { id: 'deliberation', icon: I.warn, label: 'deliberation', meta: '2', metaNew: true },
    ]},
    { label: 'content', items: [
      { id: 'bulletins', icon: I.bullets, label: 'bulletins', meta: 'w17', metaNew: true },
      { id: 'activity', icon: I.zap, label: 'activity feed' },
    ]},
    { label: 'account', items: [
      { id: 'team', icon: I.team, label: 'team' },
      { id: 'keys', icon: I.zap, label: 'api keys' },
      { id: 'billing', icon: I.billing, label: 'billing' },
      { id: 'audit', icon: I.doc, label: 'audit log' },
      { id: 'settings', icon: I.settings, label: 'settings' },
      { id: 'onboarding', icon: I.plus, label: 'onboarding' },
      { id: 'kit', icon: I.doc, label: 'kit reference' },
    ]},
  ];
  return (
    <aside className="sidebar">
      <div className="side-brand">
        <BrandSvg />
        <span className="side-brand-word">0dai<span className="side-brand-tld">.dev</span></span>
        <span className="side-brand-env">admin</span>
      </div>
      <nav className="side-nav">
        {groups.map((g) => (
          <div key={g.label} className="side-group">
            <div className="side-group-label">// {g.label}</div>
            {g.items.map((it) => (
              <button
                key={it.id}
                className={`side-link ${page === it.id ? 'is-active' : ''}`}
                onClick={() => setPage(it.id)}
                title={collapsed ? it.label : ''}
              >
                <span className="side-link-icon">{it.icon}</span>
                <span className="side-link-label">{it.label}</span>
                {it.meta ? <span className={`side-link-meta ${it.metaNew ? 'is-new' : ''}`}>{it.meta}</span> : null}
              </button>
            ))}
          </div>
        ))}
      </nav>
      <div className="side-foot">
        <div className="side-foot-row">
          <span className="side-foot-dot" />
          <span className="side-foot-text">all systems · v4.0.7</span>
        </div>
      </div>
    </aside>
  );
}

function Topbar({ crumbs, onCollapse, onCmdK, env, setEnv, onHelp }) {
  return (
    <header className="topbar">
      <Tip text="collapse sidebar" pos="bottom">
        <button className="topbar-collapse" onClick={onCollapse}>{I.more}</button>
      </Tip>
      <div className="crumbs">
        {crumbs.map((c, i) => (
          <React.Fragment key={i}>
            {i > 0 ? <span className="crumb-sep">/</span> : null}
            <span className="crumb">{c}</span>
          </React.Fragment>
        ))}
      </div>
      <button className="cmdk" onClick={onCmdK}>
        <span style={{ color: 'var(--fg-4)' }}>{I.search}</span>
        <span style={{ flex: 1, textAlign: 'left' }}>search · jump · run a command</span>
        <span className="cmdk-kbd">⌘K</span>
      </button>
      <Tip text="environment" pos="bottom">
        <button className={`env-switcher env-${env}`} onClick={() => setEnv(env === 'prod' ? 'staging' : env === 'staging' ? 'dev' : 'prod')}>
          <span className="env-switcher-dot" />
          <span>env: {env}</span>
          <span style={{ color: 'var(--fg-4)' }}>{I.chevDown}</span>
        </button>
      </Tip>
      <NotificationBell />
      <Tip text="shortcuts" pos="bottom" kbd="?">
        <button className="bell-btn" onClick={onHelp}>{I.help}</button>
      </Tip>
      <Dropdown
        align="right"
        trigger={<div className="avatar">EK</div>}
        items={[
          { label: 'erik@dev.team' },
          { icon: I.team, text: 'profile' },
          { icon: I.settings, text: 'settings', shortcut: '⌘,' },
          { icon: I.help, text: 'help & docs' },
          { sep: true },
          { icon: I.x, text: 'sign out', danger: true },
        ]}
      />
    </header>
  );
}

// ───────────────────────────────────────────────────────────────
// Page: Dashboard
// ───────────────────────────────────────────────────────────────
function PageDashboard() {
  const toast = useToast();
  const stats = [
    { mark: '// nodes', n: '142', em: '', lbl: 'captured · this repo', trend: '+9 this week', up: true },
    { mark: '// tasks', n: '6.3k', em: '', lbl: 'routed · network · w17', trend: '+12% wow', up: true },
    { mark: '// saved', n: '$0.41', em: '', lbl: 'avg per shipped patch', trend: '-$0.04 vs w16', up: false },
    { mark: '// digest', n: '13', em: '', lbl: 'consecutive fridays', trend: 'w18 queued · fri 09:00', up: true },
  ];

  const activity = [
    { t: '09:34', m: '✓', kind: 'is-ok',   text: <><span className="feed-mono">repo/auth</span> · pattern <span className="feed-strong">rotateRefresh</span> promoted to recommended</> },
    { t: '09:22', m: '·',                  text: <><span className="feed-mono">2-of-3 consensus</span> reached on <span className="feed-strong">jest-30 migration</span></> },
    { t: '09:14', m: '⚠', kind: 'is-warn', text: <><span className="feed-strong">opus</span> rate-limited · falling back to <span className="feed-mono">sonnet-4.5</span> for 3 tasks</> },
    { t: '08:51', m: '·',                  text: <>routing rebalanced — <span className="feed-strong">tests-flaky</span> now defaults to opus (was sonnet)</> },
    { t: '08:40', m: '✗', kind: 'is-err',  text: <><span className="feed-strong">patch held</span> · proposed lock conflicts with pattern <span className="feed-mono">#staged-flag</span></> },
    { t: '08:22', m: '·',                  text: <><span className="feed-mono">@erik</span> archived w15 bulletin · 4 patterns shipped</> },
    { t: '08:11', m: '✓', kind: 'is-ok',   text: <>doctor passed · <span className="feed-mono">0 warnings, 0 errors</span></> },
  ];

  return (
    <>
      <div className="page-head">
        <div className="page-head-left">
          <div className="page-kicker">// dashboard · tuesday, apr 29, 2026 · w18</div>
          <h1 className="page-title">good morning, <em>erik</em>.</h1>
          <p className="page-sub">7 repos online · 142 patterns captured · next friday digest queued. nothing currently held in deliberation.</p>
        </div>
        <div className="page-actions">
          <button className="btn btn-secondary"><span>{I.upload}</span>export</button>
          <button className="btn btn-primary" onClick={() => toast({ kind: 'info', title: 'pretend dispatch', text: '0dai run "ship auth" — opus assigned' })}>
            <span>{I.zap}</span>dispatch task<span className="btn-kbd">⌘⏎</span>
          </button>
        </div>
      </div>

      <div className="grid-4" style={{ marginBottom: 24 }}>
        {stats.map((s, i) => (
          <div key={i} className="card stat-card">
            <div className="stat-card-mark">{s.mark}</div>
            <div className="stat-card-num">{s.n}{s.em ? <em> {s.em}</em> : null}</div>
            <div className="stat-card-lbl">{s.lbl}</div>
            <div className={`stat-card-trend ${s.up ? 'is-up' : 'is-down'}`}>{s.up ? '↗' : '↘'} {s.trend}</div>
          </div>
        ))}
      </div>

      <div className="grid-12">
        <div className="card">
          <div className="card-head">
            <div>
              <div className="card-head-title">// 168h routing distribution</div>
              <div className="card-head-sub">tasks dispatched · last 7 days · n=412</div>
            </div>
            <div className="card-head-actions">
              <div className="seg">
                <span className="seg-opt">24h</span>
                <span className="seg-opt is-active">7d</span>
                <span className="seg-opt">30d</span>
              </div>
            </div>
          </div>
          <div className="card-body">
            <RoutingChart />
          </div>
          <div className="card-foot">
            <span>// last sync</span>
            <span style={{ color: 'var(--fg-2)' }}>3m ago</span>
            <span style={{ marginLeft: 'auto' }}>opus: 47% · sonnet: 31% · gemini: 18% · gpt-4o: 4%</span>
          </div>
        </div>

        <div className="card">
          <div className="card-head">
            <div className="card-head-title">// activity feed</div>
            <div className="card-head-actions">
              <button className="btn btn-ghost btn-sm">view all</button>
            </div>
          </div>
          <div className="card-body">
            <div className="feed">
              {activity.map((a, i) => (
                <div key={i} className="feed-item">
                  <span className="feed-time">{a.t}</span>
                  <span className={`feed-marker ${a.kind || ''}`}>{a.m}</span>
                  <span className="feed-text">{a.text}</span>
                </div>
              ))}
            </div>
          </div>
        </div>
      </div>

      <div style={{ marginTop: 24 }}>
        <div className="alert alert-ok">
          <span className="alert-ico">{I.check}</span>
          <div className="alert-body">
            <div className="alert-title">friday digest queued — w18</div>
            <div className="alert-text">5 items drafted · sign-off due thu 22:00 · auto-ship fri 09:00 UTC</div>
          </div>
          <span className="alert-close">{I.x}</span>
        </div>
      </div>
    </>
  );
}

function RoutingChart() {
  // Stylized stacked-bar chart, 7 days
  const days = [
    { d: 'mon', opus: 38, sonnet: 32, gem: 20, gpt: 10 },
    { d: 'tue', opus: 44, sonnet: 28, gem: 22, gpt: 6 },
    { d: 'wed', opus: 49, sonnet: 30, gem: 17, gpt: 4 },
    { d: 'thu', opus: 51, sonnet: 28, gem: 17, gpt: 4 },
    { d: 'fri', opus: 47, sonnet: 31, gem: 18, gpt: 4 },
    { d: 'sat', opus: 42, sonnet: 34, gem: 20, gpt: 4 },
    { d: 'sun', opus: 47, sonnet: 31, gem: 18, gpt: 4 },
  ];
  return (
    <div style={{ display: 'flex', gap: 12, alignItems: 'flex-end', height: 160 }}>
      {days.map((d, i) => {
        const total = d.opus + d.sonnet + d.gem + d.gpt;
        return (
          <div key={i} style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 6, alignItems: 'center' }}>
            <div style={{ width: '100%', height: 140, display: 'flex', flexDirection: 'column', justifyContent: 'flex-end', borderRadius: 4, overflow: 'hidden' }}>
              <div style={{ height: `${(d.opus/total)*100}%`, background: 'var(--accent)' }} />
              <div style={{ height: `${(d.sonnet/total)*100}%`, background: 'color-mix(in oklch, var(--accent) 55%, var(--bg-3))' }} />
              <div style={{ height: `${(d.gem/total)*100}%`, background: 'var(--info)' }} />
              <div style={{ height: `${(d.gpt/total)*100}%`, background: 'var(--fg-4)' }} />
            </div>
            <span className="mono" style={{ fontSize: 10, color: 'var(--fg-3)' }}>{d.d}</span>
          </div>
        );
      })}
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8, fontFamily: 'var(--f-mono)', fontSize: 11, color: 'var(--fg-3)', marginLeft: 16 }}>
        <span><span style={{ display: 'inline-block', width: 8, height: 8, background: 'var(--accent)', borderRadius: 2, marginRight: 6 }} />opus</span>
        <span><span style={{ display: 'inline-block', width: 8, height: 8, background: 'color-mix(in oklch, var(--accent) 55%, var(--bg-3))', borderRadius: 2, marginRight: 6 }} />sonnet</span>
        <span><span style={{ display: 'inline-block', width: 8, height: 8, background: 'var(--info)', borderRadius: 2, marginRight: 6 }} />gemini</span>
        <span><span style={{ display: 'inline-block', width: 8, height: 8, background: 'var(--fg-4)', borderRadius: 2, marginRight: 6 }} />gpt-4o</span>
      </div>
    </div>
  );
}

// ───────────────────────────────────────────────────────────────
// Page: Repos (data table)
// ───────────────────────────────────────────────────────────────
const REPOS = [
  { id: 1, name: 'repo/auth',       lang: 'typescript', patterns: 47, lastSync: '3m ago',  status: 'live',  cost: '$0.41', tasks: 412 },
  { id: 2, name: 'repo/payments',   lang: 'typescript', patterns: 38, lastSync: '12m ago', status: 'live',  cost: '$0.52', tasks: 287 },
  { id: 3, name: 'repo/dash',       lang: 'react',      patterns: 29, lastSync: '1h ago',  status: 'warn',  cost: '$0.38', tasks: 198 },
  { id: 4, name: 'repo/api-gateway',lang: 'go',         patterns: 22, lastSync: '4h ago',  status: 'live',  cost: '$0.29', tasks: 156 },
  { id: 5, name: 'repo/infra',      lang: 'terraform',  patterns: 6,  lastSync: '2d ago',  status: 'idle',  cost: '$0.18', tasks: 41 },
  { id: 6, name: 'repo/mobile',     lang: 'swift',      patterns: 0,  lastSync: 'never',   status: 'err',   cost: '—',     tasks: 0 },
  { id: 7, name: 'repo/playground', lang: 'mixed',      patterns: 0,  lastSync: '8d ago',  status: 'idle',  cost: '$0.02', tasks: 3 },
];

function PageRepos({ openDrawer }) {
  const [search, setSearch] = useState('');
  const [sort, setSort] = useState({ key: 'name', dir: 'asc' });
  const [selected, setSelected] = useState(new Set());
  const [statusFilter, setStatusFilter] = useState('all');

  const filtered = useMemo(() => {
    let r = REPOS;
    if (search) r = r.filter((x) => x.name.includes(search.toLowerCase()));
    if (statusFilter !== 'all') r = r.filter((x) => x.status === statusFilter);
    r = [...r].sort((a, b) => {
      const v = a[sort.key] > b[sort.key] ? 1 : -1;
      return sort.dir === 'asc' ? v : -v;
    });
    return r;
  }, [search, sort, statusFilter]);

  function toggleSort(key) {
    setSort((s) => s.key === key ? { key, dir: s.dir === 'asc' ? 'desc' : 'asc' } : { key, dir: 'asc' });
  }
  function toggleSel(id) {
    setSelected((s) => { const n = new Set(s); n.has(id) ? n.delete(id) : n.add(id); return n; });
  }
  function toggleSelAll() {
    setSelected((s) => s.size === filtered.length ? new Set() : new Set(filtered.map((r) => r.id)));
  }

  const Col = ({ k, children }) => (
    <th className={sort.key === k ? 'is-sorted' : ''} onClick={() => toggleSort(k)}>
      {children}<span className="sort-ico">{sort.key === k ? (sort.dir === 'asc' ? '↑' : '↓') : '↕'}</span>
    </th>
  );

  return (
    <>
      <div className="page-head">
        <div className="page-head-left">
          <div className="page-kicker">// repos · 7 online · 142 patterns total</div>
          <h1 className="page-title">repos</h1>
          <p className="page-sub">all repositories your 0dai instance is observing. click a row for detail · select multiple for bulk actions.</p>
        </div>
        <div className="page-actions">
          <button className="btn btn-secondary"><span>{I.filter}</span>filter</button>
          <button className="btn btn-primary"><span>{I.plus}</span>add repo</button>
        </div>
      </div>

      <div className="tbl-wrap">
        <div className="tbl-toolbar">
          <div className="tbl-toolbar-search">
            <span className="tbl-toolbar-search-ico">{I.search}</span>
            <input placeholder="search repos by name…" value={search} onChange={(e) => setSearch(e.target.value)} />
          </div>
          <div className="seg">
            {['all','live','warn','idle','err'].map((s) => (
              <span key={s} className={`seg-opt ${statusFilter === s ? 'is-active' : ''}`} onClick={() => setStatusFilter(s)}>{s}</span>
            ))}
          </div>
          {selected.size > 0 ? (
            <div className="btn-group">
              <button className="btn btn-secondary btn-sm">sync ({selected.size})</button>
              <button className="btn btn-secondary btn-sm">archive</button>
              <button className="btn btn-secondary btn-sm">{I.trash}</button>
            </div>
          ) : null}
          <div className="tbl-toolbar-count">{filtered.length} of {REPOS.length}</div>
        </div>
        <table className="tbl">
          <thead>
            <tr>
              <th className="tbl-checkbox-col">
                <label className="check"><input type="checkbox" checked={selected.size === filtered.length && filtered.length > 0} onChange={toggleSelAll} /><span className="check-box" /></label>
              </th>
              <Col k="name">repo</Col>
              <Col k="lang">stack</Col>
              <Col k="patterns">patterns</Col>
              <Col k="tasks">tasks · 7d</Col>
              <Col k="cost">avg cost</Col>
              <Col k="lastSync">last sync</Col>
              <Col k="status">status</Col>
              <th style={{ width: 60 }}></th>
            </tr>
          </thead>
          <tbody>
            {filtered.length === 0 ? (
              <tr><td colSpan={9}><div className="tbl-empty"><div className="tbl-empty-ico">{I.search}</div>no repos match "{search}"</div></td></tr>
            ) : filtered.map((r) => (
              <tr key={r.id} className={selected.has(r.id) ? 'is-selected' : ''} onClick={() => openDrawer(r)}>
                <td onClick={(e) => e.stopPropagation()}>
                  <label className="check"><input type="checkbox" checked={selected.has(r.id)} onChange={() => toggleSel(r.id)} /><span className="check-box" /></label>
                </td>
                <td><span className="tbl-row-primary">{r.name}</span></td>
                <td><span className="badge badge-square">{r.lang}</span></td>
                <td className="tbl-row-mono">{r.patterns}</td>
                <td className="tbl-row-mono">{r.tasks}</td>
                <td className="tbl-row-mono">{r.cost}</td>
                <td className="tbl-row-mono">{r.lastSync}</td>
                <td>
                  <span className={`badge badge-${r.status === 'live' ? 'live' : r.status === 'warn' ? 'warn' : r.status === 'err' ? 'err' : 'idle'}`}>
                    <span className={`badge-dot ${r.status === 'live' ? 'badge-dot-pulse' : ''}`} />{r.status}
                  </span>
                </td>
                <td onClick={(e) => e.stopPropagation()}>
                  <div className="tbl-row-actions">
                    <Dropdown
                      align="right"
                      trigger={<button className="btn btn-icon btn-ghost btn-sm">{I.more}</button>}
                      items={[
                        { icon: I.refresh, text: 'sync now', shortcut: '⌘S' },
                        { icon: I.eye, text: 'view patterns' },
                        { icon: I.edit, text: 'configure' },
                        { icon: I.external, text: 'open in github' },
                        { sep: true },
                        { icon: I.archive, text: 'archive' },
                        { icon: I.trash, text: 'delete', danger: true },
                      ]}
                    />
                  </div>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
        <div className="tbl-foot">
          <span>showing {filtered.length} of {REPOS.length}</span>
          <div className="tbl-foot-pages">
            <span className="page-num">‹</span>
            <span className="page-num is-active">1</span>
            <span className="page-num">2</span>
            <span className="page-num">›</span>
          </div>
        </div>
      </div>
    </>
  );
}

// ───────────────────────────────────────────────────────────────
// Drawer: Repo detail
// ───────────────────────────────────────────────────────────────
function RepoDrawer({ repo, onClose }) {
  if (!repo) return null;
  return (
    <>
      <div className="drawer-back" onClick={onClose} />
      <div className="drawer">
        <div className="drawer-head">
          <div style={{ flex: 1 }}>
            <div className="mono" style={{ fontSize: 10, color: 'var(--fg-4)', marginBottom: 4 }}>// repo detail</div>
            <h2 style={{ margin: 0, fontFamily: 'var(--f-display)', fontSize: 22, fontWeight: 400, letterSpacing: '-0.015em' }}>{repo.name}</h2>
            <div style={{ display: 'flex', gap: 8, marginTop: 8 }}>
              <span className="badge badge-square">{repo.lang}</span>
              <span className={`badge badge-${repo.status === 'live' ? 'live' : repo.status === 'warn' ? 'warn' : repo.status === 'err' ? 'err' : 'idle'}`}>
                <span className="badge-dot" />{repo.status}
              </span>
            </div>
          </div>
          <span className="modal-close" onClick={onClose}>{I.x}</span>
        </div>
        <div className="drawer-body">
          <div className="grid-2" style={{ marginBottom: 20 }}>
            <div>
              <div className="mono" style={{ fontSize: 10, color: 'var(--fg-4)', marginBottom: 4 }}>// patterns captured</div>
              <div style={{ fontFamily: 'var(--f-display)', fontSize: 28, color: 'var(--accent)' }}>{repo.patterns}</div>
            </div>
            <div>
              <div className="mono" style={{ fontSize: 10, color: 'var(--fg-4)', marginBottom: 4 }}>// tasks · 7d</div>
              <div style={{ fontFamily: 'var(--f-display)', fontSize: 28 }}>{repo.tasks}</div>
            </div>
          </div>

          <div className="kit-subgroup-label">// config</div>
          <div className="field">
            <span className="field-lbl">// auto-sync interval</span>
            <select className="select"><option>every 5 minutes</option><option>every hour</option><option>manual only</option></select>
          </div>
          <div className="field">
            <span className="field-lbl">// pattern contribution</span>
            <label className="check"><input type="checkbox" defaultChecked /><span className="check-box" />contribute patterns to the network</label>
          </div>
          <div className="field">
            <span className="field-lbl">// routing override</span>
            <textarea className="textarea mono" defaultValue={'tag:tests-flaky = "opus"\ntag:docs = "haiku"'} />
          </div>

          <div className="kit-subgroup-label" style={{ marginTop: 20 }}>// recent activity</div>
          <div className="feed">
            <div className="feed-item"><span className="feed-time">3m</span><span className="feed-marker is-ok">✓</span><span className="feed-text">pattern <span className="feed-mono">rotateRefresh</span> promoted</span></div>
            <div className="feed-item"><span className="feed-time">2h</span><span className="feed-marker">·</span><span className="feed-text">12 tasks dispatched</span></div>
            <div className="feed-item"><span className="feed-time">5h</span><span className="feed-marker is-warn">⚠</span><span className="feed-text">deliberation: race in <span className="feed-mono">renewSession()</span></span></div>
          </div>
        </div>
        <div className="drawer-foot">
          <button className="btn btn-secondary"><span>{I.link}</span>open in github</button>
          <button className="btn btn-primary" style={{ marginLeft: 'auto' }}>save changes</button>
        </div>
      </div>
    </>
  );
}

// ───────────────────────────────────────────────────────────────
// Page: Bulletin composer
// ───────────────────────────────────────────────────────────────
function PageBulletins() {
  const toast = useToast();
  const [items, setItems] = useState([
    { id: 1, tag: 'routing', head: 'opus reclaims test-generation lead', body: 'sonnet 4.5 dropped 6 pts on flaky-test repair this week (n=412 tasks). routing default updated. estimated savings: $0.08/task.' },
    { id: 2, tag: 'security', head: 'CVE-2026-0411 — patched template in registry', body: 'lodash transitive in scaffolders ≤3.2.1. master plan auto-bumps. 27 projects re-scaffolded overnight.' },
    { id: 3, tag: 'pattern', head: 'next.js app router → 21% fewer migration bugs', body: 'three independent projects converged on the same migration shape. promoted to recommended pattern.' },
    { id: 4, tag: 'failure', head: 'do not ask agents to "modernize jest config"', body: '14 attempts across 9 projects. 2 succeeded. flagged as anti-pattern.' },
  ]);
  const [activeId, setActiveId] = useState(1);
  const [meta, setMeta] = useState({ wk: 'w18', date: '2026-05-02', schedule: 'fri 09:00 UTC' });
  const cur = items.find((i) => i.id === activeId);

  function update(field, value) {
    setItems((arr) => arr.map((it) => it.id === activeId ? { ...it, [field]: value } : it));
  }
  function addItem() {
    const id = Math.max(...items.map((i) => i.id)) + 1;
    setItems((arr) => [...arr, { id, tag: 'pattern', head: 'new item', body: '' }]);
    setActiveId(id);
  }
  function delItem(id) {
    setItems((arr) => arr.filter((i) => i.id !== id));
    if (id === activeId) setActiveId(items[0]?.id);
  }

  return (
    <>
      <div className="page-head">
        <div className="page-head-left">
          <div className="page-kicker">// bulletin composer · {meta.wk} · drafts auto-saved</div>
          <h1 className="page-title">weekly digest, <em>composed</em></h1>
          <p className="page-sub">draft this friday's bulletin. left: items in order. right: editor + live preview. sign + schedule when ready.</p>
        </div>
        <div className="page-actions">
          <button className="btn btn-ghost">discard draft</button>
          <button className="btn btn-secondary">save</button>
          <button className="btn btn-primary" onClick={() => toast({ kind: 'info', title: 'queued for friday', text: `w18 will ship ${meta.schedule}` })}>
            <span>{I.send}</span>sign &amp; schedule
          </button>
        </div>
      </div>

      <div className="alert alert-info" style={{ marginBottom: 24 }}>
        <span className="alert-ico">{I.info}</span>
        <div className="alert-body">
          <div className="alert-title">sign-off deadline · thursday 22:00 UTC</div>
          <div className="alert-text">2 reviewers required · once signed, the digest is locked and shipped via the release key (ed25519).</div>
        </div>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '280px 1fr 1fr', gap: 20 }}>
        {/* Items list */}
        <div className="card">
          <div className="card-head">
            <div className="card-head-title">items · {items.length}</div>
            <div className="card-head-actions"><button className="btn btn-icon btn-ghost btn-sm" onClick={addItem}>{I.plus}</button></div>
          </div>
          <div style={{ padding: 8 }}>
            {items.map((it, i) => (
              <div
                key={it.id}
                onClick={() => setActiveId(it.id)}
                style={{
                  padding: '10px 12px', borderRadius: 6, cursor: 'pointer',
                  background: activeId === it.id ? 'var(--bg-hover)' : 'transparent',
                  borderLeft: `2px solid ${activeId === it.id ? 'var(--accent)' : 'transparent'}`,
                  marginBottom: 2,
                }}
              >
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 }}>
                  <span className="mono" style={{ fontSize: 10, color: 'var(--fg-4)' }}>#{i + 1}</span>
                  <span className={`badge badge-square badge-${it.tag === 'routing' ? 'live' : it.tag === 'security' ? 'warn' : it.tag === 'failure' ? 'err' : 'idle'}`}>{it.tag}</span>
                  <span className="btn btn-icon btn-ghost btn-sm" style={{ marginLeft: 'auto', width: 18, height: 18 }} onClick={(e) => { e.stopPropagation(); delItem(it.id); }}>{I.x}</span>
                </div>
                <div style={{ fontSize: 12, color: 'var(--fg-2)', lineHeight: 1.35 }}>{it.head}</div>
              </div>
            ))}
          </div>
          <div className="card-foot">
            <span>// drag to reorder</span>
          </div>
        </div>

        {/* Editor */}
        <div className="card">
          <div className="card-head">
            <div className="card-head-title">edit</div>
            <div className="card-head-sub">#{cur ? items.indexOf(cur) + 1 : '—'}</div>
          </div>
          <div className="card-body">
            {cur ? (
              <>
                <div className="field">
                  <span className="field-lbl">// tag</span>
                  <div className="seg">
                    {['routing','security','pattern','failure'].map((t) => (
                      <span key={t} className={`seg-opt ${cur.tag === t ? 'is-active' : ''}`} onClick={() => update('tag', t)}>{t}</span>
                    ))}
                  </div>
                </div>
                <div className="field">
                  <span className="field-lbl">// headline <span className="field-lbl-req">*</span></span>
                  <input className="input" value={cur.head} onChange={(e) => update('head', e.target.value)} />
                  <div className="field-help">aim for under 70 chars. lead with the verb.</div>
                </div>
                <div className="field">
                  <span className="field-lbl">// body</span>
                  <textarea className="textarea" rows={6} value={cur.body} onChange={(e) => update('body', e.target.value)} />
                  <div className="field-help">facts only. include n= when citing data. one paragraph max.</div>
                </div>
              </>
            ) : <div style={{ color: 'var(--fg-3)' }}>no item selected</div>}
          </div>
        </div>

        {/* Preview */}
        <div className="card">
          <div className="card-head">
            <div className="card-head-title">preview</div>
            <div className="card-head-actions"><span className="badge">{meta.wk}</span></div>
          </div>
          <div className="card-body" style={{ background: 'var(--bg)' }}>
            <div style={{ paddingBottom: 16, marginBottom: 16, borderBottom: '1px dashed var(--line)' }}>
              <div className="mono" style={{ fontSize: 11, color: 'var(--fg-3)' }}>0dai · friday digest · {meta.wk} · {meta.date}</div>
              <div style={{ fontFamily: 'var(--f-display)', fontSize: 24, marginTop: 6 }}>this week in coding agents.</div>
            </div>
            {items.map((it, i) => (
              <div key={it.id} style={{ paddingBottom: 14, marginBottom: 14, borderBottom: i < items.length - 1 ? '1px dashed var(--line)' : 'none' }}>
                <div style={{ display: 'flex', gap: 8, alignItems: 'flex-start' }}>
                  <span className={`badge badge-square badge-${it.tag === 'routing' ? 'live' : it.tag === 'security' ? 'warn' : it.tag === 'failure' ? 'err' : 'idle'}`}>{it.tag}</span>
                  <div style={{ flex: 1 }}>
                    <div style={{ fontSize: 14, fontWeight: 600, marginBottom: 4 }}>{it.head}</div>
                    <div style={{ fontSize: 12, color: 'var(--fg-2)' }}>{it.body}</div>
                  </div>
                </div>
              </div>
            ))}
          </div>
          <div className="card-foot">
            <span>// est. read time</span>
            <span style={{ color: 'var(--fg-2)' }}>~4 min</span>
            <span style={{ marginLeft: 'auto' }}>2,447 subs</span>
          </div>
        </div>
      </div>
    </>
  );
}

// ───────────────────────────────────────────────────────────────
// Page: Settings
// ───────────────────────────────────────────────────────────────
function PageSettings() {
  const toast = useToast();
  const [confirmOpen, setConfirmOpen] = useState(false);
  const [optOut, setOptOut] = useState(false);
  const [shipping, setShipping] = useState({ patterns: true, failures: true, routing: false });
  const [name, setName] = useState('Erik K.');
  const [email, setEmail] = useState('erik@dev.team');
  const [emailErr, setEmailErr] = useState('');
  const [vol, setVol] = useState(60);
  const [tab, setTab] = useState('profile');

  function save(e) {
    e.preventDefault();
    if (!email.includes('@')) { setEmailErr('invalid email'); return; }
    setEmailErr('');
    toast({ kind: 'info', title: 'saved', text: 'profile changes applied' });
  }

  return (
    <>
      <div className="page-head">
        <div className="page-head-left">
          <div className="page-kicker">// settings · workspace · personal</div>
          <h1 className="page-title">settings</h1>
        </div>
      </div>

      <div className="tabs" style={{ marginBottom: 28 }}>
        <span className={`tab ${tab === 'profile' ? 'is-active' : ''}`} onClick={() => setTab('profile')}>profile</span>
        <span className={`tab ${tab === 'workspace' ? 'is-active' : ''}`} onClick={() => setTab('workspace')}>workspace<span className="tab-count">3</span></span>
        <span className={`tab ${tab === 'network' ? 'is-active' : ''}`} onClick={() => setTab('network')}>network</span>
        <span className={`tab ${tab === 'integrations' ? 'is-active' : ''}`} onClick={() => setTab('integrations')}>integrations</span>
        <span className={`tab ${tab === 'danger' ? 'is-active' : ''}`} onClick={() => setTab('danger')}>danger zone</span>
      </div>

      {tab === 'profile' && (
        <form onSubmit={save} style={{ maxWidth: 640 }}>
          <SettingsSection title="profile" sub="how you appear to your team.">
            <div className="field">
              <span className="field-lbl">// avatar</span>
              <div className="filedrop">
                <div className="filedrop-ico">{I.upload}</div>
                <div className="filedrop-strong">drop an image or click to upload</div>
                <div className="filedrop-sub">png, jpg, webp · max 2mb · 256×256 recommended</div>
              </div>
            </div>
            <div className="field-row">
              <div className="field">
                <span className="field-lbl">// display name</span>
                <input className="input" value={name} onChange={(e) => setName(e.target.value)} />
              </div>
              <div className="field">
                <span className="field-lbl">// email <span className="field-lbl-req">*</span></span>
                <input className={`input ${emailErr ? 'is-error' : ''}`} type="email" value={email} onChange={(e) => setEmail(e.target.value)} />
                {emailErr ? <div className="field-err">{I.err} {emailErr}</div> : null}
              </div>
            </div>
            <div className="field">
              <span className="field-lbl">// bio</span>
              <textarea className="textarea" rows={3} placeholder="what do you build? (shown in your bulletin signoff)" />
            </div>
          </SettingsSection>

          <SettingsSection title="notifications" sub="when 0dai pings you.">
            <div className="field">
              <label className="check"><input type="checkbox" defaultChecked /><span className="check-box" />friday digest in my inbox</label>
            </div>
            <div className="field">
              <label className="check"><input type="checkbox" defaultChecked /><span className="check-box" />deliberation alerts (when 2/3 fails)</label>
            </div>
            <div className="field">
              <label className="check"><input type="checkbox" /><span className="check-box" />weekly cost report</label>
            </div>
            <div className="field">
              <span className="field-lbl">// notification volume — {vol}%</span>
              <input type="range" min="0" max="100" value={vol} onChange={(e) => setVol(+e.target.value)} className="slider" />
            </div>
          </SettingsSection>

          <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end', marginTop: 16 }}>
            <button type="button" className="btn btn-ghost">discard</button>
            <button type="submit" className="btn btn-primary">save changes</button>
          </div>
        </form>
      )}

      {tab === 'network' && (
        <div style={{ maxWidth: 640 }}>
          <SettingsSection title="network participation" sub="control what your repos contribute to the 0dai network.">
            <div className="field" style={{ paddingBottom: 16, borderBottom: '1px dashed var(--line)' }}>
              <label style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
                <span style={{ flex: 1 }}>
                  <div style={{ fontWeight: 500, fontSize: 13 }}>opt out of network sharing</div>
                  <div style={{ fontSize: 12, color: 'var(--fg-3)', marginTop: 2 }}>your repo still receives the digest. nothing flows upstream.</div>
                </span>
                <label className="toggle"><input type="checkbox" checked={optOut} onChange={() => setOptOut(!optOut)} /><span className="toggle-track" /></label>
              </label>
            </div>
            <div style={{ opacity: optOut ? 0.4 : 1, pointerEvents: optOut ? 'none' : 'auto' }}>
              <div className="field-lbl" style={{ marginTop: 14, marginBottom: 8 }}>// share by category</div>
              {[
                { k: 'patterns', l: 'pattern outcomes', s: 'what worked, what didn\'t. anonymized.' },
                { k: 'failures', l: 'failure modes', s: 'helps the network avoid known anti-patterns.' },
                { k: 'routing', l: 'model routing telemetry', s: 'which model won which task type.' },
              ].map((s) => (
                <label key={s.k} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '10px 0', borderBottom: '1px dashed var(--line)' }}>
                  <span style={{ flex: 1 }}>
                    <div style={{ fontWeight: 500, fontSize: 13 }}>{s.l}</div>
                    <div style={{ fontSize: 11, color: 'var(--fg-3)' }}>{s.s}</div>
                  </span>
                  <label className="toggle"><input type="checkbox" checked={shipping[s.k]} onChange={() => setShipping((x) => ({ ...x, [s.k]: !x[s.k] }))} /><span className="toggle-track" /></label>
                </label>
              ))}
            </div>
          </SettingsSection>

          <SettingsSection title="bulletin signing" sub="verification key the cli uses to authenticate digests.">
            <div className="code">
              <div>// release key · ed25519 · rotated 2026-01-01</div>
              <div className="code-line-hl">0dai-rel-key-2026.pub</div>
              <div>ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK7+...wQqL3</div>
            </div>
            <div style={{ display: 'flex', gap: 8, marginTop: 12 }}>
              <button className="btn btn-secondary btn-sm"><span>{I.copy}</span>copy pubkey</button>
              <button className="btn btn-ghost btn-sm">view rotation log</button>
            </div>
          </SettingsSection>
        </div>
      )}

      {tab === 'workspace' && (
        <div style={{ maxWidth: 640 }}>
          <SettingsSection title="workspace" sub="shared with your team.">
            <div className="field">
              <span className="field-lbl">// workspace name</span>
              <input className="input" defaultValue="acme-engineering" />
            </div>
            <div className="field">
              <span className="field-lbl">// workspace url</span>
              <div className="input-with-affix">
                <span className="input-affix mono" style={{ fontSize: 12 }}>0dai.dev/</span>
                <input className="input mono" defaultValue="acme" />
              </div>
            </div>
            <div className="field">
              <span className="field-lbl">// default cli</span>
              <select className="select" defaultValue="claude code">
                <option>claude code</option><option>codex</option><option>gemini cli</option><option>cursor cli</option><option>aider</option>
              </select>
            </div>
          </SettingsSection>
        </div>
      )}

      {tab === 'integrations' && (
        <div className="grid-2">
          {[
            { n: 'github', s: 'sync repos · open PRs · ship patches', on: true },
            { n: 'slack', s: 'friday digest in #engineering', on: true },
            { n: 'linear', s: 'auto-create tickets from held deliberations', on: false },
            { n: 'sentry', s: 'feed errors into pattern detector', on: false },
            { n: 'pagerduty', s: 'wake humans when consensus stalls', on: false },
            { n: 'datadog', s: 'cost & latency metrics', on: false },
          ].map((i) => (
            <div key={i.n} className="card" style={{ padding: 16 }}>
              <div style={{ display: 'flex', alignItems: 'flex-start', gap: 12 }}>
                <div style={{ width: 40, height: 40, background: 'var(--bg-3)', borderRadius: 8, display: 'grid', placeItems: 'center', color: 'var(--fg-3)' }}>{I.link}</div>
                <div style={{ flex: 1 }}>
                  <div style={{ fontWeight: 600 }}>{i.n}</div>
                  <div style={{ fontSize: 12, color: 'var(--fg-3)', marginTop: 2 }}>{i.s}</div>
                </div>
                {i.on ? <span className="badge badge-live"><span className="badge-dot" />connected</span> : <button className="btn btn-secondary btn-sm">connect</button>}
              </div>
            </div>
          ))}
        </div>
      )}

      {tab === 'danger' && (
        <div style={{ maxWidth: 640 }}>
          <div className="card" style={{ borderColor: 'color-mix(in oklch, var(--err) 40%, var(--line))' }}>
            <div className="card-head" style={{ borderColor: 'color-mix(in oklch, var(--err) 30%, var(--line))' }}>
              <div className="card-head-title" style={{ color: 'var(--err)' }}>// danger zone</div>
            </div>
            <div className="card-body">
              <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '12px 0' }}>
                <div style={{ flex: 1 }}>
                  <div style={{ fontWeight: 500 }}>archive workspace</div>
                  <div style={{ fontSize: 12, color: 'var(--fg-3)' }}>read-only. patterns frozen. digests stop.</div>
                </div>
                <button className="btn btn-secondary">archive</button>
              </div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '12px 0', borderTop: '1px dashed var(--line)' }}>
                <div style={{ flex: 1 }}>
                  <div style={{ fontWeight: 500, color: 'var(--err)' }}>delete workspace</div>
                  <div style={{ fontSize: 12, color: 'var(--fg-3)' }}>irreversible. all patterns lost. cannot be undone.</div>
                </div>
                <button className="btn btn-danger" onClick={() => setConfirmOpen(true)}>delete forever</button>
              </div>
            </div>
          </div>
        </div>
      )}

      {confirmOpen && (
        <div className="modal-back" onClick={() => setConfirmOpen(false)}>
          <div className="modal" onClick={(e) => e.stopPropagation()}>
            <div className="modal-head">
              <div style={{ flex: 1 }}>
                <h3 className="modal-title">delete <em style={{ fontStyle: 'italic', color: 'var(--err)' }}>acme-engineering</em>?</h3>
                <div className="modal-sub">// this cannot be undone</div>
              </div>
              <span className="modal-close" onClick={() => setConfirmOpen(false)}>{I.x}</span>
            </div>
            <div className="modal-body">
              <div className="alert alert-err" style={{ marginBottom: 16 }}>
                <span className="alert-ico">{I.alert}</span>
                <div className="alert-body">
                  <div className="alert-title">142 patterns will be permanently destroyed</div>
                  <div className="alert-text">13 weeks of bulletin signatures will be invalidated. there is no recovery.</div>
                </div>
              </div>
              <div className="field">
                <span className="field-lbl">// type <span className="mono" style={{ color: 'var(--fg)' }}>acme-engineering</span> to confirm</span>
                <input className="input mono" placeholder="workspace name" />
              </div>
            </div>
            <div className="modal-foot">
              <button className="btn btn-ghost" onClick={() => setConfirmOpen(false)}>cancel</button>
              <button className="btn btn-danger" disabled>delete workspace</button>
            </div>
          </div>
        </div>
      )}
    </>
  );
}

function SettingsSection({ title, sub, children }) {
  return (
    <div className="card" style={{ marginBottom: 16 }}>
      <div className="card-head">
        <div>
          <div className="card-head-title">{title}</div>
          {sub ? <div className="card-head-sub">// {sub}</div> : null}
        </div>
      </div>
      <div className="card-body">{children}</div>
    </div>
  );
}

// ───────────────────────────────────────────────────────────────
// Page: Billing
// ───────────────────────────────────────────────────────────────
function PageBilling() {
  const invoices = [
    { id: 'inv-2026-04', date: 'apr 1, 2026', amt: '$60.00', status: 'paid', items: '3 seats · pro' },
    { id: 'inv-2026-03', date: 'mar 1, 2026', amt: '$60.00', status: 'paid', items: '3 seats · pro' },
    { id: 'inv-2026-02', date: 'feb 1, 2026', amt: '$40.00', status: 'paid', items: '2 seats · pro' },
    { id: 'inv-2026-01', date: 'jan 1, 2026', amt: '$20.00', status: 'paid', items: '1 seat · pro' },
    { id: 'inv-2025-12', date: 'dec 1, 2025', amt: '$0.00',  status: 'free', items: 'free tier' },
  ];
  return (
    <>
      <div className="page-head">
        <div className="page-head-left">
          <div className="page-kicker">// billing · pro plan · 3 seats · next charge may 1</div>
          <h1 className="page-title">billing</h1>
        </div>
        <div className="page-actions">
          <button className="btn btn-secondary">change plan</button>
          <button className="btn btn-primary">manage seats</button>
        </div>
      </div>

      <div className="grid-3" style={{ marginBottom: 24 }}>
        <div className="card stat-card">
          <div className="stat-card-mark">// current plan</div>
          <div className="stat-card-num display"><em>pro</em></div>
          <div className="stat-card-lbl">$20/seat/mo · 3 seats</div>
        </div>
        <div className="card stat-card">
          <div className="stat-card-mark">// next charge</div>
          <div className="stat-card-num">$60</div>
          <div className="stat-card-lbl">may 1, 2026 · visa •• 4242</div>
        </div>
        <div className="card stat-card">
          <div className="stat-card-mark">// usage this month</div>
          <div className="stat-card-num">412 / ∞</div>
          <div className="stat-card-lbl">tasks routed (unlimited on pro)</div>
        </div>
      </div>

      <div className="tbl-wrap">
        <div className="tbl-toolbar">
          <div className="card-head-title">invoices</div>
          <div className="tbl-toolbar-count">5 invoices · all paid</div>
        </div>
        <table className="tbl">
          <thead><tr><th>invoice</th><th>date</th><th>items</th><th>amount</th><th>status</th><th></th></tr></thead>
          <tbody>
            {invoices.map((i) => (
              <tr key={i.id}>
                <td><span className="tbl-row-primary mono">{i.id}</span></td>
                <td className="tbl-row-mono">{i.date}</td>
                <td>{i.items}</td>
                <td className="tbl-row-mono">{i.amt}</td>
                <td><span className={`badge badge-${i.status === 'paid' ? 'live' : 'idle'}`}>{i.status}</span></td>
                <td><button className="btn btn-ghost btn-sm">download</button></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </>
  );
}

// ───────────────────────────────────────────────────────────────
// Page: Kit reference
// ───────────────────────────────────────────────────────────────
function PageKit() {
  const colors = [
    ['bg', '#0b0c0d'], ['bg-1', '#111315'], ['bg-2', '#16191c'], ['bg-3', '#1d2125'],
    ['fg', '#e8eaed'], ['fg-2', '#b6bbc0'], ['fg-3', '#7e858c'], ['fg-4', '#565c63'],
    ['accent', '#7BD389'], ['warn', '#f4b13c'], ['err', '#ef6361'], ['info', '#6aa9ff'],
  ];
  const spacings = [['s-1', 4], ['s-2', 8], ['s-3', 12], ['s-4', 16], ['s-5', 24], ['s-6', 32], ['s-7', 48], ['s-8', 64]];
  const [modalOpen, setModalOpen] = useState(false);
  return (
    <>
      <div className="page-head">
        <div className="page-head-left">
          <div className="page-kicker">// design system · v1.0 · last updated apr 29</div>
          <h1 className="page-title">kit <em>reference</em></h1>
          <p className="page-sub">every token, atom, and pattern in the admin kit. one source of truth.</p>
        </div>
      </div>

      <KitSection id="01" title="Colors">
        <div className="kit-swatch-row">
          {colors.map(([n, v]) => (
            <div key={n} className="kit-swatch" style={{ background: `var(--${n})` }}>
              <span className="kit-swatch-lbl">{n}</span>
            </div>
          ))}
        </div>
      </KitSection>

      <KitSection id="02" title="Type">
        <div className="kit-type-row"><span className="kit-type-meta">display · 32 · 400</span><span style={{ fontFamily: 'var(--f-display)', fontSize: 32, letterSpacing: '-0.02em' }}>// agents that compound.</span></div>
        <div className="kit-type-row"><span className="kit-type-meta">display · 22 · 400</span><span style={{ fontFamily: 'var(--f-display)', fontSize: 22 }}>delete workspace?</span></div>
        <div className="kit-type-row"><span className="kit-type-meta">sans · 14 · 600</span><span style={{ fontSize: 14, fontWeight: 600 }}>card title · settings &gt; profile</span></div>
        <div className="kit-type-row"><span className="kit-type-meta">sans · 13 · 400</span><span style={{ fontSize: 13 }}>body copy at the default. used everywhere.</span></div>
        <div className="kit-type-row"><span className="kit-type-meta">mono · 11 · 400</span><span className="mono" style={{ fontSize: 11, color: 'var(--fg-3)' }}>// kicker · timestamp · label</span></div>
        <div className="kit-type-row"><span className="kit-type-meta">mono · 10 · 600</span><span className="mono" style={{ fontSize: 10, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.06em' }}>tag · badge</span></div>
      </KitSection>

      <KitSection id="03" title="Spacing">
        <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
          {spacings.map(([n, v]) => (
            <div key={n} style={{ display: 'grid', gridTemplateColumns: '80px 1fr', gap: 16, alignItems: 'center' }}>
              <span className="mono" style={{ fontSize: 11, color: 'var(--fg-3)' }}>{n} · {v}px</span>
              <div className="kit-spacing-bar" style={{ width: v * 6 }} />
            </div>
          ))}
        </div>
      </KitSection>

      <KitSection id="04" title="Buttons">
        <div className="kit-subgroup">
          <div className="kit-subgroup-label">variants</div>
          <div className="kit-demo">
            <button className="btn btn-primary">primary</button>
            <button className="btn btn-secondary">secondary</button>
            <button className="btn btn-ghost">ghost</button>
            <button className="btn btn-danger">danger</button>
            <button className="btn btn-primary" disabled>disabled</button>
          </div>
        </div>
        <div className="kit-subgroup">
          <div className="kit-subgroup-label">sizes</div>
          <div className="kit-demo">
            <button className="btn btn-primary btn-sm">small</button>
            <button className="btn btn-primary">default</button>
            <button className="btn btn-primary btn-lg">large</button>
          </div>
        </div>
        <div className="kit-subgroup">
          <div className="kit-subgroup-label">with icon · group · kbd</div>
          <div className="kit-demo">
            <button className="btn btn-primary"><span>{I.zap}</span>dispatch<span className="btn-kbd">⌘⏎</span></button>
            <div className="btn-group">
              <button className="btn btn-secondary is-active">code</button>
              <button className="btn btn-secondary">preview</button>
              <button className="btn btn-secondary">diff</button>
            </div>
            <button className="btn btn-icon btn-secondary">{I.plus}</button>
          </div>
        </div>
      </KitSection>

      <KitSection id="05" title="Badges & status">
        <div className="kit-subgroup">
          <div className="kit-subgroup-label">badges · status pills</div>
          <div className="kit-demo">
            <span className="badge">default</span>
            <span className="badge badge-live"><span className="badge-dot badge-dot-pulse" />live</span>
            <span className="badge badge-warn"><span className="badge-dot" />warn</span>
            <span className="badge badge-err"><span className="badge-dot" />error</span>
            <span className="badge badge-info"><span className="badge-dot" />info</span>
            <span className="badge badge-idle">idle</span>
            <span className="badge badge-square">typescript</span>
            <span className="badge badge-square badge-live">routing</span>
          </div>
        </div>

        <div className="kit-subgroup">
          <div className="kit-subgroup-label">notification counters · overlays</div>
          <div className="kit-demo" style={{ gap: 28 }}>
            <div className="kit-cnt-demo">
              <button className="bell-btn"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinejoin="round" strokeLinecap="round"><path d="M3 6a5 5 0 0 1 10 0v3l1.5 2H1.5L3 9V6z"/><path d="M6 13a2 2 0 0 0 4 0"/></svg><span className="bell-badge">3</span></button>
              <div className="kit-cnt-lbl">err · default</div>
            </div>
            <div className="kit-cnt-demo">
              <button className="bell-btn"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinejoin="round" strokeLinecap="round"><path d="M3 6a5 5 0 0 1 10 0v3l1.5 2H1.5L3 9V6z"/><path d="M6 13a2 2 0 0 0 4 0"/></svg><span className="bell-badge is-accent">12</span></button>
              <div className="kit-cnt-lbl">accent</div>
            </div>
            <div className="kit-cnt-demo">
              <button className="bell-btn"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinejoin="round" strokeLinecap="round"><path d="M3 6a5 5 0 0 1 10 0v3l1.5 2H1.5L3 9V6z"/><path d="M6 13a2 2 0 0 0 4 0"/></svg><span className="bell-badge is-warn">99+</span></button>
              <div className="kit-cnt-lbl">warn · overflow</div>
            </div>
            <div className="kit-cnt-demo">
              <button className="bell-btn"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinejoin="round" strokeLinecap="round"><path d="M3 6a5 5 0 0 1 10 0v3l1.5 2H1.5L3 9V6z"/><path d="M6 13a2 2 0 0 0 4 0"/></svg><span className="bell-badge is-dot is-accent" /></button>
              <div className="kit-cnt-lbl">dot only</div>
            </div>
            <div className="kit-cnt-demo">
              <button className="bell-btn" style={{ position: 'relative' }}><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinejoin="round" strokeLinecap="round"><path d="M3 6a5 5 0 0 1 10 0v3l1.5 2H1.5L3 9V6z"/><path d="M6 13a2 2 0 0 0 4 0"/></svg></button>
              <div className="kit-cnt-lbl">no badge</div>
            </div>
          </div>
        </div>
      </KitSection>

      <KitSection id="06" title="Form controls">
        <div className="grid-2">
          <div className="field">
            <span className="field-lbl">// text input</span>
            <input className="input" placeholder="placeholder text" />
            <div className="field-help">help text under the field</div>
          </div>
          <div className="field">
            <span className="field-lbl">// error state</span>
            <input className="input is-error" defaultValue="not an email" />
            <div className="field-err">{I.err} must be a valid email</div>
          </div>
          <div className="field">
            <span className="field-lbl">// with affix</span>
            <div className="input-with-affix"><span className="input-affix">{I.search}</span><input className="input" placeholder="search" /></div>
          </div>
          <div className="field">
            <span className="field-lbl">// select</span>
            <select className="select"><option>option one</option><option>option two</option></select>
          </div>
          <div className="field">
            <span className="field-lbl">// segmented</span>
            <div className="seg"><span className="seg-opt is-active">day</span><span className="seg-opt">week</span><span className="seg-opt">month</span></div>
          </div>
          <div className="field">
            <span className="field-lbl">// toggle</span>
            <label style={{ display: 'flex', gap: 10, alignItems: 'center' }}>
              <label className="toggle"><input type="checkbox" defaultChecked /><span className="toggle-track" /></label>
              <span style={{ fontSize: 13 }}>contribute patterns to the network</span>
            </label>
          </div>
          <div className="field">
            <span className="field-lbl">// checkbox · radio</span>
            <div style={{ display: 'flex', gap: 16 }}>
              <label className="check"><input type="checkbox" defaultChecked /><span className="check-box" />checked</label>
              <label className="radio"><input type="radio" name="r" defaultChecked /><span className="radio-box" />option a</label>
              <label className="radio"><input type="radio" name="r" /><span className="radio-box" />option b</label>
            </div>
          </div>
          <div className="field">
            <span className="field-lbl">// slider</span>
            <input type="range" defaultValue="60" className="slider" />
          </div>
        </div>
        <div className="field" style={{ marginTop: 16 }}>
          <span className="field-lbl">// textarea</span>
          <textarea className="textarea" rows={4} placeholder="multi-line text input…" />
        </div>
        <div className="field">
          <span className="field-lbl">// file drop</span>
          <div className="filedrop"><div className="filedrop-ico">{I.upload}</div><div className="filedrop-strong">drop a file</div><div className="filedrop-sub">png · jpg · csv · max 5mb</div></div>
        </div>
      </KitSection>

      <KitSection id="07" title="Cards & stats">
        <div className="grid-3">
          <div className="card stat-card">
            <div className="stat-card-mark">// primary</div>
            <div className="stat-card-num">142<em> +9</em></div>
            <div className="stat-card-lbl">patterns captured · this repo</div>
            <div className="stat-card-trend is-up">↗ +12% wow</div>
          </div>
          <div className="card stat-card">
            <div className="stat-card-mark">// neutral</div>
            <div className="stat-card-num">6.3k</div>
            <div className="stat-card-lbl">tasks routed · network</div>
          </div>
          <div className="card stat-card">
            <div className="stat-card-mark">// negative</div>
            <div className="stat-card-num">$0.41</div>
            <div className="stat-card-lbl">avg cost / patch</div>
            <div className="stat-card-trend is-down">↘ -$0.04 vs w16</div>
          </div>
        </div>
      </KitSection>

      <KitSection id="08" title="Alerts">
        <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
          <div className="alert alert-ok"><span className="alert-ico">{I.check}</span><div className="alert-body"><div className="alert-title">all systems nominal</div><div className="alert-text">no deliberations held · digest queued</div></div></div>
          <div className="alert alert-info"><span className="alert-ico">{I.info}</span><div className="alert-body"><div className="alert-title">sign-off due thursday 22:00</div><div className="alert-text">2 reviewers required before the digest auto-ships.</div></div></div>
          <div className="alert alert-warn"><span className="alert-ico">{I.warn}</span><div className="alert-body"><div className="alert-title">opus rate-limited</div><div className="alert-text">3 tasks queued · falling back to sonnet</div></div></div>
          <div className="alert alert-err"><span className="alert-ico">{I.alert}</span><div className="alert-body"><div className="alert-title">deliberation held</div><div className="alert-text">2/3 consensus failed on auth refactor</div></div></div>
        </div>
      </KitSection>

      <KitSection id="09" title="Tabs">
        <div className="kit-subgroup">
          <div className="kit-subgroup-label">underline</div>
          <div className="tabs"><span className="tab is-active">overview</span><span className="tab">patterns<span className="tab-count">142</span></span><span className="tab">activity</span><span className="tab">settings</span></div>
        </div>
        <div className="kit-subgroup">
          <div className="kit-subgroup-label">pill</div>
          <div className="pill-tabs"><span className="pill-tab is-active">24h</span><span className="pill-tab">7d</span><span className="pill-tab">30d</span></div>
        </div>
      </KitSection>

      <KitSection id="10" title="Overlays">
        <div className="kit-demo">
          <button className="btn btn-secondary" onClick={() => setModalOpen(true)}>open modal</button>
          <button className="btn btn-secondary" disabled>command palette · ⌘K</button>
        </div>
      </KitSection>

      <KitSection id="11" title="Avatars">
        <div className="kit-subgroup">
          <div className="kit-subgroup-label">sizes</div>
          <div className="kit-demo">
            <span className="kit-avatar kit-avatar-sm kit-avatar-a">EK</span>
            <span className="kit-avatar kit-avatar-b">MV</span>
            <span className="kit-avatar kit-avatar-lg kit-avatar-c">RS</span>
            <span className="kit-avatar kit-avatar-ghost">??</span>
          </div>
        </div>
        <div className="kit-subgroup">
          <div className="kit-subgroup-label">with status · stack · meta</div>
          <div className="kit-demo">
            <span className="kit-avatar kit-avatar-a">EK<span className="kit-avatar-status is-on" /></span>
            <span className="kit-avatar kit-avatar-c">MV<span className="kit-avatar-status is-idle" /></span>
            <span className="kit-avatar kit-avatar-d">RS<span className="kit-avatar-status is-off" /></span>
            <div className="kit-avatar-stack">
              <span className="kit-avatar kit-avatar-a">EK</span>
              <span className="kit-avatar kit-avatar-b">MV</span>
              <span className="kit-avatar kit-avatar-c">RS</span>
              <span className="kit-avatar kit-avatar-ghost">+4</span>
            </div>
            <span className="kit-avatar-meta">
              <span className="kit-avatar kit-avatar-a">EK<span className="kit-avatar-status is-on" /></span>
              <span>
                <div className="kit-avatar-meta-name">erik k.</div>
                <div className="kit-avatar-meta-role">admin · active now</div>
              </span>
            </span>
          </div>
        </div>
      </KitSection>

      <KitSection id="12" title="Dropdowns & tooltips">
        <div className="kit-subgroup">
          <div className="kit-subgroup-label">menu</div>
          <div className="kit-demo">
            <Dropdown
              trigger={<button className="btn btn-secondary">actions {I.chevDown}</button>}
              items={[
                { label: 'recent' },
                { icon: I.eye, text: 'view details', shortcut: '↵' },
                { icon: I.edit, text: 'rename', shortcut: 'E' },
                { icon: I.archive, text: 'archive', shortcut: 'A' },
                { sep: true },
                { icon: I.trash, text: 'delete', shortcut: '⌫', danger: true },
              ]}
              align="left"
            />
            <Dropdown
              trigger={<button className="btn btn-icon btn-secondary">{I.more}</button>}
              items={[
                { icon: I.link, text: 'copy link' },
                { icon: I.send, text: 'share' },
                { icon: I.download, text: 'export' },
              ]}
              align="left"
            />
          </div>
        </div>
        <div className="kit-subgroup">
          <div className="kit-subgroup-label">tooltip · 4 positions + with kbd</div>
          <div className="kit-demo" style={{ gap: 40, padding: '36px 24px' }}>
            <Tip text="hover · top" pos="top"><span className="badge">top</span></Tip>
            <Tip text="hover · bottom" pos="bottom"><span className="badge">bottom</span></Tip>
            <Tip text="hover · left" pos="left"><span className="badge">left</span></Tip>
            <Tip text="hover · right" pos="right"><span className="badge">right</span></Tip>
            <Tip text="dispatch task" pos="top" kbd="⌘⏎"><span className="badge badge-live"><span className="badge-dot" />with kbd</span></Tip>
          </div>
        </div>
      </KitSection>

      <KitSection id="13" title="Tags & chips">
        <div className="kit-subgroup">
          <div className="kit-subgroup-label">filter chips · counts · active</div>
          <div className="kit-demo">
            <div className="kit-chip-row">
              <span className="kit-chip is-active">all<span className="kit-chip-count">142</span></span>
              <span className="kit-chip">tests<span className="kit-chip-count">38</span></span>
              <span className="kit-chip">auth<span className="kit-chip-count">21</span></span>
              <span className="kit-chip">infra<span className="kit-chip-count">17</span></span>
              <span className="kit-chip">style<span className="kit-chip-count">11</span></span>
              <span className="kit-chip">deprecated<span className="kit-chip-count">4</span></span>
            </div>
          </div>
        </div>
        <div className="kit-subgroup">
          <div className="kit-subgroup-label">removable · selected · sub-pill</div>
          <div className="kit-demo">
            <div className="kit-chip-row">
              <span className="kit-chip is-active">typescript<span className="kit-chip-x">×</span></span>
              <span className="kit-chip is-active">auth<span className="kit-chip-x">×</span></span>
              <span className="kit-chip is-active">renewSession<span className="kit-chip-x">×</span></span>
            </div>
            <span className="kit-pill">new</span>
            <span className="kit-pill">beta</span>
            <span className="kit-pill">v4.1</span>
          </div>
        </div>
      </KitSection>

      <KitSection id="14" title="Tables">
        <div className="kit-subgroup-label">sortable · selected row · hover</div>
        <div style={{ background: 'var(--bg-1)', border: '1px solid var(--line)', borderRadius: 'var(--r-3)', padding: '4px 8px' }}>
          <table className="kit-tbl">
            <thead>
              <tr>
                <th style={{ width: 32 }}><input type="checkbox" className="check-box-inline" /></th>
                <th className="sort">name</th>
                <th>status</th>
                <th>tasks</th>
                <th>last activity</th>
                <th style={{ width: 40 }}></th>
              </tr>
            </thead>
            <tbody>
              <tr className="is-selected">
                <td><input type="checkbox" defaultChecked /></td>
                <td>repo/auth</td>
                <td><span className="badge badge-live"><span className="badge-dot badge-dot-pulse" />routing</span></td>
                <td className="mono">142</td>
                <td className="mono">12m ago</td>
                <td>{I.more}</td>
              </tr>
              <tr>
                <td><input type="checkbox" /></td>
                <td>repo/api</td>
                <td><span className="badge">idle</span></td>
                <td className="mono">38</td>
                <td className="mono">1h ago</td>
                <td>{I.more}</td>
              </tr>
              <tr>
                <td><input type="checkbox" /></td>
                <td>repo/web</td>
                <td><span className="badge badge-warn"><span className="badge-dot" />held</span></td>
                <td className="mono">17</td>
                <td className="mono">3h ago</td>
                <td>{I.more}</td>
              </tr>
              <tr>
                <td><input type="checkbox" /></td>
                <td>repo/cli</td>
                <td><span className="badge badge-info"><span className="badge-dot" />review</span></td>
                <td className="mono">9</td>
                <td className="mono">yesterday</td>
                <td>{I.more}</td>
              </tr>
            </tbody>
          </table>
        </div>
      </KitSection>

      <KitSection id="15" title="Lists & logs">
        <div className="kit-subgroup">
          <div className="kit-subgroup-label">key · value</div>
          <div className="kit-demo kit-demo-stack">
            <div className="kit-kv"><span className="kit-kv-k">model</span><span className="kit-kv-v">sonnet-4.5 <span className="mono">· $3 / mtok</span></span></div>
            <div className="kit-kv"><span className="kit-kv-k">fallback</span><span className="kit-kv-v">haiku-4.5 <span className="mono">· $0.80 / mtok</span></span></div>
            <div className="kit-kv"><span className="kit-kv-k">routing tag</span><span className="kit-kv-v"><code className="inline">tests-flaky</code></span></div>
            <div className="kit-kv"><span className="kit-kv-k">win rate</span><span className="kit-kv-v">89% <span className="mono">· n=412</span></span></div>
            <div className="kit-kv"><span className="kit-kv-k">last promoted</span><span className="kit-kv-v"><span className="mono">apr 29 · 14:22 utc</span></span></div>
          </div>
        </div>
        <div className="kit-subgroup">
          <div className="kit-subgroup-label">log stream</div>
          <div className="kit-log">
            <div className="kit-log-line"><span className="kit-log-time">14:22:01</span><span className="kit-log-lvl is-info">INFO</span><span className="kit-log-msg">dispatched <em>renewSession</em> → sonnet-4.5</span></div>
            <div className="kit-log-line"><span className="kit-log-time">14:22:03</span><span className="kit-log-lvl is-ok">OK</span><span className="kit-log-msg">patch landed in 1.8s · 3 files changed</span></div>
            <div className="kit-log-line"><span className="kit-log-time">14:22:07</span><span className="kit-log-lvl is-warn">WARN</span><span className="kit-log-msg">2/3 reviewers required · digest blocked</span></div>
            <div className="kit-log-line is-err"><span className="kit-log-time">14:22:14</span><span className="kit-log-lvl is-err">ERR</span><span className="kit-log-msg">opus rate-limited · falling back</span></div>
            <div className="kit-log-line"><span className="kit-log-time">14:22:18</span><span className="kit-log-lvl is-info">INFO</span><span className="kit-log-msg">pattern <em>rotateRefresh</em> promoted · won 89% of n=412</span></div>
          </div>
        </div>
      </KitSection>

      <KitSection id="16" title="Progress">
        <div className="kit-subgroup">
          <div className="kit-subgroup-label">linear · with label · sizes · states</div>
          <div className="kit-demo kit-demo-stack" style={{ gap: 14 }}>
            <KitProgress label="// patch applied" pct={64} />
            <KitProgress label="// uploading session.tar" pct={38} meta="3.2 / 8.4 MB" />
            <KitProgress label="// indexing repo" indeterminate meta="streaming…" />
            <KitProgress label="// digest signed" pct={100} state="ok" meta="ed25519 · verified" />
            <KitProgress label="// rate limit" pct={92} state="warn" meta="quota 92%" />
            <KitProgress label="// dispatch failed" pct={47} state="err" meta="3 retries · giving up" />
            <KitProgress size="sm" label="// thin variant" pct={56} />
          </div>
        </div>

        <div className="kit-subgroup">
          <div className="kit-subgroup-label">segmented · stacked</div>
          <div className="kit-demo kit-demo-stack" style={{ gap: 16 }}>
            <div>
              <div style={{ display: 'flex', justifyContent: 'space-between', fontFamily: 'var(--f-mono)', fontSize: 11, color: 'var(--fg-3)', marginBottom: 5 }}>
                <span>// route mix · this week</span><span>n=6,341 tasks</span>
              </div>
              <div className="kit-segbar">
                <i style={{ flex: 52, background: 'var(--accent)' }} />
                <i style={{ flex: 28, background: 'var(--info)' }} />
                <i style={{ flex: 14, background: 'var(--warn)' }} />
                <i style={{ flex: 6, background: 'var(--fg-4)' }} />
              </div>
              <div className="kit-segbar-legend">
                <span><i style={{ background: 'var(--accent)' }} />sonnet · 52%</span>
                <span><i style={{ background: 'var(--info)' }} />haiku · 28%</span>
                <span><i style={{ background: 'var(--warn)' }} />opus · 14%</span>
                <span><i style={{ background: 'var(--fg-4)' }} />gemini · 6%</span>
              </div>
            </div>
            <div>
              <div style={{ display: 'flex', justifyContent: 'space-between', fontFamily: 'var(--f-mono)', fontSize: 11, color: 'var(--fg-3)', marginBottom: 5 }}>
                <span>// quota used · 412 of 1,000 MTok</span><span>41% · resets may 1</span>
              </div>
              <div className="kit-segbar">
                <i style={{ flex: 41, background: 'var(--accent)' }} />
                <i style={{ flex: 59, background: 'var(--bg-3)' }} />
              </div>
            </div>
          </div>
        </div>

        <div className="kit-subgroup">
          <div className="kit-subgroup-label">ring · sizes · states · with delta</div>
          <div className="kit-demo" style={{ gap: 28, alignItems: 'flex-start' }}>
            <Ring pct={94} label="uptime" delta="+0.4 w/w" size={72} />
            <Ring pct={72} label="cache hit" />
            <Ring pct={38} label="quota" kind="warn" delta="−12 wow" />
            <Ring pct={12} label="errors" kind="err" />
            <Ring pct={56} label="signed" />
          </div>
        </div>

        <div className="kit-subgroup">
          <div className="kit-subgroup-label">milestone tracker</div>
          <div className="kit-demo" style={{ padding: '24px 28px' }}>
            <div className="kit-mstones">
              <div className="kit-mstone is-done">
                <span className="kit-mstone-dot">{I.check}</span>
                <div className="kit-mstone-lbl">received</div>
                <div className="kit-mstone-sub">14:22:01</div>
              </div>
              <div className="kit-mstone-line is-done" />
              <div className="kit-mstone is-done">
                <span className="kit-mstone-dot">{I.check}</span>
                <div className="kit-mstone-lbl">routed</div>
                <div className="kit-mstone-sub">sonnet-4.5</div>
              </div>
              <div className="kit-mstone-line is-active" />
              <div className="kit-mstone is-active">
                <span className="kit-mstone-dot is-pulse" />
                <div className="kit-mstone-lbl">applying</div>
                <div className="kit-mstone-sub">3 files · 1.8s</div>
              </div>
              <div className="kit-mstone-line" />
              <div className="kit-mstone">
                <span className="kit-mstone-dot" />
                <div className="kit-mstone-lbl">review</div>
                <div className="kit-mstone-sub">2/3 reviewers</div>
              </div>
              <div className="kit-mstone-line" />
              <div className="kit-mstone">
                <span className="kit-mstone-dot" />
                <div className="kit-mstone-lbl">shipped</div>
                <div className="kit-mstone-sub">est. 18:00</div>
              </div>
            </div>
          </div>
        </div>
      </KitSection>

      <KitSection id="17" title="Sparklines & micro charts">
        <div className="kit-demo" style={{ gap: 14 }}>
          <div className="kit-spark-card">
            <div className="kit-spark-card-lbl">// patches / day</div>
            <div className="kit-spark-card-num">847<em>+12%</em></div>
            <Spark points={[12,18,22,17,28,34,42,38,52,61,58,70]} />
          </div>
          <div className="kit-spark-card">
            <div className="kit-spark-card-lbl">// cost / patch</div>
            <div className="kit-spark-card-num">$0.41<em style={{ color: 'var(--err)' }}>-9%</em></div>
            <Spark points={[58,52,49,55,47,44,41,38,42,40,38,36]} kind="err" />
          </div>
          <div className="kit-spark-card">
            <div className="kit-spark-card-lbl">// held deliberations</div>
            <div className="kit-spark-card-num">2<em style={{ color: 'var(--warn)' }}>+1</em></div>
            <div className="kit-minibar">
              {[18,22,8,12,4,6,14,10,8,16,4,22].map((h, i) => (
                <i key={i} style={{ height: h, background: h > 14 ? 'var(--warn)' : 'var(--fg-3)' }} />
              ))}
            </div>
          </div>
        </div>
      </KitSection>

      <KitSection id="18" title="Code & terminal">
        <div className="kit-subgroup">
          <div className="kit-subgroup-label">inline · block</div>
          <div className="kit-demo kit-demo-stack" style={{ gap: 14 }}>
            <div style={{ color: 'var(--fg-2)', fontSize: 13 }}>
              install with <code className="inline">npx 0dai init</code> and add to <code className="inline">~/.0dai/patterns/</code>
            </div>
            <div className="kit-code-wrap">
              <pre><span className="com">{`// rotateRefresh.ts · promoted apr 29
`}</span><span className="kw">export async function</span>{` renewSession(token: `}<span className="kw">string</span>{`) {
  `}<span className="kw">return</span>{` mutex.run(token, `}<span className="kw">async</span>{` () => {
    `}<span className="kw">if</span>{` (cache.has(token)) `}<span className="kw">return</span>{` cache.get(token);
    `}<span className="kw">const</span>{` fresh = `}<span className="kw">await</span>{` api.refresh(token);
    cache.set(token, fresh, `}<span className="str">{'\'5m\''}</span>{`);
    `}<span className="kw">return</span>{` fresh;
  });
}`}</pre>
              <button className="kit-code-copy">copy</button>
            </div>
          </div>
        </div>
        <div className="kit-subgroup">
          <div className="kit-subgroup-label">terminal</div>
          <div className="kit-term">
            <div><span className="kit-term-prompt">$</span> <span className="kit-term-path">~/repo/auth</span> 0dai dispatch <span className="kit-term-comment"># renewSession race</span></div>
            <div className="kit-term-out">→ routing tag: <span style={{ color: 'var(--accent)' }}>tests-flaky</span> · model: sonnet-4.5</div>
            <div className="kit-term-out">→ patch applied in 1.8s · 3 files changed</div>
            <div className="kit-term-out">→ won 89% of n=412 · promoted to rotateRefresh</div>
            <div><span className="kit-term-prompt">$</span> <span className="kit-term-cursor" /></div>
          </div>
        </div>
      </KitSection>

      <KitSection id="19" title="Tree / file list">
        <div className="kit-tree" style={{ maxWidth: 420 }}>
          <div className="kit-tree-row"><span className="kit-tree-indent">▾</span><span className="kit-tree-ico">{I.repos}</span>repo/auth<span className="kit-tree-meta">142</span></div>
          <div className="kit-tree-row"><span className="kit-tree-indent" /><span className="kit-tree-indent">▾</span><span className="kit-tree-ico">{I.doc}</span>src<span className="kit-tree-meta">38</span></div>
          <div className="kit-tree-row is-active"><span className="kit-tree-indent" /><span className="kit-tree-indent" /><span className="kit-tree-indent">›</span><span className="kit-tree-ico">{I.doc}</span>renewSession.ts<span className="kit-tree-meta">+24 -18</span></div>
          <div className="kit-tree-row"><span className="kit-tree-indent" /><span className="kit-tree-indent" /><span className="kit-tree-indent">›</span><span className="kit-tree-ico">{I.doc}</span>session.test.ts</div>
          <div className="kit-tree-row"><span className="kit-tree-indent" /><span className="kit-tree-indent" /><span className="kit-tree-indent">›</span><span className="kit-tree-ico">{I.doc}</span>cache.ts</div>
          <div className="kit-tree-row"><span className="kit-tree-indent" /><span className="kit-tree-indent">›</span><span className="kit-tree-ico">{I.archive}</span>patterns<span className="kit-tree-meta">17</span></div>
          <div className="kit-tree-row"><span className="kit-tree-indent" /><span className="kit-tree-indent">›</span><span className="kit-tree-ico">{I.doc}</span>README.md</div>
        </div>
      </KitSection>

      <KitSection id="20" title="Banners">
        <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
          <div className="kit-banner is-accent">
            <span className="kit-banner-ico">{I.zap}</span>
            <div className="kit-banner-body">
              <strong>v4.1.0 shipped</strong>
              <span className="kit-banner-sub">// session roaming · ed25519 keys · 4 new MCP tools</span>
            </div>
            <div className="kit-banner-actions">
              <button className="btn btn-sm btn-ghost">read changelog</button>
              <span className="kit-banner-x">×</span>
            </div>
          </div>
          <div className="kit-banner is-info">
            <span className="kit-banner-ico">{I.info}</span>
            <div className="kit-banner-body">
              <strong>sign-off window opens thursday</strong>
              <span className="kit-banner-sub">// 2 reviewers required before the w18 digest auto-ships</span>
            </div>
            <div className="kit-banner-actions">
              <button className="btn btn-sm btn-secondary">queue review</button>
              <span className="kit-banner-x">×</span>
            </div>
          </div>
          <div className="kit-banner is-warn">
            <span className="kit-banner-ico">{I.warn}</span>
            <div className="kit-banner-body">
              <strong>quota at 38%</strong>
              <span className="kit-banner-sub">// est. 11d remaining on current plan</span>
            </div>
            <div className="kit-banner-actions">
              <button className="btn btn-sm btn-secondary">top up</button>
              <span className="kit-banner-x">×</span>
            </div>
          </div>
        </div>
      </KitSection>

      <KitSection id="21" title="Skeletons & loaders">
        <div className="kit-subgroup">
          <div className="kit-subgroup-label">row · line · circle</div>
          <div className="kit-demo kit-demo-stack" style={{ gap: 14, padding: 18 }}>
            <SkeletonRow lines={2} />
            <SkeletonRow lines={3} />
            <SkeletonRow avatar={false} lines={1} />
          </div>
        </div>
        <div className="kit-subgroup">
          <div className="kit-subgroup-label">spinner · stepper</div>
          <div className="kit-demo">
            <span className="spinner" style={{ width: 18, height: 18, border: '2px solid var(--bg-3)', borderTopColor: 'var(--accent)', borderRadius: '50%', display: 'inline-block', animation: 'spin 0.8s linear infinite' }} />
            <span style={{ fontFamily: 'var(--f-mono)', fontSize: 11, color: 'var(--fg-3)' }}>dispatching…</span>
            <div style={{ flex: 1, minWidth: 320 }}>
              <Stepper current={1} steps={['received', 'routed', 'applied', 'reviewed']} />
            </div>
          </div>
        </div>
      </KitSection>

      <KitSection id="22" title="Tokens · radius / shadow / motion">
        <div className="kit-subgroup">
          <div className="kit-subgroup-label">radius</div>
          <div className="kit-token-row">
            {[['r-1','4px'],['r-2','6px'],['r-3','8px'],['r-4','12px'],['r-5','16px']].map(([n,v]) => (
              <div key={n} className="kit-token">
                <div className="kit-token-radius-demo" style={{ borderRadius: `var(--${n})` }} />
                <div className="kit-token-name">{n}</div>
                <div className="kit-token-val">{v}</div>
              </div>
            ))}
          </div>
        </div>
        <div className="kit-subgroup">
          <div className="kit-subgroup-label">shadow</div>
          <div className="kit-token-row">
            {[['sh-1','popover'],['sh-2','card'],['sh-3','modal'],['sh-4','overlay'],['none','flat']].map(([n,l]) => (
              <div key={n} className="kit-token" style={{ background: 'var(--bg)' }}>
                <div className="kit-token-shadow-demo" style={{ boxShadow: n === 'none' ? 'none' : `var(--${n})`, border: n === 'none' ? '1px solid var(--line)' : '1px solid var(--line)' }} />
                <div className="kit-token-name">{n}</div>
                <div className="kit-token-val">{l}</div>
              </div>
            ))}
          </div>
        </div>
        <div className="kit-subgroup">
          <div className="kit-subgroup-label">motion · easing</div>
          <div className="kit-token-row">
            {[['linear','t · 1.6s'],['ease','default'],['ease-in-out','symmetric'],['out-quint','exit'],['back-out','overshoot']].map(([n,l]) => (
              <div key={n} className="kit-token">
                <div className="kit-token-motion-demo" />
                <div className="kit-token-name">{n}</div>
                <div className="kit-token-val">{l}</div>
              </div>
            ))}
          </div>
        </div>
      </KitSection>

      <KitSection id="23" title="Iconography">
        <div className="kit-icons">
          {Object.entries(I).map(([name, node]) => (
            <figure key={name}>
              {React.cloneElement(node, { size: 18 })}
              <figcaption>{name}</figcaption>
            </figure>
          ))}
        </div>
      </KitSection>

      {modalOpen && (
        <div className="modal-back" onClick={() => setModalOpen(false)}>
          <div className="modal" onClick={(e) => e.stopPropagation()}>
            <div className="modal-head">
              <div style={{ flex: 1 }}>
                <h3 className="modal-title">example modal</h3>
                <div className="modal-sub">// pattern used for confirmations, forms, lightweight flows</div>
              </div>
              <span className="modal-close" onClick={() => setModalOpen(false)}>{I.x}</span>
            </div>
            <div className="modal-body">a modal sits over the page with a backdrop. esc closes it. focus is trapped inside.</div>
            <div className="modal-foot">
              <button className="btn btn-ghost" onClick={() => setModalOpen(false)}>cancel</button>
              <button className="btn btn-primary" onClick={() => setModalOpen(false)}>confirm</button>
            </div>
          </div>
        </div>
      )}
    </>
  );
}

function Spark({ points, kind }) {
  const max = Math.max(...points), min = Math.min(...points), span = max - min || 1;
  const w = 120, h = 32;
  const xs = points.map((_, i) => (i / (points.length - 1)) * w);
  const ys = points.map((p) => h - ((p - min) / span) * (h - 4) - 2);
  const path = xs.map((x, i) => `${i === 0 ? 'M' : 'L'}${x.toFixed(1)} ${ys[i].toFixed(1)}`).join(' ');
  const area = `${path} L${w} ${h} L0 ${h} Z`;
  return (
    <svg className={`kit-spark ${kind === 'err' ? 'kit-spark-err' : kind === 'warn' ? 'kit-spark-warn' : ''}`} viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none">
      <path className="kit-spark-area" d={area} />
      <path d={path} />
      <circle className="kit-spark-dot" cx={xs[xs.length - 1]} cy={ys[ys.length - 1]} r="2" />
    </svg>
  );
}

function Ring({ pct, label, kind, size = 56, delta }) {
  const stroke = size >= 72 ? 6 : 5;
  const r = size / 2 - stroke / 2 - 1;
  const c = 2 * Math.PI * r;
  const numSize = Math.round(size * 0.34);
  return (
    <div className="kit-ring-wrap">
      <div className="kit-ring" style={{ width: size, height: size }}>
        <svg width={size} height={size}>
          <circle className="kit-ring-track" cx={size / 2} cy={size / 2} r={r} strokeWidth={stroke} />
          <circle
            className={`kit-ring-fill ${kind === 'warn' ? 'is-warn' : kind === 'err' ? 'is-err' : ''}`}
            cx={size / 2} cy={size / 2} r={r} strokeWidth={stroke}
            strokeDasharray={c} strokeDashoffset={c * (1 - pct / 100)}
          />
        </svg>
        <div className="kit-ring-text" style={{ fontSize: numSize }}>
          <span className="kit-ring-num">{pct}</span><span className="kit-ring-pct">%</span>
        </div>
      </div>
      <div className="kit-ring-lbl">{label}</div>
      {delta ? (
        <div className={`kit-ring-delta ${delta.trim().startsWith('+') ? 'is-up' : 'is-down'}`}>{delta}</div>
      ) : null}
    </div>
  );
}

function KitProgress({ label, pct = 0, indeterminate, meta, state, size }) {
  const p = Math.max(0, Math.min(100, pct));
  return (
    <div className={`kit-prog ${size === 'sm' ? 'is-sm' : ''} ${state ? 'is-' + state : ''}`}>
      <div className="kit-prog-head">
        <span className="kit-prog-lbl">{label}</span>
        <span className="kit-prog-meta">{meta ?? (indeterminate ? 'streaming…' : `${p}%`)}</span>
      </div>
      <div className={`kit-prog-track ${indeterminate ? 'is-indet' : ''}`}>
        {indeterminate
          ? <div className="kit-prog-bar-indet" />
          : <div className="kit-prog-bar" style={{ width: p + '%' }} />}
      </div>
    </div>
  );
}

function KitSection({ id, title, children }) {
  return (
    <div className="kit-section">
      <div className="kit-section-head">
        <span className="kit-section-id">// {id}</span>
        <h2 className="kit-section-title">{title}</h2>
      </div>
      {children}
    </div>
  );
}

// ───────────────────────────────────────────────────────────────
// Page: Patterns (graph + table hybrid)
// ───────────────────────────────────────────────────────────────
function PagePatterns() {
  return (
    <>
      <div className="page-head">
        <div className="page-head-left">
          <div className="page-kicker">// patterns · 142 captured · 17 promoted to network</div>
          <h1 className="page-title">pattern library</h1>
          <p className="page-sub">what your agents have learned across all repos. promoted patterns ship in friday digests.</p>
        </div>
        <div className="page-actions">
          <div className="seg"><span className="seg-opt is-active">graph</span><span className="seg-opt">list</span></div>
          <button className="btn btn-primary"><span>{I.plus}</span>capture pattern</button>
        </div>
      </div>

      <div className="card">
        <div className="card-head">
          <div className="card-head-title">// pattern graph · 142 nodes</div>
          <div className="card-head-actions">
            <div className="pill-tabs"><span className="pill-tab is-active">all</span><span className="pill-tab">promoted</span><span className="pill-tab">anti</span></div>
            <button className="btn btn-ghost btn-sm">reset zoom</button>
          </div>
        </div>
        <div className="card-body" style={{ padding: 0, background: 'var(--bg)', position: 'relative', height: 420, overflow: 'hidden', borderTop: '1px solid var(--line)' }}>
          <PatternGraph />
        </div>
        <div className="card-foot">
          <span>// hover a node for detail · drag to pan</span>
          <span style={{ marginLeft: 'auto' }}>4 promoted this week · 2 flagged as anti</span>
        </div>
      </div>
    </>
  );
}

function PatternGraph() {
  // Decorative SVG graph
  const nodes = [
    { x: 200, y: 120, r: 14, label: 'rotateRefresh', kind: 'pro' },
    { x: 380, y: 80, r: 9, label: 'staged-flag', kind: 'pro' },
    { x: 540, y: 160, r: 12, label: 'jest-30-config', kind: 'anti' },
    { x: 700, y: 100, r: 10, label: 'rsc-migration', kind: 'pro' },
    { x: 320, y: 240, r: 8, label: 'oauth-pkce', kind: 'neu' },
    { x: 480, y: 290, r: 11, label: 'session-stickiness', kind: 'anti' },
    { x: 620, y: 240, r: 9, label: 'retry-with-jitter', kind: 'pro' },
    { x: 180, y: 320, r: 7, label: 'lockfile-merge', kind: 'neu' },
    { x: 760, y: 320, r: 8, label: 'cve-2026-0411', kind: 'pro' },
  ];
  const edges = [[0,1],[1,2],[2,3],[0,4],[4,5],[5,6],[3,6],[4,7],[6,8],[2,5]];
  function color(k) { return k === 'pro' ? 'var(--accent)' : k === 'anti' ? 'var(--err)' : 'var(--fg-3)'; }
  return (
    <svg width="100%" height="100%" viewBox="0 0 900 420" style={{ position: 'absolute', inset: 0 }}>
      <defs>
        <radialGradient id="bgg" cx="50%" cy="50%">
          <stop offset="0%" stopColor="rgba(123,211,137,0.06)" />
          <stop offset="100%" stopColor="rgba(0,0,0,0)" />
        </radialGradient>
      </defs>
      <rect width="900" height="420" fill="url(#bgg)" />
      {edges.map(([a, b], i) => (
        <line key={i} x1={nodes[a].x} y1={nodes[a].y} x2={nodes[b].x} y2={nodes[b].y} stroke="var(--line-3)" strokeWidth="1" opacity="0.6" />
      ))}
      {nodes.map((n, i) => (
        <g key={i}>
          <circle cx={n.x} cy={n.y} r={n.r + 6} fill={color(n.kind)} opacity="0.08" />
          <circle cx={n.x} cy={n.y} r={n.r} fill={color(n.kind)} opacity="0.85" />
          <text x={n.x} y={n.y + n.r + 14} fill="var(--fg-2)" fontSize="11" fontFamily="var(--f-mono)" textAnchor="middle">{n.label}</text>
        </g>
      ))}
    </svg>
  );
}

// ───────────────────────────────────────────────────────────────
// Page: Team
// ───────────────────────────────────────────────────────────────
function PageTeam() {
  const members = [
    { name: 'Erik K.',     email: 'erik@dev.team',    role: 'admin',  last: 'now',    tasks: 142 },
    { name: 'Maya R.',     email: 'maya@dev.team',    role: 'editor', last: '12m',    tasks: 87 },
    { name: 'Tom P.',      email: 'tom@dev.team',     role: 'editor', last: '1h',     tasks: 64 },
    { name: 'Lina S.',     email: 'lina@dev.team',    role: 'viewer', last: '2d',     tasks: 0 },
    { name: 'pending',     email: 'sam@dev.team',     role: 'invite', last: 'never',  tasks: 0 },
  ];
  return (
    <>
      <div className="page-head">
        <div className="page-head-left">
          <div className="page-kicker">// team · 4 active · 1 invite pending · pro plan</div>
          <h1 className="page-title">team</h1>
        </div>
        <div className="page-actions">
          <button className="btn btn-primary"><span>{I.plus}</span>invite member</button>
        </div>
      </div>
      <div className="tbl-wrap">
        <table className="tbl">
          <thead><tr><th>member</th><th>role</th><th>tasks · 7d</th><th>last seen</th><th></th></tr></thead>
          <tbody>
            {members.map((m, i) => (
              <tr key={i}>
                <td>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
                    <div className="avatar" style={{ width: 28, height: 28, fontSize: 10 }}>{m.name.slice(0,2).toUpperCase()}</div>
                    <div>
                      <div className="tbl-row-primary">{m.name}</div>
                      <div className="tbl-row-mono" style={{ fontSize: 11 }}>{m.email}</div>
                    </div>
                  </div>
                </td>
                <td><span className={`badge ${m.role === 'admin' ? 'badge-live' : m.role === 'invite' ? 'badge-warn' : ''}`}>{m.role}</span></td>
                <td className="tbl-row-mono">{m.tasks}</td>
                <td className="tbl-row-mono">{m.last}</td>
                <td><button className="btn btn-icon btn-ghost btn-sm">{I.more}</button></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </>
  );
}

// ───────────────────────────────────────────────────────────────
// Page: Routing
// ───────────────────────────────────────────────────────────────
function PageRouting() {
  const routes = [
    { tag: 'tests-flaky', model: 'opus-4.1',    fallback: 'sonnet-4.5', winRate: 89, cost: '$0.08', n: 412 },
    { tag: 'auth',        model: 'opus-4.1',    fallback: 'sonnet-4.5', winRate: 91, cost: '$0.11', n: 287 },
    { tag: 'docs',        model: 'haiku-4.5',   fallback: 'sonnet-4.5', winRate: 78, cost: '$0.02', n: 156 },
    { tag: 'migration',   model: 'sonnet-4.5',  fallback: 'opus-4.1',   winRate: 84, cost: '$0.07', n: 198 },
    { tag: 'qa',          model: 'gemini-2',    fallback: 'sonnet-4.5', winRate: 76, cost: '$0.04', n: 89 },
    { tag: 'refactor',    model: 'opus-4.1',    fallback: 'sonnet-4.5', winRate: 82, cost: '$0.12', n: 67 },
  ];
  return (
    <>
      <div className="page-head">
        <div className="page-head-left">
          <div className="page-kicker">// routing · 6 active rules · rebalanced 3h ago</div>
          <h1 className="page-title">routing rules</h1>
          <p className="page-sub">which model handles which task type. updated automatically from network win-rates · override per-repo in <code className="mono" style={{ background: 'var(--bg-3)', padding: '1px 5px', borderRadius: 3 }}>.0dai/routing.toml</code>.</p>
        </div>
        <div className="page-actions">
          <button className="btn btn-secondary">export config</button>
          <button className="btn btn-primary"><span>{I.plus}</span>add rule</button>
        </div>
      </div>
      <div className="tbl-wrap">
        <table className="tbl">
          <thead><tr><th>tag</th><th>primary model</th><th>fallback</th><th>win rate</th><th>avg cost</th><th>n · 7d</th><th></th></tr></thead>
          <tbody>
            {routes.map((r, i) => (
              <tr key={i}>
                <td><span className="badge badge-square badge-live">tag:{r.tag}</span></td>
                <td><span className="tbl-row-primary mono">{r.model}</span></td>
                <td className="tbl-row-mono">{r.fallback}</td>
                <td>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                    <div className="progress" style={{ width: 80 }}><div className="progress-fill" style={{ width: `${r.winRate}%` }} /></div>
                    <span className="mono" style={{ fontSize: 11 }}>{r.winRate}%</span>
                  </div>
                </td>
                <td className="tbl-row-mono">{r.cost}</td>
                <td className="tbl-row-mono">{r.n}</td>
                <td><button className="btn btn-icon btn-ghost btn-sm">{I.edit}</button></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </>
  );
}

// ───────────────────────────────────────────────────────────────
// Page: Activity (full feed)
// ───────────────────────────────────────────────────────────────
function PageActivity() {
  const groups = [
    { d: 'today · apr 29', items: [
      { t: '09:34', m: '✓', kind: 'is-ok',   text: <>pattern <span className="feed-mono">rotateRefresh</span> promoted</>, who: 'erik' },
      { t: '09:22', m: '·',                  text: '2-of-3 consensus reached on jest-30 migration', who: '0dai' },
      { t: '09:14', m: '⚠', kind: 'is-warn', text: 'opus rate-limited · falling back to sonnet-4.5', who: '0dai' },
      { t: '08:51', m: '·',                  text: 'routing rebalanced — tests-flaky now defaults to opus', who: '0dai' },
      { t: '08:40', m: '✗', kind: 'is-err',  text: 'patch held · race condition surfaced', who: '0dai' },
    ]},
    { d: 'yesterday · apr 28', items: [
      { t: '18:22', m: '·',                  text: 'w17 digest archived · 4 patterns shipped', who: 'erik' },
      { t: '14:10', m: '✓', kind: 'is-ok',   text: 'repo/payments synced · +3 patterns', who: '0dai' },
      { t: '11:04', m: '·',                  text: 'maya invited to workspace', who: 'erik' },
    ]},
    { d: 'apr 27', items: [
      { t: '22:00', m: '✓', kind: 'is-ok',   text: 'w17 digest signed by 2 reviewers', who: 'tom' },
      { t: '21:14', m: '·',                  text: 'maya signed off on item #3', who: 'maya' },
    ]},
  ];
  return (
    <>
      <div className="page-head">
        <div className="page-head-left">
          <div className="page-kicker">// activity · everything that happened</div>
          <h1 className="page-title">activity feed</h1>
        </div>
        <div className="page-actions">
          <div className="seg"><span className="seg-opt is-active">all</span><span className="seg-opt">human</span><span className="seg-opt">agent</span></div>
        </div>
      </div>
      <div className="card">
        <div className="card-body">
          {groups.map((g, gi) => (
            <div key={gi} style={{ marginBottom: 28 }}>
              <div className="mono" style={{ fontSize: 11, color: 'var(--fg-4)', marginBottom: 8, paddingBottom: 6, borderBottom: '1px dashed var(--line)' }}>// {g.d}</div>
              <div className="feed">
                {g.items.map((a, i) => (
                  <div key={i} className="feed-item">
                    <span className="feed-time">{a.t}</span>
                    <span className={`feed-marker ${a.kind || ''}`}>{a.m}</span>
                    <span className="feed-text"><span className="feed-strong" style={{ color: 'var(--accent)' }}>@{a.who}</span> · {a.text}</span>
                  </div>
                ))}
              </div>
            </div>
          ))}
        </div>
      </div>
    </>
  );
}

// ───────────────────────────────────────────────────────────────
// Command palette
// ───────────────────────────────────────────────────────────────
function CmdPalette({ open, onClose, setPage }) {
  const [q, setQ] = useState('');
  const [idx, setIdx] = useState(0);
  const inputRef = useRef(null);

  const items = useMemo(() => [
    { section: 'navigate', label: 'go to dashboard',   icon: I.home, do: () => setPage('dashboard') },
    { section: 'navigate', label: 'go to repos',       icon: I.repos, do: () => setPage('repos') },
    { section: 'navigate', label: 'go to patterns',    icon: I.patterns, do: () => setPage('patterns') },
    { section: 'navigate', label: 'go to bulletins',   icon: I.bullets, do: () => setPage('bulletins') },
    { section: 'navigate', label: 'go to routing',     icon: I.routing, do: () => setPage('routing') },
    { section: 'navigate', label: 'go to settings',    icon: I.settings, do: () => setPage('settings') },
    { section: 'actions',  label: 'dispatch task…',    icon: I.zap, shortcut: '⌘⏎', do: () => {} },
    { section: 'actions',  label: 'compose bulletin',  icon: I.edit, do: () => setPage('bulletins') },
    { section: 'actions',  label: 'invite member',     icon: I.plus, do: () => setPage('team') },
    { section: 'actions',  label: 'run doctor',        icon: I.check, do: () => {} },
    { section: 'jump',     label: 'repo/auth',         icon: I.repos, do: () => setPage('repos') },
    { section: 'jump',     label: 'repo/payments',     icon: I.repos, do: () => setPage('repos') },
  ], [setPage]);

  const filtered = useMemo(() => q ? items.filter((i) => i.label.toLowerCase().includes(q.toLowerCase())) : items, [q, items]);

  useEffect(() => {
    if (open) setTimeout(() => inputRef.current?.focus(), 50);
    if (open) { setQ(''); setIdx(0); }
  }, [open]);

  useEffect(() => { setIdx(0); }, [q]);

  function onKey(e) {
    if (e.key === 'ArrowDown') { e.preventDefault(); setIdx((i) => Math.min(i + 1, filtered.length - 1)); }
    else if (e.key === 'ArrowUp') { e.preventDefault(); setIdx((i) => Math.max(i - 1, 0)); }
    else if (e.key === 'Enter') { filtered[idx]?.do(); onClose(); }
    else if (e.key === 'Escape') onClose();
  }

  if (!open) return null;
  let lastSection = '';
  return (
    <div className="modal-back" onClick={onClose}>
      <div className="cmdp" onClick={(e) => e.stopPropagation()}>
        <div className="cmdp-input-wrap">
          <span className="cmdp-input-ico">{I.search}</span>
          <input ref={inputRef} className="cmdp-input" placeholder="search · jump · run a command…" value={q} onChange={(e) => setQ(e.target.value)} onKeyDown={onKey} />
          <span className="cmdk-kbd">esc</span>
        </div>
        <div className="cmdp-list">
          {filtered.length === 0 ? (
            <div style={{ padding: 32, textAlign: 'center', color: 'var(--fg-3)', fontSize: 13 }}>no results for "{q}"</div>
          ) : filtered.map((it, i) => {
            const showSection = it.section !== lastSection;
            lastSection = it.section;
            return (
              <React.Fragment key={i}>
                {showSection ? <div className="cmdp-section-label">// {it.section}</div> : null}
                <div className={`cmdp-item ${idx === i ? 'is-active' : ''}`} onMouseEnter={() => setIdx(i)} onClick={() => { it.do(); onClose(); }}>
                  <span className="cmdp-item-ico">{it.icon}</span>
                  <span className="cmdp-item-label">{it.label}</span>
                  {it.shortcut ? <span className="cmdp-item-shortcut">{it.shortcut}</span> : null}
                </div>
              </React.Fragment>
            );
          })}
        </div>
        <div className="cmdp-foot">
          <span className="cmdp-foot-key"><span className="cmdp-foot-kbd">↑↓</span> navigate</span>
          <span className="cmdp-foot-key"><span className="cmdp-foot-kbd">⏎</span> select</span>
          <span className="cmdp-foot-key"><span className="cmdp-foot-kbd">esc</span> close</span>
        </div>
      </div>
    </div>
  );
}

// ───────────────────────────────────────────────────────────────
// App
// ───────────────────────────────────────────────────────────────
function App() {
  const initialPage = new URLSearchParams(window.location.search).get('page') || 'kit';
  const [page, setPage] = useState(initialPage);
  const [collapsed, setCollapsed] = useState(false);
  const [drawer, setDrawer] = useState(null);
  const [cmd, setCmd] = useState(false);
  const [help, setHelp] = useState(false);
  const [env, setEnv] = useState('prod');

  useEffect(() => {
    function onKey(e) {
      const tag = e.target?.tagName;
      const inField = tag === 'INPUT' || tag === 'TEXTAREA';
      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') { e.preventDefault(); setCmd(true); }
      else if (e.key === '?' && !inField) { e.preventDefault(); setHelp(true); }
      else if (e.key === 'Escape') { setCmd(false); setDrawer(null); setHelp(false); }
    }
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, []);

  const titleByPage = {
    dashboard: 'dashboard',
    repos: 'repos',
    patterns: 'patterns',
    routing: 'routing',
    bulletins: 'bulletins',
    activity: 'activity',
    team: 'team',
    billing: 'billing',
    settings: 'settings',
    kit: 'kit reference',
  };
  const crumbs = ['acme-engineering', titleByPage[page] || page];

  let Body;
  if (page === 'dashboard') Body = <PageDashboard />;
  else if (page === 'repos') Body = <PageRepos openDrawer={setDrawer} />;
  else if (page === 'patterns') Body = <PagePatterns />;
  else if (page === 'routing') Body = <PageRouting />;
  else if (page === 'bulletins') Body = <PageBulletins />;
  else if (page === 'activity') Body = <PageActivity />;
  else if (page === 'team') Body = <PageTeam />;
  else if (page === 'billing') Body = <PageBilling />;
  else if (page === 'deliberation') Body = <PageDeliberation />;
  else if (page === 'keys') Body = <PageKeys />;
  else if (page === 'audit') Body = <PageAudit />;
  else if (page === 'onboarding') Body = <PageOnboarding />;
  else if (page === 'settings') Body = <PageSettings />;
  else if (page === 'kit') Body = <PageKit />;
  else Body = <PageDashboard />;

  return (
    <ToastProvider>
      <div className={`shell ${collapsed ? 'is-collapsed' : ''}`}>
        <Sidebar page={page} setPage={setPage} collapsed={collapsed} />
        <Topbar crumbs={crumbs} onCollapse={() => setCollapsed((c) => !c)} onCmdK={() => setCmd(true)} env={env} setEnv={setEnv} onHelp={() => setHelp(true)} />
        <main className="main">{Body}</main>
      </div>
      <RepoDrawer repo={drawer} onClose={() => setDrawer(null)} />
      <CmdPalette open={cmd} onClose={() => setCmd(false)} setPage={setPage} />
      <ShortcutHelp open={help} onClose={() => setHelp(false)} />
    </ToastProvider>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
