// Diary / Portfolio / Goals / Habits — wired to real data via window.LifeData
// Memories / Letters / Notes — Phase 2 placeholders

const { useState: useStateD, useMemo: useMemoD, useEffect: useEffectD } = React;

/* ─── DIARY ─────────────────────────────────────────────────────── */
function DiaryPage({ data }) {
  const [entries, setEntries] = useStateD(data.diary);
  const [idx, setIdx] = useStateD(0);
  const [composing, setComposing] = useStateD(entries.length === 0);

  // Find today's entry index, or default to most recent
  const todayIso = window.LifeData.todayHKT();
  const todayExists = entries.some(e => e.isoDate === todayIso);

  useEffectD(() => {
    setEntries(window.LifeData.diary);
  }, [composing]);

  const entry = entries[idx];

  const onSaved = (savedIso) => {
    setEntries([...window.LifeData.diary]);
    const newIdx = window.LifeData.diary.findIndex(e => e.isoDate === savedIso);
    setIdx(Math.max(0, newIdx));
    setComposing(false);
  };

  return (
    <div className="page-in diary-shell" style={{ display: "grid", gridTemplateColumns: "240px 1fr", height: "100%", padding: 0 }}>
      <aside style={{ borderRight: "1px solid var(--rule)", padding: "32px 0", overflow: "auto" }} className="paper-scroll">
        <div style={{ padding: "0 24px 16px" }}>
          <div className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)" }}>Chapter I</div>
          <h2 className="han-display" style={{ fontSize: 22, margin: "4px 0 0", letterSpacing: "0.25em" }}>日 記</h2>
          <button className="btn btn-gold" style={{ marginTop: 16, width: "100%", justifyContent: "center" }} onClick={() => setComposing(true)}>
            ✦ {todayExists ? "編輯今日" : "寫今日"}
          </button>
        </div>
        <hr className="rule" style={{ margin: "0 12px" }} />
        <div style={{ padding: "12px 0" }}>
          {entries.length === 0 && (
            <div style={{ padding: "20px 24px", color: "var(--ink-3)", fontSize: 13 }}>尚無記錄</div>
          )}
          {entries.map((d, i) => (
            <div key={d.isoDate} onClick={() => { setIdx(i); setComposing(false); }} style={{
              padding: "12px 24px", cursor: "pointer",
              borderLeft: i === idx && !composing ? "3px solid var(--gold)" : "3px solid transparent",
              background: i === idx && !composing ? "oklch(0.90 0.025 78 / 0.5)" : "transparent"
            }}>
              <div className="mono" style={{ fontSize: 11, color: "var(--ink-3)", letterSpacing: "0.1em" }}>{d.date} · {d.weekday}</div>
              <div className="han-display" style={{ fontSize: 15, marginTop: 4, fontWeight: 500 }}>{d.title}</div>
              <div className="han-body" style={{ fontSize: 12, color: "var(--ink-3)", marginTop: 4, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
                {d.body.slice(0, 30)}
              </div>
            </div>
          ))}
        </div>
      </aside>

      <div style={{ overflow: "auto", padding: "56px 80px 100px" }} className="paper-scroll">
        {composing ? (
          <ComposeEntry
            initial={entries.find(e => e.isoDate === todayIso)?.body || ""}
            onSaved={onSaved}
            onCancel={() => setComposing(false)}
          />
        ) : entry ? (
          <article style={{ maxWidth: 640, margin: "0 auto" }}>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 8 }}>
              <div className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)" }}>Entry · {entries.length - idx}</div>
              <div className="mono" style={{ fontSize: 11, color: "var(--ink-3)" }}>{entry.date}</div>
            </div>
            <h1 className="han-display" style={{ fontSize: 36, margin: "8px 0", fontWeight: 500 }}>{entry.title}</h1>
            <div className="han-body" style={{ display: "flex", gap: 14, fontSize: 13, color: "var(--ink-3)" }}>
              <span>{entry.weekday}</span>
              {entry.weather !== '—' && <><span>·</span><span>{entry.weather}</span></>}
              {entry.mood !== '—' && <><span>·</span><span>心境：{entry.mood}</span></>}
            </div>
            <hr className="rule" style={{ margin: "24px 0" }} />
            <DropCapBody body={entry.body} />
            {entry.tags.length > 0 && (
              <div style={{ display: "flex", gap: 8, marginTop: 32, flexWrap: "wrap" }}>
                {entry.tags.map(t => <span key={t} className="tag">#{t}</span>)}
              </div>
            )}
            <div style={{ marginTop: 48, textAlign: "center", color: "var(--ink-3)" }}>
              <span style={{ fontFamily: "var(--font-en)", fontStyle: "italic", fontSize: 14 }}>~ fin ~</span>
            </div>
          </article>
        ) : (
          <div style={{ textAlign: "center", padding: "80px 0", color: "var(--ink-3)" }}>
            <p className="han-body" style={{ fontSize: 16 }}>仍未開卷。撳「寫今日」記下第一頁。</p>
          </div>
        )}
      </div>
    </div>
  );
}

function DropCapBody({ body }) {
  const paras = body.split("\n\n").filter(p => p.trim());
  return (
    <div className="han-body" style={{ fontSize: 16.5, color: "var(--ink)", lineHeight: 2 }}>
      {paras.map((p, i) => (
        <p key={i} style={{ margin: "0 0 1.4em" }}>
          {i === 0 ? (
            <>
              <span style={{
                float: "left", fontFamily: "var(--font-han)",
                fontSize: 56, lineHeight: 0.9, fontWeight: 600,
                color: "var(--gold-deep)", marginRight: 8, marginTop: 6
              }}>{p[0]}</span>
              {p.slice(1)}
            </>
          ) : p}
        </p>
      ))}
    </div>
  );
}

function ComposeEntry({ initial, onSaved, onCancel }) {
  const [body, setBody] = useStateD(initial || "");
  const [saving, setSaving] = useStateD(false);
  const [err, setErr] = useStateD(null);

  const save = async () => {
    if (!body.trim()) { setErr('內容空白'); return; }
    setSaving(true);
    setErr(null);
    try {
      const iso = window.LifeData.todayHKT();
      await window.LifeData.saveDiary(iso, body);
      onSaved(iso);
    } catch (e) {
      console.error(e);
      setErr('儲存失敗：' + (e?.message || e));
      setSaving(false);
    }
  };

  const todayIso = window.LifeData.todayHKT();
  const today = new Date(todayIso + 'T00:00:00+08:00');
  const dateStr = `${today.getUTCFullYear()}.${String(today.getUTCMonth()+1).padStart(2,"0")}.${String(today.getUTCDate()).padStart(2,"0")}`;

  return (
    <div style={{ maxWidth: 640, margin: "0 auto" }}>
      <div className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)" }}>Today · {dateStr}</div>
      <h1 className="han-display" style={{ fontSize: 28, margin: "8px 0 16px", fontWeight: 500 }}>今日有咩開心事？</h1>
      <textarea
        placeholder="開始書寫⋯"
        value={body} onChange={e => setBody(e.target.value)}
        autoFocus
        style={{
          marginTop: 8, width: "100%", minHeight: 360,
          background: "transparent", border: "none", outline: "none",
          fontFamily: "var(--font-han)", fontSize: 16.5, lineHeight: 2,
          color: "var(--ink)", resize: "vertical",
          backgroundImage: "linear-gradient(to bottom, transparent 31px, var(--rule-2) 31px, var(--rule-2) 32px, transparent 32px)",
          backgroundSize: "100% 32px"
        }}
      />
      <div style={{ display: "flex", gap: 12, marginTop: 24, alignItems: "center" }}>
        <button className="btn btn-gold" onClick={save} disabled={saving}>
          {saving ? "封存中⋯" : "封存此頁"}
        </button>
        <button className="btn btn-ghost" onClick={onCancel} disabled={saving}>取消</button>
        {err && <span style={{ color: "oklch(0.55 0.13 25)", fontSize: 13 }}>{err}</span>}
      </div>
      <div className="han-body" style={{ fontSize: 12, color: "var(--ink-3)", marginTop: 14, fontStyle: "italic" }}>
        AES-256-GCM 加密，伺服器只見密文。
      </div>
    </div>
  );
}

