// PrepScreen.jsx — Daily Prep List
// Minimal Apple-inspired. Neutral surfaces, ink accents.
// Three interaction variants (Tweaks): stepper / tap / numpad sheet

const { useState: usePrep, useMemo: useMemoPrep, useRef: useRefPrep, useEffect: useEffectPrep } = React;

// ------------------------------------------------------------------
// Header
// ------------------------------------------------------------------
const PrepHeader = ({ onBack, items, progress, filter, setFilter, interactionMode, setInteractionMode, picIds = [], onOpenAssign, onAddItem }) => {
  const total = items.length;
  const completedCount = items.filter(it => {
    const q = (progress[it.id] || []).reduce((s, e) => s + e.qty, 0);
    return q >= it.target;
  }).length;

  const pics = picIds.map(id => window.SAMPLE_STAFF.find(s => s.id === id)).filter(Boolean);

  return (
    <div style={{
      padding: '16px 24px',
      background: 'var(--bg-surface)',
      borderBottom: '1px solid var(--border-1)',
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 20 }}>
        {/* Title block */}
        <div style={{ minWidth: 0, flexShrink: 0 }}>
          <div style={{ fontSize: 11, color: 'var(--fg-3)', fontWeight: 500, letterSpacing: '0.06em', textTransform: 'uppercase' }}>
            Today · {new Date().toLocaleDateString('en-US', { weekday: 'long' })}
          </div>
          <div style={{ fontSize: 22, fontWeight: 600, letterSpacing: '-0.02em', color: 'var(--fg-1)', marginTop: 2, lineHeight: 1.1 }}>Daily Prep</div>
        </div>

        {/* Divider */}
        <div style={{ width: 1, alignSelf: 'stretch', background: 'var(--border-1)' }} />

        {/* PIC chips — inline */}
        <div style={{ flex: 1, minWidth: 0, display: 'flex', alignItems: 'center', gap: 8 }}>
          <div style={{
            fontSize: 10, fontWeight: 500, letterSpacing: '0.08em',
            color: 'var(--fg-3)', textTransform: 'uppercase',
            flexShrink: 0,
          }}>PIC</div>
          <div style={{ flex: 1, display: 'flex', flexWrap: 'wrap', gap: 6, alignItems: 'center', minWidth: 0 }}>
            {pics.length === 0 ? (
              <span style={{ fontSize: 13, color: 'var(--fg-3)' }}>Unassigned</span>
            ) : pics.map(s => (
              <span key={s.id} style={{
                fontSize: 13, fontWeight: 500, color: 'var(--fg-1)',
                padding: '3px 10px',
                background: 'var(--bg-sunken)',
                borderRadius: 999,
                letterSpacing: '-0.005em',
              }}>{s.name}</span>
            ))}
          </div>
          <button onClick={onOpenAssign} style={{
            fontSize: 12, fontWeight: 500, color: 'var(--fg-2)',
            padding: '4px 10px',
            background: '#FFFFFF',
            border: '1px solid var(--border-1)',
            borderRadius: 999,
            display: 'inline-flex', alignItems: 'center', gap: 4,
            cursor: 'pointer',
            flexShrink: 0,
          }}>
            <Icon name="edit" size={12} strokeWidth={2} color="var(--fg-2)" />
            Edit
          </button>
        </div>

        {/* Divider */}
        <div style={{ width: 1, alignSelf: 'stretch', background: 'var(--border-1)' }} />

        {/* Done counter */}
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, flexShrink: 0 }}>
          <div style={{ fontSize: 10, fontWeight: 500, letterSpacing: '0.06em', color: 'var(--fg-3)', textTransform: 'uppercase' }}>
            Done
          </div>
          <div style={{ fontSize: 22, fontWeight: 600, fontFamily: 'var(--font-num)', letterSpacing: '-0.02em', color: 'var(--fg-1)', lineHeight: 1 }}>
            {completedCount}<span style={{ color: 'var(--fg-3)', fontWeight: 500 }}>/{total}</span>
          </div>
        </div>

        {/* Add item */}
        <button
          onClick={onAddItem}
          aria-label="Set today's prep targets"
          style={{
            flexShrink: 0,
            width: 36, height: 36,
            borderRadius: 999,
            background: 'var(--fg-1)',
            border: 'none',
            color: '#FFFFFF',
            display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
            cursor: 'pointer',
            boxShadow: '0 1px 2px rgba(0,0,0,0.06)',
            transition: 'transform 120ms var(--ease-snap), background 120ms var(--ease-snap)',
          }}
          onMouseEnter={e => { e.currentTarget.style.background = '#000'; }}
          onMouseLeave={e => { e.currentTarget.style.background = 'var(--fg-1)'; }}
          onMouseDown={e => { e.currentTarget.style.transform = 'scale(0.94)'; }}
          onMouseUp={e => { e.currentTarget.style.transform = ''; }}
        >
          <Icon name="plus" size={16} color="#FFFFFF" strokeWidth={2.4} />
        </button>
      </div>
    </div>
  );
};

// ------------------------------------------------------------------
// Filter pill row (sits inside the scroll / list area, not in the header)
// ------------------------------------------------------------------
const PrepFilterPills = ({ items, progress, filter, setFilter }) => {
  const primaryLeft = items.filter(it => {
    if (it.priority !== 'primary') return false;
    const q = (progress[it.id] || []).reduce((s, e) => s + e.qty, 0);
    return q < it.target;
  }).length;
  const secondaryLeft = items.filter(it => {
    if (it.priority !== 'secondary') return false;
    const q = (progress[it.id] || []).reduce((s, e) => s + e.qty, 0);
    return q < it.target;
  }).length;
  const doneCount = items.filter(it => {
    const q = (progress[it.id] || []).reduce((s, e) => s + e.qty, 0);
    return q >= it.target;
  }).length;
  const tabs = [
    { k: 'All', count: null },
    { k: 'Primary', count: primaryLeft },
    { k: 'Secondary', count: secondaryLeft },
    { k: 'Done', count: doneCount },
  ];
  return (
    <div style={{ display: 'flex', alignItems: 'stretch', gap: 6, marginBottom: 16 }}>
      {tabs.map(({ k, count }) => {
        const active = filter === k;
        return (
          <button key={k} onClick={() => setFilter(k)} style={{
            flex: 1,
            height: 36, padding: '0 12px',
            borderRadius: 999,
            background: active ? 'var(--fg-1)' : '#FFFFFF',
            color: active ? '#FFFFFF' : 'var(--fg-2)',
            fontSize: 13, fontWeight: 500,
            border: active ? '1px solid var(--fg-1)' : '1px solid var(--border-1)',
            display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 7,
            cursor: 'pointer',
          }}>
            {k}
            {count !== null && (
              <span style={{
                minWidth: 20, height: 20, padding: '0 6px',
                borderRadius: 999,
                background: active ? 'rgba(255,255,255,0.22)' : 'var(--bg-sunken)',
                color: active ? '#fff' : 'var(--fg-2)',
                fontSize: 11, fontWeight: 600, fontFamily: 'var(--font-num)',
                display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                lineHeight: 1,
              }}>{count}</span>
            )}
          </button>
        );
      })}
    </div>
  );
};

