/* =============================================================================
   portal/Worksheets-ui.jsx — the three worksheet components + admin read-only.
   Loads after Worksheets.jsx (uses window.useWorksheet etc).
   ============================================================================= */

/* =================== RECOMMENDER BRIEF WORKSHEET ========================== */
function RecommenderWorksheet({ onNavigate, readOnly, clientId }) {
  const { C } = UI;
  const D = WORKSHEETS.recommender;
  const [recs, setRecs, saved] = useWorksheet('recommender', () => [blankRec(1), blankRec(2)], clientId);

  const update = (i, patch) => setRecs(recs.map((r, n) => n === i ? { ...r, ...patch } : r));
  const setStrength = (i, si, patch) => update(i, { strengths: recs[i].strengths.map((s, n) => n === si ? { ...s, ...patch } : s) });
  const addRec = () => setRecs([...recs, blankRec(recs.length + 1)]);
  const removeRec = (i) => setRecs(recs.filter((_, n) => n !== i));

  return (
    <div className="kh-fade" style={{ padding: '40px 40px 72px', maxWidth: 960, margin: '0 auto' }}>
      {!readOnly && <RecommenderTabs active="worksheet" onNavigate={onNavigate} />}
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', gap: 16, flexWrap: 'wrap' }}>
        <WsHeader eyebrow="Plan · before the packet" title={D.title} intro={readOnly ? null : D.intro} />
        <div style={{ display: 'flex', alignItems: 'center', gap: 14, paddingBottom: 24 }}>
          {!readOnly && <WsSaveBadge saved={saved} />}
          <button onClick={() => window.downloadRecommenderDoc && window.downloadRecommenderDoc(clientId)}
            style={{ display: 'inline-flex', alignItems: 'center', gap: 7, background: '#fff', border: `1px solid ${C.hair}`, cursor: 'pointer', padding: '9px 14px', fontFamily: C.sans, fontSize: 10.5, fontWeight: 600, letterSpacing: '0.1em', textTransform: 'uppercase', color: C.carbon, borderRadius: 2, whiteSpace: 'nowrap' }}>
            <Icon name="download" size={14} color="var(--kh-carbon)" /> Download as Word
          </button>
        </div>
      </div>

      {recs.map((rec, i) => (
        <div key={i} style={{ border: `1px solid ${C.hair}`, marginBottom: 22 }}>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12, padding: '15px 20px', background: C.carbon }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 12, flex: 1 }}>
              <span style={{ fontFamily: C.sans, fontSize: 10, fontWeight: 600, letterSpacing: '0.16em', textTransform: 'uppercase', color: C.clay }}>Recommender {i + 1}</span>
              {readOnly
                ? <span style={{ fontFamily: C.sans, fontSize: 15, fontWeight: 500, color: '#fff' }}>{rec.name || '—'}</span>
                : <input value={rec.name} onChange={e => update(i, { name: e.target.value })} placeholder="Recommender name + relationship" style={{ flex: 1, maxWidth: 380, fontFamily: C.sans, fontSize: 14, color: '#fff', background: 'rgba(255,255,255,0.08)', border: '1px solid rgba(255,255,255,0.2)', borderRadius: 2, padding: '8px 11px', outline: 'none' }} />}
            </div>
            {!readOnly && recs.length > 1 && <button onClick={() => removeRec(i)} title="Remove" style={{ background: 'none', border: 'none', cursor: 'pointer', padding: 4 }}><Icon name="x" size={15} color="rgba(255,255,255,0.7)" /></button>}
          </div>

          <div style={{ padding: '20px 22px' }}>
            <div style={{ fontFamily: C.sans, fontSize: 11, fontWeight: 600, letterSpacing: '0.1em', textTransform: 'uppercase', color: C.carbon, marginBottom: 6 }}>Strengths to highlight</div>
            <p style={{ fontFamily: C.serif, fontStyle: 'italic', fontSize: 13, lineHeight: 1.5, color: C.carbon50, margin: '0 0 14px' }}>{D.strengthPrompts}</p>
            <div style={{ border: `1px solid ${C.hair}` }}>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1.6fr', background: C.porcelain, borderBottom: `1px solid ${C.hair}` }}>
                <div style={wsTh(C)}>Key strength</div><div style={{ ...wsTh(C), borderLeft: `1px solid ${C.hair}` }}>Example</div>
              </div>
              {rec.strengths.map((s, si) => (
                <div key={si} style={{ display: 'grid', gridTemplateColumns: '1fr 1.6fr', borderBottom: si < rec.strengths.length - 1 ? `1px solid ${C.hair}` : 'none' }}>
                  {readOnly ? (
                    <>
                      <div style={wsTd(C, true)}>{s.strength || '—'}</div>
                      <div style={{ ...wsTd(C), borderLeft: `1px solid ${C.hair}` }}>{s.example || '—'}</div>
                    </>
                  ) : (
                    <>
                      <textarea value={s.strength} onChange={e => setStrength(i, si, { strength: e.target.value })} rows={2} style={{ ...wsCellArea(C) }} placeholder={si === 0 ? 'e.g. Cross-functional leadership' : ''} />
                      <textarea value={s.example} onChange={e => setStrength(i, si, { example: e.target.value })} rows={2} style={{ ...wsCellArea(C), borderLeft: `1px solid ${C.hair}` }} placeholder={si === 0 ? 'A specific story that proves it' : ''} />
                    </>
                  )}
                </div>
              ))}
            </div>
            {!readOnly && <button onClick={() => update(i, { strengths: [...rec.strengths, { strength: '', example: '' }] })} style={wsAddBtn(C)}><Icon name="plus" size={13} /> Add a strength</button>}

            <div style={{ fontFamily: C.sans, fontSize: 11, fontWeight: 600, letterSpacing: '0.1em', textTransform: 'uppercase', color: C.carbon, margin: '22px 0 10px' }}>Development area</div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
              <WsField label="Feedback" readOnly={readOnly} value={rec.devFeedback} onChange={v => update(i, { devFeedback: v })} placeholder="How has this recommender seen you grow?" />
              <WsField label="Example of improvement" readOnly={readOnly} value={rec.devExample} onChange={v => update(i, { devExample: v })} placeholder="A concrete example of how you improved." />
            </div>
          </div>
        </div>
      ))}
      {!readOnly && <button onClick={addRec} style={wsAddBtn(C)}><Icon name="plus" size={14} /> Add a recommender</button>}
      {!readOnly && window.ModuleTabFooter && <ModuleTabFooter tabs={window.RECOMMENDER_TABS} activeKey="worksheet" onNavigate={onNavigate} />}
    </div>
  );
}
function blankRec(n) { return { name: '', strengths: [{ strength: '', example: '' }, { strength: '', example: '' }, { strength: '', example: '' }, { strength: '', example: '' }, { strength: '', example: '' }], devFeedback: '', devExample: '' }; }