/* ─── TASKS / 待辦 ──────────────────────────────────────────────── */
function TasksPage({ data }) {
  const [tasks, setTasks] = useStateD(data.tasks || []);
  const [newTitle, setNewTitle] = useStateD("");
  const [newEndDate, setNewEndDate] = useStateD("");
  const [adding, setAdding] = useStateD(false);
  const [err, setErr] = useStateD(null);

  const todayIso = window.LifeData.todayHKT();

  const refresh = () => setTasks([...window.LifeData.tasks]);

  const add = async (e) => {
    e?.preventDefault();
    if (!newTitle.trim()) { setErr("標題唔可以空白"); return; }
    setErr(null); setAdding(true);
    try {
      await window.LifeData.addTask({
        title: newTitle.trim(),
        start_date: todayIso,
        end_date: newEndDate || null,
      });
      setNewTitle(""); setNewEndDate("");
      refresh();
    } catch (e) { setErr(String(e)); }
    finally { setAdding(false); }
  };

  const toggle = async (id, isDone) => {
    await window.LifeData.toggleTaskComplete(id, !isDone);
    refresh();
  };

  const remove = async (id) => {
    if (!confirm("確定刪除？")) return;
    await window.LifeData.deleteTask(id);
    refresh();
  };

  const pending = tasks.filter(t => !t.completed_at);
  const completed = tasks.filter(t => t.completed_at)
    .sort((a, b) => (b.completed_at || 0) - (a.completed_at || 0));

  // Stats
  const completedThisWeek = completed.filter(t => {
    const days = (Date.now()/1000 - t.completed_at) / 86400;
    return days <= 7;
  }).length;

  const fmtDays = (start, end_or_now) => {
    const s = new Date(start + 'T00:00:00+08:00').getTime();
    const e = (typeof end_or_now === 'number' ? end_or_now * 1000 : new Date(end_or_now + 'T00:00:00+08:00').getTime());
    const d = Math.max(0, Math.round((e - s) / 86400000));
    return d;
  };

  return (
    <div className="page-in" style={{ padding: "56px 72px 100px", maxWidth: 980, margin: "0 auto" }}>
      <div className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)" }}>Chapter II</div>
      <h1 className="han-display" style={{ fontSize: 38, margin: "4px 0 0", letterSpacing: "0.2em", fontWeight: 500 }}>待 辦 工 作</h1>
      <div className="en-title" style={{ fontSize: 18, color: "var(--ink-2)", marginTop: 4 }}>Pending & Done · 紀錄手上嘅事</div>
      <hr className="rule" style={{ margin: "24px 0 28px" }} />

      {/* Stats strip */}
      <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 16, marginBottom: 28 }}>
        <StatTile zh="進行中" en="Pending" value={pending.length} />
        <StatTile zh="本週完成" en="Done · 7d" value={completedThisWeek} accent />
        <StatTile zh="累積完成" en="All-time" value={completed.length} />
      </div>

      {/* Add new task */}
      <form onSubmit={add} className="card" style={{ padding: "20px 24px", marginBottom: 24 }}>
        <div className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)", marginBottom: 12 }}>New · 新增</div>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 180px auto", gap: 12, alignItems: "stretch" }}>
          <input
            className="field"
            placeholder="想做嘅事..."
            value={newTitle}
            onChange={e => setNewTitle(e.target.value)}
            disabled={adding}
            autoFocus
          />
          <input
            className="field"
            type="date"
            value={newEndDate}
            onChange={e => setNewEndDate(e.target.value)}
            disabled={adding}
            placeholder="結束日（可空）"
            min={todayIso}
            style={{ colorScheme: "light" }}
          />
          <button type="submit" className="btn btn-gold" disabled={adding}>
            {adding ? "⋯" : "✦ 加入"}
          </button>
        </div>
        <div style={{ display: "flex", justifyContent: "space-between", marginTop: 8 }}>
          <span className="han-body" style={{ fontSize: 11, color: "var(--ink-3)", fontStyle: "italic" }}>
            開始日預設今日 · 結束日可留空
          </span>
          {err && <span style={{ color: "oklch(0.55 0.13 25)", fontSize: 12 }}>{err}</span>}
        </div>
      </form>

      {/* Pending */}
      <div style={{ marginBottom: 36 }}>
        <SectionHead num="I" zh="進行中" en="Pending" count={pending.length} />
        <div style={{ marginTop: 16, display: "flex", flexDirection: "column", gap: 10 }}>
          {pending.length === 0 ? (
            <div className="card" style={{ padding: "32px 24px", textAlign: "center", color: "var(--ink-3)", fontStyle: "italic" }}>
              <span className="en-title" style={{ fontSize: 14 }}>~ 心無罣礙 ~</span>
              <p className="han-body" style={{ fontSize: 13, marginTop: 8, marginBottom: 0 }}>暫時冇待辦</p>
            </div>
          ) : pending.map(t => {
            const days = fmtDays(t.start_date, Date.now() / 1000);
            const overdue = t.end_date && t.end_date < todayIso;
            return (
              <div key={t.id} className="card" style={{ padding: "16px 20px", display: "grid", gridTemplateColumns: "auto 1fr auto", gap: 16, alignItems: "center" }}>
                <button onClick={() => toggle(t.id, false)} title="標為完成" style={{
                  width: 24, height: 24, borderRadius: "50%",
                  border: "1.5px solid var(--gold-deep)",
                  background: "transparent", cursor: "pointer",
                  display: "flex", alignItems: "center", justifyContent: "center",
                  flexShrink: 0
                }}>
                  <span style={{ width: 8, height: 8, borderRadius: "50%", background: "transparent" }} />
                </button>
                <div>
                  <div className="han-display" style={{ fontSize: 16, fontWeight: 500, color: "var(--ink)" }}>{t.title}</div>
                  <div className="mono" style={{ fontSize: 11, color: overdue ? "oklch(0.55 0.13 25)" : "var(--ink-3)", marginTop: 4, letterSpacing: "0.05em" }}>
                    {t.start_date} → {t.end_date || '⋯'} · 第 {days + 1} 日
                    {overdue && <span style={{ marginLeft: 8 }}>⚠ 已過期</span>}
                  </div>
                </div>
                <button onClick={() => remove(t.id)} title="刪除" className="btn btn-ghost" style={{ padding: "4px 10px", fontSize: 11 }}>✕</button>
              </div>
            );
          })}
        </div>
      </div>

      {/* Completed log */}
      <div>
        <SectionHead num="II" zh="完成紀錄" en="Completed Log" count={completed.length} />
        <div style={{ marginTop: 16, display: "flex", flexDirection: "column" }}>
          {completed.length === 0 ? (
            <div className="han-body" style={{ fontSize: 13, color: "var(--ink-3)", fontStyle: "italic", padding: "16px 0" }}>
              尚無紀錄。每完成一件事，都會在此累積。
            </div>
          ) : completed.map((t, i) => {
            const completedIso = new Date(t.completed_at * 1000).toISOString().slice(0, 10);
            const days = fmtDays(t.start_date, t.completed_at);
            return (
              <div key={t.id} style={{
                display: "grid", gridTemplateColumns: "auto 1fr auto auto",
                gap: 16, alignItems: "center",
                padding: "12px 4px",
                borderBottom: i === completed.length - 1 ? "none" : "1px dotted var(--rule)"
              }}>
                <button onClick={() => toggle(t.id, true)} title="取消完成" style={{
                  width: 24, height: 24, borderRadius: "50%",
                  border: "1.5px solid var(--gold-deep)",
                  background: "var(--gold)",
                  color: "oklch(0.20 0.04 60)",
                  cursor: "pointer",
                  display: "flex", alignItems: "center", justifyContent: "center",
                  flexShrink: 0, fontSize: 13, fontWeight: 700
                }}>✓</button>
                <div>
                  <div className="han-display" style={{ fontSize: 16, color: "var(--ink)", fontWeight: 500 }}>{t.title}</div>
                  <div className="mono" style={{ fontSize: 11, color: "var(--ink-3)", marginTop: 4, letterSpacing: "0.05em" }}>
                    {t.start_date} → {completedIso} · 用咗 {days} 日
                  </div>
                </div>
                <span className="chop" style={{ fontSize: 10, padding: "3px 8px" }}>已 完 成</span>
                <button onClick={() => remove(t.id)} title="刪除" style={{
                  background: "transparent", border: "none", color: "var(--ink-3)",
                  cursor: "pointer", padding: 4, fontSize: 12
                }}>✕</button>
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}

function StatTile({ zh, en, value, accent }) {
  return (
    <div className="card" style={{
      padding: "18px 20px", textAlign: "center",
      background: accent ? "linear-gradient(135deg, oklch(0.92 0.04 78 / 0.5), oklch(0.94 0.025 80 / 0.2))" : "var(--paper)"
    }}>
      <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)" }}>{en}</div>
      <div className="bignum" style={{ fontSize: 28, color: accent ? "var(--gold-deep)" : "var(--ink)", marginTop: 4 }}>{value}</div>
      <div className="han-body" style={{ fontSize: 12, color: "var(--ink-3)", marginTop: 2 }}>{zh}</div>
    </div>
  );
}

function SectionHead({ num, zh, en, count, onMore }) {
  return (
    <div style={{ display: "flex", alignItems: "baseline", justifyContent: "space-between", borderBottom: "1px solid var(--rule)", paddingBottom: 8 }}>
      <div style={{ display: "flex", alignItems: "baseline", gap: 14 }}>
        <span className="en-title" style={{ fontSize: 18, color: "var(--gold-deep)" }}>{num}.</span>
        <h2 className="han-display" style={{ margin: 0, fontSize: 18, letterSpacing: "0.2em", fontWeight: 500 }}>{zh}</h2>
        <span className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)" }}>{en}</span>
        {count != null && <span className="mono" style={{ fontSize: 11, color: "var(--ink-3)" }}>· {count}</span>}
      </div>
      {onMore && <a onClick={onMore} style={{ cursor: "pointer", color: "var(--ink-3)", fontFamily: "var(--font-en)", fontStyle: "italic", fontSize: 13 }}>more →</a>}
    </div>
  );
}

/* ─── PORTFOLIO ─────────────────────────────────────────────────── */
function PortfolioPage({ data }) {
  const p = data.portfolio;
  if (!p) {
    return (
      <div className="page-in" style={{ padding: "80px 72px", maxWidth: 1100, margin: "0 auto", textAlign: "center" }}>
        <h1 className="han-display" style={{ fontSize: 38, fontWeight: 500, letterSpacing: "0.2em" }}>淨 資 產</h1>
        <p className="han-body" style={{ marginTop: 32, color: "var(--ink-3)", fontSize: 14 }}>
          尚未收到 Mac Mini 推送嘅 snapshot。<br/>
          請確認 <code>com.jerry.life.finance</code> launchd job 正在運行。
        </p>
      </div>
    );
  }

  const fmtMoney = (v, ccy) => v == null ? '—' : `${v >= 0 ? '+' : ''}${v.toLocaleString('en-US', {maximumFractionDigits: 2})} ${ccy}`;
  const colorPnL = v => v == null ? 'var(--ink-3)' : (v >= 0 ? 'oklch(0.50 0.10 145)' : 'oklch(0.55 0.13 25)');
  const fmtTime = iso => {
    if (!iso) return '—';
    const d = new Date(iso);
    return `${d.getMonth()+1}/${d.getDate()} ${String(d.getHours()).padStart(2,'0')}:${String(d.getMinutes()).padStart(2,'0')}`;
  };

  return (
    <div className="page-in" style={{ padding: "56px 72px 100px", maxWidth: 1100, margin: "0 auto" }}>
      <div className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)" }}>Chapter III</div>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
        <h1 className="han-display" style={{ fontSize: 38, margin: "4px 0 0", letterSpacing: "0.2em", fontWeight: 500 }}>淨 資 產</h1>
        <div className="mono" style={{ fontSize: 12, color: "var(--ink-3)" }}>更新於 {fmtTime(p.updated_at)}</div>
      </div>
      <div className="en-title" style={{ fontSize: 18, color: "var(--ink-2)", marginTop: 4 }}>Trading Systems · Live Snapshot</div>
      <hr className="rule" style={{ margin: "24px 0 32px" }} />

      <div style={{ display: "flex", flexDirection: "column", gap: 24 }}>
        {(p.systems || []).map(sys => <SystemCard key={sys.key} sys={sys} fmtMoney={fmtMoney} colorPnL={colorPnL} />)}
      </div>

      <div style={{ marginTop: 64, textAlign: "center", color: "var(--ink-3)" }}>
        <span className="en-title" style={{ fontSize: 13, fontStyle: "italic" }}>
          盈虧之外，問自己：是否仍依紀律？
        </span>
      </div>
    </div>
  );
}

function SystemCard({ sys, fmtMoney, colorPnL }) {
  const status = !sys.ok ? { label: '⚠ 無回應', color: 'oklch(0.55 0.13 25)' }
    : sys.emergency_stop ? { label: '🛑 緊急停止', color: 'oklch(0.55 0.13 25)' }
    : !sys.trading_enabled ? { label: '⏸ 已停用', color: 'var(--ink-3)' }
    : { label: '● 運行中', color: 'oklch(0.50 0.10 145)' };

  return (
    <div className="card" style={{ padding: "28px 32px" }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 16 }}>
        <div>
          <div className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)" }}>{sys.key.replace('_', ' ').toUpperCase()}</div>
          <h3 className="han-display" style={{ fontSize: 22, margin: "4px 0 0", fontWeight: 500 }}>{sys.icon} {sys.name}</h3>
        </div>
        <div className="mono" style={{ fontSize: 12, color: status.color }}>{status.label}</div>
      </div>

      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 24, marginBottom: sys.positions_count > 0 ? 20 : 0 }}>
        <div>
          <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)" }}>{sys.trailing_window_days || 90}-Day PnL</div>
          <div className="bignum" style={{ fontSize: 24, color: colorPnL(sys.trailing_pnl), marginTop: 4 }}>
            {fmtMoney(sys.trailing_pnl, sys.currency)}
          </div>
          <div className="mono" style={{ fontSize: 11, color: "var(--ink-3)", marginTop: 2 }}>
            {sys.trailing_trades || 0} trades
          </div>
        </div>
        <div>
          <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)" }}>Today</div>
          <div className="bignum" style={{ fontSize: 24, color: colorPnL(sys.today_pnl), marginTop: 4 }}>
            {fmtMoney(sys.today_pnl, sys.currency)}
          </div>
          <div className="mono" style={{ fontSize: 11, color: "var(--ink-3)", marginTop: 2 }}>
            {sys.today_trades || 0} trades · {sys.positions_count || 0} positions open
          </div>
        </div>
      </div>

      {sys.positions_count > 0 && (
        <>
          <hr className="rule" style={{ margin: "8px 0 14px" }} />
          <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(160px, 1fr))", gap: 8 }}>
            {(sys.positions || []).map(pos => (
              <div key={pos.symbol} className="mono" style={{
                padding: "8px 12px",
                background: "oklch(0.92 0.025 78 / 0.4)",
                fontSize: 12, display: "flex", justifyContent: "space-between"
              }}>
                <span>{pos.symbol}</span>
                <span>
                  <span style={{ color: pos.side === 'LONG' ? 'oklch(0.50 0.10 145)' : 'oklch(0.55 0.13 25)', fontWeight: 600 }}>
                    {pos.side}
                  </span>
                  <span style={{ color: "var(--ink-3)", marginLeft: 8 }}>{pos.qty}</span>
                </span>
              </div>
            ))}
          </div>
        </>
      )}
    </div>
  );
}

