// mlc-sync.jsx — MLC (Mechanical Licensing Collective) sync console
// ─────────────────────────────────────────────────────────────────────
// The MLC is the US blanket-license administrator for streaming
// mechanicals. Every work in our catalog that earns from a US DSP
// (Spotify, Apple, Amazon, etc.) collects its mechanical share through
// the MLC — but only if the work is **registered, matched, and
// claim-clean** at the MLC. Anything unmatched accrues to the
// black-box pool and gets distributed by market share if not claimed
// within the holdback window.
//
// This screen is the operational surface for that sync:
//
//   01 OVERVIEW         — pipeline health: what's matched, what isn't,
//                          what's unregistered, what's earning, what's at risk
//   02 REGISTRATIONS    — works we've sent to MLC + ack status
//   03 USAGE & MATCHES  — DSP usage MLC has identified that we should claim
//   04 CLAIMS & CONFLICTS — overlap claims to resolve with other publishers
//   05 DISTRIBUTIONS    — historical MLC payments, line-level reconciliation
//   06 ACTIVITY         — registrations sent / acks / claims / disputes
//
// Schema (mock — would map to astro.mlc_*):
//   mlc_work     :  workId, mlcCode, status (matched|unmatched|conflict|pending),
//                   registeredAt, lastAck, dspMatches[], claimedShare, blackBox
//   mlc_usage    :  isrc, workId|null, dsp, period, plays, royalty, status
//   mlc_claim    :  id, mlcCode, ourShare, conflictWith[], filedAt, status
//   mlc_distrib  :  period, gross, matched, blackbox, ourCut

const { useState: useMLS, useMemo: useMLM, useEffect: useMLE } = React;

// ─────────── Connection profile (single MLC endpoint, our org's IPI)
const MLC_CONNECTION = {
  status: 'live',
  org: 'Rocket Science Music Publishing',
  publisherCode: 'RSMP',          // MLC-issued publisher code
  ipi: '00731298011',              // our publisher IPI
  ipiSubAccts: [
    { name:'RS Editions',     ipi:'00731298233', code:'RSED' },
    { name:'Pluralis Music',  ipi:'00554029981', code:'PLUR' },
    { name:'Saint Records',   ipi:'00892014700', code:'SRMP' },
  ],
  endpoints: {
    bulkMatch:   { url:'https://api.themlc.com/v3/works/bulk-match',   ok:true,  ms:182 },
    publicSearch:{ url:'https://api.themlc.com/v3/works/search',        ok:true,  ms:94 },
    register:    { url:'https://api.themlc.com/v3/works/register',      ok:true,  ms:248 },
    statements:  { url:'https://api.themlc.com/v3/distributions/feed',  ok:true,  ms:411 },
    claims:      { url:'https://api.themlc.com/v3/claims',              ok:true,  ms:166 },
  },
  lastPoll:        '2026-04-30T16:14:00Z',
  nextScheduled:   '2026-04-30T18:00:00Z',
  pollFreq:        'Every 2h',
  rateLimitWindow: '1,000 / hour · 142 used',
  apiKeyLast4:     'a4f9',
  apiKeyExpires:   '2026-09-12',
};

// ─────────── MLC-mirrored works
// Each row is the projection of one of our WORKS into the MLC's database.
// matchPct = how confident MLC's matcher is that DSP usage maps to this work.
// Real values are deterministically seeded off the work id so it's stable.
function _hash(s){ let h=2166136261>>>0; for(let i=0;i<s.length;i++){h^=s.charCodeAt(i);h=Math.imul(h,16777619);} return h>>>0; }
function _r(seed, n){ const h = _hash(seed); return h % n; }

function buildMlcWorks() {
  if (window.__MLC_WORKS_CACHE) return window.__MLC_WORKS_CACHE;
  const works = (window.WORKS || []);
  const out = works.map((w, i) => {
    const r1 = _r(w.id+'·mlc·1', 100);
    const r2 = _r(w.id+'·mlc·2', 100);
    const r3 = _r(w.id+'·mlc·3', 100);
    let status, matchPct, holdback, mlcCode;
    if (r1 < 60)       { status = 'matched';     matchPct = 92 + (r2 % 8); }
    else if (r1 < 78)  { status = 'partial';     matchPct = 60 + (r2 % 25); }
    else if (r1 < 90)  { status = 'unmatched';   matchPct = 0 + (r2 % 30); }
    else if (r1 < 96)  { status = 'conflict';    matchPct = 100; }
    else               { status = 'unregistered';matchPct = 0; }
    if (status !== 'unregistered') mlcCode = 'MLC' + String(8000000 + (_hash(w.id) % 1900000)).padStart(7,'0');
    holdback = (status === 'unmatched' || status === 'partial')
      ? Math.round(((w.plays||1000000)/1e6) * (12 + (r3 % 18))) // approx $ accruing in black-box
      : 0;
    // Pretend US streaming share is ~38% of plays, royalty ≈ $0.0044/stream of mech
    const usPlays = Math.round((w.plays || 0) * 0.38);
    const earned  = (status === 'matched' || status === 'partial')
      ? Math.round(usPlays * 0.0044 * (matchPct/100))
      : 0;
    return {
      workId: w.id,
      iswc: w.iswc,
      title: w.title,
      writers: w.writers,
      status,
      mlcCode,
      matchPct,
      usPlays,
      earned,
      holdback,
      registeredAt: status !== 'unregistered'
        ? `2024-${String(((_hash(w.id)>>3)%12)+1).padStart(2,'0')}-${String(((_hash(w.id)>>5)%27)+1).padStart(2,'0')}`
        : null,
      lastAck:    status === 'unregistered' ? null : '2026-' + (((_hash(w.id)>>7)%4 < 2) ? '03' : '04') + '-' + String(((_hash(w.id)>>9)%27)+1).padStart(2,'0'),
      // List of DSPs that MLC has confirmed usage for
      dspMatches: ['Spotify','Apple Music','Amazon Music','YouTube Music','Tidal','Pandora']
        .filter((_,j) => (_hash(w.id+'·dsp·'+j) % 100) < (status === 'matched' ? 78 : 40)),
    };
  });
  // Add a few "pure unregistered" MLC entries — works we know about but never sent
  ['w_pending_a','w_pending_b','w_pending_c'].forEach((id, i) => {
    out.push({
      workId: id, iswc: '', title: ['Old Reasons','Half Moon','Pyrite Sun'][i],
      writers: [['A. Cohen'],['M. Lee'],['K. Davis'][i]||['A. Cohen']],
      status:'unregistered', mlcCode: null, matchPct: 0,
      usPlays: 100000 + i*40000, earned: 0, holdback: 1200 + i*400,
      registeredAt: null, lastAck: null, dspMatches: [],
    });
  });
  window.__MLC_WORKS_CACHE = out;
  return out;
}

