/* global React, Card, Button, Segmented, Pill, Eyebrow */
// ============================================================================
// Today (Idag) — the boys' day as a timeline (Season 1 spec, _spec-season1-app.md).
//
// Reads plan_item (the day's tasks), schedule_block (school / team context),
// calendar_event and the morning check-in. The boys write only two things:
// their own check-in (RLS) and done/skipped + a result on their own released
// items (log_plan_item()). Drafts are invisible to them by RLS.
//
// Behind a flag: open the app once with ?idag=1 (and ?idag=0 to switch off).
// ============================================================================
const { useState: useStateI, useEffect: useEffectI, useCallback: useCallbackI } = React;

function ymdI(d) {
  const z = (n) => String(n).padStart(2, '0');
  return `${d.getFullYear()}-${z(d.getMonth() + 1)}-${z(d.getDate())}`;
}
function addDaysI(s, n) { const d = new Date(s + 'T12:00:00'); d.setDate(d.getDate() + n); return ymdI(d); }
function hhmm(t) { return t ? String(t).slice(0, 5) : ''; }
const WEEKDAYS = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
const AREA_LABEL = { physical: 'Training', skill: 'Skill', academic: 'Study', profile: 'Task', team: 'Team', school: 'School', sleep: 'Sleep', other: '' };
const CONTEXT_KINDS = ['school', 'team', 'games', 'travel', 'sleep', 'free'];
const SPORT_KINDS = ['team', 'games', 'travel'];
const toMin = (t) => { if (!t) return null; const [h, m] = String(t).split(':'); return Number(h) * 60 + Number(m); };
const fromMin = (m) => `${String(Math.floor(m / 60)).padStart(2, '0')}:${String(m % 60).padStart(2, '0')}`;
const BLOCK = {
  morning: { title: 'Morning', accent: 'var(--warning)' },
  afternoon: { title: 'Afternoon', accent: 'var(--ink-400)' },
  sports: { title: 'Sports', accent: 'var(--success)' },
  evening: { title: 'Evening', accent: 'var(--ink-700)' },
};

// The day as blocks in time order: Morning (06:00 → school), School, Afternoon (→ first sport),
// Sports (first to last sport thing: home training, travel, dressing, practice, games), Evening (→ lights out).
// Without school or sport the day splits at 12:00 and 18:00.
function daySegments({ school, sportFrom, sportTo }) {
  const anchors = [school && { key: 'school', from: school.from, to: school.to },
                   sportFrom != null && { key: 'sports', from: sportFrom, to: sportTo }].filter(Boolean).sort((a, b) => a.from - b.from);
  const segs = [];
  const gap = (key, from, to) => { if (to > from) segs.push({ key, from, to }); };
  let cur = 6 * 60;
  if (!anchors.length) { gap('morning', cur, 12 * 60); gap('afternoon', 12 * 60, 18 * 60); gap('evening', 18 * 60, 24 * 60); return segs; }
  anchors.forEach((a, n) => {
    if (n === 0) {
      if (a.from > 13 * 60) { gap('morning', cur, 12 * 60); gap('afternoon', 12 * 60, a.from); }
      else gap('morning', cur, a.from);
    } else gap(anchors[n - 1].key === 'school' ? 'afternoon' : 'evening', cur, a.from);
    segs.push({ key: a.key, from: a.from, to: a.to });
    cur = a.to;
  });
  if (cur < 17 * 60) { gap('afternoon', cur, 18 * 60); gap('evening', Math.max(cur, 18 * 60), 24 * 60); }
  else gap('evening', cur, 24 * 60);
  // merge neighbours with the same name (e.g. two afternoon gaps)
  return segs.reduce((out, g) => { const last = out[out.length - 1]; if (last && last.key === g.key) last.to = g.to; else out.push({ ...g }); return out; }, []);
}