/* ─── GOALS ──────────────────────────────────────────────────────── */
function GoalsPage({ data }) {
  const [goals, setGoals] = useStateD(data.goals || []);
  const [editing, setEditing] = useStateD(null); // null | {} | {id...}

  const refresh = () => setGoals([...window.LifeData.goals]);

  const onProgressChange = async (id, progress) => {
    await window.LifeData.updateGoal(id, { progress });
    refresh();
  };

  const onDelete = async (g) => {
    if (!confirm(`確定刪除「${g.title}」？`)) return;
    await window.LifeData.deleteGoal(g.id);
    refresh();
  };

  return (
    <div className="page-in" style={{ padding: "56px 72px 100px", maxWidth: 1000, margin: "0 auto" }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start" }}>
        <div>
          <div className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)" }}>Chapter V</div>
          <h1 className="han-display" style={{ fontSize: 38, margin: "4px 0 0", letterSpacing: "0.2em", fontWeight: 500 }}>目 標</h1>
          <div className="en-title" style={{ fontSize: 18, color: "var(--ink-2)", marginTop: 4 }}>Goals & Yearly Themes</div>
        </div>
        <button className="btn btn-gold" onClick={() => setEditing({})}>✦ 新增目標</button>
      </div>
      <hr className="rule" style={{ margin: "24px 0 32px" }} />

      <YearThemeCard theme={data.yearTheme} />

      <div style={{ marginTop: 36, display: "flex", flexDirection: "column", gap: 18 }}>
        {goals.length === 0 ? (
          <div className="card" style={{ padding: "40px 28px", textAlign: "center", color: "var(--ink-3)" }}>
            <p className="han-body" style={{ fontSize: 14 }}>尚無目標。撳右上「新增目標」開始。</p>
          </div>
        ) : goals.map((g) => (
          <div key={g.id} className="card" style={{ padding: "24px 28px" }}>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", gap: 16 }}>
              <div style={{ flex: 1 }}>
                <h3 className="han-display" style={{ fontSize: 22, margin: 0, fontWeight: 500 }}>
                  {g.done && <span style={{ color: "var(--gold-deep)", marginRight: 8 }}>✓</span>}
                  {g.title}
                </h3>
                {g.enTitle && <div className="en-title" style={{ fontSize: 14, color: "var(--ink-3)", marginTop: 2 }}>{g.enTitle}</div>}
              </div>
              <div className="mono" style={{ fontSize: 12, color: "var(--ink-3)", whiteSpace: "nowrap" }}>{g.target}</div>
              <div style={{ display: "flex", gap: 4 }}>
                <button onClick={() => setEditing(g)} title="編輯" style={{
                  padding: "4px 10px", fontSize: 11,
                  background: "transparent", border: "1px solid var(--rule)",
                  cursor: "pointer", fontFamily: "var(--font-han)", color: "var(--ink-3)"
                }}>編輯</button>
                <button onClick={() => onDelete(g)} title="刪除" style={{
                  padding: "4px 10px", fontSize: 11,
                  background: "transparent", border: "1px solid var(--rule)",
                  cursor: "pointer", color: "var(--ink-3)"
                }}>✕</button>
              </div>
            </div>
            {g.note && <p className="han-body" style={{ fontSize: 14, color: "var(--ink-2)", marginTop: 12, marginBottom: 16, whiteSpace: "pre-line" }}>{g.note}</p>}

            {/* Inline progress slider */}
            <div style={{ marginTop: g.note ? 0 : 16 }}>
              <div style={{ height: 6, background: "oklch(0.88 0.025 78)", position: "relative", borderRadius: 1 }}>
                <div style={{
                  position: "absolute", inset: 0, width: `${g.progress*100}%`,
                  background: "linear-gradient(90deg, var(--gold), var(--gold-deep))",
                  borderRadius: 1, transition: "width .3s ease"
                }} />
              </div>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginTop: 8 }}>
                <input
                  type="range"
                  min="0" max="100" step="5"
                  value={Math.round(g.progress * 100)}
                  onChange={e => onProgressChange(g.id, Number(e.target.value) / 100)}
                  style={{ flex: 1, marginRight: 16, accentColor: "var(--gold-deep)" }}
                />
                <span className="mono" style={{ fontSize: 13, color: "var(--gold-deep)", minWidth: 52, textAlign: "right" }}>
                  {(g.progress * 100).toFixed(0)}%
                </span>
              </div>
            </div>
          </div>
        ))}
      </div>

      {editing != null && (
        <GoalEditor
          initial={editing}
          onClose={() => setEditing(null)}
          onSaved={() => { refresh(); setEditing(null); }}
        />
      )}
    </div>
  );
}

function GoalEditor({ initial, onClose, onSaved }) {
  const isNew = !initial.id;
  const [title, setTitle] = useStateD(initial.title || '');
  const [enTitle, setEnTitle] = useStateD(initial.enTitle || '');
  const [target, setTarget] = useStateD(initial.target && initial.target !== '—' ? initial.target : '');
  const [progress, setProgress] = useStateD(typeof initial.progress === 'number' ? Math.round(initial.progress * 100) : 0);
  const [note, setNote] = useStateD(initial.note || '');
  const [saving, setSaving] = useStateD(false);
  const [err, setErr] = useStateD(null);

  const save = async () => {
    if (!title.trim()) { setErr('要輸入目標'); return; }
    setSaving(true); setErr(null);
    try {
      const payload = {
        title: title.trim(),
        en_title: enTitle.trim() || null,
        target: target.trim() || null,
        progress: progress / 100,
        note: note.trim() || null,
      };
      if (isNew) {
        await window.LifeData.addGoal(payload);
      } else {
        await window.LifeData.updateGoal(initial.id, payload);
      }
      onSaved();
    } catch (e) {
      console.error(e);
      setErr('儲存失敗：' + (e?.message || e));
      setSaving(false);
    }
  };

  return (
    <div onClick={onClose} style={{
      position: "fixed", inset: 0, zIndex: 100,
      background: "oklch(0.10 0.02 60 / 0.65)", backdropFilter: "blur(4px)",
      display: "flex", alignItems: "center", justifyContent: "center", padding: 20
    }}>
      <div onClick={e => e.stopPropagation()} className="paper modal-mobile-full" style={{
        width: "100%", maxWidth: 560, maxHeight: "90vh",
        overflowY: "auto", padding: "32px 36px",
        border: "1px solid var(--rule)",
        boxShadow: "0 30px 80px oklch(0 0 0 / 0.4)"
      }}>
        <div className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)" }}>{isNew ? "New Goal · 新增" : "Edit Goal · 編輯"}</div>
        <h2 className="han-display" style={{ fontSize: 24, margin: "8px 0 18px", fontWeight: 500 }}>
          {isNew ? '新增一個目標' : '編輯目標'}
        </h2>

        <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>標題（必填）</div>
        <input className="field" value={title} onChange={e => setTitle(e.target.value)} placeholder="例：跑完一場全馬"
          autoFocus style={{ marginBottom: 12 }} />

        <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>英文副題（可選）</div>
        <input className="field" value={enTitle} onChange={e => setEnTitle(e.target.value)} placeholder="Marathon"
          style={{ marginBottom: 12 }} />

        <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>目標日期 / 範圍</div>
        <input className="field" value={target} onChange={e => setTarget(e.target.value)} placeholder="例：2027 Q4 / 2026.11 / 持續"
          style={{ marginBottom: 16 }} />

        <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>進度 · {progress}%</div>
        <div style={{ marginBottom: 16 }}>
          <input
            type="range" min="0" max="100" step="5"
            value={progress}
            onChange={e => setProgress(Number(e.target.value))}
            style={{ width: "100%", accentColor: "var(--gold-deep)" }}
          />
          <div style={{ height: 6, background: "oklch(0.88 0.025 78)", position: "relative", marginTop: 2, borderRadius: 1 }}>
            <div style={{
              position: "absolute", inset: 0, width: `${progress}%`,
              background: "linear-gradient(90deg, var(--gold), var(--gold-deep))",
              borderRadius: 1
            }} />
          </div>
        </div>

        <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>備註（可選）</div>
        <textarea className="field" value={note} onChange={e => setNote(e.target.value)}
          placeholder="例：目前最遠 18 公里"
          style={{ minHeight: 80, resize: "vertical", lineHeight: 1.7, marginBottom: 16 }} />

        <div style={{ display: "flex", gap: 8, justifyContent: "flex-end", marginTop: 16 }}>
          <button className="btn btn-ghost" onClick={onClose} disabled={saving}>取消</button>
          <button className="btn btn-gold" onClick={save} disabled={saving}>
            {saving ? "儲存中⋯" : "儲存"}
          </button>
        </div>
        {err && <div style={{ color: "oklch(0.55 0.13 25)", fontSize: 13, marginTop: 10, textAlign: "right" }}>{err}</div>}
      </div>
    </div>
  );
}

function YearThemeCard({ theme }) {
  const [editing, setEditing] = useStateD(false);
  return (
    <>
      <div style={{
        display: "grid", gridTemplateColumns: "auto 1fr auto",
        gap: 32, alignItems: "center",
        padding: "28px 32px",
        background: "linear-gradient(135deg, oklch(0.92 0.04 78 / 0.5), oklch(0.94 0.025 80 / 0.2))",
        border: "1px solid var(--rule)",
        position: "relative"
      }}>
        <button onClick={() => setEditing(true)} title="編輯年度主題" style={{
          position: "absolute", top: 10, right: 12,
          background: "transparent", border: "1px solid var(--rule)",
          color: "var(--ink-3)", cursor: "pointer",
          padding: "3px 10px", borderRadius: 2, fontSize: 11,
          fontFamily: "var(--font-han)", letterSpacing: "0.1em"
        }}>✎ 編輯</button>

        <div style={{
          fontFamily: "var(--font-han)",
          fontSize: 80, fontWeight: 600,
          color: "var(--gold-deep)",
          lineHeight: 1, letterSpacing: "0.05em"
        }}>{theme.word || '—'}</div>
        <div>
          <div className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)" }}>Year of {theme.year} · 年度主題</div>
          <div className="en-title" style={{ fontSize: 24, marginTop: 4, color: "var(--ink)" }}>{theme.enWord || ''}</div>
          {theme.description && (
            <p className="han-body" style={{ fontSize: 14, color: "var(--ink-2)", marginTop: 8, marginBottom: 0, maxWidth: 480 }}>
              {theme.description}
            </p>
          )}
        </div>
        <div style={{ textAlign: "right", color: "var(--ink-3)" }}>
          <div className="mono" style={{ fontSize: 11, letterSpacing: "0.2em" }}>
            {Math.floor((Date.now() - new Date(`${theme.year}-01-01`)) / 86400000)} / 365
          </div>
          <div className="en-caps" style={{ fontSize: 9, marginTop: 4 }}>days in</div>
        </div>
      </div>

      {editing && <YearThemeEditor theme={theme} onClose={() => setEditing(false)} />}
    </>
  );
}