// ─────────── MLC-identified DSP usage that *might* match our works
function buildMlcUsage() {
  if (window.__MLC_USAGE_CACHE) return window.__MLC_USAGE_CACHE;
  const recs = (window.RECORDINGS || []);
  const out = [];
  // 24 candidate lines — mix of matched, partial, ambiguous
  for (let i=0; i<24; i++) {
    const rec = recs[i % recs.length] || { isrc:'USXXX'+i, title:'Line '+i, artist:'Various' };
    const r = _r('mlc·use·'+i, 100);
    let confidence, status, conflictWith;
    if (r < 55)      { confidence = 92 + (r%7); status = 'auto-matched'; }
    else if (r < 75) { confidence = 70 + (r%15); status = 'review';      }
    else if (r < 88) { confidence = 40 + (r%25); status = 'low-confidence';}
    else             { confidence = 100;          status = 'overlap'; conflictWith = ['Universal MGB','Sony Music Pub','Concord Music Pub'][r%3]; }
    const period = ['2025-Q3','2025-Q4','2026-Q1'][r%3];
    const plays  = 50000 + (_hash(rec.isrc+i) % 800000);
    const dsp    = ['Spotify','Apple Music','Amazon Music','YouTube Music'][r%4];
    out.push({
      id:'mlcu_'+i, isrc: rec.isrc, title: rec.title, artist: rec.artist,
      dsp, period, plays, royalty: Math.round(plays*0.0044),
      confidence, status, conflictWith,
      candidateWorkId: rec.workId || 'w_01',
    });
  }
  window.__MLC_USAGE_CACHE = out;
  return out;
}

// ─────────── MLC distribution history (quarterly)
const MLC_DISTRIBUTIONS = [
  { period:'2026-Q1', payDate:'2026-04-15', gross: 1842000, matched: 1411800, blackbox: 430200, ourCut: 38420, status:'reconciled' },
  { period:'2025-Q4', payDate:'2026-01-15', gross: 1701400, matched: 1289600, blackbox: 411800, ourCut: 32100, status:'reconciled' },
  { period:'2025-Q3', payDate:'2025-10-15', gross: 1612200, matched: 1208900, blackbox: 403300, ourCut: 28940, status:'reconciled' },
  { period:'2025-Q2', payDate:'2025-07-15', gross: 1554800, matched: 1170200, blackbox: 384600, ourCut: 26110, status:'partially-reconciled' },
  { period:'2025-Q1', payDate:'2025-04-15', gross: 1488200, matched: 1098100, blackbox: 390100, ourCut: 24400, status:'reconciled' },
  { period:'2024-Q4', payDate:'2025-01-15', gross: 1429600, matched: 1041800, blackbox: 387800, ourCut: 22120, status:'reconciled' },
  // Black-box redistribution (annual)
  { period:'2024 BB',  payDate:'2025-09-30', gross: 0,       matched: 0,        blackbox: 0,      ourCut: 14882, status:'reconciled', kind:'blackbox-redistribution', note:'Annual unmatched pool · market-share basis' },
];

// ─────────── Activity feed
const MLC_ACTIVITY = [
  { time:'2m',  who:'system',  what:'Bulk Match poll completed',          target:'14 new matches · 2 conflicts surfaced', kind:'match' },
  { time:'1h',  who:'a.cohen', what:'registered',                          target:'3 works (W-9824, W-7711, W-7712)',     kind:'register' },
  { time:'4h',  who:'system',  what:'received MLC ack for batch',          target:'BAT-2026-0430-A · 12/12 accepted',     kind:'ack' },
  { time:'1d',  who:'k.davis', what:'filed counter-claim on',              target:'10% (MLC8214099) vs Universal MGB',    kind:'claim' },
  { time:'1d',  who:'system',  what:'Q1 2026 distribution parsed',         target:'$38,420 / 412 works · ready for reconciliation', kind:'distrib' },
  { time:'2d',  who:'m.lee',   what:'updated writer share on',             target:'Wildfires (T-822.444.118-2)',          kind:'register' },
  { time:'3d',  who:'system',  what:'unmatched holdback alert',            target:'$3,840 accruing on 11 works',          kind:'alert' },
  { time:'5d',  who:'system',  what:'MLC public search verified',          target:'Send Me · matched at 100%',            kind:'match' },
  { time:'1w',  who:'a.cohen', what:'resolved overlap claim',              target:'Two Face — Concord released share',    kind:'claim' },
  { time:'2w',  who:'system',  what:'Q4 2025 distribution reconciled',     target:'$32,100 across 388 works',             kind:'distrib' },
];

// ─────────── small helpers
const fmt$ = (n) => '$' + (n||0).toLocaleString('en-US');
const fmtCompact = (n) => {
  if (n >= 1e6) return '$' + (n/1e6).toFixed(1) + 'M';
  if (n >= 1e3) return '$' + Math.round(n/1e3) + 'k';
  return '$' + (n||0).toLocaleString();
};
const fmtNum = (n) => (n||0).toLocaleString('en-US');

const STATUS_TONES = {
  matched:      { fg:'var(--ok)',     bg:'var(--ok)',     label:'Matched'      },
  partial:      { fg:'var(--info)',   bg:'var(--info)',   label:'Partial'      },
  unmatched:    { fg:'var(--danger)', bg:'var(--danger)', label:'Unmatched'    },
  conflict:     { fg:'var(--danger)', bg:'var(--danger)', label:'Conflict'     },
  unregistered: { fg:'var(--ink-3)',  bg:'var(--ink-3)',  label:'Unregistered' },
};

function StatusDot({ status, size=6 }) {
  const t = STATUS_TONES[status] || STATUS_TONES.matched;
  return <span style={{display:'inline-block',width:size,height:size,borderRadius:size/2,background:t.bg,marginRight:6,verticalAlign:'middle'}}/>;
}

// ─────────── Inline sparkline for match-rate trend
function MlcSpark({ vals, w=80, h=18, color='var(--ink)' }) {
  const max = Math.max(...vals, 1), min = Math.min(...vals, 0);
  const span = (max - min) || 1;
  const pts = vals.map((v,i) => {
    const x = (i/(vals.length-1))*w;
    const y = h - ((v-min)/span)*h;
    return x.toFixed(1)+','+y.toFixed(1);
  }).join(' ');
  return (
    <svg width={w} height={h} style={{display:'block'}}>
      <polyline points={pts} fill="none" stroke={color} strokeWidth={1.2}/>
    </svg>
  );
}

// ─────────── KPI cell (matches subpubs / royalties pattern)
function MlcKpi({ l, v, sub, accent, danger }) {
  return (
    <div style={{padding:'18px 20px',display:'flex',flexDirection:'column',gap:4,minHeight:96}}>
      <div className="ff-mono upper" style={{fontSize:9,letterSpacing:'.12em',color:'var(--ink-3)'}}>{l}</div>
      <div className="ff-mono num" style={{fontSize:28,lineHeight:1,fontWeight:500,
        color: danger ? 'var(--danger)' : (accent ? 'var(--accent-ink)' : 'var(--ink)'),
        background: accent ? 'var(--accent)' : 'transparent',
        padding: accent ? '2px 6px' : 0, alignSelf:'flex-start', marginTop:4,
      }}>{v}</div>
      {sub && <div style={{fontSize:11,color:'var(--ink-3)',marginTop:4,lineHeight:1.4}}>{sub}</div>}
    </div>
  );
}

