/* =============================================================================
   portal/AppWorksheet.jsx — per-school Application Worksheet.
   Renders the school's schema (window.appWorksheetFor), auto-saves to the shared
   store (worksheet key appws-<slug>), and exports the whole thing to Word.
   Used in the school module ("Application Worksheet" tab) and read-only in admin.
   ============================================================================= */

function AppWorksheet({ slug, clientId, readOnly }) {
  const { C } = UI;
  const D = (window.appWorksheetFor ? appWorksheetFor(slug) : { title: 'Application Worksheet', sections: [] });
  const key = 'appws-' + slug;
  const [val, setVal, saved] = useWorksheet(key, {}, clientId);
  const set = (id, v) => setVal(Object.assign({}, val, { [id]: v }));
  const schoolName = (window.SCHOOLS && SCHOOLS.canonical(slug)) || slug;

  return (
    <div className="kh-fade" style={{ maxWidth: 920, margin: '0 auto', padding: readOnly ? '8px 0 0' : '4px 0 40px' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', gap: 16, flexWrap: 'wrap', marginBottom: 8 }}>
        {!readOnly && <p style={{ fontFamily: C.serif, fontSize: 15.5, lineHeight: 1.6, color: C.carbon70, margin: 0, maxWidth: 680 }}>{D.intro}</p>}
        {!readOnly && (
          <div style={{ display: 'flex', alignItems: 'center', gap: 14, flexShrink: 0 }}>
            <WsSaveBadge saved={saved} />
            <button onClick={() => window.downloadAppWorksheetDoc && window.downloadAppWorksheetDoc(slug, 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>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 28, marginTop: 24 }}>
        {D.sections.map(sec => (
          <div key={sec.id}>
            <div className="kh-eyebrow" style={{ marginBottom: sec.note ? 6 : 14 }}>{sec.title}</div>
            {sec.note && <p style={{ fontFamily: C.serif, fontSize: 13, lineHeight: 1.5, color: C.carbon50, margin: '0 0 14px', maxWidth: 680 }}>{sec.note}</p>}
            <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
              {sec.fields.map(f => {
                if (f.when) {
                  const g = val[f.when];
                  const ans = g && (typeof g === 'object' ? g.ans : g);
                  if (ans !== 'Yes') return null;
                }
                return <AppField key={f.id} f={f} value={val[f.id]} onChange={(v) => set(f.id, v)} readOnly={readOnly} />;
              })}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

// A label that ends in a parenthetical character/word/limit hint (e.g. "...
// shaped you (250 characters)") renders that part as a de-emphasized caption
// instead of jamming it into the bold label text.
function splitLabelLimit(label) {
  const m = /^(.*?)\s*(\([^()]*(?:character|word|limit)[^()]*\))\s*$/i.exec(label);
  return m ? { main: m[1], limit: m[2] } : { main: label, limit: null };
}

function AppField({ f, value, onChange, readOnly }) {
  const { C } = UI;
  const cond = f.when ? value : null; // for yesno repeaters gated by a prior answer (handled inline below)
  const { main: labelMain, limit: labelLimit } = splitLabelLimit(f.label);
  const label = (
    <div style={{ marginBottom: 7 }}>
      <label style={{ fontFamily: C.sans, fontWeight: 600, fontSize: 13, color: C.carbon }}>{labelMain}</label>
      {labelLimit && <p style={{ fontFamily: C.serif, fontSize: 13, lineHeight: 1.5, color: C.carbon70, margin: '4px 0 0' }}>{labelLimit}</p>}
      {f.help && <p style={{ fontFamily: C.serif, fontSize: 13, lineHeight: 1.5, color: C.carbon70, margin: '4px 0 0' }}>{f.help}</p>}
    </div>
  );
  const area = { width: '100%', fontFamily: C.serif, fontSize: 15, lineHeight: 1.6, color: C.carbon, background: readOnly ? 'transparent' : '#fff', border: readOnly ? 'none' : `1px solid var(--border-rule)`, borderRadius: 2, padding: readOnly ? 0 : '11px 13px', outline: 'none', resize: 'vertical', boxSizing: 'border-box' };
  const inp = { width: '100%', fontFamily: C.sans, fontSize: 13.5, color: C.carbon, background: readOnly ? 'transparent' : '#fff', border: readOnly ? 'none' : `1px solid var(--border-rule)`, borderRadius: 2, padding: readOnly ? 0 : '9px 11px', outline: 'none', boxSizing: 'border-box' };

  if (readOnly) {
    return (
      <div>{label}<AppFieldReadOnly f={f} value={value} C={C} /></div>
    );
  }

  if (f.type === 'text') return <div>{label}<input value={value || ''} onChange={e => onChange(e.target.value)} style={inp} /></div>;
  if (f.type === 'textarea') return <div>{label}<textarea rows={4} value={value || ''} onChange={e => onChange(e.target.value)} style={{ ...area, minHeight: 92 }} /></div>;
  if (f.type === 'select') return (
    <div>{label}<select value={value || ''} onChange={e => onChange(e.target.value)} style={{ ...inp, cursor: 'pointer', maxWidth: 320 }}>
      <option value="">Select…</option>
      {f.optionGroups
        ? f.optionGroups.map(g => <optgroup key={g.group} label={g.group}>{g.options.map(o => <option key={o} value={o}>{o}</option>)}</optgroup>)
        : f.options.map(o => <option key={o} value={o}>{o}</option>)}
    </select></div>
  );
  if (f.type === 'yesno') {
    const v = value || {};
    return (
      <div>{label}
        <div style={{ display: 'flex', gap: 10, marginBottom: v.ans === 'Yes' ? 10 : 0 }}>
          {['Yes', 'No'].map(opt => {
            const on = v.ans === opt;
            return <button key={opt} onClick={() => onChange({ ...v, ans: opt })} style={{ fontFamily: C.sans, fontSize: 12.5, fontWeight: 600, padding: '7px 18px', cursor: 'pointer', borderRadius: 999, border: `1px solid ${on ? C.carbon : 'var(--border-rule)'}`, background: on ? C.carbon : '#fff', color: on ? '#fff' : C.carbon70 }}>{opt}</button>;
          })}
        </div>
        {v.ans === 'Yes' && f.explainLabel && <div>
          <textarea rows={3} placeholder={f.explainLabel} value={v.explain || ''} onChange={e => onChange({ ...v, explain: e.target.value })} style={{ ...area, minHeight: 72 }} />
          {f.explainMax && <div style={{ fontFamily: C.sans, fontSize: 10.5, color: (v.explain || '').length > f.explainMax ? 'var(--st-alert, #a35a3a)' : C.carbon50, textAlign: 'right', marginTop: 4 }}>{(v.explain || '').length} / {f.explainMax} characters</div>}
        </div>}
      </div>
    );
  }
  if (f.type === 'repeater') return <AppRepeater f={f} value={value} onChange={onChange} />;
  if (f.type === 'table') return <div>{label}<WsTable columns={f.columns} rows={Array.isArray(value) ? value : []} setRows={onChange} readOnly={false} addLabel={'Add a row'} minWidth={760} /></div>;
  return null;
}

function AppRepeater({ f, value, onChange }) {
  const { C } = UI;
  const rows = Array.isArray(value) ? value : [];
  const setCell = (i, k, v) => onChange(rows.map((r, n) => n === i ? { ...r, [k]: v } : r));
  const add = () => onChange([...rows, {}]);
  const remove = (i) => onChange(rows.filter((_, n) => n !== i));
  const inp = { width: '100%', fontFamily: C.sans, fontSize: 13.5, color: C.carbon, background: '#fff', border: `1px solid var(--border-rule)`, borderRadius: 2, padding: '9px 11px', outline: 'none', boxSizing: 'border-box' };
  const area = { ...inp, fontFamily: C.serif, fontSize: 14.5, lineHeight: 1.55, resize: 'vertical', minHeight: 70 };
  return (
    <div>
      <div style={{ marginBottom: 8 }}>
        <label style={{ fontFamily: C.sans, fontWeight: 600, fontSize: 13, color: C.carbon }}>{splitLabelLimit(f.label).main}</label>
        {splitLabelLimit(f.label).limit && <p style={{ fontFamily: C.serif, fontSize: 13, lineHeight: 1.5, color: C.carbon70, margin: '4px 0 0' }}>{splitLabelLimit(f.label).limit}</p>}
        {f.help && <p style={{ fontFamily: C.serif, fontSize: 13, lineHeight: 1.5, color: C.carbon70, margin: '4px 0 0' }}>{f.help}</p>}
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        {rows.map((row, i) => (
          <div key={i} style={{ border: `1px solid ${C.hair}`, background: '#fbfaf7', padding: '14px 16px', position: 'relative' }}>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 12, paddingRight: 26 }}>
              {f.sub.map(sf => {
                if (sf.type === 'yesno') {
                  const on = row[sf.key];
                  return (
                    <div key={sf.key} style={{ display: 'flex', flexDirection: 'column', gap: 6, flex: '1 1 100%' }}>
                      <span style={{ fontFamily: C.sans, fontSize: 9, fontWeight: 600, letterSpacing: '0.1em', textTransform: 'uppercase', color: C.carbon50 }}>{sf.label}</span>
                      <div style={{ display: 'flex', gap: 10 }}>
                        {['Yes', 'No'].map(opt => (
                          <button key={opt} onClick={() => setCell(i, sf.key, opt)} style={{ fontFamily: C.sans, fontSize: 12.5, fontWeight: 600, padding: '7px 18px', cursor: 'pointer', borderRadius: 999, border: `1px solid ${on === opt ? C.carbon : 'var(--border-rule)'}`, background: on === opt ? C.carbon : '#fff', color: on === opt ? '#fff' : C.carbon70 }}>{opt}</button>
                        ))}
                      </div>
                      {on === 'Yes' && sf.explainKey && (() => {
                        const words = (row[sf.explainKey] || '').trim().split(/\s+/).filter(Boolean).length;
                        return (
                          <div style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
                            <span style={{ fontFamily: C.sans, fontSize: 9, fontWeight: 600, letterSpacing: '0.1em', textTransform: 'uppercase', color: C.carbon50 }}>{sf.explainLabel}{sf.explainWordMax ? ` (${sf.explainWordMax} word limit)` : ''}</span>
                            <textarea rows={3} value={row[sf.explainKey] || ''} onChange={e => setCell(i, sf.explainKey, e.target.value)} style={area} />
                            {sf.explainWordMax && <div style={{ fontFamily: C.sans, fontSize: 10.5, color: words > sf.explainWordMax ? 'var(--st-alert, #a35a3a)' : C.carbon50, textAlign: 'right', marginTop: 4 }}>{words} / {sf.explainWordMax} words</div>}
                          </div>
                        );
                      })()}
                    </div>
                  );
                }
                return (
                <label key={sf.key} style={{ display: 'flex', flexDirection: 'column', gap: 5, flex: sf.type === 'textarea' ? '1 1 100%' : '1 1 200px' }}>
                  <span style={{ fontFamily: C.sans, fontSize: 9, fontWeight: 600, letterSpacing: '0.1em', textTransform: 'uppercase', color: C.carbon50 }}>{sf.label}</span>
                  {sf.type === 'textarea' ? <textarea rows={3} value={row[sf.key] || ''} onChange={e => setCell(i, sf.key, e.target.value)} style={area} />
                    : sf.type === 'select' ? <select value={row[sf.key] || ''} onChange={e => setCell(i, sf.key, e.target.value)} style={{ ...inp, cursor: 'pointer' }}><option value="">Select…</option>{sf.optionGroups ? sf.optionGroups.map(g => <optgroup key={g.group} label={g.group}>{g.options.map(o => <option key={o} value={o}>{o}</option>)}</optgroup>) : sf.options.map(o => <option key={o} value={o}>{o}</option>)}</select>
                    : <input value={row[sf.key] || ''} onChange={e => setCell(i, sf.key, e.target.value)} style={inp} />}
                </label>
                );
              })}
            </div>
            <button onClick={() => remove(i)} title="Remove" style={{ position: 'absolute', top: 10, right: 10, background: 'none', border: 'none', cursor: 'pointer', padding: 4 }}><Icon name="x" size={15} color="var(--kh-carbon-50)" /></button>
          </div>
        ))}
        {rows.length < (f.max || 99) && (
          <button onClick={add} style={{ display: 'inline-flex', alignItems: 'center', gap: 8, alignSelf: 'flex-start', background: '#fff', border: `1px dashed ${C.carbon30}`, padding: '9px 14px', cursor: 'pointer', fontFamily: C.sans, fontSize: 11, fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase', color: C.carbon70, borderRadius: 2 }}>
            <Icon name="plus" size={13} /> {f.addLabel || 'Add'}
          </button>
        )}
      </div>
    </div>
  );
}

function AppFieldReadOnly({ f, value, C }) {
  const empty = <span style={{ fontFamily: C.serif, fontStyle: 'italic', fontSize: 14, color: C.carbon50 }}>Not answered</span>;
  if (f.type === 'yesno') {
    const v = value || {};
    if (!v.ans) return empty;
    return <div style={{ fontFamily: C.sans, fontSize: 14, color: C.carbon }}>{v.ans}{v.explain ? <div style={{ fontFamily: C.serif, marginTop: 4, color: C.carbon70, whiteSpace: 'pre-wrap' }}>{v.explain}</div> : null}</div>;
  }
  if (f.type === 'repeater') {
    const rows = Array.isArray(value) ? value : [];
    if (!rows.length) return empty;
    return <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>{rows.map((r, i) => (
      <div key={i} style={{ border: `1px solid ${C.hair}`, padding: '10px 13px' }}>{f.sub.map(sf => {
        if (sf.type === 'yesno') return r[sf.key] ? <div key={sf.key} style={{ marginBottom: 4 }}><span style={{ fontFamily: C.sans, fontSize: 10, letterSpacing: '0.06em', textTransform: 'uppercase', color: C.carbon50 }}>{sf.label}: </span><span style={{ fontFamily: C.serif, fontSize: 14, color: C.carbon }}>{r[sf.key]}</span>{r[sf.key] === 'Yes' && sf.explainKey && r[sf.explainKey] ? <div style={{ fontFamily: C.serif, fontSize: 14, marginTop: 3, color: C.carbon70, whiteSpace: 'pre-wrap' }}>{r[sf.explainKey]}</div> : null}</div> : null;
        return r[sf.key] ? <div key={sf.key} style={{ marginBottom: 4 }}><span style={{ fontFamily: C.sans, fontSize: 10, letterSpacing: '0.06em', textTransform: 'uppercase', color: C.carbon50 }}>{sf.label}: </span><span style={{ fontFamily: C.serif, fontSize: 14, color: C.carbon }}>{r[sf.key]}</span></div> : null;
      })}</div>
    ))}</div>;
  }
  if (f.type === 'table') {
    const rows = Array.isArray(value) ? value : [];
    if (!rows.length) return empty;
    return <div style={{ border: `1px solid ${C.hair}`, overflowX: 'auto' }}><table style={{ width: '100%', borderCollapse: 'collapse', minWidth: 560 }}><thead><tr>{f.columns.map(c => <th key={c.key} style={{ textAlign: 'left', padding: '7px 10px', fontFamily: C.sans, fontSize: 9, fontWeight: 600, letterSpacing: '0.06em', textTransform: 'uppercase', color: C.carbon50, borderBottom: `1px solid ${C.rule}` }}>{c.label}</th>)}</tr></thead><tbody>{rows.map((r, i) => <tr key={i}>{f.columns.map(c => <td key={c.key} style={{ padding: '7px 10px', borderBottom: `1px solid ${C.hair}`, fontFamily: C.sans, fontSize: 13, color: r[c.key] ? C.carbon : C.carbon50 }}>{r[c.key] || '—'}</td>)}</tr>)}</tbody></table></div>;
  }
  if (value == null || String(value).trim() === '') return empty;
  return <div style={{ fontFamily: f.type === 'textarea' ? C.serif : C.sans, fontSize: 14.5, lineHeight: 1.6, color: C.carbon, whiteSpace: 'pre-wrap' }}>{String(value)}</div>;
}

window.AppWorksheet = AppWorksheet;

/* =================== INTERVIEW PREPARATION WORKSHEET ===================== */
// Hoisted to module scope (not defined inside InterviewWorksheet's render body) --
// a component defined inline in JSX gets a fresh function identity every render,
// so React treated every keystroke's re-render as a brand-new component type and
// remounted the textarea, dropping focus after each character.
function QBlock({ q, value, onChange, readOnly, area }) {
  const { C } = UI;
  return (
    <div>
      <div style={{ marginBottom: 7 }}>
        <label style={{ fontFamily: C.sans, fontWeight: 600, fontSize: 13.5, color: C.carbon }}>{q.label}</label>
        {q.help && !readOnly && <p style={{ fontFamily: C.serif, fontSize: 13, lineHeight: 1.5, color: C.carbon70, margin: '4px 0 0' }}>{q.help}</p>}
      </div>
      {readOnly
        ? ((value && String(value).trim()) ? <div style={{ fontFamily: C.serif, fontSize: 14.5, lineHeight: 1.6, color: C.carbon, whiteSpace: 'pre-wrap' }}>{value}</div> : <span style={{ fontFamily: C.serif, fontStyle: 'italic', fontSize: 14, color: C.carbon50 }}>Not answered</span>)
        : <textarea rows={4} value={value || ''} onChange={e => onChange(e.target.value)} style={area} />}
    </div>
  );
}
function InterviewWorksheet({ onNavigate, clientId, readOnly }) {
  const { C } = UI;
  const D = WORKSHEETS.interview;
  const [general, setGeneral, s1] = useWorksheet('ivGeneral', {}, clientId);
  const [personal, setPersonal, s2] = useWorksheet('ivPersonal', {}, clientId);
  const [stories, setStories, s3] = useWorksheet('ivStories', [], clientId);
  const [schools, setSchools, s4] = useWorksheet('ivSchools', [], clientId);
  const saved = [s1, s2, s3, s4].includes('saving') ? 'saving' : [s1, s2, s3, s4].includes('saved') ? 'saved' : 'idle';

  const area = { width: '100%', fontFamily: C.serif, fontSize: 15, lineHeight: 1.6, color: C.carbon, background: readOnly ? 'transparent' : '#fff', border: readOnly ? 'none' : `1px solid var(--border-rule)`, borderRadius: 2, padding: readOnly ? 0 : '11px 13px', outline: 'none', resize: 'vertical', minHeight: readOnly ? 0 : 96, boxSizing: 'border-box' };

  const addStory = () => setStories([...(stories || []), {}]);
  const setStory = (i, k, v) => setStories(stories.map((s, n) => n === i ? { ...s, [k]: v } : s));
  const STAR = [['situation', 'Situation'], ['task', 'Task'], ['action', 'Action'], ['result', 'Result']];

  const remaining = (window.SCHOOLS ? SCHOOLS.remaining(schools.map(s => s.name)) : []);
  const addSchool = (name) => { const e = window.SCHOOLS && SCHOOLS.resolve(name); setSchools([...schools, { key: e ? e.key : name, name: e ? e.name : name, short: e ? e.short : name, answers: {} }]); };
  const setSchoolAns = (i, k, v) => setSchools(schools.map((s, n) => n === i ? { ...s, answers: { ...s.answers, [k]: v } } : s));

  return (
    <div className="kh-fade" style={{ maxWidth: 920, margin: '0 auto', padding: readOnly ? '8px 0 0' : '4px 0 40px' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', gap: 16, flexWrap: 'wrap', marginBottom: 8 }}>
        {!readOnly && <p style={{ fontFamily: C.serif, fontSize: 15.5, lineHeight: 1.6, color: C.carbon70, margin: 0, maxWidth: 680 }}>{D.intro}</p>}
        {!readOnly && (
          <div style={{ display: 'flex', alignItems: 'center', gap: 14, flexShrink: 0 }}>
            <WsSaveBadge saved={saved} />
            <button onClick={() => window.downloadInterviewDoc && window.downloadInterviewDoc(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>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 30, marginTop: 24 }}>
        <div>
          <div className="kh-eyebrow" style={{ marginBottom: 14 }}>General questions</div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
            {D.general.map(q => <QBlock key={q.id} q={q} value={general[q.id]} onChange={v => setGeneral({ ...general, [q.id]: v })} readOnly={readOnly} area={area} />)}
          </div>
        </div>

        <div>
          <div className="kh-eyebrow" style={{ marginBottom: 14 }}>Personal qualities</div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
            {D.personal.map(q => <QBlock key={q.id} q={q} value={personal[q.id]} onChange={v => setPersonal({ ...personal, [q.id]: v })} readOnly={readOnly} area={area} />)}
          </div>
        </div>

        <div>
          <div className="kh-eyebrow" style={{ marginBottom: 8 }}>Behavioral questions · STAR stories</div>
          {!readOnly && (
            <div style={{ background: C.porcelain, border: `1px solid ${C.hair}`, padding: '14px 16px', marginBottom: 16 }}>
              <p style={{ fontFamily: C.serif, fontSize: 13.5, lineHeight: 1.55, color: C.carbon70, margin: '0 0 8px' }}>{D.behavioralNote}</p>
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
                {D.behavioralPrompts.map((p, i) => <span key={i} style={{ fontFamily: C.sans, fontSize: 11, color: C.carbon70, background: '#fff', border: `1px solid ${C.hair}`, borderRadius: 999, padding: '4px 10px' }}>{p}</span>)}
              </div>
            </div>
          )}
          <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
            {(stories || []).map((st, i) => (
              <div key={i} style={{ border: `1px solid ${C.hair}`, background: readOnly ? '#fff' : '#fbfaf7', padding: '14px 16px', position: 'relative' }}>
                <div style={{ fontFamily: C.sans, fontWeight: 600, fontSize: 12, letterSpacing: '0.04em', color: C.carbon, marginBottom: 10 }}>STAR Story #{i + 1}{st.title ? ' — ' + st.title : ''}</div>
                {!readOnly && <input value={st.title || ''} onChange={e => setStory(i, 'title', e.target.value)} placeholder="Short title (e.g. Turned around the stalled launch)" style={{ width: '100%', fontFamily: C.sans, fontSize: 13, color: C.carbon, border: `1px solid var(--border-rule)`, borderRadius: 2, padding: '8px 10px', outline: 'none', marginBottom: 10, boxSizing: 'border-box' }} />}
                <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                  {STAR.map(([k, lbl]) => (
                    <div key={k}>
                      <div style={{ fontFamily: C.sans, fontSize: 9, fontWeight: 600, letterSpacing: '0.1em', textTransform: 'uppercase', color: C.carbon50, marginBottom: 3 }}>{lbl}</div>
                      {readOnly
                        ? ((st[k] && String(st[k]).trim()) ? <div style={{ fontFamily: C.serif, fontSize: 14, lineHeight: 1.55, color: C.carbon, whiteSpace: 'pre-wrap' }}>{st[k]}</div> : <span style={{ fontFamily: C.serif, fontStyle: 'italic', fontSize: 13.5, color: C.carbon50 }}>—</span>)
                        : <textarea rows={2} value={st[k] || ''} onChange={e => setStory(i, k, e.target.value)} style={{ ...area, minHeight: 56 }} />}
                    </div>
                  ))}
                </div>
                {!readOnly && <button onClick={() => setStories(stories.filter((_, n) => n !== i))} title="Remove" style={{ position: 'absolute', top: 10, right: 10, background: 'none', border: 'none', cursor: 'pointer', padding: 4 }}><Icon name="x" size={15} color="var(--kh-carbon-50)" /></button>}
              </div>
            ))}
            {!readOnly && <button onClick={addStory} style={{ display: 'inline-flex', alignItems: 'center', gap: 8, alignSelf: 'flex-start', background: '#fff', border: `1px dashed ${C.carbon30}`, padding: '9px 14px', cursor: 'pointer', fontFamily: C.sans, fontSize: 11, fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase', color: C.carbon70, borderRadius: 2 }}><Icon name="plus" size={13} /> Add a STAR story</button>}
            {readOnly && !(stories || []).length && <span style={{ fontFamily: C.serif, fontStyle: 'italic', fontSize: 14, color: C.carbon50 }}>No stories yet</span>}
          </div>
        </div>

        <div>
          <div className="kh-eyebrow" style={{ marginBottom: 14 }}>School specifics</div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
            {schools.map((sc, i) => (
              <div key={sc.key} style={{ border: `1px solid ${C.hair}`, padding: '18px 20px' }}>
                <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, marginBottom: 14 }}>
                  <span style={{ fontFamily: C.sans, fontWeight: 600, fontSize: 15, color: C.carbon }}>{sc.name}</span>
                  {!readOnly && <button onClick={() => setSchools(schools.filter((_, n) => n !== i))} title="Remove school" style={{ background: 'none', border: 'none', cursor: 'pointer', padding: 4 }}><Icon name="x" size={15} color="var(--kh-carbon-50)" /></button>}
                </div>
                <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
                  {D.schoolQuestions.map(q => (
                    <React.Fragment key={q.key}>
                      {q.key === 'askQuestions' && (
                        <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap' }}>
                          <label style={{ display: 'flex', flexDirection: 'column', gap: 5, flex: '1 1 220px' }}>
                            <span style={{ fontFamily: C.sans, fontSize: 9, fontWeight: 600, letterSpacing: '0.1em', textTransform: 'uppercase', color: C.carbon50 }}>Interviewer name</span>
                            {readOnly
                              ? <span style={{ fontFamily: C.serif, fontSize: 14.5, color: ((sc.answers || {})._interviewerName ? C.carbon : C.carbon50) }}>{(sc.answers || {})._interviewerName || '—'}</span>
                              : <input value={(sc.answers || {})._interviewerName || ''} onChange={e => setSchoolAns(i, '_interviewerName', e.target.value)} style={{ width: '100%', fontFamily: C.sans, fontSize: 13.5, color: C.carbon, border: `1px solid var(--border-rule)`, borderRadius: 2, padding: '9px 11px', outline: 'none', boxSizing: 'border-box' }} />}
                          </label>
                          <label style={{ display: 'flex', flexDirection: 'column', gap: 5, flex: '0 1 220px' }}>
                            <span style={{ fontFamily: C.sans, fontSize: 9, fontWeight: 600, letterSpacing: '0.1em', textTransform: 'uppercase', color: C.carbon50 }}>Interviewer type</span>
                            {readOnly
                              ? <span style={{ fontFamily: C.serif, fontSize: 14.5, color: ((sc.answers || {})._interviewerType ? C.carbon : C.carbon50) }}>{(sc.answers || {})._interviewerType || '—'}</span>
                              : <select value={(sc.answers || {})._interviewerType || ''} onChange={e => setSchoolAns(i, '_interviewerType', e.target.value)} style={{ fontFamily: C.sans, fontSize: 13.5, color: C.carbon, border: `1px solid var(--border-rule)`, borderRadius: 2, padding: '9px 11px', outline: 'none', cursor: 'pointer', background: '#fff' }}>
                                <option value="">Select…</option>
                                <option value="Current student">Current student</option>
                                <option value="Alumnus / alumna">Alumnus / alumna</option>
                                <option value="Admissions committee">Admissions committee</option>
                              </select>}
                          </label>
                        </div>
                      )}
                      <QBlock q={q} value={(sc.answers || {})[q.key]} onChange={v => setSchoolAns(i, q.key, v)} readOnly={readOnly} area={area} />
                    </React.Fragment>
                  ))}
                </div>
              </div>
            ))}
            {!readOnly && remaining.length > 0 && (
              <div><select value="" onChange={e => { if (e.target.value) addSchool(e.target.value); }} style={{ fontFamily: C.sans, fontSize: 12.5, color: C.carbon, border: `1px dashed ${C.carbon30}`, padding: '9px 13px', borderRadius: 2, background: '#fff', cursor: 'pointer' }}>
                <option value="">+ Add a school…</option>
                {remaining.map(o => <option key={o} value={o}>{o}</option>)}
              </select></div>
            )}
            {readOnly && !schools.length && <span style={{ fontFamily: C.serif, fontStyle: 'italic', fontSize: 14, color: C.carbon50 }}>No schools added</span>}
          </div>
        </div>
      </div>
    </div>
  );
}
window.InterviewWorksheet = InterviewWorksheet;

/* ---- Word (.doc) export --------------------------------------------------- */
function downloadAppWorksheetDoc(slug, cid, clientName) {
  const D = window.appWorksheetFor ? appWorksheetFor(slug) : null;
  if (!D) return;
  const val = (window.wsRead ? wsRead('appws-' + slug, {}, cid) : {}) || {};
  const name = window.wsResolveClientName ? wsResolveClientName(clientName) : (clientName || 'Client');
  const school = (window.SCHOOLS && SCHOOLS.canonical(slug)) || slug;
  const esc = (t) => String(t == null ? '' : t).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
  const para = (t) => esc(t).replace(/\n/g, '<br/>');
  const blank = '<span class="empty">[Blank]</span>';

  let body = `<p class="intro">${esc(D.intro)}</p>`;
  D.sections.forEach(sec => {
    body += `<h2>${esc(sec.title)}</h2>`;
    sec.fields.forEach(f => {
      const v = val[f.id];
      body += `<p class="lbl">${esc(f.label)}</p>`;
      if (f.type === 'yesno') {
        const a = v || {};
        body += `<div class="answer">${a.ans ? esc(a.ans) : blank}${a.explain ? '<br/>' + para(a.explain) : ''}</div>`;
      } else if (f.type === 'repeater') {
        const rows = Array.isArray(v) ? v : [];
        if (!rows.length) body += `<div class="answer">${blank}</div>`;
        else rows.forEach((r, i) => {
          body += `<div class="answer"><strong>#${i + 1}</strong><br/>` + f.sub.map(sf => {
            if (sf.type === 'yesno') return `${esc(sf.label)}: ${r[sf.key] ? esc(r[sf.key]) : '—'}` + (r[sf.key] === 'Yes' && sf.explainKey && r[sf.explainKey] ? '<br/>' + esc(r[sf.explainKey]).replace(/\n/g, '<br/>') : '');
            return `${esc(sf.label)}: ${r[sf.key] ? esc(r[sf.key]).replace(/\n/g, '<br/>') : '—'}`;
          }).join('<br/>') + `</div>`;
        });
      } else if (f.type === 'table') {
        const rows = Array.isArray(v) ? v : [];
        if (!rows.length) body += `<div class="answer">${blank}</div>`;
        else {
          body += `<table class="tbl"><tr>${f.columns.map(c => `<th>${esc(c.label)}</th>`).join('')}</tr>` + rows.map(r => `<tr>${f.columns.map(c => `<td>${r[c.key] ? esc(r[c.key]) : ''}</td>`).join('')}</tr>`).join('') + `</table>`;
        }
      } else {
        body += `<div class="answer">${(v != null && String(v).trim() !== '') ? para(v) : blank}</div>`;
      }
    });
  });

  const html = `<!doctype html><html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-html40">
<head><meta charset="utf-8"/><title>${esc(school)} Application Worksheet — ${esc(name)}</title>
<style>
  body { font-family: Georgia, 'Times New Roman', serif; font-size: 11pt; color: #1d1d1d; line-height: 1.5; }
  .doc-head { border-bottom: 2px solid #1d1d1d; padding-bottom: 10px; margin-bottom: 18px; }
  .eyebrow { font-family: Arial, sans-serif; font-size: 8pt; letter-spacing: 2px; text-transform: uppercase; color: #6b6b6b; }
  h1 { font-family: Arial, sans-serif; font-size: 20pt; margin: 6px 0 2px; }
  .worksheet-title { font-family: Arial, sans-serif; font-size: 13pt; font-weight: bold; color: #1d1d1d; margin: 0 0 4px; }
  .meta { font-family: Arial, sans-serif; font-size: 9pt; color: #6b6b6b; }
  h2 { font-family: Arial, sans-serif; font-size: 12pt; letter-spacing: 1px; text-transform: uppercase; border-bottom: 1px solid #1d1d1d; padding-bottom: 3px; margin: 22px 0 10px; }
  .lbl { font-family: Arial, sans-serif; font-size: 9.5pt; font-weight: bold; margin: 12px 0 3px; }
  .answer { border: 1px solid #cccccc; background: #fafafa; padding: 8px 10px; margin-bottom: 8px; min-height: 16px; }
  .tbl { border-collapse: collapse; width: 100%; margin-bottom: 10px; }
  .tbl th { font-family: Arial, sans-serif; font-size: 8.5pt; text-transform: uppercase; text-align: left; border: 1px solid #999; padding: 4px 6px; background: #eee; }
  .tbl td { font-size: 10pt; border: 1px solid #ccc; padding: 4px 6px; }
  .intro { color: #444; }
  .empty { color: #999999; font-style: italic; }
</style></head><body>
<div class="doc-head"><div class="eyebrow">Karen Hamou Consulting</div><h1>${esc(name)}</h1><div class="worksheet-title">${esc(school)} Application Worksheet</div><div class="meta">Exported ${new Date().toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' })}</div></div>
${body}
</body></html>`;

  const blob = new Blob(['\ufeff' + html], { type: 'application/msword' });
  const fname = window.wsFileName ? wsFileName(school + ' Application Worksheet', name, 'docx') : `${school} Application Worksheet — ${name}.docx`;
  if (window.wsDownloadDocx) { wsDownloadDocx(html, fname); return; }
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url; a.download = fname.replace(/\.docx$/i, '.doc');
  document.body.appendChild(a); a.click(); a.remove();
  setTimeout(() => URL.revokeObjectURL(url), 1000);
}
window.downloadAppWorksheetDoc = downloadAppWorksheetDoc;