function YearThemeEditor({ theme, onClose }) {
  const [year, setYear] = useStateD(theme.year || new Date().getFullYear());
  const [word, setWord] = useStateD(theme.word || '');
  const [enWord, setEnWord] = useStateD(theme.enWord || '');
  const [description, setDescription] = useStateD(theme.description || '');
  const [saving, setSaving] = useStateD(false);
  const [err, setErr] = useStateD(null);

  const save = async () => {
    setSaving(true); setErr(null);
    try {
      await window.LifeData.saveYearTheme({
        year: Number(year) || new Date().getFullYear(),
        word: word.trim(),
        enWord: enWord.trim(),
        description: description.trim(),
      });
      onClose();
    } catch (e) {
      setErr('儲存失敗：' + (e?.message || e));
      setSaving(false);
    }
  };

  const clearAll = () => {
    setWord(''); setEnWord(''); setDescription('');
  };

  const reset = async () => {
    if (!confirm('重置為預設文字？')) return;
    setSaving(true);
    try {
      await window.LifeData.resetYearTheme();
      onClose();
    } catch (e) {
      setErr('重置失敗：' + (e?.message || e));
      setSaving(false);
    }
  };

  return (
    <div onClick={onClose} style={{
      position: "fixed", inset: 0, zIndex: 100,
      background: "oklch(0.10 0.02 60 / 0.65)", backdropFilter: "blur(4px)",
      display: "flex", alignItems: "center", justifyContent: "center", padding: 20
    }}>
      <div onClick={e => e.stopPropagation()} className="paper modal-mobile-full" style={{
        width: "100%", maxWidth: 560, maxHeight: "90vh",
        overflowY: "auto", padding: "32px 36px",
        border: "1px solid var(--rule)",
        boxShadow: "0 30px 80px oklch(0 0 0 / 0.4)"
      }}>
        <div className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)" }}>Year Theme · 年度主題</div>
        <h2 className="han-display" style={{ fontSize: 24, margin: "8px 0 18px", fontWeight: 500 }}>編輯年度主題</h2>

        <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>年份</div>
        <input className="field" type="number" value={year} onChange={e => setYear(e.target.value)}
          min="2000" max="2100" style={{ marginBottom: 12, width: 120 }} />

        <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>主題詞 · 中文</div>
        <input className="field" value={word} onChange={e => setWord(e.target.value)}
          placeholder="例：明心 / 深耕 / 靜觀" style={{ marginBottom: 12 }} />

        <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>主題詞 · English</div>
        <input className="field" value={enWord} onChange={e => setEnWord(e.target.value)}
          placeholder="Clarity / Deepen / Stillness" style={{ marginBottom: 12 }} />

        <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>描述（可清空）</div>
        <textarea className="field" value={description} onChange={e => setDescription(e.target.value)}
          placeholder="一段話描述今年想培養的心境⋯（可留空）"
          style={{ minHeight: 90, resize: "vertical", lineHeight: 1.7, marginBottom: 16 }} />

        <div style={{ display: "flex", gap: 8, justifyContent: "space-between", marginTop: 16, flexWrap: "wrap" }}>
          <div style={{ display: "flex", gap: 8 }}>
            <button onClick={clearAll} disabled={saving} style={{
              background: "transparent", border: "1px solid var(--rule)", color: "var(--ink-3)",
              cursor: "pointer", padding: "8px 14px", borderRadius: 2, fontSize: 12,
              fontFamily: "var(--font-han)", letterSpacing: "0.1em"
            }}>清空文字</button>
            <button onClick={reset} disabled={saving} style={{
              background: "transparent", border: "1px solid var(--rule)", color: "var(--ink-3)",
              cursor: "pointer", padding: "8px 14px", borderRadius: 2, fontSize: 12,
              fontFamily: "var(--font-han)", letterSpacing: "0.1em"
            }}>重置為預設</button>
          </div>
          <div style={{ display: "flex", gap: 8 }}>
            <button className="btn btn-ghost" onClick={onClose} disabled={saving}>取消</button>
            <button className="btn btn-gold" onClick={save} disabled={saving}>
              {saving ? "儲存中⋯" : "儲存"}
            </button>
          </div>
        </div>
        {err && <div style={{ color: "oklch(0.55 0.13 25)", fontSize: 13, marginTop: 10, textAlign: "right" }}>{err}</div>}
      </div>
    </div>
  );
}

/* ─── HABITS / 日課 ──────────────────────────────────────────────── */
function HabitsPage({ data }) {
  const [, force] = useStateD(0);
  const [editing, setEditing] = useStateD(false);
  const [config, setConfig] = useStateD(JSON.parse(JSON.stringify(window.LifeData.habitsConfig || [])));
  const [saving, setSaving] = useStateD(false);
  const [savedTick, setSavedTick] = useStateD(false);

  const days = ["一","二","三","四","五","六","日"];
  const todayIso = window.LifeData.todayHKT();

  const toggle = async (habitKey) => {
    await window.LifeData.toggleHabit(habitKey);
    force(x => x + 1);
  };

  const startEdit = () => {
    setConfig(JSON.parse(JSON.stringify(window.LifeData.habitsConfig || [])));
    setEditing(true);
  };
  const cancelEdit = () => {
    setConfig(JSON.parse(JSON.stringify(window.LifeData.habitsConfig || [])));
    setEditing(false);
  };
  const save = async () => {
    // Sanity: drop empty-name rows; ensure unique keys
    const cleaned = config.filter(h => h.name && h.name.trim()).map(h => ({
      key: h.key || ('habit_' + Date.now() + '_' + Math.random().toString(36).slice(2, 6)),
      name: h.name.trim(),
      target: (h.target || '').trim() || '每日',
    }));
    setSaving(true);
    try {
      await window.LifeData.saveHabitsConfig(cleaned);
      setEditing(false);
      setSavedTick(true);
      setTimeout(() => setSavedTick(false), 2000);
      force(x => x + 1);
    } catch (e) {
      alert('儲存失敗：' + (e?.message || e));
    } finally {
      setSaving(false);
    }
  };

  const updateField = (i, k, v) => {
    const arr = [...config];
    arr[i] = { ...arr[i], [k]: v };
    setConfig(arr);
  };
  const addHabit = () => setConfig([
    ...config,
    { key: 'habit_' + Date.now() + '_' + Math.random().toString(36).slice(2, 6), name: '', target: '每日' }
  ]);
  const removeHabit = (i) => setConfig(config.filter((_, idx) => idx !== i));

  return (
    <div className="page-in" style={{ padding: "56px 72px 100px", maxWidth: 1000, margin: "0 auto" }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start" }}>
        <div>
          <div className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)" }}>Chapter VI</div>
          <h1 className="han-display" style={{ fontSize: 38, margin: "4px 0 0", letterSpacing: "0.2em", fontWeight: 500 }}>身 心 日 課</h1>
          <div className="en-title" style={{ fontSize: 18, color: "var(--ink-2)", marginTop: 4 }}>Daily Practice</div>
        </div>
        <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
          {savedTick && (
            <span className="han-body" style={{ fontSize: 12, color: "var(--gold-deep)", fontStyle: "italic" }}>
              ✓ 已儲存
            </span>
          )}
          {!editing ? (
            <button className="btn btn-ghost" onClick={startEdit}>✎ 編輯日課</button>
          ) : (
            <>
              <button className="btn btn-ghost" onClick={cancelEdit} disabled={saving}>取消</button>
              <button className="btn btn-gold" onClick={save} disabled={saving}>
                {saving ? "儲存中⋯" : "✓ 儲存"}
              </button>
            </>
          )}
        </div>
      </div>
      <p className="han-body" style={{ fontSize: 14, color: "var(--ink-2)", maxWidth: 520, marginTop: 12 }}>
        每日修行非為證得，只為令心地清明。
      </p>
      <hr className="rule" style={{ margin: "24px 0 32px" }} />

      {editing ? (
        <div>
          <div className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)", marginBottom: 12 }}>Edit Habits · 編輯日課列表</div>
          <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
            {config.length === 0 && (
              <div className="han-body" style={{ fontSize: 13, color: "var(--ink-3)", padding: "16px 0", fontStyle: "italic" }}>
                尚未設置任何日課。撳「✦ 新增」加入。
              </div>
            )}
            {config.map((h, i) => (
              <div key={h.key || i} style={{ display: "grid", gridTemplateColumns: "1fr 1fr auto", gap: 10, alignItems: "center" }}>
                <input
                  className="field"
                  value={h.name || ''}
                  onChange={e => updateField(i, 'name', e.target.value)}
                  placeholder="日課名稱（例：打坐）"
                />
                <input
                  className="field"
                  value={h.target || ''}
                  onChange={e => updateField(i, 'target', e.target.value)}
                  placeholder="頻率/目標（例：每日 20 分鐘）"
                />
                <button onClick={() => removeHabit(i)} title="刪除" style={{
                  background: "transparent", border: "1px solid var(--rule)",
                  color: "var(--ink-3)", cursor: "pointer", padding: "9px 14px",
                  borderRadius: 2, fontSize: 12
                }}>✕</button>
              </div>
            ))}
            <button className="btn btn-ghost" onClick={addHabit} style={{ alignSelf: "flex-start", marginTop: 8 }}>
              ✦ 新增一項日課
            </button>
          </div>
          <p className="han-body" style={{ fontSize: 12, color: "var(--ink-3)", marginTop: 16, fontStyle: "italic" }}>
            提示：刪除一項日課唔會清除過去嘅打卡記錄，只係佢唔再喺呢度顯示。
          </p>
        </div>
      ) : (
        <>
          <div style={{ marginBottom: 28 }}>
            <div className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)", marginBottom: 12 }}>Today · {todayIso}</div>
            {data.habits.length === 0 ? (
              <div className="han-body" style={{ fontSize: 13, color: "var(--ink-3)", fontStyle: "italic" }}>
                尚未設置任何日課。撳右上「✎ 編輯日課」加入。
              </div>
            ) : (
              <div style={{ display: "flex", gap: 12, flexWrap: "wrap" }}>
                {data.habits.map(h => (
                  <button
                    key={h.key}
                    onClick={() => toggle(h.key)}
                    className="btn"
                    style={{
                      background: h.week[h.week.length - 1] ? "var(--gold)" : "transparent",
                      color: h.week[h.week.length - 1] ? "oklch(0.20 0.04 60)" : "var(--ink-2)",
                      border: h.week[h.week.length - 1] ? "1px solid var(--gold)" : "1px solid var(--rule)",
                      padding: "10px 22px"
                    }}
                  >
                    {h.week[h.week.length - 1] ? "✓ " : "○ "}{h.name}
                  </button>
                ))}
              </div>
            )}
          </div>

          {data.habits.length > 0 && (
            <table style={{ width: "100%", borderCollapse: "collapse" }}>
              <thead>
                <tr style={{ borderBottom: "1px solid var(--rule)" }}>
                  <th style={{ textAlign: "left", padding: "10px 0", fontFamily: "var(--font-han)", fontSize: 12, color: "var(--ink-3)", fontWeight: 500, letterSpacing: "0.2em" }}>日課</th>
                  <th style={{ textAlign: "left", padding: "10px 0", fontFamily: "var(--font-han)", fontSize: 12, color: "var(--ink-3)", fontWeight: 500, letterSpacing: "0.2em" }}>頻率</th>
                  {days.map(d => (
                    <th key={d} style={{ width: 36, fontFamily: "var(--font-han)", fontSize: 12, color: "var(--ink-3)", fontWeight: 500 }}>{d}</th>
                  ))}
                  <th style={{ textAlign: "right", padding: "10px 0", fontFamily: "var(--font-en)", fontStyle: "italic", fontSize: 12, color: "var(--ink-3)" }}>streak</th>
                </tr>
              </thead>
              <tbody>
                {data.habits.map((h) => (
                  <tr key={h.key} style={{ borderBottom: "1px dotted var(--rule)" }}>
                    <td style={{ padding: "16px 0", fontSize: 15, fontFamily: "var(--font-han)" }}>{h.name}</td>
                    <td style={{ padding: "16px 0", fontSize: 13, color: "var(--ink-3)", fontFamily: "var(--font-han)" }}>{h.target}</td>
                    {h.week.map((d, di) => (
                      <td key={di} style={{ textAlign: "center" }}>
                        <span style={{
                          display: "inline-block", width: 18, height: 18, borderRadius: 2,
                          background: d ? "var(--gold-deep)" : "oklch(0.88 0.02 75)",
                          border: d ? "none" : "1px dashed var(--rule)"
                        }} />
                      </td>
                    ))}
                    <td className="mono" style={{ textAlign: "right", padding: "16px 0", fontSize: 14, color: "var(--gold-deep)" }}>{h.streak} 天</td>
                  </tr>
                ))}
              </tbody>
            </table>
          )}
        </>
      )}
    </div>
  );
}

