// split-sheet.jsx — Split sheet workshop for works/recordings.
//
// Renders as either:
//   • An embedded tab inside Work-detail (tab='splitsheet')
//   • A standalone overlay drawer (called via window.openSplitSheet({ work }))
//
// Schema is compatible with the existing window.WORKS rows:
//   { id, title, iswc?, writers:[{name, share, ipi, pro, role, splitShares?, perfShare?, mechShare?, syncShare?}] }
//
// Sheet adds:
//   { sheet_id, song, recordingDate?, studio?, workType, version?, lyrics_excerpt?,
//     writers:[…with email, signed, signedAt, signedMethod, address?],
//     producers:[{name, share, role}], status, notes, history:[] }
//
// Persists to window.__SPLIT_SHEETS keyed by work id.

(function () {
  const { useMemo, useState, useEffect, useRef } = React;

  // ── seed store ─────────────────────────────────────────────────────
  function ensureStore() {
    if (!window.__SPLIT_SHEETS) window.__SPLIT_SHEETS = {};
    return window.__SPLIT_SHEETS;
  }
  function loadSheet(work) {
    const store = ensureStore();
    if (store[work.id]) return store[work.id];
    const writers = (work.writers || []).map((w, i) => ({
      name: w.name || `Writer ${i + 1}`,
      role: w.role || 'Composer/Author',
      pro: w.pro || '',
      ipi: w.ipi || '',
      share: +(w.share || 0),
      perfShare: w.splitShares ? +(w.perfShare || w.share || 0) : +(w.share || 0),
      mechShare: w.splitShares ? +(w.mechShare || w.share || 0) : +(w.share || 0),
      syncShare: w.splitShares ? +(w.syncShare || w.share || 0) : +(w.share || 0),
      splitShares: !!w.splitShares,
      email: '',
      address: '',
      signed: false,
      signedAt: null,
      signedMethod: null,
    }));
    const sheet = {
      sheet_id: 'SS-' + (work.id || 'NEW').slice(-8).toUpperCase() + '-' + Math.floor(Math.random() * 9000 + 1000),
      song: work.title || 'Untitled',
      iswc: work.iswc || '',
      workId: work.id,
      recordingDate: '',
      studio: '',
      workType: 'Original',
      version: '',
      lyrics_excerpt: '',
      writers,
      producers: [],
      status: 'draft', // draft | circulating | partially-signed | fully-signed | filed
      notes: '',
      created: new Date().toISOString().slice(0, 10),
      history: [{ when: new Date().toISOString(), who: 'you', what: 'Sheet drafted from work splits' }],
    };
    store[work.id] = sheet;
    return sheet;
  }
  function saveSheet(sheet) {
    const store = ensureStore();
    store[sheet.workId] = sheet;
    window.dispatchEvent(new CustomEvent('astro-split-sheet-saved', { detail: { sheet } }));
  }

  // ── share math helpers ────────────────────────────────────────────
  function sumShares(writers, key) {
    return writers.reduce((s, w) => s + (+(w[key] || 0)), 0);
  }
  function totalsBlock(sheet) {
    const w = sheet.writers || [];
    return {
      writer:    +sumShares(w, 'share').toFixed(3),
      perf:      +sumShares(w, 'perfShare').toFixed(3),
      mech:      +sumShares(w, 'mechShare').toFixed(3),
      sync:      +sumShares(w, 'syncShare').toFixed(3),
      producer:  +sumShares(sheet.producers || [], 'share').toFixed(3),
    };
  }
  function checkValid(sheet) {
    const t = totalsBlock(sheet);
    const issues = [];
    if (Math.abs(t.writer - 100) > 0.01) issues.push({ k: 'writer-total', msg: `Writer share sum = ${t.writer}% (must be 100%)`, sev: 'err' });
    if (sheet.writers.some(w => w.splitShares) && Math.abs(t.perf - 100) > 0.01)
      issues.push({ k: 'perf-total', msg: `Performance share sum = ${t.perf}%`, sev: 'err' });
    if (sheet.writers.some(w => w.splitShares) && Math.abs(t.mech - 100) > 0.01)
      issues.push({ k: 'mech-total', msg: `Mechanical share sum = ${t.mech}%`, sev: 'err' });
    sheet.writers.forEach((w, i) => {
      if (!w.name) issues.push({ k: 'name-' + i, msg: `Writer ${i+1} missing name`, sev: 'err' });
      if (!w.email) issues.push({ k: 'email-' + i, msg: `${w.name || 'Writer '+(i+1)} missing email`, sev: 'warn' });
      if (!w.ipi) issues.push({ k: 'ipi-' + i, msg: `${w.name || 'Writer '+(i+1)} missing IPI`, sev: 'warn' });
      if (!w.pro) issues.push({ k: 'pro-' + i, msg: `${w.name || 'Writer '+(i+1)} missing PRO`, sev: 'warn' });
    });
    return issues;
  }

  // ── deriving status from signatures ───────────────────────────────
  function statusFromSignatures(sheet) {
    const ws = sheet.writers || [];
    if (!ws.length) return 'draft';
    const signed = ws.filter(w => w.signed).length;
    if (signed === 0) return sheet.status === 'circulating' ? 'circulating' : 'draft';
    if (signed < ws.length) return 'partially-signed';
    return sheet.status === 'filed' ? 'filed' : 'fully-signed';
  }

  // ── small UI atoms (reuse ASTRO conventions) ──────────────────────
  const num = (v, dp = 2) => Number(v || 0).toFixed(dp);
  function StatPill({ label, value, tone, sub }) {
    const tones = {
      ok:   { bg: 'oklch(0.95 0.06 145)', fg: 'oklch(0.32 0.12 145)' },
      err:  { bg: 'oklch(0.95 0.07 25)',  fg: 'oklch(0.42 0.18 25)' },
      warn: { bg: 'oklch(0.95 0.06 75)',  fg: 'oklch(0.42 0.18 75)' },
      neutral: { bg: 'var(--bg-2)', fg: 'var(--ink)' },
    };
    const t = tones[tone || 'neutral'];
    return (
      <div style={{ background: t.bg, color: t.fg, padding: '12px 14px', border: '1px solid var(--rule-soft)' }}>
        <div className="ff-mono upper" style={{ fontSize: 9, letterSpacing: '.12em', opacity: 0.75 }}>{label}</div>
        <div className="ff-display num" style={{ fontSize: 26, fontWeight: 600, letterSpacing: '-0.02em', marginTop: 4 }}>{value}</div>
        {sub && <div className="ff-mono" style={{ fontSize: 10, marginTop: 4, opacity: 0.7 }}>{sub}</div>}
      </div>
    );
  }
  function Pill({ tone, dot, children }) {
    const c = tone === 'ok' ? 'oklch(0.55 0.16 145)' : tone === 'err' ? 'oklch(0.55 0.18 25)' : tone === 'warn' ? 'oklch(0.55 0.16 75)' : 'var(--ink-3)';
    return (
      <span className="ff-mono upper" style={{
        display: 'inline-flex', alignItems: 'center', gap: 6, padding: '4px 10px', fontSize: 10, letterSpacing: '.08em',
        border: '1px solid var(--rule)', color: c, background: 'transparent',
      }}>
        {dot && <span style={{ width: 6, height: 6, borderRadius: '50%', background: c }} />}
        {children}
      </span>
    );
  }

  // ── main panel ────────────────────────────────────────────────────
  function SplitSheetWorkshop({ work, embedded }) {
    const [sheet, setSheet] = useState(() => loadSheet(work));
    const [section, setSection] = useState('roster'); // roster | producers | meta | sign | review
    const issues = useMemo(() => checkValid(sheet), [sheet]);
    const totals = useMemo(() => totalsBlock(sheet), [sheet]);
    const errCount = issues.filter(i => i.sev === 'err').length;
    const warnCount = issues.filter(i => i.sev === 'warn').length;

    function commit(next, note) {
      next.status = statusFromSignatures(next);
      if (note) next.history = [{ when: new Date().toISOString(), who: 'you', what: note }, ...(next.history || [])].slice(0, 50);
      setSheet({ ...next });
      saveSheet(next);
    }

    // ── handlers
    function setW(i, patch) {
      const ws = [...sheet.writers];
      ws[i] = { ...ws[i], ...patch };
      commit({ ...sheet, writers: ws }, patch.signed === true ? `${ws[i].name} signed` : null);
    }
    function addWriter() {
      const ws = [...sheet.writers, { name: '', role: 'Composer/Author', pro: '', ipi: '', share: 0, perfShare: 0, mechShare: 0, syncShare: 0, splitShares: false, email: '', signed: false }];
      commit({ ...sheet, writers: ws }, 'Added writer');
    }
    function removeWriter(i) {
      const ws = sheet.writers.filter((_, j) => j !== i);
      commit({ ...sheet, writers: ws }, 'Removed writer');
    }
    function rebalanceEqual() {
      const n = sheet.writers.length || 1;
      const each = +(100 / n).toFixed(3);
      const rem = +(100 - each * (n - 1)).toFixed(3);
      const ws = sheet.writers.map((w, i) => {
        const s = i === n - 1 ? rem : each;
        return { ...w, share: s, perfShare: s, mechShare: s, syncShare: s };
      });
      commit({ ...sheet, writers: ws }, 'Rebalanced equal');
    }
    function autoTrueUp() {
      // trim/expand last writer to make total exactly 100
      const ws = [...sheet.writers];
      if (!ws.length) return;
      const sum = sumShares(ws, 'share');
      const delta = +(100 - sum).toFixed(3);
      ws[ws.length - 1].share = +(+ws[ws.length - 1].share + delta).toFixed(3);
      ws[ws.length - 1].perfShare = +(+ws[ws.length - 1].perfShare + delta).toFixed(3);
      ws[ws.length - 1].mechShare = +(+ws[ws.length - 1].mechShare + delta).toFixed(3);
      ws[ws.length - 1].syncShare = +(+ws[ws.length - 1].syncShare + delta).toFixed(3);
      commit({ ...sheet, writers: ws }, 'Auto true-up to 100%');
    }
    function sendForSign() {
      const next = { ...sheet, status: 'circulating', writers: sheet.writers.map(w => ({ ...w, signedMethod: w.signedMethod || 'eSign' })) };
      commit(next, `Sent for signature to ${sheet.writers.filter(w => w.email).length} writers`);
      window.toast && window.toast('Split sheet sent for signing', 'soft');
    }
    function fileSheet() {
      commit({ ...sheet, status: 'filed' }, 'Filed split sheet');
      window.toast && window.toast(`Sheet ${sheet.sheet_id} filed`, 'soft');
    }
    function exportPdf() {
      // Print-to-PDF via window.print scoped to a synthesized HTML doc
      const html = renderPrintableHTML(sheet, totals);
      const w = window.open('', '_blank');
      if (!w) { window.toast && window.toast('Pop-up blocked'); return; }
      w.document.write(html); w.document.close();
      setTimeout(() => { w.print(); }, 300);
    }
    function exportJson() {
      const blob = new Blob([JSON.stringify(sheet, null, 2)], { type: 'application/json' });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url; a.download = `${sheet.sheet_id}.json`; a.click();
      setTimeout(() => URL.revokeObjectURL(url), 1000);
    }
    function pushToCwr() {
      // Hand off to CWR generator with current writer splits
      window.toast && window.toast('Splits pushed to CWR generator queue', 'soft');
    }

    const sections = [
      { k: 'roster',    l: 'Writers' },
      { k: 'producers', l: 'Producers' },
      { k: 'meta',      l: 'Session info' },
      { k: 'sign',      l: 'Signatures' },
      { k: 'review',    l: 'Review & file' },
    ];

    const wrap = embedded ? {} : { background: 'var(--bg)', color: 'var(--ink)', minHeight: '100vh' };

    return (
      <div style={wrap}>
        {/* Hero */}
        <div style={{ padding: embedded ? '0 0 22px' : '32px 32px 22px', borderBottom: embedded ? '1px solid var(--rule)' : 'none' }}>
          <div className="ff-mono upper" style={{ fontSize: 10, letterSpacing: '.18em', color: 'var(--ink-3)', marginBottom: 8 }}>
            SPLIT SHEET · {sheet.sheet_id}
          </div>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', gap: 24, flexWrap: 'wrap' }}>
            <div>
              <h2 className="ff-display" style={{ fontSize: 'clamp(28px, 3.4vw, 44px)', fontWeight: 600, letterSpacing: '-0.03em', lineHeight: 1, margin: 0 }}>
                {sheet.song}
              </h2>
              <div className="ff-mono" style={{ fontSize: 11, color: 'var(--ink-3)', marginTop: 8, display: 'flex', gap: 12, flexWrap: 'wrap' }}>
                {sheet.iswc && <span>ISWC {sheet.iswc}</span>}
                {sheet.studio && <span>· {sheet.studio}</span>}
                {sheet.recordingDate && <span>· {sheet.recordingDate}</span>}
                <Pill tone={sheet.status === 'fully-signed' || sheet.status === 'filed' ? 'ok' : sheet.status === 'partially-signed' ? 'warn' : 'neutral'} dot>{sheet.status}</Pill>
              </div>
            </div>
            <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
              <button onClick={exportJson} className="ff-mono upper" style={btnGhost}>JSON</button>
              <button onClick={exportPdf} className="ff-mono upper" style={btnGhost}>Export PDF</button>
              <button onClick={pushToCwr} className="ff-mono upper" style={btnGhost}>→ CWR</button>
              {sheet.status === 'draft'
                ? <button onClick={sendForSign} disabled={errCount > 0} className="ff-mono upper" style={errCount > 0 ? btnDisabled : btnPrimary}>Send for signature</button>
                : sheet.status !== 'filed' && sheet.status !== 'fully-signed'
                  ? <Pill tone="warn" dot>Awaiting signatures</Pill>
                  : sheet.status === 'fully-signed'
                    ? <button onClick={fileSheet} className="ff-mono upper" style={btnPrimary}>File sheet</button>
                    : <Pill tone="ok" dot>Filed</Pill>}
            </div>
          </div>
          {/* Totals strip */}
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(5, 1fr)', gap: 0, marginTop: 22, border: '1px solid var(--rule)' }}>
            <StatPill label="WRITER %" value={num(totals.writer)} tone={Math.abs(totals.writer - 100) < 0.01 ? 'ok' : 'err'} sub="must = 100" />
            <StatPill label="PERF %" value={num(totals.perf)} tone={Math.abs(totals.perf - 100) < 0.01 ? 'ok' : sheet.writers.some(w => w.splitShares) ? 'err' : 'neutral'} />
            <StatPill label="MECH %" value={num(totals.mech)} tone={Math.abs(totals.mech - 100) < 0.01 ? 'ok' : sheet.writers.some(w => w.splitShares) ? 'err' : 'neutral'} />
            <StatPill label="SIGNATURES" value={`${sheet.writers.filter(w => w.signed).length}/${sheet.writers.length}`} tone={sheet.writers.length && sheet.writers.every(w => w.signed) ? 'ok' : 'neutral'} />
            <StatPill label="ISSUES" value={`${errCount} err · ${warnCount} warn`} tone={errCount ? 'err' : warnCount ? 'warn' : 'ok'} />
          </div>
        </div>

        {/* Section tabs */}
        <div style={{ display: 'flex', borderBottom: '1px solid var(--rule)', padding: embedded ? 0 : '0 32px' }}>
          {sections.map(s => (
            <button key={s.k} onClick={() => setSection(s.k)} className="ff-mono upper" style={{
              padding: '14px 18px', fontSize: 11, fontWeight: 600, letterSpacing: '.08em',
              borderBottom: section === s.k ? '3px solid var(--ink)' : '3px solid transparent', marginBottom: -1,
              color: section === s.k ? 'var(--ink)' : 'var(--ink-3)', background: 'transparent', border: 0, cursor: 'pointer',
            }}>{s.l}</button>
          ))}
        </div>

        {/* Body */}
        <div style={{ padding: embedded ? '24px 0 60px' : '24px 32px 60px' }}>
          {section === 'roster' && <RosterSection sheet={sheet} setW={setW} addWriter={addWriter} removeWriter={removeWriter} rebalanceEqual={rebalanceEqual} autoTrueUp={autoTrueUp} totals={totals} />}
          {section === 'producers' && <ProducersSection sheet={sheet} commit={commit} />}
          {section === 'meta' && <MetaSection sheet={sheet} commit={commit} />}
          {section === 'sign' && <SignSection sheet={sheet} setW={setW} commit={commit} />}
          {section === 'review' && <ReviewSection sheet={sheet} issues={issues} totals={totals} />}
        </div>
      </div>
    );
  }

  // ── Roster
  function RosterSection({ sheet, setW, addWriter, removeWriter, rebalanceEqual, autoTrueUp, totals }) {
    const splitMode = sheet.writers.some(w => w.splitShares);
    return (
      <div>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 12 }}>
          <div className="ff-mono upper" style={{ fontSize: 10, letterSpacing: '.12em', color: 'var(--ink-3)' }}>WRITER ROSTER · {sheet.writers.length}</div>
          <div style={{ display: 'flex', gap: 8 }}>
            <button onClick={rebalanceEqual} className="ff-mono upper" style={btnGhost}>Equal split</button>
            <button onClick={autoTrueUp} className="ff-mono upper" style={btnGhost}>Auto true-up</button>
          </div>
        </div>
        <div style={{ border: '1px solid var(--rule)' }}>
          <div className="ff-mono upper" style={{ display: 'grid', gridTemplateColumns: splitMode ? '20px 1.4fr 110px 80px 130px 70px 70px 70px 70px 80px 28px' : '20px 1.4fr 130px 80px 130px 80px 80px 110px 28px', gap: 10, padding: '10px 14px', fontSize: 9, color: 'var(--ink-3)', letterSpacing: '.12em', background: 'var(--bg-2)', borderBottom: '1px solid var(--rule)' }}>
            <span>#</span>
            <span>NAME</span>
            <span>ROLE</span>
            <span>PRO</span>
            <span>IPI</span>
            {splitMode ? <><span>WR%</span><span>PR%</span><span>MR%</span><span>SY%</span></> : <><span>SHARE%</span><span>SPLIT?</span></>}
            <span>EMAIL</span>
            <span></span>
          </div>
          {sheet.writers.length === 0 && (
            <div className="ff-mono" style={{ padding: 24, textAlign: 'center', color: 'var(--ink-3)', fontSize: 12 }}>No writers — add one.</div>
          )}
          {sheet.writers.map((w, i) => (
            <div key={i} style={{ display: 'grid', gridTemplateColumns: splitMode ? '20px 1.4fr 110px 80px 130px 70px 70px 70px 70px 80px 28px' : '20px 1.4fr 130px 80px 130px 80px 80px 110px 28px', gap: 10, padding: '10px 14px', alignItems: 'center', borderTop: i ? '1px solid var(--rule-soft)' : 'none' }}>
              <span className="ff-display num" style={{ fontSize: 12, color: 'var(--ink-4)' }}>{String(i + 1).padStart(2, '0')}</span>
              <input value={w.name} onChange={e => setW(i, { name: e.target.value })} placeholder="Writer name" style={inp} />
              <select value={w.role} onChange={e => setW(i, { role: e.target.value })} style={inp}>
                <option>Composer/Author</option><option>Composer</option><option>Author</option><option>Arranger</option><option>Adaptor</option><option>Translator</option>
              </select>
              <input value={w.pro} onChange={e => setW(i, { pro: e.target.value })} placeholder="ASCAP" style={{ ...inp, fontFamily: 'var(--ff-mono)' }} />
              <input value={w.ipi} onChange={e => setW(i, { ipi: e.target.value })} placeholder="00000000000" style={{ ...inp, fontFamily: 'var(--ff-mono)', fontSize: 11 }} />
              {splitMode ? (
                <>
                  <input type="number" step="0.001" value={w.share} onChange={e => setW(i, { share: +e.target.value })} style={{ ...inp, textAlign: 'right' }} />
                  <input type="number" step="0.001" value={w.perfShare} onChange={e => setW(i, { perfShare: +e.target.value })} style={{ ...inp, textAlign: 'right' }} />
                  <input type="number" step="0.001" value={w.mechShare} onChange={e => setW(i, { mechShare: +e.target.value })} style={{ ...inp, textAlign: 'right' }} />
                  <input type="number" step="0.001" value={w.syncShare} onChange={e => setW(i, { syncShare: +e.target.value })} style={{ ...inp, textAlign: 'right' }} />
                </>
              ) : (
                <>
                  <input type="number" step="0.001" value={w.share} onChange={e => { const v = +e.target.value; setW(i, { share: v, perfShare: v, mechShare: v, syncShare: v }); }} style={{ ...inp, textAlign: 'right' }} />
                  <label className="ff-mono" style={{ fontSize: 10, color: 'var(--ink-3)', display: 'flex', gap: 4, alignItems: 'center' }}>
                    <input type="checkbox" checked={!!w.splitShares} onChange={e => setW(i, { splitShares: e.target.checked })} />split
                  </label>
                </>
              )}
              <input value={w.email} onChange={e => setW(i, { email: e.target.value })} placeholder="email@…" style={{ ...inp, fontSize: 11 }} />
              <button onClick={() => removeWriter(i)} title="Remove" style={{ background: 'transparent', border: 0, color: 'var(--ink-4)', cursor: 'pointer', fontSize: 14 }}>×</button>
            </div>
          ))}
          <div style={{ borderTop: '1px solid var(--rule)', padding: '10px 14px', display: 'flex', justifyContent: 'space-between', alignItems: 'center', background: 'var(--bg-2)' }}>
            <button onClick={addWriter} className="ff-mono upper" style={btnGhost}>+ Add writer</button>
            <div className="ff-mono" style={{ fontSize: 11, color: Math.abs(totals.writer - 100) < 0.01 ? 'var(--ink)' : 'oklch(0.55 0.18 25)' }}>
              TOTAL · {num(totals.writer)}%
            </div>
          </div>
        </div>
      </div>
    );
  }

  // ── Producers
  function ProducersSection({ sheet, commit }) {
    const ps = sheet.producers || [];
    function setP(i, patch) {
      const next = [...ps]; next[i] = { ...next[i], ...patch };
      commit({ ...sheet, producers: next });
    }
    function add() { commit({ ...sheet, producers: [...ps, { name: '', role: 'Producer', share: 0 }] }, 'Added producer'); }
    function remove(i) { commit({ ...sheet, producers: ps.filter((_, j) => j !== i) }, 'Removed producer'); }
    return (
      <div>
        <div className="ff-mono" style={{ fontSize: 11, color: 'var(--ink-3)', marginBottom: 12, lineHeight: 1.6 }}>
          Producer points are typically negotiated separately from writer splits — capture them here so the sheet matches the deal memo and the producer letter goes out alongside.
        </div>
        <div style={{ border: '1px solid var(--rule)' }}>
          <div className="ff-mono upper" style={{ display: 'grid', gridTemplateColumns: '1.4fr 200px 100px 28px', gap: 10, padding: '10px 14px', fontSize: 9, color: 'var(--ink-3)', letterSpacing: '.12em', background: 'var(--bg-2)', borderBottom: '1px solid var(--rule)' }}>
            <span>NAME</span><span>ROLE</span><span>POINTS</span><span></span>
          </div>
          {ps.length === 0 && <div className="ff-mono" style={{ padding: 24, textAlign: 'center', color: 'var(--ink-3)', fontSize: 12 }}>No producers attached.</div>}
          {ps.map((p, i) => (
            <div key={i} style={{ display: 'grid', gridTemplateColumns: '1.4fr 200px 100px 28px', gap: 10, padding: '10px 14px', alignItems: 'center', borderTop: i ? '1px solid var(--rule-soft)' : 'none' }}>
              <input value={p.name} onChange={e => setP(i, { name: e.target.value })} placeholder="Producer name" style={inp} />
              <select value={p.role} onChange={e => setP(i, { role: e.target.value })} style={inp}>
                <option>Producer</option><option>Co-Producer</option><option>Executive Producer</option><option>Mix</option><option>Master</option><option>Vocal Production</option>
              </select>
              <input type="number" step="0.001" value={p.share} onChange={e => setP(i, { share: +e.target.value })} style={{ ...inp, textAlign: 'right' }} />
              <button onClick={() => remove(i)} style={{ background: 'transparent', border: 0, color: 'var(--ink-4)', cursor: 'pointer', fontSize: 14 }}>×</button>
            </div>
          ))}
          <div style={{ borderTop: '1px solid var(--rule)', padding: '10px 14px', background: 'var(--bg-2)' }}>
            <button onClick={add} className="ff-mono upper" style={btnGhost}>+ Add producer</button>
          </div>
        </div>
      </div>
    );
  }

  // ── Session metadata
  function MetaSection({ sheet, commit }) {
    function setKey(k, v) { commit({ ...sheet, [k]: v }); }
    return (
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14, maxWidth: 920 }}>
        <Field label="STUDIO"><input value={sheet.studio} onChange={e => setKey('studio', e.target.value)} placeholder="Electric Lady, NYC" style={inp} /></Field>
        <Field label="RECORDING DATE"><input type="date" value={sheet.recordingDate} onChange={e => setKey('recordingDate', e.target.value)} style={inp} /></Field>
        <Field label="WORK TYPE"><select value={sheet.workType} onChange={e => setKey('workType', e.target.value)} style={inp}>
          <option>Original</option><option>Cover</option><option>Sample-based</option><option>Interpolation</option><option>Translation</option><option>Adaptation</option><option>Remix</option>
        </select></Field>
        <Field label="VERSION"><input value={sheet.version} onChange={e => setKey('version', e.target.value)} placeholder="Album / Radio Edit / Remix…" style={inp} /></Field>
        <Field label="ISWC"><input value={sheet.iswc} onChange={e => setKey('iswc', e.target.value)} placeholder="T-…" style={{ ...inp, fontFamily: 'var(--ff-mono)' }} /></Field>
        <Field label="NOTES" wide><textarea value={sheet.notes} onChange={e => setKey('notes', e.target.value)} rows={4} placeholder="Special agreements, side-letters, source attributions…" style={{ ...inp, resize: 'vertical', minHeight: 80 }} /></Field>
        <Field label="LYRICS EXCERPT" wide><textarea value={sheet.lyrics_excerpt} onChange={e => setKey('lyrics_excerpt', e.target.value)} rows={4} placeholder="First 8 bars / hook — for fingerprinting & dispute reference" style={{ ...inp, resize: 'vertical', minHeight: 80 }} /></Field>
      </div>
    );
  }
  function Field({ label, wide, children }) {
    return (
      <label style={{ display: 'block', gridColumn: wide ? '1 / -1' : 'auto' }}>
        <div className="ff-mono upper" style={{ fontSize: 9, letterSpacing: '.12em', color: 'var(--ink-3)', marginBottom: 6 }}>{label}</div>
        {children}
      </label>
    );
  }

  // ── Signatures
  function SignSection({ sheet, setW, commit }) {
    function toggleSign(i) {
      const w = sheet.writers[i];
      if (w.signed) {
        setW(i, { signed: false, signedAt: null, signedMethod: null });
      } else {
        setW(i, { signed: true, signedAt: new Date().toISOString(), signedMethod: w.signedMethod || 'eSign' });
      }
    }
    function setMethod(i, method) { setW(i, { signedMethod: method }); }
    return (
      <div>
        <div className="ff-mono" style={{ fontSize: 11, color: 'var(--ink-3)', marginBottom: 12, lineHeight: 1.6, maxWidth: 720 }}>
          Mark each writer signed once you have the artifact (e.g. countersigned PDF or eSign envelope completion). All-signed flips the sheet to <strong>fully-signed</strong>; once filed it locks.
        </div>
        <div style={{ border: '1px solid var(--rule)' }}>
          <div className="ff-mono upper" style={{ display: 'grid', gridTemplateColumns: '1.6fr 1fr 110px 110px 130px 90px', gap: 10, padding: '10px 14px', fontSize: 9, color: 'var(--ink-3)', letterSpacing: '.12em', background: 'var(--bg-2)', borderBottom: '1px solid var(--rule)' }}>
            <span>WRITER</span><span>EMAIL</span><span>SHARE</span><span>METHOD</span><span>SIGNED AT</span><span>STATUS</span>
          </div>
          {sheet.writers.map((w, i) => (
            <div key={i} style={{ display: 'grid', gridTemplateColumns: '1.6fr 1fr 110px 110px 130px 90px', gap: 10, padding: '12px 14px', alignItems: 'center', borderTop: i ? '1px solid var(--rule-soft)' : 'none' }}>
              <div>
                <div style={{ fontSize: 13, fontWeight: 500 }}>{w.name || `Writer ${i + 1}`}</div>
                <div className="ff-mono" style={{ fontSize: 10, color: 'var(--ink-3)' }}>{w.role} · {w.pro || '—'} · IPI {w.ipi || '—'}</div>
              </div>
              <span className="ff-mono" style={{ fontSize: 11, color: w.email ? 'var(--ink-2)' : 'oklch(0.55 0.16 75)' }}>{w.email || 'no email'}</span>
              <span className="ff-mono num" style={{ fontSize: 12 }}>{num(w.share)}%</span>
              <select value={w.signedMethod || 'eSign'} onChange={e => setMethod(i, e.target.value)} style={inp} disabled={w.signed}>
                <option>eSign</option><option>Wet ink</option><option>Email confirm</option><option>In-person</option>
              </select>
              <span className="ff-mono" style={{ fontSize: 10, color: 'var(--ink-3)' }}>{w.signedAt ? w.signedAt.replace('T', ' ').slice(0, 16) + 'Z' : '—'}</span>
              <button onClick={() => toggleSign(i)} className="ff-mono upper" style={w.signed ? btnPrimaryGreen : btnGhost}>{w.signed ? '✓ Signed' : 'Mark signed'}</button>
            </div>
          ))}
        </div>
      </div>
    );
  }

  // ── Review & file
  function ReviewSection({ sheet, issues, totals }) {
    return (
      <div style={{ display: 'grid', gridTemplateColumns: '1.4fr 1fr', gap: 24 }}>
        <div>
          <div className="ff-mono upper" style={{ fontSize: 10, letterSpacing: '.12em', color: 'var(--ink-3)', marginBottom: 10 }}>VALIDATION</div>
          <div style={{ border: '1px solid var(--rule)' }}>
            {issues.length === 0 && (
              <div style={{ padding: 18, display: 'flex', gap: 10, alignItems: 'center', background: 'oklch(0.97 0.04 145)' }}>
                <span style={{ width: 10, height: 10, borderRadius: '50%', background: 'oklch(0.55 0.16 145)' }} />
                <span className="ff-mono" style={{ fontSize: 12, color: 'oklch(0.32 0.12 145)' }}>All checks pass — ready to circulate.</span>
              </div>
            )}
            {issues.map((iss, k) => (
              <div key={k} style={{ display: 'grid', gridTemplateColumns: '60px 1fr', gap: 10, padding: '10px 14px', alignItems: 'center', borderTop: k ? '1px solid var(--rule-soft)' : 'none', background: iss.sev === 'err' ? 'oklch(0.98 0.02 25)' : 'transparent' }}>
                <Pill tone={iss.sev === 'err' ? 'err' : 'warn'} dot>{iss.sev}</Pill>
                <span className="ff-mono" style={{ fontSize: 11 }}>{iss.msg}</span>
              </div>
            ))}
          </div>

          <div className="ff-mono upper" style={{ fontSize: 10, letterSpacing: '.12em', color: 'var(--ink-3)', marginTop: 24, marginBottom: 10 }}>CWR / REGISTRATION PUSH</div>
          <div style={{ padding: 18, border: '1px solid var(--rule)', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
            <div className="ff-mono" style={{ fontSize: 11, lineHeight: 1.6, color: 'var(--ink-2)' }}>
              Once filed, splits feed directly into the next CWR transmission for this work — SWR shares update, PWR linkage is preserved, and the sheet reference attaches as ARI metadata.
            </div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 6, alignItems: 'flex-end' }}>
              <Pill dot tone={sheet.status === 'filed' ? 'ok' : 'warn'}>{sheet.status === 'filed' ? 'Linked to CWR queue' : 'Not yet filed'}</Pill>
            </div>
          </div>
        </div>

        <div>
          <div className="ff-mono upper" style={{ fontSize: 10, letterSpacing: '.12em', color: 'var(--ink-3)', marginBottom: 10 }}>HISTORY</div>
          <div style={{ border: '1px solid var(--rule)', maxHeight: 460, overflow: 'auto' }}>
            {(sheet.history || []).map((h, i) => (
              <div key={i} style={{ padding: '10px 14px', borderTop: i ? '1px solid var(--rule-soft)' : 'none' }}>
                <div className="ff-mono" style={{ fontSize: 10, color: 'var(--ink-3)' }}>{h.when?.slice(0, 16).replace('T', ' ')}Z · {h.who}</div>
                <div style={{ fontSize: 12, marginTop: 2 }}>{h.what}</div>
              </div>
            ))}
          </div>
        </div>
      </div>
    );
  }

  // ── printable PDF html
  function renderPrintableHTML(sheet, totals) {
    const safe = (s) => String(s || '').replace(/[&<>]/g, c => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;' }[c]));
    const wrows = sheet.writers.map((w, i) => `
      <tr>
        <td>${i + 1}</td><td>${safe(w.name)}</td><td>${safe(w.role)}</td><td>${safe(w.pro)}</td><td>${safe(w.ipi)}</td>
        <td style="text-align:right">${(+w.share).toFixed(2)}%</td>
        <td>${w.signed ? '✓ ' + (w.signedAt || '').slice(0, 10) : '—'}</td>
      </tr>`).join('');
    return `<!doctype html><html><head><meta charset="utf-8"><title>Split Sheet ${safe(sheet.sheet_id)}</title>
      <style>
        body{font-family:Georgia,serif;color:#111;padding:48px;line-height:1.5;font-size:11pt}
        h1{font-family:Inter,sans-serif;font-size:22pt;margin:0 0 8px;letter-spacing:-.02em}
        h2{font-family:Inter,sans-serif;font-size:11pt;letter-spacing:.18em;text-transform:uppercase;color:#666;margin:32px 0 8px;font-weight:600}
        table{border-collapse:collapse;width:100%;font-size:10pt}
        th,td{border-bottom:1px solid #ccc;padding:8px 6px;text-align:left;vertical-align:top}
        th{background:#f3f3f3;font-family:Inter,sans-serif;text-transform:uppercase;font-size:8pt;letter-spacing:.1em;color:#333}
        .meta{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:16px;font-size:10pt}
        .meta div{padding:6px 0;border-bottom:1px solid #eee}
        .sig{margin-top:48px;border-top:2px solid #111;padding-top:12px;font-size:10pt}
        .sig-line{display:flex;justify-content:space-between;border-bottom:1px solid #888;padding:24px 0 6px;margin-top:12px}
      </style></head><body>
      <div style="font-family:Inter,sans-serif;letter-spacing:.18em;font-size:9pt;color:#888">SPLIT SHEET · ${safe(sheet.sheet_id)}</div>
      <h1>${safe(sheet.song)}</h1>
      <div style="font-family:Inter,sans-serif;font-size:10pt;color:#444">${safe(sheet.workType)}${sheet.version ? ' · ' + safe(sheet.version) : ''}${sheet.iswc ? ' · ISWC ' + safe(sheet.iswc) : ''}</div>

      <div class="meta">
        <div><strong>Studio:</strong> ${safe(sheet.studio) || '—'}</div>
        <div><strong>Recording date:</strong> ${safe(sheet.recordingDate) || '—'}</div>
        <div><strong>Sheet ID:</strong> ${safe(sheet.sheet_id)}</div>
        <div><strong>Created:</strong> ${safe(sheet.created)}</div>
      </div>

      <h2>Writer splits — must sum to 100%</h2>
      <table>
        <thead><tr><th>#</th><th>Writer</th><th>Role</th><th>PRO</th><th>IPI</th><th>Share</th><th>Signed</th></tr></thead>
        <tbody>${wrows}</tbody>
        <tfoot><tr><th colspan="5" style="text-align:right">TOTAL</th><th style="text-align:right">${(+totals.writer).toFixed(2)}%</th><th></th></tr></tfoot>
      </table>

      ${sheet.notes ? `<h2>Notes</h2><div style="font-size:10pt">${safe(sheet.notes)}</div>` : ''}

      <h2>Signatures</h2>
      <p style="font-size:10pt;color:#444">By signing below, each writer confirms the share allocation above and grants the rights necessary to register this work and account royalties accordingly.</p>
      ${sheet.writers.map(w => `<div class="sig-line"><div>${safe(w.name)} · ${safe(w.role)}</div><div>Date: ____________</div></div>`).join('')}
    </body></html>`;
  }

  // ── styles
  const inp = {
    width: '100%', padding: '6px 8px', fontSize: 12, background: 'var(--bg)', color: 'var(--ink)',
    border: '1px solid var(--rule-soft)', fontFamily: 'inherit',
  };
  const btnGhost = {
    padding: '7px 12px', fontSize: 11, letterSpacing: '.08em', background: 'transparent',
    color: 'var(--ink)', border: '1px solid var(--rule)', cursor: 'pointer',
  };
  const btnPrimary = {
    padding: '7px 14px', fontSize: 11, letterSpacing: '.08em', background: 'var(--ink)',
    color: 'var(--bg)', border: 0, cursor: 'pointer', fontWeight: 600,
  };
  const btnPrimaryGreen = {
    padding: '7px 14px', fontSize: 11, letterSpacing: '.08em', background: 'oklch(0.55 0.16 145)',
    color: 'oklch(0.99 0 0)', border: 0, cursor: 'pointer', fontWeight: 600,
  };
  const btnDisabled = {
    padding: '7px 14px', fontSize: 11, letterSpacing: '.08em', background: 'var(--bg-2)',
    color: 'var(--ink-4)', border: '1px solid var(--rule)', cursor: 'not-allowed', fontWeight: 600,
  };

  // ── overlay launcher
  function SplitSheetOverlay() {
    const [open, setOpen] = useState(null);
    useEffect(() => {
      const onOpen = (e) => setOpen(e.detail || null);
      const onClose = () => setOpen(null);
      window.addEventListener('astro-open-split-sheet', onOpen);
      window.addEventListener('astro-close-split-sheet', onClose);
      window.openSplitSheet = (work) => setOpen({ work });
      return () => {
        window.removeEventListener('astro-open-split-sheet', onOpen);
        window.removeEventListener('astro-close-split-sheet', onClose);
      };
    }, []);
    if (!open || !open.work) return null;
    return (
      <div style={{ position: 'fixed', inset: 0, background: 'oklch(0 0 0 / .55)', zIndex: 9000, display: 'flex', justifyContent: 'flex-end' }}
        onClick={() => setOpen(null)}>
        <div onClick={e => e.stopPropagation()} style={{ width: 'min(1180px, 95vw)', height: '100vh', overflow: 'auto', background: 'var(--bg)', boxShadow: '-12px 0 40px oklch(0 0 0 / .25)' }}>
          <div style={{ position: 'sticky', top: 0, background: 'var(--bg)', zIndex: 1, padding: '12px 24px', borderBottom: '1px solid var(--rule)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
            <div className="ff-mono upper" style={{ fontSize: 10, letterSpacing: '.18em', color: 'var(--ink-3)' }}>SPLIT SHEET WORKSHOP</div>
            <button onClick={() => setOpen(null)} style={{ background: 'transparent', border: 0, fontSize: 18, color: 'var(--ink-3)', cursor: 'pointer' }}>×</button>
          </div>
          <div style={{ padding: '0 24px' }}>
            <SplitSheetWorkshop work={open.work} embedded />
          </div>
        </div>
      </div>
    );
  }

  // ── exports
  Object.assign(window, {
    SplitSheetWorkshop,
    SplitSheetOverlay,
    splitSheetLoad: loadSheet,
    splitSheetTotals: totalsBlock,
    splitSheetIssues: checkValid,
  });
})();
