// ───────────────────────────────────────────────────────────── COPYRIGHT
// Top-level "Copyright Registrations" — track filings with national copyright
// offices (US, EU, UK, JP, etc.). Distinct from PRO/CMO registrations (CWR).
//
// Data model: astro.copyright_registrations (92 cols) — registration_number,
// jurisdiction, status, claimant, copyright_type, title, dates, filing fee,
// certificate URL, ISN value, plus excluded/included material flags and
// representative + correspondence + mailing-correspondent contact blocks.
//
// US-specific block (astro.copyright_registrations_us, 27 cols) is exposed in
// the drawer when jurisdiction = US.

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

// ─────────────────────────── seeded RNG
function seed(s){let h=2166136261;for(let i=0;i<s.length;i++){h^=s.charCodeAt(i);h=Math.imul(h,16777619);}return ()=>((h=Math.imul(h^(h>>>13),3432918353))>>>0)/4294967296;}
function fmt$(n,c){ const cur = c || 'USD'; if(n>=1e6) return (cur==='USD'?'$':'')+ (n/1e6).toFixed(1)+'M'; if(n>=1e3) return (cur==='USD'?'$':'') + (n/1e3).toFixed(1)+'k'; return (cur==='USD'?'$':'') + n.toFixed(2); }
function daysAgo(d){ const t = new Date(); t.setDate(t.getDate()-d); return t.toISOString().slice(0,10); }
function daysFromNow(d){ const t = new Date(); t.setDate(t.getDate()+d); return t.toISOString().slice(0,10); }
function yyyymmdd(d){ return d ? d.slice(0,10) : '—'; }

// ─────────────────────────── taxonomy
// Status — drives UI colour and the active workflow stage
const STATUS = {
  draft:        { label:'DRAFT',         color:'var(--ink-3)', desc:'Not submitted' },
  submitted:    { label:'SUBMITTED',     color:'#7a6e2d',      desc:'Awaiting examination' },
  in_examination: { label:'EXAMINING',   color:'#7a6e2d',      desc:'Under examiner review' },
  correspondence: { label:'CORRESPONDENCE', color:'#c79538',   desc:'Office requested clarification' },
  registered:   { label:'REGISTERED',    color:'#3a6a3a',      desc:'Certificate issued' },
  rejected:     { label:'REJECTED',      color:'#a04432',      desc:'Refused — review correspondence' },
  withdrawn:    { label:'WITHDRAWN',     color:'var(--ink-3)', desc:'Voluntarily withdrawn' },
};

// Copyright type — corresponds to USCO record types and equivalents
const COPYRIGHT_TYPE = {
  PA:   { label:'Performing Arts',     desc:'Music, lyrics, screenplays, choreography' },
  SR:   { label:'Sound Recording',     desc:'Master recording (separate from underlying composition)' },
  TX:   { label:'Literary Work',       desc:'Lyrics-only, books, articles' },
  VA:   { label:'Visual Arts',         desc:'Cover art, photography' },
  SE:   { label:'Serial',              desc:'Periodical, journal' },
};

// Jurisdictions (per ref.copyright_jurisdictions)
const JURISDICTIONS = [
  { code:'US', name:'United States',    office:'U.S. Copyright Office',    fee:65,  cur:'USD' },
  { code:'GB', name:'United Kingdom',   office:'UK IPO',                   fee:0,   cur:'GBP' },
  { code:'DE', name:'Germany',          office:'DPMA',                     fee:30,  cur:'EUR' },
  { code:'FR', name:'France',           office:'INPI',                     fee:38,  cur:'EUR' },
  { code:'JP', name:'Japan',            office:'Agency for Cultural Affairs', fee:3000, cur:'JPY' },
  { code:'CA', name:'Canada',           office:'CIPO',                     fee:50,  cur:'CAD' },
  { code:'AU', name:'Australia',        office:'IP Australia',             fee:0,   cur:'AUD' },
  { code:'BR', name:'Brazil',           office:'Biblioteca Nacional',      fee:80,  cur:'BRL' },
  { code:'IN', name:'India',            office:'Copyright Office, India',  fee:500, cur:'INR' },
  { code:'KR', name:'South Korea',      office:'KCC',                      fee:23000, cur:'KRW' },
  { code:'MX', name:'Mexico',           office:'INDAUTOR',                 fee:204, cur:'MXN' },
  { code:'EU', name:'European Union',   office:'EUIPO',                    fee:30,  cur:'EUR' },
];
const JUR_BY_CODE = Object.fromEntries(JURISDICTIONS.map(j => [j.code, j]));

// ISN types — International Standard Number for content
const ISN_TYPES = ['ISWC','ISRC','ISBN','ISMN','ISAN'];

// Office service numbers (US uses eService, etc.)
const OFFICE_NOTES = {
  US: ['eCO Service','eCO Special Handling','Group Registration'],
  GB: ['Standard application'],
  DE: ['Standardanmeldung'],
  FR: ['Dépôt SACEM','Dépôt INPI'],
  JP: ['通常申請'],
};