/* ─── TRADE JOURNAL / 交易日誌 ───────────────────────────────────── */
const TRADE_SYSTEMS = [
  { value: 'futu_hsi', label: '🇭🇰 HSI 富途' },
  { value: 'tiger_us', label: '🇺🇸 Tiger US' },
  { value: 'dydx_crypto', label: '₿ Crypto dYdX' },
  { value: 'manual', label: '手動其他' },
];

function TradeJournalPage({ data }) {
  const [trades, setTrades] = useStateD(data.trades || []);
  const [filter, setFilter] = useStateD('all'); // all | open | closed
  const [editing, setEditing] = useStateD(null);

  const refresh = () => setTrades([...window.LifeData.trades]);

  const filtered = trades.filter(t => {
    if (filter === 'all') return true;
    return t.status === filter;
  });

  const stats = {
    total: trades.length,
    open: trades.filter(t => t.status === 'open').length,
    closed: trades.filter(t => t.status === 'closed').length,
  };

  const onDelete = async (t) => {
    if (!confirm(`確定刪除 ${t.symbol || '無 symbol'} 嘅日誌？`)) return;
    await window.LifeData.deleteTrade(t.id);
    refresh();
  };

  return (
    <div className="page-in" style={{ padding: "56px 72px 100px", maxWidth: 1100, margin: "0 auto" }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start" }}>
        <div>
          <div className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)" }}>Chapter VII</div>
          <h1 className="han-display" style={{ fontSize: 38, margin: "4px 0 0", letterSpacing: "0.2em", fontWeight: 500 }}>交 易 日 誌</h1>
          <div className="en-title" style={{ fontSize: 18, color: "var(--ink-2)", marginTop: 4 }}>Trade Journal · 思路與覆盤</div>
        </div>
        <button className="btn btn-gold" onClick={() => setEditing({ trade_date: window.LifeData.todayHKT(), status: 'open' })}>
          ✦ 新一筆
        </button>
      </div>
      <p className="han-body" style={{ fontSize: 14, color: "var(--ink-2)", maxWidth: 580, marginTop: 12 }}>
        每筆交易寫低 thesis 同覆盤。Thesis、數字、教訓全部 AES 加密；只有日期、symbol、方向係 plaintext 用嚟篩選。
      </p>
      <hr className="rule" style={{ margin: "24px 0" }} />

      <div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 16, marginBottom: 28 }}>
        <StatTile zh="進行中" en="Open" value={stats.open} accent />
        <StatTile zh="已平倉" en="Closed" value={stats.closed} />
        <StatTile zh="總紀錄" en="All-time" value={stats.total} />
      </div>

      <div style={{ display: "flex", gap: 8, marginBottom: 24 }}>
        {[['all', '全部'], ['open', '進行中'], ['closed', '已平倉']].map(([v, lbl]) => (
          <button key={v} onClick={() => setFilter(v)} className="tag" style={{
            cursor: "pointer", padding: "5px 14px",
            background: filter === v ? "var(--ink)" : "oklch(0.88 0.04 78 / 0.5)",
            color: filter === v ? "var(--paper)" : "var(--ink-2)",
            border: "1px solid var(--rule)"
          }}>{lbl}</button>
        ))}
      </div>

      {filtered.length === 0 ? (
        <div className="card" style={{ padding: "60px 40px", textAlign: "center" }}>
          <window.LotusMark size={36} />
          <p className="han-body" style={{ fontSize: 14, color: "var(--ink-3)", marginTop: 16, marginBottom: 0 }}>
            {trades.length === 0 ? '尚無交易日誌。撳「✦ 新一筆」開始。' : '無符合嘅項目。'}
          </p>
        </div>
      ) : (
        <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          {filtered.map(t => <TradeCard key={t.id} trade={t} onEdit={() => setEditing(t)} onDelete={() => onDelete(t)} />)}
        </div>
      )}

      {editing != null && (
        <TradeEditor
          initial={editing}
          onClose={() => setEditing(null)}
          onSaved={() => { refresh(); setEditing(null); }}
        />
      )}
    </div>
  );
}

function TradeCard({ trade, onEdit, onDelete }) {
  const sysLabel = TRADE_SYSTEMS.find(s => s.value === trade.system)?.label || trade.system || '—';
  const sideColor = trade.side === 'LONG' ? 'oklch(0.50 0.10 145)' : trade.side === 'SHORT' ? 'oklch(0.55 0.13 25)' : 'var(--ink-3)';
  const isOpen = trade.status === 'open';
  const pnlNum = parseFloat(trade.pnl);
  const pnlOk = !isNaN(pnlNum);

  return (
    <div className="card" style={{ padding: "20px 24px" }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 10, gap: 12, flexWrap: "wrap" }}>
        <div style={{ display: "flex", alignItems: "baseline", gap: 14 }}>
          <span className="mono" style={{ fontSize: 12, color: "var(--ink-3)" }}>{trade.trade_date}</span>
          <h3 className="han-display" style={{ fontSize: 20, margin: 0, fontWeight: 500 }}>
            {trade.symbol || '—'}
            {trade.side && (
              <span style={{ color: sideColor, marginLeft: 10, fontSize: 14, fontWeight: 600 }}>{trade.side}</span>
            )}
          </h3>
          <span className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)" }}>{sysLabel}</span>
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
          <span className="chop" style={{
            background: isOpen ? "var(--gold-deep)" : "var(--ink)",
            fontSize: 10, padding: "3px 8px"
          }}>{isOpen ? '進 行 中' : '已 平 倉'}</span>
          {pnlOk && (
            <span className="bignum" style={{ fontSize: 16, color: pnlNum >= 0 ? 'oklch(0.50 0.10 145)' : 'oklch(0.55 0.13 25)' }}>
              {pnlNum >= 0 ? '+' : ''}{pnlNum}
            </span>
          )}
        </div>
      </div>

      {(trade.qty || trade.entry_px || trade.exit_px) && (
        <div className="mono" style={{ fontSize: 11, color: "var(--ink-3)", letterSpacing: "0.05em", marginBottom: 10 }}>
          {trade.qty && `數量 ${trade.qty}`}
          {trade.entry_px && ` · 入 ${trade.entry_px}`}
          {trade.exit_px && ` · 出 ${trade.exit_px}`}
        </div>
      )}

      {trade.thesis && (
        <div style={{ marginBottom: trade.outcome || trade.lessons ? 12 : 0 }}>
          <div className="en-caps" style={{ fontSize: 9, color: "var(--gold-deep)", marginBottom: 4 }}>Thesis · 入市理由</div>
          <p className="han-body" style={{ fontSize: 14, color: "var(--ink)", margin: 0, lineHeight: 1.7, whiteSpace: "pre-line" }}>{trade.thesis}</p>
        </div>
      )}
      {trade.outcome && (
        <div style={{ marginBottom: trade.lessons ? 12 : 0 }}>
          <div className="en-caps" style={{ fontSize: 9, color: "var(--gold-deep)", marginBottom: 4 }}>Outcome · 結果</div>
          <p className="han-body" style={{ fontSize: 14, color: "var(--ink)", margin: 0, lineHeight: 1.7, whiteSpace: "pre-line" }}>{trade.outcome}</p>
        </div>
      )}
      {trade.lessons && (
        <div>
          <div className="en-caps" style={{ fontSize: 9, color: "var(--gold-deep)", marginBottom: 4 }}>Lessons · 教訓</div>
          <p className="han-body" style={{ fontSize: 14, color: "var(--ink-2)", margin: 0, lineHeight: 1.7, fontStyle: "italic", whiteSpace: "pre-line" }}>{trade.lessons}</p>
        </div>
      )}

      <div style={{ display: "flex", gap: 4, justifyContent: "flex-end", marginTop: 14 }}>
        <button onClick={onEdit} style={{
          padding: "4px 10px", fontSize: 11,
          background: "transparent", border: "1px solid var(--rule)",
          cursor: "pointer", fontFamily: "var(--font-han)", color: "var(--ink-3)"
        }}>編輯</button>
        <button onClick={onDelete} style={{
          padding: "4px 10px", fontSize: 11,
          background: "transparent", border: "1px solid var(--rule)",
          cursor: "pointer", color: "var(--ink-3)"
        }}>✕</button>
      </div>
    </div>
  );
}

function TradeEditor({ initial, onClose, onSaved }) {
  const isNew = !initial.id;
  const [trade_date, setTradeDate] = useStateD(initial.trade_date || window.LifeData.todayHKT());
  const [system, setSystem] = useStateD(initial.system || 'manual');
  const [symbol, setSymbol] = useStateD(initial.symbol || '');
  const [side, setSide] = useStateD(initial.side || 'LONG');
  const [status, setStatus] = useStateD(initial.status || 'open');
  const [qty, setQty] = useStateD(initial.qty || '');
  const [entry_px, setEntry] = useStateD(initial.entry_px || '');
  const [exit_px, setExit] = useStateD(initial.exit_px || '');
  const [pnl, setPnl] = useStateD(initial.pnl || '');
  const [thesis, setThesis] = useStateD(initial.thesis || '');
  const [outcome, setOutcome] = useStateD(initial.outcome || '');
  const [lessons, setLessons] = useStateD(initial.lessons || '');
  const [saving, setSaving] = useStateD(false);
  const [err, setErr] = useStateD(null);

  const save = async () => {
    if (!trade_date) { setErr('要填日期'); return; }
    setSaving(true); setErr(null);
    try {
      await window.LifeData.saveTrade({
        id: initial.id,
        trade_date, system, symbol: symbol.trim() || null, side, status,
        qty, entry_px, exit_px, pnl,
        thesis: thesis.trim(), outcome: outcome.trim(), lessons: lessons.trim(),
      });
      onSaved();
    } catch (e) {
      console.error(e);
      setErr('儲存失敗：' + (e?.message || e));
      setSaving(false);
    }
  };

  return (
    <div onClick={onClose} style={{
      position: "fixed", inset: 0, zIndex: 100,
      background: "oklch(0.10 0.02 60 / 0.65)", backdropFilter: "blur(4px)",
      display: "flex", alignItems: "center", justifyContent: "center", padding: 20
    }}>
      <div onClick={e => e.stopPropagation()} className="paper modal-mobile-full" style={{
        width: "100%", maxWidth: 720, maxHeight: "90vh",
        overflowY: "auto", padding: "32px 36px",
        border: "1px solid var(--rule)",
        boxShadow: "0 30px 80px oklch(0 0 0 / 0.4)"
      }}>
        <div className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)" }}>{isNew ? "New Trade · 新一筆" : "Edit Trade · 編輯"}</div>
        <h2 className="han-display" style={{ fontSize: 24, margin: "8px 0 18px", fontWeight: 500 }}>
          {isNew ? '新一筆交易日誌' : '編輯交易日誌'}
        </h2>

        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 12, marginBottom: 12 }}>
          <div>
            <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>日期</div>
            <input className="field" type="date" value={trade_date} onChange={e => setTradeDate(e.target.value)} style={{ colorScheme: "light" }} />
          </div>
          <div>
            <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>平台</div>
            <select className="field" value={system} onChange={e => setSystem(e.target.value)}>
              {TRADE_SYSTEMS.map(s => <option key={s.value} value={s.value}>{s.label}</option>)}
            </select>
          </div>
          <div>
            <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>狀態</div>
            <select className="field" value={status} onChange={e => setStatus(e.target.value)}>
              <option value="open">進行中</option>
              <option value="closed">已平倉</option>
            </select>
          </div>
        </div>

        <div style={{ display: "grid", gridTemplateColumns: "2fr 1fr", gap: 12, marginBottom: 12 }}>
          <div>
            <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>Symbol（明文）</div>
            <input className="field" value={symbol} onChange={e => setSymbol(e.target.value)} placeholder="HSI / NG / BTC-USD" />
          </div>
          <div>
            <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>方向</div>
            <select className="field" value={side} onChange={e => setSide(e.target.value)}>
              <option value="LONG">LONG 多</option>
              <option value="SHORT">SHORT 空</option>
            </select>
          </div>
        </div>

        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr 1fr", gap: 12, marginBottom: 16 }}>
          <div>
            <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>數量</div>
            <input className="field" value={qty} onChange={e => setQty(e.target.value)} placeholder="1" />
          </div>
          <div>
            <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>入價</div>
            <input className="field" value={entry_px} onChange={e => setEntry(e.target.value)} placeholder="2.755" />
          </div>
          <div>
            <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>出價</div>
            <input className="field" value={exit_px} onChange={e => setExit(e.target.value)} placeholder="平倉後填" />
          </div>
          <div>
            <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>P&L</div>
            <input className="field" value={pnl} onChange={e => setPnl(e.target.value)} placeholder="100 / -50" />
          </div>
        </div>

        <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>Thesis · 入市理由（加密）</div>
        <textarea className="field" value={thesis} onChange={e => setThesis(e.target.value)}
          placeholder="點解入市？信號 / 預期 / 止損位 / 止賺位"
          style={{ minHeight: 90, resize: "vertical", lineHeight: 1.7, marginBottom: 12 }} />

        <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>Outcome · 結果（加密）</div>
        <textarea className="field" value={outcome} onChange={e => setOutcome(e.target.value)}
          placeholder="走勢點？跟 thesis 啱定錯？平倉時嘅情緒？"
          style={{ minHeight: 70, resize: "vertical", lineHeight: 1.7, marginBottom: 12 }} />

        <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>Lessons · 教訓（加密）</div>
        <textarea className="field" value={lessons} onChange={e => setLessons(e.target.value)}
          placeholder="下次相同情況點做？要改規則嗎？"
          style={{ minHeight: 70, resize: "vertical", lineHeight: 1.7, marginBottom: 16 }} />

        <div style={{ display: "flex", gap: 8, justifyContent: "flex-end", marginTop: 16 }}>
          <button className="btn btn-ghost" onClick={onClose} disabled={saving}>取消</button>
          <button className="btn btn-gold" onClick={save} disabled={saving}>
            {saving ? "封存中⋯" : "封存"}
          </button>
        </div>
        {err && <div style={{ color: "oklch(0.55 0.13 25)", fontSize: 13, marginTop: 10, textAlign: "right" }}>{err}</div>}
      </div>
    </div>
  );
}