function DayBlock({ title, from, until, accent, children, onAdd }) {
  return (
    <div style={{ border: '1px solid var(--border)', borderLeft: `3px solid ${accent}`, borderRadius: 8, marginBottom: 8,
                  background: 'var(--bg-raised)', padding: '10px 12px' }}>
      <div style={{ display: 'flex', gap: 12, alignItems: 'baseline', marginBottom: 2 }}>
        <div style={{ width: 44, fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--fg-muted)' }}>{from}</div>
        <div style={{ flex: 1, fontSize: 15, fontWeight: 500 }}>{title} {until && <span style={{ fontSize: 13, color: 'var(--fg-muted)', fontWeight: 400 }}>until {until}</span>}</div>
        {onAdd && <button onClick={onAdd} aria-label={`Add to ${title}`} style={{ all: 'unset', cursor: 'pointer', width: 28, height: 28, borderRadius: 14,
          textAlign: 'center', lineHeight: '28px', fontSize: 20, color: 'var(--signal)', border: '1px solid var(--border)' }}>+</button>}
      </div>
      {children}
    </div>
  );
}

function IdagScreen(props = {}) {
  const kids = (window.MEMBERS || []).filter(m => m.isMyFamily && /^(axel|otto)/i.test(m.name));
  const myDb = window.MY_MEMBER_DB_ID;
  const isAdmin = !!window.MY_IS_ADMIN;
  const mine = kids.find(k => k.db_id === myDb);
  const [ownDb, setMemberDb] = useStateI(mine ? mine.db_id : (kids[0] && kids[0].db_id));
  const memberDb = props.memberDb || ownDb;
  const [day, setDay] = useStateI(ymdI(new Date()));
  const [state, setState] = useStateI({ loading: true, error: null, items: [], blocks: [], events: [], checkin: null, sets: { today: {}, last: {} } });
  const [open, setOpen] = useStateI(null);
  const [school, setSchool] = useStateI({ s: null, tomorrow: null });
  const [sheet, setSheet] = useStateI(null);          // { anchor, note } — the add/edit bottom sheet

  const member = kids.find(k => k.db_id === memberDb);
  const canWrite = isAdmin || memberDb === myDb;
  const isToday = day === ymdI(new Date());

  const load = useCallbackI(async () => {
    if (!memberDb) return;
    setState(s => ({ ...s, loading: true, error: null }));
    try {
      const d = await window.PlanAPI.getDay(memberDb, day);
      const blocks = d.blocks.filter(b => CONTEXT_KINDS.includes(b.kind));
      // Exercise cards (027) need last time's sets and anything already ticked today
      const keys = [...new Set(d.items.filter(i => i.rx && i.rx.key).map(i => i.rx.key))];
      const sets = await window.PlanAPI.sets.forCard(memberDb, keys, day);
      setState({ loading: false, error: null, items: d.items, blocks, events: d.events, checkin: d.checkin, sets });
      loadSchool();
    } catch (e) {
      setState(s => ({ ...s, loading: false, error: e.message }));
    }
  }, [memberDb, day]);

  useEffectI(() => { load(); }, [load]);

  // School: today's classes (in the timeline) and the next school day (for "pack for tomorrow")
  async function loadSchool() {
    try {
      const P = window.PlanAPI;
      const [s, tomorrow] = await Promise.all([P.getSchoolDay(memberDb, day), P.getSchoolDay(memberDb, P.nextSchoolDay(day))]);
      setSchool({ s, tomorrow });
    } catch (e) { console.warn('[school]', e); setSchool({ s: null, tomorrow: null }); }
  }
  async function toggleSchoolItem(n) {
    try { await window.PlanAPI.notes.toggle(n, !n.done); loadSchool(); } catch (e) { alert('Could not save: ' + e.message); }
  }
  const addNote = (anchor) => setSheet({ anchor, note: null });
  const editNote = (n) => setSheet({ anchor: { type: n.anchor_type, ref: n.anchor_ref, block: n.block, subject: n.subject,
    label: n.anchor_type === 'lesson' ? n.subject : (n.block ? n.block[0].toUpperCase() + n.block.slice(1) : 'Today') }, note: n });

  async function logItem(item, status, value) {
    const { error } = await window.sb.rpc('log_plan_item', { p_item: item.id, p_status: status, p_value: value ?? null, p_text: null });
    if (error) { alert('Could not save: ' + error.message); return; }
    load();
  }

  // An exercise card changed its item's status: patch it in place, so other cards keep what is typed but not yet ticked
  const patchItem = (r) => r && setState(s => ({ ...s, items: s.items.map(i => i.id === r.id ? { ...i, status: r.status, result_value: r.result_value } : i) }));

  async function saveCheckin(c) {
    const row = { family_id: member.familyId, member_id: memberDb, day, ...c, updated_at: new Date().toISOString() };
    const { error } = await window.sb.from('checkin').upsert(row, { onConflict: 'member_id,day' });
    if (error) { alert('Could not save: ' + error.message); return; }
    load();
  }

  const { items, blocks, events, checkin } = state;
  const actionable = items.filter(i => i.status !== 'draft');
  const done = actionable.filter(i => i.status === 'done').length;
  const pain = checkin && checkin.pain;
  const lighter = checkin && !pain && ((checkin.soreness && checkin.soreness >= 4) || (checkin.sleep_hours != null && checkin.sleep_hours < 8));

  // The day in blocks. On a school day with a timetable (024) the School block is the day's classes;
  // otherwise the plain school schedule block marks the school hours.
  const classes = school.s && school.s.schoolDay && school.s.lessons.length > 0 && window.SchoolBlock ? school.s : null;
  const schoolBlockRow = blocks.find(b => b.kind === 'school');
  const schoolSpan = classes ? { from: toMin(classes.start), to: toMin(classes.end) }
    : schoolBlockRow ? { from: toMin(schoolBlockRow.start_time), to: toMin(schoolBlockRow.end_time) } : null;
  const sporty = [...items.filter(i => i.area === 'physical' && i.start_time), ...blocks.filter(b => SPORT_KINDS.includes(b.kind))];
  const sportFrom = sporty.length ? Math.min(...sporty.map(x => toMin(x.start_time))) : null;
  const sportTo = sporty.length ? Math.max(...sporty.map(x => toMin(x.end_time) || toMin(x.start_time) + 45)) : null;
  const segs = daySegments({ school: schoolSpan, sportFrom, sportTo });
  // Which block (by position) a time falls in; untimed things go to the first afternoon, else the last block
  const segIdx = (t) => { const m = toMin(t);
    if (m == null) { const a = segs.findIndex(x => x.key === 'afternoon'); return a >= 0 ? a : segs.length - 1; }
    if (m < 6 * 60) return 0;
    const i = segs.findIndex(x => m >= x.from && m < x.to); return i >= 0 ? i : segs.length - 1; };
  const segOf = (t) => (segs[segIdx(t)] || {}).key;
  const rows = [
    ...items.filter(i => !(classes && i.area === 'school')).map(i => ({ type: 'item', t: hhmm(i.start_time) || '99:99', i })),
    ...blocks.filter(b => b.kind !== 'school').map(b => ({ type: 'block', t: hhmm(b.start_time), b })),
  ].sort((a, b) => a.t.localeCompare(b.t));
  const inSeg = (idx) => rows.filter(r => segIdx(r.t === '99:99' ? null : r.t) === idx);
  const renderRow = (r) => {
    const blockKey = segOf(r.t === '99:99' ? null : r.t);
    if (r.type === 'block') {
      const sporty = SPORT_KINDS.includes(r.b.kind);
      return <React.Fragment key={'b' + r.b.id}>
        <ContextRow b={r.b} onAdd={canWrite && sporty ? () => addNote({ type: 'schedule', ref: String(r.b.id), block: blockKey,
          label: `${r.b.label} · ${hhmm(r.b.start_time)}` }) : null} />
        {NL && <NL indent notes={notesBySched[r.b.id]} canWrite={canWrite} onToggle={toggleSchoolItem} onEdit={canWrite ? editNote : null} />}
      </React.Fragment>;
    }
    if (r.i.rx && window.ExerciseCard) {
      const k = r.i.rx.key;
      return <React.Fragment key={r.i.id}>
        <window.ExerciseCard item={r.i} memberDb={memberDb} day={day} today={state.sets.today[k]} last={state.sets.last[k]}
          canWrite={canWrite && r.i.status !== 'draft'} blocked={pain} onChanged={patchItem} />
        {NL && <NL indent notes={notesByItem[r.i.id]} canWrite={canWrite} onToggle={toggleSchoolItem} onEdit={canWrite ? editNote : null} />}
      </React.Fragment>;
    }
    return <React.Fragment key={r.i.id}>
      <ItemRow flat item={r.i} open={open === r.i.id} onToggle={() => setOpen(open === r.i.id ? null : r.i.id)}
               canWrite={canWrite && r.i.status !== 'draft'} blocked={pain && r.i.area === 'physical'} onLog={logItem} go={props.go}
               onAddNote={canWrite ? () => addNote({ type: 'plan_item', ref: r.i.id, block: blockKey, label: r.i.title }) : null} />
      {NL && <NL indent notes={notesByItem[r.i.id]} canWrite={canWrite} onToggle={toggleSchoolItem} onEdit={canWrite ? editNote : null} />}
    </React.Fragment>;
  };
  const SP = window.SchoolParts || {};
  const hour = new Date().getHours();

  // Notes (026): each lands where it is attached — a plan item, a sports session, a block — with sensible fallbacks
  const segKeys = new Set(segs.map(g => g.key));
  const home = (k) => segKeys.has(k) ? k : segKeys.has('afternoon') ? 'afternoon' : 'evening';
  const dayNotes = (school.s && school.s.dayNotes) || [];
  const lessonUsed = (school.s && school.s.usedIds) || new Set();
  const notesByItem = {}, notesBySched = {}, notesByBlock = { morning: [], school: [], afternoon: [], sports: [], evening: [] };
  const push = (m, k, n) => { (m[k] = m[k] || []).push(n); };
  dayNotes.forEach(n => {
    if (n.anchor_type === 'lesson') {                       // the School block shows these; without classes today they go to the afternoon
      if (!classes && n.kind !== 'bring') push(notesByBlock, home('afternoon'), n);
      return;
    }
    if (n.anchor_type === 'block' && n.anchor_ref === 'school') { if (!classes) push(notesByBlock, home('afternoon'), n); return; }
    if (n.anchor_type === 'plan_item' && items.some(i => i.id === n.anchor_ref)) return push(notesByItem, n.anchor_ref, n);
    if (n.anchor_type === 'schedule' && blocks.some(b => String(b.id) === String(n.anchor_ref))) return push(notesBySched, n.anchor_ref, n);
    if (n.anchor_type === 'block') return push(notesByBlock, home(n.anchor_ref), n);
    if (n.anchor_type === 'day') return push(notesByBlock, home('morning'), n);
    push(notesByBlock, home(n.block || 'afternoon'), n);
  });
  const NL = window.NoteList;

  const dateLabel = new Date(day + 'T12:00:00');
  return (
    <div style={{ maxWidth: 640, margin: '0 auto', padding: '20px 16px 120px', fontFamily: 'var(--font-sans)' }}>
      {isAdmin && kids.length > 1 && !props.memberDb && (
        <div style={{ marginBottom: 14 }}>
          <Segmented options={kids.map(k => ({ value: k.db_id, label: k.name }))} value={memberDb} onChange={setMemberDb} />
        </div>
      )}

      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 }}>
        <button onClick={() => setDay(addDaysI(day, -1))} style={navBtn}>‹</button>
        <div style={{ flex: 1, textAlign: 'center' }}>
          <Eyebrow>{isToday ? 'Today' : day === addDaysI(ymdI(new Date()), 1) ? 'Tomorrow' : day === addDaysI(ymdI(new Date()), -1) ? 'Yesterday' : ''}</Eyebrow>
          <div style={{ fontSize: 20, fontWeight: 500, marginTop: 2 }}>
            {WEEKDAYS[(dateLabel.getDay() + 6) % 7]} {dateLabel.getDate()} {dateLabel.toLocaleString('en-GB', { month: 'short' })}
          </div>
        </div>
        <button onClick={() => setDay(addDaysI(day, 1))} style={navBtn}>›</button>
      </div>
      {!isToday && <div style={{ textAlign: 'center', marginBottom: 10 }}>
        <button onClick={() => setDay(ymdI(new Date()))} style={{ ...linkBtn }}>Back to today</button></div>}

      {!state.loading && items.length > 0 && <HabitsStrip habits={window.PlanAPI.habitsFor({ items, checkin })} />}

      {events.length > 0 && (
        <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', justifyContent: 'center', margin: '8px 0 12px' }}>
          {events.map(e => <Pill key={e.id}>{e.label}</Pill>)}
        </div>
      )}

      {state.error && <Card pad={16} style={{ borderColor: 'var(--danger)', marginBottom: 12 }}>Something went wrong: {state.error}</Card>}

      {pain && <Banner tone="danger">Something hurts: no physical training today. Tell Mum or Dad.</Banner>}
      {lighter && <Banner tone="warning">Tired or sore today: swap strength for mobility and take it easy.</Banner>}
      {!classes && window.SchoolCard && memberDb && <window.SchoolCard s={school.s} tomorrow={school.tomorrow} reload={loadSchool}
        memberDb={memberDb} day={day} canWrite={canWrite} isToday={isToday} />}

      {actionable.length > 0 && (
        <div style={{ margin: '14px 0 6px', fontSize: 13, color: 'var(--fg-muted)' }}>
          {done} of {actionable.length} done
          <div style={{ height: 4, background: 'var(--ink-100)', borderRadius: 2, marginTop: 6 }}>
            <div style={{ height: 4, width: `${actionable.length ? (100 * done / actionable.length) : 0}%`, background: 'var(--success)', borderRadius: 2 }} />
          </div>
        </div>
      )}

      {state.loading && <div style={{ color: 'var(--fg-muted)', padding: 24, textAlign: 'center' }}>Loading…</div>}
      {!state.loading && items.length === 0 && (
        <div style={{ textAlign: 'center', color: 'var(--fg-muted)', fontSize: 13, margin: '6px 0' }}>No training plan for this day yet.</div>
      )}

      {!state.loading && <div style={{ marginTop: 10 }}>
        {segs.map((g, n) => {
          const until = fromMin(Math.min(g.to, 24 * 60 - 1));
          if (g.key === 'school') {
            if (!classes) return <DayBlock key="school" title="School" from={fromMin(g.from)} until={until} accent="var(--signal)"
              onAdd={canWrite ? () => addNote({ type: 'block', ref: 'school', block: 'school', label: 'School' }) : null}>
              {schoolBlockRow && <ContextRow b={schoolBlockRow} />}{inSeg(n).map(renderRow)}</DayBlock>;
            return <window.SchoolBlock key="school" s={classes} isToday={isToday} canWrite={canWrite} onToggle={toggleSchoolItem}
              memberDb={memberDb} day={day} reload={loadSchool} onAdd={addNote} onEdit={canWrite ? editNote : null}>{inSeg(n).map(renderRow)}</window.SchoolBlock>;
          }
          const mine = inSeg(n);
          const firstOfKind = segs.findIndex(x => x.key === g.key) === n;   // block notes and extras go in the first block of that name
          const morning = g.key === 'morning', afternoon = g.key === 'afternoon' && firstOfKind, evening = g.key === 'evening';
          const checkinHere = morning && ((isToday && canWrite && !checkin) || checkin);
          const pack = morning && SP.MorningPack && <SP.MorningPack s={classes} canWrite={canWrite} onToggle={toggleSchoolItem} />;
          const due = afternoon && SP.DueSoon && classes && <SP.DueSoon s={school.s} day={day} canWrite={canWrite} onToggle={toggleSchoolItem} />;
          const tomorrowPack = evening && SP.PackTomorrow && <SP.PackTomorrow tomorrow={school.tomorrow} day={day} />;
          const blockNotes = firstOfKind ? notesByBlock[g.key] || [] : [];
          const hasExtra = blockNotes.length || checkinHere || (morning && classes && classes.bring.length) || (afternoon && school.s && school.s.todo && school.s.todo.length)
            || (evening && school.tomorrow && school.tomorrow.schoolDay && (school.tomorrow.bring.length || school.tomorrow.tests.length));
          const B = BLOCK[g.key];
          if (!mine.length && !hasExtra && !canWrite) return null;
          return (
            <DayBlock key={g.key + n} title={B.title} from={fromMin(g.from)} until={g.to < 24 * 60 ? until : null} accent={B.accent}
              onAdd={canWrite ? () => addNote({ type: 'block', ref: g.key, block: g.key, label: B.title }) : null}>
              {NL && <NL notes={blockNotes} canWrite={canWrite} onToggle={toggleSchoolItem} onEdit={canWrite ? editNote : null} />}
              {morning && isToday && canWrite && !checkin && <CheckinCard flat onSave={saveCheckin} />}
              {morning && checkin && <CheckinSummary c={checkin} />}
              {pack}
              {mine.map(renderRow)}
              {due}
              {tomorrowPack}
            </DayBlock>
          );
        })}
      </div>}

      {sheet && window.NoteSheet && <window.NoteSheet anchor={sheet.anchor} note={sheet.note} day={day} memberDb={memberDb} isAdmin={isAdmin}
        onClose={() => setSheet(null)} onSaved={loadSchool} />}
      {isToday && canWrite && window.RestBar && items.some(i => i.rx) && <><div style={{ height: 64 }} /><window.RestBar /></>}
    </div>
  );
}