// ─────────────────────────── data
function buildRegistrations() {
  const r = seed('copyright_v1');
  const works = (typeof window.ALL_WORKS !== 'undefined') ? window.ALL_WORKS : [];
  const recs = [];
  if (typeof window.RECORDING_GRAPH !== 'undefined') {
    Object.values(window.RECORDING_GRAPH).forEach(rg => {
      (rg.recordings || []).forEach(rec => recs.push(rec));
    });
  }

  const out = [];
  // Aim for ~70 registrations
  for (let i = 0; i < 70; i++) {
    // Decide work-or-recording subject
    const isWork = r() < 0.55;
    const work = works.length ? works[Math.floor(r()*works.length)] : null;
    const rec = recs.length ? recs[Math.floor(r()*recs.length)] : null;
    if (isWork && !work) continue;
    if (!isWork && !rec) continue;

    const title = (isWork ? work.title : rec.title) || `Untitled ${i+1}`;
    const subjectIsrc = !isWork ? (rec.isrc || null) : null;
    const subjectIswc = isWork ? (work.iswc || null) : null;
    const writers = (work && work.writers) || [];
    const artist = (rec && rec.artist) || (work && work.parties && work.parties[0]) || 'Unknown';

    // Type — recordings get SR, works mostly PA, some TX (lyrics-only)
    const type = isWork ? (r() < 0.85 ? 'PA' : 'TX') : 'SR';

    // Jurisdiction — heavily weighted to US
    const j = r() < 0.55 ? JURISDICTIONS[0] : JURISDICTIONS[Math.floor(r()*JURISDICTIONS.length)];

    // Status weighting — most are registered, some pending, a few problem
    const sRoll = r();
    const status = sRoll < 0.55 ? 'registered'
      : sRoll < 0.70 ? 'submitted'
      : sRoll < 0.80 ? 'in_examination'
      : sRoll < 0.86 ? 'correspondence'
      : sRoll < 0.91 ? 'draft'
      : sRoll < 0.96 ? 'rejected'
      : 'withdrawn';

    // Dates depending on status
    const ageDays = Math.floor(r() * 1200) + 30;
    const submittedAt = (status !== 'draft') ? daysAgo(ageDays) : null;
    const registeredAt = (status === 'registered') ? daysAgo(Math.max(ageDays - Math.floor(r()*180+90), 30)) : null;
    const yearOfCompletion = 2014 + Math.floor(r()*11);
    const dateOfFirstPublication = daysAgo(Math.floor(r()*1000)+200);

    // Registration number — format depends on jurisdiction
    let regNum = null;
    if (status === 'registered' || status === 'correspondence' || status === 'in_examination') {
      if (j.code === 'US') {
        const prefix = type === 'PA' ? 'PA' : type === 'SR' ? 'SR' : type === 'TX' ? 'TX' : 'VA';
        regNum = `${prefix}u${String(Math.floor(r()*9999999)).padStart(7,'0')}`;
      } else if (j.code === 'GB') {
        regNum = `GB-${2020 + Math.floor(r()*6)}-${String(Math.floor(r()*999999)).padStart(6,'0')}`;
      } else if (j.code === 'DE') {
        regNum = `DPMA-${String(Math.floor(r()*99999999)).padStart(8,'0')}`;
      } else if (j.code === 'JP') {
        regNum = `JP-第${String(Math.floor(r()*9999999)).padStart(7,'0')}号`;
      } else {
        regNum = `${j.code}${String(Math.floor(r()*9999999)).padStart(7,'0')}`;
      }
    }

    // ECO service number (US)
    const ecoNum = (j.code === 'US' && submittedAt) ? `1-${String(Math.floor(r()*9999999999)).padStart(10,'0')}` : null;

    // Filing fee
    const fee = j.fee + (status === 'registered' && r() < 0.2 ? 100 : 0); // surcharges for special handling
    const filingFeeAmount = (status !== 'draft' && status !== 'withdrawn') ? fee : null;

    // Excluded / included material — recordings often exclude composition, works often exclude prior version
    const excluded = {
      sound_recording: !isWork ? false : r() < 0.15,
      lyrics:          isWork && type === 'PA' ? r() < 0.10 : false,
      music:           isWork && type === 'TX' ? true : false,  // lyrics-only excludes music
      musical_arrangement: r() < 0.07,
      text:            !isWork && r() < 0.10,
      other:           r() < 0.05 ? 'Sample of [redacted] used under existing license' : null,
    };
    const included = {
      sound_recording: !isWork,
      lyrics:          isWork && type !== 'TX' ? true : (type === 'TX'),
      music:           isWork && type === 'PA' ? true : false,
      musical_arrangement: isWork && type === 'PA' ? true : false,
      text:            type === 'TX',
      other:           null,
    };

    // Previous registrations — sometimes a song was registered before in unpublished form
    const hasPrev = r() < 0.18;
    const prev1 = hasPrev ? { number:`Pau${String(Math.floor(r()*999999)).padStart(6,'0')}`, year: yearOfCompletion - Math.floor(r()*3+1) } : null;

    // Claimant — typically the artist's publishing or label entity
    const claimant = isWork
      ? (writers[0]?.name || artist) + ' Publishing'
      : artist + ' Records';

    // Reps/correspondents (USCO requires)
    const repFirst = ['Avery','Casey','Devon','Eden','Florence','Greer','Harper','Imani','Juno','Kit'][Math.floor(r()*10)];
    const repLast  = ['Adair','Bellamy','Cordova','Daugherty','Elmore','Foley','Glasser','Hartley','Imhof','Jasper'][Math.floor(r()*10)];
    const repOrg   = ['Kobalt','Concord','Downtown','Reservoir','Anthem','Primary Wave','BMG','Warner Chappell'][Math.floor(r()*8)];

    // Certificate
    const hasCert = status === 'registered' && r() < 0.92;

    // ISN type/value
    const isnType = isWork ? 'ISWC' : 'ISRC';
    const isnValue = isWork ? subjectIswc : subjectIsrc;

    // Title type
    const titleType = type === 'TX' ? 'LYRICS' : 'MAIN';

    out.push({
      id: `cr_${String(i+1).padStart(4,'0')}`,
      custom_id: `CR-${(20260000 + i).toString()}`,
      registration_number: regNum,
      eco_service_number: ecoNum,
      copyright_type: type,
      title,
      title_type: titleType,
      status,
      jurisdiction: j,

      work_id: isWork ? work?.id : null,
      recording_id: !isWork ? rec?.id : null,
      subject_kind: isWork ? 'work' : 'recording',
      subject_label: title,
      subject_secondary: artist,
      subject_writers: writers.slice(0, 4),

      claimant_name: claimant,

      copyright_date: registeredAt || submittedAt,
      year_of_completion: yearOfCompletion,
      is_published: r() < 0.85,
      date_of_first_publication: dateOfFirstPublication,
      country_of_publication: j.code,

      isn_type: isnType,
      isn_value: isnValue,
      isn_date: isnValue ? daysAgo(Math.floor(r()*900)+200) : null,

      excluded, included,

      prev_reg: prev1 ? [prev1] : [],

      // Representative
      rep: {
        first: repFirst, last: repLast, organization: repOrg,
        email: `${repFirst.toLowerCase()}.${repLast.toLowerCase()}@${repOrg.toLowerCase().replace(/\s/g,'')}.com`,
        phone: `+1-${Math.floor(200+r()*700)}-${Math.floor(100+r()*900)}-${Math.floor(1000+r()*9000)}`,
        address: `${Math.floor(100+r()*9900)} ${['Fifth','Sunset','Wilshire','Madison','Park'][Math.floor(r()*5)]} Ave`,
        city: ['New York','Los Angeles','Nashville','Chicago','London'][Math.floor(r()*5)],
        state: ['NY','CA','TN','IL','—'][Math.floor(r()*5)],
        postal: String(10000 + Math.floor(r()*89999)),
        country: 'US',
      },

      submitted_at: submittedAt,
      registered_at: registeredAt,
      filing_fee_amount: filingFeeAmount,
      filing_fee_currency: j.cur,
      local_registration_number: regNum,

      certificate_url: hasCert ? `r2://copyright/${regNum}.pdf` : null,
      certificate_file_name: hasCert ? `${regNum}.pdf` : null,
      certificate_uploaded_at: hasCert ? daysAgo(Math.floor(r()*60)) : null,

      created_at: daysAgo(ageDays),
      updated_at: daysAgo(Math.floor(r()*30)),
    });
  }
  return out;
}