/* =================== SCHOOL ENGAGEMENT WORKSHEET ========================== */
function EngagementWorksheet({ onNavigate, readOnly, clientId }) {
  const { C } = UI;
  const D = WORKSHEETS.engagement;
  const [intro, setIntro, s1] = useWorksheet('engageIntro', '', clientId);
  const [schools, setSchools, s2] = useWorksheet('engageSchools', () => wsTargetSchools(clientId).map(s => ({ key: s.key, name: s.name, short: s.short, interests: '', questions: '', draft: '' })), clientId);
  const [openSample, setOpenSample] = React.useState(null);
  const saved = s1 === 'saving' || s2 === 'saving' ? 'saving' : (s1 === 'saved' || s2 === 'saved') ? 'saved' : 'idle';

  const setSchool = (i, patch) => setSchools(schools.map((s, n) => n === i ? { ...s, ...patch } : s));
  const addSchool = (name) => {
    if (!name) return;
    const entry = window.SCHOOLS && SCHOOLS.resolve ? SCHOOLS.resolve(name) : null;
    const reg = entry && window.REGISTRY ? REGISTRY.schoolModules.find(s => s.id === 's/' + entry.key) : null;
    setSchools([...schools, { key: entry ? entry.key : name, name: entry ? entry.name : name, short: entry ? entry.short : name, logo: reg ? reg.logo : null, interests: '', questions: '', draft: '' }]);
  };

  return (
    <div className="kh-fade" style={{ padding: '40px 40px 72px', maxWidth: 960, margin: '0 auto' }}>
      {!readOnly && <EngagementTabs active="worksheet" onNavigate={onNavigate} />}
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', gap: 16, flexWrap: 'wrap' }}>
        <WsHeader eyebrow="Plan · outreach" title={D.title} intro={readOnly ? null : D.intro} />
        <div style={{ display: 'flex', alignItems: 'center', gap: 14, paddingBottom: 24 }}>
          {!readOnly && <WsSaveBadge saved={saved} />}
          <button onClick={() => window.downloadEngagementDoc && window.downloadEngagementDoc(clientId)}
            style={{ display: 'inline-flex', alignItems: 'center', gap: 7, background: '#fff', border: `1px solid ${C.hair}`, cursor: 'pointer', padding: '9px 14px', fontFamily: C.sans, fontSize: 10.5, fontWeight: 600, letterSpacing: '0.1em', textTransform: 'uppercase', color: C.carbon, borderRadius: 2, whiteSpace: 'nowrap' }}>
            <Icon name="download" size={14} color="var(--kh-carbon)" /> Download as Word
          </button>
        </div>
      </div>

      {/* Sample emails */}
      {!readOnly && (
        <div style={{ marginBottom: 34 }}>
          <div className="kh-eyebrow" style={{ marginBottom: 6 }}>Sample outreach</div>
          <p style={{ fontFamily: C.serif, fontSize: 14.5, lineHeight: 1.6, color: C.carbon70, margin: '0 0 16px', maxWidth: 720 }}>{D.initialOutreachNote}</p>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
            {D.samples.map(s => (
              <div key={s.id} style={{ border: `1px solid ${C.hair}` }}>
                <button onClick={() => setOpenSample(openSample === s.id ? null : s.id)} style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12, width: '100%', textAlign: 'left', background: openSample === s.id ? C.porcelain : '#fff', border: 'none', cursor: 'pointer', padding: '14px 18px' }}>
                  <span style={{ display: 'flex', alignItems: 'center', gap: 11 }}>
                    <Icon name="message" size={16} color="var(--kh-clay-deep)" />
                    <span style={{ fontFamily: C.sans, fontWeight: 500, fontSize: 14, color: C.carbon }}>{s.title}</span>
                  </span>
                  <Icon name={openSample === s.id ? 'chevronDown' : 'chevronRight'} size={16} color="var(--kh-carbon-50)" />
                </button>
                {openSample === s.id && (
                  <div style={{ padding: '4px 18px 18px' }}>
                    <div style={{ position: 'relative', background: C.porcelain, border: `1px solid ${C.hair}`, padding: '16px 18px' }}>
                      <button onClick={() => { try { navigator.clipboard.writeText(s.body); } catch (e) {} }} style={{ position: 'absolute', top: 12, right: 12, display: 'inline-flex', alignItems: 'center', gap: 6, background: '#fff', border: `1px solid ${C.hair}`, cursor: 'pointer', padding: '6px 11px', fontFamily: C.sans, fontSize: 10, fontWeight: 600, letterSpacing: '0.08em', textTransform: 'uppercase', color: C.carbon, borderRadius: 2 }}><Icon name="files" size={12} /> Copy</button>
                      <pre style={{ fontFamily: C.serif, fontSize: 14, lineHeight: 1.6, color: C.carbon, whiteSpace: 'pre-wrap', margin: 0, paddingRight: 70 }}>{s.body}</pre>
                    </div>
                  </div>
                )}
              </div>
            ))}
          </div>
        </div>
      )}

      {/* 30-second intro */}
      <div style={{ marginBottom: 32 }}>
        <WsField label={D.introPrompt} readOnly={readOnly} value={intro} onChange={setIntro} rows={4} placeholder="I'm currently a… / I'm applying to SCHOOL because… / I'd love to learn more about…" big />
      </div>

      {/* Per-school notes + questions */}
      <div className="kh-eyebrow" style={{ marginBottom: 14 }}>By school</div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
        {schools.map((sc, i) => (
          <div key={i} style={{ border: `1px solid ${C.hair}` }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 11, padding: '13px 18px', borderBottom: `1px solid ${C.hair}`, background: C.porcelain }}>
              <UI.SchoolMark slug={(sc.key || '').toString().split('/').pop()} short={sc.short} size={44} variant="solid" />
              <span style={{ fontFamily: C.sans, fontWeight: 600, fontSize: 15, color: C.carbon }}>{sc.name}</span>
              {!readOnly && schools.length > 1 && <button onClick={() => setSchools(schools.filter((_, n) => n !== i))} title="Remove" style={{ marginLeft: 'auto', background: 'none', border: 'none', cursor: 'pointer', padding: 4 }}><Icon name="x" size={14} color="var(--kh-carbon-50)" /></button>}
            </div>
            <div style={{ padding: '18px 18px', display: 'flex', flexDirection: 'column', gap: 16 }}>
              <WsField label={D.perSchool.interestsLabel} help={D.perSchool.interestsHelp} readOnly={readOnly} value={sc.interests} onChange={v => setSchool(i, { interests: v })} />
              <WsField label={D.perSchool.questionsLabel} help={D.perSchool.questionsHelp} readOnly={readOnly} value={sc.questions} onChange={v => setSchool(i, { questions: v })} />
              <WsField label={D.perSchool.draftLabel} help={D.perSchool.draftHelp} readOnly={readOnly} value={sc.draft} onChange={v => setSchool(i, { draft: v })} big />
            </div>
          </div>
        ))}
      </div>
      {!readOnly && <WsAddSchool onAdd={addSchool} present={schools.map(s => s.name)} />}
      {!readOnly && window.ModuleTabFooter && <ModuleTabFooter tabs={window.ENGAGEMENT_TABS} activeKey="worksheet" onNavigate={onNavigate} />}
    </div>
  );
}