/* ─── HEALTH / 健康 ─────────────────────────────────────────────── */
function HealthPage({ data }) {
  const [, force] = useStateD(0);
  const [today, setToday] = useStateD(null);
  const todayIso = window.LifeData.todayHKT();

  useEffectD(() => {
    const t = (window.LifeData.health || []).find(h => h.date === todayIso);
    setToday(t || { date: todayIso });
  }, [todayIso]);

  if (!today) return null;

  const updateField = async (field, value) => {
    const next = { ...today, [field]: value };
    setToday(next);
  };
  const save = async () => {
    const payload = {
      weight: numOrNull(today.weight),
      bp_sys: intOrNull(today.bp_sys),
      bp_dia: intOrNull(today.bp_dia),
      heart_rate: intOrNull(today.heart_rate),
      sleep_hours: numOrNull(today.sleep_hours),
      sleep_quality: intOrNull(today.sleep_quality),
      notes: today.notes || null,
    };
    await window.LifeData.saveHealth(todayIso, payload);
    force(x => x + 1);
  };

  const history = (data.health || []).filter(h => h.date <= todayIso).slice(0, 30).reverse();

  return (
    <div className="page-in" style={{ padding: "56px 72px 100px", maxWidth: 1100, margin: "0 auto" }}>
      <div className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)" }}>Chapter VIII</div>
      <h1 className="han-display" style={{ fontSize: 38, margin: "4px 0 0", letterSpacing: "0.2em", fontWeight: 500 }}>身 體 日 課</h1>
      <div className="en-title" style={{ fontSize: 18, color: "var(--ink-2)", marginTop: 4 }}>Health · 身為本錢</div>
      <p className="han-body" style={{ fontSize: 14, color: "var(--ink-2)", maxWidth: 580, marginTop: 12 }}>
        每日記低身體狀況。長期 sparkline 比某一日數值更值得睇。
      </p>
      <hr className="rule" style={{ margin: "24px 0 32px" }} />

      <div className="card" style={{ padding: "24px 28px", marginBottom: 28 }}>
        <div className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)", marginBottom: 14 }}>Today · {todayIso}</div>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 14, marginBottom: 14 }}>
          <NumField label="體重 kg" value={today.weight} onChange={v => updateField('weight', v)} step="0.1" />
          <NumField label="血壓 高" value={today.bp_sys} onChange={v => updateField('bp_sys', v)} />
          <NumField label="血壓 低" value={today.bp_dia} onChange={v => updateField('bp_dia', v)} />
          <NumField label="心率 bpm" value={today.heart_rate} onChange={v => updateField('heart_rate', v)} />
        </div>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14, marginBottom: 14 }}>
          <NumField label="睡眠（小時）" value={today.sleep_hours} onChange={v => updateField('sleep_hours', v)} step="0.5" />
          <div>
            <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>睡眠質素 1-5</div>
            <div style={{ display: "flex", gap: 4 }}>
              {[1,2,3,4,5].map(n => (
                <button key={n} onClick={() => updateField('sleep_quality', n)} className="btn"
                  style={{
                    flex: 1, padding: "8px 0",
                    background: today.sleep_quality === n ? "var(--gold)" : "transparent",
                    color: today.sleep_quality === n ? "oklch(0.20 0.04 60)" : "var(--ink-2)",
                    border: today.sleep_quality === n ? "1px solid var(--gold)" : "1px solid var(--rule)"
                  }}>{n}</button>
              ))}
            </div>
          </div>
        </div>
        <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>備註（明文 — 唔加密）</div>
        <textarea className="field" value={today.notes || ''} onChange={e => updateField('notes', e.target.value)}
          placeholder="今日身體點？跑咗 5 公里？感冒？" style={{ minHeight: 60, resize: "vertical", lineHeight: 1.7 }} />
        <div style={{ display: "flex", justifyContent: "flex-end", marginTop: 14 }}>
          <button className="btn btn-gold" onClick={save}>儲存今日</button>
        </div>
      </div>

      <h2 className="han-display" style={{ fontSize: 18, letterSpacing: "0.2em", fontWeight: 500, color: "var(--ink-2)", marginBottom: 16 }}>近 30 日趨勢</h2>
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 18 }}>
        <SparkCard title="體重 (kg)" data={history.map(h => h.weight)} dates={history.map(h => h.date)} unit="kg" />
        <SparkCard title="血壓 高 (mmHg)" data={history.map(h => h.bp_sys)} dates={history.map(h => h.date)} unit="" warn={[140, 'high']} />
        <SparkCard title="血壓 低 (mmHg)" data={history.map(h => h.bp_dia)} dates={history.map(h => h.date)} unit="" warn={[90, 'high']} />
        <SparkCard title="心率 (bpm)" data={history.map(h => h.heart_rate)} dates={history.map(h => h.date)} unit="" />
        <SparkCard title="睡眠時數" data={history.map(h => h.sleep_hours)} dates={history.map(h => h.date)} unit="h" />
        <SparkCard title="睡眠質素" data={history.map(h => h.sleep_quality)} dates={history.map(h => h.date)} unit="/5" />
      </div>
    </div>
  );
}

function NumField({ label, value, onChange, step = '1' }) {
  return (
    <div>
      <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>{label}</div>
      <input className="field" type="number" step={step}
        value={value ?? ''} onChange={e => onChange(e.target.value === '' ? null : e.target.value)} />
    </div>
  );
}

function numOrNull(v) {
  if (v == null || v === '') return null;
  const n = Number(v);
  return isNaN(n) ? null : n;
}
function intOrNull(v) {
  const n = numOrNull(v);
  return n == null ? null : Math.round(n);
}

function SparkCard({ title, data, dates, unit, warn }) {
  const valid = data.filter(v => v != null && !isNaN(Number(v))).map(Number);
  const latest = valid.length ? valid[valid.length - 1] : null;
  return (
    <div className="card" style={{ padding: "18px 22px" }}>
      <div className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)" }}>{title}</div>
      <div className="bignum" style={{ fontSize: 24, marginTop: 4, color: "var(--ink)" }}>
        {latest != null ? `${latest}${unit}` : <span style={{ color: 'var(--ink-3)', fontSize: 16 }}>—</span>}
      </div>
      <Sparkline data={data} dates={dates} />
    </div>
  );
}

function Sparkline({ data, dates, height = 40 }) {
  const validPoints = data.map((v, i) => v != null && !isNaN(Number(v)) ? { x: i, v: Number(v) } : null).filter(Boolean);
  if (validPoints.length < 2) {
    return <div style={{ height, marginTop: 8, color: "var(--ink-3)", fontSize: 11, fontStyle: "italic" }}>需 ≥ 2 日數據</div>;
  }
  const w = 320;
  const min = Math.min(...validPoints.map(p => p.v));
  const max = Math.max(...validPoints.map(p => p.v));
  const range = max - min || 1;
  const points = validPoints.map(p => {
    const x = (p.x / Math.max(1, data.length - 1)) * w;
    const y = height - ((p.v - min) / range) * height;
    return `${x},${y}`;
  }).join(' ');
  const last = validPoints[validPoints.length - 1];
  const lastX = (last.x / Math.max(1, data.length - 1)) * w;
  const lastY = height - ((last.v - min) / range) * height;
  return (
    <svg width="100%" height={height} viewBox={`0 0 ${w} ${height}`} preserveAspectRatio="none" style={{ marginTop: 8 }}>
      <polyline points={points} fill="none" stroke="var(--gold-deep)" strokeWidth="1.6" />
      <circle cx={lastX} cy={lastY} r="2.5" fill="var(--gold-deep)" />
    </svg>
  );
}

/* ─── DATES / 日期 ──────────────────────────────────────────────── */
const LU_MONTH_NAMES = ['正','二','三','四','五','六','七','八','九','十','冬','臘'];
const LU_DAY_NAMES = [
  '初一','初二','初三','初四','初五','初六','初七','初八','初九','初十',
  '十一','十二','十三','十四','十五','十六','十七','十八','十九','二十',
  '廿一','廿二','廿三','廿四','廿五','廿六','廿七','廿八','廿九','三十'
];

function nextOccurrenceISO(item, todayIso) {
  const todayY = parseInt(todayIso.slice(0, 4), 10);
  if (item.is_lunar && window.Lunar) {
    const [, lm, ld] = item.date.split('-').map(Number);
    for (let ly = todayY - 1; ly <= todayY + 1; ly++) {
      try {
        const s = window.Lunar.toSolar(ly, lm, ld);
        if (s.iso >= todayIso) return s.iso;
      } catch {}
    }
    return null;
  }
  const [, mm, dd] = item.date.split('-');
  for (let y = todayY; y <= todayY + 1; y++) {
    const iso = `${y}-${mm}-${dd}`;
    if (iso >= todayIso) return iso;
  }
  return item.date;
}

