// Shell: Sidebar + Topbar + Dice overlay.

const NAV_SECTIONS = [
  {
    label: 'Кампанія',
    items: [
      { id: 'campaign', label: 'Про кампанію', icon: 'rune', shortcut: '1' },
      { id: 'notes',    label: 'Журнал',       icon: 'book', shortcut: '2' },
    ],
  },
  {
    label: 'Лист персонажа',
    items: [
      { id: 'character', label: 'Персонаж', icon: 'character', shortcut: '3' },
      { id: 'combat',    label: 'Бій',      icon: 'sword',     shortcut: '4', hot: true },
      { id: 'skills',    label: 'Навички',  icon: 'skill',     shortcut: '5' },
      { id: 'spells',    label: 'Магія',    icon: 'spell',     shortcut: '6' },
      { id: 'inventory', label: 'Інвентар', icon: 'bag',       shortcut: '7' },
      { id: 'features',  label: 'Риси',     icon: 'star',      shortcut: '8' },
    ],
  },
];

const NAV_ADMIN_ITEM = { id: 'admin', label: 'Адмін', icon: 'gear' };

// ============== SIDEBAR ==============
const CharacterSwitcher = ({ characters, activeId, onSwitchCharacter, onAddCharacter, onDuplicateCharacter, onDeleteCharacter, canDeleteChar }) => {
  const [open, setOpen] = useState(false);
  const wrapRef = useRef(null);
  const ch = characters.find(c => c.id === activeId) || characters[0];

  useEffect(() => {
    if (!open) return;
    const onClick = (e) => { if (!wrapRef.current?.contains(e.target)) setOpen(false); };
    window.addEventListener('mousedown', onClick);
    return () => window.removeEventListener('mousedown', onClick);
  }, [open]);

  // Якщо тільки 1 персонаж і не можна додавати — без дропдауну
  const canOpen = characters.length > 1 || !!onAddCharacter;

  if (!ch) return null;

  return (
    <div className="char-switcher" ref={wrapRef}>
      <div className="character-pill" onClick={() => canOpen && setOpen(v => !v)}
        style={{ cursor: canOpen ? 'pointer' : 'default' }}>
        <div className="portrait">
          {ch.portrait
            ? <img src={ch.portrait} alt={ch.name} style={{ width: '100%', height: '100%', objectFit: 'cover' }}/>
            : ch.name.split(' ').map(p => p[0]).slice(0, 2).join('')
          }
        </div>
        <div className="igrow" style={{ minWidth: 0 }}>
          <div className="name" style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{ch.name}</div>
          <div className="meta">lvl {ch.level} · {ch.klass.toLowerCase()}</div>
        </div>
        {canOpen && (
          <Icon name="chevronD" size={12} style={{ color: 'var(--ink-3)', transform: open ? 'rotate(180deg)' : 'none', transition: 'transform 0.2s' }}/>
        )}
      </div>

      {open && canOpen && (
        <div className="char-dropdown fade-in">
          <div className="char-dropdown-head">
            <span className="caps mono" style={{ fontSize: 9, color: 'var(--ink-3)' }}>персонажі</span>
            <span className="mono" style={{ fontSize: 10, color: 'var(--ink-3)' }}>{characters.length}</span>
          </div>
          {characters.map(c => (
            <div key={c.id} className={`char-row ${c.id === activeId ? 'active' : ''}`}>
              <div className="char-row-main" onClick={() => { onSwitchCharacter(c.id); setOpen(false); }}>
                <div className="char-row-portrait">
                  {c.portrait
                    ? <img src={c.portrait} alt={c.name}/>
                    : <span>{c.name.split(' ').map(p => p[0]).slice(0, 2).join('')}</span>
                  }
                </div>
                <div className="igrow" style={{ minWidth: 0 }}>
                  <div className="char-row-name">{c.name}</div>
                  <div className="char-row-meta">
                    <span>lvl {c.level}</span>
                    <span>·</span>
                    <span>{c.klass}</span>
                    <span>·</span>
                    <span className={c.hp / c.hpMax < 0.3 ? 'crimson' : ''}>{c.hp}/{c.hpMax} hp</span>
                  </div>
                </div>
                {c.id === activeId && <Icon name="check" size={12} style={{ color: 'var(--gold-1)' }}/>}
              </div>
              {/* Видалення — тільки якщо є дозвіл */}
              {onDeleteCharacter && characters.length > 1 && (!canDeleteChar || canDeleteChar(c.id)) && (
                <button className="char-row-del" onClick={(e) => { e.stopPropagation(); onDeleteCharacter(c.id); }} title="Видалити">
                  <Icon name="trash" size={11}/>
                </button>
              )}
            </div>
          ))}
          {(onAddCharacter || onDuplicateCharacter) && (
            <div className="char-dropdown-actions">
              {onAddCharacter && (
                <button className="char-action" onClick={() => { onAddCharacter(); setOpen(false); }}>
                  <Icon name="plus" size={12}/>
                  <span>Новий персонаж</span>
                </button>
              )}
              {onDuplicateCharacter && (
                <button className="char-action" onClick={() => { onDuplicateCharacter(); setOpen(false); }}>
                  <Icon name="save" size={12}/>
                  <span>Дублювати поточного</span>
                </button>
              )}
            </div>
          )}
        </div>
      )}
    </div>
  );
};