// ------------------------------------------------------------------
// Item progress
// ------------------------------------------------------------------
const ItemProgress = ({ item, entries }) => {
  const total = entries.reduce((s, e) => s + e.qty, 0);
  const pct = Math.min(100, (total / item.target) * 100);
  const done = total >= item.target;
  return (
    <>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 4 }}>
        <span style={{
          fontSize: 22, fontWeight: 500, fontFamily: 'var(--font-num)',
          color: 'var(--fg-1)',
          letterSpacing: '-0.02em',
        }}>{total}</span>
        <span style={{ fontSize: 13, color: 'var(--fg-3)', fontWeight: 400 }}>/ {item.target}</span>
      </div>
      <div style={{ marginTop: 6, width: '100%' }}>
        <ProgressBar pct={pct} height={3} color={done ? 'var(--fg-1)' : 'var(--fg-2)'} bg="var(--border-1)" />
      </div>
    </>
  );
};

// ------------------------------------------------------------------
// Entry chips
// ------------------------------------------------------------------
const EntryChips = ({ entries, onRemove }) => (
  <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginTop: 10 }}>
    {entries.length === 0 && (
      <span style={{ fontSize: 12, color: 'var(--fg-3)' }}>No entries yet</span>
    )}
    {entries.map((e, i) => {
      const s = window.SAMPLE_STAFF.find(x => x.id === e.staffId);
      if (!s) return null;
      return (
        <div key={i} style={{
          display: 'inline-flex', alignItems: 'center', gap: 6,
          padding: '3px 8px 3px 3px',
          background: 'var(--bg-sunken)', borderRadius: 999,
          fontSize: 12, fontWeight: 500, color: 'var(--fg-2)',
        }}>
          <Avatar staff={s} size={18} />
          <span><span style={{ fontWeight: 600, color: 'var(--fg-1)' }}>{e.qty}</span> · {e.ts}</span>
          {onRemove && (
            <button onClick={() => onRemove(i)} style={{
              width: 16, height: 16, borderRadius: 999,
              display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
              color: 'var(--fg-3)',
            }}>
              <Icon name="x" size={10} strokeWidth={2} />
            </button>
          )}
        </div>
      );
    })}
  </div>
);

// ------------------------------------------------------------------
// Variant D: Table row (dense)
// ------------------------------------------------------------------
const TABLE_GRID = '1.3fr 180px 100px 88px';

// ------------------------------------------------------------------
// Contributor avatars — shown in the progress cell
// Aggregates entries by staffId → renders tiny avatar with qty badge
// ------------------------------------------------------------------
const ContributorAvatars = ({ entries }) => {
  if (!entries || entries.length === 0) return null;
  const byStaff = {};
  entries.forEach(e => { byStaff[e.staffId] = (byStaff[e.staffId] || 0) + e.qty; });
  const contribs = Object.entries(byStaff)
    .map(([id, qty]) => ({ staff: window.SAMPLE_STAFF.find(s => s.id === id), qty }))
    .filter(c => c.staff);
  const max = 3;
  const shown = contribs.slice(0, max);
  const rest = contribs.length - max;
  return (
    <div style={{ display: 'inline-flex', alignItems: 'center', gap: 3 }}>
      {shown.map(({ staff, qty }) => (
        <div key={staff.id} style={{ position: 'relative', width: 22, height: 22 }} title={`${staff.name}: ${qty}`}>
          <Avatar staff={staff} size={22} />
          <div style={{
            position: 'absolute', right: -4, bottom: -4,
            minWidth: 14, height: 14, padding: '0 3px',
            background: '#FFFFFF',
            border: '1.5px solid var(--bg-surface)',
            borderRadius: 999,
            fontSize: 9, fontWeight: 600, fontFamily: 'var(--font-num)',
            color: 'var(--fg-1)',
            display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
            lineHeight: 1,
            boxShadow: '0 0 0 1px var(--border-2)',
          }}>{qty}</div>
        </div>
      ))}
      {rest > 0 && (
        <div style={{
          width: 22, height: 22, borderRadius: 999,
          background: 'var(--bg-sunken)',
          border: '1px solid var(--border-1)',
          fontSize: 10, fontWeight: 600, color: 'var(--fg-2)',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
        }}>+{rest}</div>
      )}
    </div>
  );
};

const TableHeader = ({ category, count }) => (
  <div style={{
    display: 'grid',
    gridTemplateColumns: TABLE_GRID,
    gap: 16,
    padding: '10px 14px',
    background: 'var(--bg-sunken)',
    borderTopLeftRadius: 12, borderTopRightRadius: 12,
    border: '1px solid var(--border-1)',
    borderBottom: '1px solid var(--border-2)',
    fontSize: 10, fontWeight: 500, letterSpacing: '0.06em',
    color: 'var(--fg-3)', textTransform: 'uppercase',
    alignItems: 'center',
  }}>
    <div style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>
      <span style={{ color: 'var(--fg-1)', fontWeight: 600, letterSpacing: '0.08em' }}>{category}</span>
      <span style={{ color: 'var(--fg-3)', fontWeight: 500, fontSize: 10 }}>{count} item{count !== 1 ? 's' : ''}</span>
    </div>
    <div>Progress</div>
    <div style={{ textAlign: 'right' }}>Team</div>
    <div style={{ textAlign: 'right' }}>Action</div>
  </div>
);

const TableRow = ({ item, entries, onTap, isLast }) => {
  const total = entries.reduce((s, e) => s + e.qty, 0);
  const done = total >= item.target;
  const pct = Math.min(100, (total / item.target) * 100);
  const [hover, setHover] = usePrep(false);
  return (
    <div
      onClick={() => onTap(item)}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{
        display: 'grid',
        gridTemplateColumns: TABLE_GRID,
        gap: 16,
        alignItems: 'center',
        padding: '12px 14px',
        borderLeft: '1px solid var(--border-1)',
        borderRight: '1px solid var(--border-1)',
        borderBottom: isLast ? '1px solid var(--border-1)' : '1px solid var(--border-2)',
        borderBottomLeftRadius: isLast ? 12 : 0,
        borderBottomRightRadius: isLast ? 12 : 0,
        background: hover ? 'var(--bg-sunken)' : 'var(--bg-surface)',
        cursor: 'pointer',
        transition: 'background 120ms var(--ease-snap)',
      }}
    >
      <div style={{ minWidth: 0 }}>
        <div style={{
          fontSize: 14, fontWeight: 500, letterSpacing: '-0.005em',
          color: done ? 'var(--fg-3)' : 'var(--fg-1)',
          textDecoration: done ? 'line-through' : 'none',
          whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
        }}>
          {item.name}
        </div>
        {item.note && (
          <div style={{
            fontSize: 11, color: 'var(--fg-3)', marginTop: 2, fontStyle: 'italic',
            whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
          }}>“{item.note}”</div>
        )}
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 5, alignItems: 'stretch', minWidth: 0 }}>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 3, justifyContent: 'flex-start' }}>
          <span style={{ fontSize: 15, fontWeight: 500, fontFamily: 'var(--font-num)', color: 'var(--fg-1)', letterSpacing: '-0.01em' }}>{total}</span>
          <span style={{ fontSize: 11, color: 'var(--fg-3)', fontWeight: 400 }}>/{item.target}</span>
        </div>
        <ProgressBar pct={pct} height={3} color={done ? 'var(--fg-1)' : 'var(--fg-2)'} bg="var(--border-1)" />
      </div>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end', minHeight: 22 }}>
        <ContributorAvatars entries={entries} />
      </div>
      <div style={{ justifySelf: 'end' }}>
        <button
          onClick={(e) => { e.stopPropagation(); onTap(item); }}
          style={{
            display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
            padding: '8px 18px',
            background: done ? 'transparent' : (hover ? 'var(--fg-1)' : '#FFFFFF'),
            color: done ? 'var(--fg-2)' : (hover ? '#FFFFFF' : 'var(--fg-1)'),
            border: '1px solid ' + (done ? 'var(--border-1)' : (hover ? 'var(--fg-1)' : 'var(--border-2)')),
            borderRadius: 8,
            fontSize: 13, fontWeight: 500,
            cursor: 'pointer',
            transition: 'all 120ms var(--ease-snap)',
          }}
        >
          Log
        </button>
      </div>
    </div>
  );
};

