/* ============================================================
   screens-a.jsx — Today, Habits, Library, Material detail
   Exposes window.Screens = { today, habits, library, material }
   ============================================================ */
const React = window.React;
const { useState, useRef } = React;
const Icon = window.Icon;
const A = window.PlannerActions;

const DAY_NAMES = ["Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Вс"];

/* helper: navigation handler passed via props.nav */

/* ================= TODAY ================= */
function TodayScreen({ state, day, tweaks, nav }) {
  const Cmp = window;
  const [adding, setAdding] = useState(false);
  const [draft, setDraft] = useState("");
  const [draftDesc, setDraftDesc] = useState("");
  const [draftPts, setDraftPts] = useState(25);
  const [draftTime, setDraftTime] = useState("");
  const [draftTimeEnd, setDraftTimeEnd] = useState("");
  const tasks = state.tasks;
  const doneCount = tasks.filter((t) => t.done).length;
  const goodHabits = state.habits.filter((h) => h.kind === "good");
  const i = state.todayIdx;

  const submit = () => {
    if (!draft.trim()) return;
    const t = draftTime || null;
    const te = draftTimeEnd || null;
    let dur = 45;
    if (t && te) {
      const [h1, m1] = t.split(":").map(Number);
      const [h2, m2] = te.split(":").map(Number);
      const diff = (h2 * 60 + m2) - (h1 * 60 + m1);
      if (diff > 0) dur = diff;
    }
    A.addTask({ title: draft.trim(), desc: draftDesc.trim(), pts: Number(draftPts) || 0, time: t, timeEnd: te, dur, kind: "personal", linkId: null });
    setDraft(""); setDraftDesc(""); setDraftPts(25); setDraftTime(""); setDraftTimeEnd(""); setAdding(false);
  };

  return (
    <div className="page screen-enter">
      <div className="page-head">
        <div className="page-head__titles">
          <div className="kicker-row"><span className="eyebrow-mono">Сегодня</span><span className="date-stamp">{state.dateLabel}</span></div>
          <h1 className="page-title">{(() => { const h = new Date().getHours(); return h >= 5 && h < 12 ? "Доброе утро." : h >= 12 && h < 18 ? "Добрый день." : h >= 18 && h < 23 ? "Добрый вечер." : "Доброй ночи."; })()}</h1>
        </div>
        <div className="page-actions">
          <Cmp.GButton icon="plus" variant="ink" onClick={() => setAdding((v) => !v)}>Новая задача</Cmp.GButton>
        </div>
      </div>

      <div className="cols cols--today">
        {/* LEFT: tasks */}
        <div className="stack-5">
          {adding && (
            <div className="task" style={{ display: "block" }}>
              <div className="row-3" style={{ gap: 12 }}>
                <input autoFocus value={draft} onChange={(e) => setDraft(e.target.value)}
                  onKeyDown={(e) => e.key === "Enter" && !e.shiftKey && submit()}
                  placeholder="Что нужно сделать?"
                  style={{ flex: 1, border: "none", background: "transparent", fontFamily: "var(--font-slab)", fontSize: "var(--t-body-lg)", outline: "none" }} />
                <div className="row-2 mono" style={{ fontSize: 13 }}>
                  <span className="muted">PTS</span>
                  <input type="number" value={draftPts} onChange={(e) => setDraftPts(e.target.value)}
                    style={{ width: 56, border: "1px solid var(--ink-100)", padding: "4px 6px", fontFamily: "var(--font-mono)", background: "var(--paper-00)" }} />
                </div>
                <Cmp.GButton variant="signal" onClick={submit}>Добавить</Cmp.GButton>
              </div>
              <textarea value={draftDesc} onChange={(e) => setDraftDesc(e.target.value)}
                placeholder="Описание (необязательно)"
                rows={2}
                style={{ width: "100%", marginTop: 10, border: "1px solid var(--ink-40)", background: "var(--paper-00)", padding: "8px 10px", fontFamily: "var(--font-slab)", fontSize: "var(--t-body)", resize: "vertical", outline: "none", boxSizing: "border-box" }} />
              <div className="row-3" style={{ marginTop: 10, gap: 10, alignItems: "center" }}>
                <span className="e-label">Время:</span>
                <input type="time" value={draftTime} onChange={(e) => setDraftTime(e.target.value)}
                  style={{ border: "1px solid var(--ink-40)", padding: "4px 8px", fontFamily: "var(--font-mono)", background: "var(--paper-00)", fontSize: "var(--t-small)" }} />
                <span className="muted">—</span>
                <input type="time" value={draftTimeEnd} onChange={(e) => setDraftTimeEnd(e.target.value)}
                  style={{ border: "1px solid var(--ink-40)", padding: "4px 8px", fontFamily: "var(--font-mono)", background: "var(--paper-00)", fontSize: "var(--t-small)" }} />
              </div>
            </div>
          )}

          <div>
            <Cmp.SectionRule kicker="План дня" right={<span className="e-label">{doneCount}/{tasks.length} готово</span>}>Задачи</Cmp.SectionRule>
            <div className="stack">
              {tasks.map((t) => <TaskRow key={t.id} t={t} state={state} nav={nav} />)}
            </div>
          </div>
        </div>

        {/* RIGHT: scale + quick habits */}
        <div className="stack-5">
          <div className="task" style={{ display: "block", padding: "var(--s-5)" }}>
            <Cmp.SectionRule kicker="Шкала">Баллы за день</Cmp.SectionRule>
            <Cmp.PointsScale day={day} variant={tweaks.scaleVariant} />
            <div className="row-3" style={{ marginTop: "var(--s-5)", justifyContent: "space-between" }}>
              <div><div className="e-label">Прогресс к цели</div>
                <div className="ring-total" style={{ fontSize: 22 }}>{Math.round((day.net / day.target) * 100)}%</div></div>
              <Cmp.GButton variant="ghost" icon="stats" onClick={() => nav({ screen: "stats" })}>Статистика</Cmp.GButton>
            </div>
          </div>

          <div className="task" style={{ display: "block", padding: "var(--s-5)" }}>
            <Cmp.SectionRule kicker="Журнал" right={<span className="task__link" onClick={() => nav({ screen: "habits" })}>все<Icon name="arrow" size={13} /></span>}>Привычки</Cmp.SectionRule>
            <div className="stack-3">
              {goodHabits.slice(0, 4).map((h) => (
                <div key={h.id} className="row-3" style={{ gap: 12 }}>
                  <span className="habit__icon" style={{ width: 30, height: 30, flex: "0 0 30px", background: h.days[i] ? "var(--ok-tint)" : "var(--paper-00)" }}>
                    <Icon name={h.icon} size={16} />
                  </span>
                  <span style={{ flex: 1 }}>{h.name}</span>
                  <span className="task__pts pts-pos">+{h.pts}</span>
                  <button className={"task__check" + (h.days[i] ? " task__check--on" : "")} onClick={() => A.toggleHabitToday(h.id)}>
                    {h.days[i] && <Icon name="check" size={16} />}
                  </button>
                </div>
              ))}
            </div>
          </div>

          <MoodCard state={state} />
        </div>
      </div>
    </div>
  );
}