/* =================== ENGAGEMENT TRACKER ================================== */
function EngagementTracker({ onNavigate, readOnly, clientId }) {
  const { C } = UI;
  const D = WORKSHEETS.tracker;
  const [outreach, setOutreach, s1] = useWorksheet('trackerOutreach', [], clientId);
  const [events, setEvents, s2] = useWorksheet('trackerEvents', [], clientId);
  const saved = s1 === 'saving' || s2 === 'saving' ? 'saving' : (s1 === 'saved' || s2 === 'saved') ? 'saved' : 'idle';
  const [filter, setFilter] = React.useState('');

  // schools present in the data, for the filter dropdown
  const schoolsInData = [...new Set([...outreach, ...events].map(r => r && r.school).filter(Boolean))].sort();
  const match = (r) => !filter || r.school === filter;
  // index-preserving setters so edits to a filtered view map back to the full array
  const setFilteredOutreach = makeFilteredSetter(outreach, setOutreach, match, filter);
  const setFilteredEvents = makeFilteredSetter(events, setEvents, match, filter);

  return (
    <div className="kh-fade" style={{ padding: '40px 40px 72px', maxWidth: 1140, margin: '0 auto' }}>
      {!readOnly && <EngagementTabs active="tracker" onNavigate={onNavigate} />}
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', gap: 16, flexWrap: 'wrap' }}>
        <WsHeader eyebrow="Track · outreach log" title={D.title} intro={readOnly ? null : D.intro} />
        {!readOnly && <div style={{ paddingBottom: 24 }}><WsSaveBadge saved={saved} /></div>}
      </div>

      {schoolsInData.length > 0 && (
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 20, flexWrap: 'wrap' }}>
          <span style={{ fontFamily: C.sans, fontSize: 10, fontWeight: 600, letterSpacing: '0.12em', textTransform: 'uppercase', color: C.carbon50 }}>Filter by school</span>
          <button onClick={() => setFilter('')} style={trackerChip(C, filter === '')}>All</button>
          {schoolsInData.map(s => <button key={s} onClick={() => setFilter(s)} style={trackerChip(C, filter === s)}>{s}</button>)}
        </div>
      )}

      <div className="kh-eyebrow" style={{ marginBottom: 12 }}>Outreach{filter ? ' · ' + filter : ''}</div>
      <WsTable columns={D.outreachColumns} rows={outreach.filter(match)} setRows={setFilteredOutreach} readOnly={readOnly} addLabel="Add a contact" minWidth={1180} newRow={filter ? { school: filter } : {}} />

      <div className="kh-eyebrow" style={{ margin: '40px 0 12px' }}>Events attended{filter ? ' · ' + filter : ''}</div>
      <WsTable columns={D.eventColumns} rows={events.filter(match)} setRows={setFilteredEvents} readOnly={readOnly} addLabel="Add an event" minWidth={900} newRow={filter ? { school: filter } : {}} />
      {!readOnly && window.ModuleTabFooter && <ModuleTabFooter tabs={window.ENGAGEMENT_TABS} activeKey="tracker" onNavigate={onNavigate} />}
    </div>
  );
}