// ─────────── 01 OVERVIEW TAB
function MlcOverviewTab({ mlcWorks, mlcUsage, go, setTab }) {
  const stats = useMLM(() => {
    const counts = { matched:0, partial:0, unmatched:0, conflict:0, unregistered:0 };
    let totalEarned = 0, totalHoldback = 0;
    mlcWorks.forEach(w => {
      counts[w.status] = (counts[w.status]||0) + 1;
      totalEarned += w.earned; totalHoldback += w.holdback;
    });
    const total = mlcWorks.length;
    const matchPct = total ? ((counts.matched + counts.partial) / total * 100) : 0;
    return { counts, total, matchPct, totalEarned, totalHoldback };
  }, [mlcWorks]);

  const usageStats = useMLM(() => {
    const by = { 'auto-matched':0, 'review':0, 'low-confidence':0, 'overlap':0 };
    mlcUsage.forEach(u => { by[u.status] = (by[u.status]||0)+1; });
    return by;
  }, [mlcUsage]);

  // Match-rate trend (last 8 quarters, deterministic)
  const trend = [62, 64, 67, 71, 73, 76, 78, Math.round(stats.matchPct)];

  return (
    <div>
      {/* KPI strip */}
      <div style={{display:'grid',gridTemplateColumns:'repeat(5, 1fr)',borderTop:'1px solid var(--rule)',borderBottom:'1px solid var(--rule)'}}>
        <MlcKpi l="WORKS AT MLC" v={fmtNum(stats.total)}
          sub={`${stats.counts.unregistered} unregistered · ${stats.total - stats.counts.unregistered} on file`}/>
        <div style={{borderLeft:'1px solid var(--rule)'}}>
          <MlcKpi l="MATCH RATE" v={stats.matchPct.toFixed(1)+'%'}
            sub={`${stats.counts.matched} matched · ${stats.counts.partial} partial`}/>
        </div>
        <div style={{borderLeft:'1px solid var(--rule)'}}>
          <MlcKpi l="UNMATCHED" v={fmtNum(stats.counts.unmatched)} danger
            sub={`${fmt$(stats.totalHoldback)} accruing in black-box pool`}/>
        </div>
        <div style={{borderLeft:'1px solid var(--rule)'}}>
          <MlcKpi l="CONFLICTS" v={fmtNum(stats.counts.conflict)}
            sub="overlapping claims · need resolution"/>
        </div>
        <div style={{borderLeft:'1px solid var(--rule)'}}>
          <MlcKpi l="LAST DISTRIBUTION" v={fmtCompact(MLC_DISTRIBUTIONS[0].ourCut)} accent
            sub={`${MLC_DISTRIBUTIONS[0].period} · paid ${MLC_DISTRIBUTIONS[0].payDate}`}/>
        </div>
      </div>

      {/* Pipeline diagram */}
      <div style={{marginTop:24,padding:'0 4px'}}>
        <div className="ff-mono upper" style={{fontSize:10,letterSpacing:'.12em',color:'var(--ink-3)',marginBottom:14}}>
          THE PIPELINE · CATALOG → MLC → DSP USAGE → DISTRIBUTION
        </div>
        <div style={{display:'grid',gridTemplateColumns:'1fr auto 1fr auto 1fr auto 1fr',alignItems:'center',gap:0,fontSize:12}}>
          {/* Catalog */}
          <PipelineNode
            title="Our catalog"
            big={fmtNum(stats.total)}
            sub="works in scope"
            note={`+${stats.counts.unregistered} not yet sent`}
          />
          <PipelineArrow/>
          {/* Registered */}
          <PipelineNode
            title="Registered at MLC"
            big={fmtNum(stats.total - stats.counts.unregistered)}
            sub={`${((stats.total - stats.counts.unregistered)/stats.total*100).toFixed(0)}% of catalog`}
            note="ack received"
          />
          <PipelineArrow/>
          {/* Matched */}
          <PipelineNode
            title="Matched to usage"
            big={fmtNum(stats.counts.matched + stats.counts.partial)}
            sub={`${stats.matchPct.toFixed(0)}% of catalog`}
            note={`${stats.counts.partial} partial`}
            accent
          />
          <PipelineArrow/>
          {/* Earned */}
          <PipelineNode
            title="Earning"
            big={fmtCompact(stats.totalEarned)}
            sub="lifetime mech"
            note={`vs ${fmtCompact(stats.totalHoldback)} held`}
          />
        </div>
      </div>

      {/* Two columns: leakage + connection */}
      <div style={{display:'grid',gridTemplateColumns:'1.4fr 1fr',gap:24,marginTop:32,paddingTop:24,borderTop:'1px solid var(--rule)'}}>
        {/* Leakage card — what's at risk */}
        <div>
          <div style={{display:'flex',alignItems:'baseline',justifyContent:'space-between',marginBottom:14}}>
            <div className="ff-mono upper" style={{fontSize:10,letterSpacing:'.12em',color:'var(--ink-3)'}}>
              LEAKAGE · WHAT'S COSTING US RIGHT NOW
            </div>
            <button onClick={()=>setTab('registrations')} className="ff-mono upper"
              style={{fontSize:10,letterSpacing:'.08em',color:'var(--ink-2)',background:'transparent',border:'1px solid var(--rule)',padding:'4px 10px',cursor:'pointer'}}>
              FIX → REGISTRATIONS
            </button>
          </div>
          <div style={{border:'1px solid var(--rule)'}}>
            <LeakRow
              dot="danger"
              count={stats.counts.unregistered}
              title="works never registered with MLC"
              risk={fmt$(stats.counts.unregistered * 280)}
              note="Estimated quarterly mech share if registered"
              cta="Register now"
              onClick={()=>setTab('registrations')}
            />
            <LeakRow
              dot="danger"
              count={stats.counts.unmatched}
              title="registered works with zero DSP matches"
              risk={fmt$(Math.round(stats.totalHoldback * 0.6))}
              note="Already accrued in black-box pool · re-claim within 3 yrs"
              cta="Run Bulk Match"
              onClick={()=>setTab('matches')}
            />
            <LeakRow
              dot="warn"
              count={stats.counts.partial}
              title="works with partial DSP coverage"
              risk={fmt$(Math.round(stats.totalHoldback * 0.4))}
              note="Some DSPs matched, others not — usually a release-side ISRC gap"
              cta="Investigate"
              onClick={()=>setTab('matches')}
            />
            <LeakRow
              dot="warn"
              count={stats.counts.conflict}
              title="overlap claims with other publishers"
              risk="—"
              note="Distribution is held in escrow until resolved"
              cta="Resolve"
              onClick={()=>setTab('claims')}
              last
            />
          </div>
        </div>

        {/* Connection panel */}
        <div>
          <div className="ff-mono upper" style={{fontSize:10,letterSpacing:'.12em',color:'var(--ink-3)',marginBottom:14}}>
            CONNECTION
          </div>
          <div style={{border:'1px solid var(--rule)',padding:16}}>
            <div style={{display:'flex',alignItems:'center',gap:10,marginBottom:14}}>
              <span style={{display:'inline-block',width:8,height:8,borderRadius:4,background:'var(--ok)'}}/>
              <div style={{fontSize:14,fontWeight:600}}>Live</div>
              <span className="ff-mono" style={{fontSize:10,color:'var(--ink-3)',marginLeft:'auto'}}>
                last poll {new Date(MLC_CONNECTION.lastPoll).toLocaleTimeString('en-US',{hour:'numeric',minute:'2-digit'})}
              </span>
            </div>
            <ConnRow l="Publisher" v={`${MLC_CONNECTION.org} · ${MLC_CONNECTION.publisherCode}`}/>
            <ConnRow l="Primary IPI" v={MLC_CONNECTION.ipi} mono/>
            <ConnRow l="Sub-accounts" v={`${MLC_CONNECTION.ipiSubAccts.length} entities`}/>
            <ConnRow l="Poll cadence" v={MLC_CONNECTION.pollFreq}/>
            <ConnRow l="Rate limit" v={MLC_CONNECTION.rateLimitWindow}/>
            <ConnRow l="API key" v={`···${MLC_CONNECTION.apiKeyLast4} · expires ${MLC_CONNECTION.apiKeyExpires}`} mono/>
            <div style={{borderTop:'1px solid var(--rule)',marginTop:12,paddingTop:12}}>
              <div className="ff-mono upper" style={{fontSize:9,letterSpacing:'.1em',color:'var(--ink-3)',marginBottom:8}}>ENDPOINTS</div>
              {Object.entries(MLC_CONNECTION.endpoints).map(([k,v]) => (
                <div key={k} style={{display:'flex',alignItems:'center',gap:8,fontSize:11,padding:'3px 0'}}>
                  <span style={{display:'inline-block',width:6,height:6,borderRadius:3,background: v.ok?'var(--ok)':'var(--danger)'}}/>
                  <span className="ff-mono" style={{flex:1,color:'var(--ink-2)'}}>{k}</span>
                  <span className="ff-mono num" style={{color:'var(--ink-3)'}}>{v.ms}ms</span>
                </div>
              ))}
            </div>
            <button className="ff-mono upper"
              style={{marginTop:14,width:'100%',fontSize:10,letterSpacing:'.1em',padding:'8px 12px',background:'transparent',color:'var(--ink-2)',border:'1px solid var(--rule)',cursor:'pointer'}}>
              POLL NOW
            </button>
          </div>

          {/* Match-rate trend */}
          <div style={{marginTop:20,border:'1px solid var(--rule)',padding:16}}>
            <div className="ff-mono upper" style={{fontSize:9,letterSpacing:'.1em',color:'var(--ink-3)',marginBottom:8}}>
              MATCH-RATE TREND · 8 QUARTERS
            </div>
            <div style={{display:'flex',alignItems:'flex-end',gap:14}}>
              <div className="ff-mono num" style={{fontSize:28,fontWeight:500,lineHeight:1}}>{stats.matchPct.toFixed(1)}%</div>
              <div style={{flex:1}}>
                <MlcSpark vals={trend} w={140} h={28}/>
              </div>
              <div className="ff-mono num" style={{fontSize:11,color:'var(--ok)'}}>+{(trend[7]-trend[0])}pp</div>
            </div>
            <div style={{fontSize:11,color:'var(--ink-3)',marginTop:8,lineHeight:1.4}}>
              Sustained climb since Q3 2024 — driven by sub-account split and Bulk Match
              automation.
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

function PipelineNode({ title, big, sub, note, accent }) {
  return (
    <div style={{padding:'14px 16px',border:'1px solid var(--rule)',background: accent ? 'var(--bg-2)' : 'var(--paper)'}}>
      <div className="ff-mono upper" style={{fontSize:9,letterSpacing:'.1em',color:'var(--ink-3)'}}>{title}</div>
      <div className="ff-mono num" style={{fontSize:24,fontWeight:500,marginTop:6,lineHeight:1, color: accent ? 'var(--accent-ink)' : 'var(--ink)'}}>{big}</div>
      <div style={{fontSize:11,color:'var(--ink-2)',marginTop:4}}>{sub}</div>
      {note && <div style={{fontSize:10,color:'var(--ink-3)',marginTop:4}}>{note}</div>}
    </div>
  );
}
function PipelineArrow() {
  return (
    <div style={{display:'flex',alignItems:'center',justifyContent:'center',padding:'0 6px'}}>
      <svg width={28} height={12} viewBox="0 0 28 12" style={{color:'var(--ink-3)'}}>
        <line x1="0" y1="6" x2="22" y2="6" stroke="currentColor" strokeWidth="1"/>
        <polyline points="18,2 22,6 18,10" fill="none" stroke="currentColor" strokeWidth="1"/>
      </svg>
    </div>
  );
}
function LeakRow({ dot, count, title, risk, note, cta, onClick, last }) {
  const dotColor = dot === 'danger' ? 'var(--danger)' : dot === 'warn' ? 'var(--warn, #d4881f)' : 'var(--ok)';
  return (
    <div style={{display:'grid',gridTemplateColumns:'auto 1fr auto auto',alignItems:'center',gap:14,padding:'14px 16px',borderBottom: last?'none':'1px solid var(--rule)'}}>
      <div style={{display:'flex',alignItems:'center',gap:10}}>
        <span style={{display:'inline-block',width:8,height:8,borderRadius:4,background:dotColor}}/>
        <span className="ff-mono num" style={{fontSize:18,fontWeight:500,minWidth:32}}>{count}</span>
      </div>
      <div>
        <div style={{fontSize:13}}>{title}</div>
        <div style={{fontSize:11,color:'var(--ink-3)',marginTop:2}}>{note}</div>
      </div>
      <div className="ff-mono num" style={{fontSize:13,color: risk==='—' ? 'var(--ink-3)' : 'var(--danger)',whiteSpace:'nowrap'}}>{risk}</div>
      <button onClick={onClick} className="ff-mono upper"
        style={{fontSize:10,letterSpacing:'.08em',padding:'5px 10px',background:'transparent',color:'var(--ink)',border:'1px solid var(--ink)',cursor:'pointer',whiteSpace:'nowrap'}}>
        {cta} →
      </button>
    </div>
  );
}
function ConnRow({ l, v, mono }) {
  return (
    <div style={{display:'flex',justifyContent:'space-between',gap:10,padding:'5px 0',fontSize:11,borderBottom:'1px solid var(--rule-soft, var(--bg-2))'}}>
      <span style={{color:'var(--ink-3)'}}>{l}</span>
      <span className={mono?'ff-mono':''} style={{color:'var(--ink)',textAlign:'right'}}>{v}</span>
    </div>
  );
}

// ─────────── 02 REGISTRATIONS TAB
function MlcRegistrationsTab({ mlcWorks, go }) {
  const [filter, setFilter] = useMLS('all');
  const [selected, setSelected] = useMLS(new Set());

  const filtered = useMLM(() => {
    if (filter === 'all') return mlcWorks;
    return mlcWorks.filter(w => w.status === filter);
  }, [mlcWorks, filter]);

  const filters = [
    { k:'all',           l:'All',           n: mlcWorks.length },
    { k:'matched',       l:'Matched',       n: mlcWorks.filter(w=>w.status==='matched').length },
    { k:'partial',       l:'Partial',       n: mlcWorks.filter(w=>w.status==='partial').length },
    { k:'unmatched',     l:'Unmatched',     n: mlcWorks.filter(w=>w.status==='unmatched').length },
    { k:'conflict',      l:'Conflict',      n: mlcWorks.filter(w=>w.status==='conflict').length },
    { k:'unregistered',  l:'Not registered', n: mlcWorks.filter(w=>w.status==='unregistered').length },
  ];

  const toggle = (id) => {
    setSelected(s => { const n=new Set(s); if(n.has(id))n.delete(id);else n.add(id); return n; });
  };
  const toggleAll = () => {
    if (selected.size === filtered.length) setSelected(new Set());
    else setSelected(new Set(filtered.map(w => w.workId)));
  };

  return (
    <div style={{paddingTop:8}}>
      {/* Filter bar + bulk action */}
      <div style={{display:'flex',alignItems:'center',gap:0,borderBottom:'1px solid var(--rule)',marginBottom:0}}>
        {filters.map(f => (
          <button key={f.k} onClick={()=>setFilter(f.k)} className="ff-mono upper"
            style={{padding:'10px 14px',border:0,background:'transparent',
              borderBottom:'2px solid '+(filter===f.k?'var(--ink)':'transparent'),
              color: filter===f.k?'var(--ink)':'var(--ink-3)',
              fontSize:11,letterSpacing:'.06em',cursor:'pointer',display:'flex',gap:8,alignItems:'baseline'}}>
            {f.l} <span className="ff-mono num" style={{fontSize:10,color:'var(--ink-3)'}}>{f.n}</span>
          </button>
        ))}
        <div style={{flex:1}}/>
        {selected.size > 0 && (
          <div style={{display:'flex',gap:8,alignItems:'center',padding:'0 8px'}}>
            <span className="ff-mono" style={{fontSize:11,color:'var(--ink-2)'}}>{selected.size} selected</span>
            <button className="ff-mono upper" style={{fontSize:10,letterSpacing:'.08em',padding:'6px 12px',background:'var(--ink)',color:'var(--bg)',border:0,cursor:'pointer'}}>
              REGISTER WITH MLC →
            </button>
            <button className="ff-mono upper" style={{fontSize:10,letterSpacing:'.08em',padding:'6px 12px',background:'transparent',color:'var(--ink-2)',border:'1px solid var(--rule)',cursor:'pointer'}}>
              RUN BULK MATCH
            </button>
          </div>
        )}
      </div>

      {/* Table */}
      <div style={{overflowX:'auto'}}>
        <table style={{width:'100%',borderCollapse:'collapse',fontSize:12,minWidth:1100}}>
          <thead>
            <tr style={{borderBottom:'1px solid var(--rule)'}}>
              <th style={thStyle({w:36,center:true})}>
                <input type="checkbox" checked={selected.size === filtered.length && filtered.length > 0} onChange={toggleAll}/>
              </th>
              <th style={thStyle({left:true})}>Work</th>
              <th style={thStyle({w:110})}>ISWC</th>
              <th style={thStyle({w:120})}>MLC code</th>
              <th style={thStyle({w:110})}>Status</th>
              <th style={thStyle({w:80,right:true})}>Match</th>
              <th style={thStyle({w:160,left:true})}>DSP coverage</th>
              <th style={thStyle({w:100,right:true})}>US plays</th>
              <th style={thStyle({w:100,right:true})}>Earned</th>
              <th style={thStyle({w:100,right:true})}>At risk</th>
            </tr>
          </thead>
          <tbody>
            {filtered.slice(0, 30).map(w => {
              const tone = STATUS_TONES[w.status];
              return (
                <tr key={w.workId} style={{borderBottom:'1px solid var(--rule-soft, var(--bg-2))', cursor:'pointer'}}
                    onClick={()=> w.workId.startsWith('w_') && go && go('work', { id: w.workId })}>
                  <td style={tdStyle({center:true})} onClick={e=>e.stopPropagation()}>
                    <input type="checkbox" checked={selected.has(w.workId)} onChange={()=>toggle(w.workId)}/>
                  </td>
                  <td style={tdStyle()}>
                    <div style={{fontWeight:500}}>{w.title}</div>
                    <div style={{fontSize:10,color:'var(--ink-3)',marginTop:2}}>{(w.writers||[]).join(' · ')}</div>
                  </td>
                  <td style={tdStyle({mono:true,muted:true})}>{w.iswc || '—'}</td>
                  <td style={tdStyle({mono:true})}>
                    {w.mlcCode || <span style={{color:'var(--ink-3)'}}>—</span>}
                  </td>
                  <td style={tdStyle()}>
                    <span style={{display:'inline-flex',alignItems:'center',gap:6,fontSize:11,
                      color: tone.fg, padding:'2px 6px', border: '1px solid '+tone.fg}}>
                      <StatusDot status={w.status}/>{tone.label}
                    </span>
                  </td>
                  <td style={tdStyle({mono:true,num:true,right:true})}>
                    {w.status === 'unregistered' ? '—' :
                      <span style={{color: w.matchPct >= 90 ? 'var(--ok)' : w.matchPct >= 60 ? 'var(--ink)' : 'var(--danger)'}}>
                        {w.matchPct}%
                      </span>}
                  </td>
                  <td style={tdStyle()}>
                    <DspBar matches={w.dspMatches}/>
                  </td>
                  <td style={tdStyle({mono:true,num:true,right:true,muted:true})}>{fmtNum(w.usPlays)}</td>
                  <td style={tdStyle({mono:true,num:true,right:true})}>{fmt$(w.earned)}</td>
                  <td style={tdStyle({mono:true,num:true,right:true})}>
                    {w.holdback > 0 ? <span style={{color:'var(--danger)'}}>{fmt$(w.holdback)}</span> : <span style={{color:'var(--ink-3)'}}>—</span>}
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
        {filtered.length > 30 && (
          <div style={{padding:'14px 16px',fontSize:11,color:'var(--ink-3)',textAlign:'center',borderBottom:'1px solid var(--rule)'}}>
            Showing 30 of {filtered.length} — refine filter to narrow
          </div>
        )}
      </div>
    </div>
  );
}

function DspBar({ matches }) {
  const ALL = ['Spotify','Apple Music','Amazon Music','YouTube Music','Tidal','Pandora'];
  return (
    <div style={{display:'flex',gap:3}}>
      {ALL.map(d => {
        const on = matches.includes(d);
        return (
          <span key={d} title={d + (on?' · matched':' · not matched')}
            style={{
              width:14,height:14,display:'inline-block',
              border:'1px solid '+(on?'var(--ok)':'var(--rule)'),
              background: on?'var(--ok)':'transparent',
            }}/>
        );
      })}
    </div>
  );
}

function thStyle({ w, left, right, center }) {
  return {
    width: w, padding:'8px 10px',
    textAlign: left?'left': right?'right': center?'center':'left',
    fontSize:9, letterSpacing:'.1em', textTransform:'uppercase',
    color:'var(--ink-3)', fontWeight:500,
  };
}
function tdStyle({ mono, num, right, center, muted }={}) {
  return {
    padding:'10px 10px',
    fontFamily: mono?'var(--ff-mono, monospace)':'inherit',
    fontVariantNumeric: num?'tabular-nums':'normal',
    textAlign: right?'right': center?'center':'left',
    color: muted?'var(--ink-3)':'var(--ink)',
    verticalAlign:'top',
  };
}

// ─────────── 03 USAGE & MATCHES TAB
function MlcMatchesTab({ mlcUsage, mlcWorks }) {
  const [tab, setTab] = useMLS('review');
  const usageByStatus = (s) => mlcUsage.filter(u => u.status === s);

  const lists = {
    'auto-matched':    usageByStatus('auto-matched'),
    'review':          usageByStatus('review'),
    'low-confidence':  usageByStatus('low-confidence'),
    'overlap':         usageByStatus('overlap'),
  };

  const T = [
    { k:'review',         l:'Needs review',   n: lists['review'].length,        warn:true },
    { k:'low-confidence', l:'Low confidence', n: lists['low-confidence'].length, warn:true },
    { k:'overlap',        l:'Overlaps',       n: lists['overlap'].length,        warn:true },
    { k:'auto-matched',   l:'Auto-matched',   n: lists['auto-matched'].length },
  ];

  return (
    <div style={{paddingTop:8}}>
      <div style={{display:'flex',alignItems:'baseline',justifyContent:'space-between',marginBottom:14}}>
        <div style={{fontSize:13,color:'var(--ink-2)',maxWidth:680,lineHeight:1.5}}>
          MLC's Bulk Match endpoint cross-references DSP usage against our registered works.
          High-confidence matches auto-claim. Anything below {' '}
          <span className="ff-mono num" style={{color:'var(--ink)'}}>92%</span>{' '}
          comes here for human review — confirm or reject; the matcher learns from each call.
        </div>
        <button className="ff-mono upper"
          style={{fontSize:10,letterSpacing:'.1em',padding:'8px 14px',background:'var(--ink)',color:'var(--bg)',border:0,cursor:'pointer',whiteSpace:'nowrap'}}>
          RUN BULK MATCH ↻
        </button>
      </div>

      {/* sub-tabs */}
      <div style={{display:'flex',borderBottom:'1px solid var(--rule)'}}>
        {T.map(t => (
          <button key={t.k} onClick={()=>setTab(t.k)} className="ff-mono upper"
            style={{padding:'10px 14px',border:0,background:'transparent',
              borderBottom:'2px solid '+(tab===t.k?'var(--ink)':'transparent'),
              color: tab===t.k?'var(--ink)':'var(--ink-3)',fontSize:11,letterSpacing:'.06em',cursor:'pointer',
              display:'flex',alignItems:'baseline',gap:8}}>
            {t.l}
            <span className="ff-mono num" style={{fontSize:10, color: t.warn && t.n>0 ? 'var(--danger)':'var(--ink-3)'}}>{t.n}</span>
          </button>
        ))}
      </div>

      {/* list */}
      <div>
        {(lists[tab]||[]).map(u => <MatchRow key={u.id} u={u} mlcWorks={mlcWorks}/>)}
        {(lists[tab]||[]).length === 0 && (
          <div style={{padding:'40px 20px',textAlign:'center',color:'var(--ink-3)',border:'1px dashed var(--rule)',marginTop:16,fontSize:13}}>
            Nothing here. Re-run Bulk Match to refresh.
          </div>
        )}
      </div>
    </div>
  );
}

function MatchRow({ u, mlcWorks }) {
  const candidate = mlcWorks.find(w => w.workId === u.candidateWorkId);
  return (
    <div style={{display:'grid',gridTemplateColumns:'1fr auto',gap:24,alignItems:'center',padding:'14px 0',borderBottom:'1px solid var(--rule)'}}>
      <div style={{display:'grid',gridTemplateColumns:'1.4fr 1fr 0.8fr 0.8fr',gap:18,alignItems:'center'}}>
        {/* DSP usage line */}
        <div>
          <div style={{fontSize:13,fontWeight:500}}>{u.title}</div>
          <div style={{fontSize:11,color:'var(--ink-3)',marginTop:2}}>{u.artist} · <span className="ff-mono">{u.isrc}</span></div>
        </div>
        {/* candidate work */}
        <div>
          <div className="ff-mono upper" style={{fontSize:9,letterSpacing:'.1em',color:'var(--ink-3)'}}>CANDIDATE WORK</div>
          <div style={{fontSize:12,marginTop:2}}>
            {candidate ? candidate.title : 'no match'}
          </div>
          {candidate && <div className="ff-mono" style={{fontSize:10,color:'var(--ink-3)'}}>{candidate.iswc}</div>}
        </div>
        {/* metrics */}
        <div>
          <div className="ff-mono upper" style={{fontSize:9,letterSpacing:'.1em',color:'var(--ink-3)'}}>{u.dsp} · {u.period}</div>
          <div className="ff-mono num" style={{fontSize:13,marginTop:2}}>{fmtNum(u.plays)} <span style={{color:'var(--ink-3)',fontSize:10}}>plays</span></div>
          <div className="ff-mono num" style={{fontSize:11,color:'var(--ink-2)'}}>{fmt$(u.royalty)}</div>
        </div>
        {/* confidence + conflict */}
        <div>
          <div className="ff-mono upper" style={{fontSize:9,letterSpacing:'.1em',color:'var(--ink-3)'}}>CONFIDENCE</div>
          <div style={{display:'flex',alignItems:'center',gap:6,marginTop:4}}>
            <div style={{flex:1,height:6,background:'var(--bg-2)',position:'relative'}}>
              <div style={{position:'absolute',top:0,left:0,bottom:0,width:u.confidence+'%',background: u.confidence>=90?'var(--ok)':u.confidence>=70?'var(--ink)':'var(--danger)'}}/>
            </div>
            <span className="ff-mono num" style={{fontSize:11,minWidth:32,textAlign:'right'}}>{u.confidence}%</span>
          </div>
          {u.conflictWith && (
            <div style={{fontSize:10,color:'var(--danger)',marginTop:4}}>
              conflicts with {u.conflictWith}
            </div>
          )}
        </div>
      </div>
      {/* actions */}
      <div style={{display:'flex',gap:6}}>
        {u.status === 'overlap' ? (
          <>
            <button className="ff-mono upper" style={btnPrimary}>FILE COUNTER ⚖</button>
            <button className="ff-mono upper" style={btnGhost}>RELEASE</button>
          </>
        ) : (
          <>
            <button className="ff-mono upper" style={btnPrimary}>CLAIM ✓</button>
            <button className="ff-mono upper" style={btnGhost}>REJECT</button>
            <button className="ff-mono upper" style={btnGhost}>SKIP</button>
          </>
        )}
      </div>
    </div>
  );
}

const btnPrimary = { fontSize:10,letterSpacing:'.08em',padding:'6px 10px',background:'var(--ink)',color:'var(--bg)',border:0,cursor:'pointer',whiteSpace:'nowrap' };
const btnGhost   = { fontSize:10,letterSpacing:'.08em',padding:'6px 10px',background:'transparent',color:'var(--ink-2)',border:'1px solid var(--rule)',cursor:'pointer',whiteSpace:'nowrap' };

// ─────────── 04 CLAIMS & CONFLICTS TAB
function MlcClaimsTab({ mlcWorks, mlcUsage }) {
  const conflicts = mlcWorks.filter(w => w.status === 'conflict');
  const overlaps  = mlcUsage.filter(u => u.status === 'overlap');

  return (
    <div style={{paddingTop:8}}>
      <div style={{fontSize:13,color:'var(--ink-2)',maxWidth:680,lineHeight:1.5,marginBottom:18}}>
        When two publishers claim overlapping shares of the same work, the MLC holds
        distribution in escrow until the dispute is resolved. Resolve by sub-publisher
        agreement, splits letter, or — if necessary — formal counter-claim.
      </div>

      {/* conflicts */}
      <div className="ff-mono upper" style={{fontSize:10,letterSpacing:'.12em',color:'var(--ink-3)',marginBottom:10}}>
        CONFLICTS ON OUR WORKS · {conflicts.length}
      </div>
      <div style={{border:'1px solid var(--rule)',marginBottom:30}}>
        {conflicts.length === 0 && (
          <div style={{padding:'20px',textAlign:'center',color:'var(--ink-3)',fontSize:13}}>No active conflicts</div>
        )}
        {conflicts.map((w,i) => (
          <div key={w.workId} style={{display:'grid',gridTemplateColumns:'1fr auto auto auto',gap:14,padding:'14px 16px',alignItems:'center',borderBottom: i<conflicts.length-1?'1px solid var(--rule)':'none'}}>
            <div>
              <div style={{fontSize:13,fontWeight:500}}>{w.title}</div>
              <div style={{fontSize:11,color:'var(--ink-3)',marginTop:2}}>
                <span className="ff-mono">{w.iswc}</span> · {w.mlcCode}
              </div>
            </div>
            <div>
              <div className="ff-mono upper" style={{fontSize:9,letterSpacing:'.1em',color:'var(--ink-3)'}}>OUR SHARE</div>
              <div className="ff-mono num" style={{fontSize:13,marginTop:2}}>{50 + (_hash(w.workId)%40)}%</div>
            </div>
            <div>
              <div className="ff-mono upper" style={{fontSize:9,letterSpacing:'.1em',color:'var(--ink-3)'}}>CONFLICTING</div>
              <div style={{fontSize:12,marginTop:2}}>{['Universal MGB','Sony Music Pub','Concord','Kobalt'][_hash(w.workId)%4]}</div>
            </div>
            <div style={{display:'flex',gap:6}}>
              <button className="ff-mono upper" style={btnPrimary}>RESOLVE →</button>
              <button className="ff-mono upper" style={btnGhost}>EVIDENCE</button>
            </div>
          </div>
        ))}
      </div>

      {/* overlap claims */}
      <div className="ff-mono upper" style={{fontSize:10,letterSpacing:'.12em',color:'var(--ink-3)',marginBottom:10}}>
        OVERLAPPING USAGE CLAIMS · {overlaps.length}
      </div>
      <div style={{border:'1px solid var(--rule)'}}>
        {overlaps.length === 0 && (
          <div style={{padding:'20px',textAlign:'center',color:'var(--ink-3)',fontSize:13}}>No overlap claims</div>
        )}
        {overlaps.map((u,i) => (
          <div key={u.id} style={{display:'grid',gridTemplateColumns:'1.4fr 1fr 1fr auto',gap:14,padding:'14px 16px',alignItems:'center',borderBottom: i<overlaps.length-1?'1px solid var(--rule)':'none'}}>
            <div>
              <div style={{fontSize:13,fontWeight:500}}>{u.title}</div>
              <div style={{fontSize:11,color:'var(--ink-3)',marginTop:2}}>
                {u.artist} · <span className="ff-mono">{u.isrc}</span>
              </div>
            </div>
            <div>
              <div className="ff-mono upper" style={{fontSize:9,letterSpacing:'.1em',color:'var(--ink-3)'}}>USAGE</div>
              <div style={{fontSize:12,marginTop:2}}>{u.dsp} · {u.period}</div>
              <div className="ff-mono num" style={{fontSize:11,color:'var(--ink-2)'}}>{fmtNum(u.plays)} plays · {fmt$(u.royalty)}</div>
            </div>
            <div>
              <div className="ff-mono upper" style={{fontSize:9,letterSpacing:'.1em',color:'var(--ink-3)'}}>CONFLICTING</div>
              <div style={{fontSize:12,marginTop:2}}>{u.conflictWith}</div>
            </div>
            <div style={{display:'flex',gap:6}}>
              <button className="ff-mono upper" style={btnPrimary}>FILE ⚖</button>
              <button className="ff-mono upper" style={btnGhost}>RELEASE</button>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ─────────── 05 DISTRIBUTIONS TAB
function MlcDistributionsTab({ go }) {
  const total = MLC_DISTRIBUTIONS.reduce((s,d)=>s+d.ourCut, 0);
  const totalGross = MLC_DISTRIBUTIONS.reduce((s,d)=>s+(d.gross||0), 0);
  const totalBB = MLC_DISTRIBUTIONS.reduce((s,d)=>s+(d.blackbox||0), 0);
  return (
    <div style={{paddingTop:8}}>
      {/* summary */}
      <div style={{display:'grid',gridTemplateColumns:'repeat(4, 1fr)',borderTop:'1px solid var(--rule)',borderBottom:'1px solid var(--rule)'}}>
        <MlcKpi l="LIFETIME COLLECTED" v={fmtCompact(total)} accent
          sub={`${MLC_DISTRIBUTIONS.length} distribution cycles`}/>
        <div style={{borderLeft:'1px solid var(--rule)'}}>
          <MlcKpi l="MARKET GROSS" v={fmtCompact(totalGross)} sub="MLC pool across same period"/>
        </div>
        <div style={{borderLeft:'1px solid var(--rule)'}}>
          <MlcKpi l="OUR SHARE" v={(total/totalGross*100).toFixed(2)+'%'} sub="of total MLC pool"/>
        </div>
        <div style={{borderLeft:'1px solid var(--rule)'}}>
          <MlcKpi l="BLACK-BOX POOL" v={fmtCompact(totalBB)} danger sub="industry-wide unmatched"/>
        </div>
      </div>

      {/* table */}
      <div style={{marginTop:24}}>
        <table style={{width:'100%',borderCollapse:'collapse',fontSize:12}}>
          <thead>
            <tr style={{borderBottom:'1px solid var(--rule)'}}>
              <th style={thStyle({left:true,w:130})}>Period</th>
              <th style={thStyle({left:true,w:120})}>Pay date</th>
              <th style={thStyle({right:true})}>Pool gross</th>
              <th style={thStyle({right:true})}>Pool matched</th>
              <th style={thStyle({right:true})}>Black-box</th>
              <th style={thStyle({right:true})}>Our cut</th>
              <th style={thStyle({left:true,w:200})}>Status</th>
              <th style={thStyle({w:140,right:true})}></th>
            </tr>
          </thead>
          <tbody>
            {MLC_DISTRIBUTIONS.map((d,i) => {
              const isBB = d.kind === 'blackbox-redistribution';
              return (
                <tr key={i} style={{borderBottom:'1px solid var(--rule-soft, var(--bg-2))'}}>
                  <td style={tdStyle()}>
                    <span className="ff-mono">{d.period}</span>
                    {isBB && <span className="ff-mono upper" style={{marginLeft:8,fontSize:9,letterSpacing:'.08em',padding:'1px 6px',background:'var(--bg-2)',color:'var(--ink-2)'}}>BB REDIST.</span>}
                  </td>
                  <td style={tdStyle({mono:true,muted:true})}>{d.payDate}</td>
                  <td style={tdStyle({mono:true,num:true,right:true,muted:true})}>{d.gross ? fmtCompact(d.gross) : '—'}</td>
                  <td style={tdStyle({mono:true,num:true,right:true,muted:true})}>{d.matched ? fmtCompact(d.matched) : '—'}</td>
                  <td style={tdStyle({mono:true,num:true,right:true})}>
                    {d.blackbox ? <span style={{color:'var(--ink-3)'}}>{fmtCompact(d.blackbox)}</span> : '—'}
                  </td>
                  <td style={tdStyle({mono:true,num:true,right:true})}>
                    <span style={{fontWeight:500}}>{fmt$(d.ourCut)}</span>
                  </td>
                  <td style={tdStyle()}>
                    {d.status === 'reconciled' ? (
                      <span style={{display:'inline-flex',alignItems:'center',gap:6,fontSize:11,color:'var(--ok)'}}>
                        <span style={{display:'inline-block',width:6,height:6,borderRadius:3,background:'var(--ok)'}}/>
                        Reconciled
                      </span>
                    ) : (
                      <span style={{display:'inline-flex',alignItems:'center',gap:6,fontSize:11,color:'var(--info)'}}>
                        <span style={{display:'inline-block',width:6,height:6,borderRadius:3,background:'var(--info)'}}/>
                        Partially reconciled
                      </span>
                    )}
                    {d.note && <div style={{fontSize:10,color:'var(--ink-3)',marginTop:2}}>{d.note}</div>}
                  </td>
                  <td style={tdStyle({right:true})}>
                    <button onClick={()=> go && go('royalties', { period: d.period, source:'MLC' })} className="ff-mono upper"
                      style={btnGhost}>OPEN STMT →</button>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>

      {/* explainer */}
      <div style={{marginTop:24,padding:16,background:'var(--bg-2)',border:'1px solid var(--rule)',fontSize:12,color:'var(--ink-2)',lineHeight:1.5}}>
        <div className="ff-mono upper" style={{fontSize:10,letterSpacing:'.1em',color:'var(--ink-3)',marginBottom:8}}>
          HOW THIS RECONCILES
        </div>
        Each MLC quarterly distribution arrives as a single payment with a line-level
        usage report. We post the gross to{' '}
        <button onClick={()=>go && go('royalties')} style={{textDecoration:'underline',color:'var(--ink)'}}>Royalties</button>{' '}
        as an inbound statement, run it through{' '}
        <button onClick={()=>go && go('reconciliation')} style={{textDecoration:'underline',color:'var(--ink)'}}>Reconciliation</button>{' '}
        to allocate per work, then push splits down through the active{' '}
        <button onClick={()=>go && go('agreements')} style={{textDecoration:'underline',color:'var(--ink)'}}>Agreement waterfalls</button>{' '}
        to writers and sub-publishers.
      </div>
    </div>
  );
}

// ─────────── 06 ACTIVITY
function MlcActivityTab() {
  const KIND_TONE = {
    match:    { fg:'var(--ok)',     l:'MATCH'     },
    register: { fg:'var(--info)',   l:'REGISTER'  },
    ack:      { fg:'var(--ok)',     l:'ACK'       },
    claim:    { fg:'var(--accent-ink, var(--ink))', l:'CLAIM' },
    distrib:  { fg:'var(--ink)',    l:'DISTRIB.'  },
    alert:    { fg:'var(--danger)', l:'ALERT'     },
  };
  return (
    <div style={{paddingTop:8,maxWidth:820}}>
      {MLC_ACTIVITY.map((a,i) => {
        const t = KIND_TONE[a.kind] || KIND_TONE.match;
        return (
          <div key={i} style={{display:'grid',gridTemplateColumns:'80px 90px 1fr',gap:14,padding:'12px 0',borderBottom:'1px solid var(--rule)',alignItems:'baseline'}}>
            <span className="ff-mono" style={{fontSize:11,color:'var(--ink-3)'}}>{a.time}</span>
            <span className="ff-mono upper" style={{fontSize:9,letterSpacing:'.1em',color:t.fg,border:'1px solid '+t.fg,padding:'2px 6px',justifySelf:'start'}}>
              {t.l}
            </span>
            <div style={{fontSize:13,lineHeight:1.5}}>
              <span style={{color:'var(--ink-3)'}}>{a.who}</span>{' '}
              <span>{a.what}</span>{' '}
              <span style={{fontWeight:500}}>{a.target}</span>
            </div>
          </div>
        );
      })}
    </div>
  );
}

// ─────────── MAIN SCREEN
function ScreenMlcSync({ go, payload }) {
  const [tab, setTab] = useMLS(payload?.tab || 'overview');
  const mlcWorks = useMLM(() => buildMlcWorks(), []);
  const mlcUsage = useMLM(() => buildMlcUsage(), []);

  const counts = useMLM(() => {
    const c = { matched:0, partial:0, unmatched:0, conflict:0, unregistered:0 };
    mlcWorks.forEach(w => { c[w.status] = (c[w.status]||0)+1; });
    return c;
  }, [mlcWorks]);

  const reviewCount = mlcUsage.filter(u => u.status === 'review' || u.status === 'low-confidence' || u.status === 'overlap').length;
  const conflictCount = counts.conflict + mlcUsage.filter(u => u.status==='overlap').length;

  const TABS = [
    { k:'overview',      l:'Overview' },
    { k:'registrations', l:'Registrations', n: mlcWorks.length },
    { k:'matches',       l:'Usage & matches', n: reviewCount, warn: reviewCount > 0 },
    { k:'claims',        l:'Claims & conflicts', n: conflictCount, warn: conflictCount > 0 },
    { k:'distributions', l:'Distributions',  n: MLC_DISTRIBUTIONS.length },
    { k:'activity',      l:'Activity' },
  ];

  return (
    <div>
      <PageHeader
        eyebrow={['REGISTRATIONS', 'MECHANICAL LICENSING COLLECTIVE', 'US BLANKET LICENSE']}
        title="MLC sync"
        highlight="MLC"
        sub="Every US streaming mechanical penny that lands in our account first passes through the MLC. This is the operational view of that pipeline — what we've registered, what's matched, what's leaking into the black-box pool, and what's reconciling against quarterly distributions."
        actions={
          <div style={{display:'flex',gap:8,alignItems:'center'}}>
            <span style={{display:'inline-flex',alignItems:'center',gap:6,fontSize:11,color:'var(--ink-2)'}}>
              <span style={{display:'inline-block',width:8,height:8,borderRadius:4,background:'var(--ok)'}}/>
              Live
            </span>
            <button className="ff-mono upper"
              style={{fontSize:10,letterSpacing:'.1em',padding:'10px 16px',background:'var(--ink)',color:'var(--bg)',border:0,cursor:'pointer',whiteSpace:'nowrap'}}>
              POLL MLC NOW ↻
            </button>
          </div>
        }
      />

      {/* Tab strip */}
      <div style={{borderBottom:'1px solid var(--rule)',display:'flex',gap:0}}>
        {TABS.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,
            display:'flex',alignItems:'baseline',gap:8
          }}>
            {t.l}
            {t.n != null && (
              <span className="ff-mono num" style={{fontSize:10, color: t.warn ? 'var(--danger)' : 'var(--ink-3)'}}>{t.n}</span>
            )}
          </button>
        ))}
      </div>

      {/* Body */}
      <div style={{paddingTop:8}}>
        {tab === 'overview'      && <MlcOverviewTab mlcWorks={mlcWorks} mlcUsage={mlcUsage} go={go} setTab={setTab}/>}
        {tab === 'registrations' && <MlcRegistrationsTab mlcWorks={mlcWorks} go={go}/>}
        {tab === 'matches'       && <MlcMatchesTab mlcUsage={mlcUsage} mlcWorks={mlcWorks}/>}
        {tab === 'claims'        && <MlcClaimsTab mlcWorks={mlcWorks} mlcUsage={mlcUsage}/>}
        {tab === 'distributions' && <MlcDistributionsTab go={go}/>}
        {tab === 'activity'      && <MlcActivityTab/>}
      </div>
    </div>
  );
}

// Expose
Object.assign(window, { ScreenMlcSync });
