/* ============================================================
   PROGRESS PORTFOLIO v2 — Daily Quest Log
   ============================================================ */

function StatStrip({ me, today }) {
  const P = window.PP;
  const scores = P.decayedScores(me, today);
  const power = P.power(me, today);
  const streak = P.streak(me, today);
  return (
    <div className="stat-strip">
      {P.CAT_ORDER.map(c => {
        const lvl = P.catLevel(scores[c] || 0).level;
        const hue = P.CATS[c].hue;
        return (
          <div key={c} className="stat-strip-item" style={{ '--sh': `oklch(0.82 0.15 ${hue})` }}>
            <span className="stat-strip-key">{c}</span>
            <span className="stat-strip-lvl">{lvl}</span>
          </div>
        );
      })}
      <div className="stat-strip-sep" />
      <div className="stat-strip-item" style={{ '--sh': 'var(--accent)' }}>
        <span className="stat-strip-key">PWR</span>
        <span className="stat-strip-lvl">{power}</span>
      </div>
      {streak > 0 && (
        <div className="stat-strip-item" style={{ '--sh': 'oklch(0.82 0.15 55)' }}>
          <span className="stat-strip-key">🔥</span>
          <span className="stat-strip-lvl">{streak}</span>
        </div>
      )}
    </div>
  );
}

function DayCompleteOverlay({ me, today, doneCount, total, anim, onClose, record }) {
  const P = window.PP;
  const isPerfect = doneCount === total && total > 0;
  const scores = P.decayedScores(me, today);
  const power = P.power(me, today);
  const streak = P.streak(me, today);
  const lvl = P.profileLevel(me).level;
  const boxRef = useRef(null);
  const [phase, setPhase] = useState(0);

  // Calculate points earned today per category
  const todayGains = {};
  if (record && record.items) {
    record.items.forEach(function(item) {
      var log = record.logs && record.logs[item.iid];
      if (!log || !log.done || !log.values) return;
      var task = P.taskById(item.taskId);
      if (!task) return;
      task.fields.forEach(function(f) {
        var v = log.values[f.key];
        if (v == null) return;
        Object.keys(f.stats || {}).forEach(function(s) {
          todayGains[s] = (todayGains[s] || 0) + v * f.stats[s];
        });
      });
    });
  }
  const gainEntries = P.CAT_ORDER.filter(function(c) { return todayGains[c] > 0; });

  // Money earned today
  const moneyToday = (record && me.business && me.business.income)
    ? me.business.income.filter(function(e) { return e.iso === today; }).reduce(function(s, e) { return s + Number(e.amount || 0); }, 0)
    : 0;

  useEffect(function() {
    var t1 = setTimeout(function() { setPhase(1); }, 400);
    var t2 = setTimeout(function() { if (isPerfect) setPhase(2); }, 1800);
    return function() { clearTimeout(t1); clearTimeout(t2); };
  }, []);

  useEffect(function() {
    if (phase >= 1 && boxRef.current && anim && anim !== 'none') {
      var color = getComputedStyle(document.documentElement).getPropertyValue('--accent').trim();
      window.PP.themeCompletionFx && window.PP.themeCompletionFx(boxRef.current, anim, color);
    }
  }, [phase]);

  return (
    <div className="daycomplete-scrim" onClick={function(e) { if (e.target === e.currentTarget) onClose(); }}>
      <div className={"daycomplete-box dc-dramatic" + (phase >= 1 ? " dc-visible" : "") + (isPerfect ? " dc-perfect" : "")} ref={boxRef}>
        {isPerfect && phase >= 2 && <div className="dc-perfect-stamp">PERFECT DAY</div>}
        <div className="dc-badge">DAY COMPLETE</div>
        <div className="dc-date mono">{P.prettyDate(today)}</div>
        <div className="dc-tasks mono">{doneCount}/{total} QUESTS</div>
        {streak > 0 && <div className="dc-streak">🔥 {streak}-DAY STREAK</div>}
        {gainEntries.length > 0 && (
          <div className="dc-gains">
            <div className="dc-gains-label mono">TODAY'S GAINS</div>
            <div className="dc-gains-grid">
              {gainEntries.map(function(c) {
                return (
                  <div key={c} className="dc-gain-item" style={{'--ch': `oklch(0.82 0.15 ${P.CATS[c].hue})`}}>
                    <span className="dc-gain-key">{c}</span>
                    <span className="dc-gain-val mono">+{Math.round(todayGains[c])} {P.CATS[c].unit}</span>
                  </div>
                );
              })}
            </div>
          </div>
        )}
        {moneyToday > 0 && <div className="dc-money">💰 +${moneyToday.toLocaleString()} earned today</div>}
        <div className="dc-power mono">⚡ {power} POWER · LV {lvl}</div>
        {isPerfect && (
          <div className="dc-perfect-ring">
            <svg viewBox="0 0 100 100" className="dc-ring-svg">
              <circle cx="50" cy="50" r="44" className="dc-ring-bg"/>
              <circle cx="50" cy="50" r="44" className="dc-ring-fill" style={{strokeDashoffset: phase >= 2 ? 0 : 276}}/>
            </svg>
            <span className="dc-ring-label">100%</span>
          </div>
        )}
        <button className="btn btn-accent dc-close" onClick={onClose}>Continue →</button>
      </div>
    </div>
  );
}