// Returns a setRows(filteredRows) that merges changes back into the full array,
// preserving rows hidden by the current filter.
function makeFilteredSetter(allRows, setAll, match, filter) {
  return (nextFiltered) => {
    const hidden = allRows.filter(r => !match(r));
    setAll([...nextFiltered, ...hidden]);
  };
}
function trackerChip(C, on) {
  return { fontFamily: C.sans, fontSize: 11, fontWeight: 600, letterSpacing: '0.02em', padding: '6px 12px', borderRadius: 999, cursor: 'pointer', border: `1px solid ${on ? C.carbon : C.hair}`, background: on ? C.carbon : '#fff', color: on ? '#fff' : C.carbon70, whiteSpace: 'nowrap' };
}

/* ---- shared field + table primitives ------------------------------------- */
function WsField({ label, help, value, onChange, readOnly, placeholder, rows, big }) {
  const { C } = UI;
  return (
    <div>
      <div style={{ fontFamily: C.sans, fontSize: 12.5, fontWeight: 600, color: C.carbon }}>{label}</div>
      {help && <p style={{ fontFamily: C.serif, fontSize: 13, lineHeight: 1.5, color: C.carbon50, margin: '4px 0 0' }}>{help}</p>}
      {readOnly
        ? <div style={{ fontFamily: C.serif, fontSize: 14.5, lineHeight: 1.6, color: value ? C.carbon : C.carbon50, whiteSpace: 'pre-wrap', marginTop: 8 }}>{value || 'Not answered'}</div>
        : <textarea value={value || ''} onChange={e => onChange(e.target.value)} rows={rows || (big ? 6 : 3)} placeholder={placeholder} style={{ ...wsArea(C), marginTop: 8, minHeight: big ? 130 : 80 }} />}
    </div>
  );
}

