// writer-payments.jsx — Per-writer payment statements
// ─────────────────────────────────────────────────────────────────
// Generates writer-facing distribution reports: gross income → fees
// → net payable, broken down by source (PRO/mech/DSP/sync), period,
// and per-work line items. Pulls from window.__STMT_INDEX +
// window.RS.works (for splits) + window.FEE_ENGINE (for fees).
//
// Tabs:
//   01 OVERVIEW   — all writers, period totals
//   02 STATEMENT  — single-writer detailed statement (printable)
//   03 EXPORT     — CSV bulk + per-writer CSV
//
// Exports: window.ScreenWriterPayments, window.WRITER_PAYMENTS_ENGINE
// ─────────────────────────────────────────────────────────────────
(function () {
  if (typeof window === 'undefined' || !window.React) return;
  const _S = React.useState, _E = React.useEffect, _M = React.useMemo;

  function Mono({ children, upper, size, color, style, ...rest }) {
    return <span className={'ff-mono' + (upper?' upper':'')} style={{ fontSize: size||11, color: color||'var(--ink)', letterSpacing: upper?'.08em':0, ...style }} {...rest}>{children}</span>;
  }

  // ─── ENGINE ──────────────────────────────────────────────────
  // Build per-writer ledger from statements + RS works.
  function buildLedger(opts) {
    const { period } = opts || {};
    const idx = window.__STMT_INDEX;
    const works = window.RS?.works || [];
    if (!idx || !works.length) return { writers: [], totals: { gross: 0, fee: 0, net: 0, lines: 0 } };

    // Map work title/ISWC → writer-share rows
    const titleIndex = new Map();
    const iswcIndex = new Map();
    works.forEach(w => {
      const title = (w['Work Title'] || '').toLowerCase().trim();
      if (title) titleIndex.set(title, w);
      if (w.ISWC) iswcIndex.set(w.ISWC.replace(/[-\.]/g,''), w);
    });

    // Walk every line in every statement
    const writerMap = new Map(); // writerId → { writer, lines, sources, works, gross, fee, net }
    let totalGross = 0, totalFee = 0, totalNet = 0, totalLines = 0;

    (idx.statements || []).forEach(stmt => {
      const lines = stmt.lines || [];
      lines.forEach(line => {
        // Resolve to a Work
        let work = null;
        const isw = (line.iswc || '').replace(/[-\.]/g,'');
        if (isw && iswcIndex.has(isw)) work = iswcIndex.get(isw);
        else if (line.workTitle) work = titleIndex.get(line.workTitle.toLowerCase().trim());
        if (!work || !work.writerShares?.length) return;

        const gross = +line.grossUsd || +line.grossAmount || 0;
        if (gross <= 0) return;

        // Determine product/source type
        const productType = line.productType ||
          (stmt.parser?.includes('mech') || stmt.parser?.includes('mlc') || stmt.parser?.includes('hfa') ? 'mechanical' :
           stmt.parser?.includes('rsd') || stmt.parser?.includes('symphonic') ? 'mechanical' :
           stmt.parser?.includes('soundex') ? 'neighbour' :
           'performance');

        // Distribute gross by writer-share %s
        work.writerShares.forEach(ws => {
          const sharePct = parseFloat(ws['Performance Share'] || ws['Mech Share'] || ws['Sync Share']) || 0;
          if (sharePct <= 0) return;
          const writerId = ws.profile?.profile_id || ws.Writer || 'unknown';
          const writerName = ws.profile?.artist_name || ws.Writer || 'Unknown writer';
          const shareGross = gross * (sharePct / 100);

          // Apply fee
          const feeResult = window.FEE_ENGINE?.compute({
            grossAmount: shareGross,
            productType,
            writerId,
          }) || { gross: shareGross, fee: shareGross * 0.10, net: shareGross * 0.90, feePct: 10 };

          if (!writerMap.has(writerId)) {
            writerMap.set(writerId, {
              writerId, writerName, profile: ws.profile,
              lines: [], sources: {}, works: new Set(),
              gross: 0, fee: 0, net: 0,
              ipi: ws.profile?.ipi_name_number,
              pro: ws.profile?.pro_affiliation || ws.Society,
            });
          }
          const w = writerMap.get(writerId);
          w.lines.push({
            stmtId: stmt.id,
            stmtSource: stmt.sourceName,
            period: stmt.period?.label,
            workTitle: work['Work Title'],
            iswc: work.ISWC,
            productType,
            sharePct,
            sourceGross: gross,
            gross: feeResult.gross,
            feePct: feeResult.feePct,
            fee: feeResult.fee,
            net: feeResult.net,
            dsp: line.dsp,
            territory: line.territory,
          });
          w.works.add(work['Work Title']);
          w.sources[productType] = (w.sources[productType] || 0) + feeResult.net;
          w.gross += feeResult.gross;
          w.fee += feeResult.fee;
          w.net += feeResult.net;

          totalGross += feeResult.gross;
          totalFee += feeResult.fee;
          totalNet += feeResult.net;
          totalLines++;
        });
      });
    });

    const writers = Array.from(writerMap.values()).sort((a, b) => b.net - a.net);
    return { writers, totals: { gross: totalGross, fee: totalFee, net: totalNet, lines: totalLines } };
  }

  function exportCsvForWriter(writer) {
    const rows = [['Period', 'Source', 'Work', 'ISWC', 'Type', 'Territory', 'DSP', 'Share %', 'Source Gross', 'Pro-Rata Gross', 'Fee %', 'Fee', 'Net (USD)']];
    writer.lines.forEach(l => {
      rows.push([
        l.period || '', l.stmtSource || '', l.workTitle || '', l.iswc || '',
        l.productType || '', l.territory || '', l.dsp || '',
        l.sharePct, l.sourceGross.toFixed(2), l.gross.toFixed(2),
        l.feePct, l.fee.toFixed(2), l.net.toFixed(2),
      ]);
    });
    rows.push([]);
    rows.push(['', '', '', '', '', '', '', 'TOTALS', '', writer.gross.toFixed(2), '', writer.fee.toFixed(2), writer.net.toFixed(2)]);
    return rows.map(r => r.map(c => {
      const s = String(c == null ? '' : c);
      return /[",\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
    }).join(',')).join('\n');
  }

  function downloadCsv(filename, content) {
    const blob = new Blob([content], { type: 'text/csv;charset=utf-8' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url; a.download = filename; a.click();
    setTimeout(() => URL.revokeObjectURL(url), 1000);
  }

  window.WRITER_PAYMENTS_ENGINE = { buildLedger, exportCsvForWriter, downloadCsv };

  // ─── SCREEN ──────────────────────────────────────────────────
  function ScreenWriterPayments({ go, payload }) {
    const PageHeader = window.PageHeader;
    const [tab, setTab] = _S(payload?.tab || 'overview');
    const [activeWriter, setActiveWriter] = _S(payload?.writerId || null);
    const [search, setSearch] = _S('');

    const ledger = _M(() => buildLedger({}), []);

    const filteredWriters = _M(() => {
      const q = search.toLowerCase().trim();
      if (!q) return ledger.writers;
      return ledger.writers.filter(w => w.writerName.toLowerCase().includes(q) || (w.ipi||'').includes(q));
    }, [ledger.writers, search]);

    const currentWriter = activeWriter ? ledger.writers.find(w => w.writerId === activeWriter) : null;

    return (
      <div>
        {PageHeader && (
          <PageHeader
            eyebrow={['ROYALTIES', 'WRITER PAYMENTS', `${ledger.writers.length} WRITERS · $${Math.round(ledger.totals.net).toLocaleString()} NET`]}
            title="distribute to writers."
            highlight="distribute to writers."
            sub="Per-writer distribution reports computed from reconciled statement income, split by ownership %, fees applied per the cascade."
          />
        )}

        <div style={{ borderBottom: '1px solid var(--rule)', display: 'flex', gap: 0, marginBottom: 24 }}>
          {[{ k: 'overview', l: 'Overview' }, { k: 'statement', l: 'Statement' }, { k: 'export', l: 'Export' }].map(t => (
            <button key={t.k} onClick={() => setTab(t.k)} style={{
              padding: '14px 22px', background: 'transparent', border: 0,
              borderBottom: '2px solid ' + (tab === t.k ? 'var(--ink)' : 'transparent'),
              cursor: 'pointer', color: tab === t.k ? 'var(--ink)' : 'var(--ink-3)',
              fontSize: 13, fontWeight: tab === t.k ? 600 : 400,
            }}>{t.l}</button>
          ))}
        </div>

        {tab === 'overview' && <OverviewTab ledger={ledger} filteredWriters={filteredWriters} search={search} setSearch={setSearch} onPick={(id) => { setActiveWriter(id); setTab('statement'); }}/>}
        {tab === 'statement' && <StatementTab writer={currentWriter} writers={ledger.writers} setActive={setActiveWriter}/>}
        {tab === 'export' && <ExportTab ledger={ledger}/>}
      </div>
    );
  }

  // ─── 01 OVERVIEW ─────────────────────────────────────────────
  function OverviewTab({ ledger, filteredWriters, search, setSearch, onPick }) {
    return (
      <div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', borderTop: '1px solid var(--rule)', borderBottom: '1px solid var(--rule)', marginBottom: 24 }}>
          {[
            { l: 'GROSS · ALL WRITERS', v: '$' + Math.round(ledger.totals.gross).toLocaleString(), s: 'pre-fee' },
            { l: 'FEES DEDUCTED', v: '−$' + Math.round(ledger.totals.fee).toLocaleString(), s: 'admin/sub-pub', tone: '#a32a18' },
            { l: 'NET PAYABLE', v: '$' + Math.round(ledger.totals.net).toLocaleString(), s: 'to writers', tone: '#0a8754' },
            { l: 'LINE ITEMS', v: ledger.totals.lines.toLocaleString(), s: 'matched + distributed' },
          ].map((c, i) => (
            <div key={i} style={{ padding: '18px 22px', borderRight: i < 3 ? '1px solid var(--rule)' : 0 }}>
              <Mono upper size={9} color="var(--ink-3)">{c.l}</Mono>
              <div className="ff-display" style={{ fontSize: 26, fontWeight: 600, letterSpacing: '-0.02em', marginTop: 4, color: c.tone || 'var(--ink)' }}>{c.v}</div>
              <div style={{ fontSize: 11, color: 'var(--ink-2)', marginTop: 3 }}>{c.s}</div>
            </div>
          ))}
        </div>

        <div style={{ marginBottom: 14 }}>
          <input type="text" value={search} onChange={(e) => setSearch(e.target.value)} placeholder="Search writers by name or IPI…" style={{ width: 360, padding: '8px 12px', border: '1px solid var(--rule)', fontSize: 12, background: 'var(--bg)', color: 'var(--ink)' }}/>
        </div>

        <div style={{ border: '1px solid var(--rule)' }}>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 130px 100px 110px 110px 110px 100px', gap: 14, padding: '10px 16px', background: 'var(--bg-2)', borderBottom: '1px solid var(--rule)' }}>
            <Mono upper size={9} color="var(--ink-3)">WRITER</Mono>
            <Mono upper size={9} color="var(--ink-3)">PRO · IPI</Mono>
            <Mono upper size={9} color="var(--ink-3)" style={{ textAlign: 'right' }}>WORKS</Mono>
            <Mono upper size={9} color="var(--ink-3)" style={{ textAlign: 'right' }}>GROSS</Mono>
            <Mono upper size={9} color="var(--ink-3)" style={{ textAlign: 'right' }}>FEE</Mono>
            <Mono upper size={9} color="var(--ink-3)" style={{ textAlign: 'right' }}>NET</Mono>
            <Mono upper size={9} color="var(--ink-3)" style={{ textAlign: 'right' }}>—</Mono>
          </div>
          {filteredWriters.length === 0 ? (
            <div style={{ padding: 22, color: 'var(--ink-3)', fontSize: 12, textAlign: 'center' }}>No writers match — or no reconciled income yet</div>
          ) : filteredWriters.slice(0, 200).map((w, i) => (
            <div key={w.writerId} onClick={() => onPick(w.writerId)} style={{ display: 'grid', gridTemplateColumns: '1fr 130px 100px 110px 110px 110px 100px', gap: 14, padding: '11px 16px', borderBottom: i < filteredWriters.length - 1 ? '1px solid var(--rule-soft)' : 0, alignItems: 'center', cursor: 'pointer' }}>
              <div style={{ fontSize: 13, fontWeight: 500 }}>{w.writerName}</div>
              <Mono size={10} color="var(--ink-3)">{w.pro || '—'} {w.ipi ? '· ' + w.ipi : ''}</Mono>
              <Mono size={11} style={{ textAlign: 'right' }}>{w.works.size}</Mono>
              <Mono size={11} style={{ textAlign: 'right' }}>${w.gross.toFixed(2)}</Mono>
              <Mono size={11} style={{ textAlign: 'right', color: '#a32a18' }}>−${w.fee.toFixed(2)}</Mono>
              <Mono size={12} style={{ textAlign: 'right', color: '#0a8754', fontWeight: 600 }}>${w.net.toFixed(2)}</Mono>
              <div style={{ textAlign: 'right' }}><Mono upper size={9} color="var(--ink-3)">VIEW →</Mono></div>
            </div>
          ))}
        </div>
      </div>
    );
  }

  // ─── 02 STATEMENT ────────────────────────────────────────────
  function StatementTab({ writer, writers, setActive }) {
    if (!writer) {
      return (
        <div style={{ padding: 40, textAlign: 'center', border: '1px solid var(--rule)', background: 'var(--paper)' }}>
          <Mono upper size={9} color="var(--ink-3)">SELECT A WRITER</Mono>
          <div style={{ marginTop: 14, fontSize: 13, color: 'var(--ink-2)' }}>Pick a writer from the Overview tab to view their detailed statement.</div>
          {writers.length > 0 && (
            <select onChange={(e) => setActive(e.target.value)} value="" style={{ marginTop: 14, padding: '8px 12px', border: '1px solid var(--rule)', fontSize: 12, background: 'var(--bg)', color: 'var(--ink)' }}>
              <option value="">— pick writer —</option>
              {writers.map(w => <option key={w.writerId} value={w.writerId}>{w.writerName}</option>)}
            </select>
          )}
        </div>
      );
    }

    // Group lines by source
    const bySource = {};
    writer.lines.forEach(l => {
      const k = l.stmtSource || 'Unknown';
      if (!bySource[k]) bySource[k] = { lines: [], gross: 0, fee: 0, net: 0 };
      bySource[k].lines.push(l);
      bySource[k].gross += l.gross; bySource[k].fee += l.fee; bySource[k].net += l.net;
    });

    return (
      <div>
        {/* Statement header (printable) */}
        <div style={{ border: '1px solid var(--rule)', padding: '28px 32px', marginBottom: 18, background: 'var(--paper)' }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 18 }}>
            <div>
              <Mono upper size={9} color="var(--ink-3)">DISTRIBUTION STATEMENT</Mono>
              <div className="ff-display" style={{ fontSize: 32, fontWeight: 600, letterSpacing: '-0.02em', marginTop: 6 }}>{writer.writerName}</div>
              <div style={{ fontSize: 12, color: 'var(--ink-2)', marginTop: 6 }}>
                {writer.pro || '—'} {writer.ipi ? '· IPI ' + writer.ipi : ''} · {writer.works.size} works · {writer.lines.length} line items
              </div>
            </div>
            <div style={{ display: 'flex', gap: 8 }}>
              <button onClick={() => downloadCsv(`writer_${writer.writerName.replace(/\s+/g,'_')}.csv`, exportCsvForWriter(writer))} style={{ padding: '8px 14px', border: '1px solid var(--ink)', background: 'var(--ink)', color: 'var(--bg)', fontSize: 12, cursor: 'pointer' }}>Download CSV</button>
              <button onClick={() => window.print()} style={{ padding: '8px 14px', border: '1px solid var(--rule)', fontSize: 12, background: 'transparent', cursor: 'pointer' }}>Print</button>
            </div>
          </div>

          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', borderTop: '1px solid var(--rule)', borderBottom: '1px solid var(--rule)', padding: '18px 0' }}>
            <div>
              <Mono upper size={9} color="var(--ink-3)">GROSS</Mono>
              <div className="ff-display" style={{ fontSize: 30, fontWeight: 600, letterSpacing: '-0.02em', marginTop: 4 }}>${writer.gross.toFixed(2)}</div>
            </div>
            <div>
              <Mono upper size={9} color="var(--ink-3)">FEE · {writer.gross > 0 ? ((writer.fee / writer.gross) * 100).toFixed(1) : 0}%</Mono>
              <div className="ff-display" style={{ fontSize: 30, fontWeight: 600, letterSpacing: '-0.02em', marginTop: 4, color: '#a32a18' }}>−${writer.fee.toFixed(2)}</div>
            </div>
            <div>
              <Mono upper size={9} color="var(--ink-3)">NET PAYABLE</Mono>
              <div className="ff-display" style={{ fontSize: 30, fontWeight: 600, letterSpacing: '-0.02em', marginTop: 4, color: '#0a8754' }}>${writer.net.toFixed(2)}</div>
            </div>
          </div>
        </div>

        {/* By source summary */}
        <div style={{ border: '1px solid var(--rule)', marginBottom: 18 }}>
          <div style={{ padding: '10px 16px', borderBottom: '1px solid var(--rule)', background: 'var(--bg-2)' }}>
            <Mono upper size={9} color="var(--ink-3)">BY SOURCE · {Object.keys(bySource).length}</Mono>
          </div>
          {Object.entries(bySource).sort((a, b) => b[1].net - a[1].net).map(([src, agg], i, arr) => (
            <div key={src} style={{ display: 'grid', gridTemplateColumns: '1fr 100px 110px 110px 110px', gap: 14, padding: '11px 16px', borderBottom: i < arr.length - 1 ? '1px solid var(--rule-soft)' : 0, alignItems: 'center' }}>
              <div style={{ fontSize: 13, fontWeight: 500 }}>{src}</div>
              <Mono size={11} style={{ textAlign: 'right' }}>{agg.lines.length} lines</Mono>
              <Mono size={11} style={{ textAlign: 'right' }}>${agg.gross.toFixed(2)}</Mono>
              <Mono size={11} style={{ textAlign: 'right', color: '#a32a18' }}>−${agg.fee.toFixed(2)}</Mono>
              <Mono size={12} style={{ textAlign: 'right', color: '#0a8754', fontWeight: 600 }}>${agg.net.toFixed(2)}</Mono>
            </div>
          ))}
        </div>

        {/* Line items */}
        <div style={{ border: '1px solid var(--rule)' }}>
          <div style={{ padding: '10px 16px', borderBottom: '1px solid var(--rule)', background: 'var(--bg-2)' }}>
            <Mono upper size={9} color="var(--ink-3)">LINE ITEMS · {writer.lines.length}</Mono>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '90px 1fr 90px 70px 90px 80px 80px 90px', gap: 10, padding: '8px 16px', borderBottom: '1px solid var(--rule)', background: 'var(--bg)' }}>
            <Mono upper size={9} color="var(--ink-3)">PERIOD</Mono>
            <Mono upper size={9} color="var(--ink-3)">WORK</Mono>
            <Mono upper size={9} color="var(--ink-3)">SOURCE</Mono>
            <Mono upper size={9} color="var(--ink-3)">TYPE</Mono>
            <Mono upper size={9} color="var(--ink-3)" style={{ textAlign: 'right' }}>SHARE</Mono>
            <Mono upper size={9} color="var(--ink-3)" style={{ textAlign: 'right' }}>GROSS</Mono>
            <Mono upper size={9} color="var(--ink-3)" style={{ textAlign: 'right' }}>FEE</Mono>
            <Mono upper size={9} color="var(--ink-3)" style={{ textAlign: 'right' }}>NET</Mono>
          </div>
          {writer.lines.slice(0, 100).map((l, i) => (
            <div key={i} style={{ display: 'grid', gridTemplateColumns: '90px 1fr 90px 70px 90px 80px 80px 90px', gap: 10, padding: '9px 16px', borderBottom: '1px solid var(--rule-soft)', alignItems: 'baseline', fontSize: 11 }}>
              <Mono size={10} color="var(--ink-3)">{l.period || '—'}</Mono>
              <div style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{l.workTitle}</div>
              <Mono size={10} color="var(--ink-3)">{l.stmtSource}</Mono>
              <Mono size={10}>{l.productType?.slice(0,4)}</Mono>
              <Mono size={11} style={{ textAlign: 'right' }}>{l.sharePct}%</Mono>
              <Mono size={11} style={{ textAlign: 'right' }}>${l.gross.toFixed(2)}</Mono>
              <Mono size={11} style={{ textAlign: 'right', color: '#a32a18' }}>−${l.fee.toFixed(2)}</Mono>
              <Mono size={11} style={{ textAlign: 'right', color: '#0a8754', fontWeight: 600 }}>${l.net.toFixed(2)}</Mono>
            </div>
          ))}
          {writer.lines.length > 100 && (
            <div style={{ padding: '11px 16px', textAlign: 'center', fontSize: 11, color: 'var(--ink-3)' }}>
              + {writer.lines.length - 100} more lines — download CSV for full ledger
            </div>
          )}
        </div>
      </div>
    );
  }

  // ─── 03 EXPORT ───────────────────────────────────────────────
  function ExportTab({ ledger }) {
    const [busy, setBusy] = _S(false);

    function bulkExport() {
      // Single CSV with all writer rows (summary)
      const rows = [['Writer', 'PRO', 'IPI', 'Works', 'Lines', 'Gross USD', 'Fee USD', 'Net USD']];
      ledger.writers.forEach(w => {
        rows.push([w.writerName, w.pro || '', w.ipi || '', w.works.size, w.lines.length, w.gross.toFixed(2), w.fee.toFixed(2), w.net.toFixed(2)]);
      });
      rows.push([]);
      rows.push(['', '', '', '', 'TOTAL', ledger.totals.gross.toFixed(2), ledger.totals.fee.toFixed(2), ledger.totals.net.toFixed(2)]);
      const csv = rows.map(r => r.map(c => {
        const s = String(c == null ? '' : c);
        return /[",\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
      }).join(',')).join('\n');
      downloadCsv('writer_payments_summary.csv', csv);
    }

    async function bulkPerWriter() {
      setBusy(true);
      // Trigger downloads sequentially with a small gap
      for (const w of ledger.writers.slice(0, 50)) {
        downloadCsv(`writer_${w.writerName.replace(/\s+/g,'_').replace(/[^a-zA-Z0-9_-]/g,'')}.csv`, exportCsvForWriter(w));
        await new Promise(r => setTimeout(r, 250));
      }
      setBusy(false);
    }

    return (
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 22 }}>
        <div style={{ border: '1px solid var(--rule)', padding: 22, background: 'var(--paper)' }}>
          <Mono upper size={9} color="var(--ink-3)">SUMMARY EXPORT</Mono>
          <div style={{ fontSize: 16, fontWeight: 600, marginTop: 4, fontFamily: 'Space Grotesk' }}>All-writers summary CSV</div>
          <div style={{ fontSize: 12, color: 'var(--ink-2)', marginTop: 8, lineHeight: 1.5 }}>One row per writer with totals: gross, fee, net. Useful for accounting handoff.</div>
          <div style={{ marginTop: 18 }}>
            <button onClick={bulkExport} style={{ padding: '8px 16px', border: '1px solid var(--ink)', background: 'var(--ink)', color: 'var(--bg)', fontSize: 12, fontWeight: 600, cursor: 'pointer' }}>Download summary.csv</button>
          </div>
        </div>

        <div style={{ border: '1px solid var(--rule)', padding: 22, background: 'var(--paper)' }}>
          <Mono upper size={9} color="var(--ink-3)">PER-WRITER EXPORT</Mono>
          <div style={{ fontSize: 16, fontWeight: 600, marginTop: 4, fontFamily: 'Space Grotesk' }}>One CSV per writer · detailed</div>
          <div style={{ fontSize: 12, color: 'var(--ink-2)', marginTop: 8, lineHeight: 1.5 }}>Full line-item ledger for each writer — every reconciled statement line, work, fee, net. {ledger.writers.length} files (max 50 per batch).</div>
          <div style={{ marginTop: 18 }}>
            <button onClick={bulkPerWriter} disabled={busy} style={{ padding: '8px 16px', border: '1px solid var(--ink)', background: busy ? 'var(--rule)' : 'var(--ink)', color: busy ? 'var(--ink-3)' : 'var(--bg)', fontSize: 12, fontWeight: 600, cursor: busy ? 'not-allowed' : 'pointer' }}>
              {busy ? 'Generating…' : `Download ${Math.min(ledger.writers.length, 50)} writer CSVs`}
            </button>
          </div>
        </div>
      </div>
    );
  }

  window.ScreenWriterPayments = ScreenWriterPayments;
  console.log('[WriterPayments] loaded');
})();