const OnlineDot = ({ name, role }) => (
  <div title={`${name} (${role}) онлайн`}
    style={{ display: 'flex', alignItems: 'center', gap: 5, fontSize: 10,
      fontFamily: 'var(--font-mono)', color: 'var(--ink-2)' }}>
    <span style={{ width: 7, height: 7, borderRadius: '50%',
      background: '#4ae04a', boxShadow: '0 0 5px #4ae04a88', flexShrink: 0 }}/>
    {name}
  </div>
);

const Sidebar = ({ active, onNavigate, onOpenDice, character, characters, activeId,
  onSwitchCharacter, onAddCharacter, onDuplicateCharacter, onDeleteCharacter, canDeleteChar,
  currentUser, onlineUsers, campaigns, activeCampaignId, onSwitchCampaign, isAdmin }) => (
  <aside className="sidebar">
    <div className="brand">
      <div className="brand-icon">
        <Icon name="spell" size={18}/>
      </div>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div className="brand-word">GRIMOIRE</div>
        {currentUser && (
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 9, color: 'var(--gold-1)',
            letterSpacing: '0.08em', marginTop: 1 }}>
            {currentUser.name} · {currentUser.role}
          </div>
        )}
        {campaigns && campaigns.length > 1 && onSwitchCampaign ? (
          <select
            value={activeCampaignId}
            onChange={e => onSwitchCampaign(e.target.value)}
            style={{
              marginTop: 4, fontFamily: 'var(--font-mono)', fontSize: 9,
              color: 'var(--ink-2)', background: 'var(--bg-0)',
              border: '1px solid var(--line-0)', borderRadius: 4,
              padding: '2px 4px', cursor: 'pointer', width: '100%',
            }}
          >
            {campaigns.map(c => (
              <option key={c.id} value={c.id}>{c.icon} {c.name}</option>
            ))}
          </select>
        ) : campaigns && campaigns.length === 1 ? (
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 9, color: 'var(--ink-3)',
            letterSpacing: '0.06em', marginTop: 2 }}>
            {campaigns[0].icon} {campaigns[0].name}
          </div>
        ) : null}
      </div>
    </div>

    <CharacterSwitcher
      characters={characters}
      activeId={activeId}
      onSwitchCharacter={onSwitchCharacter}
      onAddCharacter={onAddCharacter}
      onDuplicateCharacter={onDuplicateCharacter}
      onDeleteCharacter={onDeleteCharacter}
      canDeleteChar={canDeleteChar}
    />

    <nav className="nav">
      {NAV_SECTIONS.map((sect, si) => (
        <div key={si}>
          <div className="nav-section-label">{sect.label}</div>
          {sect.items.map(it => (
            <div
              key={it.id}
              className={`nav-item ${active === it.id ? 'active' : ''}`}
              onClick={() => onNavigate(it.id)}
            >
              <Icon name={it.icon} size={16} className="nav-icon"/>
              <span>{it.label}</span>
              <span className="nav-shortcut">{it.shortcut}</span>
            </div>
          ))}
          {/* Кнопка "До столу" — плейсхолдер для F03, після Журналу */}
          {si === 0 && (
            <div className="nav-item" style={{ opacity: 0.45, cursor: 'not-allowed' }}
              title="Скоро: інтерактивний стіл для бою (F03)">
              <Icon name="sword" size={16} className="nav-icon" style={{ color: 'var(--azure-1)' }}/>
              <span style={{ color: 'var(--ink-2)' }}>До столу</span>
              <span className="mono" style={{ fontSize: 9, color: 'var(--azure-1)', marginLeft: 'auto', padding: '1px 5px', border: '1px solid var(--azure-1)', borderRadius: 3 }}>скоро</span>
            </div>
          )}
        </div>
      ))}
      {isAdmin && (
        <div>
          <div className="nav-section-label">Система</div>
          <div
            className={`nav-item ${active === NAV_ADMIN_ITEM.id ? 'active' : ''}`}
            onClick={() => onNavigate(NAV_ADMIN_ITEM.id)}
          >
            <Icon name={NAV_ADMIN_ITEM.icon} size={16} className="nav-icon"/>
            <span>{NAV_ADMIN_ITEM.label}</span>
          </div>
        </div>
      )}
    </nav>

    <div className="sidebar-bottom">
      <div className="dice-launcher" onClick={onOpenDice}>
        <Icon name="dice" size={18} style={{ color: 'var(--gold-1)' }}/>
        <span className="dice-launch-label">Кинути куб</span>
        <span className="dice-launch-key">R</span>
      </div>
      {/* Онлайн */}
      {onlineUsers && Object.keys(onlineUsers).length > 0 && (
        <div style={{ borderTop: '1px solid var(--line-0)', paddingTop: 8, marginTop: 4,
          display: 'flex', flexDirection: 'column', gap: 5 }}>
          {Object.values(onlineUsers).filter(u => u.name !== currentUser?.name).map((u, i) => (
            <OnlineDot key={i} name={u.name} role={u.role}/>
          ))}
        </div>
      )}

      <div className="flex ica ig-8" style={{ paddingLeft: 4, color: 'var(--ink-3)', fontSize: 11, cursor: 'pointer' }}
        onClick={() => window.postMessage({ type: '__activate_edit_mode' }, '*')}
        title="Налаштування теми та відображення">
        <Icon name="gear" size={14}/>
        <span className="mono">налаштування</span>
      </div>
    </div>
  </aside>
);

