// ============================================================
// SCREEN 7 · NOTES / JOURNAL
// ============================================================

const KIND_META = {
  battle:    { label: 'Битва',    icon: 'sword'     },
  find:      { label: 'Знахідка', icon: 'star'      },
  npc:       { label: 'Зустріч',  icon: 'character' },
  milestone: { label: 'Важливе',  icon: 'star'      },
  travel:    { label: 'Подорож',  icon: 'hourglass' },
  lore:      { label: 'Лор',      icon: 'rune'      },
};

const BLANK_TIMELINE_EVENT = () => ({
  _id: Math.random().toString(36).slice(2, 10),
  date: new Date().toLocaleDateString('uk-UA', { day: '2-digit', month: '2-digit', year: 'numeric' }),
  session: '',
  kind: 'find',
  title: '',
  body: '',
  related: '',
});

const ScreenNotes = ({ ch, setCh, timeline, setTimeline }) => {
  const { push } = useToast();
  if (!ch) return null;
  const [tab, setTabRaw] = useState(() => sessionStorage.getItem('notes_tab') || 'sessions');
  const setTab = (t) => { sessionStorage.setItem('notes_tab', t); setTabRaw(t); };
  const [quickNote, setQuickNoteRaw] = useState(() => sessionStorage.getItem('notes_qn') || '');
  const setQuickNote = (v) => { const s = typeof v === 'function' ? v(quickNote) : v; sessionStorage.setItem('notes_qn', s); setQuickNoteRaw(s); };

  // ── Sessions ──
  const sessions = ch.sessions ?? SESSIONS;
  const setSessions = (updater) => setCh(c => ({
    ...c,
    sessions: typeof updater === 'function'
      ? updater(c.sessions ?? SESSIONS)
      : updater,
  }));
  const [timelineFilter, setTimelineFilter] = useState('ALL');
  const [addSessionOpen, setAddSessionOpen] = useState(false);
  const [newSessionTitle, setNewSessionTitle] = useState('');
  const [newSessionBody, setNewSessionBody] = useState('');
  const [newSessionDate, setNewSessionDate] = useState('');
  const [newSessionTags, setNewSessionTags] = useState('');
  const [editSessionOpen, setEditSessionOpen] = useState(false);
  const [editSessionDraft, setEditSessionDraft] = useState(null);
  const [expandedSessions, setExpandedSessions] = useState({});
  const openEditSession = (s) => { setEditSessionDraft({ ...s }); setEditSessionOpen(true); };
  const saveEditSession = () => {
    if (editSessionDraft.n == null) { setEditSessionOpen(false); return; }
    setSessions(ss => ss.map(s => s.n === editSessionDraft.n ? editSessionDraft : s));
    setEditSessionOpen(false);
    push({ label: `Сесію #${editSessionDraft.n} збережено` });
  };
  const deleteSession = (n) => {
    if (!window.confirm(`Видалити запис сесії #${n}?`)) return;
    setSessions(ss => ss.filter(s => s.n !== n));
    setEditSessionOpen(false);
    push({ label: `Запис #${n} видалено` });
  };
  const todayStr = () => new Date().toLocaleDateString('uk-UA', { day: '2-digit', month: '2-digit', year: 'numeric' });
  const openAddSession = () => {
    setNewSessionTitle('');
    setNewSessionBody('');
    setNewSessionDate(todayStr());
    setNewSessionTags('');
    setAddSessionOpen(true);
  };
  const nextSessionN = (ss) => ss.length > 0 ? Math.max(...ss.map(x => x.n)) + 1 : 1;
  const submitNewSession = () => {
    if (!newSessionTitle.trim() && !newSessionBody.trim()) return;
    const tags = newSessionTags.split(',').map(t => t.trim()).filter(Boolean);
    setSessions(s => [{
      n:     nextSessionN(s),
      date:  newSessionDate.trim() || todayStr(),
      title: newSessionTitle.trim() || newSessionBody.trim().slice(0, 60),
      body:  newSessionBody.trim(),
      tags:  tags.length ? tags : ['нова'],
    }, ...s]);
    setAddSessionOpen(false);
    setTab('sessions');
    push({ label: `Сесію додано: ${newSessionTitle.trim() || 'новий запис'}` });
  };

  // ── Timeline (global) ──
  const [addTimelineOpen, setAddTimelineOpen] = useState(false);
  const [newEvent, setNewEvent] = useState(BLANK_TIMELINE_EVENT());
  // timelineDetailId — стабільний _id відкритої події; timelineDetail деривується з timeline щоразу
  const [timelineDetailId, setTimelineDetailId] = useState(null);
  const timelineDetail = timelineDetailId
    ? (timeline.find(e => e._id === timelineDetailId) ?? null)
    : null;
  const [timelineEditMode, setTimelineEditMode] = useState(false);
  const [timelineEditDraft, setTimelineEditDraft] = useState(null);

  const parseUADate = (s) => { const [d, m, y] = (s || '').split('.').map(Number); return (y > 0 && m > 0 && d > 0) ? new Date(y, m - 1, d).getTime() : 0; };
  const filteredTimeline = (timelineFilter === 'ALL' ? timeline : timeline.filter(e => e.kind === timelineFilter))
    .slice().sort((a, b) => parseUADate(b.date) - parseUADate(a.date));

  const openAddTimeline = () => {
    setNewEvent(BLANK_TIMELINE_EVENT());
    setAddTimelineOpen(true);
  };
  const submitNewEvent = () => {
    if (!newEvent.title.trim()) return;
    const meta = KIND_META[newEvent.kind] || KIND_META['find'];
    const ev = {
      _id:       newEvent._id || Math.random().toString(36).slice(2, 10),
      date:      newEvent.date.trim() || todayStr(),
      session:   newEvent.session ? (parseInt(newEvent.session, 10) || null) : null,
      kind:      newEvent.kind,
      kindLabel: meta.label,
      icon:      meta.icon,
      title:     newEvent.title.trim(),
      body:      newEvent.body.trim(),
      related:   newEvent.related.split(',').map(r => r.trim()).filter(Boolean),
    };
    setTimeline(tl => [ev, ...tl]);
    setAddTimelineOpen(false);
    push({ label: `Подію додано: ${ev.title}` });
  };

  const openTimelineDetail = (ev) => {
    // Якщо у старій події немає _id (завантажена до патчу) — мінтимо на льоту і зберігаємо
    if (!ev._id) {
      const id = Math.random().toString(36).slice(2, 10);
      setTimeline(tl => tl.map(e => e === ev ? { ...e, _id: id } : e));
      setTimelineDetailId(id);
    } else {
      setTimelineDetailId(ev._id);
    }
    setTimelineEditMode(false);
    setTimelineEditDraft(null);
  };
  const startTimelineEdit = () => {
    setTimelineEditDraft({
      ...timelineDetail,
      related: (timelineDetail.related || []).join(', '),
      session: timelineDetail.session != null ? String(timelineDetail.session) : '',
    });
    setTimelineEditMode(true);
  };
  const saveTimelineEdit = () => {
    const meta = KIND_META[timelineEditDraft.kind] || KIND_META['find'];
    const updated = {
      ...timelineEditDraft,
      kindLabel: meta.label,
      icon:      meta.icon,
      session:   timelineEditDraft.session ? (parseInt(timelineEditDraft.session, 10) || null) : null,
      related:   typeof timelineEditDraft.related === 'string'
        ? timelineEditDraft.related.split(',').map(r => r.trim()).filter(Boolean)
        : timelineEditDraft.related,
    };
    setTimeline(tl => tl.map(e => e._id === timelineDetailId ? updated : e));
    setTimelineEditMode(false);
    setTimelineEditDraft(null);
    push({ label: `Подію оновлено: ${updated.title}` });
  };
  const deleteTimelineEvent = () => {
    if (!window.confirm(`Видалити подію «${timelineDetail?.title}»?`)) return;
    setTimeline(tl => tl.filter(e => e._id !== timelineDetailId));
    setTimelineDetailId(null);
    push({ label: 'Подію видалено' });
  };

  // ── Quests (per-character) ──
  const quests = ch.quests ?? [];
  const setQuests = (updater) => setCh(c => ({
    ...c,
    quests: typeof updater === 'function' ? updater(c.quests ?? []) : updater,
  }));
  const [addQuestOpen, setAddQuestOpen] = useState(false);
  const [newQuest, setNewQuest] = useState({ name: '', kind: 'побічний', progress: 0 });
  const toggleQuestStatus = (i) => setQuests(qs => qs.map((q, j) => j === i ? { ...q, status: q.status === 'done' ? 'active' : 'done' } : q));
  const setQuestProgress = (i, v) => setQuests(qs => qs.map((q, j) => j === i ? { ...q, progress: Math.max(0, Math.min(100, v)) } : q));
  const deleteQuest = (i, name) => { if (!window.confirm(`Видалити квест «${name}»?`)) return; setQuests(qs => qs.filter((_, j) => j !== i)); };
  const submitNewQuest = () => {
    if (!newQuest.name.trim()) return;
    setQuests(qs => [...qs, { ...newQuest, name: newQuest.name.trim(), status: 'active' }]);
    setNewQuest({ name: '', kind: 'побічний', progress: 0 });
    setAddQuestOpen(false);
    push({ label: `Квест додано: ${newQuest.name.trim()}` });
  };

  // ── NPCs (per-character) ──
  const npcs = ch.npcs ?? [];
  const setNpcs = (updater) => setCh(c => ({
    ...c,
    npcs: typeof updater === 'function' ? updater(c.npcs ?? []) : updater,
  }));
  const [npcDetailId, setNpcDetailId] = useState(null);
  const npcDetail = npcDetailId ? (npcs.find(n => n._id === npcDetailId) ?? null) : null;
  const [npcEditMode, setNpcEditMode] = useState(false);
  const [npcEditDraft, setNpcEditDraft] = useState(null);
  const openNpcDetail = (n) => {
    // Мінтимо _id для старих NPC без ідентифікатора
    if (!n._id) {
      const id = Math.random().toString(36).slice(2, 10);
      setNpcs(ns => ns.map(x => x === n ? { ...x, _id: id } : x));
      setNpcDetailId(id);
    } else {
      setNpcDetailId(n._id);
    }
    setNpcEditMode(false);
    setNpcEditDraft(null);
  };
  const startNpcEdit = () => { setNpcEditDraft({ ...npcDetail }); setNpcEditMode(true); };
  const saveNpcEdit = () => {
    setNpcs(ns => ns.map(n => n._id === npcDetailId ? npcEditDraft : n));
    setNpcEditMode(false);
    setNpcEditDraft(null);
  };
  const deleteNpc = () => {
    if (!window.confirm(`Видалити NPC «${npcDetail.name}»?`)) return;
    setNpcs(ns => ns.filter(n => n._id !== npcDetailId));
    setNpcDetailId(null);
    push({ label: `NPC видалено: ${npcDetail.name}` });
  };
  const [addNpcOpen, setAddNpcOpen] = useState(false);
  const [newNpc, setNewNpc] = useState({ name: '', rel: 'нейтр.', note: '' });
  const submitNewNpc = () => {
    if (!newNpc.name.trim()) return;
    setNpcs(ns => [...ns, { ...newNpc, name: newNpc.name.trim(), _id: Math.random().toString(36).slice(2, 10) }]);
    setNewNpc({ name: '', rel: 'нейтр.', note: '' });
    setAddNpcOpen(false);
    push({ label: `NPC додано: ${newNpc.name.trim()}` });
  };

  const saveQuickNote = () => {
    if (!quickNote.trim()) return;
    setSessions(s => {
      const entry = {
        n: nextSessionN(s),
        date: new Date().toLocaleDateString('uk-UA', { day: '2-digit', month: '2-digit', year: 'numeric' }),
        title: quickNote.trim().split('\n')[0].slice(0, 60),
        body: quickNote.trim(),
        tags: ['нотатка'],
      };
      return [entry, ...s];
    });
    setQuickNote('');
    setTab('sessions');
  };

  return (
    <>
      <SectionHeader
        title="Журнал кампанії"
        eyebrow="сесії · хронологія · квести · NPC та локації"
        action={
          <div className="flex ig-6">
            {tab === 'sessions' && <Btn primary sm onClick={openAddSession}><Icon name="plus" size={11}/> Нова сесія</Btn>}
            {tab === 'timeline' && <Btn primary sm onClick={openAddTimeline}><Icon name="plus" size={11}/> Подія</Btn>}
          </div>
        }
      />

      <div className="journal-tabs mb-16">
        {[
          ['sessions', 'Сесії', 'book'],
          ['timeline', 'Хронологія', 'hourglass'],
          ['quests', 'Квести', 'scroll'],
          ['npcs', 'NPC та локації', 'character'],
        ].map(([id, label, icon]) => (
          <button key={id} className={`journal-tab ${tab === id ? 'active' : ''}`} onClick={() => setTab(id)}>
            <Icon name={icon} size={14}/>
            <span>{label}</span>
            <span className="mono" style={{ fontSize: 10, color: 'var(--ink-3)', marginLeft: 'auto' }}>
              {id === 'sessions' ? sessions.length :
               id === 'timeline' ? timeline.length :
               id === 'quests' ? quests.length :
               id === 'npcs' ? npcs.length : 0}
            </span>
          </button>
        ))}
      </div>

      <div className="journal-grid">
        {/* MAIN COLUMN */}
        <div className="icol ig-16">
          {tab === 'sessions' && (
            <Card title="Сесії" tag={`всього: ${sessions.length}`}>
              {sessions.length === 0 && (
                <div className="mono dim" style={{ textAlign: 'center', padding: '24px 0', fontSize: 12 }}>
                  Немає записів — натисни «Нова сесія»
                </div>
              )}
              {sessions.map(s => {
                const LIMIT = 400;
                const isLong = (s.body || '').length > LIMIT;
                const expanded = !!expandedSessions[s.n];
                const displayBody = isLong && !expanded
                  ? s.body.slice(0, LIMIT) + '…'
                  : (s.body || '');
                return (
                  <div key={s.n} className="session-card">
                    <div className="session-mark">
                      <div className="session-mark-n">{s.n.toString().padStart(2, '0')}</div>
                      <div className="caps mono" style={{ fontSize: 9, color: 'var(--gold-0)' }}>сесія</div>
                    </div>
                    <div className="session-body">
                      <div className="flex iba ig-8 mb-6">
                        <h3 style={{ fontSize: 16 }}>{s.title}</h3>
                        <span className="mono dim" style={{ fontSize: 11 }}>{s.date}</span>
                        <div className="igrow"/>
                        <Btn ghost sm onClick={() => openEditSession(s)}><Icon name="edit" size={11}/></Btn>
                      </div>
                      <div className="script" style={{ fontSize: 14, lineHeight: 1.6, color: 'var(--ink-1)', whiteSpace: 'pre-wrap' }}>
                        {displayBody}
                      </div>
                      {isLong && (
                        <button
                          style={{ marginTop: 6, background: 'none', border: 'none', cursor: 'pointer',
                            fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--gold-1)', padding: 0 }}
                          onClick={() => setExpandedSessions(e => ({ ...e, [s.n]: !expanded }))}>
                          {expanded ? '▲ згорнути' : '▼ читати далі'}
                        </button>
                      )}
                      <div className="flex ig-6 iwrap mt-12">
                        {(s.tags || []).map(t => <Chip key={t} muted sm>{t}</Chip>)}
                      </div>
                    </div>
                  </div>
                );
              })}
            </Card>
          )}

          {tab === 'timeline' && (
            <Card title="Хронологія світу" tag={`${timeline.length} подій`}
              action={
                <div className="flex ig-4">
                  <Chip active={timelineFilter==='ALL'} onClick={() => setTimelineFilter('ALL')}>Усі</Chip>
                  <Chip active={timelineFilter==='battle'} onClick={() => setTimelineFilter('battle')}>Битви</Chip>
                  <Chip active={timelineFilter==='find'} onClick={() => setTimelineFilter('find')}>Знахідки</Chip>
                  <Chip active={timelineFilter==='npc'} onClick={() => setTimelineFilter('npc')}>NPC</Chip>
                  <Chip active={timelineFilter==='milestone'} onClick={() => setTimelineFilter('milestone')}>Важливі</Chip>
                  <Chip active={timelineFilter==='travel'} onClick={() => setTimelineFilter('travel')}>Подорожі</Chip>
                  <Chip active={timelineFilter==='lore'} onClick={() => setTimelineFilter('lore')}>Лор</Chip>
                </div>
              }>
              {filteredTimeline.length === 0 && (
                <div className="mono dim" style={{ textAlign: 'center', padding: '24px 0', fontSize: 12 }}>
                  Немає подій — натисни «+ Подія»
                </div>
              )}
              <div className="timeline">
                {filteredTimeline.map((ev, i) => (
                  <div key={i} className={`timeline-entry kind-${ev.kind}`}>
                    <div className="timeline-marker">
                      <Icon name={ev.icon} size={14}/>
                    </div>
                    <div className="timeline-body">
                      <div className="flex iba ig-8 mb-4 iwrap">
                        <span className="caps mono" style={{ fontSize: 10, color: 'var(--gold-0)' }}>{ev.date}</span>
                        <Chip sm muted>{ev.kindLabel}</Chip>
                        {ev.session && <Chip sm>сесія {ev.session}</Chip>}
                        <div className="igrow"/>
                        <Btn ghost sm onClick={() => openTimelineDetail(ev)}><Icon name="edit" size={10}/></Btn>
                      </div>
                      <div className="display" style={{ fontSize: 15, marginBottom: 4 }}>{ev.title}</div>
                      <div className="script" style={{ fontSize: 13, color: 'var(--ink-1)', lineHeight: 1.55 }}>{ev.body}</div>
                      {ev.related && ev.related.length > 0 && (
                        <div className="flex ig-4 iwrap mt-8">
                          {ev.related.map((r, j) => <Chip key={j} muted sm>↪ {r}</Chip>)}
                        </div>
                      )}
                    </div>
                  </div>
                ))}
                {timeline.length > 0 && (
                  <div className="timeline-end">
                    <Icon name="hourglass" size={16} style={{ color: 'var(--gold-0)' }}/>
                    <span className="caps mono" style={{ fontSize: 10, color: 'var(--ink-3)' }}>початок історії</span>
                  </div>
                )}
              </div>
            </Card>
          )}

          {tab === 'quests' && (
            <Card title="Квести" tag={`${quests.filter(q => q.status === 'active').length} активних`}
              action={<Btn primary sm onClick={() => setAddQuestOpen(true)}><Icon name="plus" size={11}/> Квест</Btn>}>
              {quests.length === 0 && (
                <div className="mono dim" style={{ textAlign: 'center', padding: '20px 0', fontSize: 12 }}>Немає квестів</div>
              )}
              {quests.map((q, i) => (
                <div key={i} className="quest-card">
                  <div className="flex ica ig-10 mb-6">
                    <Dot lg on={q.status === 'active'} color={q.status === 'done' ? 'emerald' : ''}
                      title={q.status === 'done' ? 'Виконано · клік → активний' : 'Активний · клік → виконано'}
                      onClick={() => toggleQuestStatus(i)}/>
                    <span style={{ fontWeight: 600, fontSize: 14, textDecoration: q.status === 'done' ? 'line-through' : 'none', color: q.status === 'done' ? 'var(--ink-3)' : 'inherit' }}>{q.name}</span>
                    <Chip sm muted>{q.kind}</Chip>
                    <div className="igrow"/>
                    <div className="flex ica ig-4">
                      <input type="number" min="0" max="100" value={q.progress}
                        style={{ width: 42, textAlign: 'right', background: 'none', border: 'none', fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--ink-3)', cursor: 'text' }}
                        onChange={e => setQuestProgress(i, Math.max(0, Math.min(100, parseInt(e.target.value, 10) || 0)))}
                        onClick={e => e.stopPropagation()}/>
                      <span className="mono dim" style={{ fontSize: 10 }}>%</span>
                    </div>
                    <IconBtn name="trash" size={11} title="Видалити квест" onClick={() => deleteQuest(i, q.name)}/>
                  </div>
                  <Bar pct={q.progress} color={q.status === 'done' ? 'emerald' : ''}/>
                </div>
              ))}
            </Card>
          )}

          {tab === 'npcs' && (
            <Card title="NPC та локації" tag={`${npcs.length} осіб`}
              action={<Btn primary sm onClick={() => setAddNpcOpen(true)}><Icon name="plus" size={11}/> NPC</Btn>}>
              {npcs.length === 0 && (
                <div className="mono dim" style={{ textAlign: 'center', padding: '20px 0', fontSize: 12 }}>Немає NPC</div>
              )}
              {npcs.map((n, i) => (
                <div key={i} className="npc-card">
                  <div className="npc-portrait">{n.name.split(' ').map(p => p[0]).slice(0, 2).join('')}</div>
                  <div className="igrow">
                    <div className="flex ica ig-6 mb-4">
                      <span style={{ fontWeight: 600 }}>{n.name}</span>
                      <Chip sm color={n.rel === 'ворог' ? 'crimson' : n.rel === 'союзник' ? 'emerald' : 'azure'} fill>{n.rel}</Chip>
                    </div>
                    <div className="mono dim" style={{ fontSize: 12 }}>{n.note}</div>
                  </div>
                  <IconBtn name="chevronR" size={14} onClick={() => openNpcDetail(n)}/>
                </div>
              ))}
            </Card>
          )}

        </div>

        {/* SIDE COLUMN */}
        <div className="icol ig-16">
          <Card title="Швидка нотатка" tag="⌘+enter → у журнал">
            <textarea className="textarea" rows="5" placeholder="що тільки що сталося в сесії…"
              value={quickNote} onChange={(e) => setQuickNote(e.target.value)}
              onKeyDown={(e) => { if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') saveQuickNote(); }}/>
            <div className="flex ig-6 mt-8">
              <Btn primary sm onClick={saveQuickNote}><Icon name="check" size={11}/> До журналу</Btn>
              <Btn ghost sm onClick={() => setQuickNote('')}><Icon name="x" size={11}/> Скинути</Btn>
            </div>
          </Card>

          <Card title="Активні квести" tag={`${quests.filter(q => q.status === 'active').length} з ${quests.length}`}>
            {quests.filter(q => q.status === 'active').slice(0, 3).map((q, i) => (
              <div key={i} className="mini-quest">
                <Dot on/>
                <div className="igrow">
                  <div style={{ fontSize: 13, fontWeight: 500 }}>{q.name}</div>
                  <Bar pct={q.progress} thin style={{ marginTop: 4 }}/>
                </div>
                <Chip sm muted>{q.kind}</Chip>
              </div>
            ))}
            {quests.filter(q => q.status === 'active').length === 0 && (
              <span className="mono dim" style={{ fontSize: 11 }}>Немає активних квестів</span>
            )}
          </Card>

          <Card title="Останні NPC">
            <div className="icol">
              {npcs.slice(0, 4).map((n, i) => (
                <div key={i} className="flex ica ig-8" style={{ padding: '6px 0', borderBottom: i < Math.min(3, npcs.length - 1) ? '1px solid var(--line-0)' : 'none' }}>
                  <div style={{
                    width: 28, height: 28, borderRadius: '50%',
                    background: 'var(--bg-3)', border: '1px solid var(--gold-2)',
                    display: 'flex', alignItems: 'center', justifyContent: 'center',
                    fontFamily: 'var(--font-display)', fontSize: 10, color: 'var(--gold-1)',
                  }}>{n.name.split(' ').map(p => p[0]).slice(0, 2).join('')}</div>
                  <div className="igrow">
                    <div style={{ fontSize: 12, fontWeight: 500 }}>{n.name}</div>
                    <div className="mono dim" style={{ fontSize: 9 }}>{n.rel}</div>
                  </div>
                </div>
              ))}
              {npcs.length === 0 && <span className="mono dim" style={{ fontSize: 11 }}>Немає NPC</span>}
            </div>
          </Card>

          <Card title="Календар">
            <div className="flex ica ig-10">
              <Icon name="hourglass" size={18} style={{ color: 'var(--gold-0)' }}/>
              <div className="igrow">
                <div className="display" style={{ fontSize: 14 }}>{sessions.length > 0 ? sessions.reduce((a, b) => (a.n ?? 0) > (b.n ?? 0) ? a : b).date : '—'}</div>
                <div className="mono dim" style={{ fontSize: 10 }}>сесія {sessions.length} · остання</div>
              </div>
              <Btn ghost sm onClick={openAddSession}>+ подія</Btn>
            </div>
          </Card>
        </div>
      </div>

      {/* ===== MODAL: Редагування запису сесії ===== */}
      {editSessionOpen && editSessionDraft && (
        <div className="dice-overlay-backdrop" onClick={() => setEditSessionOpen(false)}>
          <div className="dice-overlay" style={{ width: 620, minHeight: '78vh' }} onClick={e => e.stopPropagation()}>
            <div className="dice-overlay-head">
              <Icon name="edit" size={18} style={{ color: 'var(--gold-1)' }}/>
              <h2>Редагування сесії #{editSessionDraft.n}</h2>
              <div className="igrow"/>
              <IconBtn name="x" onClick={() => setEditSessionOpen(false)}/>
            </div>
            <div className="dice-overlay-body" style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
              <div style={{ display: 'flex', flexDirection: 'column', flex: 1, gap: 12, minHeight: 0 }}>
                <div className="flex ig-10">
                  <div style={{ flex: 1 }}>
                    <div className="field-label mb-4">Заголовок</div>
                    <input className="input" autoFocus
                      value={editSessionDraft.title}
                      onChange={e => setEditSessionDraft(d => ({ ...d, title: e.target.value }))}/>
                  </div>
                  <div style={{ width: 128 }}>
                    <div className="field-label mb-4">Дата</div>
                    <input className="input"
                      value={editSessionDraft.date}
                      onChange={e => setEditSessionDraft(d => ({ ...d, date: e.target.value }))}/>
                  </div>
                </div>
                <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0 }}>
                  <div className="field-label mb-4">Нотатки сесії</div>
                  <textarea className="textarea"
                    style={{ flex: 1, resize: 'none', height: 'auto', minHeight: 120 }}
                    value={editSessionDraft.body}
                    onChange={e => setEditSessionDraft(d => ({ ...d, body: e.target.value }))}/>
                </div>
                <div>
                  <div className="field-label mb-4">Теги <span className="mono dim">(через кому)</span></div>
                  <input className="input"
                    value={(editSessionDraft.tags || []).join(', ')}
                    onChange={e => setEditSessionDraft(d => ({ ...d, tags: e.target.value.split(',').map(t => t.trim()).filter(Boolean) }))}/>
                </div>
                <div className="flex ig-8">
                  <Btn primary onClick={saveEditSession}><Icon name="check" size={12}/> Зберегти</Btn>
                  <Btn ghost onClick={() => setEditSessionOpen(false)}>Скасувати</Btn>
                  <div className="igrow"/>
                  <Btn danger onClick={() => deleteSession(editSessionDraft.n)}>
                    <Icon name="trash" size={12}/> Видалити
                  </Btn>
                </div>
              </div>
            </div>
          </div>
        </div>
      )}

      {/* ===== MODAL: Деталі / Редагування події хронології ===== */}
      {timelineDetail && (
        <div className="dice-overlay-backdrop" onClick={() => { setTimelineDetailId(null); setTimelineEditMode(false); }}>
          <div className="dice-overlay" style={{ width: 560, minHeight: '65vh' }} onClick={e => e.stopPropagation()}>
            <div className="dice-overlay-head">
              <Icon name={timelineDetail.icon || 'star'} size={18} style={{ color: 'var(--gold-1)' }}/>
              <h2>{timelineEditMode ? 'Редагувати подію' : timelineDetail.title}</h2>
              <div className="igrow"/>
              {!timelineEditMode && <IconBtn name="edit" size={14} title="Редагувати" onClick={startTimelineEdit}/>}
              <IconBtn name="x" onClick={() => { setTimelineDetailId(null); setTimelineEditMode(false); }}/>
            </div>
            <div className="dice-overlay-body">
              {timelineEditMode && timelineEditDraft ? (
                <div className="icol ig-12">
                  <div className="flex ig-10">
                    <div style={{ flex: 1 }}>
                      <div className="field-label mb-4">Заголовок *</div>
                      <input className="input" autoFocus value={timelineEditDraft.title}
                        onChange={e => setTimelineEditDraft(d => ({ ...d, title: e.target.value }))}/>
                    </div>
                    <div style={{ width: 120 }}>
                      <div className="field-label mb-4">Дата</div>
                      <input className="input" value={timelineEditDraft.date}
                        onChange={e => setTimelineEditDraft(d => ({ ...d, date: e.target.value }))}/>
                    </div>
                  </div>
                  <div className="flex ig-10">
                    <div style={{ flex: 1 }}>
                      <div className="field-label mb-4">Тип</div>
                      <select className="input" value={timelineEditDraft.kind}
                        onChange={e => setTimelineEditDraft(d => ({ ...d, kind: e.target.value }))}>
                        {Object.entries(KIND_META).map(([k, v]) => <option key={k} value={k}>{v.label}</option>)}
                      </select>
                    </div>
                    <div style={{ width: 80 }}>
                      <div className="field-label mb-4">Сесія #</div>
                      <input className="input" type="number" min="1" value={timelineEditDraft.session}
                        onChange={e => setTimelineEditDraft(d => ({ ...d, session: e.target.value }))}/>
                    </div>
                  </div>
                  <div>
                    <div className="field-label mb-4">Опис</div>
                    <textarea className="textarea" rows="5" value={timelineEditDraft.body}
                      onChange={e => setTimelineEditDraft(d => ({ ...d, body: e.target.value }))}/>
                  </div>
                  <div>
                    <div className="field-label mb-4">Пов'язані <span className="mono dim">(через кому)</span></div>
                    <input className="input" placeholder="Корвін, Іві, Фадлебург…" value={timelineEditDraft.related}
                      onChange={e => setTimelineEditDraft(d => ({ ...d, related: e.target.value }))}/>
                  </div>
                  <div className="flex ig-8 mt-4">
                    <Btn primary onClick={saveTimelineEdit}><Icon name="check" size={12}/> Зберегти</Btn>
                    <Btn ghost onClick={() => { setTimelineEditMode(false); setTimelineEditDraft(null); }}>Скасувати</Btn>
                    <div className="igrow"/>
                    <Btn danger onClick={deleteTimelineEvent}><Icon name="trash" size={12}/> Видалити</Btn>
                  </div>
                </div>
              ) : (
                <div className="icol ig-12">
                  <div className="flex ica ig-8 mb-4">
                    <span className="caps mono" style={{ fontSize: 10, color: 'var(--gold-0)' }}>{timelineDetail.date}</span>
                    <Chip sm muted>{timelineDetail.kindLabel}</Chip>
                    {timelineDetail.session && <Chip sm>сесія {timelineDetail.session}</Chip>}
                  </div>
                  <div className="script" style={{ fontSize: 15, lineHeight: 1.65, color: 'var(--ink-1)' }}>
                    {timelineDetail.body}
                  </div>
                  {timelineDetail.related && timelineDetail.related.length > 0 && (
                    <div className="flex ig-6 iwrap mt-4">
                      {timelineDetail.related.map((r, i) => <Chip key={i} muted sm>↪ {r}</Chip>)}
                    </div>
                  )}
                </div>
              )}
            </div>
          </div>
        </div>
      )}

      {/* ===== MODAL: Нова подія хронології ===== */}
      {addTimelineOpen && (
        <div className="dice-overlay-backdrop" onClick={() => setAddTimelineOpen(false)}>
          <div className="dice-overlay" style={{ width: 520, minHeight: '65vh' }} onClick={e => e.stopPropagation()}>
            <div className="dice-overlay-head">
              <Icon name="hourglass" size={18} style={{ color: 'var(--gold-1)' }}/>
              <h2>Нова подія</h2>
              <div className="igrow"/>
              <IconBtn name="x" onClick={() => setAddTimelineOpen(false)}/>
            </div>
            <div className="dice-overlay-body" style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
              <div style={{ display: 'flex', flexDirection: 'column', flex: 1, gap: 12, minHeight: 0 }}>
                <div className="flex ig-10">
                  <div style={{ flex: 1 }}>
                    <div className="field-label mb-4">Заголовок *</div>
                    <input className="input" autoFocus placeholder="Назва події…"
                      value={newEvent.title}
                      onChange={e => setNewEvent(v => ({ ...v, title: e.target.value }))}/>
                  </div>
                  <div style={{ width: 120 }}>
                    <div className="field-label mb-4">Дата</div>
                    <input className="input"
                      value={newEvent.date}
                      onChange={e => setNewEvent(v => ({ ...v, date: e.target.value }))}/>
                  </div>
                </div>
                <div className="flex ig-10">
                  <div style={{ flex: 1 }}>
                    <div className="field-label mb-4">Тип</div>
                    <select className="input" value={newEvent.kind}
                      onChange={e => setNewEvent(v => ({ ...v, kind: e.target.value }))}>
                      {Object.entries(KIND_META).map(([k, v]) => <option key={k} value={k}>{v.label}</option>)}
                    </select>
                  </div>
                  <div style={{ width: 80 }}>
                    <div className="field-label mb-4">Сесія #</div>
                    <input className="input" type="number" min="1" placeholder="1"
                      value={newEvent.session}
                      onChange={e => setNewEvent(v => ({ ...v, session: e.target.value }))}/>
                  </div>
                </div>
                <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0 }}>
                  <div className="field-label mb-4">Опис</div>
                  <textarea className="textarea" style={{ flex: 1, resize: 'none', minHeight: 80 }}
                    placeholder="Що сталось…"
                    value={newEvent.body}
                    onChange={e => setNewEvent(v => ({ ...v, body: e.target.value }))}
                    onKeyDown={e => { if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') submitNewEvent(); }}/>
                  <div className="mono dim" style={{ fontSize: 10, marginTop: 4 }}>⌘+Enter → зберегти</div>
                </div>
                <div>
                  <div className="field-label mb-4">Пов'язані <span className="mono dim">(через кому)</span></div>
                  <input className="input" placeholder="Корвін, Іві, Фадлебург…"
                    value={newEvent.related}
                    onChange={e => setNewEvent(v => ({ ...v, related: e.target.value }))}/>
                </div>
                <div className="flex ig-8">
                  <Btn primary onClick={submitNewEvent}><Icon name="check" size={12}/> Додати</Btn>
                  <Btn ghost onClick={() => setAddTimelineOpen(false)}>Скасувати</Btn>
                </div>
              </div>
            </div>
          </div>
        </div>
      )}

      {/* ===== MODAL: Деталі NPC ===== */}
      {npcDetail && (
        <div className="dice-overlay-backdrop" onClick={() => { setNpcDetailId(null); setNpcEditMode(false); }}>
          <div className="dice-overlay" style={{ width: 440, minHeight: '55vh' }} onClick={e => e.stopPropagation()}>
            <div className="dice-overlay-head">
              <div style={{
                width: 32, height: 32, borderRadius: '50%',
                background: 'var(--bg-3)', border: '1px solid var(--gold-2)',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontFamily: 'var(--font-display)', fontSize: 12, color: 'var(--gold-1)',
              }}>{npcDetail.name.split(' ').map(p => p[0]).slice(0, 2).join('')}</div>
              <h2>{npcEditMode ? 'Редагувати NPC' : npcDetail.name}</h2>
              <div className="igrow"/>
              {!npcEditMode && <IconBtn name="edit" size={14} title="Редагувати" onClick={startNpcEdit}/>}
              <IconBtn name="x" onClick={() => { setNpcDetailId(null); setNpcEditMode(false); }}/>
            </div>
            <div className="dice-overlay-body">
              {npcEditMode && npcEditDraft ? (
                <div className="icol ig-12">
                  <div>
                    <div className="field-label mb-4">Ім'я</div>
                    <input className="input" autoFocus value={npcEditDraft.name}
                      onChange={e => setNpcEditDraft(d => ({ ...d, name: e.target.value }))}/>
                  </div>
                  <div>
                    <div className="field-label mb-4">Ставлення</div>
                    <select className="input" value={npcEditDraft.rel}
                      onChange={e => setNpcEditDraft(d => ({ ...d, rel: e.target.value }))}>
                      {['союзник','нейтр.','ворог','невідомо'].map(r => <option key={r}>{r}</option>)}
                    </select>
                  </div>
                  <div>
                    <div className="field-label mb-4">Нотатка</div>
                    <textarea className="textarea" rows="4" value={npcEditDraft.note || ''}
                      onChange={e => setNpcEditDraft(d => ({ ...d, note: e.target.value }))}/>
                  </div>
                  <div className="flex ig-8 mt-4">
                    <Btn primary onClick={saveNpcEdit}><Icon name="check" size={12}/> Зберегти</Btn>
                    <Btn ghost onClick={() => { setNpcEditMode(false); setNpcEditDraft(null); }}>Скасувати</Btn>
                    <div className="igrow"/>
                    <Btn danger onClick={deleteNpc}><Icon name="trash" size={12}/> Видалити</Btn>
                  </div>
                </div>
              ) : (
                <div className="icol ig-12">
                  <div className="flex ica ig-8">
                    <Chip color={npcDetail.rel === 'ворог' ? 'crimson' : npcDetail.rel === 'союзник' ? 'emerald' : 'azure'} fill>{npcDetail.rel}</Chip>
                    {npcDetail.role && <span className="mono dim" style={{ fontSize: 12 }}>{npcDetail.role}</span>}
                  </div>
                  {npcDetail.note && (
                    <div className="script" style={{ fontSize: 14, lineHeight: 1.65, color: 'var(--ink-1)', padding: '10px 0' }}>
                      {npcDetail.note}
                    </div>
                  )}
                  {npcDetail.tags && npcDetail.tags.length > 0 && (
                    <div className="flex ig-6 iwrap">
                      {npcDetail.tags.map((t, i) => <Chip key={i} muted sm>{t}</Chip>)}
                    </div>
                  )}
                </div>
              )}
            </div>
          </div>
        </div>
      )}

      {/* ===== MODAL: Новий NPC ===== */}
      {addNpcOpen && (
        <div className="dice-overlay-backdrop" onClick={() => setAddNpcOpen(false)}>
          <div className="dice-overlay" style={{ width: 440, minHeight: '52vh' }} onClick={e => e.stopPropagation()}>
            <div className="dice-overlay-head">
              <Icon name="character" size={18} style={{ color: 'var(--gold-1)' }}/>
              <h2>Новий NPC</h2>
              <div className="igrow"/>
              <IconBtn name="x" onClick={() => setAddNpcOpen(false)}/>
            </div>
            <div className="dice-overlay-body">
              <div className="icol ig-12">
                <div>
                  <div className="field-label mb-4">Ім'я *</div>
                  <input className="input" autoFocus placeholder="Ім'я персонажа" value={newNpc.name}
                    onChange={e => setNewNpc(v => ({ ...v, name: e.target.value }))}
                    onKeyDown={e => e.key === 'Enter' && submitNewNpc()}/>
                </div>
                <div>
                  <div className="field-label mb-4">Ставлення</div>
                  <select className="input" value={newNpc.rel}
                    onChange={e => setNewNpc(v => ({ ...v, rel: e.target.value }))}>
                    {['союзник','нейтр.','ворог','невідомо'].map(r => <option key={r}>{r}</option>)}
                  </select>
                </div>
                <div>
                  <div className="field-label mb-4">Нотатка</div>
                  <textarea className="textarea" rows="3" placeholder="Хто це і що відомо..."
                    value={newNpc.note} onChange={e => setNewNpc(v => ({ ...v, note: e.target.value }))}/>
                </div>
                <div className="flex ig-8 mt-4">
                  <Btn primary onClick={submitNewNpc}><Icon name="plus" size={12}/> Додати</Btn>
                  <Btn ghost onClick={() => setAddNpcOpen(false)}>Скасувати</Btn>
                </div>
              </div>
            </div>
          </div>
        </div>
      )}

      {/* ===== MODAL: Новий квест ===== */}
      {addQuestOpen && (
        <div className="dice-overlay-backdrop" onClick={() => setAddQuestOpen(false)}>
          <div className="dice-overlay" style={{ width: 420, minHeight: 360 }} onClick={e => e.stopPropagation()}>
            <div className="dice-overlay-head">
              <Icon name="scroll" size={18} style={{ color: 'var(--gold-1)' }}/>
              <h2>Новий квест</h2>
              <div className="igrow"/>
              <IconBtn name="x" onClick={() => setAddQuestOpen(false)}/>
            </div>
            <div className="dice-overlay-body">
              <div className="icol ig-12">
                <div>
                  <div className="field-label mb-4">Назва *</div>
                  <input className="input" autoFocus placeholder="Назва квесту…" value={newQuest.name}
                    onChange={e => setNewQuest(v => ({ ...v, name: e.target.value }))}
                    onKeyDown={e => e.key === 'Enter' && submitNewQuest()}/>
                </div>
                <div>
                  <div className="field-label mb-4">Тип</div>
                  <div className="flex ig-6">
                    {['основний','побічний','особистий'].map(k => (
                      <Chip key={k} active={newQuest.kind === k} onClick={() => setNewQuest(v => ({ ...v, kind: k }))}>{k}</Chip>
                    ))}
                  </div>
                </div>
                <div className="flex ig-8 mt-4">
                  <Btn primary onClick={submitNewQuest}><Icon name="plus" size={12}/> Додати</Btn>
                  <Btn ghost onClick={() => setAddQuestOpen(false)}>Скасувати</Btn>
                </div>
              </div>
            </div>
          </div>
        </div>
      )}

      {/* ===== MODAL: Нова сесія ===== */}
      {addSessionOpen && (
        <div className="dice-overlay-backdrop" onClick={() => setAddSessionOpen(false)}>
          <div className="dice-overlay" style={{ width: 560, minHeight: '72vh' }} onClick={e => e.stopPropagation()}>
            <div className="dice-overlay-head">
              <Icon name="book" size={18} style={{ color: 'var(--gold-1)' }}/>
              <h2>Нова сесія</h2>
              <div className="igrow"/>
              <IconBtn name="x" onClick={() => setAddSessionOpen(false)}/>
            </div>
            <div className="dice-overlay-body" style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
              <div style={{ display: 'flex', flexDirection: 'column', flex: 1, gap: 12, minHeight: 0 }}>
                <div className="flex ig-10">
                  <div style={{ flex: 1 }}>
                    <div className="field-label mb-4">Заголовок</div>
                    <input className="input" placeholder="Назва сесії…" autoFocus
                      value={newSessionTitle}
                      onChange={e => setNewSessionTitle(e.target.value)}
                      onKeyDown={e => e.key === 'Enter' && e.target.blur()}/>
                  </div>
                  <div style={{ width: 130 }}>
                    <div className="field-label mb-4">Дата</div>
                    <input className="input"
                      value={newSessionDate}
                      onChange={e => setNewSessionDate(e.target.value)}/>
                  </div>
                </div>
                <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0 }}>
                  <div className="field-label mb-4">Нотатки сесії</div>
                  <textarea className="textarea" style={{ flex: 1, resize: 'none', minHeight: 80 }}
                    placeholder="Що сталося під час сесії…"
                    value={newSessionBody}
                    onChange={e => setNewSessionBody(e.target.value)}
                    onKeyDown={e => { if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') submitNewSession(); }}/>
                  <div className="mono dim" style={{ fontSize: 10, marginTop: 4 }}>⌘+Enter → зберегти</div>
                </div>
                <div>
                  <div className="field-label mb-4">Теги <span className="mono dim">(через кому)</span></div>
                  <input className="input" placeholder="Бій, Знахідка, Місто…"
                    value={newSessionTags}
                    onChange={e => setNewSessionTags(e.target.value)}/>
                </div>
                <div className="flex ig-8">
                  <Btn primary onClick={submitNewSession}><Icon name="check" size={12}/> Зберегти</Btn>
                  <Btn ghost onClick={() => setAddSessionOpen(false)}>Скасувати</Btn>
                </div>
              </div>
            </div>
          </div>
        </div>
      )}
    </>
  );
};

window.ScreenNotes = ScreenNotes;