// ------------------------------------------------------------------
// Variant A: Stepper row
// ------------------------------------------------------------------
const StepperRow = ({ item, entries, onContribute, currentStaff }) => {
  const total = entries.reduce((s, e) => s + e.qty, 0);
  const done = total >= item.target;
  const remaining = Math.max(0, item.target - total);
  const [pendingDelta, setPendingDelta] = usePrep(0);
  const [pickerOpen, setPickerOpen] = usePrep(false);

  const commit = (staff) => {
    if (pendingDelta !== 0) onContribute(staff, pendingDelta);
    setPendingDelta(0);
    setPickerOpen(false);
  };

  return (
    <div style={{
      display: 'flex', gap: 20, padding: 16,
      background: 'var(--bg-surface)', borderRadius: 14,
      border: '1px solid var(--border-1)',
      alignItems: 'center',
    }}>
      <div style={{ flex: '0 0 200px' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 4 }}>
          <CategoryChip category={item.category} small />
          <PriorityPill priority={item.priority} small />
        </div>
        <div style={{ fontSize: 15, fontWeight: 500, letterSpacing: '-0.005em', color: done ? 'var(--fg-3)' : 'var(--fg-1)', textDecoration: done ? 'line-through' : 'none' }}>
          {item.name}
        </div>
        {item.note && (
          <div style={{ fontSize: 12, color: 'var(--fg-3)', marginTop: 3, fontStyle: 'italic' }}>“{item.note}”</div>
        )}
      </div>
      <div style={{ flex: '0 0 170px' }}>
        <ItemProgress item={item} entries={entries} />
      </div>
      <div style={{ flex: 1 }}>
        <EntryChips entries={entries} />
      </div>
      <div style={{
        display: 'flex', alignItems: 'center', gap: 2,
        background: 'var(--bg-sunken)', borderRadius: 10, padding: 3,
      }}>
        <button onClick={() => setPendingDelta(d => Math.max(d - 1, -total))} className="tap" style={{
          width: 36, height: 36, borderRadius: 8,
          background: '#FFFFFF', color: 'var(--fg-1)',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <Icon name="minus" size={16} strokeWidth={1.8} color="var(--fg-1)" />
        </button>
        <div style={{
          minWidth: 48, textAlign: 'center',
          fontSize: 17, fontWeight: 500, fontFamily: 'var(--font-num)',
          color: pendingDelta !== 0 ? 'var(--fg-1)' : 'var(--fg-3)',
        }}>
          {pendingDelta > 0 ? '+' : ''}{pendingDelta || 0}
        </div>
        <button onClick={() => setPendingDelta(d => d + 1)} disabled={pendingDelta >= remaining} className="tap" style={{
          width: 36, height: 36, borderRadius: 8,
          background: pendingDelta >= remaining ? 'var(--bg-sunken)' : '#FFFFFF',
          opacity: pendingDelta >= remaining ? 0.4 : 1,
          cursor: pendingDelta >= remaining ? 'not-allowed' : 'pointer',
          color: 'var(--fg-1)',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <Icon name="plus" size={16} strokeWidth={1.8} color="var(--fg-1)" />
        </button>
      </div>
      <Btn
        variant={pendingDelta !== 0 ? 'primary' : 'secondary'}
        size="md"
        disabled={pendingDelta === 0}
        onClick={() => setPickerOpen(true)}
      >
        Sign
      </Btn>
      <StaffPicker
        open={pickerOpen}
        onClose={() => setPickerOpen(false)}
        onPick={commit}
        title={`Who made ${pendingDelta > 0 ? '+' : ''}${pendingDelta} of ${item.name}?`}
      />
    </div>
  );
};

// ------------------------------------------------------------------
// Variant B: Tap card
// ------------------------------------------------------------------
const TapCard = ({ item, entries, onContribute }) => {
  const total = entries.reduce((s, e) => s + e.qty, 0);
  const done = total >= item.target;
  const pct = Math.min(100, (total / item.target) * 100);
  const [pickerOpen, setPickerOpen] = usePrep(false);
  const [pending, setPending] = usePrep(0);

  const handleTap = () => {
    setPending(1);
    setPickerOpen(true);
  };
  const commit = (staff) => {
    onContribute(staff, pending);
    setPickerOpen(false);
  };

  return (
    <div style={{
      background: 'var(--bg-surface)',
      borderRadius: 14,
      border: '1px solid var(--border-1)',
      overflow: 'hidden',
      display: 'flex', flexDirection: 'column',
      position: 'relative',
    }}>
      <div style={{ padding: 16, position: 'relative' }}>
        <div style={{ display: 'flex', gap: 6, marginBottom: 6 }}>
          <CategoryChip category={item.category} small />
          <PriorityPill priority={item.priority} small />
        </div>
        <div style={{ fontSize: 15, fontWeight: 500, color: done ? 'var(--fg-3)' : 'var(--fg-1)', letterSpacing: '-0.005em', textDecoration: done ? 'line-through' : 'none' }}>
          {item.name}
        </div>
        {item.note && (
          <div style={{ fontSize: 12, color: 'var(--fg-3)', marginTop: 3, fontStyle: 'italic' }}>“{item.note}”</div>
        )}
        <div style={{ marginTop: 10 }}>
          <ItemProgress item={item} entries={entries} />
        </div>
        <EntryChips entries={entries} />
      </div>
      <div style={{
        display: 'flex', gap: 1,
        borderTop: '1px solid var(--border-1)',
        background: 'var(--border-2)',
      }}>
        <button onClick={handleTap} disabled={done} style={{
          flex: 1, padding: '12px 0',
          background: 'var(--bg-surface)',
          color: done ? 'var(--fg-3)' : 'var(--fg-1)',
          fontSize: 14, fontWeight: 500,
          opacity: done ? 0.5 : 1,
          cursor: done ? 'not-allowed' : 'pointer',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 6,
        }}>
          <Icon name="plus" size={14} strokeWidth={1.8} color={done ? 'var(--fg-3)' : 'var(--fg-1)'} />
          {done ? 'Target reached' : 'I made 1'}
        </button>
        <button onClick={() => { setPending(null); setPickerOpen(true); }} disabled={done} style={{
          padding: '12px 18px',
          background: 'var(--bg-surface)',
          color: 'var(--fg-2)',
          fontSize: 13, fontWeight: 500,
          opacity: done ? 0.5 : 1,
          cursor: done ? 'not-allowed' : 'pointer',
        }}>
          Other…
        </button>
      </div>
      <StaffPicker
        open={pickerOpen}
        onClose={() => setPickerOpen(false)}
        onPick={(s) => commit(s)}
        title={pending === 1 ? `Who made 1 of ${item.name}?` : `Who worked on ${item.name}?`}
      />
    </div>
  );
};

// ------------------------------------------------------------------
// Variant C: Numpad sheet
// ------------------------------------------------------------------
const NumpadRow = ({ item, entries, onTap }) => {
  const total = entries.reduce((s, e) => s + e.qty, 0);
  const done = total >= item.target;
  return (
    <button onClick={() => onTap(item)} style={{
      width: '100%', textAlign: 'left',
      display: 'flex', alignItems: 'center', gap: 16, padding: 14,
      background: 'var(--bg-surface)', borderRadius: 12,
      border: '1px solid var(--border-1)',
      transition: 'transform 140ms',
    }}
    onMouseDown={e => e.currentTarget.style.transform = 'scale(0.996)'}
    onMouseUp={e => e.currentTarget.style.transform = ''}
    onMouseLeave={e => e.currentTarget.style.transform = ''}
    >
      <div style={{ flex: '0 0 220px' }}>
        <div style={{ display: 'flex', gap: 6, marginBottom: 4 }}>
          <CategoryChip category={item.category} small />
          <PriorityPill priority={item.priority} small />
        </div>
        <div style={{ fontSize: 15, fontWeight: 500, color: done ? 'var(--fg-3)' : 'var(--fg-1)', textDecoration: done ? 'line-through' : 'none' }}>{item.name}</div>
        {item.note && (
          <div style={{ fontSize: 12, color: 'var(--fg-3)', marginTop: 3, fontStyle: 'italic' }}>“{item.note}”</div>
        )}
      </div>
      <div style={{ flex: '0 0 170px' }}>
        <ItemProgress item={item} entries={entries} />
      </div>
      <div style={{ flex: 1 }}>
        <EntryChips entries={entries} />
      </div>
      <div style={{
        display: 'flex', alignItems: 'center', gap: 4,
        color: 'var(--fg-1)', fontWeight: 500, fontSize: 13,
      }}>
        Log <Icon name="chevron" size={14} color="var(--fg-1)" strokeWidth={1.8} />
      </div>
    </button>
  );
};

// ------------------------------------------------------------------
// Full-screen crew log sheet — each crew shows running total, ± commits live
// ------------------------------------------------------------------
const CrewLogSheet = ({ open, onClose, item, entries = [], onAdjust }) => {
  if (!open || !item) return null;

  // Sum existing contributions by staff — this IS the running total shown in each row
  const byStaff = {};
  entries.forEach(e => { byStaff[e.staffId] = (byStaff[e.staffId] || 0) + e.qty; });

  const total = entries.reduce((s, e) => s + e.qty, 0);
  const pct = Math.min(100, (total / item.target) * 100);
  const staff = window.SAMPLE_STAFF;
  const done = total >= item.target;

  return (
    <div style={{
      position: 'absolute', inset: 0, zIndex: 50,
      background: 'var(--bg-app)',
      display: 'flex', flexDirection: 'column',
      animation: 'slideUp 180ms var(--ease-snap)',
    }}>
      <style>{`@keyframes slideUp { from { transform: translateY(20px); opacity: 0 } to { transform: translateY(0); opacity: 1 } }`}</style>

      {/* Header */}
      <div style={{
        padding: '16px 24px 14px',
        background: 'var(--bg-surface)',
        borderBottom: '1px solid var(--border-1)',
        display: 'flex', alignItems: 'center', gap: 12,
      }}>
        <button onClick={onClose} style={{
          width: 36, height: 36, borderRadius: 999,
          background: 'var(--bg-sunken)',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
          cursor: 'pointer',
        }}>
          <Icon name="chevronL" size={18} strokeWidth={2} color="var(--fg-1)" />
        </button>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 11, color: 'var(--fg-3)', fontWeight: 500, letterSpacing: '0.06em', textTransform: 'uppercase' }}>
            Log prep · {item.category}
          </div>
          <div style={{ fontSize: 20, fontWeight: 600, letterSpacing: '-0.02em', color: 'var(--fg-1)', marginTop: 1 }}>{item.name}</div>
        </div>
        <div style={{ textAlign: 'right' }}>
          <div style={{ fontSize: 10, color: 'var(--fg-3)', fontWeight: 500, letterSpacing: '0.06em', textTransform: 'uppercase' }}>Progress</div>
          <div style={{ fontSize: 20, fontWeight: 600, fontFamily: 'var(--font-num)', letterSpacing: '-0.02em', color: done ? 'var(--fg-1)' : 'var(--fg-1)' }}>
            {total}
            <span style={{ color: 'var(--fg-3)', fontWeight: 500 }}>/{item.target}</span>
          </div>
        </div>
      </div>

      {/* Progress bar */}
      <div style={{ padding: '12px 24px 0', background: 'var(--bg-surface)' }}>
        <ProgressBar pct={pct} height={4} color={done ? 'var(--fg-1)' : 'var(--fg-2)'} bg="var(--border-1)" />
      </div>

      {/* Crew grid */}
      <div className="scroll-soft" style={{
        flex: 1, overflowY: 'auto',
        padding: '20px 24px 110px',
        background: 'var(--bg-surface)',
      }}>
        <div style={{
          fontSize: 11, color: 'var(--fg-3)', fontWeight: 500,
          letterSpacing: '0.06em', textTransform: 'uppercase', marginBottom: 12,
        }}>
          Tap + each time a crew member finishes a batch · tap − to undo
        </div>
        <div style={{
          display: 'grid',
          gridTemplateColumns: 'repeat(2, 1fr)',
          gap: 10,
        }}>
          {staff.map(s => {
            const count = byStaff[s.id] || 0;
            const active = count > 0;
            return (
              <div key={s.id} style={{
                display: 'flex', alignItems: 'center', gap: 14,
                padding: '12px 14px',
                background: active ? 'var(--fg-1)' : 'var(--bg-sunken)',
                borderRadius: 12,
                transition: 'background 140ms var(--ease-snap)',
              }}>
                <Avatar staff={s} size={44} />
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{
                    fontSize: 15, fontWeight: 500,
                    color: active ? '#FFFFFF' : 'var(--fg-1)',
                    letterSpacing: '-0.005em',
                  }}>{s.name}</div>
                  <div style={{
                    fontSize: 11, fontWeight: 400, letterSpacing: '0.04em', textTransform: 'uppercase',
                    color: active ? 'rgba(255,255,255,0.65)' : 'var(--fg-3)',
                  }}>
                    {s.role}
                  </div>
                </div>
                <div style={{
                  display: 'flex', alignItems: 'center', gap: 4,
                  background: active ? 'rgba(255,255,255,0.15)' : '#FFFFFF',
                  borderRadius: 10, padding: 3,
                  border: active ? 'none' : '1px solid var(--border-1)',
                }}>
                  <button
                    onClick={() => onAdjust(s, -1)}
                    disabled={count === 0}
                    className="tap"
                    style={{
                      width: 34, height: 34, borderRadius: 7,
                      background: active ? 'rgba(255,255,255,0.15)' : 'var(--bg-sunken)',
                      display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                      opacity: count === 0 ? 0.35 : 1,
                      cursor: count === 0 ? 'default' : 'pointer',
                    }}
                  >
                    <Icon name="minus" size={14} strokeWidth={2} color={active ? '#FFFFFF' : 'var(--fg-1)'} />
                  </button>
                  <div style={{
                    minWidth: 36, textAlign: 'center',
                    fontSize: 18, fontWeight: 600, fontFamily: 'var(--font-num)',
                    color: active ? '#FFFFFF' : 'var(--fg-1)',
                    letterSpacing: '-0.02em',
                  }}>{count}</div>
                  <button
                    onClick={() => onAdjust(s, +1)}
                    disabled={done}
                    className="tap"
                    style={{
                      width: 34, height: 34, borderRadius: 7,
                      background: active ? 'rgba(255,255,255,0.15)' : 'var(--bg-sunken)',
                      display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                      opacity: done ? 0.35 : 1,
                      cursor: done ? 'not-allowed' : 'pointer',
                    }}
                  >
                    <Icon name="plus" size={14} strokeWidth={2} color={active ? '#FFFFFF' : 'var(--fg-1)'} />
                  </button>
                </div>
              </div>
            );
          })}
        </div>
      </div>

      {/* Footer action bar */}
      <div style={{
        position: 'absolute', left: 0, right: 0, bottom: 0,
        padding: '14px 24px',
        background: 'var(--bg-surface)',
        borderTop: '1px solid var(--border-1)',
        display: 'flex', alignItems: 'center', gap: 12,
      }}>
        <div style={{ flex: 1, minWidth: 0, display: 'flex', alignItems: 'center', gap: 6 }}>
          <Icon name={done ? 'check' : 'clock'} size={14} color="var(--fg-3)" strokeWidth={2} />
          <span style={{ fontSize: 12, color: 'var(--fg-3)', fontWeight: 500 }}>
            {done ? 'Target reached — great work' : `${item.target - total} more to reach target`}
          </span>
        </div>
        <Btn variant="primary" size="lg" onClick={onClose}>Done</Btn>
      </div>
    </div>
  );
};

const NumpadSheet = ({ open, onClose, item, entries = [], onSubmit }) => {
  const [qty, setQty] = usePrep('');
  const [stage, setStage] = usePrep('qty');
  const [staff, setStaff] = usePrep(null);
  useMemoPrep(() => { if (open) { setQty(''); setStage('qty'); setStaff(null); } }, [open, item?.id]);
  if (!open || !item) return null;
  const currentTotal = entries.reduce((s, e) => s + e.qty, 0);
  const remaining = Math.max(0, item.target - currentTotal);
  const qtyNum = parseInt(qty || '0');
  const overLimit = qtyNum > remaining;
  const atTarget = remaining === 0;
  return (
    <Modal open={open} onClose={onClose} width={520} title={stage === 'qty' ? `Add prep — ${item.name}` : `Who did it?`}>
      {stage === 'qty' ? (
        <div style={{ padding: 24, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 20 }}>
          <div style={{ fontSize: 13, color: 'var(--fg-2)', textAlign: 'center' }}>
            {atTarget ? (
              <span>Already at target of <strong style={{ color: 'var(--fg-1)' }}>{item.target}</strong> — no more needed.</span>
            ) : (
              <span>
                <strong style={{ color: 'var(--fg-1)' }}>{currentTotal}</strong> done of <strong style={{ color: 'var(--fg-1)' }}>{item.target}</strong>
                {' · '}
                <strong style={{ color: 'var(--fg-1)' }}>{remaining}</strong> more needed
              </span>
            )}
          </div>
          <div style={{
            display: 'flex', alignItems: 'baseline', gap: 8,
            padding: '18px 28px',
            background: overLimit ? 'rgba(220,38,38,0.08)' : 'var(--bg-sunken)',
            borderRadius: 14,
            minWidth: 200, justifyContent: 'center',
            transition: 'background 140ms var(--ease-snap)',
          }}>
            <span style={{
              fontSize: 44, fontWeight: 400, fontFamily: 'var(--font-num)',
              letterSpacing: '-0.03em',
              color: overLimit ? '#DC2626' : (qty ? 'var(--fg-1)' : 'var(--fg-3)'),
            }}>
              {qty || '0'}
            </span>
          </div>
          {overLimit && (
            <div style={{ fontSize: 12, color: '#DC2626', fontWeight: 500, marginTop: -8 }}>
              Can't exceed the assigned target ({item.target})
            </div>
          )}
          <NumPad value={qty} onChange={setQty} maxLen={3} />
          <Btn
            variant="primary" size="lg" fullWidth
            disabled={!qty || qtyNum === 0 || atTarget || overLimit}
            onClick={() => setStage('staff')}
          >
            {atTarget ? 'Target already reached' : overLimit ? 'Over limit' : 'Continue'}
          </Btn>
        </div>
      ) : (
        <div style={{
          padding: 24,
          display: 'grid',
          gridTemplateColumns: 'repeat(3, 1fr)',
          gap: 10,
        }}>
          {window.SAMPLE_STAFF.map(s => (
            <button key={s.id} onClick={() => onSubmit(s, parseInt(qty))} style={{
              display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 10,
              padding: '16px 12px',
              background: 'var(--bg-sunken)', borderRadius: 12,
            }}>
              <Avatar staff={s} size={48} />
              <div style={{ textAlign: 'center' }}>
                <div style={{ fontSize: 14, fontWeight: 500, color: 'var(--fg-1)' }}>{s.name}</div>
                <div style={{ fontSize: 11, color: 'var(--fg-3)', fontWeight: 400, letterSpacing: '0.04em', textTransform: 'uppercase' }}>{s.role}</div>
              </div>
            </button>
          ))}
        </div>
      )}
    </Modal>
  );
};

// ------------------------------------------------------------------
// Set Targets sheet — full-screen bulk editor for tonight's targets.
// Lists all prep items with − / + counters and a Primary/Secondary
// toggle per item. No units — numbers only.
// ------------------------------------------------------------------
const SetTargetsSheet = ({ open, onClose, items, onSave }) => {
  // Local draft state, keyed by item id: { target, priority, note }
  const [draft, setDraft] = usePrep({});
  const [editingNote, setEditingNote] = usePrep(null);

  useEffectPrep(() => {
    if (open) {
      const next = {};
      items.forEach(it => { next[it.id] = { target: it.target, priority: it.priority, note: it.note || '' }; });
      setDraft(next);
      setEditingNote(null);
    }
  }, [open]);

  if (!open) return null;

  const bump = (id, delta) => {
    setDraft(prev => {
      const cur = prev[id] || { target: 0, priority: 'primary', note: '' };
      const next = Math.max(0, cur.target + delta);
      return { ...prev, [id]: { ...cur, target: next } };
    });
  };

  const setNote = (id, v) => {
    setDraft(prev => {
      const cur = prev[id] || { target: 0, priority: 'primary', note: '' };
      return { ...prev, [id]: { ...cur, note: v } };
    });
  };

  const setExact = (id, v) => {
    setDraft(prev => {
      const cur = prev[id] || { target: 0, priority: 'primary' };
      const n = Math.max(0, Number(v) || 0);
      return { ...prev, [id]: { ...cur, target: n } };
    });
  };

  const togglePriority = (id) => {
    setDraft(prev => {
      const cur = prev[id] || { target: 0, priority: 'primary' };
      return { ...prev, [id]: { ...cur, priority: cur.priority === 'primary' ? 'secondary' : 'primary' } };
    });
  };

  const filtered = items;

  // Count changes vs original
  const changes = items.reduce((n, it) => {
    const d = draft[it.id];
    if (!d) return n;
    if (d.target !== it.target || d.priority !== it.priority || (d.note || '') !== (it.note || '')) return n + 1;
    return n;
  }, 0);

  // Group filtered by category, preserving input order within each
  const order = ['Meat', 'Vegetable', 'Sauce', 'Other', 'Cleaning & Fixing'];
  const grouped = order
    .map(cat => ({ category: cat, rows: filtered.filter(it => it.category === cat) }))
    .filter(g => g.rows.length > 0);

  const handleSave = () => {
    onSave(draft);
    onClose();
  };

  return (
    <div style={{
      position: 'absolute', inset: 0, zIndex: 50,
      background: 'var(--bg-page)',
      display: 'flex', flexDirection: 'column',
      animation: 'slideUp 180ms var(--ease-snap)',
    }}>
      <style>{`@keyframes slideUp { from { transform: translateY(20px); opacity: 0 } to { transform: translateY(0); opacity: 1 } }`}</style>

      {/* Header */}
      <div style={{
        flexShrink: 0,
        padding: '16px 24px 14px',
        borderBottom: '1px solid var(--border-1)',
        background: 'var(--bg-surface)',
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
          <button onClick={onClose} style={{
            width: 36, height: 36, borderRadius: 999,
            background: 'var(--bg-sunken)',
            display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
            cursor: 'pointer', flexShrink: 0,
          }}>
            <Icon name="chevronL" size={18} strokeWidth={2} color="var(--fg-1)" />
          </button>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 11, color: 'var(--fg-3)', fontWeight: 500, letterSpacing: '0.06em', textTransform: 'uppercase' }}>
              Today · {new Date().toLocaleDateString('en-US', { weekday: 'short', month: 'short', day: 'numeric' })}
            </div>
            <div style={{ fontSize: 20, fontWeight: 600, letterSpacing: '-0.02em', color: 'var(--fg-1)', marginTop: 1 }}>
              Set today's prep targets
            </div>
          </div>
        </div>
      </div>

      {/* List */}
      <div className="scroll-soft" style={{
        flex: 1, overflowY: 'auto',
        padding: '16px 24px 120px',
      }}>
        {grouped.length === 0 && (
          <div style={{ padding: 48, textAlign: 'center', color: 'var(--fg-3)', fontSize: 15 }}>
            No items match.
          </div>
        )}
        {grouped.map(g => (
          <div key={g.category} style={{ marginBottom: 28 }}>
            <div style={{
              display: 'flex', alignItems: 'baseline', gap: 10,
              padding: '0 4px 12px',
            }}>
              <div style={{
                fontSize: 18, fontWeight: 600, letterSpacing: '-0.01em', color: 'var(--fg-1)',
              }}>{g.category}</div>
              <div style={{ fontSize: 12, color: 'var(--fg-3)', fontWeight: 500 }}>
                {g.rows.length} item{g.rows.length !== 1 ? 's' : ''}
              </div>
              <div style={{ flex: 1, height: 1, background: 'var(--border-1)', marginLeft: 8 }} />
            </div>
            <div style={{
              background: '#FFFFFF',
              borderRadius: 14,
              border: '1px solid var(--border-2)',
              overflow: 'hidden',
            }}>
              {g.rows.map((it, idx) => {
                const d = draft[it.id] || { target: it.target, priority: it.priority, note: it.note || '' };
                const isSecondary = d.priority === 'secondary';
                const hasNote = !!(d.note && d.note.trim());
                const isEditingNote = editingNote === it.id;
                const changed = d.target !== it.target || d.priority !== it.priority || (d.note || '') !== (it.note || '');
                return (
                  <div key={it.id} style={{
                    borderBottom: idx === g.rows.length - 1 ? 'none' : '1px solid var(--border-2)',
                    background: changed ? 'rgba(37, 99, 235, 0.04)' : 'transparent',
                  }}>
                  <div style={{
                    display: 'grid',
                    gridTemplateColumns: '1fr 92px 224px',
                    alignItems: 'center',
                    gap: 14,
                    padding: '12px 14px',
                  }}>
                    {/* Name */}
                    <div style={{ minWidth: 0 }}>
                      <div style={{
                        fontSize: 15, fontWeight: 500, color: 'var(--fg-1)',
                        whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
                      }}>{it.name}</div>
                      {hasNote && !isEditingNote && (
                        <div style={{
                          fontSize: 12, color: 'var(--fg-2)', marginTop: 3,
                          whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
                          fontStyle: 'italic',
                        }}>
                          “{d.note}”
                        </div>
                      )}
                      {changed && !hasNote && (
                        <div style={{
                          fontSize: 11, color: '#2563EB', fontWeight: 500,
                          fontVariantNumeric: 'tabular-nums', marginTop: 2,
                        }}>
                          was {it.target} · {it.priority === 'primary' ? 'Primary' : 'Secondary'}
                        </div>
                      )}
                    </div>

                    {/* Priority pill — its own column */}
                    <div style={{ display: 'flex', justifyContent: 'flex-start' }}>
                      <button
                        onClick={() => togglePriority(it.id)}
                        style={{
                          height: 24, padding: '0 10px',
                          borderRadius: 999,
                          background: isSecondary ? 'var(--bg-sunken)' : '#DBEAFE',
                          color: isSecondary ? 'var(--fg-3)' : '#1E40AF',
                          fontSize: 10, fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase',
                          border: 'none', cursor: 'pointer',
                        }}
                        title="Tap to switch between Primary and Secondary"
                      >
                        {isSecondary ? 'Secondary' : 'Primary'}
                      </button>
                    </div>

                    {/* Counter — centered in its column */}
                    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6 }}>
                      <button
                        onClick={() => bump(it.id, -1)}
                        disabled={d.target <= 0}
                        style={{
                          width: 40, height: 40, borderRadius: 10,
                          border: '1px solid var(--border-1)',
                          background: d.target <= 0 ? 'var(--bg-sunken)' : '#FFFFFF',
                          color: d.target <= 0 ? 'var(--fg-3)' : 'var(--fg-1)',
                          fontSize: 20, fontWeight: 400,
                          cursor: d.target <= 0 ? 'default' : 'pointer',
                          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                        }}
                      >−</button>
                      <input
                        type="number"
                        min="0"
                        value={d.target}
                        onChange={e => setExact(it.id, e.target.value)}
                        style={{
                          width: 56, height: 40,
                          textAlign: 'center', textAlignLast: 'center',
                          padding: 0, lineHeight: '40px',
                          fontFamily: 'var(--font-num)', fontWeight: 600, fontSize: 18,
                          color: 'var(--fg-1)',
                          background: 'var(--bg-sunken)',
                          border: '1px solid transparent', borderRadius: 10,
                          outline: 'none',
                          MozAppearance: 'textfield',
                        }}
                      />
                      <button
                        onClick={() => bump(it.id, 1)}
                        style={{
                          width: 40, height: 40, borderRadius: 10,
                          border: '1px solid var(--border-1)', background: '#FFFFFF',
                          color: 'var(--fg-1)',
                          fontSize: 20, fontWeight: 400, cursor: 'pointer',
                          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                        }}
                      >+</button>
                      <button
                        onClick={() => setEditingNote(isEditingNote ? null : it.id)}
                        title={hasNote ? 'Edit comment' : 'Add comment'}
                        style={{
                          width: 40, height: 40, borderRadius: 10,
                          border: '1px solid ' + (hasNote || isEditingNote ? '#2563EB' : 'var(--border-1)'),
                          background: hasNote || isEditingNote ? '#EFF6FF' : '#FFFFFF',
                          color: hasNote || isEditingNote ? '#2563EB' : 'var(--fg-2)',
                          cursor: 'pointer', marginLeft: 4,
                          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                          flexShrink: 0,
                        }}
                      >
                        <Icon name="edit" size={16} strokeWidth={2} />
                      </button>
                    </div>
                  </div>
                  {isEditingNote && (
                    <div style={{
                      padding: '0 14px 12px',
                      display: 'flex', gap: 8, alignItems: 'center',
                    }}>
                      <input
                        type="text"
                        autoFocus
                        value={d.note || ''}
                        onChange={e => setNote(it.id, e.target.value)}
                        onKeyDown={e => { if (e.key === 'Enter' || e.key === 'Escape') setEditingNote(null); }}
                        placeholder="Add a comment for the team…"
                        maxLength={120}
                        style={{
                          flex: 1, height: 38, padding: '0 12px',
                          fontSize: 14, fontFamily: 'var(--font-ui)',
                          background: '#FFFFFF', color: 'var(--fg-1)',
                          border: '1px solid #2563EB', borderRadius: 10,
                          outline: 'none',
                        }}
                      />
                      <button
                        onClick={() => setEditingNote(null)}
                        style={{
                          height: 38, padding: '0 14px',
                          background: '#2563EB', color: '#FFFFFF',
                          border: 'none', borderRadius: 10,
                          fontSize: 13, fontWeight: 600, cursor: 'pointer',
                        }}
                      >Done</button>
                    </div>
                  )}
                  </div>
                );
              })}
            </div>
          </div>
        ))}
      </div>

      {/* Sticky footer */}
      <div style={{
        flexShrink: 0,
        padding: '14px 24px',
        borderTop: '1px solid var(--border-1)',
        background: 'var(--bg-surface)',
        display: 'flex', alignItems: 'center', gap: 10,
        boxShadow: '0 -4px 20px rgba(0,0,0,0.04)',
      }}>
        <div style={{ flex: 1, fontSize: 13, color: 'var(--fg-3)' }}>
          {changes === 0 ? 'No changes' : (
            <span><strong style={{ color: 'var(--fg-1)', fontWeight: 600 }}>{changes}</strong> {changes === 1 ? 'item' : 'items'} updated</span>
          )}
        </div>
        <Btn variant="ghost" size="lg" onClick={onClose}>Cancel</Btn>
        <Btn variant="primary" size="lg" onClick={handleSave} disabled={changes === 0}>
          Save targets
        </Btn>
      </div>
    </div>
  );
};