function DatesPage({ data }) {
  const [items, setItems] = useStateD([...(data.dates || [])]);
  const [editing, setEditing] = useStateD(null);
  const todayIso = window.LifeData.todayHKT();

  const refresh = () => setItems([...window.LifeData.dates]);

  const onDelete = async (it) => {
    if (!confirm(`刪除「${it.title}」？`)) return;
    await window.LifeData.deleteDate(it.id);
    refresh();
  };

  // Festival presets
  const festivals = window.Lunar?.upcomingFestivals?.(todayIso, 365) || [];

  // Build enriched + sorted user list
  const enriched = items.map(it => {
    const next = nextOccurrenceISO(it, todayIso);
    const days = next ? Math.round((new Date(next + 'T00:00:00+08:00') - new Date(todayIso + 'T00:00:00+08:00')) / 86400000) : null;
    return { ...it, _next: next, _days: days };
  }).sort((a, b) => (a._days ?? 9999) - (b._days ?? 9999));

  return (
    <div className="page-in" style={{ padding: "56px 72px 100px", maxWidth: 980, margin: "0 auto" }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start" }}>
        <div>
          <div className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)" }}>Chapter IX</div>
          <h1 className="han-display" style={{ fontSize: 38, margin: "4px 0 0", letterSpacing: "0.2em", fontWeight: 500 }}>重 要 日 期</h1>
          <div className="en-title" style={{ fontSize: 18, color: "var(--ink-2)", marginTop: 4 }}>Important Dates · 紀念與提醒</div>
        </div>
        <button className="btn btn-gold" onClick={() => setEditing({ is_lunar: false, recurring: 'yearly' })}>
          ✦ 加入日期
        </button>
      </div>
      <hr className="rule" style={{ margin: "24px 0" }} />

      {/* My dates */}
      <div style={{ marginBottom: 32 }}>
        <SectionHead num="I" zh="我的日期" en="My Dates" count={enriched.length} />
        <div style={{ marginTop: 16, display: "flex", flexDirection: "column", gap: 10 }}>
          {enriched.length === 0 ? (
            <div className="card" style={{ padding: "32px 24px", textAlign: "center", color: "var(--ink-3)" }}>
              <p className="han-body" style={{ fontSize: 13, fontStyle: "italic" }}>
                尚未加入。生日、紀念日、法會、忌日，都可以記低自動提醒。
              </p>
            </div>
          ) : enriched.map(it => {
            const tag = it._days == null ? '—' : it._days < 0 ? '已過' : it._days === 0 ? '今日' : `${it._days} 日後`;
            const lunarLabel = it.is_lunar
              ? `農曆 ${LU_MONTH_NAMES[parseInt(it.date.split('-')[1])-1]}月${LU_DAY_NAMES[parseInt(it.date.split('-')[2])-1]}`
              : null;
            return (
              <div key={it.id} className="card" style={{ padding: "16px 20px" }}>
                <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", gap: 12 }}>
                  <div style={{ flex: 1 }}>
                    <h3 className="han-display" style={{ fontSize: 17, margin: 0, fontWeight: 500 }}>{it.title}</h3>
                    <div className="mono" style={{ fontSize: 11, color: "var(--ink-3)", marginTop: 4, letterSpacing: "0.05em" }}>
                      下次：{it._next || it.date}
                      {lunarLabel && <span style={{ marginLeft: 10 }}>· {lunarLabel}</span>}
                      {it.recurring === 'yearly' && <span style={{ marginLeft: 10 }}>· 每年</span>}
                    </div>
                    {it.notes && <p className="han-body" style={{ fontSize: 12, color: "var(--ink-3)", marginTop: 4, marginBottom: 0, fontStyle: "italic" }}>{it.notes}</p>}
                  </div>
                  <span className="mono" style={{ fontSize: 12, color: it._days < 0 ? "var(--ink-3)" : it._days === 0 ? "var(--gold-deep)" : "var(--ink-2)", fontWeight: 600, whiteSpace: "nowrap" }}>{tag}</span>
                  <div style={{ display: "flex", gap: 4 }}>
                    <button onClick={() => setEditing(it)} style={{
                      padding: "4px 10px", fontSize: 11,
                      background: "transparent", border: "1px solid var(--rule)",
                      cursor: "pointer", fontFamily: "var(--font-han)", color: "var(--ink-3)"
                    }}>編輯</button>
                    <button onClick={() => onDelete(it)} style={{
                      padding: "4px 10px", fontSize: 11,
                      background: "transparent", border: "1px solid var(--rule)",
                      cursor: "pointer", color: "var(--ink-3)"
                    }}>✕</button>
                  </div>
                </div>
              </div>
            );
          })}
        </div>
      </div>

      {/* Festival countdown */}
      <div>
        <SectionHead num="II" zh="節日倒數" en="Festivals" count={festivals.length} />
        <div className="card" style={{ marginTop: 16, padding: "16px 24px" }}>
          {festivals.length === 0 ? (
            <p className="muted">無</p>
          ) : festivals.slice(0, 8).map(f => (
            <div key={f.iso} style={{ display: "flex", justifyContent: "space-between", padding: "8px 0", borderBottom: "1px dotted var(--rule)", fontSize: 14 }}>
              <span>{f.name}</span>
              <span className="mono" style={{ color: "var(--ink-3)", fontSize: 12 }}>
                {f.iso} · {f.days === 0 ? '今日' : f.days + ' 日後'}
              </span>
            </div>
          ))}
        </div>
      </div>

      {editing != null && (
        <DateEditor
          initial={editing}
          onClose={() => setEditing(null)}
          onSaved={() => { refresh(); setEditing(null); }}
        />
      )}
    </div>
  );
}

function DateEditor({ initial, onClose, onSaved }) {
  const isNew = !initial.id;
  const [title, setTitle] = useStateD(initial.title || '');
  const [date, setDate] = useStateD(initial.date || '');
  const [is_lunar, setIsLunar] = useStateD(!!initial.is_lunar);
  const [recurring, setRecurring] = useStateD(initial.recurring || 'yearly');
  const [notes, setNotes] = useStateD(initial.notes || '');
  const [saving, setSaving] = useStateD(false);
  const [err, setErr] = useStateD(null);

  const save = async () => {
    if (!title.trim() || !date) { setErr('要填標題同日期'); return; }
    setSaving(true); setErr(null);
    try {
      const payload = { title: title.trim(), date, is_lunar, recurring, notes: notes.trim() || null };
      if (isNew) await window.LifeData.addDate(payload);
      else await window.LifeData.updateDate(initial.id, payload);
      onSaved();
    } catch (e) {
      setErr('儲存失敗：' + (e?.message || e));
      setSaving(false);
    }
  };

  return (
    <div onClick={onClose} style={{
      position: "fixed", inset: 0, zIndex: 100,
      background: "oklch(0.10 0.02 60 / 0.65)", backdropFilter: "blur(4px)",
      display: "flex", alignItems: "center", justifyContent: "center", padding: 20
    }}>
      <div onClick={e => e.stopPropagation()} className="paper modal-mobile-full" style={{
        width: "100%", maxWidth: 520, padding: "32px 36px",
        border: "1px solid var(--rule)",
        boxShadow: "0 30px 80px oklch(0 0 0 / 0.4)"
      }}>
        <div className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)" }}>{isNew ? "New Date · 新增" : "Edit Date · 編輯"}</div>
        <h2 className="han-display" style={{ fontSize: 24, margin: "8px 0 18px", fontWeight: 500 }}>
          {isNew ? '加入一個日期' : '編輯日期'}
        </h2>

        <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>標題</div>
        <input className="field" value={title} onChange={e => setTitle(e.target.value)}
          placeholder="例：媽媽生日 / 結婚紀念日" autoFocus style={{ marginBottom: 12 }} />

        <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>日期</div>
        <input className="field" type="date" value={date} onChange={e => setDate(e.target.value)}
          style={{ marginBottom: 8, colorScheme: "light" }} />

        <label style={{ display: "flex", alignItems: "center", gap: 8, fontSize: 13, color: "var(--ink-2)", cursor: "pointer", marginBottom: 14 }}>
          <input type="checkbox" checked={is_lunar} onChange={e => setIsLunar(e.target.checked)}
            style={{ width: "auto", flex: "0 0 auto", accentColor: "var(--gold-deep)" }} />
          農曆日期（每年自動轉公曆）
        </label>

        <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>重複</div>
        <select className="field" value={recurring} onChange={e => setRecurring(e.target.value)} style={{ marginBottom: 12 }}>
          <option value="yearly">每年</option>
          <option value="once">只一次</option>
        </select>

        <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 4 }}>備註（可選）</div>
        <textarea className="field" value={notes} onChange={e => setNotes(e.target.value)}
          placeholder="例：記得送花" style={{ minHeight: 60, resize: "vertical", lineHeight: 1.7, marginBottom: 16 }} />

        <div style={{ display: "flex", gap: 8, justifyContent: "flex-end" }}>
          <button className="btn btn-ghost" onClick={onClose} disabled={saving}>取消</button>
          <button className="btn btn-gold" onClick={save} disabled={saving}>
            {saving ? "儲存中⋯" : "儲存"}
          </button>
        </div>
        {err && <div style={{ color: "oklch(0.55 0.13 25)", fontSize: 13, marginTop: 10, textAlign: "right" }}>{err}</div>}
      </div>
    </div>
  );
}

/* ─── PHASE 2 PLACEHOLDERS ─────────────────────────────────────── */
function PlaceholderPage({ chapter, zh, en, blurb }) {
  return (
    <div className="page-in" style={{ padding: "56px 72px 100px", maxWidth: 880, margin: "0 auto" }}>
      <div className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)" }}>Chapter {chapter}</div>
      <h1 className="han-display" style={{ fontSize: 38, margin: "4px 0 0", letterSpacing: "0.2em", fontWeight: 500 }}>{zh}</h1>
      <div className="en-title" style={{ fontSize: 18, color: "var(--ink-2)", marginTop: 4 }}>{en}</div>
      <hr className="rule" style={{ margin: "24px 0 32px" }} />
      <div className="card" style={{ padding: "60px 40px", textAlign: "center" }}>
        <window.LotusMark size={48} />
        <p className="han-body" style={{ fontSize: 16, color: "var(--ink-2)", marginTop: 24, lineHeight: 1.9 }}>
          {blurb}
        </p>
        <div className="en-caps" style={{ fontSize: 10, color: "var(--gold-deep)", marginTop: 24, letterSpacing: "0.4em" }}>
          Phase II · 待展開
        </div>
      </div>
    </div>
  );
}

/* ─── NOTES / 備忘 (encrypted credential vault) ─────────────────── */
const DEFAULT_CATS = ['金融', '證件', '保險', '帳號', '醫療', '設備', '其他'];