function WsTable({ columns, rows, setRows, readOnly, addLabel, minWidth, newRow, rowStyle }) {
  const { C } = UI;
  const setCell = (i, k, v) => setRows(rows.map((r, n) => n === i ? { ...r, [k]: v } : r));
  const th = { textAlign: 'left', padding: '9px 11px', fontFamily: C.sans, fontSize: 9, fontWeight: 600, letterSpacing: '0.08em', textTransform: 'uppercase', color: C.carbon50, borderBottom: `1px solid ${C.rule}`, whiteSpace: 'nowrap' };
  const td = { padding: readOnly ? '9px 11px' : '5px 7px', borderBottom: `1px solid ${C.hair}`, verticalAlign: 'middle' };
  const inp = { width: '100%', fontFamily: C.sans, fontSize: 13, color: C.carbon, background: '#fff', border: `1px solid var(--border-rule)`, borderRadius: 2, padding: '7px 8px', outline: 'none', boxSizing: 'border-box' };
  if (readOnly && !rows.length) return <div style={{ fontFamily: C.serif, fontStyle: 'italic', fontSize: 14, color: C.carbon50 }}>Nothing logged yet.</div>;
  return (
    <div>
      <div style={{ border: `1px solid ${C.hair}`, overflowX: 'auto', background: '#fff' }}>
        <table style={{ width: '100%', borderCollapse: 'collapse', minWidth }}>
          <thead><tr>{columns.map(c => <th key={c.key} style={{ ...th, width: c.width }}>{c.label}</th>)}{!readOnly && <th style={{ ...th, width: 34 }}></th>}</tr></thead>
          <tbody>
            {rows.map((row, i) => (
              <tr key={i} style={rowStyle ? rowStyle(row) : undefined}>
                {columns.map(c => (
                  <td key={c.key} style={{ ...td, textAlign: c.type === 'check' ? 'center' : 'left' }}>
                    {readOnly ? <WsCellRead c={c} v={row[c.key]} row={row} /> : <WsCellEdit c={c} v={row[c.key]} onChange={v => setCell(i, c.key, v)} inp={inp} row={row} />}
                  </td>
                ))}
                {!readOnly && <td style={{ ...td, textAlign: 'center' }}><button onClick={() => setRows(rows.filter((_, n) => n !== i))} title="Remove" style={{ background: 'none', border: 'none', cursor: 'pointer', padding: 3 }}><Icon name="x" size={13} color="var(--kh-carbon-50)" /></button></td>}
              </tr>
            ))}
            {!rows.length && <tr><td colSpan={columns.length + 1} style={{ padding: '18px 12px', textAlign: 'center', fontFamily: C.serif, fontStyle: 'italic', fontSize: 14, color: C.carbon50 }}>Nothing logged yet.</td></tr>}
          </tbody>
        </table>
      </div>
      {!readOnly && <button onClick={() => setRows([...rows, { ...(newRow || {}) }])} style={wsAddBtn(C)}><Icon name="plus" size={14} /> {addLabel}</button>}
    </div>
  );
}
function WsCellRead({ c, v, row }) {
  const { C } = UI;
  if (c.type === 'check') return v ? <Icon name="check" size={15} color="var(--sch-completed)" /> : <span style={{ color: C.carbon30 }}>—</span>;
  if (c.key === 'kind') {
    if (v === 'Official') return <span style={{ fontFamily: C.sans, fontSize: 11, fontWeight: 700, letterSpacing: '0.04em', textTransform: 'uppercase', color: C.carbon }}>Official</span>;
    if (v === 'Practice') return <span style={{ fontFamily: C.sans, fontSize: 11, fontStyle: 'italic', letterSpacing: '0.02em', color: C.carbon50 }}>Practice</span>;
    return <span style={{ color: C.carbon30 }}>—</span>;
  }
  if (c.key === 'composite' && row) {
    const isOfficial = row.kind === 'Official';
    const isPractice = row.kind === 'Practice';
    return <span style={{ fontFamily: C.sans, fontSize: isOfficial ? 16 : 13, fontWeight: isOfficial ? 700 : 400, fontStyle: isPractice ? 'italic' : 'normal', color: v ? (isPractice ? C.carbon50 : C.carbon) : C.carbon50 }}>{v || '—'}</span>;
  }
  return <span style={{ fontFamily: C.sans, fontSize: 13, color: v ? C.carbon : C.carbon50 }}>{v || '—'}</span>;
}
function WsCellEdit({ c, v, onChange, inp, row }) {
  const { C } = UI;
  if (c.type === 'check') return <button onClick={() => onChange(!v)} style={{ width: 20, height: 20, borderRadius: 4, border: `1.5px solid ${v ? C.carbon : C.carbon30}`, background: v ? C.carbon : 'transparent', cursor: 'pointer', display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}>{v && <Icon name="check" size={12} color="#fff" />}</button>;
  if (c.type === 'select') {
    const kindStyle = c.key === 'kind' && v === 'Official' ? { fontWeight: 700 } : c.key === 'kind' && v === 'Practice' ? { fontStyle: 'italic', color: C.carbon50 } : null;
    return <select value={v || ''} onChange={e => onChange(e.target.value)} style={{ ...inp, cursor: 'pointer', ...(kindStyle || {}) }}><option value="">—</option>{c.options.map(o => <option key={o} value={o}>{o}</option>)}</select>;
  }
  if (c.type === 'school') return <select value={v || ''} onChange={e => onChange(e.target.value)} style={{ ...inp, cursor: 'pointer' }}><option value="">—</option>{WS_SCHOOL_OPTS.map(o => <option key={o} value={o}>{o}</option>)}</select>;
  if (c.type === 'date') return <input type="date" value={v || ''} onChange={e => onChange(e.target.value)} style={inp} />;
  if (c.key === 'composite' && row) {
    const isOfficial = row.kind === 'Official';
    const isPractice = row.kind === 'Practice';
    return <input value={v || ''} onChange={e => onChange(e.target.value)} style={{ ...inp, fontWeight: isOfficial ? 700 : 400, fontStyle: isPractice ? 'italic' : 'normal', color: isPractice ? C.carbon50 : C.carbon }} />;
  }
  return <input value={v || ''} onChange={e => onChange(e.target.value)} style={inp} />;
}

function WsAddSchool({ onAdd, present }) {
  const { C } = UI;
  const [open, setOpen] = React.useState(false);
  const ref = React.useRef(null);
  React.useEffect(() => { const h = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); }; document.addEventListener('mousedown', h); return () => document.removeEventListener('mousedown', h); }, []);
  const remaining = window.SCHOOLS ? SCHOOLS.remaining(present) : WS_SCHOOL_OPTS.filter(o => o !== 'Other' && !(present || []).map(p => String(p).toLowerCase()).includes(String(o).toLowerCase()));
  return (
    <div ref={ref} style={{ position: 'relative', display: 'inline-block', marginTop: 14 }}>
      <button onClick={() => setOpen(o => !o)} style={wsAddBtn(C)}><Icon name="plus" size={14} /> Add a school</button>
      {open && (
        <div style={{ position: 'absolute', bottom: '120%', left: 0, zIndex: 40, background: '#fff', border: `1px solid var(--border-rule)`, minWidth: 220, boxShadow: 'var(--shadow-2)', padding: 4, maxHeight: 280, overflowY: 'auto' }}>
          {remaining.map(o => <button key={o} onClick={() => { onAdd(o); setOpen(false); }} style={{ display: 'block', width: '100%', textAlign: 'left', background: 'none', border: 'none', cursor: 'pointer', padding: '8px 10px', fontFamily: C.sans, fontSize: 12.5, color: C.carbon }} onMouseEnter={e => e.currentTarget.style.background = C.porcelain} onMouseLeave={e => e.currentTarget.style.background = 'none'}>{o}</button>)}
        </div>
      )}
    </div>
  );
}

