function TodayView() {
  const { state, update } = useStore();
  const data = window.PLAN_DATA;
  const TODAY = useToday();
  const today = fmtDate(TODAY);
  const startDate = data.meta.startDate;
  const activeEnd = data.meta.activeEndDate;
  const bufferEnd = data.meta.bufferEndDate;
  const defaultDate = today < startDate ? startDate : (today > bufferEnd ? bufferEnd : today);
  const [workDate, setWorkDate] = React.useState(defaultDate);
  const [pendingDraft, setPendingDraft] = React.useState('');
  const selectedEntry = plannedDay(workDate) || data.calendar[0];
  const dayState = state.days[workDate] || {};
  const phase = currentPhaseFor(parseDate(workDate));
  const activeDays = data.calendar.filter(day => day.date <= activeEnd);
  const activeTotal = activeDays.length;
  const dayNumber = Math.max(1, Math.min(activeTotal, daysBetween(parseDate(startDate), parseDate(workDate)) + 1));
  const daysToActiveEnd = Math.max(0, daysBetween(TODAY, parseDate(activeEnd)));
  const sprintPct = Math.round((dayNumber / activeTotal) * 100);
  const phaseTotal = phase ? daysBetween(parseDate(phase.start), parseDate(phase.end)) + 1 : 1;
  const phaseElapsed = phase ? Math.max(0, Math.min(phaseTotal, daysBetween(parseDate(phase.start), parseDate(workDate)) + 1)) : 0;
  const phasePct = Math.round((phaseElapsed / phaseTotal) * 100);
  const totalDone = Object.values(state.days || {}).filter(item => item?.done).length;
  const openPending = Object.values(state.pending || {}).filter(item => item?.status !== 'done').length;

  function startOfWeek(d) {
    const out = new Date(d);
    while (out.getDay() !== 1) out.setDate(out.getDate() - 1);
    return out;
  }
  const weekStart = startOfWeek(parseDate(workDate));
  const weekDays = Array.from({ length: 7 }, (_, i) => {
    const d = new Date(weekStart);
    d.setDate(d.getDate() + i);
    return fmtDate(d);
  });
  const plannedHours = weekDays.reduce((sum, key) => sum + Number(plannedDay(key)?.hours || 0), 0);
  const actualHours = weekDays.reduce((sum, key) => sum + Number(state.days?.[key]?.actualHours || 0), 0);

  function setDay(dateText, patch) {
    update(prev => ({
      ...prev,
      days: {
        ...(prev.days || {}),
        [dateText]: {
          ...(prev.days?.[dateText] || {}),
          ...patch,
        },
      },
    }));
  }

  function addPending(title = pendingDraft) {
    const clean = String(title || '').trim();
    if (!clean) return;
    const item = createPendingItem(clean, workDate, {
      targetDate: addDays(workDate, 1),
      type: selectedEntry.type,
      note: selectedEntry.deliverable,
    });
    update(prev => ({ ...prev, pending: { ...(prev.pending || {}), [item.id]: item } }));
    setPendingDraft('');
  }

  const yesterday = addDays(workDate, -1);
  const yesterdayEntry = plannedDay(yesterday);
  const yesterdayState = state.days?.[yesterday];
  const missedKey = `dismissedMiss_${yesterday}`;
  const missedYesterday = yesterdayEntry && !dayIsActive(yesterdayState) && !state[missedKey] && workDate >= today;

  const upcomingIndex = Math.max(0, data.calendar.findIndex(day => day.date === workDate));
  const upcoming = data.calendar.slice(upcomingIndex, upcomingIndex + 7);

  return (
    <div className="today-page">
      <section className="today-hero">
        <div>
          <div className="kicker">{TODAY.toLocaleDateString('en-US', { weekday: 'long', month: 'long', day: '2-digit', year: 'numeric' })} - IST</div>
          <h1 className="h-title">Day <em>{dayNumber}</em> of {activeTotal}.<br />Capstone ready in <em>{daysToActiveEnd}</em> days.</h1>
        </div>
        <div className="streak-wrap">
          <div className="streak-ring">{Object.values(state.days || {}).filter(dayIsActive).length}</div>
          <div>
            <div className="kicker">Active Days</div>
            <p className="mono muted">done - note - or hours</p>
          </div>
        </div>
      </section>

      {missedYesterday && (
        <section className="missed-card">
          <div>
            <div className="kicker">Missed: {yesterday} ({yesterdayEntry.type})</div>
            <h2>Yesterday slipped. Absorb it or carry the work forward.</h2>
          </div>
          <div className="row">
            <button className="btn primary" onClick={() => addPending(yesterdayEntry.focus)}>Carry to Pending</button>
            <button className="btn" onClick={() => setDay(yesterday, { done: false, note: 'Absorbed missed day without shifting schedule.' })}>Absorb</button>
            <button className="btn ghost" onClick={() => update(prev => ({ ...prev, [missedKey]: true }))}>Dismiss</button>
          </div>
        </section>
      )}

      <section className="metric-grid">
        <div className="metric-card">
          <div className="kicker">Sprint</div>
          <div className="metric-value">{sprintPct}%</div>
          <div className="mono muted">{dayNumber} / {activeTotal} days</div>
        </div>
        <div className="metric-card">
          <div className="kicker">Current Phase</div>
          <div className="metric-value accent-text">{phase?.name || selectedEntry.phase}</div>
          <div className="mono muted">{phase?.start} - {phase?.end}</div>
        </div>
        <div className="metric-card">
          <div className="kicker">Tasks Closed</div>
          <div className="metric-value">{totalDone}</div>
          <div className="mono muted">of {data.calendar.length}</div>
        </div>
        <div className="metric-card">
          <div className="kicker">Open Pending</div>
          <div className="metric-value">{openPending}</div>
          <div className="mono muted">DB synced queue</div>
        </div>
      </section>

      <section className="wide-card">
        <div className="between">
          <div>
            <div className="kicker">Phase Progress</div>
            <h2>{phase?.focus || selectedEntry.phase}</h2>
          </div>
          <div className="mono right">{phaseElapsed} / {phaseTotal} days<br /><strong>{phasePct}%</strong></div>
        </div>
        <ProgressBar value={phasePct} />
        <div className="between mono muted">
          <span>{phase?.start}</span>
          <span>{phase?.end}</span>
        </div>
      </section>

      <section className="wide-card hours-card">
        <div>
          <div className="kicker">Hours This Week</div>
          <h2><span className={actualHours < plannedHours ? 'rose-text' : 'accent-text'}>{actualHours.toFixed(1)}h</span> <span className="muted">/ {plannedHours.toFixed(1)}h planned</span></h2>
        </div>
        <div className="week-line">
          {weekDays.map(key => <span key={key} className={dayIsActive(state.days?.[key]) ? 'on' : ''}></span>)}
        </div>
      </section>

      <section className="date-card">
        <div>
          <div className="kicker">Work Date</div>
          <h2>{formatLongDate(workDate)}</h2>
        </div>
        <div className="row">
          <button className="btn" onClick={() => setWorkDate(addDays(today, -1))}>Yesterday</button>
          <button className="btn primary" onClick={() => setWorkDate(today < startDate ? startDate : today)}>Today</button>
          <input className="input date-input" type="date" min={startDate} max={bufferEnd} value={workDate} onChange={event => setWorkDate(event.target.value)} />
        </div>
      </section>

      <section className="mission-card">
        <div className="mission-head">
          <div className="row">
            <div className="kicker">Today's Mission</div>
            <PhasePill phase={selectedEntry.phase} />
            <TypePill type={selectedEntry.type} />
            <Pill>{selectedEntry.hours}h planned</Pill>
          </div>
          <Check on={!!dayState.done} onClick={() => setDay(workDate, { done: !dayState.done })} size={28} />
        </div>

        <div className="mission-body">
          <div className="kicker accent-text">{categoryLabel(selectedEntry.newTopicIds?.length ? data.topics.find(t => t.id === selectedEntry.newTopicIds[0])?.category : 'enterprise_repo')}</div>
          <h2>{selectedEntry.focus}</h2>
          <div className="mission-detail-grid">
            <div>
              <div className="kicker">Concept</div>
              <p className="copy">{selectedEntry.concept}</p>
            </div>
            <div>
              <div className="kicker">Practice</div>
              <p className="copy">{selectedEntry.practice}</p>
            </div>
            <div>
              <div className="kicker">Done When</div>
              <p className="copy">{selectedEntry.deliverable}</p>
            </div>
          </div>
          <div className="daily-block-list">
            {(selectedEntry.blocks || []).map(block => (
              <div className="daily-block-row" key={block.label}>
                <span className="mono accent-text">{block.minutes}m</span>
                <strong>{block.label}</strong>
                <p>{block.task}</p>
              </div>
            ))}
          </div>
          {!!selectedEntry.dueRebuildIds?.length && (
            <div className="due-topic-list">
              <div className="kicker">Due Rebuild Topics</div>
              {selectedEntry.dueRebuildIds.slice(0, 6).map(id => {
                const topic = state.rebuild?.topics?.[id] || data.topics.find(item => item.id === id);
                if (!topic) return null;
                return (
                  <div className="due-topic-row" key={id}>
                    <Pill tone={categoryTone(topic.category)}>{categoryLabel(topic.category)}</Pill>
                    <div>
                      <strong>{topic.title}</strong>
                      <p>{topic.artifactPrompt}</p>
                    </div>
                  </div>
                );
              })}
            </div>
          )}
        </div>

        <div className="mission-pending">
          <div className="between">
            <div>
              <div className="kicker">Carry Forward Unfinished Work</div>
              <p className="muted">Save the exact piece she could not finish so it appears in Pending.</p>
            </div>
            <button className="btn ghost" onClick={() => update({ view: 'pending' })}>Open pending</button>
          </div>
          <div className="pending-inline">
            <input className="input" value={pendingDraft} onChange={event => setPendingDraft(event.target.value)} placeholder="e.g. redo pytest fixtures, finish FastAPI validation errors" />
            <button className="btn primary" onClick={() => addPending()}>+ Pending</button>
          </div>
        </div>

        <div className="daily-log-grid">
          <label>
            <span className="kicker">Actual Hours</span>
            <input className="input mono" type="number" step="0.25" min="0" placeholder="0.0" value={dayState.actualHours || ''} onChange={event => setDay(workDate, { actualHours: event.target.value })} />
          </label>
          <label>
            <span className="kicker">Sleep Hours</span>
            <input className="input mono" type="number" step="0.25" min="0" placeholder="0.0" value={dayState.sleepHours || ''} onChange={event => setDay(workDate, { sleepHours: event.target.value })} />
          </label>
          <label>
            <span className="kicker">Energy (1-5)</span>
            <Rating value={dayState.energy || 0} onChange={value => setDay(workDate, { energy: value })} />
          </label>
          <label>
            <span className="kicker">Sleep Quality (1-5)</span>
            <Rating value={dayState.sleep || 0} onChange={value => setDay(workDate, { sleep: value })} color="var(--blue)" />
          </label>
        </div>

        <textarea className="textarea" value={dayState.note || ''} onChange={event => setDay(workDate, { note: event.target.value })} placeholder="Day notes - wins, blockers, weak concepts..." />
      </section>

      <section className="road-card">
        <div className="kicker">Up Next</div>
        <h2>The road ahead.</h2>
        <div className="road-list">
          {upcoming.map(day => (
            <div className={`road-row ${state.days?.[day.date]?.done ? 'done' : ''}`} key={day.date}>
              <span className={day.date === workDate ? 'accent-text mono' : 'mono muted'}>{day.date === workDate ? 'TODAY' : day.day.toUpperCase()}</span>
              <span className="mono">{formatShortDate(day.date)}</span>
              <TypePill type={day.type} />
              <span className="road-focus">{day.focus}</span>
              <span className="mono muted">{day.hours}h</span>
              <Check on={!!state.days?.[day.date]?.done} onClick={() => setDay(day.date, { done: !state.days?.[day.date]?.done })} size={22} />
            </div>
          ))}
        </div>
      </section>
    </div>
  );
}

window.TodayView = TodayView;