// ------------------------------------------------------------------
// Main
// ------------------------------------------------------------------
const PrepScreen = ({ onBack, prepState, setPrepState, interactionMode, setInteractionMode, currentStaff, showToast }) => {
  // Target / priority overrides — edited via Set Targets sheet.
  // Shape: { [itemId]: { target?: number, priority?: 'primary'|'secondary' } }
  const [overrides, setOverrides] = usePrep(() => {
    try {
      const raw = localStorage.getItem('snap-prep-overrides');
      return raw ? JSON.parse(raw) : {};
    } catch { return {}; }
  });
  useEffectPrep(() => {
    try { localStorage.setItem('snap-prep-overrides', JSON.stringify(overrides)); } catch {}
  }, [overrides]);
  // Full catalog (for Set Targets sheet) and the "assigned tonight" subset
  // (target > 0) that the staff actually sees in Daily Prep.
  const allItems = useMemoPrep(() => window.SAMPLE_PREP_ITEMS.map(it => {
    const o = overrides[it.id];
    if (!o) return it;
    return { ...it, target: o.target ?? it.target, priority: o.priority ?? it.priority, note: o.note ?? it.note };
  }), [overrides]);
  const items = useMemoPrep(() => allItems.filter(it => (it.target ?? 0) > 0), [allItems]);
  const [addOpen, setAddOpen] = usePrep(false);
  const [filter, setFilter] = usePrep('All');
  const [sheetItem, setSheetItem] = usePrep(null);
  const [picIds, setPicIds] = usePrep(() => {
    const all = new Set();
    window.SAMPLE_PREP_ITEMS.forEach(it => (window.SAMPLE_PREP_PIC?.[it.id] || []).forEach(id => all.add(id)));
    return Array.from(all);
  });
  const [assignOpen, setAssignOpen] = usePrep(false);

  const visible = useMemoPrep(() => {
    return items.filter(it => {
      const entries = prepState[it.id] || [];
      const q = entries.reduce((s, e) => s + e.qty, 0);
      const done = q >= it.target;
      if (filter === 'Primary') return it.priority === 'primary' && !done;
      if (filter === 'Secondary') return it.priority === 'secondary' && !done;
      if (filter === 'Done') return done;
      return true;
    });
  }, [filter, prepState]);

  const grouped = useMemoPrep(() => {
    const by = {};
    visible.forEach(it => {
      if (!by[it.category]) by[it.category] = [];
      by[it.category].push(it);
    });
    Object.values(by).forEach(arr => arr.sort((a, b) => {
      if (a.priority !== b.priority) return a.priority === 'primary' ? -1 : 1;
      return 0;
    }));
    const order = ['Meat', 'Vegetable', 'Sauce', 'Other', 'Cleaning & Fixing'];
    return order.filter(c => by[c]).map(c => ({ category: c, items: by[c] }));
  }, [visible]);

  const contribute = (itemId, staff, qty) => {
    const item = items.find(i => i.id === itemId);
    const existing = prepState[itemId] || [];
    const currentTotal = existing.reduce((s, e) => s + e.qty, 0);
    const remaining = item ? Math.max(0, item.target - currentTotal) : qty;
    const capped = Math.max(0, Math.min(qty, remaining));
    if (capped === 0) {
      showToast({ message: `${item?.name || 'Item'} already at target (${item?.target})`, staff });
      return;
    }
    setPrepState(prev => {
      const existing2 = prev[itemId] || [];
      const next = [...existing2, { staffId: staff.id, qty: capped, ts: new Date().toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false }) }];
      return { ...prev, [itemId]: next };
    });
    if (capped < qty) {
      showToast({ message: `Capped at +${capped} — target of ${item.target} reached`, staff });
    } else {
      showToast({ message: `+${capped} logged for ${staff.name}`, staff });
    }
  };

  const adjustCrew = (itemId, staff, delta) => {
    const ts = new Date().toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false });
    setPrepState(prev => {
      const existing = prev[itemId] || [];
      if (delta > 0) {
        const item = items.find(i => i.id === itemId);
        const currentTotal = existing.reduce((s, e) => s + e.qty, 0);
        if (item && currentTotal >= item.target) {
          // Silently no-op; button should already be disabled
          return prev;
        }
        return { ...prev, [itemId]: [...existing, { staffId: staff.id, qty: 1, ts }] };
      }
      // delta < 0 — remove 1 from this staff's most recent entry
      let removed = false;
      const next = [];
      for (let i = existing.length - 1; i >= 0; i--) {
        const e = existing[i];
        if (!removed && e.staffId === staff.id) {
          if (e.qty > 1) next.unshift({ ...e, qty: e.qty - 1 });
          // else drop the entry entirely
          removed = true;
        } else {
          next.unshift(e);
        }
      }
      return { ...prev, [itemId]: next };
    });
  };

  const contributeMany = (itemId, payload) => {
    if (!payload || payload.length === 0) return;
    const item = items.find(i => i.id === itemId);
    const existing = prepState[itemId] || [];
    const currentTotal = existing.reduce((s, e) => s + e.qty, 0);
    let remaining = item ? Math.max(0, item.target - currentTotal) : Infinity;
    const ts = new Date().toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false });
    const added = [];
    let dropped = 0;
    for (const p of payload) {
      const take = Math.max(0, Math.min(p.qty, remaining));
      if (take > 0) {
        added.push({ staffId: p.staff.id, qty: take, ts });
        remaining -= take;
      }
      dropped += (p.qty - take);
    }
    if (added.length === 0) {
      showToast({ message: `${item?.name || 'Item'} already at target (${item?.target})` });
      return;
    }
    setPrepState(prev => {
      const existing2 = prev[itemId] || [];
      return { ...prev, [itemId]: [...existing2, ...added] };
    });
    if (dropped > 0) {
      showToast({ message: `Capped at target — ${dropped} over limit dropped` });
    }
  };

  return (
    <div style={{ height: '100%', display: 'flex', flexDirection: 'column', position: 'relative' }}>
      <PrepHeader
        onBack={onBack}
        items={items}
        progress={prepState}
        filter={filter}
        setFilter={setFilter}
        interactionMode={interactionMode}
        setInteractionMode={setInteractionMode}
        picIds={picIds}
        onOpenAssign={() => setAssignOpen(true)}
        onAddItem={() => setAddOpen(true)}
      />
      <div className="scroll-soft" style={{
        flex: 1, overflowY: 'auto',
        padding: '20px 24px 40px',
      }}>
        {items.length === 0 ? (
          <div style={{
            minHeight: 360,
            display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
            gap: 16, padding: '60px 24px',
            textAlign: 'center',
          }}>
            <div style={{
              width: 72, height: 72, borderRadius: 999,
              background: 'var(--bg-sunken)',
              display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
            }}>
              <Icon name="plus" size={30} color="var(--fg-3)" strokeWidth={2} />
            </div>
            <div style={{ fontSize: 20, fontWeight: 600, color: 'var(--fg-1)', letterSpacing: '-0.01em' }}>
              Nothing assigned today
            </div>
            <div style={{ fontSize: 15, color: 'var(--fg-3)', maxWidth: 420, lineHeight: 1.45 }}>
              Pick today's prep items and set targets to get started.
            </div>
          </div>
        ) : (
          <React.Fragment>
        <PrepFilterPills items={items} progress={prepState} filter={filter} setFilter={setFilter} />
        {grouped.map(g => (
          <div key={g.category} style={{ marginBottom: 20 }}>
            {interactionMode === 'table' && (
              <div>
                <TableHeader category={g.category} count={g.items.length} />
                {g.items.map((it, idx) => (
                  <TableRow
                    key={it.id} item={it}
                    entries={prepState[it.id] || []}
                    onTap={(item) => setSheetItem(item)}
                    isLast={idx === g.items.length - 1}
                  />
                ))}
              </div>
            )}
            {interactionMode !== 'table' && (
              <div style={{
                display: 'flex', alignItems: 'center', gap: 10, marginBottom: 10,
                padding: '0 4px',
              }}>
                <CategoryChip category={g.category} />
                <div style={{ fontSize: 12, color: 'var(--fg-3)', fontWeight: 500 }}>
                  {g.items.length} item{g.items.length !== 1 ? 's' : ''}
                </div>
                <div style={{ flex: 1, height: 1, background: 'var(--border-1)', marginLeft: 8 }} />
              </div>
            )}
            {interactionMode === 'stepper' && (
              <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                {g.items.map(it => (
                  <StepperRow
                    key={it.id} item={it}
                    entries={prepState[it.id] || []}
                    onContribute={(staff, delta) => contribute(it.id, staff, delta)}
                    currentStaff={currentStaff}
                  />
                ))}
              </div>
            )}
            {interactionMode === 'tap' && (
              <div style={{
                display: 'grid',
                gridTemplateColumns: 'repeat(auto-fill, minmax(340px, 1fr))',
                gap: 12,
              }}>
                {g.items.map(it => (
                  <TapCard
                    key={it.id} item={it}
                    entries={prepState[it.id] || []}
                    onContribute={(staff, delta) => contribute(it.id, staff, delta)}
                  />
                ))}
              </div>
            )}
            {interactionMode === 'sheet' && (
              <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                {g.items.map(it => (
                  <NumpadRow
                    key={it.id} item={it}
                    entries={prepState[it.id] || []}
                    onTap={(it) => setSheetItem(it)}
                  />
                ))}
              </div>
            )}
          </div>
        ))}
          </React.Fragment>
        )}
      </div>
      <CrewLogSheet
        open={!!sheetItem}
        onClose={() => setSheetItem(null)}
        item={sheetItem}
        entries={sheetItem ? (prepState[sheetItem.id] || []) : []}
        onAdjust={(staff, delta) => adjustCrew(sheetItem.id, staff, delta)}
      />
      <StaffMultiPicker
        open={assignOpen}
        onClose={() => setAssignOpen(false)}
        selectedIds={picIds}
        onSave={(ids) => {
          setPicIds(ids);
          showToast({ message: ids.length === 0 ? 'PIC cleared' : `PIC updated · ${ids.length} assigned` });
        }}
        title="Assign PIC for Daily Prep"
      />
      <SetTargetsSheet
        open={addOpen}
        onClose={() => setAddOpen(false)}
        items={allItems}
        onSave={(draft) => {
          // Diff draft against sample defaults; only persist real deltas.
          const next = {};
          let changed = 0;
          window.SAMPLE_PREP_ITEMS.forEach(base => {
            const d = draft[base.id];
            if (!d) return;
            const targetDelta = d.target !== base.target ? d.target : undefined;
            const priorityDelta = d.priority !== base.priority ? d.priority : undefined;
            const baseNote = base.note || '';
            const draftNote = d.note || '';
            const noteDelta = draftNote !== baseNote ? draftNote : undefined;
            if (targetDelta !== undefined || priorityDelta !== undefined || noteDelta !== undefined) {
              next[base.id] = {};
              if (targetDelta !== undefined) next[base.id].target = targetDelta;
              if (priorityDelta !== undefined) next[base.id].priority = priorityDelta;
              if (noteDelta !== undefined) next[base.id].note = noteDelta;
              changed++;
            }
          });
          setOverrides(next);
          showToast({ message: changed === 0 ? 'Targets reset to defaults' : `Updated ${changed} target${changed !== 1 ? 's' : ''}`, icon: 'check' });
        }}
      />
    </div>
  );
};

Object.assign(window, { PrepScreen });
