// ============================================================
// SCREEN 1 · CHARACTER (overview / dashboard)
// ============================================================

// Illustration uploader / placeholder used inside the Biography card.
const BiographyIllustration = ({ portrait, onChange, name }) => {
  const inputRef = useRef(null);
  const [drag, setDrag] = useState(false);

  const { push: pushToast } = useToast();
  const onFile = (file) => {
    if (!file || !/^image\//.test(file.type)) return;
    if (file.size > 4 * 1024 * 1024) { pushToast({ label: '⚠ Файл занадто великий', detail: 'Максимальний розмір портрету — 4 МБ' }); return; }
    const reader = new FileReader();
    reader.onload = (e) => onChange(e.target.result);
    reader.readAsDataURL(file);
  };

  return (
    <div className={`bio-illust ${drag ? 'drag' : ''} ${portrait ? 'has-image' : ''}`}
      onDragOver={(e) => { e.preventDefault(); setDrag(true); }}
      onDragLeave={() => setDrag(false)}
      onDrop={(e) => { e.preventDefault(); setDrag(false); onFile(e.dataTransfer.files[0]); }}
      onClick={() => inputRef.current?.click()}>
      <input ref={inputRef} type="file" accept="image/*" style={{ display: 'none' }}
        onChange={(e) => onFile(e.target.files[0])}/>
      {portrait
        ? <img src={portrait} alt={name}/>
        : (
          <>
            {/* hatched illuminated frame */}
            <svg className="bio-illust-svg" viewBox="0 0 200 280" preserveAspectRatio="none">
              <defs>
                <pattern id="bio-hatch" patternUnits="userSpaceOnUse" width="6" height="6" patternTransform="rotate(45)">
                  <line x1="0" y1="0" x2="0" y2="6" stroke="currentColor" strokeWidth="0.5" opacity="0.4"/>
                </pattern>
              </defs>
              <rect x="0" y="0" width="200" height="280" fill="url(#bio-hatch)"/>
              <rect x="14" y="14" width="172" height="252" fill="none" stroke="currentColor" strokeWidth="0.8" opacity="0.6"/>
              <rect x="22" y="22" width="156" height="236" fill="none" stroke="currentColor" strokeWidth="0.4" opacity="0.4"/>
              {/* corners */}
              <path d="M14 14 L14 30 M14 14 L30 14 M186 14 L186 30 M186 14 L170 14 M14 266 L14 250 M14 266 L30 266 M186 266 L186 250 M186 266 L170 266" stroke="currentColor" strokeWidth="1.2"/>
            </svg>
            <div className="bio-illust-caption">
              <Icon name="upload" size={28} style={{ marginBottom: 8, color: 'var(--gold-0)' }}/>
              <div className="caps mono" style={{ fontSize: 9, color: 'var(--gold-0)', marginBottom: 4 }}>ілюстрація</div>
              <div style={{ fontSize: 11, color: 'var(--ink-3)', maxWidth: 160, textAlign: 'center', lineHeight: 1.4 }}>
                перетягни фото або клікни щоб обрати
              </div>
            </div>
          </>
        )}
      {portrait && (
        <div className="bio-illust-overlay">
          <Btn sm><Icon name="upload" size={11}/> Змінити</Btn>
          <Btn sm danger onClick={(e) => { e.stopPropagation(); onChange(null); }}>
            <Icon name="x" size={11}/> Прибрати
          </Btn>
        </div>
      )}
    </div>
  );
};

const ScreenCharacter = ({ ch, setCh }) => {
  const { push } = useToast();
  if (!ch) return null;
  const importRef = useRef(null);
  const [editOpen, setEditOpen] = useState(false);
  const [editDraft, setEditDraft] = useState(null);

  const doExport = () => {
    const json = JSON.stringify(ch, null, 2);
    const blob = new Blob([json], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url; a.download = `${ch.name || 'character'}.json`; a.click();
    // Даємо браузеру час почати завантаження перед тим як відкликати URL
    setTimeout(() => URL.revokeObjectURL(url), 100);
    push({ label: 'Експортовано', detail: `${ch.name}.json` });
  };

  const doImport = (e) => {
    const file = e.target.files[0]; if (!file) return;
    const reader = new FileReader();
    reader.onload = (ev) => {
      try {
        const data = JSON.parse(ev.target.result);
        if (data.name && data.klass) {
          setCh(() => ({ ...data, id: ch.id }));
          push({ label: 'Імпортовано', detail: data.name });
        } else {
          push({ label: '⚠ Помилка імпорту', detail: 'Файл не є даними персонажа' });
        }
      } catch {
        push({ label: '⚠ Помилка читання', detail: 'Перевір формат JSON' });
      }
    };
    reader.readAsText(file);
    e.target.value = '';
  };

  const openEdit = () => { setEditDraft({ ...ch }); setEditOpen(true); };
  const setF = (k, v) => setEditDraft(d => ({ ...d, [k]: v }));
  const saveEdit = () => {
    // Мержимо editDraft поверх поточного стану — не перезаписуємо поля що могли змінитись ззовні (Firebase)
    setCh(c => ({ ...c, ...editDraft }));
    setEditOpen(false);
    push({ label: 'Збережено', detail: editDraft.name });
  };

  const XP_THRESHOLDS = [0, 300, 900, 2700, 6500, 14000, 23000, 34000, 48000, 64000, 85000, 100000, 120000, 140000, 165000, 195000, 225000, 265000, 305000, 355000];
  const levelSystem = ch.levelSystem || 'xp';

  const [xpInput, setXpInput] = useState(0);
  const doAddXp = () => {
    if (!xpInput) return;
    setCh(c => ({ ...c, xp: c.xp + xpInput }));
    push({ icon: 'star', label: '+XP', value: `+${xpInput}`, detail: `Всього: ${ch.xp + xpInput}` });
    setXpInput(0);
  };
  const doLevelUp = () => {
    const newLevel = Math.min(20, ch.level + 1);
    const newProf = Math.floor((newLevel - 1) / 4) + 2;
    const newXpNext = XP_THRESHOLDS[newLevel] ?? XP_THRESHOLDS[19];
    setCh(c => ({ ...c, level: newLevel, profBonus: newProf, xpNext: newXpNext, hitDiceTotal: newLevel }));
    push({ icon: 'star', label: `Рівень ${newLevel}!`, detail: `${ch.klass} · Профіцієнція +${newProf}` });
  };
  const canLevelUpXp = levelSystem === 'xp' && ch.xp >= ch.xpNext && ch.level < 20;

  const generateBio = () => {
    const { personality = '', ideals = '', bonds = '', flaws = '' } = ch.traits || {};
    const parts = [];
    if (personality) parts.push(`${ch.name} — ${personality.charAt(0).toLowerCase() + personality.slice(1).replace(/\.$/, '')}.`);
    if (ideals)      parts.push(`${ch.name.split(' ')[0]} вірить у ${ideals.charAt(0).toLowerCase() + ideals.slice(1).replace(/\.$/, '')}.`);
    if (bonds)       parts.push(`Їх пов'язує ${bonds.charAt(0).toLowerCase() + bonds.slice(1).replace(/\.$/, '')}.`);
    if (flaws)       parts.push(`Проте ${flaws.charAt(0).toLowerCase() + flaws.slice(1).replace(/\.$/, '')}.`);
    if (!parts.length) { push({ label: '⚠ Немає рис', detail: 'Заповни риси особистості спочатку' }); return; }
    if ((ch.biography || '').trim() && !window.confirm('Поточна біографія буде перезаписана. Продовжити?')) return;
    setCh(c => ({ ...c, biography: parts.join(' ') }));
    push({ label: 'Біографію згенеровано', detail: 'на основі рис особистості' });
  };

  const [addingLang, setAddingLang] = useState(false);
  const [langInput, setLangInput] = useState('');
  const doAddLang = () => {
    if (!langInput.trim()) return;
    setCh(c => ({ ...c, languages: [c.languages, langInput.trim()].filter(Boolean).join(', ') }));
    setLangInput(''); setAddingLang(false);
  };

  const removeLang = (lang) => setCh(c => ({
    ...c,
    languages: (c.languages || '').split(',').map(l => l.trim()).filter(l => l && l !== lang).join(', ')
  }));

  const [addingTool, setAddingTool] = useState(false);
  const [toolInput, setToolInput] = useState('');
  const doAddTool = () => {
    if (!toolInput.trim()) return;
    setCh(c => ({ ...c, toolProfs: [c.toolProfs, toolInput.trim()].filter(Boolean).join(', ') }));
    setToolInput(''); setAddingTool(false);
  };
  const removeTool = (tool) => setCh(c => ({
    ...c,
    toolProfs: (c.toolProfs || '').split(',').map(t => t.trim()).filter(t => t && t !== tool).join(', ')
  }));

  // Per-character ability scores (fallback to global ABILITIES if not set)
  const abilityVal = (k) => (ch.abilityScores || {})[k] ?? (ABILITIES.find(a => a.k === k)?.v ?? 10);

  // Per-character saving throw proficiencies (fallback to global SAVES)
  const saveProf = (k) => (ch.saveProfs || {})[k] ?? (SAVES.find(s => s.k === k)?.prof ?? false);
  const toggleSaveProf = (k) => setCh(c => ({ ...c, saveProfs: { ...(c.saveProfs || {}), [k]: !saveProf(k) } }));

  const rollAbility = (ab) => {
    const m = mod(abilityVal(ab.k));
    const r = rollDie(20);
    push({ icon: 'dice', label: `${ab.name} (${ab.k})`, value: r + m, detail: `d20[${r}] ${fmtMod(m)}` });
  };

  const rollSave = (sk) => {
    const ab = ABILITIES.find(a => a.k === sk.k);
    const hasProf = saveProf(sk.k);
    const m = mod(abilityVal(sk.k)) + (hasProf ? ch.profBonus : 0);
    const r = rollDie(20);
    push({ icon: 'shield', label: `Ряткуб ${ab.name}`, value: r + m, detail: `d20[${r}] ${fmtMod(m)}`, crit: r === 20 });
  };

  return (
    <>
      <SectionHeader
        title="Лист персонажа"
        eyebrow="ідентичність · характеристики · риси · походження"
        action={
          <div className="flex ig-6">
            <input ref={importRef} type="file" accept=".json" style={{ display: 'none' }} onChange={doImport}/>
            <Btn ghost sm onClick={() => importRef.current?.click()}><Icon name="upload" size={12}/> Імпорт</Btn>
            <Btn ghost sm onClick={doExport}><Icon name="download" size={12}/> Експорт</Btn>
          </div>
        }
      />

      {/* ========== IDENTITY CARD ========== */}
      <Ornamented size={42} className="character-identity mb-16">
        <div className="identity-portrait">
          <PortraitDrop
            value={ch.portrait}
            onChange={(p) => setCh(c => ({ ...c, portrait: p }))}
            name={ch.name}
            size={120}
          />
          <div className="inspire-toggle">
            <button className={`inspire-btn ${ch.inspiration ? 'on' : ''}`}
              onClick={() => setCh(c => ({ ...c, inspiration: !c.inspiration }))}
              title="Натхнення (Inspiration)">
              <Icon name="star" size={16}/>
            </button>
            <span className="caps mono" style={{ fontSize: 9, color: 'var(--gold-0)' }}>Натхнення</span>
          </div>
        </div>

        <div className="identity-detail">
          <div className="flex ica ig-12 iwrap mb-4">
            <h1 style={{ fontSize: 34, letterSpacing: '0.04em' }}>{ch.name}</h1>
            <span className="script" style={{ fontSize: 17, color: 'var(--ink-2)' }}>«{ch.epithet}»</span>
            <div className="igrow"/>
            <Btn ghost sm onClick={openEdit}><Icon name="edit" size={12}/> Редагувати</Btn>
          </div>

          <div className="flex ig-8 iwrap mb-12">
            <Chip>{ch.race}</Chip>
            <Chip>{ch.klass} <b style={{ marginLeft: 4, color: 'var(--gold-1)' }}>{ch.level}</b></Chip>
            <Chip muted>{ch.subclass}</Chip>
            <Chip muted>{ch.background}</Chip>
            <Chip muted>{ch.alignment}</Chip>
          </div>

          <div className="identity-meta">
            <div className="meta-tile">
              <div className="caps mono" style={{ fontSize: 9, color: 'var(--ink-3)', marginBottom: 2 }}>
                Досвід <span style={{ opacity: 0.6 }}>({levelSystem === 'milestone' ? 'майлстоун' : 'XP'})</span>
              </div>
              {levelSystem === 'xp' ? (
                <>
                  <div className="display" style={{ fontSize: 18 }}>{ch.xp.toLocaleString('uk-UA')}<span style={{ fontSize: 12, color: 'var(--ink-3)' }}> / {ch.xpNext.toLocaleString('uk-UA')}</span></div>
                  <Bar pct={(ch.xp / ch.xpNext) * 100} thin/>
                  <div className="flex ig-4 ica" style={{ marginTop: 4 }}>
                    <input className="input" type="number" min="0" placeholder="+XP"
                      style={{ width: 58, height: 20, padding: '0 5px', fontSize: 11 }}
                      value={xpInput || ''} onChange={e => setXpInput(Number(e.target.value) || 0)}
                      onKeyDown={e => e.key === 'Enter' && doAddXp()}/>
                    <Btn sm ghost onClick={doAddXp} style={{ height: 20, padding: '0 5px' }}><Icon name="plus" size={9}/></Btn>
                    {canLevelUpXp && (
                      <Btn sm onClick={doLevelUp} style={{ height: 20, padding: '0 6px', background:'var(--gold-1)', color:'var(--bg-0)', fontSize:10 }}>⬆ Рівень!</Btn>
                    )}
                  </div>
                </>
              ) : (
                <div className="flex ica ig-6" style={{ marginTop: 4 }}>
                  <span className="mono" style={{ fontSize: 10, color: 'var(--ink-3)' }}>Рівень {ch.level}{ch.level < 20 ? '' : ' (макс)'}</span>
                  {ch.level < 20 && (
                    <Btn sm ghost onClick={doLevelUp} style={{ height: 22, padding: '0 8px', fontSize: 11 }}>⬆ Підняти рівень</Btn>
                  )}
                </div>
              )}
            </div>
            <div className="meta-tile" data-tooltip={`рівень ${ch.level} → +${ch.profBonus}`}>
              <div className="caps mono" style={{ fontSize: 9, color: 'var(--ink-3)' }}>Бонус майстер.</div>
              <div className="display" style={{ fontSize: 20, color: 'var(--gold-1)' }}>{fmtMod(ch.profBonus)}</div>
            </div>
            <div className="meta-tile">
              <div className="caps mono" style={{ fontSize: 9, color: 'var(--ink-3)' }}>Швидкість</div>
              <div className="display" style={{ fontSize: 20 }}>{ch.speed}<span style={{ fontSize: 11, color: 'var(--ink-3)' }}> фут</span></div>
            </div>
            <div className="meta-tile">
              <div className="caps mono" style={{ fontSize: 9, color: 'var(--ink-3)' }}>Кубик HP</div>
              <div className="display" style={{ fontSize: 20 }}>{ch.hitDiceTotal - ch.hitDiceUsed}<span style={{ fontSize: 12, color: 'var(--ink-3)' }}> / {ch.hitDiceTotal} d{ch.hitDie}</span></div>
            </div>
            <div className="meta-tile">
              <div className="caps mono" style={{ fontSize: 9, color: 'var(--ink-3)' }}>Пасивне сприйн.</div>
              <div className="display" style={{ fontSize: 20 }}>{ch.passivePerc}</div>
            </div>
          </div>
        </div>
      </Ornamented>

      {/* ========== MAIN GRID ========== */}
      <div className="character-grid">
        <div className="icol ig-16">
          {/* Ability scores */}
          <Card title="Характеристики" tag="клік → ролл (d20 + мод)">
            <div className="ability-row">
              {ABILITIES.map(ab => {
                const v = abilityVal(ab.k);
                const m = mod(v);
                return (
                  <div key={ab.k} className="stat" onClick={() => rollAbility(ab)}
                    data-tooltip={`(${v} − 10) / 2 = ${m >= 0 ? '+' : ''}${m}`}>
                    {saveProf(ab.k) && <Dot on lg className="stat-save" title="Майстерність у ряткубі" onClick={e => { e.stopPropagation(); toggleSaveProf(ab.k); }}/>}
                    <div className="stat-k">{ab.k}</div>
                    <div className="stat-v">{v}</div>
                    <div className="stat-m">{fmtMod(m)}</div>
                    <div className="caps mono" style={{ fontSize: 8, color: 'var(--ink-3)', marginTop: 6 }}>{ab.name}</div>
                  </div>
                );
              })}
            </div>
          </Card>

          {/* Saving throws */}
          <Card title="Рятівні Кидки" tag="клік → ролл · Dot → змінити"
            action={<span className="mono" style={{ fontSize: 10, color: 'var(--ink-3)' }}>● = майстерність</span>}>
            <div className="save-row">
              {SAVES.map((s) => {
                const hasProf = saveProf(s.k);
                const m = mod(abilityVal(s.k)) + (hasProf ? ch.profBonus : 0);
                return (
                  <div key={s.k} className="save-cell" onClick={() => rollSave(s)}
                    data-tooltip={hasProf ? `мод ${s.k} (${fmtMod(mod(abilityVal(s.k)))}) + проф (${ch.profBonus})` : `мод ${s.k}`}>
                    <Dot on={hasProf} onClick={e => { e.stopPropagation(); toggleSaveProf(s.k); }}/>
                    <span className="display" style={{ fontSize: 12, letterSpacing: '0.14em', flex: 1 }}>{s.k}</span>
                    <span className="display" style={{ fontSize: 16, color: m >= 0 ? 'var(--ink-0)' : 'var(--crimson-1)' }}>{fmtMod(m)}</span>
                  </div>
                );
              })}
            </div>
          </Card>
        </div>

        <div className="icol ig-16">
          {/* Personality */}
          <Card title="Особистість" tag="редаговано">
            <div className="icol ig-12">
              <Field label="Особистісні риси">
                <textarea className="textarea" rows="2"
                  value={ch.traits?.personality || ''}
                  onChange={(e) => setCh(c => ({ ...c, traits: { ...(c.traits || {}), personality: e.target.value } }))}/>
              </Field>
              <Field label="Ідеали">
                <input className="input"
                  value={ch.traits?.ideals || ''}
                  onChange={(e) => setCh(c => ({ ...c, traits: { ...(c.traits || {}), ideals: e.target.value } }))}/>
              </Field>
              <Field label="Зв'язки">
                <input className="input"
                  value={ch.traits?.bonds || ''}
                  onChange={(e) => setCh(c => ({ ...c, traits: { ...(c.traits || {}), bonds: e.target.value } }))}/>
              </Field>
              <Field label="Вади">
                <input className="input"
                  value={ch.traits?.flaws || ''}
                  onChange={(e) => setCh(c => ({ ...c, traits: { ...(c.traits || {}), flaws: e.target.value } }))}/>
              </Field>
            </div>
          </Card>

          {/* Background */}
          <Card title="Походження">
            <div className="icol ig-12">
              <Field label="Передісторія">
                <input className="input"
                  value={ch.background || ''}
                  onChange={(e) => setCh(c => ({ ...c, background: e.target.value }))}/>
              </Field>
              <Field label="Мови">
                <div className="flex ig-6 iwrap">
                  {(ch.languages || '').split(',').map(l => l.trim()).filter(Boolean).map(l => (
                    <Chip key={l}>{l}<span onClick={() => removeLang(l)} style={{ marginLeft: 4, cursor: 'pointer', opacity: 0.5, lineHeight: 1 }}>×</span></Chip>
                  ))}
                  {addingLang ? (
                    <div className="flex ig-4 ica">
                      <input className="input" autoFocus placeholder="назва мови"
                        style={{ width: 120, height: 26, padding: '2px 8px', fontSize: 12 }}
                        value={langInput} onChange={e => setLangInput(e.target.value)}
                        onKeyDown={e => { if (e.key === 'Enter') doAddLang(); if (e.key === 'Escape') { setAddingLang(false); setLangInput(''); } }}/>
                      <IconBtn name="check" size={12} onClick={doAddLang}/>
                      <IconBtn name="x" size={12} onClick={() => { setAddingLang(false); setLangInput(''); }}/>
                    </div>
                  ) : (
                    <Chip muted onClick={() => setAddingLang(true)}>+ додати</Chip>
                  )}
                </div>
              </Field>
              <Field label="Інструменти">
                <div className="flex ig-6 iwrap">
                  {(ch.toolProfs || '').split(',').map(t => t.trim()).filter(Boolean).map(t => (
                    <Chip key={t}>{t}<span onClick={() => removeTool(t)} style={{ marginLeft: 4, cursor: 'pointer', opacity: 0.5, lineHeight: 1 }}>×</span></Chip>
                  ))}
                  {addingTool ? (
                    <div className="flex ig-4 ica">
                      <input className="input" autoFocus placeholder="назва інструменту"
                        style={{ width: 140, height: 26, padding: '2px 8px', fontSize: 12 }}
                        value={toolInput} onChange={e => setToolInput(e.target.value)}
                        onKeyDown={e => { if (e.key === 'Enter') doAddTool(); if (e.key === 'Escape') { setAddingTool(false); setToolInput(''); } }}/>
                      <IconBtn name="check" size={12} onClick={doAddTool}/>
                      <IconBtn name="x" size={12} onClick={() => { setAddingTool(false); setToolInput(''); }}/>
                    </div>
                  ) : (
                    <Chip muted onClick={() => setAddingTool(true)}>+ додати</Chip>
                  )}
                </div>
              </Field>
            </div>
          </Card>
        </div>
      </div>

      {/* ========== BIOGRAPHY ========== */}
      <Card className="mt-12" title="Біографія" tag="історія персонажа · вільний текст"
        action={<Btn ghost sm onClick={generateBio}><Icon name="spell" size={11}/> Згенерувати з рис</Btn>}>
        <div className="bio-layout">
          <BiographyIllustration portrait={ch.portrait} onChange={(p) => setCh(c => ({ ...c, portrait: p }))} name={ch.name}/>
          <div className="bio-text">
            <textarea className="textarea bio-textarea" rows="14"
              value={ch.biography || ''}
              onChange={(e) => setCh(c => ({ ...c, biography: e.target.value }))}
              style={{ fontFamily: 'var(--font-script)', fontSize: 16, lineHeight: 1.7 }}/>
            <div className="bio-footer mt-8">
              <div className="bio-stats">
                <span><b>{(ch.biography || '').length}</b> символів</span>
                <span><b>{(ch.biography || '').trim().split(/\s+/).filter(Boolean).length}</b> слів</span>
                <span><b>{(ch.biography || '').split(/\n\n+/).filter(Boolean).length}</b> абзаців</span>
              </div>
              <Btn ghost sm onClick={() => { push({ label: 'Відкриваємо діалог друку…', detail: 'Ctrl+P або ⌘+P' }); setTimeout(() => window.print(), 300); }}><Icon name="download" size={11}/> Експорт як PDF</Btn>
            </div>
          </div>
        </div>
      </Card>
      {/* ===== MODAL: Редагування персонажа ===== */}
      {editOpen && editDraft && (
        <div className="dice-overlay-backdrop" onClick={() => setEditOpen(false)}>
          <div className="dice-overlay" style={{ width: 620, maxHeight: '90vh', display: 'flex', flexDirection: 'column' }} onClick={e => e.stopPropagation()}>
            <div className="dice-overlay-head">
              <Icon name="character" size={18} style={{ color: 'var(--gold-1)' }}/>
              <h2>Редагування персонажа</h2>
              <div className="igrow"/>
              <IconBtn name="x" onClick={() => setEditOpen(false)}/>
            </div>
            <div className="dice-overlay-body" style={{ flex: 1, minHeight: 0, overflowY: 'auto' }}>
              <div className="icol ig-16">

                {/* Ідентичність */}
                <div>
                  <div className="caps mono mb-8" style={{ fontSize: 9, color: 'var(--gold-1)', letterSpacing: '0.1em' }}>ІДЕНТИЧНІСТЬ</div>
                  <div className="icol ig-8">
                    <div className="flex ig-8">
                      <div className="igrow"><div className="field-label mb-4">Ім'я</div>
                        <input className="input" value={editDraft.name} onChange={e => setF('name', e.target.value)}/></div>
                      <div className="igrow"><div className="field-label mb-4">Епітет</div>
                        <input className="input" value={editDraft.epithet} onChange={e => setF('epithet', e.target.value)}/></div>
                    </div>
                    <div className="flex ig-8">
                      <div className="igrow"><div className="field-label mb-4">Раса</div>
                        <input className="input" value={editDraft.race} onChange={e => setF('race', e.target.value)}/></div>
                      <div className="igrow"><div className="field-label mb-4">Клас</div>
                        <select className="input" value={editDraft.klass} onChange={e => setF('klass', e.target.value)} style={{ cursor: 'pointer' }}>
                          <optgroup label="🛡 Воїни">
                            <option>Боєць</option>
                            <option>Воїн</option>
                            <option>Варвар</option>
                            <option>Монах</option>
                          </optgroup>
                          <optgroup label="✦ Священні">
                            <option>Паладин</option>
                            <option>Жрець</option>
                            <option>Клерик</option>
                          </optgroup>
                          <optgroup label="🌿 Природа">
                            <option>Друід</option>
                            <option>Слідопит</option>
                            <option>Рейнджер</option>
                          </optgroup>
                          <optgroup label="🗡 Спритні">
                            <option>Розбійник</option>
                            <option>Бард</option>
                          </optgroup>
                          <optgroup label="✨ Арканісти">
                            <option>Чарівник</option>
                            <option>Чародій</option>
                            <option>Чорнокнижник</option>
                            <option>Некромант</option>
                          </optgroup>
                        </select></div>
                      <div className="igrow"><div className="field-label mb-4">Підклас</div>
                        <input className="input" value={editDraft.subclass} onChange={e => setF('subclass', e.target.value)}/></div>
                      <div style={{ width: 68 }}><div className="field-label mb-4">Рівень</div>
                        <input className="input" type="number" min="1" max="20" value={editDraft.level}
                          onChange={e => {
                            const lv = Math.max(1, Math.min(20, Number(e.target.value) || 1));
                            setEditDraft(d => ({ ...d, level: lv, profBonus: Math.floor((lv - 1) / 4) + 2 }));
                          }}/></div>
                      <div style={{ width: 110 }}><div className="field-label mb-4">Система левелапу</div>
                        <select className="input" value={editDraft.levelSystem || 'xp'}
                          onChange={e => setEditDraft(d => ({ ...d, levelSystem: e.target.value }))}>
                          <option value="xp">XP</option>
                          <option value="milestone">Майлстоун</option>
                        </select></div>
                    </div>
                    <div className="flex ig-8">
                      <div className="igrow"><div className="field-label mb-4">Передісторія</div>
                        <input className="input" value={editDraft.background} onChange={e => setF('background', e.target.value)}/></div>
                      <div className="igrow"><div className="field-label mb-4">Мировосприйняття</div>
                        <input className="input" value={editDraft.alignment} onChange={e => setF('alignment', e.target.value)}/></div>
                    </div>
                  </div>
                </div>

                {/* Характеристики */}
                <div>
                  <div className="caps mono mb-8" style={{ fontSize: 9, color: 'var(--gold-1)', letterSpacing: '0.1em' }}>ХАРАКТЕРИСТИКИ</div>
                  <div style={{ display: 'grid', gridTemplateColumns: 'repeat(6, 1fr)', gap: 8 }}>
                    {ABILITIES.map(ab => (
                      <div key={ab.k}>
                        <div className="field-label mb-4" style={{ fontSize: 10, textAlign: 'center' }}>{ab.k}</div>
                        <input className="input" type="number" min="1" max="30" style={{ textAlign: 'center' }}
                          value={(editDraft.abilityScores || {})[ab.k] ?? ab.v}
                          onChange={e => {
                            const newScores = {
                              ...(editDraft.abilityScores || {}),
                              [ab.k]: Math.max(1, Math.min(30, Number(e.target.value) || 1)),
                            };
                            setEditDraft(d => ({
                              ...d,
                              abilityScores: newScores,
                              passivePerc: 10 + Math.floor(((newScores.WIS ?? 10) - 10) / 2),
                              carryMax: (newScores.STR ?? 10) * 15,
                              initiative: Math.floor(((newScores.DEX ?? 10) - 10) / 2),
                            }));
                          }}/>
                      </div>
                    ))}
                  </div>
                </div>

                {/* Бойові характеристики */}
                <div>
                  <div className="caps mono mb-8" style={{ fontSize: 9, color: 'var(--gold-1)', letterSpacing: '0.1em' }}>БОЙОВІ ХАРАКТЕРИСТИКИ</div>
                  <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 8 }}>
                    {[
                      ['HP макс', 'hpMax', 1, 999],
                      ['КЗ', 'ac', 1, 30],
                      ['Ініціатива', 'initiative', -5, 10],
                      ['Швидкість', 'speed', 5, 120],
                      ['Бонус майстерн.', 'profBonus', 1, 6],
                      ['Пасивне сприйн.', 'passivePerc', 1, 30],
                      ['Кубик HP (d?)', 'hitDie', 4, 20],
                      ['Кубики HP (к-сть)', 'hitDiceTotal', 1, 20],
                    ].map(([label, key, min, max]) => (
                      <div key={key}>
                        <div className="field-label mb-4" style={{ fontSize: 10 }}>{label}</div>
                        <input className="input" type="number" min={min} max={max}
                          value={editDraft[key]}
                          onChange={e => setF(key, Math.max(min, Math.min(max, Number(e.target.value) || min)))}/>
                      </div>
                    ))}
                  </div>
                </div>

                {/* Магія */}
                <div>
                  <div className="caps mono mb-8" style={{ fontSize: 9, color: 'var(--gold-1)', letterSpacing: '0.1em' }}>МАГІЯ</div>
                  <div className="flex ig-8">
                    <div>
                      <div className="field-label mb-4">Заклинальна хар-ка</div>
                      <select className="input" value={editDraft.spellAbility || 'WIS'} onChange={e => setF('spellAbility', e.target.value)} style={{ cursor: 'pointer' }}>
                        {['STR','DEX','CON','INT','WIS','CHA'].map(a => <option key={a}>{a}</option>)}
                      </select>
                    </div>
                    <div style={{ width: 110 }}>
                      <div className="field-label mb-4">СК закляття</div>
                      <input className="input" type="number" min="1" max="30"
                        value={editDraft.spellSaveDC ?? 0}
                        onChange={e => setF('spellSaveDC', Math.max(1, Math.min(30, Number(e.target.value) || 1)))}/>
                    </div>
                    <div style={{ width: 110 }}>
                      <div className="field-label mb-4">Бонус атаки закл.</div>
                      <input className="input" type="number" min="-5" max="20"
                        value={editDraft.spellAttack ?? 0}
                        onChange={e => setF('spellAttack', Math.max(-5, Math.min(20, Number(e.target.value) || 0)))}/>
                    </div>
                  </div>
                </div>

                {/* Досвід */}
                <div>
                  <div className="caps mono mb-8" style={{ fontSize: 9, color: 'var(--gold-1)', letterSpacing: '0.1em' }}>ДОСВІД</div>
                  <div className="flex ig-8">
                    <div className="igrow"><div className="field-label mb-4">XP поточний</div>
                      <input className="input" type="number" min="0" value={editDraft.xp}
                        onChange={e => setF('xp', Math.max(0, Number(e.target.value) || 0))}/></div>
                    <div className="igrow"><div className="field-label mb-4">XP до наступного рівня</div>
                      <input className="input" type="number" min="1" value={editDraft.xpNext}
                        onChange={e => setF('xpNext', Math.max(1, Number(e.target.value) || 1))}/></div>
                  </div>
                </div>

                {/* Вміння */}
                <div>
                  <div className="caps mono mb-8" style={{ fontSize: 9, color: 'var(--gold-1)', letterSpacing: '0.1em' }}>ВМІННЯ</div>
                  <div className="icol ig-8">
                    <div><div className="field-label mb-4">Мови (через кому)</div>
                      <input className="input" value={editDraft.languages || ''}
                        onChange={e => setF('languages', e.target.value)}/></div>
                    <div><div className="field-label mb-4">Інструменти (через кому)</div>
                      <input className="input" value={editDraft.toolProfs || ''}
                        onChange={e => setF('toolProfs', e.target.value)}/></div>
                    <div><div className="field-label mb-4">Зброя та броня (через кому)</div>
                      <input className="input" value={editDraft.weaponProfs || ''}
                        onChange={e => setF('weaponProfs', e.target.value)}/></div>
                  </div>
                </div>

                <div className="flex ig-8 mt-4">
                  <Btn primary onClick={saveEdit}><Icon name="check" size={12}/> Зберегти зміни</Btn>
                  <Btn ghost onClick={() => setEditOpen(false)}>Скасувати</Btn>
                </div>
              </div>
            </div>
          </div>
        </div>
      )}
    </>
  );
};

window.ScreenCharacter = ScreenCharacter;
