/* Diary module — Nutri-style screens */

const _DIARY_MONTHS = ['January','February','March','April','May','June','July','August','September','October','November','December'];
const _DIARY_MONTHS_SHORT = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];

/* ── Title display helpers — never render the literal "Untitled" ──
   _diaryTitle: clean title or '' (treats legacy auto-stored "Untitled" as empty).
   _diaryLabel: best label for list cards — title → first line of text → mood label. */
function _diaryTitle(t) { const s = (t || '').trim(); return (s && s !== 'Untitled') ? s : ''; }
function _diaryLabel(entry) {
  const t = _diaryTitle(entry && entry.title);
  if (t) return t;
  const body = ((entry && entry.text) || '').trim();
  if (body) { const first = body.split('\n')[0].trim(); return first.length > 60 ? first.slice(0, 60) + '…' : first; }
  const m = ND_MOOD_META[entry && entry.mood];
  return m ? m.label + ' day' : '';
}

/* ── Tag color helper (built-in + custom) ── */
function _getTagColor(tag) {
  if (ND_TAG_COLORS[tag]) return ND_TAG_COLORS[tag];
  const palette = ['#E8845A','#C15C9B','#3BA8C0','#8B6ACF','#D6A920','#5BA870','#C44B4B','#45829B'];
  let h = 0;
  for (let i = 0; i < tag.length; i++) h = ((h << 5) - h + tag.charCodeAt(i)) | 0;
  return palette[Math.abs(h) % palette.length];
}

/* ── Date range presets & compute (used by DiaryStats) ── */
const _DIARY_RANGE_PRESETS = [
  { id: 'today',       label: 'Today' },
  { id: 'last7',       label: 'Last 7 Days' },
  { id: 'last14',      label: 'Last 14 Days' },
  { id: 'last30',      label: 'Last 30 Days' },
  { id: 'thisMonth',   label: 'This Month' },
  { id: 'lastMonth',   label: 'Last Month' },
  { id: 'thisQuarter', label: 'This Quarter' },
  { id: 'thisYear',    label: 'This Year' },
  { id: 'allTime',     label: 'All Time' },
  { id: 'custom',      label: '📅 Custom' },
];

function _diaryRangeCompute(rangeId, customStart, customEnd, entries) {
  // Local-timezone date key — never toISOString() which shifts in UTC+N timezones.
  function _iso(d) { return d.getFullYear() + '-' + String(d.getMonth()+1).padStart(2,'0') + '-' + String(d.getDate()).padStart(2,'0'); }
  const today = todayISO();
  const now = new Date();
  switch (rangeId) {
    case 'today':     return { start: today, end: today, label: 'Today' };
    case 'last7':     return { start: daysAgo(6),  end: today, label: 'Last 7 Days' };
    case 'last14':    return { start: daysAgo(13), end: today, label: 'Last 14 Days' };
    case 'last30':    return { start: daysAgo(29), end: today, label: 'Last 30 Days' };
    case 'thisMonth': {
      const s = `${now.getFullYear()}-${String(now.getMonth()+1).padStart(2,'0')}-01`;
      return { start: s, end: today, label: 'This Month' };
    }
    case 'lastMonth': {
      const lm1 = new Date(now.getFullYear(), now.getMonth()-1, 1);
      const lmE = new Date(now.getFullYear(), now.getMonth(), 0);
      return { start: _iso(lm1), end: _iso(lmE), label: 'Last Month' };
    }
    case 'thisQuarter': {
      const qStart = new Date(now.getFullYear(), Math.floor(now.getMonth()/3)*3, 1);
      return { start: _iso(qStart), end: today, label: 'This Quarter' };
    }
    case 'thisYear':  return { start: `${now.getFullYear()}-01-01`, end: today, label: 'This Year' };
    case 'allTime': {
      const dates = entries.map(e => e.date).filter(Boolean).sort();
      return dates.length ? { start: dates[0], end: today, label: 'All Time' } : { start: today, end: today, label: 'All Time' };
    }
    case 'custom': {
      if (!customStart && !customEnd) return { start: daysAgo(29), end: today, label: 'Custom Range' };
      const s = customStart || today, e = customEnd || today;
      const [rs, re] = s <= e ? [s, e] : [e, s];
      return { start: rs, end: re, label: `${rs} → ${re}` };
    }
    default: return { start: daysAgo(29), end: today, label: 'Last 30 Days' };
  }
}

/* ── Diary Range Selector ── */
function _DiaryRangeSelector({ rangeId, setRangeId, customStart, setCustomStart, customEnd, setCustomEnd }) {
  return (
    <div>
      <div style={{
        display: 'flex', gap: 6, overflowX: 'auto',
        margin: '0 -18px', padding: '0 18px 2px',
        scrollbarWidth: 'none',
      }} className="nutri-scroll-x">
        {_DIARY_RANGE_PRESETS.map(p => (
          <button key={p.id} onClick={() => setRangeId(p.id)} style={{
            flexShrink: 0, padding: '6px 12px', borderRadius: 999,
            background: rangeId === p.id ? 'var(--text)' : 'var(--surface)',
            color:      rangeId === p.id ? 'var(--bg)'   : 'var(--text)',
            border: '1px solid ' + (rangeId === p.id ? 'var(--text)' : 'var(--border-2)'),
            fontSize: 12, fontWeight: 600, cursor: 'pointer', font: 'inherit', whiteSpace: 'nowrap',
          }}>{p.label}</button>
        ))}
      </div>
      {rangeId === 'custom' && (
        <div style={{ display: 'flex', gap: 8, alignItems: 'center', marginTop: 8 }}>
          <input type="date" value={customStart} onChange={e => setCustomStart(e.target.value)} style={{
            flex: 1, padding: '8px 10px', borderRadius: 10,
            border: '1px solid var(--border-2)', background: 'var(--surface)',
            color: 'var(--text)', font: 'inherit', fontSize: 13,
          }}/>
          <span style={{ fontSize: 13, color: 'var(--muted)', flexShrink: 0, fontWeight: 700 }}>→</span>
          <input type="date" value={customEnd} onChange={e => setCustomEnd(e.target.value)} style={{
            flex: 1, padding: '8px 10px', borderRadius: 10,
            border: '1px solid var(--border-2)', background: 'var(--surface)',
            color: 'var(--text)', font: 'inherit', fontSize: 13,
          }}/>
        </div>
      )}
    </div>
  );
}