function NotesPage({ data }) {
  const [notes, setNotes] = useStateD(data.notes || []);
  const [cat, setCat] = useStateD('全部');
  const [reveal, setReveal] = useStateD({});
  const [editing, setEditing] = useStateD(null); // null = no modal; {} = new; {id...} = edit
  const [search, setSearch] = useStateD('');

  const refresh = () => setNotes([...window.LifeData.notes]);

  // Build categories from existing + defaults
  const cats = useMemoD(() => {
    const used = new Set(notes.map(n => n.category));
    return Array.from(new Set([...DEFAULT_CATS, ...used])).filter(Boolean);
  }, [notes]);

  const filtered = notes.filter(n => {
    if (cat !== '全部' && n.category !== cat) return false;
    if (search.trim()) {
      const q = search.toLowerCase();
      const hay = (n.title + ' ' + n.category + ' ' + (n.note || '') + ' ' + n.fields.map(f => f.join(' ')).join(' ')).toLowerCase();
      if (!hay.includes(q)) return false;
    }
    return true;
  });

  const toggleReveal = (id) => setReveal(r => ({ ...r, [id]: !r[id] }));

  const onDelete = async (note) => {
    if (!confirm(`確定刪除「${note.title}」？此動作不可復原。`)) return;
    await window.LifeData.deleteSecretNote(note.id);
    refresh();
  };

  return (
    <div className="page-in" style={{ padding: "56px 72px 100px", maxWidth: 1100, margin: "0 auto" }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start" }}>
        <div>
          <div className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)" }}>Chapter VII</div>
          <h1 className="han-display" style={{ fontSize: 38, margin: "4px 0 0", letterSpacing: "0.2em", fontWeight: 500 }}>備 忘 錄</h1>
          <div className="en-title" style={{ fontSize: 18, color: "var(--ink-2)", marginTop: 4 }}>Things to Remember</div>
        </div>
        <button className="btn btn-gold" onClick={() => setEditing({})}>✦ 新增</button>
      </div>
      <p className="han-body" style={{ fontSize: 14, color: "var(--ink-2)", maxWidth: 520, marginTop: 12 }}>
        重要的不是記住所有事，是把該記住的放在找得到的地方。內容用 AES-256 加密，伺服器只見類別。
      </p>
      <hr className="rule" style={{ margin: "24px 0" }} />

      {/* Controls: category filter + search */}
      <div style={{ display: "flex", gap: 16, alignItems: "center", marginBottom: 24, flexWrap: "wrap" }}>
        <div style={{ display: "flex", gap: 6, flexWrap: "wrap" }}>
          {['全部', ...cats].map(c => (
            <button key={c} onClick={() => setCat(c)} className="tag" style={{
              cursor: "pointer", padding: "5px 14px",
              background: cat === c ? "var(--ink)" : "oklch(0.88 0.04 78 / 0.5)",
              color: cat === c ? "var(--paper)" : "var(--ink-2)",
              border: "1px solid var(--rule)"
            }}>{c}</button>
          ))}
        </div>
        <input
          className="field"
          placeholder="搜尋..."
          value={search}
          onChange={e => setSearch(e.target.value)}
          style={{ flex: 1, minWidth: 200, maxWidth: 280 }}
        />
      </div>

      {filtered.length === 0 ? (
        <div className="card" style={{ padding: "60px 40px", textAlign: "center" }}>
          <window.LotusMark size={40} />
          <p className="han-body" style={{ fontSize: 14, color: "var(--ink-3)", marginTop: 16, marginBottom: 0 }}>
            {notes.length === 0 ? '尚未加入任何備忘。撳右上「新增」開始。' : '無符合嘅項目。'}
          </p>
        </div>
      ) : (
        <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(360px, 1fr))", gap: 18 }}>
          {filtered.map(n => {
            const isRevealed = !!reveal[n.id];
            const updated = n.updated_at ? new Date(n.updated_at * 1000).toISOString().slice(0, 10).replace(/-/g, '.') : '';
            return (
              <div key={n.id} className="card" style={{ padding: "20px 24px" }}>
                <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
                  <div>
                    <span className="en-caps" style={{ fontSize: 10, color: "var(--gold-deep)" }}>{n.category}</span>
                    <h3 className="han-display" style={{ fontSize: 17, margin: "4px 0 0", fontWeight: 500 }}>{n.title}</h3>
                  </div>
                  <span className="mono" style={{ fontSize: 10, color: "var(--ink-3)" }}>upd. {updated}</span>
                </div>
                <hr className="rule" style={{ margin: "12px 0" }} />
                {n.fields.length > 0 ? (
                  <dl style={{ margin: 0, display: "grid", gridTemplateColumns: "auto 1fr", rowGap: 8, columnGap: 16 }}>
                    {n.fields.map(([k, v], fi) => (
                      <React.Fragment key={fi}>
                        <dt style={{ fontSize: 12, color: "var(--ink-3)", fontFamily: "var(--font-han)" }}>{k}</dt>
                        <dd className="mono" style={{ margin: 0, fontSize: 13, color: "var(--ink)", wordBreak: "break-all" }}>
                          {isRevealed ? v : (v || '').replace(/[A-Za-z0-9]/g, "•")}
                        </dd>
                      </React.Fragment>
                    ))}
                  </dl>
                ) : (
                  <p className="han-body" style={{ fontSize: 12, color: "var(--ink-3)", margin: 0, fontStyle: "italic" }}>
                    無欄位
                  </p>
                )}
                {n.note && (
                  <>
                    <hr className="rule" style={{ margin: "12px 0" }} />
                    <p className="han-body" style={{ fontSize: 13, color: "var(--ink-2)", margin: 0, lineHeight: 1.7, whiteSpace: "pre-line" }}>
                      {isRevealed ? n.note : '— 已隱藏 —'}
                    </p>
                  </>
                )}
                <div style={{ display: "flex", gap: 8, marginTop: 16, justifyContent: "space-between" }}>
                  <button onClick={() => toggleReveal(n.id)} style={{
                    padding: "4px 10px", fontSize: 11,
                    background: "transparent", border: "1px solid var(--rule)",
                    cursor: "pointer", fontFamily: "var(--font-han)", color: "var(--ink-2)",
                    letterSpacing: "0.1em"
                  }}>{isRevealed ? "✦ 隱藏" : "○ 顯示"}</button>
                  <div style={{ display: "flex", gap: 4 }}>
                    <button onClick={() => setEditing(n)} style={{
                      padding: "4px 10px", fontSize: 11,
                      background: "transparent", border: "1px solid var(--rule)",
                      cursor: "pointer", fontFamily: "var(--font-han)", color: "var(--ink-3)",
                    }}>編輯</button>
                    <button onClick={() => onDelete(n)} style={{
                      padding: "4px 10px", fontSize: 11,
                      background: "transparent", border: "1px solid var(--rule)",
                      cursor: "pointer", color: "var(--ink-3)",
                    }}>✕</button>
                  </div>
                </div>
              </div>
            );
          })}
        </div>
      )}

      {editing != null && (
        <NoteEditor
          initial={editing}
          cats={cats}
          onClose={() => setEditing(null)}
          onSaved={() => { refresh(); setEditing(null); }}
        />
      )}
    </div>
  );
}

function NoteEditor({ initial, cats, onClose, onSaved }) {
  const isNew = !initial.id;
  const [category, setCategory] = useStateD(initial.category || cats[0] || '其他');
  const [title, setTitle] = useStateD(initial.title || '');
  const [fields, setFields] = useStateD(initial.fields ? [...initial.fields] : [['', '']]);
  const [note, setNote] = useStateD(initial.note || '');
  const [saving, setSaving] = useStateD(false);
  const [err, setErr] = useStateD(null);

  const setField = (i, kv, v) => {
    const arr = fields.map((row, idx) => idx === i ? [kv === 'k' ? v : row[0], kv === 'v' ? v : row[1]] : row);
    setFields(arr);
  };
  const addField = () => setFields([...fields, ['', '']]);
  const removeField = (i) => setFields(fields.filter((_, idx) => idx !== i));

  const save = async () => {
    if (!title.trim()) { setErr('要輸入標題'); return; }
    if (!category.trim()) { setErr('要揀類別'); return; }
    setSaving(true); setErr(null);
    try {
      const cleanFields = fields.filter(([k, v]) => (k || '').trim() || (v || '').trim());
      await window.LifeData.saveSecretNote({
        id: initial.id,
        category: category.trim(),
        title: title.trim(),
        fields: cleanFields,
        note: note.trim(),
      });
      onSaved();
    } catch (e) {
      console.error(e);
      setErr('儲存失敗：' + (e?.message || e));
      setSaving(false);
    }
  };

  return (
    <div onClick={onClose} style={{
      position: "fixed", inset: 0, zIndex: 100,
      background: "oklch(0.10 0.02 60 / 0.65)", backdropFilter: "blur(4px)",
      display: "flex", alignItems: "center", justifyContent: "center", padding: 20
    }}>
      <div onClick={e => e.stopPropagation()} className="paper modal-mobile-full" style={{
        width: "100%", maxWidth: 640, maxHeight: "90vh",
        overflowY: "auto", padding: "32px 36px",
        border: "1px solid var(--rule)",
        boxShadow: "0 30px 80px oklch(0 0 0 / 0.4)"
      }}>
        <div className="en-caps" style={{ fontSize: 10, color: "var(--ink-3)" }}>{isNew ? "New Note · 新增備忘" : "Edit Note · 編輯備忘"}</div>
        <h2 className="han-display" style={{ fontSize: 24, margin: "8px 0 18px", fontWeight: 500 }}>{isNew ? '新增一頁備忘' : '編輯備忘'}</h2>

        <div style={{ display: "grid", gridTemplateColumns: "150px 1fr", gap: 12, marginBottom: 12 }}>
          <select className="field" value={category} onChange={e => setCategory(e.target.value)}>
            {cats.map(c => <option key={c} value={c}>{c}</option>)}
            <option value="__new__">+ 自訂類別⋯</option>
          </select>
          {category === '__new__' ? (
            <input className="field" placeholder="輸入新類別名稱" autoFocus
              onChange={e => setCategory(e.target.value)} value="" />
          ) : (
            <input className="field" placeholder="標題（例：HSBC 主帳戶）"
              value={title} onChange={e => setTitle(e.target.value)} autoFocus />
          )}
        </div>

        {category !== '__new__' || (
          <input className="field" placeholder="標題" style={{ marginBottom: 12 }}
            value={title} onChange={e => setTitle(e.target.value)} />
        )}

        <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 6, marginTop: 16 }}>欄位 · Fields</div>
        <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
          {fields.map((row, i) => (
            <div key={i} style={{ display: "grid", gridTemplateColumns: "150px 1fr auto", gap: 8 }}>
              <input className="field" placeholder="鍵（如：帳號）" value={row[0]} onChange={e => setField(i, 'k', e.target.value)} />
              <input className="field" placeholder="值（會被加密）" value={row[1]} onChange={e => setField(i, 'v', e.target.value)} />
              <button onClick={() => removeField(i)} title="刪欄" style={{
                background: "transparent", border: "1px solid var(--rule)",
                color: "var(--ink-3)", cursor: "pointer", padding: "0 12px", borderRadius: 2, fontSize: 12
              }}>✕</button>
            </div>
          ))}
          <button className="btn btn-ghost" onClick={addField} style={{ alignSelf: "flex-start", marginTop: 4, padding: "6px 14px", fontSize: 12 }}>
            ✦ 加欄
          </button>
        </div>

        <div className="en-caps" style={{ fontSize: 9, color: "var(--ink-3)", marginBottom: 6, marginTop: 18 }}>備忘 · Memo</div>
        <textarea
          className="field"
          value={note}
          onChange={e => setNote(e.target.value)}
          placeholder="補充說明（會被加密）"
          style={{ minHeight: 80, resize: "vertical", lineHeight: 1.7 }}
        />

        <div style={{ display: "flex", gap: 10, marginTop: 24, justifyContent: "space-between", alignItems: "center" }}>
          <span className="han-body" style={{ fontSize: 11, color: "var(--ink-3)", fontStyle: "italic" }}>
            🔒 標題、欄位、備忘 全部 AES-256 加密
          </span>
          <div style={{ display: "flex", gap: 8 }}>
            <button className="btn btn-ghost" onClick={onClose} disabled={saving}>取消</button>
            <button className="btn btn-gold" onClick={save} disabled={saving}>
              {saving ? "封存中⋯" : "封存"}
            </button>
          </div>
        </div>
        {err && <div style={{ color: "oklch(0.55 0.13 25)", fontSize: 13, marginTop: 10, textAlign: "right" }}>{err}</div>}
      </div>
    </div>
  );
}

window.DiaryPage = DiaryPage;
window.TasksPage = TasksPage;
window.PortfolioPage = PortfolioPage;
window.GoalsPage = GoalsPage;
window.HabitsPage = HabitsPage;
window.TradeJournalPage = TradeJournalPage;
window.HealthPage = HealthPage;
window.DatesPage = DatesPage;
window.NotesPage = NotesPage;
window.YearThemeCard = YearThemeCard;