function HabitsStrip({ habits }) {
  const H = window.PlanAPI.HABITS.filter(h => habits[h.key] !== null && habits[h.key] !== undefined);
  if (!H.length) return null;
  return (
    <div style={{ display: 'flex', justifyContent: 'center', gap: 14, margin: '10px 0 4px', flexWrap: 'wrap' }}>
      {H.map(h => (
        <div key={h.key} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4, minWidth: 54 }}>
          <div style={{ width: 14, height: 14, borderRadius: 7, border: '2px solid var(--success)',
                        background: habits[h.key] ? 'var(--success)' : 'transparent' }} />
          <div style={{ fontSize: 10, color: 'var(--fg-subtle)', letterSpacing: '0.04em' }}>{h.label}</div>
        </div>
      ))}
    </div>
  );
}

function ContextRow({ b, onAdd }) {
  return (
    <div onClick={onAdd || undefined} style={{ display: 'flex', gap: 12, padding: '6px 0', color: 'var(--fg-muted)', fontSize: 14,
         borderTop: '1px solid var(--border)', cursor: onAdd ? 'pointer' : 'default' }}>
      <div style={{ width: 44, fontFamily: 'var(--font-mono)', fontSize: 12, paddingTop: 1 }}>{hhmm(b.start_time)}</div>
      <div style={{ flex: 1 }}>{b.label}</div>
    </div>
  );
}