// ─────────────────────────── small components
function Stat({ label, value, sub, accent, last }) {
  return (
    <div style={{padding:'18px 22px',borderRight: last ? 'none' : '1px solid var(--rule)',flex:1,minWidth:0}}>
      <div className="ff-mono upper" style={{fontSize:9,letterSpacing:'.12em',color:'var(--ink-3)',marginBottom:8}}>{label}</div>
      <div className="ff-display" style={{fontSize:28,fontWeight:600,letterSpacing:'-0.02em',lineHeight:1,color:accent||'var(--ink)'}}>{value}</div>
      <div style={{fontSize:11,color:'var(--ink-3)',marginTop:6,letterSpacing:'-0.005em'}}>{sub}</div>
    </div>
  );
}

// ─────────────────────────── jurisdiction distribution
function JurisdictionDistribution({ items }) {
  const buckets = JURISDICTIONS.map(j => ({ j, items: items.filter(i => i.jurisdiction.code === j.code) }))
    .filter(b => b.items.length > 0)
    .sort((a,b) => b.items.length - a.items.length)
    .slice(0, 8);
  const max = Math.max(...buckets.map(b => b.items.length), 1);
  return (
    <div style={{border:'1px solid var(--rule)',marginBottom:24}}>
      <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',padding:'10px 14px',
        borderBottom:'1px solid var(--rule)',background:'var(--bg-2)'}}>
        <span className="ff-mono upper" style={{fontSize:10,letterSpacing:'.12em',color:'var(--ink-3)'}}>
          BY JURISDICTION
        </span>
        <span className="ff-mono" style={{fontSize:10,color:'var(--ink-3)',letterSpacing:'.04em'}}>
          {items.length} total filings · {buckets.length} jurisdictions
        </span>
      </div>
      <div style={{padding:'14px 18px',display:'grid',gridTemplateColumns:'repeat(4, 1fr)',gap:'12px 32px'}}>
        {buckets.map(b => {
          const reg = b.items.filter(i => i.status === 'registered').length;
          const w = (b.items.length / max) * 100;
          return (
            <div key={b.j.code}>
              <div style={{display:'flex',justifyContent:'space-between',alignItems:'baseline',marginBottom:4}}>
                <span style={{fontSize:12,color:'var(--ink-2)'}}>
                  <span className="ff-mono" style={{fontSize:10,color:'var(--ink-3)',marginRight:6,letterSpacing:'.06em'}}>{b.j.code}</span>
                  {b.j.name}
                </span>
                <span className="ff-mono num" style={{fontSize:11,color:'var(--ink-3)'}}>{b.items.length}</span>
              </div>
              <div style={{height:4,background:'var(--rule-soft)',position:'relative'}}>
                <div style={{position:'absolute',inset:0,width:w+'%',background:'var(--ink-2)'}}/>
                <div style={{position:'absolute',top:0,left:0,bottom:0,width:((reg/Math.max(b.items.length,1))*w)+'%',background:'#3a6a3a'}}/>
              </div>
              <div style={{fontSize:10,color:'var(--ink-3)',marginTop:3,letterSpacing:'.02em'}}>
                <span style={{color:'#3a6a3a'}}>{reg}</span> registered · {b.items.length - reg} pending
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ─────────────────────────── filter bar
function FilterBar({ filters, setFilters, counts }) {
  const tabs = [
    { k:'all',         l:'All',           n:counts.total || 0 },
    { k:'registered',  l:'Registered',    n:counts.byStatus.registered || 0 },
    { k:'submitted',   l:'Submitted',     n:counts.byStatus.submitted || 0 },
    { k:'in_examination', l:'Examining',  n:counts.byStatus.in_examination || 0 },
    { k:'correspondence', l:'Correspondence', n:counts.byStatus.correspondence || 0 },
    { k:'draft',       l:'Draft',         n:counts.byStatus.draft || 0 },
    { k:'rejected',    l:'Rejected',      n:counts.byStatus.rejected || 0 },
  ];
  return (
    <div style={{border:'1px solid var(--rule)',marginBottom:24,background:'var(--bg)'}}>
      <div style={{display:'flex',borderBottom:'1px solid var(--rule)',overflowX:'auto'}}>
        {tabs.map(t => (
          <button key={t.k} onClick={()=>setFilters({...filters, status:t.k})}
            className="ff-mono upper"
            style={{padding:'12px 16px',background: filters.status === t.k ? 'var(--bg-2)' : 'transparent',
              border:0,borderRight:'1px solid var(--rule)',color: filters.status === t.k ? 'var(--ink)' : 'var(--ink-3)',
              fontSize:11,letterSpacing:'.08em',cursor:'pointer',fontWeight: filters.status === t.k ? 600 : 400,whiteSpace:'nowrap'}}>
            {t.l} <span style={{opacity:.6,marginLeft:6,fontSize:10}}>{t.n}</span>
          </button>
        ))}
      </div>
      <div style={{display:'flex',padding:'10px 14px',gap:14,alignItems:'center',flexWrap:'wrap'}}>
        <span className="ff-mono upper" style={{fontSize:9,color:'var(--ink-3)',letterSpacing:'.1em'}}>FILTER</span>
        <select value={filters.jurisdiction} onChange={e=>setFilters({...filters, jurisdiction:e.target.value})}
          className="ff-mono" style={{fontSize:11,padding:'6px 10px',background:'var(--bg)',border:'1px solid var(--rule)',color:'var(--ink)'}}>
          <option value="all">All jurisdictions</option>
          {JURISDICTIONS.map(j => <option key={j.code} value={j.code}>{j.code} — {j.name}</option>)}
        </select>
        <select value={filters.type} onChange={e=>setFilters({...filters, type:e.target.value})}
          className="ff-mono" style={{fontSize:11,padding:'6px 10px',background:'var(--bg)',border:'1px solid var(--rule)',color:'var(--ink)'}}>
          <option value="all">All types</option>
          {Object.entries(COPYRIGHT_TYPE).map(([k,v]) => <option key={k} value={k}>{k} — {v.label}</option>)}
        </select>
        <select value={filters.subject} onChange={e=>setFilters({...filters, subject:e.target.value})}
          className="ff-mono" style={{fontSize:11,padding:'6px 10px',background:'var(--bg)',border:'1px solid var(--rule)',color:'var(--ink)'}}>
          <option value="all">Works + recordings</option>
          <option value="work">Works only</option>
          <option value="recording">Recordings only</option>
        </select>
        <input value={filters.q} onChange={e=>setFilters({...filters, q:e.target.value})}
          placeholder="Search title, registration #, claimant…"
          className="ff-mono" style={{flex:1,minWidth:240,fontSize:11,padding:'6px 10px',background:'var(--bg)',border:'1px solid var(--rule)',color:'var(--ink)'}}/>
        <span className="ff-mono" style={{fontSize:11,color:'var(--ink-3)',letterSpacing:'.04em',marginLeft:'auto'}}>
          {counts.total} matching
        </span>
      </div>
    </div>
  );
}

// ─────────────────────────── registration row
function RegRow({ reg, onOpen, isLast }) {
  const s = STATUS[reg.status];
  const t = COPYRIGHT_TYPE[reg.copyright_type];
  return (
    <div onClick={onOpen}
      style={{display:'grid',gridTemplateColumns:'130px 60px 1.6fr 1.2fr 130px 130px 90px',gap:0,
        padding:'12px 14px',borderBottom: isLast ? 'none' : '1px solid var(--rule-soft)',cursor:'pointer',
        alignItems:'center'}}
      onMouseEnter={e=>e.currentTarget.style.background='var(--bg-2)'}
      onMouseLeave={e=>e.currentTarget.style.background='transparent'}>
      {/* Reg # */}
      <div className="ff-mono num" style={{fontSize:11,color:reg.registration_number ? 'var(--ink)' : 'var(--ink-3)',
        overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap',paddingRight:8}}>
        {reg.registration_number || '—'}
      </div>
      {/* Type */}
      <div className="ff-mono upper" style={{fontSize:10,letterSpacing:'.08em',color:'var(--ink-2)'}}>
        {reg.copyright_type}
      </div>
      {/* Title */}
      <div style={{paddingRight:12,minWidth:0}}>
        <div style={{fontSize:13,letterSpacing:'-0.005em',color:'var(--ink)',lineHeight:1.3,
          overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{reg.title}</div>
        <div style={{fontSize:11,color:'var(--ink-3)',marginTop:2,lineHeight:1.3,
          overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>
          {reg.subject_kind === 'work' ? 'WORK · ' : 'REC · '}
          {reg.subject_secondary}
          {reg.isn_value && <span> · <span className="ff-mono">{reg.isn_value}</span></span>}
        </div>
      </div>
      {/* Claimant */}
      <div style={{paddingRight:12,minWidth:0}}>
        <div style={{fontSize:12,color:'var(--ink-2)',lineHeight:1.3,
          overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{reg.claimant_name}</div>
      </div>
      {/* Jurisdiction */}
      <div style={{minWidth:0}}>
        <div className="ff-mono upper" style={{fontSize:10,letterSpacing:'.08em',color:'var(--ink-2)'}}>{reg.jurisdiction.code}</div>
        <div style={{fontSize:11,color:'var(--ink-3)',marginTop:2,
          overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{reg.jurisdiction.office}</div>
      </div>
      {/* Date */}
      <div className="ff-mono num" style={{fontSize:11,color:'var(--ink)',paddingRight:8}}>
        {reg.registered_at || reg.submitted_at || reg.created_at}
        <div style={{fontSize:10,color:'var(--ink-3)',marginTop:2}}>
          {reg.registered_at ? 'registered' : reg.submitted_at ? 'submitted' : 'created'}
        </div>
      </div>
      {/* Status */}
      <div style={{textAlign:'right'}}>
        <span className="ff-mono upper" style={{display:'inline-block',padding:'2px 7px',fontSize:9,letterSpacing:'.08em',
          color:'var(--bg)',background:s.color,fontWeight:600}}>
          {s.label}
        </span>
      </div>
    </div>
  );
}

// ─────────────────────────── drawer
function RegDrawer({ reg, onClose, go }) {
  const s = STATUS[reg.status];
  const t = COPYRIGHT_TYPE[reg.copyright_type];

  // Compose rights breakdown — what's claimed vs excluded
  const incList = [
    reg.included.sound_recording && 'Sound recording',
    reg.included.music && 'Music',
    reg.included.lyrics && 'Lyrics',
    reg.included.musical_arrangement && 'Musical arrangement',
    reg.included.text && 'Text',
  ].filter(Boolean);
  const excList = [
    reg.excluded.sound_recording && 'Sound recording',
    reg.excluded.music && 'Music',
    reg.excluded.lyrics && 'Lyrics',
    reg.excluded.musical_arrangement && 'Musical arrangement',
    reg.excluded.text && 'Text',
    reg.excluded.other && reg.excluded.other,
  ].filter(Boolean);

  return (
    <>
      <div onClick={onClose} style={{position:'fixed',inset:0,background:'rgba(20,20,20,.45)',zIndex:80}}/>
      <aside style={{position:'fixed',top:0,right:0,bottom:0,width:600,background:'var(--bg)',
        borderLeft:'1px solid var(--rule)',zIndex:81,overflowY:'auto',display:'flex',flexDirection:'column'}}>
        {/* Header */}
        <div style={{padding:'18px 22px',borderBottom:'1px solid var(--rule)',display:'flex',justifyContent:'space-between',alignItems:'flex-start',gap:14}}>
          <div style={{flex:1,minWidth:0}}>
            <div style={{display:'flex',alignItems:'center',gap:8,marginBottom:10,flexWrap:'wrap'}}>
              <span className="ff-mono upper" style={{padding:'2px 7px',fontSize:9,letterSpacing:'.08em',color:'var(--bg)',background:s.color,fontWeight:600}}>
                {s.label}
              </span>
              <span className="ff-mono upper" style={{fontSize:10,letterSpacing:'.08em',color:'var(--ink-2)'}}>
                {reg.copyright_type} · {t.label}
              </span>
              <span className="ff-mono" style={{fontSize:10,color:'var(--ink-3)',letterSpacing:'.04em'}}>
                · {reg.custom_id}
              </span>
            </div>
            <h2 className="ff-display" style={{fontSize:22,fontWeight:600,letterSpacing:'-0.02em',lineHeight:1.15,margin:0}}>
              {reg.title}
            </h2>
            <div style={{fontSize:12,color:'var(--ink-2)',marginTop:6}}>{reg.subject_secondary}</div>
            {reg.registration_number && (
              <div className="ff-mono num" style={{fontSize:11,color:'var(--ink-2)',marginTop:8,letterSpacing:'.02em'}}>
                {reg.registration_number}
              </div>
            )}
          </div>
          <button onClick={onClose} className="ff-mono"
            style={{background:'none',border:0,fontSize:22,color:'var(--ink-3)',cursor:'pointer',padding:0,lineHeight:1,marginLeft:8}}>×</button>
        </div>

        <div style={{flex:1,overflowY:'auto'}}>

          {/* Status panel */}
          <div style={{padding:'16px 22px',borderBottom:'1px solid var(--rule)'}}>
            <div className="ff-mono upper" style={{fontSize:9,letterSpacing:'.12em',color:'var(--ink-3)',marginBottom:8}}>STATUS</div>
            <div style={{fontSize:13,color:'var(--ink)',lineHeight:1.5}}>{s.desc}</div>
            {reg.status === 'correspondence' && (
              <div style={{marginTop:10,padding:'10px 12px',background:'#c79538',color:'var(--bg)',fontSize:12,letterSpacing:'-0.005em',lineHeight:1.4}}>
                Office requested clarification on claim of musical arrangement.
                Response due in <strong>14 days</strong>.
              </div>
            )}
            {reg.status === 'rejected' && (
              <div style={{marginTop:10,padding:'10px 12px',background:'#a04432',color:'var(--bg)',fontSize:12,letterSpacing:'-0.005em',lineHeight:1.4}}>
                Refused — preexisting registration covers same claim. Review correspondence and consider supplementary registration.
              </div>
            )}
          </div>

          {/* Jurisdiction + ID block */}
          <div style={{padding:'16px 22px',borderBottom:'1px solid var(--rule)'}}>
            <div className="ff-mono upper" style={{fontSize:9,letterSpacing:'.12em',color:'var(--ink-3)',marginBottom:12}}>JURISDICTION & FILING</div>
            <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:'12px 24px'}}>
              <KV label="JURISDICTION"          value={`${reg.jurisdiction.code} · ${reg.jurisdiction.name}`}/>
              <KV label="OFFICE"                value={reg.jurisdiction.office}/>
              <KV label="REGISTRATION #"        value={reg.registration_number || '—'} mono/>
              <KV label="ECO SERVICE #"         value={reg.eco_service_number || '—'} mono/>
              <KV label="LOCAL REGISTRATION #"  value={reg.local_registration_number || '—'} mono/>
              <KV label="FILING FEE"            value={reg.filing_fee_amount != null ? `${reg.filing_fee_amount.toFixed(2)} ${reg.filing_fee_currency}` : '—'} mono/>
            </div>
          </div>

          {/* Subject linkage */}
          <div style={{padding:'16px 22px',borderBottom:'1px solid var(--rule)'}}>
            <div className="ff-mono upper" style={{fontSize:9,letterSpacing:'.12em',color:'var(--ink-3)',marginBottom:12}}>SUBJECT</div>
            <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:'12px 24px'}}>
              <KV label={reg.subject_kind === 'work' ? 'WORK ID' : 'RECORDING ID'} value={reg.subject_kind === 'work' ? reg.work_id : reg.recording_id} mono/>
              <KV label="TITLE TYPE"            value={reg.title_type} mono/>
              <KV label={reg.isn_type}          value={reg.isn_value || '—'} mono/>
              <KV label={`${reg.isn_type} DATE`} value={yyyymmdd(reg.isn_date)} mono/>
              <KV label="YEAR OF COMPLETION"    value={String(reg.year_of_completion)} mono/>
              <KV label="PUBLISHED"             value={reg.is_published ? 'Yes' : 'No'} mono/>
              <KV label="FIRST PUBLICATION"     value={yyyymmdd(reg.date_of_first_publication)} mono/>
              <KV label="COUNTRY OF PUBLICATION" value={reg.country_of_publication} mono/>
            </div>
          </div>

          {/* Claim breakdown */}
          <div style={{padding:'16px 22px',borderBottom:'1px solid var(--rule)'}}>
            <div className="ff-mono upper" style={{fontSize:9,letterSpacing:'.12em',color:'var(--ink-3)',marginBottom:12}}>CLAIM BREAKDOWN</div>
            <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:'12px 24px'}}>
              <div>
                <div className="ff-mono upper" style={{fontSize:9,letterSpacing:'.1em',color:'#3a6a3a',marginBottom:6}}>INCLUDED</div>
                {incList.length === 0 && <div style={{fontSize:12,color:'var(--ink-3)'}}>—</div>}
                {incList.map(x => (
                  <div key={x} style={{fontSize:12,color:'var(--ink)',padding:'2px 0',display:'flex',alignItems:'center',gap:6}}>
                    <span style={{display:'inline-block',width:10,height:2,background:'#3a6a3a'}}/>
                    {x}
                  </div>
                ))}
              </div>
              <div>
                <div className="ff-mono upper" style={{fontSize:9,letterSpacing:'.1em',color:'#a04432',marginBottom:6}}>EXCLUDED</div>
                {excList.length === 0 && <div style={{fontSize:12,color:'var(--ink-3)'}}>—</div>}
                {excList.map(x => (
                  <div key={x} style={{fontSize:12,color:'var(--ink-2)',padding:'2px 0',display:'flex',alignItems:'flex-start',gap:6,lineHeight:1.4}}>
                    <span style={{display:'inline-block',width:10,height:2,background:'#a04432',flexShrink:0,marginTop:7}}/>
                    {x}
                  </div>
                ))}
              </div>
            </div>
          </div>

          {/* Previous registrations */}
          {reg.prev_reg.length > 0 && (
            <div style={{padding:'16px 22px',borderBottom:'1px solid var(--rule)'}}>
              <div className="ff-mono upper" style={{fontSize:9,letterSpacing:'.12em',color:'var(--ink-3)',marginBottom:12}}>PREVIOUS REGISTRATIONS</div>
              {reg.prev_reg.map((p,i) => (
                <div key={i} style={{display:'flex',justifyContent:'space-between',padding:'4px 0'}}>
                  <span className="ff-mono num" style={{fontSize:12,color:'var(--ink)'}}>{p.number}</span>
                  <span className="ff-mono num" style={{fontSize:12,color:'var(--ink-3)'}}>{p.year}</span>
                </div>
              ))}
            </div>
          )}

          {/* Claimant + Rep */}
          <div style={{padding:'16px 22px',borderBottom:'1px solid var(--rule)'}}>
            <div className="ff-mono upper" style={{fontSize:9,letterSpacing:'.12em',color:'var(--ink-3)',marginBottom:12}}>CLAIMANT & REPRESENTATIVE</div>
            <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:'12px 24px'}}>
              <KV label="CLAIMANT" value={reg.claimant_name}/>
              <KV label="REP" value={`${reg.rep.first} ${reg.rep.last}`}/>
              <KV label="REP ORG" value={reg.rep.organization}/>
              <KV label="REP EMAIL" value={reg.rep.email} mono small/>
              <KV label="REP PHONE" value={reg.rep.phone} mono/>
              <KV label="REP ADDRESS" value={`${reg.rep.address}, ${reg.rep.city}, ${reg.rep.state} ${reg.rep.postal}`}/>
            </div>
          </div>

          {/* Timeline */}
          <div style={{padding:'16px 22px',borderBottom:'1px solid var(--rule)'}}>
            <div className="ff-mono upper" style={{fontSize:9,letterSpacing:'.12em',color:'var(--ink-3)',marginBottom:12}}>TIMELINE</div>
            <Timeline reg={reg}/>
          </div>

          {/* Certificate */}
          {reg.certificate_url && (
            <div style={{padding:'16px 22px',borderBottom:'1px solid var(--rule)'}}>
              <div className="ff-mono upper" style={{fontSize:9,letterSpacing:'.12em',color:'var(--ink-3)',marginBottom:12}}>CERTIFICATE</div>
              <div style={{display:'flex',alignItems:'center',gap:12,padding:'10px 12px',border:'1px solid var(--rule)',background:'var(--bg-2)'}}>
                <div style={{width:32,height:40,background:'var(--ink-3)',color:'var(--bg)',display:'flex',alignItems:'center',justifyContent:'center',
                  fontSize:9,fontWeight:700,letterSpacing:'.08em'}}>PDF</div>
                <div style={{flex:1,minWidth:0}}>
                  <div className="ff-mono" style={{fontSize:11,color:'var(--ink)',overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>
                    {reg.certificate_file_name}
                  </div>
                  <div style={{fontSize:10,color:'var(--ink-3)',marginTop:2}}>
                    uploaded {reg.certificate_uploaded_at}
                  </div>
                </div>
                <button className="ff-mono upper"
                  style={{padding:'6px 12px',background:'var(--ink)',color:'var(--bg)',border:0,fontSize:10,letterSpacing:'.08em',cursor:'pointer'}}>
                  DOWNLOAD
                </button>
              </div>
            </div>
          )}

        </div>

        {/* Actions */}
        <div style={{padding:'14px 22px',borderTop:'1px solid var(--rule)',display:'flex',gap:8,flexWrap:'wrap'}}>
          {reg.status === 'draft' && (
            <button className="ff-mono upper"
              style={{padding:'9px 14px',background:'var(--ink)',color:'var(--bg)',border:0,fontSize:11,letterSpacing:'.08em',cursor:'pointer'}}>
              SUBMIT
            </button>
          )}
          {reg.status === 'correspondence' && (
            <button className="ff-mono upper"
              style={{padding:'9px 14px',background:'#c79538',color:'var(--bg)',border:0,fontSize:11,letterSpacing:'.08em',cursor:'pointer'}}>
              RESPOND TO OFFICE
            </button>
          )}
          {reg.status === 'rejected' && (
            <button className="ff-mono upper"
              style={{padding:'9px 14px',background:'var(--ink)',color:'var(--bg)',border:0,fontSize:11,letterSpacing:'.08em',cursor:'pointer'}}>
              FILE SUPPLEMENTARY
            </button>
          )}
          <button className="ff-mono upper"
            style={{padding:'9px 14px',background:'transparent',color:'var(--ink-2)',border:'1px solid var(--rule)',fontSize:11,letterSpacing:'.08em',cursor:'pointer'}}>
            EDIT
          </button>
          <button className="ff-mono upper"
            style={{padding:'9px 14px',background:'transparent',color:'var(--ink-3)',border:'1px solid var(--rule)',fontSize:11,letterSpacing:'.08em',cursor:'pointer',marginLeft:'auto'}}>
            VIEW AUDIT LOG
          </button>
        </div>
      </aside>
    </>
  );
}

function KV({ label, value, mono, small }) {
  return (
    <div>
      <div className="ff-mono upper" style={{fontSize:9,letterSpacing:'.1em',color:'var(--ink-3)',marginBottom:3}}>{label}</div>
      <div className={mono ? 'ff-mono num' : ''} style={{fontSize: small ? 11 : 12,color:'var(--ink)',letterSpacing:mono?'.02em':'-0.005em',
        wordBreak: small ? 'break-all' : 'normal'}}>{value}</div>
    </div>
  );
}

function Timeline({ reg }) {
  const events = [
    reg.created_at && { date: reg.created_at, label: 'Created' },
    reg.submitted_at && { date: reg.submitted_at, label: 'Submitted to office' },
    reg.status === 'correspondence' && { date: daysAgo(7), label: 'Office correspondence received', warn: true },
    reg.status === 'rejected' && { date: daysAgo(7), label: 'Refused', warn: true, error: true },
    reg.registered_at && { date: reg.registered_at, label: 'Certificate issued', good: true },
    reg.certificate_uploaded_at && { date: reg.certificate_uploaded_at, label: 'Certificate uploaded to vault' },
  ].filter(Boolean);
  return (
    <div style={{position:'relative',paddingLeft:18}}>
      <div style={{position:'absolute',left:5,top:6,bottom:6,width:1,background:'var(--rule)'}}/>
      {events.map((e, i) => (
        <div key={i} style={{position:'relative',paddingBottom:12}}>
          <div style={{position:'absolute',left:-18,top:4,width:11,height:11,
            background: e.error ? '#a04432' : e.good ? '#3a6a3a' : e.warn ? '#c79538' : 'var(--ink-3)',
            borderRadius:'50%'}}/>
          <div className="ff-mono num" style={{fontSize:10,color:'var(--ink-3)',letterSpacing:'.02em'}}>{e.date}</div>
          <div style={{fontSize:12,color:'var(--ink)',marginTop:2,letterSpacing:'-0.005em'}}>{e.label}</div>
        </div>
      ))}
    </div>
  );
}

// ─────────────────────────── main screen
function ScreenCopyright({ go }) {
  const [filters, setFilters] = useState({ status:'all', jurisdiction:'all', type:'all', subject:'all', q:'' });
  const [openId, setOpenId] = useState(null);

  const all = useMemo(() => buildRegistrations(), []);

  const filtered = useMemo(() => {
    return all.filter(a => {
      if (filters.status !== 'all' && a.status !== filters.status) return false;
      if (filters.jurisdiction !== 'all' && a.jurisdiction.code !== filters.jurisdiction) return false;
      if (filters.type !== 'all' && a.copyright_type !== filters.type) return false;
      if (filters.subject !== 'all' && a.subject_kind !== filters.subject) return false;
      if (filters.q) {
        const q = filters.q.toLowerCase();
        const hay = [a.title, a.registration_number, a.eco_service_number, a.claimant_name, a.subject_secondary, a.isn_value].filter(Boolean).join(' ').toLowerCase();
        if (!hay.includes(q)) return false;
      }
      return true;
    }).sort((x,y) => {
      // primary: registered/submitted desc, then status order
      const dateX = x.registered_at || x.submitted_at || x.created_at;
      const dateY = y.registered_at || y.submitted_at || y.created_at;
      if (dateX !== dateY) return dateX > dateY ? -1 : 1;
      return 0;
    });
  }, [all, filters]);

  const counts = useMemo(() => {
    const byStatus = {};
    all.forEach(a => byStatus[a.status] = (byStatus[a.status]||0) + 1);
    return { byStatus, total: filtered.length };
  }, [all, filtered]);

  const metrics = useMemo(() => {
    const reg = all.filter(a => a.status === 'registered');
    const pending = all.filter(a => a.status === 'submitted' || a.status === 'in_examination');
    const action = all.filter(a => a.status === 'correspondence' || a.status === 'rejected' || a.status === 'draft');
    const totalFee = all.filter(a => a.filing_fee_amount).reduce((s,a) => s + (a.filing_fee_currency === 'USD' ? a.filing_fee_amount : a.filing_fee_amount * 0.5), 0);
    return { regCount: reg.length, pendingCount: pending.length, actionCount: action.length, totalFee };
  }, [all]);

  const openItem = openId ? all.find(a => a.id === openId) : null;

  return (
    <>
      {/* Header */}
      <div style={{display:'flex',justifyContent:'space-between',alignItems:'flex-start',
        borderBottom:'1px solid var(--rule)',paddingBottom:16,marginBottom:24}}>
        <div>
          <div className="ff-mono upper" style={{fontSize:10,letterSpacing:'.12em',color:'var(--ink-3)',marginBottom:8}}>
            RIGHTS · COPYRIGHT REGISTRATIONS
          </div>
          <h1 className="ff-display" style={{fontSize:42,fontWeight:600,letterSpacing:'-0.03em',lineHeight:1,margin:0}}>
            Copyright
          </h1>
          <div style={{fontSize:13,color:'var(--ink-2)',marginTop:10,letterSpacing:'-0.005em',maxWidth:740}}>
            Filings with national copyright offices — USCO (PA, SR, TX, VA), UK IPO, DPMA, INPI, JP ACA and others.
            Distinct from PRO/CMO registration; this is statutory copyright deposit.
          </div>
        </div>
        <div style={{display:'flex',gap:10}}>
          <button className="ff-mono upper"
            style={{padding:'8px 14px',background:'transparent',color:'var(--ink-3)',border:'1px solid var(--rule)',fontSize:11,letterSpacing:'.08em',cursor:'pointer',whiteSpace:'nowrap',flexShrink:0}}>
            EXPORT CSV
          </button>
          <button className="ff-mono upper"
            style={{padding:'8px 14px',background:'var(--ink)',color:'var(--bg)',border:0,fontSize:11,letterSpacing:'.08em',cursor:'pointer',whiteSpace:'nowrap',flexShrink:0}}>
            NEW REGISTRATION
          </button>
        </div>
      </div>

      {/* KPI strip */}
      <div style={{display:'flex',border:'1px solid var(--rule)',marginBottom:24}}>
        <Stat label="REGISTERED" value={metrics.regCount.toLocaleString()} sub="certificates issued" />
        <Stat label="PENDING" value={metrics.pendingCount.toLocaleString()} sub="awaiting examination" accent={metrics.pendingCount > 0 ? '#7a6e2d' : 'var(--ink)'}/>
        <Stat label="NEEDS ACTION" value={metrics.actionCount.toLocaleString()} sub="draft, correspondence, rejected" accent={metrics.actionCount > 0 ? '#c79538' : 'var(--ink)'}/>
        <Stat label="TOTAL FILING FEES" value={fmt$(metrics.totalFee, 'USD')} sub="USD-equivalent, lifetime" last/>
      </div>

      {/* Distribution */}
      <JurisdictionDistribution items={all}/>

      {/* Filter bar */}
      <FilterBar filters={filters} setFilters={setFilters} counts={counts}/>

      {/* Registrations list */}
      <div style={{border:'1px solid var(--rule)',background:'var(--bg)'}}>
        <div style={{display:'grid',gridTemplateColumns:'130px 60px 1.6fr 1.2fr 130px 130px 90px',gap:0,
          padding:'10px 14px',borderBottom:'1px solid var(--rule)',background:'var(--bg-2)'}}>
          {['REG #','TYPE','TITLE / SUBJECT','CLAIMANT','JURISDICTION','DATE','STATUS'].map((h,i) => (
            <span key={i} className="ff-mono upper" style={{fontSize:9,color:'var(--ink-3)',letterSpacing:'.1em',
              textAlign: i === 6 ? 'right' : 'left'}}>{h}</span>
          ))}
        </div>
        {filtered.length === 0 ? (
          <div style={{padding:'48px 24px',textAlign:'center',color:'var(--ink-3)'}}>
            <div className="ff-mono upper" style={{fontSize:11,letterSpacing:'.1em'}}>NO REGISTRATIONS MATCH CURRENT FILTERS</div>
            <button onClick={()=>setFilters({status:'all',jurisdiction:'all',type:'all',subject:'all',q:''})}
              className="ff-mono upper" style={{marginTop:14,fontSize:10,letterSpacing:'.08em',color:'var(--ink)',background:'none',border:0,cursor:'pointer'}}>
              clear filters →
            </button>
          </div>
        ) : (
          filtered.slice(0, 100).map((a, i) => (
            <RegRow key={a.id} reg={a} isLast={i === Math.min(99, filtered.length - 1)} onOpen={()=>setOpenId(a.id)}/>
          ))
        )}
        {filtered.length > 100 && (
          <div style={{padding:'12px 14px',borderTop:'1px solid var(--rule-soft)',
            display:'flex',justifyContent:'center',alignItems:'center'}}>
            <span className="ff-mono" style={{fontSize:11,color:'var(--ink-3)',letterSpacing:'.04em'}}>
              showing first 100 of {filtered.length.toLocaleString()} — narrow filters to see more
            </span>
          </div>
        )}
      </div>

      {/* Drawer */}
      {openItem && <RegDrawer reg={openItem} onClose={()=>setOpenId(null)} go={go}/>}
    </>
  );
}

window.ScreenCopyright = ScreenCopyright;
})();