// ============== TOPBAR ==============
const formatSavedAgo = (savedAt) => {
  if (!savedAt) return 'не збережено';
  const sec = Math.floor((Date.now() - savedAt) / 1000);
  if (sec < 5) return 'збережено';
  if (sec < 60) return `${sec} сек тому`;
  const min = Math.floor(sec / 60);
  if (min < 60) return `${min} хв тому`;
  return 'давно';
};

const SaveIndicator = ({ savedAt }) => {
  const [, force] = useState(0);
  useEffect(() => {
    const t = setInterval(() => force(x => x + 1), 5000);
    return () => clearInterval(t);
  }, []);
  const fresh = savedAt && (Date.now() - savedAt) < 5000;
  return (
    <div className="save-indicator" title="Автозбереження: Firebase + localStorage">
      <span className={`save-dot ${fresh ? 'fresh' : ''}`}></span>
      <span>{formatSavedAgo(savedAt)}</span>
    </div>
  );
};

const Topbar = ({ ch, setCh, onOpenDice, openCombat, showActions, savedAt }) => {
  if (!ch) return null;
  const hpPct = (ch.hp / ch.hpMax) * 100;
  const hpColor = hpPct < 25 ? 'var(--crimson-1)' : hpPct < 50 ? '#e0a050' : 'var(--ink-0)';

  const toggleAction = (k) => setCh(c => ({
    ...c, actionUsed: { ...c.actionUsed, [k]: !c.actionUsed[k] }
  }));

  return (
    <header className="topbar">
      <div className="topbar-identity">
        <div className="topbar-name">{ch.name}</div>
        <div className="topbar-sub">{ch.race.toUpperCase()} · {ch.klass.toUpperCase()} {ch.level} · {ch.subclass}</div>
      </div>

      <div className="igrow"/>

      {/* HP meter */}
      <div className="hp-meter" onClick={openCombat} style={{ cursor: 'pointer' }} title="Перейти до бойового екрану">
        <Icon name="heart" size={18} className="hp-icon"/>
        <div className="icol ig-4" style={{ width: 130 }}>
          <div className="flex ija ica">
            <span className="hp-num" style={{ color: hpColor }}>{ch.hp}<span className="hp-max"> / {ch.hpMax}</span></span>
            {ch.hpTemp > 0 && <span className="hp-temp">+{ch.hpTemp} тимч</span>}
          </div>
          <Bar pct={hpPct} color="crimson" thin/>
        </div>
      </div>

      {/* AC */}
      <div data-tooltip-down={`броня + бонуси = ${ch.ac}`}>
        <ShieldStat value={ch.ac} label="КЗ"/>
      </div>

      {/* Init + Speed */}
      <div className="icol ica ig-4" style={{ padding: '0 10px' }}
        data-tooltip-down={`мод DEX ${fmtMod(Math.floor(((ch.abilityScores?.DEX ?? 10)-10)/2))}`}>
        <div className="display" style={{ fontSize: 22, lineHeight: 1 }}>{fmtMod(ch.initiative)}</div>
        <div className="caps mono" style={{ fontSize: 9, color: 'var(--gold-0)' }}>Ініц</div>
      </div>
      <div className="icol ica ig-4" style={{ padding: '0 10px' }}>
        <div className="display" style={{ fontSize: 22, lineHeight: 1 }}>{ch.speed}</div>
        <div className="caps mono" style={{ fontSize: 9, color: 'var(--gold-0)' }}>Швидк</div>
      </div>
      <div className="icol ica ig-4" style={{ padding: '0 10px' }}
        data-tooltip-down={`10 + WIS мод (${Math.floor(((ch.abilityScores?.WIS ?? 10)-10)/2) >= 0 ? '+' : ''}${Math.floor(((ch.abilityScores?.WIS ?? 10)-10)/2)})${(ch.skillProfs?.['Уважність'] ?? 0) > 0 ? ` + проф (${ch.profBonus})` : ''}`}>
        <div className="display" style={{ fontSize: 22, lineHeight: 1 }}>{ch.passivePerc}</div>
        <div className="caps mono" style={{ fontSize: 9, color: 'var(--gold-0)' }}>Сприйн</div>
      </div>

      {showActions && (
        <>
          <div className="topbar-divider"/>
          <div className="action-chips" title="Економія дій: клік → витратити/відновити">
            <span className={`action-chip ${ch.actionUsed.action ? 'used' : ''}`} onClick={() => toggleAction('action')}>Дія</span>
            <span className={`action-chip ${ch.actionUsed.bonus ? 'used' : ''}`} onClick={() => toggleAction('bonus')}>Бонус</span>
            <span className={`action-chip ${ch.actionUsed.reaction ? 'used' : ''}`} onClick={() => toggleAction('reaction')}>Реакція</span>
          </div>
        </>
      )}

      <div className="topbar-divider"/>

      <SaveIndicator savedAt={savedAt}/>

      <Btn ghost sm onClick={onOpenDice} title="Кинути куб (R)">
        <Icon name="dice" size={13}/> Roll
      </Btn>
    </header>
  );
};