function ItemRow({ item, open, onToggle, canWrite, blocked, onLog, go, flat, onAddNote }) {
  const [val, setVal] = useStateI('');
  const isDone = item.status === 'done';
  const isSkipped = item.status === 'skipped';
  const isChanged = item.status === 'changed';
  const closed = isDone || isSkipped || isChanged;
  const L = item.ladder;
  return (
    <div style={flat ? { borderTop: '1px solid var(--border)', background: closed ? 'var(--ink-25)' : 'transparent', margin: '0 -12px', padding: '0 12px' } : {
      border: '1px solid var(--border)', borderRadius: 8, marginBottom: 8, background: closed ? 'var(--ink-25)' : 'var(--bg-raised)',
      borderLeft: `3px solid ${item.is_checkpoint ? 'var(--warning)' : isDone ? 'var(--success)' : 'var(--border-strong)'}`,
    }}>
      <button onClick={onToggle} style={{ all: 'unset', cursor: 'pointer', display: 'flex', gap: 12, padding: flat ? '8px 0' : '12px 12px', width: flat ? '100%' : 'calc(100% - 24px)' }}>
        <div style={{ width: 44, fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--fg-muted)', paddingTop: 2 }}>{hhmm(item.start_time)}</div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 11, color: 'var(--fg-subtle)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>
            {AREA_LABEL[item.area] || ''}{item.is_checkpoint ? ' · test' : ''}
          </div>
          <div style={{ fontSize: 15, fontWeight: 500, textDecoration: isSkipped ? 'line-through' : 'none', color: closed ? 'var(--fg-muted)' : 'var(--fg)' }}>
            {item.title}
          </div>
          {item.dose && <div style={{ fontSize: 13, color: 'var(--fg-muted)', marginTop: 2 }}>{item.dose}</div>}
          {L && <div style={{ fontSize: 12, color: 'var(--signal)', marginTop: 4 }}>
            {L.name}{L.step ? ` · step ${L.step} of ${L.of}` : ''}
          </div>}
          {isChanged && item.rule_note && <div style={{ fontSize: 12, color: 'var(--warning)', marginTop: 4 }}>{item.rule_note}</div>}
        </div>
        <div style={{ fontSize: 18, color: isDone ? 'var(--success)' : 'var(--fg-faint)' }}>{isDone ? '✓' : isSkipped ? '–' : ''}</div>
      </button>
      {open && (
        <div style={{ padding: flat ? '0 0 10px 56px' : '0 12px 12px 68px', fontSize: 13, color: 'var(--fg-muted)' }}>
          {item.effort && <div><strong>Effort:</strong> {item.effort}</div>}
          {item.cue && <div style={{ marginTop: 4 }}><strong>Remember:</strong> {item.cue}</div>}
          {item.detail && <div style={{ marginTop: 4 }}>{item.detail}</div>}
          {item.result_value != null && <div style={{ marginTop: 4 }}><strong>Result:</strong> {item.result_value}</div>}
          {L && L.passResult && <div style={{ marginTop: 4 }}><strong>To move up:</strong> {L.passResult}</div>}
          {L && go && <button onClick={() => go('progress', 'ladder:' + L.id)} style={{ ...linkBtn, marginTop: 6 }}>See the whole ladder →</button>}
          {onAddNote && <div><button onClick={onAddNote} style={{ ...linkBtn, marginTop: 6 }}>+ Add a note or task</button></div>}
        </div>
      )}
      {canWrite && !closed && (
        <div style={{ display: 'flex', gap: 8, padding: flat ? '0 0 10px 56px' : '0 12px 12px 68px', alignItems: 'center' }}>
          {blocked
            ? <Button kind="secondary" size="sm" onClick={() => onLog(item, 'skipped')}>Skip (it hurts)</Button>
            : <>
                {item.is_checkpoint && (
                  <input inputMode="decimal" placeholder="Result" value={val} onChange={e => setVal(e.target.value)}
                         style={{ width: 90, padding: '6px 8px', border: '1px solid var(--border-strong)', borderRadius: 6, fontSize: 14 }} />
                )}
                <Button size="sm" onClick={() => onLog(item, 'done', item.is_checkpoint && val !== '' ? Number(String(val).replace(',', '.')) : null)}>Done</Button>
                <Button kind="ghost" size="sm" onClick={() => onLog(item, 'skipped')}>Skip</Button>
              </>}
        </div>
      )}
      {canWrite && closed && !isChanged && (
        <div style={{ padding: flat ? '0 0 8px 56px' : '0 12px 10px 68px' }}>
          <button onClick={() => onLog(item, 'released')} style={linkBtn}>Undo</button>
        </div>
      )}
    </div>
  );
}

function CheckinCard({ onSave, flat }) {
  const [sleep, setSleep] = useStateI(9);
  const [energy, setEnergy] = useStateI(null);
  const [sore, setSore] = useStateI(null);
  const [pain, setPain] = useStateI(false);
  const [where, setWhere] = useStateI('');
  const scale = [1, 2, 3, 4, 5].map(n => ({ value: n, label: String(n) }));
  const ready = energy && sore && (!pain || where.trim());
  const body = (
    <>
      <Eyebrow>Morning check-in — 10 seconds</Eyebrow>
      <Row label="Sleep last night">
        <button style={stepBtn} onClick={() => setSleep(Math.max(4, sleep - 0.5))}>−</button>
        <span style={{ width: 56, textAlign: 'center', fontSize: 16 }}>{sleep} h</span>
        <button style={stepBtn} onClick={() => setSleep(Math.min(13, sleep + 0.5))}>+</button>
      </Row>
      <Row label="Energy (1 = empty, 5 = full)"><Segmented options={scale} value={energy} onChange={setEnergy} size="sm" /></Row>
      <Row label="Muscle soreness (1 = none, 5 = a lot)"><Segmented options={scale} value={sore} onChange={setSore} size="sm" /></Row>
      <Row label="Does anything hurt?">
        <Segmented options={[{ value: false, label: 'No' }, { value: true, label: 'Yes' }]} value={pain} onChange={setPain} size="sm" />
      </Row>
      {pain && <input placeholder="Where does it hurt?" value={where} onChange={e => setWhere(e.target.value)}
                      style={{ width: '100%', boxSizing: 'border-box', padding: '8px 10px', border: '1px solid var(--border-strong)', borderRadius: 6, fontSize: 14, marginTop: 8 }} />}
      <div style={{ marginTop: 12 }}>
        <Button disabled={!ready} onClick={() => onSave({ sleep_hours: sleep, energy, soreness: sore, pain, pain_where: pain ? where.trim() : null })}>Save</Button>
      </div>
    </>
  );
  return flat ? <div style={{ borderTop: '1px solid var(--border)', padding: '8px 0 10px', marginTop: 4 }}>{body}</div>
    : <Card pad={16} style={{ marginBottom: 12 }}>{body}</Card>;
}

function CheckinSummary({ c }) {
  return (
    <div style={{ fontSize: 12, color: 'var(--fg-muted)', padding: '6px 0 6px 56px', borderTop: '1px solid var(--border)', marginTop: 4 }}>
      ✓ Check-in: sleep {c.sleep_hours} h · energy {c.energy}/5 · soreness {c.soreness}/5{c.pain ? ` · hurts: ${c.pain_where || 'yes'}` : ''}
    </div>
  );
}

function Row({ label, children }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12, marginTop: 10, flexWrap: 'wrap' }}>
      <div style={{ fontSize: 14 }}>{label}</div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>{children}</div>
    </div>
  );
}

function Banner({ tone, children }) {
  const c = tone === 'danger' ? 'var(--danger)' : 'var(--warning)';
  const bg = tone === 'danger' ? 'var(--danger-tint)' : 'var(--warning-tint)';
  return <div style={{ border: `1px solid ${c}`, background: bg, borderRadius: 8, padding: '10px 12px', fontSize: 14, margin: '8px 0' }}>{children}</div>;
}

const navBtn = { width: 40, height: 40, borderRadius: 20, border: '1px solid var(--border)', background: 'var(--bg-raised)', fontSize: 20, cursor: 'pointer', color: 'var(--fg)' };
const stepBtn = { width: 32, height: 32, borderRadius: 16, border: '1px solid var(--border-strong)', background: 'var(--bg-raised)', fontSize: 18, cursor: 'pointer', color: 'var(--fg)' };
const linkBtn = { background: 'none', border: 'none', color: 'var(--signal)', cursor: 'pointer', fontSize: 13, padding: 0 };

window.IdagScreen = IdagScreen;