function TaskRow({ t, state, nav }) {
  const Cmp = window;
  const [open, setOpen] = useState(false);
  const [noteDraft, setNoteDraft] = useState("");
  const [editingDesc, setEditingDesc] = useState(false);
  const [descDraft, setDescDraft] = useState(t.desc || "");
  const linked = window.PlannerLookup.entity(state, t.linkId);
  const today = window.timeToday(t.timeLog, state.todayIdx);
  const week = window.timeWeek(t.timeLog);
  const hasNotes = (t.notes || []).length > 0;
  const hasDesc = !!t.desc;

  const saveDesc = () => {
    A.updateTaskDesc(t.id, descDraft.trim());
    setEditingDesc(false);
  };

  const addNote = () => {
    if (!noteDraft.trim()) return;
    A.addTaskNote(t.id, noteDraft);
    setNoteDraft("");
  };

  return (
    <div className={"task task--expandable" + (t.done ? " task--done" : "")} style={{ display: "block" }}>
      <div style={{ display: "flex", alignItems: "center", gap: "var(--s-4)" }}>
        <button className={"task__check" + (t.done ? " task__check--on" : "")} onClick={() => A.toggleTask(t.id)}>
          {t.done && <Icon name="check" size={17} />}
        </button>
        <div className="task__body" style={{ cursor: "pointer" }} onClick={() => setOpen((v) => !v)}>
          <div className="task__title">{t.title}</div>
          {hasDesc && !open && <div className="task__desc-preview">{t.desc}</div>}
          <div className="task__meta">
            {t.time && <span className="chip-time">{t.time}</span>}
            <span className={"task__pts " + (t.done ? "pts-pos" : "pts-ink")}>+{t.pts} PTS</span>
            <Cmp.TimeLogger timer={state.timer} kind="task" id={t.id} today={today} week={week}
              onStart={(k, i) => A.startTimer(k, i)} onStop={() => A.stopTimer()} onAdd={(sec) => A.logTime("task", t.id, sec)} />
            {linked && (
              <span className="task__link" onClick={(e) => { e.stopPropagation(); nav(linked._kind === "course" ? { screen: "course", id: linked.id } : { screen: "material", id: linked.id }); }}>
                <Icon name="link" size={13} />{linked.title.length > 30 ? linked.title.slice(0, 30) + "…" : linked.title}
              </span>
            )}
            {t.tags && t.tags.map((tg) => <span key={tg} className="link-chip__kind">#{tg}</span>)}
            {(hasNotes || hasDesc) && <span className="task__expand-hint" onClick={(e) => { e.stopPropagation(); setOpen((v) => !v); }}>
              <Icon name={open ? "arrowUp" : "arrow"} size={12} />{hasNotes ? (t.notes.length) : ""}
            </span>}
          </div>
        </div>
      </div>

      {open && (
        <div className="task__detail">
          <div className="task__detail-section">
            <div className="row-3" style={{ justifyContent: "space-between", marginBottom: 6 }}>
              <span className="e-label">Описание</span>
              {!editingDesc && <span className="task__link" onClick={() => { setDescDraft(t.desc || ""); setEditingDesc(true); }}><Icon name="plus" size={12} />{hasDesc ? "изменить" : "добавить"}</span>}
            </div>
            {editingDesc ? (
              <div>
                <textarea value={descDraft} onChange={(e) => setDescDraft(e.target.value)} autoFocus rows={2}
                  placeholder="Опишите задачу…"
                  className="task__desc-input" />
                <div className="row-2" style={{ gap: 8, marginTop: 6 }}>
                  <Cmp.GButton variant="signal" onClick={saveDesc} style={{ padding: "6px 14px", fontSize: 12 }}>Сохранить</Cmp.GButton>
                  <Cmp.GButton variant="ghost" onClick={() => setEditingDesc(false)} style={{ padding: "6px 14px", fontSize: 12 }}>Отмена</Cmp.GButton>
                </div>
              </div>
            ) : (
              hasDesc ? <div className="task__desc-text">{t.desc}</div> : <div className="muted" style={{ fontSize: "var(--t-small)" }}>Нет описания</div>
            )}
          </div>

          <div className="task__detail-section">
            <span className="e-label" style={{ marginBottom: 6, display: "block" }}>Заметки · история</span>
            {(t.notes || []).length > 0 ? (
              <div className="task__notes-list">
                {(t.notes || []).map((n) => (
                  <div key={n.id} className="task__note-item">
                    <span className="task__note-date">{n.date}</span>
                    <span className="task__note-text">{n.text}</span>
                    <button className="task__note-remove" onClick={() => A.removeTaskNote(t.id, n.id)} title="Удалить"><Icon name="close" size={12} /></button>
                  </div>
                ))}
              </div>
            ) : (
              <div className="muted" style={{ fontSize: "var(--t-small)", marginBottom: 8 }}>Пока нет записей.</div>
            )}
            <div className="row-3" style={{ gap: 8, marginTop: 8 }}>
              <input value={noteDraft} onChange={(e) => setNoteDraft(e.target.value)}
                onKeyDown={(e) => e.key === "Enter" && addNote()}
                placeholder="Добавить заметку…"
                style={{ flex: 1, border: "1px solid var(--ink-40)", background: "var(--paper-00)", padding: "6px 10px", fontFamily: "var(--font-slab)", fontSize: "var(--t-small)", outline: "none" }} />
              <Cmp.GButton variant="ink" onClick={addNote} style={{ padding: "6px 14px", fontSize: 12 }}>+</Cmp.GButton>
            </div>
          </div>
          <div className="task__detail-section" style={{ borderTop: "var(--bd-hair)", paddingTop: 8, marginTop: 8 }}>
            <span className="task__link" style={{ color: "var(--signal)", fontSize: "var(--t-small)" }}
              onClick={() => { if (confirm("Удалить задачу «" + t.title + "»?")) A.removeTask(t.id); }}>
              <Icon name="close" size={12} /> удалить задачу
            </span>
          </div>
        </div>
      )}
    </div>
  );
}

/* ================= HABITS ================= */
const HABIT_ICONS = ["book", "run", "shield", "drop", "moon", "burger", "check", "star", "flame", "flask", "film", "notes", "habits", "user"];

function HabitsScreen({ state, day, tweaks, nav }) {
  const Cmp = window;
  const i = state.todayIdx;
  const good = state.habits.filter((h) => h.kind === "good");
  const bad = state.habits.filter((h) => h.kind === "bad");
  const variant = tweaks.habitsVariant;
  const [adding, setAdding] = useState(false);
  const [hName, setHName] = useState("");
  const [hKind, setHKind] = useState("good");
  const [hPts, setHPts] = useState(15);
  const [hIcon, setHIcon] = useState("check");

  const submitHabit = () => {
    if (!hName.trim()) return;
    A.addHabit({ name: hName.trim(), kind: hKind, pts: Number(hPts) || 15, icon: hIcon });
    setHName(""); setHKind("good"); setHPts(15); setHIcon("check"); setAdding(false);
  };

  const streak = (h) => {
    let s = 0;
    for (let k = i; k >= 0; k--) { if (h.days[k]) s++; else break; }
    return s;
  };
  const weekTotal = (h) => {
    const n = h.days.filter(Boolean).length;
    return h.kind === "good" ? n * h.pts : -n * h.pts;
  };

  return (
    <div className="page screen-enter">
      <div className="page-head">
        <div className="page-head__titles">
          <div className="kicker-row"><span className="eyebrow-mono">Журнал привычек</span><span className="date-stamp">Эта неделя</span></div>
          <h1 className="page-title">Привычки</h1>
        </div>
        <div className="page-actions"><Cmp.GButton icon="plus" variant="ink" onClick={() => setAdding((v) => !v)}>Привычка</Cmp.GButton></div>
      </div>

      {adding && (
        <div className="task" style={{ display: "block", padding: "var(--s-5)", marginBottom: "var(--s-5)" }}>
          <Cmp.SectionRule kicker="Новая">Добавить привычку</Cmp.SectionRule>
          <div className="stack-3">
            <input autoFocus value={hName} onChange={(e) => setHName(e.target.value)}
              onKeyDown={(e) => e.key === "Enter" && submitHabit()}
              placeholder="Название привычки"
              style={{ width: "100%", border: "1px solid var(--ink-100)", background: "var(--paper-00)", padding: "10px 12px", fontFamily: "var(--font-slab)", fontSize: "var(--t-body-lg)", outline: "none", boxSizing: "border-box" }} />
            <div className="row-3" style={{ gap: 12, alignItems: "center" }}>
              <span className="e-label">Тип:</span>
              <div className="seg">
                <button className={"seg__btn" + (hKind === "good" ? " seg__btn--on" : "")} onClick={() => setHKind("good")}>Полезная</button>
                <button className={"seg__btn" + (hKind === "bad" ? " seg__btn--on" : "")} onClick={() => setHKind("bad")}>Вредная</button>
              </div>
              <span className="e-label" style={{ marginLeft: 16 }}>Баллы:</span>
              <input type="number" value={hPts} onChange={(e) => setHPts(e.target.value)}
                style={{ width: 64, border: "1px solid var(--ink-40)", padding: "4px 8px", fontFamily: "var(--font-mono)", background: "var(--paper-00)" }} />
            </div>
            <div>
              <span className="e-label" style={{ marginBottom: 8, display: "block" }}>Иконка:</span>
              <div className="row-2 wrap gap-2">
                {HABIT_ICONS.map((ic) => (
                  <button key={ic} onClick={() => setHIcon(ic)}
                    style={{ width: 36, height: 36, display: "grid", placeItems: "center", border: hIcon === ic ? "2px solid var(--ink-100)" : "1px solid var(--ink-40)", background: hIcon === ic ? "var(--paper-30)" : "var(--paper-00)", cursor: "pointer" }}>
                    <Icon name={ic} size={18} />
                  </button>
                ))}
              </div>
            </div>
            <div className="row-2" style={{ gap: 8, marginTop: 4 }}>
              <Cmp.GButton variant="signal" icon="check" onClick={submitHabit}>Добавить</Cmp.GButton>
              <Cmp.GButton variant="ghost" onClick={() => setAdding(false)}>Отмена</Cmp.GButton>
            </div>
          </div>
        </div>
      )}

      <div className="task" style={{ display: "flex", gap: "var(--s-6)", padding: "var(--s-5)", marginBottom: "var(--s-6)", alignItems: "center", flexWrap: "wrap" }}>
        <div><div className="e-label">Сегодня от привычек</div>
          <div className="ring-total" style={{ fontSize: 40, color: day.habitPts < 0 ? "var(--signal)" : "var(--ink-100)" }}>{day.habitPts > 0 ? "+" : ""}{day.habitPts}</div></div>
        <div className="section-rule__line" />
        <div className="row-3" style={{ gap: 24 }}>
          <div><div className="e-label">Полезных закрыто</div><div className="ring-total" style={{ fontSize: 28 }}>{good.filter((h) => h.days[i]).length}/{good.length}</div></div>
          <div><div className="e-label">Срывов</div><div className="ring-total" style={{ fontSize: 28, color: "var(--signal)" }}>{bad.filter((h) => h.days[i]).length}</div></div>
        </div>
      </div>

      {variant === "week" ? (
        <HabitWeekGrid state={state} good={good} bad={bad} weekTotal={weekTotal} />
      ) : (
        <div className="cols cols--2">
          <div>
            <Cmp.SectionRule kicker="+ Баллы">Полезные</Cmp.SectionRule>
            {good.map((h) => <HabitRow key={h.id} h={h} i={i} streak={streak(h)} />)}
          </div>
          <div>
            <Cmp.SectionRule kicker="− Баллы">Вредные</Cmp.SectionRule>
            {bad.map((h) => <HabitRow key={h.id} h={h} i={i} streak={streak(h)} />)}
          </div>
        </div>
      )}
    </div>
  );
}

function HabitRow({ h, i, streak }) {
  const on = h.days[i];
  const good = h.kind === "good";
  return (
    <div className={"habit habit--" + h.kind}>
      <span className="habit__icon"><Icon name={h.icon} size={20} /></span>
      <div className="habit__body">
        <div className="habit__name">{h.name}</div>
        <div className="habit__streak">
          {good ? <>серия {streak} {plural(streak)} · </> : ""}
          {good ? "+" : "−"}{h.pts} баллов
          {good && streak >= 3 && <> · <Icon name="flame" size={12} style={{ display: "inline", verticalAlign: "-2px", color: "var(--signal)" }} /></>}
        </div>
      </div>
      <button className={"habit__toggle" + (on ? (good ? " habit__toggle--on-good" : " habit__toggle--on-bad") : "")}
        onClick={() => window.PlannerActions.toggleHabitToday(h.id)}>
        {on ? (good ? "✓ +" + h.pts : "✕ −" + h.pts) : (good ? "Отметить" : "Был срыв")}
      </button>
      <button className="note-card__action" title="Удалить привычку" style={{ marginLeft: 4 }}
        onClick={() => { if (confirm("Удалить привычку «" + h.name + "»?")) window.PlannerActions.removeHabit(h.id); }}>
        <Icon name="close" size={13} />
      </button>
    </div>
  );
}

function HabitWeekGrid({ state, good, bad, weekTotal }) {
  const Cmp = window;
  const i = state.todayIdx;
  const renderGroup = (list, title, kicker) => (
    <div style={{ marginBottom: "var(--s-6)" }}>
      <Cmp.SectionRule kicker={kicker}>{title}</Cmp.SectionRule>
      <div className="task" style={{ display: "block", padding: "var(--s-5)" }}>
        <div className="habit-week">
          <span className="habit-week__head" style={{ textAlign: "left" }}>Привычка</span>
          {DAY_NAMES.map((d) => <span key={d} className="habit-week__head">{d}</span>)}
          <span className="habit-week__head" style={{ textAlign: "right" }}>Σ</span>
          {list.map((h) => (
            <React.Fragment key={h.id}>
              <span className="habit-week__name"><Icon name={h.icon} size={15} style={{ display: "inline", verticalAlign: "-2px", marginRight: 6 }} />{h.name}</span>
              {h.days.map((on, di) => (
                <button key={di}
                  className={"habit-cell" + (on ? (h.kind === "good" ? " habit-cell--on-good" : " habit-cell--on-bad") : "") + (di === i ? " habit-cell--today" : "")}
                  onClick={() => window.PlannerActions.toggleHabitDay(h.id, di)}>
                  {on && <Icon name={h.kind === "good" ? "check" : "close"} size={14} style={{ color: "#fff" }} />}
                </button>
              ))}
              <span className="habit-week__total" style={{ color: weekTotal(h) < 0 ? "var(--signal)" : "var(--ink-100)" }}>{weekTotal(h) > 0 ? "+" : ""}{weekTotal(h)}</span>
            </React.Fragment>
          ))}
        </div>
      </div>
    </div>
  );
  return <div>{renderGroup(good, "Полезные", "+ Баллы")}{renderGroup(bad, "Вредные", "− Баллы")}</div>;
}

function plural(n) {
  const m10 = n % 10, m100 = n % 100;
  if (m10 === 1 && m100 !== 11) return "день";
  if (m10 >= 2 && m10 <= 4 && (m100 < 10 || m100 >= 20)) return "дня";
  return "дней";
}

/* ---- Daily state / mood check-in (collapsible) --------------- */
function MoodCard({ state }) {
  const Cmp = window;
  const today = state.moods[state.todayIdx] || {};
  const Q = window.MOOD_QUESTIONS;
  const answered = Q.filter((q) => today[q.id] != null).length;
  const [open, setOpen] = useState(answered < Q.length);
  return (
    <div className="task" style={{ display: "block", padding: "var(--s-5)" }}>
      <Cmp.SectionRule kicker="Состояние" right={
        <span className="task__link" onClick={() => setOpen((o) => !o)}>{open ? "свернуть" : "изменить"}<Icon name={open ? "arrowUp" : "arrow"} size={13} /></span>
      }>Состояние дня</Cmp.SectionRule>
      {!open ? (
        <div className="mood-summary">
          {Q.map((q) => {
            const v = today[q.id];
            return (
              <div key={q.id} className="mood-summary__row">
                <span className="mood-summary__label">{q.label}</span>
                <span className="mood-summary__dot" style={{ background: v == null ? "var(--paper-30)" : v < 0 ? "var(--signal)" : v > 0 ? "var(--ink-100)" : "var(--ink-40)" }} />
                <span className="mono" style={{ width: 26, textAlign: "right", color: v == null ? "var(--text-faint)" : v < 0 ? "var(--signal)" : "var(--ink-100)" }}>{v == null ? "—" : (v > 0 ? "+" : "") + v}</span>
              </div>
            );
          })}
          <div className="muted" style={{ fontSize: "var(--t-meta)", marginTop: 8 }}>Уходит в статистику · на баллы не влияет</div>
        </div>
      ) : (
        <>
          <Cmp.MoodEntry mood={today} onChange={(f, v) => A.setMood(f, v)} />
          <div className="muted" style={{ fontSize: "var(--t-meta)", marginTop: 12 }}>Шкала −5…+5 · на баллы не влияет, только в статистику</div>
        </>
      )}
    </div>
  );
}

/* ================= LIBRARY ================= */
function LibraryScreen({ state, tweaks, nav }) {
  const Cmp = window;
  const [layout, setLayout] = useState(tweaks.libraryLayout || "grid");
  const [filter, setFilter] = useState("all");
  const [tag, setTag] = useState(null);
  React.useEffect(() => { setLayout(tweaks.libraryLayout || "grid"); }, [tweaks.libraryLayout]);

  let items = state.materials;
  if (filter !== "all") items = items.filter((m) => m.type === filter);
  if (tag) items = items.filter((m) => m.tags.includes(tag));

  const allTags = [...new Set(state.materials.flatMap((m) => m.tags))].slice(0, 10);
  const types = [["all", "Всё", "grid"], ["fiction", "Худлит", "book"], ["science", "Наука", "flask"], ["video", "Видео", "film"]];

  return (
    <div className="page page--wide screen-enter">
      <div className="page-head">
        <div className="page-head__titles">
          <div className="kicker-row"><span className="eyebrow-mono">Библиотека</span><span className="date-stamp">{state.materials.length} материалов</span></div>
          <h1 className="page-title">Библиотека</h1>
        </div>
        <div className="page-actions"><Cmp.GButton icon="plus" variant="ink" onClick={() => nav({ screen: "addMaterial" })}>Добавить</Cmp.GButton></div>
      </div>

      <div className="toolbar">
        <div className="seg">
          {types.map(([v, label, ic]) => (
            <button key={v} className={"seg__btn" + (filter === v ? " seg__btn--on" : "")} onClick={() => setFilter(v)}>
              <Icon name={ic} size={14} />{label}
            </button>
          ))}
        </div>
        <div className="spacer" />
        <div className="seg">
          {[["grid", "grid"], ["list", "list"], ["shelf", "shelf"]].map(([v, ic]) => (
            <button key={v} className={"seg__btn" + (layout === v ? " seg__btn--on" : "")} onClick={() => setLayout(v)} title={v}>
              <Icon name={ic} size={15} />
            </button>
          ))}
        </div>
      </div>

      <div className="row-2 wrap gap-2" style={{ marginBottom: "var(--s-5)" }}>
        {allTags.map((tg) => <Cmp.GTag key={tg} active={tag === tg} onClick={() => setTag(tag === tg ? null : tg)}>{tg}</Cmp.GTag>)}
      </div>

      {layout === "grid" && <LibGrid items={items} nav={nav} />}
      {layout === "list" && <LibList items={items} nav={nav} />}
      {layout === "shelf" && <LibShelf state={state} nav={nav} />}
    </div>
  );
}

function LibGrid({ items, nav }) {
  const Cmp = window;
  return (
    <div className="lib-grid lib-grid--lg">
      {items.map((m) => (
        <div className="lib-item" key={m.id}>
          <Cmp.Cover m={m} onClick={() => nav({ screen: "material", id: m.id })} />
          <div className="lib-item__meta">
            <div className="row-3" style={{ justifyContent: "space-between" }}>
              <Cmp.StatusBadge status={m.status} />
              <Cmp.RatingPips value={m.rating} />
            </div>
            <Cmp.ProgressBar value={m.progress.current} total={m.progress.total} />
            <div className="meter-num">{m.progress.current} / {m.progress.total} {m.progress.unit}</div>
          </div>
        </div>
      ))}
    </div>
  );
}

function LibList({ items, nav }) {
  const Cmp = window;
  return (
    <div className="lib-list">
      <div className="lib-row" style={{ cursor: "default", borderBottom: "2px solid var(--ink-100)" }}>
        <span></span>
        <span className="e-label">Название</span>
        <span className="e-label">Прогресс</span>
        <span className="e-label">Теги</span>
        <span className="e-label" style={{ textAlign: "right" }}>Оценка</span>
      </div>
      {items.map((m) => (
        <div className="lib-row" key={m.id} onClick={() => nav({ screen: "material", id: m.id })}>
          <div className="lib-row__cover"><Cmp.Cover m={m} showBar={false} /></div>
          <div>
            <div className="lib-item__title">{m.title}</div>
            <div className="lib-item__author">{m.author}</div>
          </div>
          <div className="stack" style={{ gap: 5 }}>
            <Cmp.ProgressBar value={m.progress.current} total={m.progress.total} />
            <span className="meter-num">{m.progress.current}/{m.progress.total} {m.progress.unit}</span>
          </div>
          <div><Cmp.StatusBadge status={m.status} /></div>
          <div style={{ textAlign: "right" }}><Cmp.RatingPips value={m.rating} /></div>
        </div>
      ))}
    </div>
  );
}

function LibShelf({ state, nav }) {
  const groups = [
    ["fiction", "Художественная литература"],
    ["science", "Научная литература"],
    ["video", "Видео и лекции"],
  ];
  const heights = ["spine--tall", "", "spine--short"];
  return (
    <div>
      {groups.map(([type, label]) => {
        const items = state.materials.filter((m) => m.type === type);
        return (
          <div className="shelf" key={type}>
            <window.SectionRule kicker={"Полка"}>{label}</window.SectionRule>
            <div className="shelf__books">
              {items.map((m, idx) => (
                <div key={m.id} className={"spine " + heights[idx % 3]}
                  style={{ background: `linear-gradient(180deg, ${m.cover.from}, ${m.cover.to})`, color: m.cover.fg }}
                  onClick={() => nav({ screen: "material", id: m.id })} title={m.title}>
                  <span className="spine__txt">{m.title}</span>
                </div>
              ))}
            </div>
            <div className="shelf__plank" />
          </div>
        );
      })}
    </div>
  );
}

window.Screens = Object.assign(window.Screens || {}, {
  today: TodayScreen, habits: HabitsScreen, library: LibraryScreen,
});