// ============== DICE OVERLAY ==============
const DICE_SIDES = [4, 6, 8, 10, 12, 20, 100];

const DiceOverlay = ({ open, onClose, history, pushHistory, ch }) => {
  const [mode, setMode] = useState('normal'); // normal | adv | dis
  const [modifier, setModifier] = useState(0);
  const [count, setCount] = useState(1);
  const [result, setResult] = useState(null);
  const [customExpr, setCustomExpr] = useState('');
  const [customError, setCustomError] = useState('');

  const doCustomRoll = () => {
    const expr = customExpr.trim();
    if (!expr) return;
    const m = expr.match(/^(\d+)d(\d+)([+-]\d+)?$/i);
    if (!m) { setCustomError('Формат: XdY або XdY+Z'); return; }
    setCustomError('');
    const count = parseInt(m[1], 10), sides = parseInt(m[2], 10), bonus = parseInt(m[3] || '0', 10);
    const rolls = rollDice(count, sides);
    const total = rolls.reduce((a, b) => a + b, 0) + bonus;
    const res = {
      id: Math.random().toString(36).slice(2),
      sides, formula: expr, rolls, total,
      crit: false, fumble: false, verdict: null,
      time: new Date().toLocaleTimeString('uk-UA', { hour: '2-digit', minute: '2-digit' }),
    };
    setResult(res);
    pushHistory(res);
  };

  useEffect(() => {
    if (!open) return;
    const onKey = (e) => {
      if (e.key === 'Escape') onClose();
      else if (e.key === 'a' || e.key === 'A') setMode(m => m === 'adv' ? 'normal' : 'adv');
      else if (e.key === 'd' || e.key === 'D') setMode(m => m === 'dis' ? 'normal' : 'dis');
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [open, onClose]);

  const doRoll = (sides) => {
    let rolls, pick, formula, total, verdict = null, crit = false, fumble = false;
    if (sides === 20 && mode !== 'normal') {
      const r = rollD20Adv(mode);
      rolls = r.rolls;
      pick = r.pick;
      total = pick + modifier;
      formula = `2d20${mode === 'adv' ? 'kh' : 'kl'} ${modifier ? (modifier > 0 ? '+ ' + modifier : '- ' + Math.abs(modifier)) : ''}`.trim();
      if (pick === 20) { crit = true; verdict = 'КРИТИЧНИЙ УДАР'; }
      else if (pick === 1) { fumble = true; verdict = 'ФАМБЛ'; }
    } else {
      rolls = rollDice(count, sides);
      const sum = rolls.reduce((a, b) => a + b, 0);
      pick = sum;
      total = sum + modifier;
      formula = `${count}d${sides}${modifier ? (modifier > 0 ? ' + ' + modifier : ' - ' + Math.abs(modifier)) : ''}`;
      if (sides === 20 && count === 1) {
        if (rolls[0] === 20) { crit = true; verdict = 'КРИТИЧНИЙ УДАР'; }
        else if (rolls[0] === 1) { fumble = true; verdict = 'ФАМБЛ'; }
      }
    }
    const res = {
      id: Math.random().toString(36).slice(2),
      sides, formula, rolls, total, crit, fumble, verdict,
      time: new Date().toLocaleTimeString('uk-UA', { hour: '2-digit', minute: '2-digit' }),
    };
    setResult(res);
    pushHistory(res);
  };

  const doNamedRoll = (label, formula, modVal, sides = 20) => {
    const r = rollD20Adv(mode);
    const total = r.pick + modVal;
    const crit = r.pick === 20, fumble = r.pick === 1;
    const res = {
      id: Math.random().toString(36).slice(2),
      sides, formula: `${label} · ${formula}`, rolls: r.rolls, total, crit, fumble,
      verdict: crit ? 'КРИТ' : fumble ? 'ФАМБЛ' : null,
      time: new Date().toLocaleTimeString('uk-UA', { hour: '2-digit', minute: '2-digit' }),
    };
    setResult(res);
    pushHistory(res);
  };

  if (!open) return null;

  return (
    <div className="dice-overlay-backdrop" onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="dice-overlay" style={{ minHeight: 420 }} onClick={(e) => e.stopPropagation()}>
        <div className="dice-overlay-head">
          <Icon name="dice" size={20} style={{ color: 'var(--gold-1)' }}/>
          <h2>Куб</h2>
          <div className="igrow"/>
          <div className="dice-mode-toggle">
            <button className={mode === 'adv' ? 'active' : ''} onClick={() => setMode(m => m === 'adv' ? 'normal' : 'adv')}>Перевага</button>
            <button className={mode === 'normal' ? 'active' : ''} onClick={() => setMode('normal')}>—</button>
            <button className={mode === 'dis' ? 'active' : ''} onClick={() => setMode(m => m === 'dis' ? 'normal' : 'dis')}>Недолік</button>
          </div>
          <IconBtn name="x" onClick={onClose} title="Esc"/>
        </div>

        <div className="dice-overlay-body">
          {result && (
            <div className={`dice-result ${result.crit ? 'crit' : ''} fade-in`} key={result.id}>
              <div className="dice-result-eyebrow">{result.formula}</div>
              <div className="dice-result-big" style={{ color: result.fumble ? 'var(--crimson-1)' : undefined }}>{result.total}</div>
              <div className="dice-result-formula">
                кидки: [{result.rolls.join(', ')}]
                {result.sides === 20 && result.rolls.length > 1 && (
                  <span style={{ color: 'var(--gold-1)', marginLeft: 6 }}>→ {mode === 'adv' ? 'найвищий' : 'найнижчий'}</span>
                )}
              </div>
              {result.verdict && (
                <div className="dice-result-verdict" style={{ color: result.crit ? 'var(--gold-1)' : 'var(--crimson-1)' }}>
                  ★ {result.verdict} ★
                </div>
              )}
            </div>
          )}

          {/* Quick context rolls */}
          <div className="mb-12">
            <div className="caps mono" style={{ fontSize: 9, color: 'var(--ink-3)', marginBottom: 6 }}>Швидко з листа</div>
            <div className="flex iwrap ig-6">
              <Btn sm onClick={() => doNamedRoll('Ініціатива', `d20${fmtMod(ch.initiative)}`, ch.initiative)}>
                <Icon name="bolt" size={11}/> Ініціатива
              </Btn>
              {SKILLS.filter(sk => ((ch.skillProfs || {})[sk.name] ?? sk.prof) > 0).map(sk => {
                const p = (ch.skillProfs || {})[sk.name] ?? sk.prof;
                const abVal = (ch.abilityScores || {})[sk.attr] ?? (ABILITIES.find(a => a.k === sk.attr)?.v ?? 10);
                const m = mod(abVal) + (p === 2 ? ch.profBonus * 2 : ch.profBonus);
                return (
                  <Btn key={sk.name} sm onClick={() => doNamedRoll(sk.name, `d20${fmtMod(m)}`, m)}>{sk.name}</Btn>
                );
              })}
              {(ch.customAttacks || []).slice(0, 2).map(a => (
                <Btn key={a.name} sm onClick={() => doNamedRoll(a.name + ' (атака)', `d20${fmtMod(a.bonus)}`, a.bonus || 0)}>
                  {a.name.length > 12 ? a.name.split(' ')[0] : a.name}
                </Btn>
              ))}
            </div>
          </div>

          {/* Modifier + count */}
          <div className="flex ica ig-12 mb-12">
            <div className="flex ica ig-6">
              <span className="caps mono" style={{ fontSize: 9, color: 'var(--ink-3)' }}>К-сть</span>
              <Stepper value={count} onChange={setCount} min={1} max={20}/>
            </div>
            <div className="flex ica ig-6">
              <span className="caps mono" style={{ fontSize: 9, color: 'var(--ink-3)' }}>Модифікатор</span>
              <Stepper value={modifier} onChange={setModifier} min={-20} max={20}/>
            </div>
          </div>

          {/* Dice grid */}
          <div className="dice-grid">
            {DICE_SIDES.map(s => (
              <button key={s} className="die-btn" onClick={() => doRoll(s)}>
                <Die sides={s} size={36} label={false}/>
                <span className="die-name">d{s}</span>
              </button>
            ))}
            <button className="die-btn" onClick={() => {
              const r = rollDie(2);
              const res = {
                id: Math.random().toString(36).slice(2),
                sides: 2, formula: 'монета', rolls: [r], total: r,
                crit: false, fumble: false,
                verdict: r === 1 ? 'ОРЕЛ' : 'РЕШКА',
                time: new Date().toLocaleTimeString('uk-UA', { hour: '2-digit', minute: '2-digit' }),
              };
              setResult(res); pushHistory(res);
            }}>
              <svg viewBox="0 0 24 24" width={36} height={36} fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinejoin="round">
                <circle cx="12" cy="12" r="9"/>
                <circle cx="12" cy="12" r="5"/>
              </svg>
              <span className="die-name">монета</span>
            </button>
          </div>

          {/* Custom formula */}
          <div className="flex ig-6 ica mt-8">
            <span className="caps mono" style={{ fontSize: 9, color: 'var(--ink-3)', whiteSpace: 'nowrap' }}>Формула</span>
            <input className="input" placeholder="2d6+3, 1d20-1…"
              value={customExpr} onChange={e => { setCustomExpr(e.target.value); setCustomError(''); }}
              onKeyDown={e => e.key === 'Enter' && doCustomRoll()}
              style={{ flex: 1 }}/>
            <Btn sm onClick={doCustomRoll}>
              <Icon name="dice" size={12}/> Кинути
            </Btn>
          </div>
          {customError && (
            <div className="mono" style={{ fontSize: 11, color: 'var(--crimson-1)', marginTop: 4 }}>{customError}</div>
          )}
        </div>

        {history.length > 0 && (
          <div className="dice-history">
            <div className="caps display" style={{ fontSize: 10, color: 'var(--ink-3)', marginBottom: 8 }}>Історія кидків</div>
            {history.slice(0, 5).map(h => (
              <div className="dice-history-row" key={h.id}>
                <span className="dhr-formula">{h.formula}</span>
                <span className="dhr-result">[{h.rolls.join(', ')}]</span>
                <span className="dhr-tag">{h.verdict || ''}</span>
                <span className="dhr-total">{h.total}</span>
                <span className="dhr-time">{h.time}</span>
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  );
};

Object.assign(window, { Sidebar, Topbar, DiceOverlay, NAV_SECTIONS });