function wsTh(C) { return { padding: '9px 12px', fontFamily: C.sans, fontSize: 9.5, fontWeight: 600, letterSpacing: '0.08em', textTransform: 'uppercase', color: C.carbon50 }; }
function wsTd(C, bold) { return { padding: '11px 12px', fontFamily: bold ? C.sans : C.serif, fontSize: bold ? 13.5 : 14, fontWeight: bold ? 500 : 400, color: C.carbon, lineHeight: 1.5 }; }
function wsCellArea(C) { return { width: '100%', fontFamily: C.serif, fontSize: 14, lineHeight: 1.55, color: C.carbon, background: '#fff', border: 'none', borderRadius: 0, padding: '10px 12px', outline: 'none', resize: 'vertical', boxSizing: 'border-box' }; }
function wsAddBtn(C) { return { display: 'inline-flex', alignItems: 'center', gap: 8, marginTop: 12, background: '#fff', border: `1px dashed ${C.carbon30}`, padding: '9px 14px', cursor: 'pointer', fontFamily: C.sans, fontSize: 11.5, fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase', color: C.carbon70, borderRadius: 2 }; }

window.WsTable = WsTable;
window.RecommenderWorksheet = RecommenderWorksheet;
window.EngagementWorksheet = EngagementWorksheet;
window.EngagementTracker = EngagementTracker;

/* =================== TEST SCORE LOG ====================================== */
function TestLog({ onNavigate, readOnly, clientId }) {
  const { C } = UI;
  const D = WORKSHEETS.testLog;
  // Seed from the questionnaire's test scores the first time; thereafter use the log.
  const seed = () => {
    try {
      const s = window.KHSync && KHSync.read(clientId || (KHSync && KHSync.DEMO_ID));
      const q = s && s.questionnaire && s.questionnaire.answers && s.questionnaire.answers.testScores;
      if (Array.isArray(q) && q.length) return q.map(r => ({ date: r.date || '', test: r.test || '', kind: 'Official', composite: r.composite || '', sections: r.sections || '', fromQuestionnaire: true }));
    } catch (e) {}
    return [];
  };
  const [rows, setRows, saved] = useWorksheet('testLog', seed, clientId);

  // Pull in any questionnaire tests that aren't yet in the log (e.g. added after first load)
  React.useEffect(() => {
    if (readOnly) return;
    try {
      const s = KHSync.read(clientId || KHSync.DEMO_ID);
      const q = (s && s.questionnaire && s.questionnaire.answers && s.questionnaire.answers.testScores) || [];
      const sig = r => [r.date, r.test, r.composite].join('|');
      const have = new Set(rows.map(sig));
      const missing = q.filter(r => (r.date || r.test || r.composite) && !have.has(sig({ date: r.date || '', test: r.test || '', composite: r.composite || '' }))).map(r => ({ date: r.date || '', test: r.test || '', kind: 'Official', composite: r.composite || '', sections: r.sections || '', fromQuestionnaire: true }));
      if (missing.length) setRows([...rows, ...missing]);
    } catch (e) {}
  }, []);

  return (
    <div className="kh-fade" style={{ maxWidth: 1000, margin: '0 auto', padding: readOnly ? '24px 24px' : '4px 4px 60px' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', gap: 16, flexWrap: 'wrap' }}>
        <WsHeader eyebrow="Track · testing history" title={D.title} intro={readOnly ? null : D.intro} />
        {!readOnly && <div style={{ paddingBottom: 24 }}><WsSaveBadge saved={saved} /></div>}
      </div>
      <WsTable columns={D.columns} rows={rows} setRows={setRows} readOnly={readOnly} addLabel="Add a test sitting" minWidth={820} rowStyle={row => row.kind === 'Practice' ? { opacity: 0.82 } : undefined} />
      {!readOnly && rows.some(r => r.fromQuestionnaire) && (
        <p style={{ fontFamily: C.serif, fontStyle: 'italic', fontSize: 12.5, lineHeight: 1.5, color: C.carbon50, marginTop: 12 }}>Tests carried over from your kickoff questionnaire are shown here. Edit or add to them anytime.</p>
      )}
    </div>
  );
}
window.TestLog = TestLog;

/* =================== KELLOGG VIDEO PREP WORKSHEET ======================== */
function VideoPrepWorksheet({ onNavigate, readOnly, clientId, variant = 'kellogg' }) {
  const { C } = UI;
  const D = variant === 'mit' ? WORKSHEETS.mitVideoPrep : WORKSHEETS.videoPrep;
  const kp = variant === 'mit' ? 'mvp' : 'vp';
  const full = variant !== 'mit';
  const [selling, setSelling, s1] = useWorksheet(kp + 'Selling', () => ['', '', '', '', ''], clientId);
  const [core, setCore, s2] = useWorksheet('vpCore', {}, clientId);
  const [stories, setStories, s3] = useWorksheet(kp + 'Stories', () => [blankVpStory()], clientId);
  const [strengths, setStrengths, s4] = useWorksheet('vpStrengths', () => [{ strength: '', dev: '' }, { strength: '', dev: '' }, { strength: '', dev: '' }], clientId);
  const [funFacts, setFunFacts, s5] = useWorksheet('vpFunFacts', () => ['', '', ''], clientId);
  const saved = full
    ? ([s1, s2, s3, s4, s5].includes('saving') ? 'saving' : [s1, s2, s3, s4, s5].includes('saved') ? 'saved' : 'idle')
    : ([s1, s3].includes('saving') ? 'saving' : [s1, s3].includes('saved') ? 'saved' : 'idle');

  const setStory = (i, patch) => setStories(stories.map((s, n) => n === i ? { ...s, ...patch } : s));
  const setStrength = (i, patch) => setStrengths(strengths.map((s, n) => n === i ? { ...s, ...patch } : s));

  return (
    <div className="kh-fade" style={{ padding: '40px 40px 72px', maxWidth: 960, margin: '0 auto' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', gap: 16, flexWrap: 'wrap' }}>
        <WsHeader eyebrow="Prep · video essays" title={D.title} intro={readOnly ? null : D.intro} />
        <div style={{ display: 'flex', alignItems: 'center', gap: 14, paddingBottom: 24 }}>
          {!readOnly && <WsSaveBadge saved={saved} />}
          <button onClick={() => window.downloadVideoPrepDoc && window.downloadVideoPrepDoc(clientId, null, variant)}
            style={{ display: 'inline-flex', alignItems: 'center', gap: 7, background: '#fff', border: `1px solid ${C.hair}`, cursor: 'pointer', padding: '9px 14px', fontFamily: C.sans, fontSize: 10.5, fontWeight: 600, letterSpacing: '0.1em', textTransform: 'uppercase', color: C.carbon, borderRadius: 2, whiteSpace: 'nowrap' }}>
            <Icon name="download" size={14} color="var(--kh-carbon)" /> Download as Word
          </button>
        </div>
      </div>

      {/* Key selling points */}
      <div style={{ border: `1px solid ${C.hair}`, marginBottom: 24 }}>
        <div style={{ padding: '14px 20px', background: C.carbon }}>
          <span style={{ fontFamily: C.sans, fontSize: 10, fontWeight: 600, letterSpacing: '0.16em', textTransform: 'uppercase', color: C.clay }}>Key selling points</span>
        </div>
        <div style={{ padding: '18px 22px' }}>
          <p style={{ fontFamily: C.serif, fontStyle: 'italic', fontSize: 13.5, lineHeight: 1.5, color: C.carbon50, margin: '0 0 14px' }}>{D.sellingPrompt}</p>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            {selling.map((sp, i) => (
              <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                <span style={{ fontFamily: C.sans, fontSize: 11, fontWeight: 600, color: C.carbon50, width: 18, textAlign: 'right' }}>{i + 1}</span>
                {readOnly
                  ? <span style={{ flex: 1, fontFamily: C.serif, fontSize: 14.5, color: sp ? C.carbon : C.carbon50 }}>{sp || '—'}</span>
                  : <input value={sp} onChange={e => setSelling(selling.map((x, n) => n === i ? e.target.value : x))} style={{ flex: 1, fontFamily: C.sans, fontSize: 14, color: C.carbon, border: `1px solid var(--border-rule)`, borderRadius: 2, padding: '9px 11px', outline: 'none' }} />}
                {!readOnly && selling.length > 1 && <button onClick={() => setSelling(selling.filter((_, n) => n !== i))} title="Remove" style={{ background: 'none', border: 'none', cursor: 'pointer', padding: 4 }}><Icon name="x" size={14} color="var(--kh-carbon-50)" /></button>}
              </div>
            ))}
          </div>
          {!readOnly && selling.length < 10 && <button onClick={() => setSelling([...selling, ''])} style={wsAddBtn(C)}><Icon name="plus" size={13} /> Add a selling point</button>}
        </div>
      </div>

      {/* Core questions */}
      {full && <>
      <div className="kh-eyebrow" style={{ marginBottom: 12 }}>Core questions</div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 16, marginBottom: 30 }}>
        {D.coreQuestions.map(q => (
          <WsField key={q.id} label={q.label} help={q.help} big readOnly={readOnly} value={core[q.id] || ''} onChange={v => setCore({ ...core, [q.id]: v })} />
        ))}
      </div>
      </>}

      {/* STAR stories */}
      <div className="kh-eyebrow" style={{ marginBottom: 6 }}>STAR stories</div>
      <p style={{ fontFamily: C.serif, fontStyle: 'italic', fontSize: 13.5, lineHeight: 1.5, color: C.carbon50, margin: '0 0 14px' }}>{D.storyPrompt}</p>
      {stories.map((st, i) => (
        <div key={i} style={{ border: `1px solid ${C.hair}`, marginBottom: 16 }}>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12, padding: '13px 18px', background: C.porcelain, borderBottom: `1px solid ${C.hair}` }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 12, flex: 1 }}>
              <span style={{ fontFamily: C.sans, fontSize: 10, fontWeight: 600, letterSpacing: '0.14em', textTransform: 'uppercase', color: C.clayDeep, whiteSpace: 'nowrap' }}>Story {i + 1}</span>
              {readOnly
                ? <span style={{ fontFamily: C.sans, fontSize: 14, fontWeight: 500, color: C.carbon }}>{st.title || '—'}</span>
                : <input value={st.title} onChange={e => setStory(i, { title: e.target.value })} placeholder="Short title" style={{ flex: 1, maxWidth: 340, fontFamily: C.sans, fontSize: 13.5, color: C.carbon, border: `1px solid var(--border-rule)`, borderRadius: 2, padding: '7px 10px', outline: 'none' }} />}
            </div>
            {!readOnly && stories.length > 1 && <button onClick={() => setStories(stories.filter((_, n) => n !== i))} title="Remove" style={{ background: 'none', border: 'none', cursor: 'pointer', padding: 4 }}><Icon name="x" size={15} color="var(--kh-carbon-50)" /></button>}
          </div>
          <div style={{ padding: '16px 20px', display: 'flex', flexDirection: 'column', gap: 12 }}>
            <WsField label="Selling point(s) this proves" readOnly={readOnly} value={st.sellingPoint || ''} onChange={v => setStory(i, { sellingPoint: v })} placeholder="Which of your key selling points does this story demonstrate?" />
            {[['situation', 'Situation'], ['task', 'Task'], ['action', 'Action'], ['result', 'Result']].map(([k, lbl]) => (
              <WsField key={k} label={lbl} readOnly={readOnly} value={st[k] || ''} onChange={v => setStory(i, { [k]: v })} />
            ))}
          </div>
        </div>
      ))}
      {!readOnly && <button onClick={() => setStories([...stories, blankVpStory()])} style={wsAddBtn(C)}><Icon name="plus" size={14} /> Add a STAR story</button>}

      {full && <>
      {/* Strengths & development areas */}
      <div className="kh-eyebrow" style={{ margin: '32px 0 6px' }}>Strengths &amp; development areas</div>
      <p style={{ fontFamily: C.serif, fontStyle: 'italic', fontSize: 13.5, lineHeight: 1.5, color: C.carbon50, margin: '0 0 14px' }}>{D.strengthPrompt}</p>
      <div style={{ border: `1px solid ${C.hair}` }}>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', background: C.porcelain, borderBottom: `1px solid ${C.hair}` }}>
          <div style={wsTh(C)}>Strength</div><div style={{ ...wsTh(C), borderLeft: `1px solid ${C.hair}` }}>Development area</div>
        </div>
        {strengths.map((s, i) => (
          <div key={i} style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', borderBottom: i < strengths.length - 1 ? `1px solid ${C.hair}` : 'none' }}>
            {readOnly ? (
              <>
                <div style={wsTd(C, true)}>{s.strength || '—'}</div>
                <div style={{ ...wsTd(C), borderLeft: `1px solid ${C.hair}` }}>{s.dev || '—'}</div>
              </>
            ) : (
              <>
                <textarea value={s.strength} onChange={e => setStrength(i, { strength: e.target.value })} rows={2} style={wsCellArea(C)} placeholder={i === 0 ? 'A strength tied to a selling point' : ''} />
                <textarea value={s.dev} onChange={e => setStrength(i, { dev: e.target.value })} rows={2} style={{ ...wsCellArea(C), borderLeft: `1px solid ${C.hair}` }} placeholder={i === 0 ? 'A genuine development area' : ''} />
              </>
            )}
          </div>
        ))}
      </div>
      {!readOnly && <button onClick={() => setStrengths([...strengths, { strength: '', dev: '' }])} style={wsAddBtn(C)}><Icon name="plus" size={13} /> Add a row</button>}

      {/* Fun facts */}
      <div className="kh-eyebrow" style={{ margin: '32px 0 6px' }}>Fun facts</div>
      <p style={{ fontFamily: C.serif, fontStyle: 'italic', fontSize: 13.5, lineHeight: 1.5, color: C.carbon50, margin: '0 0 14px' }}>{D.funFactsPrompt}</p>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
        {funFacts.map((f, i) => (
          <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <span style={{ fontFamily: C.sans, fontSize: 11, fontWeight: 600, color: C.carbon50, width: 18, textAlign: 'right' }}>{i + 1}</span>
            {readOnly
              ? <span style={{ flex: 1, fontFamily: C.serif, fontSize: 14.5, color: f ? C.carbon : C.carbon50 }}>{f || '—'}</span>
              : <input value={f} onChange={e => setFunFacts(funFacts.map((x, n) => n === i ? e.target.value : x))} style={{ flex: 1, fontFamily: C.sans, fontSize: 14, color: C.carbon, border: `1px solid var(--border-rule)`, borderRadius: 2, padding: '9px 11px', outline: 'none' }} />}
            {!readOnly && funFacts.length > 1 && <button onClick={() => setFunFacts(funFacts.filter((_, n) => n !== i))} title="Remove" style={{ background: 'none', border: 'none', cursor: 'pointer', padding: 4 }}><Icon name="x" size={14} color="var(--kh-carbon-50)" /></button>}
          </div>
        ))}
      </div>
      {!readOnly && <button onClick={() => setFunFacts([...funFacts, ''])} style={wsAddBtn(C)}><Icon name="plus" size={13} /> Add a fun fact</button>}
      </>}

      {!readOnly && (
        <div style={{ marginTop: 30, border: `1px solid ${C.hair}`, background: C.porcelain, padding: '16px 20px', display: 'flex', gap: 12, alignItems: 'flex-start' }}>
          <Icon name="message" size={17} color="var(--kh-clay-deep)" style={{ marginTop: 1 }} />
          <div style={{ fontFamily: C.serif, fontSize: 14, lineHeight: 1.55, color: C.carbon70 }}>
            When you have a first pass, share it with me using the Download as Word button above (or upload it in My Files). We’ll iterate a few times, then schedule at least two live practice sessions with feedback.
          </div>
        </div>
      )}
    </div>
  );
}
function blankVpStory() { return { title: '', sellingPoint: '', situation: '', task: '', action: '', result: '' }; }
window.VideoPrepWorksheet = VideoPrepWorksheet;