function Checklist({ me, dateISO, isToday, updateMe, today, onSetDate, onOpenReview, onEditPresets, onGain, anim, organize, readOnly }) {
  const P = window.PP;
  const org = organize || {};
  const record = me.days[dateISO];
  const [collapsed, setCollapsed] = useState({});
  const [picker, setPicker] = useState(false);
  const [logFor, setLogFor] = useState(null); // {iid, taskId}
  const [reflectOpen, setReflectOpen] = useState(false);
  const [vitalsOpen, setVitalsOpen] = useState(false);
  const [expand, setExpand] = useState({});
  const [manage, setManage] = useState(false);
  const [dragIid, setDragIid] = useState(null);
  const [dragOverSec, setDragOverSec] = useState(null);
  const [justCompleted, setJustCompleted] = useState(false);
  const [copyMenuOpen, setCopyMenuOpen] = useState(false);
  const [copyDateInput, setCopyDateInput] = useState("");
  const [editingLabel, setEditingLabel] = useState(null);

  function mutate(fn) { updateMe((m) => fn(m.days[dateISO], m)); }
  // look up task def, checking ephemeral tasks stored on the day record first
  function taskLookup(id) { return (record && record.ephemeralTasks && record.ephemeralTasks[id]) || P.taskById(id); }

  if (!record) return <Empty>{dateISO < today ? "No log recorded for this day." : "Loading…"}</Empty>;

  // group items by section, ordered by effective section order (supports empty + reordered sections)
  const secOrder = effectiveOrder();
  const bySec = {};
  record.items.forEach((it) => { (bySec[it.section] = bySec[it.section] || []).push(it); });
  const sections = secOrder.map((title) => ({ title, items: bySec[title] || [] }));

  // Auto-open the first section that has incomplete tasks; fall back to first section
  const autoOpenSection = (() => {
    for (const sec of sections) {
      if (sec.items.some(it => !(record.logs[it.iid] && record.logs[it.iid].done))) return sec.title;
    }
    return sections.length > 0 ? sections[0].title : null;
  })();

  const doneCount = record.items.filter((it) => record.logs[it.iid] && record.logs[it.iid].done).length;
  const pct = record.items.length ? doneCount / record.items.length : 0;

  function needsLog(task) {
    if (!task) return false;
    if (task.type === "review") return false;
    if (task.logQuality || task.logSkill || task.logIncome || task.requireNotes) return true;
    return task.fields.some((f) => !f.quick);
  }

  function fx(iid) {
    if (!anim || anim === "none") return;
    setTimeout(() => { const el = document.querySelector('[data-iid="' + iid + '"]'); if (el) window.runCompletionFx(el, anim, getComputedStyle(document.documentElement).getPropertyValue("--accent")); }, 20);
  }

  function toggle(it) {
    const task = taskLookup(it.taskId);
    const on = record.logs[it.iid] && record.logs[it.iid].done;
    if (on) { mutate((r) => { delete r.logs[it.iid]; }); return; }
    if (task && task.type === "review") { mutate((r) => (r.logs[it.iid] = { done: true })); onOpenReview && onOpenReview(); onGain && onGain(task, {}); fx(it.iid); return; }
    if (needsLog(task)) { setLogFor(it); return; }
    // quick: apply defaults (honoring any personal default amount)
    const td = (me.taskDefaults || {})[it.taskId] || {};
    const values = {}; task.fields.forEach((f) => (values[f.key] = td[f.key] != null ? td[f.key] : f.default));
    mutate((r) => (r.logs[it.iid] = { done: true, values }));
    onGain && onGain(task, values);
    fx(it.iid);
  }

  function saveLog(log, incomeEntry) {
    const it = logFor;
    mutate((r, m) => {
      r.logs[it.iid] = log;
      if (incomeEntry) m.business.income.push({ id: "inc" + Date.now(), iso: dateISO, ...incomeEntry });
      // if skill task with a tracked skill, add to skillHistory
      if (log.skill && log.skill.skillId) {
        if (!m.skillHistory) m.skillHistory = [];
        m.skillHistory.push({
          id: "sh_" + Date.now().toString(36),
          skillId: log.skill.skillId,
          iso: dateISO,
          min: (log.values && log.values.min) || 0,
          what: log.skill.what || "",
          notes: log.taskNote || "",
        });
      }
    });
    const task = taskLookup(it.taskId);
    onGain && onGain(task, log.values);
    fx(it.iid);
    setLogFor(null);
  }

  function addTask(taskId, section) {
    mutate((r) => { ensureOrder(r); const sec = section || r.sectionOrder[r.sectionOrder.length - 1] || "Added"; if (!r.sectionOrder.includes(sec)) r.sectionOrder.push(sec); r.items.push({ iid: P.instId(), taskId, section: sec }); });
  }
  function addEphemeralTask(taskDef, section) {
    mutate((r) => { ensureOrder(r); const sec = section || r.sectionOrder[r.sectionOrder.length - 1] || "Extras"; if (!r.sectionOrder.includes(sec)) r.sectionOrder.push(sec); if (!r.ephemeralTasks) r.ephemeralTasks = {}; r.ephemeralTasks[taskDef.id] = taskDef; r.items.push({ iid: P.instId(), taskId: taskDef.id, section: sec }); });
  }
  function removeItem(iid) { mutate((r) => { r.items = r.items.filter((x) => x.iid !== iid); delete r.logs[iid]; }); }

  // ----- section management -----
  function ensureOrder(r) {
    if (!r.sectionOrder) { const seen = []; (r.items || []).forEach((it) => { if (!seen.includes(it.section)) seen.push(it.section); }); r.sectionOrder = seen.length ? seen : ["My Day"]; }
    return r.sectionOrder;
  }
  function effectiveOrder() {
    const seen = [];
    (record.sectionOrder || []).forEach((t) => { if (!seen.includes(t)) seen.push(t); });
    record.items.forEach((it) => { if (!seen.includes(it.section)) seen.push(it.section); });
    return seen.length ? seen : ["My Day"];
  }
  function addSection() {
    const name = (prompt("New section name", "New Section") || "").trim();
    if (!name) return;
    mutate((r) => { ensureOrder(r); if (!r.sectionOrder.includes(name)) r.sectionOrder.push(name); });
  }
  function renameSection(oldT, newT) {
    newT = (newT || "").trim();
    if (!newT || newT === oldT) return;
    mutate((r) => { ensureOrder(r); if (r.sectionOrder.includes(newT)) return; r.sectionOrder = r.sectionOrder.map((t) => (t === oldT ? newT : t)); r.items.forEach((it) => { if (it.section === oldT) it.section = newT; }); });
  }
  function deleteSection(t) {
    mutate((r) => {
      ensureOrder(r);
      const remaining = r.sectionOrder.filter((x) => x !== t);
      const fallback = remaining[0] || "My Day";
      r.items.forEach((it) => { if (it.section === t) it.section = fallback; });
      r.sectionOrder = remaining.length ? remaining : [fallback];
    });
  }
  function moveSection(t, dir) {
    mutate((r) => { const o = ensureOrder(r); const i = o.indexOf(t); const j = i + dir; if (i < 0 || j < 0 || j >= o.length) return; const tmp = o[i]; o[i] = o[j]; o[j] = tmp; });
  }
  function moveTaskTo(iid, section) {
    mutate((r) => { ensureOrder(r); const it = r.items.find((x) => x.iid === iid); if (it) it.section = section; });
  }
  // drag-and-drop
  function dropOnTask(targetIid) {
    if (!dragIid || dragIid === targetIid) { setDragIid(null); setDragOverSec(null); return; }
    mutate((r) => {
      const from = r.items.findIndex((x) => x.iid === dragIid);
      if (from < 0) return;
      const dragged = r.items.splice(from, 1)[0];
      const target = r.items.find((x) => x.iid === targetIid);
      if (!target) { r.items.push(dragged); return; }
      dragged.section = target.section;
      const ti = r.items.findIndex((x) => x.iid === targetIid);
      r.items.splice(ti, 0, dragged);
    });
    setDragIid(null); setDragOverSec(null);
  }
  function dropOnSection(section) {
    if (!dragIid) { setDragOverSec(null); return; }
    mutate((r) => {
      ensureOrder(r);
      const from = r.items.findIndex((x) => x.iid === dragIid);
      if (from < 0) return;
      const dragged = r.items.splice(from, 1)[0];
      dragged.section = section;
      let insertAt = r.items.length;
      for (let k = r.items.length - 1; k >= 0; k--) { if (r.items[k].section === section) { insertAt = k + 1; break; } }
      r.items.splice(insertAt, 0, dragged);
    });
    setDragIid(null); setDragOverSec(null);
  }

  function saveDayAsPreset() {
    const name = prompt("Save as preset — name:", "My Day");
    if (!name) return;
    const id = "p" + Date.now().toString(36);
    const secs = sections.map((sec) => ({ title: sec.title, tasks: sec.items.map((it) => it.taskId) }));
    updateMe((m) => { m.presets[id] = { id, name, tag: "Saved", sections: secs }; });
  }
  function saveSection(sec) {
    updateMe((m) => {
      if (!m.sectionTemplates) m.sectionTemplates = [];
      const ei = m.sectionTemplates.findIndex((t) => t.title === sec.title);
      const tpl = { id: ei >= 0 ? m.sectionTemplates[ei].id : "st_" + Date.now().toString(36), title: sec.title, tasks: sec.items.map((it) => it.taskId) };
      if (ei >= 0) { if (!confirm('Replace saved "' + sec.title + '" template?')) return; m.sectionTemplates[ei] = tpl; }
      else m.sectionTemplates.push(tpl);
    });
  }

  // Feature 1: Insert saved section into current day
  function insertSavedSection(tpl) {
    mutate((r) => {
      ensureOrder(r);
      if (!r.sectionOrder.includes(tpl.title)) r.sectionOrder.push(tpl.title);
      tpl.tasks.forEach((tid) => r.items.push({ iid: P.instId(), taskId: tid, section: tpl.title }));
    });
  }

  // Feature 3: Copy Day
  function copyDayTo(targetISO) {
    updateMe((m) => {
      const src = m.days[dateISO];
      if (!src) return;
      const fresh = P.newDayRecord(targetISO, src.presetId, m.presets);
      // override items with exact copy from source
      fresh.items = src.items.map(function(it) { return Object.assign({}, it, { iid: P.instId() }); });
      fresh.sectionOrder = (src.sectionOrder || []).slice();
      fresh.logs = {};
      m.days[targetISO] = fresh;
    });
    setCopyMenuOpen(false);
  }

  // Feature 4: Rename task label (per-day override)
  function renameTask(taskId, newName) {
    newName = (newName || "").trim();
    if (!newName) return;
    mutate((r) => { r.taskLabels = r.taskLabels || {}; r.taskLabels[taskId] = newName; });
  }

  function changePreset(pid) {
    if (pid === '__edit__') { onEditPresets && onEditPresets(); return; }
    const preset = me.presets[pid];
    if (!preset) return;
    const doneTaskIds = {};
    record.items.forEach((it) => { if (record.logs[it.iid] && record.logs[it.iid].done) doneTaskIds[it.taskId] = record.logs[it.iid]; });
    const fresh = P.newDayRecord(dateISO, pid, me.presets);
    fresh.items.forEach((it) => { if (doneTaskIds[it.taskId]) fresh.logs[it.iid] = doneTaskIds[it.taskId]; });
    // preserve vitals
    ["sleepHrs", "wokeTime", "bedTimePrev", "morningMood", "morningEnergy", "reflection", "completed", "dayNote", "photos", "water"].forEach((k) => (fresh[k] = record[k]));
    mutate((r, m) => (m.days[dateISO] = fresh));
  }

  const dayChips = [
    { label: 'Tomorrow',   iso: P.addDays(today, 1), future: true  },
    { label: 'Today',      iso: today,                future: false },
    { label: 'Yesterday',  iso: P.addDays(today, -1), future: false },
    { label: '2 days ago', iso: P.addDays(today, -2), future: false },
  ];
  const createdISO = (me.meta && me.meta.createdISO) || today;

  return (
    <div className="checklist">
      <div className="ql-head">
        <div>
          <div className="ql-date">{P.prettyDate(dateISO)}{isToday && <span className="today-pill">TODAY</span>}</div>
          {org.showQuotes !== false && dateISO <= today && (() => { const q = P.quoteObjForDate(dateISO); return <div className="ql-quote">"{q.t}"{q.a && <span className="ql-quote-author"> — {q.a}</span>}</div>; })()}
        </div>
        <div className="ql-head-right">
          <Ring pct={pct} size={84} stroke={8}><div className="ring-pct mono">{Math.round(pct * 100)}<span>%</span></div></Ring>
        </div>
      </div>

      <StatStrip me={me} today={today} />

      {/* day switcher */}
      {readOnly ? (
        <div className="dayswitch">
          <button className="dayswitch-btn" onClick={function() { onSetDate(today); }}>Today →</button>
          <span className="dayswitch-hint mono">history view — {P.prettyDate(dateISO)}</span>
        </div>
      ) : (
      <div className="dayswitch">
        {dayChips.map(function(chip) {
          var locked = !chip.future && chip.iso < createdISO;
          return (
            <button key={chip.iso}
              className={'dayswitch-btn' + (chip.iso === dateISO ? ' on' : '') + (locked ? ' ds-locked' : '') + (chip.future ? ' ds-future' : '')}
              disabled={locked}
              onClick={function() {
                if (locked) return;
                if (chip.future && !me.days[chip.iso]) {
                  updateMe(function(m) { if (!m.days[chip.iso]) m.days[chip.iso] = P.newDayRecord(chip.iso, null, m.presets); });
                }
                onSetDate(chip.iso);
              }}>
              {chip.label}
              {!chip.future && !locked && me.days[chip.iso] && me.days[chip.iso].completed && <span className='ds-check'>✓</span>}
            </button>
          );
        })}
        <span className='dayswitch-hint mono'>plan tomorrow or edit up to 2 days back</span>
      </div>
      )}

      {/* preset + vitals — desktop layout */}
      <div className="preset-row">
        <span className="preset-label">PRESETS</span>
        <select className="preset-select" value={me.presets[record.presetId] ? record.presetId : ""} onChange={(e) => { if (e.target.value) changePreset(e.target.value); }}>
          <option value="" disabled>-- Pick a preset --</option>
          {Object.values(me.presets).map((p) => <option key={p.id} value={p.id}>{p.name}</option>)}
        </select>
        <button className="btn btn-sm" onClick={function(){ onEditPresets && onEditPresets(); }}>Edit presets</button>
        <button className="btn btn-sm" onClick={() => setVitalsOpen(true)}>⚙ Day Vitals</button>
      </div>

      {/* vitals summary */}
      <div className="vitals-row">
        <span><b className="mono">{record.sleepHrs != null ? record.sleepHrs + "h" : "—"}</b> sleep</span>
        <span><b className="mono">{record.wokeTime || "—"}</b> woke</span>
        <span><b className="mono">{record.bedTimePrev || "—"}</b> bed</span>
        <span><b className="mono">{record.morningMood || "—"}/5</b> mood</span>
        <button className="vitals-edit" onClick={() => setVitalsOpen(true)} title="Edit vitals">✎</button>
      </div>

      {/* sections tools */}
      {!readOnly && <div className="sections-tools">
        <select className="preset-select preset-select-inline" value={me.presets[record.presetId] ? record.presetId : ""} onChange={(e) => { if (e.target.value) changePreset(e.target.value); }}>
          <option value="" disabled>-- Pick a preset --</option>
          {Object.values(me.presets).map((p) => <option key={p.id} value={p.id}>{p.name}</option>)}
        </select>
        <button className={"mini-btn" + (manage ? " on" : "")} onClick={() => setManage(!manage)}>{manage ? "✓ Done" : "✎ Sections"}</button>
        <button className="mini-btn" onClick={addSection}>+ Section</button>
        {sections.length > 0 && <button className="mini-btn" onClick={saveDayAsPreset} title="Save this day's tasks as a new preset">💾 Save as preset</button>}
        {/* Feature 1: Insert saved section dropdown */}
        {(me.sectionTemplates || []).length > 0 && (
          <select className="preset-select" style={{fontSize:12,padding:'3px 28px 3px 8px'}} defaultValue="" onChange={(e) => { if (e.target.value) { const tpl = (me.sectionTemplates||[]).find(function(t){return t.id===e.target.value;}); if(tpl) insertSavedSection(tpl); e.target.value=""; } }}>
            <option value="" disabled>📌 Insert section…</option>
            {(me.sectionTemplates||[]).map(function(tpl) { return <option key={tpl.id} value={tpl.id}>{tpl.title} ({tpl.tasks.length})</option>; })}
          </select>
        )}
        {/* Feature 3: Copy Day button */}
        <div style={{position:'relative',display:'inline-block'}}>
          <button className="mini-btn" onClick={() => setCopyMenuOpen(!copyMenuOpen)}>📋 Copy Day</button>
          {copyMenuOpen && (
            <div style={{position:'absolute',top:'110%',left:0,zIndex:50,background:'var(--panel)',border:'1px solid var(--line2)',borderRadius:10,padding:10,minWidth:190,boxShadow:'0 8px 24px -8px rgba(0,0,0,.5)',display:'flex',flexDirection:'column',gap:6}}>
              <button className="mini-btn" style={{textAlign:'left'}} onClick={() => copyDayTo(today)}>Copy to Today</button>
              <button className="mini-btn" style={{textAlign:'left'}} onClick={() => copyDayTo(P.addDays(today,1))}>Copy to Tomorrow</button>
              <div style={{display:'flex',gap:4,alignItems:'center'}}>
                <input className="inp" type="date" style={{fontSize:12,padding:'4px 8px',flex:1}} value={copyDateInput} onChange={(e) => setCopyDateInput(e.target.value)} />
                <button className="mini-btn" disabled={!copyDateInput} onClick={() => { if(copyDateInput) copyDayTo(copyDateInput); setCopyDateInput(""); }}>Go</button>
              </div>
              <button className="mini-btn" style={{color:'var(--dim)'}} onClick={() => setCopyMenuOpen(false)}>Cancel</button>
            </div>
          )}
        </div>
        {manage && <span className="dim mono sections-hint">drag tasks to move/reorder · tap 📌 to save a section as a template · double-click task name to rename</span>}
      </div>}
      <div className="sections">
        {sections.length === 0 && <Empty>Blank day — tap "+ Add task" to build your schedule.</Empty>}
        {sections.map((sec, si) => {
          const sd = sec.items.filter((it) => record.logs[it.iid] && record.logs[it.iid].done).length;
          const sp = sec.items.length ? sd / sec.items.length : 0;
          const allDone = sd === sec.items.length && sec.items.length > 0;
          const isCol = manage ? false : (collapsed[sec.title] !== undefined ? collapsed[sec.title] : sec.title !== autoOpenSection);
          return (
            <div className={"sec" + (allDone ? " sec-done" : "") + (dragOverSec === sec.title ? " sec-dragover" : "")} key={sec.title}
              onDragOver={(e) => { if (dragIid) { e.preventDefault(); setDragOverSec(sec.title); } }}
              onDragLeave={() => { if (dragOverSec === sec.title) setDragOverSec(null); }}
              onDrop={(e) => { e.preventDefault(); dropOnSection(sec.title); }}>
              {manage ? (
                <div className="sec-head sec-head-edit">
                  <span className="sec-grip">⋮⋮</span>
                  <input className="sec-rename" defaultValue={sec.title} onBlur={(e) => renameSection(sec.title, e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") e.target.blur(); }} />
                  <span className="sec-prog mono">{sd}/{sec.items.length}</span>
                  <span className="pe-section-tools">
                    <button className="mini-btn" disabled={si === 0} onClick={() => moveSection(sec.title, -1)}>↑</button>
                    <button className="mini-btn" disabled={si === sections.length - 1} onClick={() => moveSection(sec.title, 1)}>↓</button>
                    <button className="mini-btn" onClick={() => saveSection(sec)} title="save section as template">📌</button>
                    <button className="mini-btn" onClick={() => deleteSection(sec.title)} title="delete section">✕</button>
                  </span>
                </div>
              ) : (
                <button className="sec-head" onClick={() => setCollapsed({ ...collapsed, [sec.title]: !isCol })}>
                  <span className="sec-caret">{isCol ? "▸" : "▾"}</span>
                  <span className="sec-title">{sec.title}</span>
                  <span className="sec-prog mono">{sd}/{sec.items.length}</span>
                  <span className="sec-barmini"><span style={{ width: sp * 100 + "%" }} /></span>
                </button>
              )}
              {!isCol && (
                <div className="sec-tasks">
                  {sec.items.length === 0 && <div className="sec-empty mono dim">empty — drag a task here, or use "Add task"</div>}
                  {sec.items.map((it) => {
                    const task = taskLookup(it.taskId);
                    if (!task) return null;
                    const log = record.logs[it.iid];
                    const on = log && log.done;
                    const cats = catChips(task);
                    const displayName = (record.taskLabels && record.taskLabels[it.taskId]) || task.name;
                    return (
                      <div className={"task" + (on ? " task-on" : "") + (dragIid === it.iid ? " task-dragging" : "")} key={it.iid} data-iid={it.iid}
                        draggable onDragStart={() => setDragIid(it.iid)} onDragEnd={() => { setDragIid(null); setDragOverSec(null); }}
                        onDragOver={(e) => { if (dragIid && dragIid !== it.iid) e.preventDefault(); }}
                        onDrop={(e) => { e.preventDefault(); e.stopPropagation(); dropOnTask(it.iid); }}>
                        {!readOnly && <span className="task-grip" title="drag to move">⋮⋮</span>}
                        {readOnly ? <span className={"check" + (on ? " on" : "")}><span className="check-box">{on && "✓"}</span></span> : <button className="check" onClick={() => toggle(it)}><span className="check-box">{on && "✓"}</span></button>}
                        <div className="task-main" onClick={() => { if (!manage) toggle(it); }}>
                          {/* Feature 4: Inline rename in manage mode */}
                          {manage && editingLabel === it.taskId ? (
                            <input
                              className="inp"
                              style={{fontSize:14,padding:'3px 7px'}}
                              autoFocus
                              defaultValue={displayName}
                              onBlur={(e) => { renameTask(it.taskId, e.target.value); setEditingLabel(null); }}
                              onKeyDown={(e) => { if (e.key === "Enter") e.target.blur(); if (e.key === "Escape") setEditingLabel(null); }}
                              onClick={(e) => e.stopPropagation()}
                            />
                          ) : (
                            <div
                              className="task-label"
                              onDoubleClick={() => { if (manage) setEditingLabel(it.taskId); }}
                              title={manage ? "Double-click to rename" : ""}
                            >{displayName}</div>
                          )}
                          {on && log.values && <div className="task-sub">{Object.keys(log.values).map((k) => { const fl = task.fields.find((f) => f.key === k); return fl && !fl.quick ? `${log.values[k]} ${fl.unit}` : null; }).filter(Boolean).join(" · ")}</div>}
                          {on && log.quality && <div className="task-sub wl">◆{log.quality.intensity} · felt {log.quality.feel}/5{log.quality.note ? " · " + log.quality.note : ""}</div>}
                          {on && log.skill && <div className="task-sub">{log.skill.skill}{log.skill.what ? " · " + log.skill.what : ""}</div>}
                          {on && log.income && Number(log.income.amount) > 0 && <div className="task-sub wl">+${log.income.amount} · {log.income.source}</div>}
                          {on && log.subtype && <div className="task-sub">{log.subtype}</div>}
                          {on && log.taskNote && <div className="task-sub task-note">"{log.taskNote}"</div>}
                        </div>
                        <div className="task-actions">
                          {manage && (
                            <select className="task-move" value={it.section} onChange={(e) => moveTaskTo(it.iid, e.target.value)} onClick={(e) => e.stopPropagation()}>
                              {secOrder.map((s) => <option key={s} value={s}>{s}</option>)}
                            </select>
                          )}
                          {cats.map((c) => <StatChip key={c} stat={c} />)}
                          {!readOnly && needsLog(task) && on && <button className="mini-btn" onClick={() => setLogFor(it)}>edit</button>}
                          {!readOnly && <button className="mini-btn" onClick={() => removeItem(it.iid)} title="remove">✕</button>}
                        </div>
                      </div>
                    );
                  })}
                </div>
              )}
            </div>
          );
        })}
      </div>

      {!readOnly && <button className="add-task-btn" onClick={() => setPicker(true)}>+ Add task from database</button>}

      {/* footer */}
      {readOnly ? (
        <div className="ql-foot"><div className="ql-foot-btns"><span className="dim mono">{record.completed ? "✓ Day completed" : Math.round(pct*100) + "% done"} — view only</span></div></div>
      ) : (
      <div className="ql-foot">
        <div className="water">
          <span className="water-label">WATER</span>
          <div className="water-dots">
            {Array.from({ length: 8 }).map((_, i) => <button key={i} className={"water-dot" + (i < record.water ? " on" : "")} onClick={() => mutate((r) => (r.water = i + 1 === r.water ? i : i + 1))} />)}
          </div>
        </div>
        <div className="ql-foot-btns">
          <button className="btn" onClick={() => setReflectOpen(true)}>Reflect</button>
          <button className={"btn " + (record.completed ? "btn-done" : "btn-accent")} onClick={() => setReflectOpen(true)}>{record.completed ? "✓ Day Complete" : "Complete Day"}</button>
        </div>
      </div>

      )}
      {/* Feature 2: Extras section for custom tasks added today */}
      {picker && <TaskPicker customTasks={me.customTasks} onClose={() => setPicker(false)} onPick={(tid) => {
        const isCustom = (me.customTasks || []).some(function(t) { return t.id === tid; });
        addTask(tid, isToday && isCustom ? "Extras" : undefined);
        setPicker(false);
      }} onPickEphemeral={(taskDef) => {
        addEphemeralTask(taskDef, isToday ? "Extras" : undefined);
        setPicker(false);
      }} onCreateCustom={(task) => {
        updateMe((m) => { if (!m.customTasks) m.customTasks = []; m.customTasks.push(task); P.rebuildIndex(m.customTasks); });
      }} onDeleteCustom={(tid) => {
        updateMe((m) => { m.customTasks = (m.customTasks || []).filter(function(t) { return t.id !== tid; }); P.rebuildIndex(m.customTasks); });
      }} />}
      {logFor && (() => { const t = taskLookup(logFor.taskId); return <LogModal task={t} existing={record.logs[logFor.iid]} dateLabel={!isToday ? P.prettyDate(dateISO) : null} defaults={me.taskDefaults} onSetDefault={(tid, vals) => updateMe((m) => { m.taskDefaults = m.taskDefaults || {}; m.taskDefaults[tid] = vals; })} onClose={() => setLogFor(null)} onSave={saveLog} skills={me.skills} />; })()}
      {reflectOpen && <ReflectModal record={record} onClose={() => setReflectOpen(false)} onSave={(refl, completed) => { const wasComplete = record.completed; mutate((r) => { r.reflection = refl; r.completed = completed; }); setReflectOpen(false); if (completed && !wasComplete) setJustCompleted(true); }} />}
      {justCompleted && <DayCompleteOverlay me={me} today={today} doneCount={doneCount} total={record.items.length} anim={anim} onClose={() => setJustCompleted(false)} record={record} />}
      {vitalsOpen && <VitalsModal record={record} dateISO={dateISO} onClose={() => setVitalsOpen(false)} onSave={(v) => { mutate((r) => Object.assign(r, v)); setVitalsOpen(false); }} />}
    </div>
  );
}

function ReflectModal({ record, onClose, onSave }) {
  const P = window.PP;
  const [v, setV] = useState(record.reflection || { feel: 4, note: "" });
  const missed = record.items.filter((it) => !(record.logs[it.iid] && record.logs[it.iid].done)).map((it) => P.taskById(it.taskId)).filter(Boolean);
  return (
    <Modal open onClose={onClose} title="End of day — reflect"
      footer={<button className="btn btn-accent" onClick={() => onSave(v, true)}>Complete day →</button>}>
      <div className="stack">
        <Field label="How do you feel about today?"><Rating value={v.feel} onChange={(n) => setV({ ...v, feel: n })} /></Field>
        <Field label="Reflection"><textarea className="ta" rows={3} value={v.note} placeholder="What went well? What will you fix tomorrow?" onChange={(e) => setV({ ...v, note: e.target.value })} /></Field>
        {missed.length > 0 && (
          <div className="missed">
            <div className="missed-head">Not completed ({missed.length})</div>
            <div className="missed-list">{missed.map((t, i) => <span key={i} className="missed-tag">{t.name}</span>)}</div>
          </div>
        )}
      </div>
    </Modal>
  );
}

function VitalsModal({ record, dateISO, onClose, onSave }) {
  const P = window.PP;
  const [sleepHrs, setSleep] = useState(record.sleepHrs != null ? record.sleepHrs : 7.5);
  const [wokeTime, setWoke] = useState(record.wokeTime || "5:30");
  const [bedTimePrev, setBed] = useState(record.bedTimePrev || "8:30 PM");
  const [morningMood, setMood] = useState(record.morningMood || 4);
  const [morningEnergy, setEnergy] = useState(record.morningEnergy || 4);
  return (
    <Modal open onClose={onClose} title={"Day vitals · " + P.prettyDate(dateISO)}
      footer={<button className="btn btn-accent" onClick={() => onSave({ sleepHrs: Number(sleepHrs), wokeTime, bedTimePrev, morningMood, morningEnergy })}>Save</button>}>
      <div className="stack">
        <Field label={`Hours of sleep — ${sleepHrs}h`}><input className="range" type="range" min="3" max="11" step="0.5" value={sleepHrs} onChange={(e) => setSleep(e.target.value)} /></Field>
        <div className="row2">
          <Field label="Woke up at"><input className="inp" value={wokeTime} onChange={(e) => setWoke(e.target.value)} /></Field>
          <Field label="Went to bed (prev. night)"><input className="inp" value={bedTimePrev} onChange={(e) => setBed(e.target.value)} /></Field>
        </div>
        <Field label="Morning mood"><Rating value={morningMood} onChange={setMood} /></Field>
        <Field label="Energy"><Rating value={morningEnergy} onChange={setEnergy} icon="▮" /></Field>
      </div>
    </Modal>
  );
}

Object.assign(window, { Checklist, VitalsModal });