/* ── SVG Donut chart ── */
function _DiaryDonutChart({ slices, size = 130 }) {
  const total = slices.reduce((s, sl) => s + sl.value, 0);
  if (!total) return null;
  const r = 42, cx = size / 2, cy = size / 2, sw = 15;
  const circ = 2 * Math.PI * r;
  let cumPct = 0;
  return (
    <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`} style={{ flexShrink: 0 }}>
      <circle cx={cx} cy={cy} r={r} fill="none" stroke="var(--ring-track)" strokeWidth={sw}/>
      {slices.map((sl, i) => {
        const pct = sl.value / total;
        const dashLen = pct * circ;
        const rotation = cumPct * 360 - 90;
        cumPct += pct;
        return (
          <circle key={i} cx={cx} cy={cy} r={r}
            fill="none" stroke={sl.color} strokeWidth={sw}
            strokeDasharray={`${dashLen} ${circ - dashLen}`}
            style={{ transform: `rotate(${rotation}deg)`, transformOrigin: `${cx}px ${cy}px` }}
          />
        );
      })}
      <text x={cx} y={cy - 4} textAnchor="middle" fontSize="18" fontWeight="800" fill="var(--text)">{total}</text>
      <text x={cx} y={cy + 12} textAnchor="middle" fontSize="9" fill="var(--muted)">entries</text>
    </svg>
  );
}

/* ═══════════════════════════════════════════════════════════════════
   DIARY HOME — today + "On This Day" + mood + recent (full entries only)
   ═══════════════════════════════════════════════════════════════════*/
function DiaryHome({ entries, onOpen, onCompose }) {
  const [q, setQ] = React.useState('');
  const [tagFilter, setTagFilter] = React.useState(null);

  const today = todayISO(); // live local date — avoids stale NUTRI_TODAY after midnight
  const todayMD = today.slice(5, 10);
  const curY = parseInt(today.slice(0, 4), 10);

  const onThisDay = React.useMemo(() =>
    entries
      .filter(e => e.date && e.date.slice(5, 10) === todayMD && e.date !== today && e.entryMode !== 'quick')
      .sort((a, b) => b.date.localeCompare(a.date)),
    [entries, today, todayMD]
  );

  const todayEntry = entries.find(e => e.date === today && e.entryMode !== 'quick');
  const last30 = entries.filter(e => e.date >= daysAgo(30));
  const moodCounts = {};
  last30.forEach(e => { moodCounts[e.mood] = (moodCounts[e.mood] || 0) + 1; });
  const total30 = last30.length || 1;

  const allTags = [...new Set(entries.flatMap(e => e.tags || []))];
  const sorted = [...entries].sort((a, b) => b.date.localeCompare(a.date));

  const isSearching = !!(q || tagFilter);

  const filtered = sorted.filter(e => {
    const ql = q.toLowerCase();
    const moodLabel = (ND_MOOD_META[e.mood]?.label || e.mood || '').toLowerCase();
    const matchQ = !q ||
      (e.title || '').toLowerCase().includes(ql) ||
      (e.text || '').toLowerCase().includes(ql) ||
      (e.tags || []).some(t => t.toLowerCase().includes(ql)) ||
      moodLabel.includes(ql) ||
      (e.date || '').includes(q) ||
      (e.date || '').slice(0, 4).includes(q);
    const matchTag = !tagFilter || (e.tags || []).includes(tagFilter);
    return matchQ && matchTag;
  });

  // Recent = full entries only when not searching; all matches when searching
  const recentEntries = isSearching
    ? filtered.filter(e => !todayEntry || e.id !== todayEntry.id)
    : filtered.filter(e => e.entryMode !== 'quick' && (!todayEntry || e.id !== todayEntry.id));
  const hiddenQuickCount = isSearching ? 0 : filtered.filter(e => e.entryMode === 'quick').length;

  const todayLabel = (() => {
    const d = new Date(today + 'T00:00:00');
    return d.toLocaleDateString(undefined, { month: 'long', day: 'numeric' });
  })();

  return (
    <div style={{ padding: '12px 18px 24px', display: 'flex', flexDirection: 'column', gap: 16 }}>

      {/* ── Header ── */}
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', paddingTop: 4 }}>
        <div>
          <div style={{ fontSize: 22, fontWeight: 700, letterSpacing: '-0.02em' }}>Diary</div>
          <div style={{ fontSize: 12.5, color: 'var(--muted)', marginTop: 2, fontWeight: 500 }}>
            {entries.length} {entries.length === 1 ? 'entry' : 'entries'} · {last30.length} this month
          </div>
        </div>
        <button onClick={onCompose} style={{
          display: 'inline-flex', alignItems: 'center', gap: 6, padding: '7px 14px', borderRadius: 999,
          background: 'var(--accent)', color: 'var(--on-accent)', border: '1px solid var(--accent)',
          font: 'inherit', fontSize: 12.5, fontWeight: 600, cursor: 'pointer',
        }}><PlusIcon size={14}/> Write</button>
      </div>

      {/* ── On This Day ── */}
      {onThisDay.length > 0 && (
        <div style={{ ...nutriStyles.card, padding: 16, borderLeft: '3px solid var(--accent)' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 12 }}>
            <span style={{ fontSize: 22 }}>📅</span>
            <div>
              <div style={{ fontSize: 14, fontWeight: 700 }}>On This Day — {todayLabel}</div>
              <div style={{ fontSize: 12, color: 'var(--muted)', marginTop: 1 }}>
                {onThisDay.length} {onThisDay.length === 1 ? 'memory' : 'memories'} from past years
              </div>
            </div>
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            {onThisDay.map(e => (
              <DiaryEntryCard key={e.id} entry={e} onClick={() => onOpen(e)} showYear yearsAgo={curY - parseInt(e.date.slice(0, 4), 10)}/>
            ))}
          </div>
        </div>
      )}

      {/* ── Today's entry / prompt ── */}
      {todayEntry ? (
        <DiaryEntryCard entry={todayEntry} onClick={() => onOpen(todayEntry)} featured/>
      ) : (
        <button onClick={onCompose} style={{
          ...nutriStyles.card, padding: 18, display: 'flex', alignItems: 'center', gap: 14,
          width: '100%', textAlign: 'left', cursor: 'pointer', font: 'inherit', color: 'var(--text)',
          background: `linear-gradient(135deg, var(--surface) 0%, var(--surface-2) 100%)`,
        }}>
          <div style={{ fontSize: 30 }}>✍️</div>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 15, fontWeight: 600 }}>Today's entry</div>
            <div style={{ fontSize: 12.5, color: 'var(--muted)', marginTop: 2 }}>How was your day? Tap to write.</div>
          </div>
          <ChevronRight size={18}/>
        </button>
      )}

      {/* ── Mood breakdown ── */}
      {last30.length > 0 && (
        <div style={{ ...nutriStyles.card, padding: 16 }}>
          <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 12 }}>
            <div style={{ fontSize: 14, fontWeight: 600 }}>Mood · 30 days</div>
            <div style={{ fontSize: 11, color: 'var(--muted)' }}>{last30.length} entries</div>
          </div>
          <div style={{ display: 'flex', height: 12, borderRadius: 999, overflow: 'hidden', background: 'var(--ring-track)', marginBottom: 12 }}>
            {Object.entries(ND_MOOD_META).map(([k, m]) => {
              const n = moodCounts[k] || 0;
              if (!n) return null;
              return <div key={k} style={{ width: `${(n / total30) * 100}%`, background: m.color }}/>;
            })}
          </div>
          <div style={{ display: 'flex', gap: 14, flexWrap: 'wrap' }}>
            {Object.entries(ND_MOOD_META).map(([k, m]) => {
              const n = moodCounts[k] || 0;
              return (
                <div key={k} style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                  <div style={{ width: 8, height: 8, borderRadius: 2, background: m.color }}/>
                  <div style={{ fontSize: 12, fontWeight: 500 }}>{m.emoji} {m.label}</div>
                  <div style={{ fontSize: 12, color: 'var(--muted)' }}>{n}</div>
                </div>
              );
            })}
          </div>
        </div>
      )}

      {/* ── Search ── */}
      <div style={{ ...nutriStyles.card, display: 'flex', alignItems: 'center', gap: 10, padding: '10px 14px', borderRadius: 14 }}>
        <SearchIcon size={16}/>
        <input value={q} onChange={e => setQ(e.target.value)} placeholder="Search entries, mood, tags…"
          style={{ flex: 1, border: 0, background: 'transparent', outline: 'none', font: 'inherit', fontSize: 14, color: 'var(--text)' }}/>
        {q && (
          <button onClick={() => setQ('')} style={{ ...iconBtnGhost, width: 24, height: 24, fontSize: 14, lineHeight: 1 }}>×</button>
        )}
      </div>

      {/* ── Tag pills ── */}
      {allTags.length > 0 && (
        <div style={{ display: 'flex', gap: 6, overflowX: 'auto', margin: '0 -18px', padding: '0 18px 4px' }}>
          {['All', ...allTags].map(t => {
            const active = t === 'All' ? !tagFilter : t === tagFilter;
            return (
              <button key={t} onClick={() => setTagFilter(t === 'All' ? null : t === tagFilter ? null : t)} style={{
                display: 'inline-flex', alignItems: 'center', gap: 4,
                padding: '6px 12px', borderRadius: 999,
                background: active ? 'var(--accent)' : 'var(--surface)',
                color: active ? 'var(--on-accent)' : 'var(--text)',
                border: active ? '1px solid var(--accent)' : '1px solid var(--border-2)',
                fontSize: 12, fontWeight: 500, cursor: 'pointer', font: 'inherit', whiteSpace: 'nowrap',
              }}>
                {t !== 'All' && <span style={{ width: 6, height: 6, borderRadius: '50%', background: _getTagColor(t) }}/>}
                {t}
              </button>
            );
          })}
        </div>
      )}

      {/* ── Recent entries (full entries only; all results when searching) ── */}
      <div style={{ fontSize: 16, fontWeight: 600, letterSpacing: '-0.01em' }}>
        {isSearching ? `Results · ${filtered.length}` : 'Recent'}
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
        {recentEntries.length ? (
          recentEntries.map(e => <DiaryEntryCard key={e.id} entry={e} onClick={() => onOpen(e)}/>)
        ) : (
          <EmptyState icon="📭"
            title={isSearching ? 'No entries match' : 'No diary entries yet'}
            subtitle={isSearching ? 'Try a different search or clear the filter.' : 'Tap Write to start your first memory.'}/>
        )}
      </div>
      {!isSearching && hiddenQuickCount > 0 && (
        <div style={{ fontSize: 12, color: 'var(--muted)', textAlign: 'center', padding: '2px 0' }}>
          {hiddenQuickCount} quick mood {hiddenQuickCount === 1 ? 'entry' : 'entries'} not shown here · visible in Calendar &amp; Timeline
        </div>
      )}

      <MemoriesArchiveSection entries={entries.filter(e => e.entryMode !== 'quick')} onOpen={onOpen}/>
      <div style={{ height: 60 }}/>
    </div>
  );
}

/* ═══════════════════════════════════════════════════════════════════
   DIARY ENTRY CARD — shared card used in all views
   ═══════════════════════════════════════════════════════════════════*/
function DiaryEntryCard({ entry, onClick, featured = false, showYear = false, yearsAgo = null }) {
  const mood = ND_MOOD_META[entry.mood] || ND_MOOD_META.okay;
  const year  = entry.date ? entry.date.slice(0, 4) : '';
  const dateLabel = entry.date
    ? new Date(entry.date + 'T00:00:00').toLocaleDateString(undefined, { month: 'short', day: 'numeric' })
    : '';
  const preview = (entry.text || '').slice(0, 120);
  const isQuick = entry.entryMode === 'quick';

  const yearsAgoLabel = yearsAgo === null ? null
    : yearsAgo === 0 ? 'This year'
    : yearsAgo === 1 ? '1 year ago'
    : `${yearsAgo} years ago`;

  return (
    <button onClick={onClick} style={{
      ...nutriStyles.card, padding: 14,
      width: '100%', textAlign: 'left', cursor: 'pointer', font: 'inherit', color: 'var(--text)',
      display: 'flex', flexDirection: 'column', gap: 8,
      borderLeft: featured ? `3px solid ${mood.color}` : `1px solid var(--border)`,
      transition: 'transform .12s ease',
    }}
    onMouseDown={e => e.currentTarget.style.transform = 'scale(.99)'}
    onMouseUp={e => e.currentTarget.style.transform = ''}
    onMouseLeave={e => e.currentTarget.style.transform = ''}>
      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 8 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, minWidth: 0 }}>
          <span style={{ fontSize: 18, lineHeight: 1, flexShrink: 0 }}>{mood.emoji}</span>
          <div style={{ fontSize: 14.5, fontWeight: 600, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
            {_diaryLabel(entry)}
          </div>
          {isQuick && (
            <span style={{
              fontSize: 9, fontWeight: 700, padding: '1px 5px', borderRadius: 4, flexShrink: 0,
              background: 'var(--surface-2)', color: 'var(--muted)', border: '1px solid var(--border)',
            }}>⚡</span>
          )}
        </div>
        <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 2, flexShrink: 0 }}>
          <div style={{ fontSize: 11, color: 'var(--muted)', fontWeight: 500, whiteSpace: 'nowrap' }}>
            {showYear ? `${dateLabel}, ${year}` : dateLabel}
          </div>
          {yearsAgoLabel !== null && (
            <div style={{
              fontSize: 10, fontWeight: 600, whiteSpace: 'nowrap',
              color: yearsAgo === 0 ? 'var(--muted)' : 'var(--accent)',
            }}>{yearsAgoLabel}</div>
          )}
        </div>
      </div>
      {preview ? (
        <div style={{
          fontSize: 12.5, color: 'var(--muted)', lineHeight: 1.5,
          display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical', overflow: 'hidden',
        }}>{preview}</div>
      ) : null}
      {entry.tags?.length > 0 && (
        <div style={{ display: 'flex', gap: 4, flexWrap: 'wrap', marginTop: 2 }}>
          {entry.tags.map(t => (
            <span key={t} style={{
              fontSize: 10.5, fontWeight: 500, padding: '2px 8px', borderRadius: 999,
              background: 'var(--surface-2)', color: 'var(--text-2)', border: '1px solid var(--border)',
              display: 'inline-flex', alignItems: 'center', gap: 4,
            }}>
              <span style={{ width: 6, height: 6, borderRadius: '50%', background: _getTagColor(t) }}/>
              {t}
            </span>
          ))}
        </div>
      )}
    </button>
  );
}

/* ═══════════════════════════════════════════════════════════════════
   DIARY CALENDAR — month grid, count badges, inline day memories
   ═══════════════════════════════════════════════════════════════════*/
function DiaryCalendar({ entries, onOpen, onCompose }) {
  const today = new Date();
  // Use the global todayISO() function (local-timezone); avoid shadowing it with a variable.
  const todayKey = todayISO();
  const currentYear = today.getFullYear();
  const [yr, setYr] = React.useState(today.getFullYear());
  const [mo, setMo] = React.useState(today.getMonth()); // 0-based
  const [selected, setSelected] = React.useState(null); // "MM-DD" or null — inline selection
  const [showGoto, setShowGoto] = React.useState(false);
  const [gotoVal, setGotoVal] = React.useState('');

  // Count entries per month-day (across all years)
  const countByMD = React.useMemo(() => {
    const c = {};
    entries.forEach(e => {
      if (!e.date || e.date.length < 10) return;
      const md = e.date.slice(5, 10);
      c[md] = (c[md] || 0) + 1;
    });
    return c;
  }, [entries]);

  // Most-recent mood per month-day (for cell tint color)
  const moodByMD = React.useMemo(() => {
    const best = {};
    [...entries].sort((a, b) => b.date.localeCompare(a.date)).forEach(e => {
      if (!e.date) return;
      const md = e.date.slice(5, 10);
      if (!best[md]) best[md] = e.mood;
    });
    return best;
  }, [entries]);

  const monthName = new Date(yr, mo, 1).toLocaleString(undefined, { month: 'long', year: 'numeric' });
  const firstDow  = new Date(yr, mo, 1).getDay();
  const daysInMo  = new Date(yr, mo + 1, 0).getDate();

  const cells = [];
  for (let i = 0; i < firstDow; i++) cells.push(null);
  for (let d = 1; d <= daysInMo; d++) cells.push(d);

  function shift(delta) {
    let nm = mo + delta, ny = yr;
    if (nm < 0) { nm = 11; ny--; }
    if (nm > 11) { nm = 0; ny++; }
    setMo(nm); setYr(ny);
    setSelected(null);
  }

  function handleGoto() {
    if (!gotoVal) return;
    const [y, m] = gotoVal.split('-').map(Number);
    if (y && m) { setYr(y); setMo(m - 1); }
    setShowGoto(false);
    setGotoVal('');
    setSelected(null);
  }

  const thisMonthCount = entries.filter(e => {
    if (!e.date) return false;
    const [ey, em] = e.date.split('-').map(Number);
    return ey === yr && em - 1 === mo;
  }).length;

  // Entries for the selected day (all years, newest first)
  const selectedEntries = React.useMemo(() => {
    if (!selected) return [];
    return entries
      .filter(e => e.date && e.date.slice(5, 10) === selected)
      .sort((a, b) => b.date.localeCompare(a.date));
  }, [selected, entries]);

  const selectedDateLabel = selected
    ? new Date(`2000-${selected}T00:00:00`).toLocaleDateString(undefined, { month: 'long', day: 'numeric' })
    : '';

  return (
    <div style={{ padding: '12px 18px 24px', display: 'flex', flexDirection: 'column', gap: 16 }}>

      {/* Header */}
      <div style={{ paddingTop: 4 }}>
        <div style={{ fontSize: 22, fontWeight: 700, letterSpacing: '-0.02em' }}>Calendar</div>
        <div style={{ fontSize: 12.5, color: 'var(--muted)', marginTop: 2, fontWeight: 500 }}>
          Tap a date to see all memories for that day across years
        </div>
      </div>

      {/* Controls */}
      <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
        <button onClick={() => { setYr(today.getFullYear()); setMo(today.getMonth()); setSelected(null); }} style={{
          padding: '7px 14px', borderRadius: 999,
          background: 'var(--surface)', border: '1px solid var(--border-2)',
          font: 'inherit', fontSize: 12.5, fontWeight: 500, cursor: 'pointer', color: 'var(--text)',
        }}>Today</button>
        <button onClick={() => setShowGoto(true)} style={{
          padding: '7px 14px', borderRadius: 999,
          background: 'var(--surface)', border: '1px solid var(--border-2)',
          font: 'inherit', fontSize: 12.5, fontWeight: 500, cursor: 'pointer', color: 'var(--text)',
        }}>Go To…</button>
        <div style={{ flex: 1 }}/>
        <button onClick={onCompose} style={{
          display: 'inline-flex', alignItems: 'center', gap: 6, padding: '7px 14px', borderRadius: 999,
          background: 'var(--accent)', color: 'var(--on-accent)', border: '1px solid var(--accent)',
          font: 'inherit', fontSize: 12.5, fontWeight: 600, cursor: 'pointer',
        }}><PlusIcon size={13}/> New</button>
      </div>

      {/* Calendar card */}
      <div style={{ ...nutriStyles.card, padding: 16 }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 12 }}>
          <button onClick={() => shift(-1)} style={iconBtnGhost}>‹</button>
          <div style={{ textAlign: 'center' }}>
            <div style={{ fontSize: 15, fontWeight: 600 }}>{monthName}</div>
            <div style={{ fontSize: 11, color: 'var(--muted)', marginTop: 1 }}>{thisMonthCount} {thisMonthCount === 1 ? 'entry' : 'entries'}</div>
          </div>
          <button onClick={() => shift(1)} style={iconBtnGhost}>›</button>
        </div>

        {/* Day-of-week headers */}
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7,1fr)', gap: 4, marginBottom: 6 }}>
          {['S','M','T','W','T','F','S'].map((d, i) => (
            <div key={i} style={{ textAlign: 'center', fontSize: 10.5, color: 'var(--muted)', fontWeight: 600, letterSpacing: '0.04em' }}>{d}</div>
          ))}
        </div>

        {/* Day cells */}
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7,1fr)', gap: 4 }}>
          {cells.map((d, i) => {
            if (!d) return <div key={i}/>;
            const mo2 = String(mo + 1).padStart(2, '0');
            const dd  = String(d).padStart(2, '0');
            const md  = `${mo2}-${dd}`;
            const iso = `${yr}-${md}`;
            const count = countByMD[md] || 0;
            const isToday = iso === todayKey;
            const isSelected = selected === md;
            const moodKey = moodByMD[md];
            const moodColor = moodKey ? ND_MOOD_META[moodKey]?.color : null;
            return (
              <button key={i}
                onClick={() => count > 0 ? setSelected(isSelected ? null : md) : null}
                style={{
                  aspectRatio: '1/1', display: 'flex', flexDirection: 'column',
                  alignItems: 'center', justifyContent: 'center', gap: 2,
                  borderRadius: 10,
                  background: isSelected
                    ? (moodColor ? `${moodColor}44` : 'var(--accent)22')
                    : moodColor ? `${moodColor}22` : 'var(--surface-2)',
                  border: isSelected
                    ? `2px solid ${moodColor || 'var(--accent)'}`
                    : isToday
                      ? '1.5px solid var(--accent)'
                      : count > 0 ? '1px solid var(--border-2)' : '1px solid var(--border)',
                  color: 'var(--text)', cursor: count > 0 ? 'pointer' : 'default', font: 'inherit',
                }}>
                <div style={{ fontSize: 11.5, fontWeight: isToday || isSelected ? 700 : count > 0 ? 600 : 400 }}>{d}</div>
                {count > 0 && (
                  <div style={{
                    fontSize: 9, fontWeight: 700, lineHeight: '13px',
                    background: moodColor || 'var(--accent)',
                    color: '#fff', borderRadius: 999,
                    padding: '0 4px', minWidth: 14, textAlign: 'center',
                  }}>{count}</div>
                )}
              </button>
            );
          })}
        </div>
      </div>

      {/* ── Inline selected-day memories ── */}
      {selected && (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
          {/* Section header */}
          <div style={{
            display: 'flex', alignItems: 'center', justifyContent: 'space-between',
            padding: '2px 0 4px', borderBottom: '1.5px solid var(--border)',
          }}>
            <div>
              <span style={{ fontSize: 15, fontWeight: 700 }}>{selectedDateLabel}</span>
              <span style={{ fontSize: 12, color: 'var(--muted)', marginLeft: 8 }}>
                {selectedEntries.length} {selectedEntries.length === 1 ? 'memory' : 'memories'} across all years
              </span>
            </div>
            <button onClick={() => setSelected(null)} style={{
              ...iconBtnGhost, width: 26, height: 26, fontSize: 14,
            }}>×</button>
          </div>

          {/* Memory cards */}
          {selectedEntries.length > 0 ? (
            selectedEntries.map(e => {
              const entryYear = e.date ? parseInt(e.date.slice(0, 4), 10) : currentYear;
              const ago = currentYear - entryYear;
              return (
                <DiaryEntryCard
                  key={e.id}
                  entry={e}
                  onClick={() => onOpen(e)}
                  showYear
                  yearsAgo={ago}
                />
              );
            })
          ) : (
            <div style={{ textAlign: 'center', padding: '20px 0', color: 'var(--muted)', fontSize: 13.5 }}>
              📭 No memories yet on {selectedDateLabel}
            </div>
          )}

          {/* Write action */}
          <button onClick={onCompose} style={{
            padding: '11px 16px', borderRadius: 999, width: '100%',
            background: 'var(--surface-2)', border: '1px solid var(--border)',
            font: 'inherit', fontSize: 13, fontWeight: 600, cursor: 'pointer', color: 'var(--text)',
            display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6,
          }}>
            <PlusIcon size={13}/>
            Write a memory for {selectedDateLabel}
          </button>
        </div>
      )}

      {/* Go To modal */}
      {showGoto && (
        <div style={{
          position: 'fixed', inset: 0, zIndex: 100,
          background: 'rgba(0,0,0,0.5)', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 24,
        }} onClick={() => setShowGoto(false)}>
          <div onClick={e => e.stopPropagation()} style={{
            background: 'var(--surface)', borderRadius: 18, padding: 24, width: '100%', maxWidth: 320,
            display: 'flex', flexDirection: 'column', gap: 16,
            boxShadow: '0 20px 60px rgba(0,0,0,0.3)',
          }}>
            <div style={{ fontSize: 16, fontWeight: 700 }}>Go To Month</div>
            <input type="month" value={gotoVal} onChange={e => setGotoVal(e.target.value)} style={{
              width: '100%', padding: '10px 12px', borderRadius: 10,
              border: '1px solid var(--border-2)', background: 'var(--surface-2)',
              font: 'inherit', fontSize: 14, color: 'var(--text)',
            }}/>
            <div style={{ display: 'flex', gap: 10 }}>
              <button onClick={() => setShowGoto(false)} style={{
                flex: 1, padding: 12, borderRadius: 999,
                background: 'var(--surface-2)', border: '1px solid var(--border)',
                font: 'inherit', fontSize: 13.5, fontWeight: 600, cursor: 'pointer', color: 'var(--text)',
              }}>Cancel</button>
              <button onClick={handleGoto} style={{
                flex: 1, padding: 12, borderRadius: 999,
                background: 'var(--accent)', border: '1px solid var(--accent)',
                font: 'inherit', fontSize: 13.5, fontWeight: 600, cursor: 'pointer', color: 'var(--on-accent)',
              }}>Go</button>
            </div>
          </div>
        </div>
      )}

      <div style={{ height: 60 }}/>
    </div>
  );
}

/* ── DIARY DATE MODAL — legacy, kept as export ── */
function DiaryDateModal({ monthDay, entries, onOpen, onClose, onCompose }) {
  const dayEntries = entries
    .filter(e => e.date && e.date.slice(5, 10) === monthDay)
    .sort((a, b) => b.date.localeCompare(a.date));
  const dateLabel = new Date(`2000-${monthDay}T00:00:00`).toLocaleDateString(undefined, { month: 'long', day: 'numeric' });
  return (
    <div style={{
      position: 'fixed', inset: 0, zIndex: 100,
      background: 'rgba(0,0,0,0.55)', display: 'flex', alignItems: 'flex-end',
    }} onClick={onClose}>
      <div onClick={e => e.stopPropagation()} style={{
        width: '100%', maxHeight: '82vh', overflow: 'auto',
        background: 'var(--bg)', borderRadius: '20px 20px 0 0',
        padding: '20px 18px 40px', display: 'flex', flexDirection: 'column', gap: 14,
        boxShadow: '0 -8px 40px rgba(0,0,0,0.2)',
      }}>
        <div style={{ width: 36, height: 4, borderRadius: 2, background: 'var(--border-2)', margin: '0 auto -4px' }}/>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
          <div>
            <div style={{ fontSize: 18, fontWeight: 700 }}>{dateLabel}</div>
            <div style={{ fontSize: 12, color: 'var(--muted)', marginTop: 1 }}>
              {dayEntries.length ? `${dayEntries.length} ${dayEntries.length === 1 ? 'memory' : 'memories'}` : 'No memories yet'}
            </div>
          </div>
          <button onClick={onClose} style={iconBtn}><XIcon size={18}/></button>
        </div>
        {dayEntries.map(e => <DiaryEntryCard key={e.id} entry={e} onClick={() => onOpen(e)} showYear/>)}
        <button onClick={onCompose} style={{
          padding: 12, borderRadius: 999, width: '100%',
          background: 'var(--surface-2)', border: '1px solid var(--border)',
          font: 'inherit', fontSize: 13.5, fontWeight: 600, cursor: 'pointer', color: 'var(--text)',
        }}>✏️ Write a memory for {dateLabel}</button>
      </div>
    </div>
  );
}

/* ═══════════════════════════════════════════════════════════════════
   DIARY TIMELINE — month-grouped, search (title/text/tags/mood/date)
   ═══════════════════════════════════════════════════════════════════*/
function DiaryTimeline({ entries, onOpen, onCompose }) {
  const [q, setQ] = React.useState('');
  const [showGoto, setShowGoto] = React.useState(false);
  const [gotoVal, setGotoVal] = React.useState('');
  const monthRefs = React.useRef({});
  const [activeTabMo, setActiveTabMo] = React.useState(() => parseInt(todayISO().slice(5, 7), 10));

  const todayMonth = parseInt(todayISO().slice(5, 7), 10);

  const filtered = React.useMemo(() => {
    if (!q) return entries;
    const ql = q.toLowerCase();
    return entries.filter(e => {
      const moodLabel = (ND_MOOD_META[e.mood]?.label || e.mood || '').toLowerCase();
      return (e.date || '').includes(q) ||
        (e.date || '').slice(0, 4).includes(q) ||
        (e.title || '').toLowerCase().includes(ql) ||
        (e.text || '').toLowerCase().includes(ql) ||
        (e.tags || []).some(t => t.toLowerCase().includes(ql)) ||
        moodLabel.includes(ql);
    });
  }, [entries, q]);

  const sorted = React.useMemo(() => [...filtered].sort((a, b) => {
    const am = parseInt((a.date || '').slice(5, 7) || '0', 10);
    const bm = parseInt((b.date || '').slice(5, 7) || '0', 10);
    if (am !== bm) return am - bm;
    const ad = parseInt((a.date || '').slice(8, 10) || '0', 10);
    const bd = parseInt((b.date || '').slice(8, 10) || '0', 10);
    if (ad !== bd) return ad - bd;
    return (a.date || '').localeCompare(b.date || '');
  }), [filtered]);

  const grouped = React.useMemo(() => {
    const g = {};
    sorted.forEach(e => {
      const mo = parseInt((e.date || '').slice(5, 7) || '0', 10);
      if (!mo) return;
      if (!g[mo]) g[mo] = [];
      g[mo].push(e);
    });
    return g;
  }, [sorted]);

  const presentMonths = Object.keys(grouped).map(Number).sort((a, b) => a - b);

  const monthsWithData = React.useMemo(() => {
    const s = new Set();
    entries.forEach(e => { if (e.date) s.add(parseInt(e.date.slice(5, 7), 10)); });
    return s;
  }, [entries]);

  function scrollToMonth(mo) {
    setActiveTabMo(mo);
    const el = monthRefs.current[mo];
    if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' });
  }

  function handleGoto() {
    if (!gotoVal) return;
    const parts = gotoVal.split('-');
    const targetMo = parseInt(parts[1] || parts[0], 10);
    if (targetMo >= 1 && targetMo <= 12) scrollToMonth(targetMo);
    setShowGoto(false);
    setGotoVal('');
  }

  return (
    <div style={{ padding: '12px 18px 24px', display: 'flex', flexDirection: 'column', gap: 14 }}>

      {/* Header */}
      <div style={{ paddingTop: 4 }}>
        <div style={{ fontSize: 22, fontWeight: 700, letterSpacing: '-0.02em' }}>Timeline</div>
        <div style={{ fontSize: 12.5, color: 'var(--muted)', marginTop: 2, fontWeight: 500 }}>
          {entries.length} {entries.length === 1 ? 'entry' : 'entries'} · grouped by calendar month
        </div>
      </div>

      {/* Controls */}
      <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
        <button onClick={() => scrollToMonth(todayMonth)} style={{
          padding: '7px 14px', borderRadius: 999,
          background: 'var(--surface)', border: '1px solid var(--border-2)',
          font: 'inherit', fontSize: 12.5, fontWeight: 500, cursor: 'pointer', color: 'var(--text)',
        }}>Today</button>
        <button onClick={() => setShowGoto(true)} style={{
          padding: '7px 14px', borderRadius: 999,
          background: 'var(--surface)', border: '1px solid var(--border-2)',
          font: 'inherit', fontSize: 12.5, fontWeight: 500, cursor: 'pointer', color: 'var(--text)',
        }}>Go To…</button>
        <div style={{ flex: 1 }}/>
        <button onClick={onCompose} style={{
          display: 'inline-flex', alignItems: 'center', gap: 6, padding: '7px 14px', borderRadius: 999,
          background: 'var(--accent)', color: 'var(--on-accent)', border: '1px solid var(--accent)',
          font: 'inherit', fontSize: 12.5, fontWeight: 600, cursor: 'pointer',
        }}><PlusIcon size={13}/> New</button>
      </div>

      {/* Search bar */}
      <div style={{ ...nutriStyles.card, display: 'flex', alignItems: 'center', gap: 10, padding: '10px 14px', borderRadius: 14 }}>
        <SearchIcon size={16}/>
        <input value={q} onChange={e => setQ(e.target.value)}
          placeholder="Search title, text, tags, mood, date…"
          style={{ flex: 1, border: 0, background: 'transparent', outline: 'none', font: 'inherit', fontSize: 14, color: 'var(--text)' }}/>
        {q && (
          <button onClick={() => setQ('')} style={{ ...iconBtnGhost, width: 24, height: 24, fontSize: 14, lineHeight: 1 }}>×</button>
        )}
      </div>
      {q && (
        <div style={{ fontSize: 12.5, color: 'var(--muted)', marginTop: -6 }}>
          {filtered.length} {filtered.length === 1 ? 'result' : 'results'} for "{q}"
        </div>
      )}

      {/* Month tabs */}
      {!q && (
        <div style={{
          display: 'flex', gap: 6, overflowX: 'auto',
          margin: '0 -18px', padding: '0 18px 4px',
          scrollbarWidth: 'none',
        }}>
          {_DIARY_MONTHS_SHORT.map((mn, i) => {
            const mo = i + 1;
            const hasData = monthsWithData.has(mo);
            const active = activeTabMo === mo;
            return (
              <button key={mo} onClick={() => hasData && scrollToMonth(mo)} style={{
                padding: '6px 12px', borderRadius: 999, flexShrink: 0,
                background: active ? 'var(--accent)' : hasData ? 'var(--surface)' : 'var(--surface-2)',
                color: active ? 'var(--on-accent)' : hasData ? 'var(--text)' : 'var(--muted)',
                border: active ? '1px solid var(--accent)' : hasData ? '1px solid var(--border-2)' : '1px solid var(--border)',
                font: 'inherit', fontSize: 12, fontWeight: active ? 700 : hasData ? 500 : 400,
                cursor: hasData ? 'pointer' : 'default', whiteSpace: 'nowrap',
                opacity: hasData ? 1 : 0.45,
              }}>{mn}</button>
            );
          })}
        </div>
      )}

      {/* Entry groups */}
      {entries.length === 0 ? (
        <EmptyState icon="📓" title="No diary entries yet" subtitle="Tap Write to start your first memory."/>
      ) : filtered.length === 0 ? (
        <EmptyState icon="🔍" title="No results" subtitle={`Nothing matched "${q}". Try mood name, tag, or date.`}/>
      ) : (
        presentMonths.map(mo => {
          const monthEntries = grouped[mo];
          const moLabel = _DIARY_MONTHS[mo - 1];
          return (
            <div key={mo} ref={el => { monthRefs.current[mo] = el; }}
              style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
              <div style={{
                display: 'flex', alignItems: 'center', justifyContent: 'space-between',
                padding: '10px 0 6px', borderBottom: '1.5px solid var(--border)',
              }}>
                <span style={{ fontSize: 15, fontWeight: 700, letterSpacing: '-0.01em' }}>{moLabel}</span>
                <span style={{
                  fontSize: 11, color: 'var(--muted)', fontWeight: 400,
                  background: 'var(--surface-2)', padding: '2px 8px', borderRadius: 999,
                  border: '1px solid var(--border)',
                }}>
                  {monthEntries.length} {monthEntries.length === 1 ? 'entry' : 'entries'}
                </span>
              </div>
              {monthEntries.map(e => (
                <DiaryEntryCard key={e.id} entry={e} onClick={() => onOpen(e)} showYear/>
              ))}
            </div>
          );
        })
      )}

      {/* Go To modal */}
      {showGoto && (
        <div style={{
          position: 'fixed', inset: 0, zIndex: 100,
          background: 'rgba(0,0,0,0.5)', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 24,
        }} onClick={() => setShowGoto(false)}>
          <div onClick={e => e.stopPropagation()} style={{
            background: 'var(--surface)', borderRadius: 18, padding: 24, width: '100%', maxWidth: 320,
            display: 'flex', flexDirection: 'column', gap: 16,
            boxShadow: '0 20px 60px rgba(0,0,0,0.3)',
          }}>
            <div style={{ fontSize: 16, fontWeight: 700 }}>Go To Month</div>
            <input type="month" value={gotoVal} onChange={e => setGotoVal(e.target.value)} style={{
              width: '100%', padding: '10px 12px', borderRadius: 10,
              border: '1px solid var(--border-2)', background: 'var(--surface-2)',
              font: 'inherit', fontSize: 14, color: 'var(--text)',
            }}/>
            <div style={{ display: 'flex', gap: 10 }}>
              <button onClick={() => setShowGoto(false)} style={{
                flex: 1, padding: 12, borderRadius: 999,
                background: 'var(--surface-2)', border: '1px solid var(--border)',
                font: 'inherit', fontSize: 13.5, fontWeight: 600, cursor: 'pointer', color: 'var(--text)',
              }}>Cancel</button>
              <button onClick={handleGoto} style={{
                flex: 1, padding: 12, borderRadius: 999,
                background: 'var(--accent)', border: '1px solid var(--accent)',
                font: 'inherit', fontSize: 13.5, fontWeight: 600, cursor: 'pointer', color: 'var(--on-accent)',
              }}>Go</button>
            </div>
          </div>
        </div>
      )}

      <div style={{ height: 60 }}/>
    </div>
  );
}

/* ═══════════════════════════════════════════════════════════════════
   DIARY ENTRY SHEET — full-screen detail view with edit button
   ═══════════════════════════════════════════════════════════════════*/
function DiaryEntrySheet({ entry, onClose, onDelete, onEdit }) {
  const store = useStore();
  if (!entry) return null;
  const mood = ND_MOOD_META[entry.mood] || ND_MOOD_META.okay;
  const linkedMovie = entry.movieId ? (store.movies ? store.movies() : []).find(m => m.id === entry.movieId) : null;
  const displayTitle = _diaryTitle(entry.title);
  const dateLabel = entry.date
    ? new Date(entry.date + 'T00:00:00').toLocaleDateString(undefined, {
        weekday: 'long', month: 'long', day: 'numeric', year: 'numeric',
      })
    : '';

  return (
    <div style={{
      position: 'absolute', inset: 0, zIndex: 30,
      display: 'flex', flexDirection: 'column', background: 'var(--bg)',
      animation: 'sheetIn .25s cubic-bezier(.2,.7,.2,1)',
      paddingTop: 'var(--safe-top)',
    }}>
      {/* Mood hero banner */}
      <div style={{
        position: 'relative', height: 160,
        background: `linear-gradient(135deg, ${mood.color}44, ${mood.color}aa)`,
        display: 'grid', placeItems: 'center', fontSize: 60, lineHeight: 1, flexShrink: 0,
      }}>
        <button onClick={onClose} style={{
          position: 'absolute', top: 14, left: 14, width: 36, height: 36, borderRadius: '50%',
          border: '1px solid rgba(0,0,0,0.1)', background: 'rgba(255,255,255,0.9)',
          color: '#14140F', display: 'grid', placeItems: 'center', cursor: 'pointer',
        }}><XIcon size={18}/></button>
        {onEdit && (
          <button onClick={onEdit} style={{
            position: 'absolute', top: 14, right: 14, width: 36, height: 36, borderRadius: '50%',
            border: '1px solid rgba(0,0,0,0.1)', background: 'rgba(255,255,255,0.9)',
            color: '#14140F', display: 'grid', placeItems: 'center', cursor: 'pointer',
          }}><EditIcon size={16}/></button>
        )}
        <span style={{ filter: 'drop-shadow(0 6px 16px rgba(20,20,15,0.18))' }}>{mood.emoji}</span>
      </div>

      {/* Body */}
      <div style={{ flex: 1, overflow: 'auto', padding: '18px 18px 80px' }}>
        <div style={{ fontSize: 11, color: 'var(--muted)', fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase' }}>
          {dateLabel}
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 6 }}>
          <div style={{ fontSize: 24, fontWeight: 700, letterSpacing: '-0.02em', flex: 1 }}>
            {displayTitle || mood.label}
          </div>
          {entry.entryMode === 'quick' && (
            <span style={{
              fontSize: 10, fontWeight: 700, padding: '2px 7px', borderRadius: 6,
              background: 'var(--surface-2)', color: 'var(--muted)', border: '1px solid var(--border)',
              flexShrink: 0,
            }}>⚡ Quick</span>
          )}
        </div>

        {entry.tags?.length > 0 && (
          <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginTop: 10 }}>
            {entry.tags.map(t => (
              <span key={t} style={{
                fontSize: 11, fontWeight: 500, padding: '3px 10px', borderRadius: 999,
                background: 'var(--surface-2)', color: 'var(--text-2)', border: '1px solid var(--border)',
                display: 'inline-flex', alignItems: 'center', gap: 4,
              }}>
                <span style={{ width: 6, height: 6, borderRadius: '50%', background: _getTagColor(t) }}/>
                {t}
              </span>
            ))}
          </div>
        )}

        {linkedMovie && (
          <div style={{ marginTop: 18 }}>
            <div style={{ fontSize: 11, color: 'var(--muted)', fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase', marginBottom: 8 }}>🎬 Linked movie</div>
            <div style={{ display: 'flex', gap: 12, alignItems: 'center', ...nutriStyles.card, padding: 10 }}>
              <MoviePoster movie={linkedMovie} w={46}/>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontWeight: 700, fontSize: 14 }}>{linkedMovie.title}{linkedMovie.year ? <span style={{ color: 'var(--muted)', fontWeight: 400 }}> · {linkedMovie.year}</span> : null}</div>
                <div style={{ fontSize: 12, color: 'var(--muted)', marginTop: 2 }}>
                  {linkedMovie.watchedDate ? '✓ Watched' : (linkedMovie.watchlist ? 'Planned to watch' : 'In your library')}
                  {linkedMovie.tmdbRating != null ? ' · ★ ' + (+linkedMovie.tmdbRating).toFixed(1) : ''}
                </div>
              </div>
            </div>
          </div>
        )}

        {entry.text ? (
          <div style={{ fontSize: 15, lineHeight: 1.7, color: 'var(--text-2)', marginTop: 20, whiteSpace: 'pre-wrap' }}>
            {entry.text}
          </div>
        ) : (
          <div style={{ fontSize: 13.5, color: 'var(--muted)', marginTop: 20, fontStyle: 'italic' }}>
            No details — quick mood entry
          </div>
        )}

        {entry.createdAt && (
          <div style={{ fontSize: 11, color: 'var(--muted)', marginTop: 20 }}>
            Written {new Date(entry.createdAt).toLocaleString()}
          </div>
        )}

        <div style={{ display: 'flex', gap: 10, marginTop: 24 }}>
          <button onClick={onDelete} style={{
            flex: 1, padding: 12, borderRadius: 999,
            background: 'transparent', color: '#A33',
            border: '1px solid rgba(170,51,51,.35)',
            fontSize: 13.5, fontWeight: 600, cursor: 'pointer', font: 'inherit',
          }}>Delete</button>
          {onEdit && (
            <button onClick={onEdit} style={{
              flex: 1, padding: 12, borderRadius: 999,
              background: 'var(--surface-2)', color: 'var(--text)',
              border: '1px solid var(--border)',
              fontSize: 13.5, fontWeight: 600, cursor: 'pointer', font: 'inherit',
            }}>Edit</button>
          )}
          <button onClick={onClose} style={{
            flex: 1, padding: 12, borderRadius: 999,
            background: 'var(--text)', color: 'var(--bg)',
            border: '1px solid var(--text)',
            fontSize: 13.5, fontWeight: 600, cursor: 'pointer', font: 'inherit',
          }}>Done</button>
        </div>
      </div>
    </div>
  );
}

/* ═══════════════════════════════════════════════════════════════════
   DIARY EDIT SHEET — edit an existing entry (supports full + quick)
   ═══════════════════════════════════════════════════════════════════*/
function DiaryEditSheet({ entry, onClose, onSave, customTags = [], onAddCustomTag }) {
  const initMode = entry.entryMode || ((entry.text && entry.text.trim()) ? 'full' : 'quick');
  const [mode, setMode]   = React.useState(initMode);
  const [title, setTitle] = React.useState(entry.title || '');
  const [text, setText]   = React.useState(entry.text  || '');
  const [mood, setMood]   = React.useState(entry.mood  || 'okay');
  const [tags, setTags]   = React.useState(entry.tags  || []);
  const [date, setDate]   = React.useState(entry.date  || todayISO());
  const [movieId, setMovieId] = React.useState(entry.movieId || null);
  const [newTag, setNewTag] = React.useState('');

  const builtInTags = Object.keys(ND_TAG_COLORS);
  const entryExtraTags = (entry.tags || []).filter(t => !ND_TAG_COLORS[t]);
  const allTags = [...new Set([...builtInTags, ...customTags.filter(t => !ND_TAG_COLORS[t]), ...entryExtraTags])];
  const canSave = mode === 'quick' ? true : !!text.trim();

  function handleAddTag() {
    const t = newTag.trim();
    if (!t) return;
    if (!allTags.includes(t) && onAddCustomTag) onAddCustomTag(t);
    if (!tags.includes(t)) setTags(prev => [...prev, t]);
    setNewTag('');
  }

  return (
    <div style={{
      position: 'absolute', inset: 0, zIndex: 40,
      display: 'flex', flexDirection: 'column', height: '100%', background: 'var(--bg)',
      paddingTop: 'var(--safe-top)',
      animation: 'sheetIn .25s cubic-bezier(.2,.7,.2,1)',
    }}>
      {/* Header */}
      <div style={{
        padding: '12px 16px 10px', display: 'flex', alignItems: 'center',
        justifyContent: 'space-between', borderBottom: '1px solid var(--border)', flexShrink: 0,
      }}>
        <button onClick={onClose} style={iconBtn}><XIcon size={18}/></button>
        <div style={{ fontSize: 15, fontWeight: 600 }}>Edit entry</div>
        <button onClick={() => canSave && onSave({ title, text, mood, tags, date, entryMode: mode, movieId })} disabled={!canSave} style={{
          background: canSave ? 'var(--accent)' : 'var(--surface-2)',
          color: canSave ? 'var(--on-accent)' : 'var(--muted)',
          border: '1px solid ' + (canSave ? 'var(--accent)' : 'var(--border-2)'),
          borderRadius: 999, padding: '6px 14px',
          fontSize: 13, fontWeight: 600, cursor: canSave ? 'pointer' : 'default', font: 'inherit',
        }}>Save</button>
      </div>

      <div style={{ flex: 1, overflow: 'auto', padding: '8px 18px 60px' }}>
        {/* Mode toggle */}
        <div style={{ display: 'flex', gap: 6, marginBottom: 14, marginTop: 8 }}>
          {[
            { id: 'full',  label: '📖 Full Entry',  desc: 'Write your thoughts' },
            { id: 'quick', label: '⚡ Quick Mood',  desc: 'Mood & tags only' },
          ].map(m => (
            <button key={m.id} onClick={() => setMode(m.id)} style={{
              flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 2,
              padding: '10px 8px', borderRadius: 14,
              background: mode === m.id ? 'var(--accent)' : 'var(--surface-2)',
              color: mode === m.id ? 'var(--on-accent)' : 'var(--text)',
              border: mode === m.id ? '1.5px solid var(--accent)' : '1px solid var(--border)',
              font: 'inherit', cursor: 'pointer',
            }}>
              <span style={{ fontSize: 13, fontWeight: 700 }}>{m.label}</span>
              <span style={{ fontSize: 10.5, opacity: 0.75 }}>{m.desc}</span>
            </button>
          ))}
        </div>

        {/* Date */}
        <label style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
          <span style={{ fontSize: 11, color: 'var(--muted)', fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase' }}>Date</span>
          <input type="date" value={date} onChange={e => setDate(e.target.value)} style={{
            width: '100%', border: '1px solid var(--border)', background: 'var(--surface-2)',
            borderRadius: 10, padding: '8px 12px', outline: 'none', font: 'inherit', fontSize: 14, color: 'var(--text)',
          }}/>
        </label>

        {/* Title */}
        <input value={title} onChange={e => setTitle(e.target.value)}
          placeholder={mode === 'quick' ? 'Title (optional)…' : 'Title…'}
          style={{
            width: '100%', border: 0, background: 'transparent', outline: 'none', font: 'inherit',
            fontSize: 22, fontWeight: 700, letterSpacing: '-0.02em', color: 'var(--text)',
            marginTop: 8, padding: '8px 0',
          }}/>

        {/* Mood picker */}
        <div style={{ display: 'flex', gap: 8, marginTop: 4 }}>
          {Object.entries(ND_MOOD_META).map(([k, m]) => (
            <button key={k} onClick={() => setMood(k)} style={{
              flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4,
              padding: '10px 0', borderRadius: 14,
              background: mood === k ? `${m.color}22` : 'var(--surface-2)',
              border: mood === k ? `1.5px solid ${m.color}` : '1px solid var(--border)',
              color: 'var(--text)', cursor: 'pointer', font: 'inherit',
            }}>
              <span style={{ fontSize: 20 }}>{m.emoji}</span>
              <span style={{ fontSize: 10.5, fontWeight: 500 }}>{m.label}</span>
            </button>
          ))}
        </div>

        {/* Textarea — full mode only */}
        {mode === 'full' && (
          <textarea value={text} onChange={e => setText(e.target.value)} placeholder="What's on your mind?"
            rows={8} style={{
              width: '100%', border: 0, background: 'transparent', outline: 'none', font: 'inherit',
              fontSize: 15, lineHeight: 1.65, color: 'var(--text-2)',
              marginTop: 18, padding: 0, resize: 'vertical', minHeight: 160,
            }}/>
        )}

        {/* Linked movie (optional) */}
        <div style={{ marginTop: 16 }}>
          <MovieLinkField value={movieId} onChange={setMovieId}/>
        </div>

        {/* Tags */}
        <div style={{ marginTop: 14 }}>
          <div style={{ fontSize: 11, color: 'var(--muted)', fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase', marginBottom: 8 }}>Tags</div>
          <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
            {allTags.map(t => {
              const on = tags.includes(t);
              return (
                <button key={t} onClick={() => setTags(on ? tags.filter(x => x !== t) : [...tags, t])} style={{
                  display: 'inline-flex', alignItems: 'center', gap: 4,
                  padding: '6px 12px', borderRadius: 999,
                  background: on ? 'var(--text)' : 'var(--surface-2)',
                  color: on ? 'var(--bg)' : 'var(--text)',
                  border: on ? '1px solid var(--text)' : '1px solid var(--border)',
                  fontSize: 12, fontWeight: 500, cursor: 'pointer', font: 'inherit',
                }}>
                  <span style={{ width: 6, height: 6, borderRadius: '50%', background: _getTagColor(t) }}/>
                  {t}
                </button>
              );
            })}
          </div>
          <div style={{ display: 'flex', gap: 8, marginTop: 10 }}>
            <input
              value={newTag}
              onChange={e => setNewTag(e.target.value)}
              onKeyDown={e => { if (e.key === 'Enter') { e.preventDefault(); handleAddTag(); } }}
              placeholder="Add custom tag… (English or Arabic)"
              style={{
                flex: 1, border: '1px solid var(--border-2)', background: 'var(--surface-2)',
                borderRadius: 10, padding: '8px 12px', outline: 'none', font: 'inherit',
                fontSize: 13, color: 'var(--text)',
              }}/>
            <button onClick={handleAddTag} style={{
              padding: '8px 14px', borderRadius: 10,
              background: newTag.trim() ? 'var(--accent)' : 'var(--surface-2)',
              color: newTag.trim() ? 'var(--on-accent)' : 'var(--muted)',
              border: '1px solid ' + (newTag.trim() ? 'var(--accent)' : 'var(--border)'),
              fontSize: 13, fontWeight: 600, cursor: newTag.trim() ? 'pointer' : 'default', font: 'inherit',
            }}>+ Add</button>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ═══════════════════════════════════════════════════════════════════
   DIARY COMPOSE — write a new entry (full or quick mood)
   ═══════════════════════════════════════════════════════════════════*/
function DiaryCompose({ onClose, onSave, customTags = [], onAddCustomTag }) {
  const [mode, setMode]   = React.useState('full');
  const [title, setTitle] = React.useState('');
  const [text, setText]   = React.useState('');
  const [mood, setMood]   = React.useState('good');
  const [tags, setTags]   = React.useState([]);
  const [date, setDate]   = React.useState(todayISO());
  const [movieId, setMovieId] = React.useState(null);
  const [newTag, setNewTag] = React.useState('');

  const builtInTags = Object.keys(ND_TAG_COLORS);
  const allTags = [...builtInTags, ...customTags.filter(t => !ND_TAG_COLORS[t])];
  const canSave = mode === 'quick' ? true : !!text.trim();

  function handleAddTag() {
    const t = newTag.trim();
    if (!t) return;
    if (!allTags.includes(t) && onAddCustomTag) onAddCustomTag(t);
    if (!tags.includes(t)) setTags(prev => [...prev, t]);
    setNewTag('');
  }

  return (
    <div style={{
      position: 'absolute', inset: 0,
      display: 'flex', flexDirection: 'column', height: '100%', background: 'var(--bg)',
      paddingTop: 'var(--safe-top)',
      animation: 'sheetIn .25s cubic-bezier(.2,.7,.2,1)',
    }}>
      {/* Header */}
      <div style={{
        padding: '12px 16px 10px', display: 'flex', alignItems: 'center',
        justifyContent: 'space-between', borderBottom: '1px solid var(--border)', flexShrink: 0,
      }}>
        <button onClick={onClose} style={iconBtn}><XIcon size={18}/></button>
        <div style={{ fontSize: 15, fontWeight: 600 }}>New entry</div>
        <button onClick={() => canSave && onSave({ title, text, mood, tags, date, entryMode: mode, movieId })} disabled={!canSave} style={{
          background: canSave ? 'var(--accent)' : 'var(--surface-2)',
          color: canSave ? 'var(--on-accent)' : 'var(--muted)',
          border: '1px solid ' + (canSave ? 'var(--accent)' : 'var(--border-2)'),
          borderRadius: 999, padding: '6px 14px',
          fontSize: 13, fontWeight: 600, cursor: canSave ? 'pointer' : 'default', font: 'inherit',
        }}>Save</button>
      </div>

      <div style={{ flex: 1, overflow: 'auto', padding: '8px 18px 60px' }}>

        {/* ── Entry mode toggle ── */}
        <div style={{ display: 'flex', gap: 6, marginBottom: 14, marginTop: 8 }}>
          {[
            { id: 'full',  label: '📖 Full Entry',  desc: 'Write your thoughts' },
            { id: 'quick', label: '⚡ Quick Mood',  desc: 'Mood & tags only' },
          ].map(m => (
            <button key={m.id} onClick={() => setMode(m.id)} style={{
              flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 2,
              padding: '10px 8px', borderRadius: 14,
              background: mode === m.id ? 'var(--accent)' : 'var(--surface-2)',
              color: mode === m.id ? 'var(--on-accent)' : 'var(--text)',
              border: mode === m.id ? '1.5px solid var(--accent)' : '1px solid var(--border)',
              font: 'inherit', cursor: 'pointer',
            }}>
              <span style={{ fontSize: 13, fontWeight: 700 }}>{m.label}</span>
              <span style={{ fontSize: 10.5, opacity: 0.75 }}>{m.desc}</span>
            </button>
          ))}
        </div>

        {/* Date */}
        <label style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
          <span style={{ fontSize: 11, color: 'var(--muted)', fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase' }}>Date</span>
          <input type="date" value={date} onChange={e => setDate(e.target.value)} style={{
            width: '100%', border: '1px solid var(--border)', background: 'var(--surface-2)',
            borderRadius: 10, padding: '8px 12px', outline: 'none', font: 'inherit', fontSize: 14, color: 'var(--text)',
          }}/>
        </label>

        {/* Title */}
        <input value={title} onChange={e => setTitle(e.target.value)}
          placeholder={mode === 'quick' ? 'Title (optional)…' : 'Title…'}
          style={{
            width: '100%', border: 0, background: 'transparent', outline: 'none', font: 'inherit',
            fontSize: 22, fontWeight: 700, letterSpacing: '-0.02em', color: 'var(--text)',
            marginTop: 8, padding: '8px 0',
          }}/>

        {/* Mood picker */}
        <div style={{ display: 'flex', gap: 8, marginTop: 4 }}>
          {Object.entries(ND_MOOD_META).map(([k, m]) => (
            <button key={k} onClick={() => setMood(k)} style={{
              flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4,
              padding: '10px 0', borderRadius: 14,
              background: mood === k ? `${m.color}22` : 'var(--surface-2)',
              border: mood === k ? `1.5px solid ${m.color}` : '1px solid var(--border)',
              color: 'var(--text)', cursor: 'pointer', font: 'inherit',
            }}>
              <span style={{ fontSize: 20 }}>{m.emoji}</span>
              <span style={{ fontSize: 10.5, fontWeight: 500 }}>{m.label}</span>
            </button>
          ))}
        </div>

        {/* Textarea — full mode only */}
        {mode === 'full' && (
          <textarea value={text} onChange={e => setText(e.target.value)}
            placeholder="What's on your mind today?"
            rows={8} style={{
              width: '100%', border: 0, background: 'transparent', outline: 'none', font: 'inherit',
              fontSize: 15, lineHeight: 1.65, color: 'var(--text-2)',
              marginTop: 18, padding: 0, resize: 'vertical', minHeight: 160,
            }}/>
        )}

        {/* Linked movie (optional) */}
        <div style={{ marginTop: mode === 'full' ? 16 : 18 }}>
          <MovieLinkField value={movieId} onChange={setMovieId}/>
        </div>

        {/* Tags */}
        <div style={{ marginTop: 14 }}>
          <div style={{ fontSize: 11, color: 'var(--muted)', fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase', marginBottom: 8 }}>Tags</div>
          <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
            {allTags.map(t => {
              const on = tags.includes(t);
              return (
                <button key={t} onClick={() => setTags(on ? tags.filter(x => x !== t) : [...tags, t])} style={{
                  display: 'inline-flex', alignItems: 'center', gap: 4,
                  padding: '6px 12px', borderRadius: 999,
                  background: on ? 'var(--text)' : 'var(--surface-2)',
                  color: on ? 'var(--bg)' : 'var(--text)',
                  border: on ? '1px solid var(--text)' : '1px solid var(--border)',
                  fontSize: 12, fontWeight: 500, cursor: 'pointer', font: 'inherit',
                }}>
                  <span style={{ width: 6, height: 6, borderRadius: '50%', background: _getTagColor(t) }}/>
                  {t}
                </button>
              );
            })}
          </div>
          {/* Add custom tag */}
          <div style={{ display: 'flex', gap: 8, marginTop: 10 }}>
            <input
              value={newTag}
              onChange={e => setNewTag(e.target.value)}
              onKeyDown={e => { if (e.key === 'Enter') { e.preventDefault(); handleAddTag(); } }}
              placeholder="Add custom tag… (English or Arabic)"
              style={{
                flex: 1, border: '1px solid var(--border-2)', background: 'var(--surface-2)',
                borderRadius: 10, padding: '8px 12px', outline: 'none', font: 'inherit',
                fontSize: 13, color: 'var(--text)',
              }}/>
            <button onClick={handleAddTag} style={{
              padding: '8px 14px', borderRadius: 10,
              background: newTag.trim() ? 'var(--accent)' : 'var(--surface-2)',
              color: newTag.trim() ? 'var(--on-accent)' : 'var(--muted)',
              border: '1px solid ' + (newTag.trim() ? 'var(--accent)' : 'var(--border)'),
              fontSize: 13, fontWeight: 600, cursor: newTag.trim() ? 'pointer' : 'default', font: 'inherit',
            }}>+ Add</button>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ═══════════════════════════════════════════════════════════════════
   DIARY STATISTICS — mood & tag analytics with date range filter
   ═══════════════════════════════════════════════════════════════════*/
function DiaryStats({ entries }) {
  const [rangeId,     setRangeId]     = React.useState('last30');
  const [customStart, setCustomStart] = React.useState('');
  const [customEnd,   setCustomEnd]   = React.useState('');

  const range = React.useMemo(
    () => _diaryRangeCompute(rangeId, customStart, customEnd, entries),
    [rangeId, customStart, customEnd, entries]
  );

  const inRange = React.useMemo(
    () => entries.filter(e => e.date && e.date >= range.start && e.date <= range.end),
    [entries, range]
  );

  // ── Mood stats ──
  const moodCounts = React.useMemo(() => {
    const c = {};
    Object.keys(ND_MOOD_META).forEach(k => { c[k] = 0; });
    inRange.forEach(e => { if (e.mood && c[e.mood] !== undefined) c[e.mood]++; });
    return c;
  }, [inRange]);

  const totalMood = Object.values(moodCounts).reduce((s, n) => s + n, 0);
  const mostCommonMoodKey = Object.entries(moodCounts).sort((a, b) => b[1] - a[1]).find(([, n]) => n > 0)?.[0] || null;

  // ── Tag stats ──
  const tagCounts = React.useMemo(() => {
    const c = {};
    inRange.forEach(e => (e.tags || []).forEach(t => { c[t] = (c[t] || 0) + 1; }));
    return c;
  }, [inRange]);

  const sortedTags = Object.entries(tagCounts).sort((a, b) => b[1] - a[1]);
  const totalTagUses = Object.values(tagCounts).reduce((s, n) => s + n, 0);
  const totalTaggedEntries = inRange.filter(e => (e.tags || []).length > 0).length;

  // ── Month breakdown ──
  const monthData = React.useMemo(() => {
    const byMonth = {};
    inRange.forEach(e => {
      if (!e.date) return;
      const mk = e.date.slice(0, 7);
      if (!byMonth[mk]) byMonth[mk] = { mood: {}, tags: {}, total: 0 };
      byMonth[mk].total++;
      if (e.mood) byMonth[mk].mood[e.mood] = (byMonth[mk].mood[e.mood] || 0) + 1;
      (e.tags || []).forEach(t => { byMonth[mk].tags[t] = (byMonth[mk].tags[t] || 0) + 1; });
    });
    return Object.entries(byMonth)
      .sort((a, b) => a[0].localeCompare(b[0]))
      .map(([mk, data]) => ({
        key: mk,
        label: (() => { try { return new Date(mk + '-01T00:00:00').toLocaleDateString(undefined, { month: 'short', year: '2-digit' }); } catch { return mk; } })(),
        ...data,
      }));
  }, [inRange]);

  const donutSlices = Object.entries(ND_MOOD_META)
    .map(([k, m]) => ({ label: m.label, emoji: m.emoji, color: m.color, value: moodCounts[k] || 0 }))
    .filter(s => s.value > 0);

  return (
    <div style={{ padding: '12px 18px 24px', display: 'flex', flexDirection: 'column', gap: 16 }}>

      {/* Header */}
      <div style={{ paddingTop: 4 }}>
        <div style={{ fontSize: 22, fontWeight: 700, letterSpacing: '-0.02em' }}>Statistics</div>
        <div style={{ fontSize: 12.5, color: 'var(--muted)', marginTop: 2, fontWeight: 500 }}>
          Mood &amp; tag insights · all entry types
        </div>
      </div>

      {/* Range Selector */}
      <_DiaryRangeSelector
        rangeId={rangeId} setRangeId={setRangeId}
        customStart={customStart} setCustomStart={setCustomStart}
        customEnd={customEnd} setCustomEnd={setCustomEnd}
      />

      {/* Range summary chips */}
      <div style={{ display: 'flex', gap: 8 }}>
        <div style={{ ...nutriStyles.card, padding: '10px 14px', display: 'flex', alignItems: 'center', gap: 8, flex: 1 }}>
          <span style={{ fontSize: 18 }}>📋</span>
          <div>
            <div style={{ fontSize: 18, fontWeight: 700, lineHeight: 1 }}>{inRange.length}</div>
            <div style={{ fontSize: 10.5, color: 'var(--muted)', fontWeight: 500, marginTop: 2 }}>{range.label}</div>
          </div>
        </div>
        {mostCommonMoodKey && (
          <div style={{ ...nutriStyles.card, padding: '10px 14px', display: 'flex', alignItems: 'center', gap: 8, flex: 1 }}>
            <span style={{ fontSize: 18 }}>{ND_MOOD_META[mostCommonMoodKey]?.emoji}</span>
            <div>
              <div style={{ fontSize: 14, fontWeight: 700, lineHeight: 1 }}>{ND_MOOD_META[mostCommonMoodKey]?.label}</div>
              <div style={{ fontSize: 10.5, color: 'var(--muted)', fontWeight: 500, marginTop: 2 }}>Most common</div>
            </div>
          </div>
        )}
        {totalTagUses > 0 && (
          <div style={{ ...nutriStyles.card, padding: '10px 14px', display: 'flex', alignItems: 'center', gap: 8, flex: 1 }}>
            <span style={{ fontSize: 18 }}>🏷️</span>
            <div>
              <div style={{ fontSize: 18, fontWeight: 700, lineHeight: 1 }}>{totalTagUses}</div>
              <div style={{ fontSize: 10.5, color: 'var(--muted)', fontWeight: 500, marginTop: 2 }}>Tag uses</div>
            </div>
          </div>
        )}
      </div>

      {inRange.length === 0 ? (
        <EmptyState icon="📊" title="No entries in this range" subtitle="Try a different date range."/>
      ) : (
        <React.Fragment>

          {/* ── Mood Distribution ── */}
          {totalMood > 0 && (
            <div style={{ ...nutriStyles.card, padding: 16 }}>
              <div style={{ fontSize: 15, fontWeight: 700, marginBottom: 14, letterSpacing: '-0.01em' }}>
                Mood Distribution
                <span style={{ fontSize: 11, color: 'var(--muted)', fontWeight: 400, marginLeft: 8 }}>{totalMood} records</span>
              </div>

              <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
                {/* Donut */}
                <_DiaryDonutChart slices={donutSlices} size={130}/>

                {/* Legend with bars */}
                <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 10 }}>
                  {Object.entries(ND_MOOD_META).map(([k, m]) => {
                    const n = moodCounts[k] || 0;
                    const pct = totalMood > 0 ? Math.round((n / totalMood) * 100) : 0;
                    return (
                      <div key={k}>
                        <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 3 }}>
                          <span style={{ fontSize: 12, fontWeight: 600 }}>{m.emoji} {m.label}</span>
                          <span style={{ fontSize: 12, color: 'var(--muted)' }}>{n} · {pct}%</span>
                        </div>
                        <div style={{ height: 6, borderRadius: 999, background: 'var(--ring-track)', overflow: 'hidden' }}>
                          <div style={{ width: `${pct}%`, height: '100%', background: m.color, borderRadius: 999 }}/>
                        </div>
                      </div>
                    );
                  })}
                </div>
              </div>
            </div>
          )}

          {/* ── Tag Usage ── */}
          {sortedTags.length > 0 && (
            <div style={{ ...nutriStyles.card, padding: 16 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 14 }}>
                <div style={{ fontSize: 15, fontWeight: 700, letterSpacing: '-0.01em' }}>Tag Usage</div>
                <div style={{ fontSize: 11, color: 'var(--muted)' }}>{totalTagUses} uses · {totalTaggedEntries} entries</div>
              </div>

              {sortedTags.slice(0, 15).map(([tag, count]) => {
                const pct = totalTagUses > 0 ? Math.round((count / totalTagUses) * 100) : 0;
                const color = _getTagColor(tag);
                return (
                  <div key={tag} style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10 }}>
                    <span style={{
                      fontSize: 11.5, fontWeight: 600,
                      overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
                      width: 76, flexShrink: 0, textAlign: 'right', color: 'var(--text)',
                    }}>{tag}</span>
                    <div style={{
                      flex: 1, height: 12, background: 'var(--ring-track)', borderRadius: 999, overflow: 'hidden', minWidth: 0,
                    }}>
                      <div style={{
                        width: `${Math.max(pct, count > 0 ? 3 : 0)}%`,
                        height: '100%', background: color, borderRadius: 999,
                      }}/>
                    </div>
                    <span style={{ fontSize: 11.5, fontWeight: 600, color: 'var(--text)', width: 22, textAlign: 'right', flexShrink: 0 }}>{count}</span>
                    <span style={{ fontSize: 11, color: 'var(--muted)', width: 34, textAlign: 'right', flexShrink: 0 }}>{pct}%</span>
                  </div>
                );
              })}
            </div>
          )}

          {/* ── Mood by Month ── */}
          {monthData.length > 0 && (
            <div style={{ ...nutriStyles.card, padding: 16 }}>
              <div style={{ fontSize: 15, fontWeight: 700, marginBottom: 14, letterSpacing: '-0.01em' }}>Mood by Month</div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
                {monthData.map(({ key, label, mood, total }) => {
                  const dominantMood = Object.entries(mood).sort((a, b) => b[1] - a[1])[0]?.[0];
                  const dominantMeta = dominantMood ? ND_MOOD_META[dominantMood] : null;
                  return (
                    <div key={key}>
                      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 5 }}>
                        <div style={{ display: 'flex', alignItems: 'center', gap: 5 }}>
                          {dominantMeta && <span style={{ fontSize: 14 }}>{dominantMeta.emoji}</span>}
                          <span style={{ fontSize: 13, fontWeight: 600 }}>{label}</span>
                        </div>
                        <span style={{ fontSize: 11, color: 'var(--muted)' }}>{total} {total === 1 ? 'entry' : 'entries'}</span>
                      </div>
                      {/* Segmented bar */}
                      <div style={{ display: 'flex', height: 10, borderRadius: 999, overflow: 'hidden', background: 'var(--ring-track)' }}>
                        {Object.entries(ND_MOOD_META).map(([k, m]) => {
                          const n = mood[k] || 0;
                          if (!n) return null;
                          return <div key={k} style={{ width: `${(n / total) * 100}%`, background: m.color }}/>;
                        })}
                      </div>
                      <div style={{ display: 'flex', gap: 10, marginTop: 4, flexWrap: 'wrap' }}>
                        {Object.entries(ND_MOOD_META).map(([k, m]) => {
                          const n = mood[k] || 0;
                          if (!n) return null;
                          const pct = Math.round((n / total) * 100);
                          return (
                            <span key={k} style={{ fontSize: 10.5, color: 'var(--muted)' }}>
                              {m.emoji} {n} <span style={{ opacity: 0.65 }}>({pct}%)</span>
                            </span>
                          );
                        })}
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>
          )}

          {/* ── Tags by Month (bar chart for top 5 tags) ── */}
          {monthData.length > 1 && sortedTags.length > 0 && (
            <div style={{ ...nutriStyles.card, padding: 16 }}>
              <div style={{ fontSize: 15, fontWeight: 700, marginBottom: 14, letterSpacing: '-0.01em' }}>Tags by Month</div>
              {sortedTags.slice(0, 5).map(([tag]) => {
                const monthCounts = monthData.map(m => ({ label: m.label, count: m.tags[tag] || 0 }));
                const maxCount = Math.max(...monthCounts.map(m => m.count), 1);
                const hasAny = monthCounts.some(m => m.count > 0);
                if (!hasAny) return null;
                const color = _getTagColor(tag);
                return (
                  <div key={tag} style={{ marginBottom: 16 }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 6 }}>
                      <span style={{ width: 8, height: 8, borderRadius: '50%', background: color, display: 'inline-block', flexShrink: 0 }}/>
                      <span style={{ fontSize: 12, fontWeight: 700 }}>{tag}</span>
                      <span style={{ fontSize: 11, color: 'var(--muted)' }}>· {tagCounts[tag]} uses</span>
                    </div>
                    <div style={{ display: 'flex', gap: 3, alignItems: 'flex-end', height: 52 }}>
                      {monthCounts.map(({ label, count }) => (
                        <div key={label} style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 2, minWidth: 0 }}>
                          {count > 0 && (
                            <span style={{ fontSize: 9, color: 'var(--text)', fontWeight: 700, lineHeight: 1 }}>{count}</span>
                          )}
                          <div style={{
                            width: '100%',
                            height: `${maxCount > 0 ? Math.max((count / maxCount) * 34, count > 0 ? 4 : 1) : 1}px`,
                            background: count > 0 ? color : 'var(--ring-track)',
                            borderRadius: '3px 3px 0 0',
                            opacity: count > 0 ? 1 : 0.3,
                          }}/>
                          <span style={{ fontSize: 8.5, color: 'var(--muted)', textAlign: 'center', lineHeight: 1.1, overflow: 'hidden', width: '100%', textOverflow: 'clip' }}>
                            {label.split(' ')[0]}
                          </span>
                        </div>
                      ))}
                    </div>
                  </div>
                );
              })}
            </div>
          )}

        </React.Fragment>
      )}

      <div style={{ height: 60 }}/>
    </div>
  );
}

/* ═══════════════════════════════════════════════════════════════════
   MEMORIES ARCHIVE — collapsible section at DiaryHome bottom
   ═══════════════════════════════════════════════════════════════════*/
function MemoriesArchiveSection({ entries, onOpen }) {
  const [open, setOpen] = React.useState(false);
  if (!open) {
    return (
      <button onClick={() => setOpen(true)} style={{
        ...nutriStyles.card, padding: 14,
        display: 'flex', alignItems: 'center', gap: 12,
        width: '100%', textAlign: 'left', cursor: 'pointer', font: 'inherit',
        color: 'var(--text)', marginTop: 4,
      }}>
        <div style={{ fontSize: 26, lineHeight: 1 }}>📖</div>
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 14.5, fontWeight: 600 }}>Memories Archive</div>
          <div style={{ fontSize: 12, color: 'var(--muted)', marginTop: 2 }}>
            {entries.length} {entries.length === 1 ? 'entry' : 'entries'} · grouped by month &amp; day across years
          </div>
        </div>
        <div style={{ fontSize: 12, color: 'var(--muted)' }}>Expand ›</div>
      </button>
    );
  }
  return <DiaryMemoriesTable entries={entries} onOpen={onOpen} onCollapse={() => setOpen(false)}/>;
}

/* ═══════════════════════════════════════════════════════════════════
   MEMORIES TABLE — groups by month → day → year
   ═══════════════════════════════════════════════════════════════════*/
function DiaryMemoriesTable({ entries, onOpen, onCollapse }) {
  const tree = {};
  entries.forEach(e => {
    if (!e.date || e.date.length < 10) return;
    const [, moStr, dStr] = e.date.split('-');
    const mo = parseInt(moStr, 10), d = parseInt(dStr, 10);
    if (!mo || !d) return;
    if (!tree[mo]) tree[mo] = {};
    if (!tree[mo][d]) tree[mo][d] = [];
    tree[mo][d].push(e);
  });

  Object.values(tree).forEach(days =>
    Object.values(days).forEach(arr => arr.sort((a, b) => a.date.localeCompare(b.date)))
  );

  const months = Object.keys(tree).map(Number).sort((a, b) => a - b);

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', paddingTop: 4 }}>
        <div>
          <div style={{ fontSize: 18, fontWeight: 700, letterSpacing: '-0.01em' }}>📖 Memories Archive</div>
          <div style={{ fontSize: 12, color: 'var(--muted)', marginTop: 2 }}>
            {entries.length} {entries.length === 1 ? 'entry' : 'entries'} · {months.length} month{months.length !== 1 ? 's' : ''} · grouped by day &amp; year
          </div>
        </div>
        {onCollapse && (
          <button onClick={onCollapse} style={{
            padding: '6px 12px', borderRadius: 999,
            background: 'var(--surface-2)', border: '1px solid var(--border)',
            font: 'inherit', fontSize: 12, color: 'var(--muted)', cursor: 'pointer',
          }}>Collapse ‹</button>
        )}
      </div>

      {!entries.length ? (
        <EmptyState icon="📭" title="No memories yet" subtitle="Write your first diary entry."/>
      ) : months.map(mo => {
        const days = Object.keys(tree[mo]).map(Number).sort((a, b) => a - b);
        const totalInMonth = Object.values(tree[mo]).reduce((s, arr) => s + arr.length, 0);
        return (
          <div key={mo} style={{ ...nutriStyles.card, padding: 16 }}>
            <div style={{
              fontSize: 15, fontWeight: 700, marginBottom: 16,
              display: 'flex', alignItems: 'center', justifyContent: 'space-between',
              paddingBottom: 10, borderBottom: '1px solid var(--border)',
            }}>
              <span>{_DIARY_MONTHS[mo - 1]}</span>
              <span style={{
                fontSize: 11, color: 'var(--muted)', fontWeight: 400,
                background: 'var(--surface-2)', padding: '2px 8px', borderRadius: 999,
              }}>
                {totalInMonth} {totalInMonth === 1 ? 'entry' : 'entries'}
              </span>
            </div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
              {days.map(d => {
                const dayEntries = tree[mo][d];
                return (
                  <div key={d}>
                    <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: 8 }}>
                      Day {d}
                    </div>
                    <div style={{ display: 'flex', flexDirection: 'column', gap: 7, paddingLeft: 10, borderLeft: '2px solid var(--border)' }}>
                      {dayEntries.map(e => {
                        const year = e.date.slice(0, 4);
                        const mood = ND_MOOD_META[e.mood] || ND_MOOD_META.okay;
                        return (
                          <button key={e.id} onClick={() => onOpen(e)} style={{
                            background: 'var(--surface-2)', border: '1px solid var(--border)',
                            borderLeft: `3px solid ${mood.color}`, borderRadius: 10, padding: '9px 12px',
                            width: '100%', textAlign: 'left', cursor: 'pointer', font: 'inherit', color: 'var(--text)',
                            display: 'flex', gap: 10, alignItems: 'flex-start',
                            transition: 'transform .12s ease',
                          }}
                          onMouseDown={ev => ev.currentTarget.style.transform = 'scale(.99)'}
                          onMouseUp={ev => ev.currentTarget.style.transform = ''}
                          onMouseLeave={ev => ev.currentTarget.style.transform = ''}>
                            <span style={{ fontSize: 16, lineHeight: 1, flexShrink: 0 }}>{mood.emoji}</span>
                            <div style={{ flex: 1, minWidth: 0 }}>
                              <div style={{ display: 'flex', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>
                                <span style={{
                                  fontSize: 10.5, fontWeight: 700,
                                  background: 'var(--surface)', color: 'var(--muted)',
                                  padding: '1px 6px', borderRadius: 4, border: '1px solid var(--border)', flexShrink: 0,
                                }}>{year}</span>
                                <span style={{ fontSize: 13, fontWeight: 600, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
                                  {_diaryLabel(e)}
                                </span>
                              </div>
                              {e.text && (
                                <div style={{
                                  fontSize: 11.5, color: 'var(--muted)', marginTop: 4,
                                  display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical',
                                  overflow: 'hidden', lineHeight: 1.5,
                                }}>{e.text}</div>
                              )}
                              {e.tags?.length > 0 && (
                                <div style={{ display: 'flex', gap: 4, flexWrap: 'wrap', marginTop: 4 }}>
                                  {e.tags.map(t => (
                                    <span key={t} style={{
                                      fontSize: 10, fontWeight: 500, padding: '1px 6px', borderRadius: 999,
                                      background: 'var(--surface)', color: 'var(--text-2)', border: '1px solid var(--border)',
                                      display: 'inline-flex', alignItems: 'center', gap: 3,
                                    }}>
                                      <span style={{ width: 5, height: 5, borderRadius: '50%', background: _getTagColor(t) }}/>
                                      {t}
                                    </span>
                                  ))}
                                </div>
                              )}
                            </div>
                          </button>
                        );
                      })}
                    </div>
                  </div>
                );
              })}
            </div>
          </div>
        );
      })}
    </div>
  );
}

Object.assign(window, {
  DiaryHome, DiaryCalendar, DiaryTimeline, DiaryStats,
  DiaryEntryCard, DiaryEntrySheet, DiaryEditSheet, DiaryCompose,
  DiaryDateModal, MemoriesArchiveSection, DiaryMemoriesTable,
});
