// ============================================================================
// CWR COMPLIANCE DASHBOARD — surfaces the in-house validation harness as a
// readable report, exposes a downloadable plaintext audit, and shows the
// scale-test result so anyone reviewing a society submission can see the
// generator's correctness posture at a glance.
//
// Loaded as window.CwrComplianceTab and rendered as a tab inside ScreenCwrAcks.
// Depends on: window.CwrTest, window.CwrBuild
// ============================================================================
(function () {
  const { useState, useMemo, useEffect } = React;

  function fmtMs(ms) {
    if (ms < 1) return '<1 ms';
    if (ms < 1000) return Math.round(ms) + ' ms';
    return (ms / 1000).toFixed(2) + ' s';
  }
  function fmtBytes(n) {
    if (n < 1024) return n + ' B';
    if (n < 1024 * 1024) return (n / 1024).toFixed(1) + ' KB';
    return (n / 1024 / 1024).toFixed(2) + ' MB';
  }

  function runScaleTest(workCount = 50000) {
    if (!window.CwrBuild) return null;
    const works = [];
    for (let i = 0; i < workCount; i++) {
      works.push({
        id: 'W' + i, title: 'WORK ' + i, iswc: 'T0345246801',
        writers: [{ id: 'WR' + i, controlled: true, lastName: 'WRITER ' + i, firstName: 'X', designation: 'CA', ipiName: '00000000000', prShare: 50 }],
        publishers: [{ id: 'P' + i, controlled: true, name: 'PUB ' + i, role: 'E', ipiName: '00000000000', prShare: 50 }],
      });
    }
    const t0 = performance.now();
    const lines = window.CwrBuild.buildTransmission({ version: '2.2', senderIpi: 199900001, senderName: 'TEST', works });
    const t1 = performance.now();
    const totalBytes = lines.reduce((s, l) => s + l.length + 2, 0);
    const trlCount = parseInt(lines[lines.length - 1].slice(16, 23), 10);
    return {
      works: works.length,
      lines: lines.length,
      bytes: totalBytes,
      buildMs: t1 - t0,
      trlCount,
      trlMatches: trlCount === lines.length,
    };
  }

  function downloadReport(suite, scale) {
    const date = new Date().toISOString();
    const L = [];
    L.push('CWR GENERATOR — COMPLIANCE REPORT');
    L.push('=================================');
    L.push('');
    L.push('Generated:        ' + date);
    L.push('Generator engine: window.CwrBuild');
    L.push('Spec coverage:    CWR 2.1, 2.1r7, 2.2, 3.0, 3.1');
    L.push('');
    L.push('SUMMARY');
    L.push('-------');
    L.push('Total assertions: ' + suite.summary.total);
    L.push('Passed:           ' + suite.summary.passed);
    L.push('Failed:           ' + suite.summary.failed);
    L.push('Pass rate:        ' + ((suite.summary.passed / suite.summary.total) * 100).toFixed(1) + '%');
    L.push('');
    if (scale) {
      L.push('SCALE TEST');
      L.push('----------');
      L.push('Work count:       ' + scale.works.toLocaleString());
      L.push('Records emitted:  ' + scale.lines.toLocaleString());
      L.push('Bytes total:      ' + fmtBytes(scale.bytes));
      L.push('Build time:       ' + fmtMs(scale.buildMs));
      L.push('TRL self-check:   ' + (scale.trlMatches ? 'PASS (TRL count = actual record count)' : 'FAIL (' + scale.trlCount + ' vs ' + scale.lines + ')'));
      L.push('');
    }
    L.push('ASSERTION DETAIL');
    L.push('----------------');
    const groups = {};
    suite.results.forEach(r => {
      const g = (r.name.split('·')[0] || 'misc').trim();
      (groups[g] = groups[g] || []).push(r);
    });
    Object.keys(groups).sort().forEach(g => {
      const arr = groups[g];
      const passed = arr.filter(x => x.pass).length;
      L.push('');
      L.push('[' + g + ']  ' + passed + '/' + arr.length);
      arr.forEach(r => {
        L.push('  ' + (r.pass ? '✓' : '✗') + '  ' + r.name + (r.detail ? '  ::  ' + r.detail : ''));
      });
    });
    L.push('');
    L.push('--- end of report ---');
    const blob = new Blob([L.join('\n')], { type: 'text/plain' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url; a.download = 'cwr-compliance-' + date.slice(0, 10) + '.txt';
    document.body.appendChild(a); a.click(); a.remove();
    setTimeout(() => URL.revokeObjectURL(url), 2000);
  }

  function CwrComplianceTab() {
    const [section, setSection] = useState('harness'); // harness | societies | fixtures | runbook
    const [running, setRunning] = useState(true);
    const [suite, setSuite] = useState(null);
    const [fixtureSuite, setFixtureSuite] = useState(null);
    const [scale, setScale] = useState(null);
    const [scaleRunning, setScaleRunning] = useState(false);
    const [filter, setFilter] = useState('all'); // all | failed | passed
    const [scaleSize, setScaleSize] = useState(50000);

    useEffect(() => {
      // defer one tick so the spinner paints
      const id = setTimeout(() => {
        if (window.CwrTest && window.REF && window.REF.ready) {
          const r = window.CwrTest.runFullSuite();
          setSuite(r);
        }
        if (window.CwrFixtures) {
          try { setFixtureSuite(window.CwrFixtures.runFixtureSuite()); } catch (e) {}
        }
        setRunning(false);
      }, 50);
      return () => clearTimeout(id);
    }, []);

    const runScale = () => {
      setScaleRunning(true);
      setTimeout(() => {
        const s = runScaleTest(scaleSize);
        setScale(s);
        setScaleRunning(false);
      }, 50);
    };

    const grouped = useMemo(() => {
      if (!suite) return [];
      const map = new Map();
      suite.results.forEach(r => {
        const g = (r.name.split('·')[0] || 'misc').trim();
        if (!map.has(g)) map.set(g, []);
        map.get(g).push(r);
      });
      return [...map.entries()].map(([name, items]) => ({
        name,
        items,
        passed: items.filter(x => x.pass).length,
        total: items.length,
      })).sort((a, b) => a.name.localeCompare(b.name));
    }, [suite]);

    const visible = (items) => {
      if (filter === 'failed') return items.filter(x => !x.pass);
      if (filter === 'passed') return items.filter(x => x.pass);
      return items;
    };

    if (running) {
      return <div style={{ padding:80, textAlign:'center', color:'var(--ink-3)' }} className="ff-mono upper" >running compliance harness…</div>;
    }
    if (!suite) {
      return <div style={{ padding:80, textAlign:'center', color:'var(--ink-3)' }}>Test harness not available.</div>;
    }

    const passRate = (suite.summary.passed / suite.summary.total) * 100;
    const allGreen = suite.summary.failed === 0;

    return (
      <div>
        {/* SECTION TABS */}
        <div style={{ display:'flex', gap:0, marginBottom:24, borderBottom:'1px solid var(--rule)' }}>
          {[
            { k:'harness',   l:'Harness',           hint: suite.summary.passed + '/' + suite.summary.total + ' assertions' },
            { k:'readiness', l:'Readiness',         hint: 'society-by-society %' },
            { k:'societies', l:'Society rules',     hint: (window.CwrSociety ? Object.keys(window.CwrSociety.SOCIETY_PROFILES).length : 0) + ' profiles' },
            { k:'fixtures',  l:'Fixtures',          hint: fixtureSuite ? (fixtureSuite.summary.checksPass + '/' + fixtureSuite.summary.checks + ' checks') : '—' },
            { k:'bytediff',  l:'Byte-diff',         hint: window.CwrByteDiff ? Object.keys(window.CwrByteDiff.SOCIETY_LAYOUTS).length + ' societies' : '—' },
            { k:'ids',       l:'ID validation',     hint: 'ISWC · IPI · ISRC · ISNI' },
            { k:'testenv',   l:'Test env',          hint: window.CwrTestEnv ? Object.keys(window.CwrTestEnv.CONFIGS).length + ' endpoints' : '—' },
            { k:'runbook',   l:'Certification',     hint: 'per-society status' },
          ].map(t => (
            <button key={t.k} onClick={() => setSection(t.k)} className="ff-mono upper" style={{
              padding:'10px 16px', fontSize:10, fontWeight:600, letterSpacing:'.08em',
              borderBottom: section === t.k ? '2px solid var(--ink)' : '2px solid transparent', marginBottom:-1,
              color: section === t.k ? 'var(--ink)' : 'var(--ink-3)', background:'transparent', border:0, cursor:'pointer',
              display:'flex', flexDirection:'column', alignItems:'flex-start', gap:2,
            }}>
              <span>{t.l}</span>
              <span className="ff-mono" style={{ fontSize:9, color:'var(--ink-4)', fontWeight:400, letterSpacing:'.04em', textTransform:'none' }}>{t.hint}</span>
            </button>
          ))}
        </div>

        {section === 'readiness' && <ReadinessSection fixtureSuite={fixtureSuite} />}
        {section === 'societies' && <SocietySection fixtureSuite={fixtureSuite} />}
        {section === 'fixtures'  && <FixtureSection suite={fixtureSuite} />}
        {section === 'bytediff'  && <ByteDiffSection />}
        {section === 'ids'       && <IdValidateSection />}
        {section === 'testenv'   && <TestEnvSection />}
        {section === 'runbook'   && (window.CwrCertTab ? React.createElement(window.CwrCertTab) : <div style={{padding:40,color:'var(--ink-3)'}}>Cert runbook not loaded.</div>)}
        {section === 'harness'   && <HarnessSection
          suite={suite} scale={scale} scaleRunning={scaleRunning}
          scaleSize={scaleSize} setScaleSize={setScaleSize}
          runScale={runScale} filter={filter} setFilter={setFilter}
          grouped={grouped} visible={visible} passRate={passRate} allGreen={allGreen}
        />}
      </div>
    );
  }

  // ──────────────────────────────────────────────────────────────────────
  // SUB-SECTION: Harness  (the original harness view, factored out)
  // ──────────────────────────────────────────────────────────────────────
  function HarnessSection({ suite, scale, scaleRunning, scaleSize, setScaleSize, runScale, filter, setFilter, grouped, visible, passRate, allGreen }) {
    return (
      <div>
        {/* HEADER STAT BAND */}
        <div style={{ display:'grid', gridTemplateColumns:'repeat(4, 1fr)', gap:1, background:'var(--rule)', border:'1px solid var(--rule)', marginBottom:24 }}>
          <Stat label="Assertions" value={suite.summary.total} />
          <Stat label="Passing" value={suite.summary.passed} accent={allGreen ? 'good' : null} />
          <Stat label="Failing" value={suite.summary.failed} accent={suite.summary.failed > 0 ? 'bad' : null} />
          <Stat label="Pass rate" value={passRate.toFixed(1) + '%'} accent={allGreen ? 'good' : null} />
        </div>

        {/* SPEC COVERAGE */}
        <Block title="Spec coverage">
          <div style={{ display:'grid', gridTemplateColumns:'repeat(5, 1fr)', gap:1, background:'var(--rule)', border:'1px solid var(--rule)' }}>
            {['2.1', '2.1r7', '2.2', '3.0', '3.1'].map(v => (
              <div key={v} style={{ background:'var(--paper)', padding:'18px 16px' }}>
                <div className="ff-mono" style={{ fontSize:10, color:'var(--ink-3)', letterSpacing:'.06em' }}>CWR v{v}</div>
                <div style={{ fontSize:24, marginTop:4, fontWeight:300 }}>✓</div>
                <div className="ff-mono" style={{ fontSize:9, color:'var(--ink-4)', marginTop:6, lineHeight:1.5 }}>
                  {v.startsWith('3') ? 'JSON sibling · XRF · NRN · NPA writer rules' : 'fixed-width · CISAC charset'}
                </div>
              </div>
            ))}
          </div>
        </Block>

        {/* RECORD-TYPE COVERAGE */}
        <Block title="Record types covered">
          <div style={{ display:'grid', gridTemplateColumns:'repeat(6, 1fr)', gap:6 }}>
            {['HDR','GRH','GRT','TRL','NWR','REV','ISW','EXC','SPU','SPT','OPU','OPT','PWR','SWR','SWT','OWR','OWT','ALT','EWT','VER','PER','REC','ORN','INS','IND','COM','MSG','ARI','XRF','NET','NCT','NVT','NPN','NPR','NWN','NOW','NRN','AGR','TER','IPA','NPA','ACK'].map(rt => (
              <div key={rt} className="ff-mono" style={{
                padding:'8px 0', textAlign:'center', fontSize:11, fontWeight:600, letterSpacing:'.08em',
                background:'var(--ink-bg)', border:'1px solid var(--rule)', color:'var(--ink-2)',
              }}>{rt}</div>
            ))}
          </div>
        </Block>

        {/* SCALE TEST */}
        <Block title="Scale test" right={
          <div style={{ display:'flex', gap:8, alignItems:'center' }}>
            <select value={scaleSize} onChange={e => setScaleSize(parseInt(e.target.value, 10))} className="ff-mono" style={{ padding:'6px 10px', fontSize:11, border:'1px solid var(--rule)', background:'var(--paper)' }}>
              <option value={1000}>1k works</option>
              <option value={10000}>10k works</option>
              <option value={50000}>50k works</option>
              <option value={100000}>100k works</option>
            </select>
            <button onClick={runScale} disabled={scaleRunning} className="ff-mono upper" style={{
              padding:'7px 14px', fontSize:11, letterSpacing:'.08em', fontWeight:600,
              background:'var(--ink)', color:'var(--paper)', border:0, cursor:'pointer',
            }}>{scaleRunning ? 'building…' : 'run'}</button>
          </div>
        }>
          {!scale ? (
            <div className="ff-mono" style={{ fontSize:11, color:'var(--ink-3)', padding:'24px 16px' }}>
              Press run to build a synthetic transmission. The harness counts records, measures bytes, validates the trailer count, and times the build.
            </div>
          ) : (
            <div style={{ display:'grid', gridTemplateColumns:'repeat(5, 1fr)', gap:1, background:'var(--rule)', border:'1px solid var(--rule)' }}>
              <Stat label="Works"          value={scale.works.toLocaleString()} small />
              <Stat label="Records"        value={scale.lines.toLocaleString()} small />
              <Stat label="Bytes"          value={fmtBytes(scale.bytes)} small />
              <Stat label="Build time"     value={fmtMs(scale.buildMs)} small />
              <Stat label="Trailer check"  value={scale.trlMatches ? 'PASS' : 'FAIL'} small accent={scale.trlMatches ? 'good' : 'bad'} />
            </div>
          )}
        </Block>

        {/* DETAILED ASSERTIONS */}
        <Block title="Assertion detail" right={
          <div style={{ display:'flex', gap:0, border:'1px solid var(--rule)' }}>
            {[['all','All'],['failed','Failed'],['passed','Passed']].map(([k,l]) => (
              <button key={k} onClick={() => setFilter(k)} className="ff-mono upper" style={{
                padding:'6px 12px', fontSize:10, letterSpacing:'.08em', fontWeight:600,
                background: filter === k ? 'var(--ink)' : 'var(--paper)',
                color: filter === k ? 'var(--paper)' : 'var(--ink-2)',
                border:0, borderRight: k === 'passed' ? 0 : '1px solid var(--rule)', cursor:'pointer',
              }}>{l}</button>
            ))}
            <button onClick={() => downloadReport(suite, scale)} className="ff-mono upper" style={{
              padding:'6px 12px', fontSize:10, letterSpacing:'.08em', fontWeight:600,
              background:'var(--paper)', color:'var(--ink-2)', border:0, borderLeft:'1px solid var(--rule)', cursor:'pointer',
            }}>Download report</button>
          </div>
        }>
          <div style={{ border:'1px solid var(--rule)', maxHeight:520, overflow:'auto' }}>
            {grouped.map(g => {
              const items = visible(g.items);
              if (items.length === 0) return null;
              const allPass = g.passed === g.total;
              return (
                <div key={g.name} style={{ borderBottom:'1px solid var(--rule)' }}>
                  <div className="ff-mono" style={{
                    display:'flex', alignItems:'center', justifyContent:'space-between',
                    padding:'10px 14px', background:'var(--ink-bg)',
                    fontSize:11, fontWeight:600, letterSpacing:'.06em', textTransform:'uppercase',
                  }}>
                    <span>{g.name}</span>
                    <span style={{ color: allPass ? 'var(--ok, #1f8a4f)' : 'var(--bad, #b94a4a)' }}>
                      {g.passed}/{g.total}
                    </span>
                  </div>
                  {items.map((r, i) => (
                    <div key={i} style={{
                      display:'flex', gap:12, padding:'8px 14px', alignItems:'baseline',
                      borderTop: i === 0 ? 0 : '1px solid var(--rule-soft, #efece8)',
                      fontSize:12,
                    }}>
                      <span className="ff-mono" style={{ color: r.pass ? 'var(--ok, #1f8a4f)' : 'var(--bad, #b94a4a)', width:14 }}>
                        {r.pass ? '✓' : '✗'}
                      </span>
                      <span style={{ flex:1, color: r.pass ? 'var(--ink-2)' : 'var(--ink)' }}>
                        {r.name.replace(g.name + ' · ', '')}
                      </span>
                      {r.detail && (
                        <span className="ff-mono" style={{ color:'var(--ink-3)', fontSize:10 }}>
                          {r.detail.length > 80 ? r.detail.slice(0, 80) + '…' : r.detail}
                        </span>
                      )}
                    </div>
                  ))}
                </div>
              );
            })}
          </div>
        </Block>
      </div>
    );
  }

  // ──────────────────────────────────────────────────────────────────────
  // SUB-SECTION: Readiness — society-by-society % score + gap list
  // ──────────────────────────────────────────────────────────────────────
  function ReadinessSection({ fixtureSuite }) {
    if (!window.CwrSociety) return <div style={{ padding:40, color:'var(--ink-3)' }}>Society engine not loaded.</div>;

    const profiles = window.CwrSociety.SOCIETY_PROFILES;
    const codes = Object.keys(profiles);

    const readiness = codes.map(code => {
      const p = profiles[code];

      const fix = fixtureSuite ? fixtureSuite.results.filter(r => r.society === code) : [];
      const fixturePass = fix.reduce((s, r) => s + r.passed, 0);
      const fixtureTotal = fix.reduce((s, r) => s + r.total, 0);
      const fixtureScore = fixtureTotal > 0 ? (fixturePass / fixtureTotal) : null;
      const fixtureCovered = fix.length > 0;

      const ruleCount = Object.keys(p.rules || {}).length;

      let certStatus = 'untested';
      if (window.CwrCert && window.CwrCert.getStatus) {
        certStatus = window.CwrCert.getStatus(code) || 'untested';
      }
      const certScore = { certified: 1, testing: 0.6, registered: 0.3, untested: 0 }[certStatus] || 0;

      const versionScore = (p.versions && p.versions.length >= 3) ? 1 : (p.versions ? p.versions.length / 3 : 0);

      // 50% fixtures, 25% cert track, 15% rules encoded, 10% version coverage
      const weights = { fixtures: 0.50, cert: 0.25, rules: 0.15, versions: 0.10 };
      let score = 0;
      let weightSum = 0;
      if (fixtureScore !== null) {
        score += fixtureScore * weights.fixtures;
        weightSum += weights.fixtures;
      }
      score += certScore * weights.cert;
      score += (ruleCount > 0 ? Math.min(1, ruleCount / 4) : 0) * weights.rules;
      score += versionScore * weights.versions;
      weightSum += weights.cert + weights.rules + weights.versions;
      const readinessPct = Math.round((score / weightSum) * 100);

      const gaps = [];
      if (!fixtureCovered) gaps.push({ severity: 'high', label: 'No reference fixture' });
      if (fixtureScore !== null && fixtureScore < 1) {
        gaps.push({ severity: 'high', label: (fixtureTotal - fixturePass) + ' fixture assertion(s) failing' });
      }
      if (ruleCount === 0) gaps.push({ severity: 'medium', label: 'No society-specific rules encoded (using base spec only)' });
      if (certStatus === 'untested') gaps.push({ severity: 'medium', label: 'Cert track not initiated' });
      else if (certStatus === 'registered') gaps.push({ severity: 'low', label: 'Cert registered but not in testing' });
      else if (certStatus === 'testing') gaps.push({ severity: 'low', label: 'Cert in testing — pending society sign-off' });
      if (!p.versions || p.versions.length < 2) gaps.push({ severity: 'low', label: 'Limited version coverage' });

      return { code, profile: p, readinessPct, fixtureScore, fixturePass, fixtureTotal, ruleCount, certStatus, gaps };
    });

    readiness.sort((a, b) => b.readinessPct - a.readinessPct);

    const avgReadiness = Math.round(readiness.reduce((s, r) => s + r.readinessPct, 0) / readiness.length);
    const greenCount = readiness.filter(r => r.readinessPct >= 80).length;
    const amberCount = readiness.filter(r => r.readinessPct >= 50 && r.readinessPct < 80).length;
    const redCount = readiness.filter(r => r.readinessPct < 50).length;

    const sevColor = (s) => s === 'high' ? 'var(--bad, #b94a4a)' : s === 'medium' ? '#c9871a' : 'var(--ink-3)';
    const scoreColor = (n) => n >= 80 ? 'var(--ok, #1f8a4f)' : n >= 50 ? '#c9871a' : 'var(--bad, #b94a4a)';

    return (
      <div>
        <div style={{ display:'grid', gridTemplateColumns:'repeat(4, 1fr)', gap:1, background:'var(--rule)', border:'1px solid var(--rule)', marginBottom:24 }}>
          <Stat label="Avg. readiness"  value={avgReadiness + '%'} accent={avgReadiness >= 80 ? 'good' : avgReadiness >= 50 ? null : 'bad'} />
          <Stat label="≥ 80% (green)"   value={greenCount} accent="good" />
          <Stat label="50–80% (amber)"  value={amberCount} />
          <Stat label="< 50% (red)"     value={redCount} accent={redCount > 0 ? 'bad' : null} />
        </div>

        <Block title="Society-by-society readiness">
          <div style={{ fontSize:11, color:'var(--ink-3)', marginBottom:12, lineHeight:1.55 }}>
            Score blends fixtures (50%) · cert-track status (25%) · rules encoded (15%) · version coverage (10%). Sorted by overall readiness.
          </div>
          <div style={{ border:'1px solid var(--rule)' }}>
            <div className="ff-mono upper" style={{ display:'grid', gridTemplateColumns:'1.4fr 90px 90px 80px 90px 1.6fr', gap:14, padding:'10px 14px', background:'var(--ink-bg)', fontSize:9, color:'var(--ink-3)', letterSpacing:'.08em', fontWeight:600, borderBottom:'1px solid var(--rule)' }}>
              <span>Society</span>
              <span style={{ textAlign:'right' }}>Score</span>
              <span style={{ textAlign:'right' }}>Fixtures</span>
              <span style={{ textAlign:'right' }}>Rules</span>
              <span>Cert</span>
              <span>Gaps</span>
            </div>
            {readiness.map((r, i) => (
              <div key={r.code} style={{ display:'grid', gridTemplateColumns:'1.4fr 90px 90px 80px 90px 1.6fr', gap:14, padding:'14px 14px', borderTop: i === 0 ? 0 : '1px solid var(--rule)', alignItems:'center' }}>
                <div>
                  <div style={{ fontSize:13, fontWeight:500 }}>{r.profile.name}</div>
                  <div className="ff-mono" style={{ fontSize:10, color:'var(--ink-3)', marginTop:2 }}>{r.code} · CISAC {r.profile.cisac}</div>
                </div>
                <div style={{ textAlign:'right' }}>
                  <div className="ff-mono" style={{ fontSize:14, fontWeight:600, color: scoreColor(r.readinessPct) }}>{r.readinessPct}%</div>
                  <div style={{ height:3, background:'var(--ink-bg)', marginTop:4 }}>
                    <div style={{ height:'100%', width: r.readinessPct + '%', background: scoreColor(r.readinessPct) }}></div>
                  </div>
                </div>
                <div className="ff-mono" style={{ fontSize:11, textAlign:'right', color: r.fixtureScore === 1 ? 'var(--ok, #1f8a4f)' : r.fixtureScore === null ? 'var(--ink-4)' : 'var(--ink-2)' }}>
                  {r.fixtureTotal > 0 ? r.fixturePass + '/' + r.fixtureTotal : '—'}
                </div>
                <div className="ff-mono" style={{ fontSize:11, textAlign:'right', color: r.ruleCount > 0 ? 'var(--ink-2)' : 'var(--ink-4)' }}>
                  {r.ruleCount > 0 ? r.ruleCount + ' encoded' : 'base only'}
                </div>
                <div>
                  <span className="ff-mono upper" style={{ fontSize:9, fontWeight:600, letterSpacing:'.08em', padding:'3px 7px', background:'var(--ink-bg)', color: r.certStatus === 'certified' ? 'var(--ok, #1f8a4f)' : r.certStatus === 'testing' ? '#c9871a' : 'var(--ink-3)' }}>
                    {r.certStatus}
                  </span>
                </div>
                <div style={{ display:'flex', flexDirection:'column', gap:3 }}>
                  {r.gaps.length === 0 ? (
                    <span className="ff-mono" style={{ fontSize:10, color:'var(--ok, #1f8a4f)' }}>✓ no gaps</span>
                  ) : (
                    r.gaps.map((g, j) => (
                      <div key={j} style={{ display:'flex', alignItems:'baseline', gap:6 }}>
                        <span style={{ width:5, height:5, background: sevColor(g.severity), display:'inline-block', flexShrink:0 }}></span>
                        <span style={{ fontSize:10.5, color:'var(--ink-2)', lineHeight:1.4 }}>{g.label}</span>
                      </div>
                    ))
                  )}
                </div>
              </div>
            ))}
          </div>
        </Block>

        <Block title="Top gaps across all societies">
          {(() => {
            const allGaps = {};
            readiness.forEach(r => {
              r.gaps.forEach(g => {
                if (!allGaps[g.label]) allGaps[g.label] = { count: 0, severity: g.severity, societies: [] };
                allGaps[g.label].count += 1;
                allGaps[g.label].societies.push(r.profile.name);
              });
            });
            const sorted = Object.entries(allGaps).sort((a, b) => b[1].count - a[1].count);
            if (sorted.length === 0) return <div className="ff-mono" style={{ fontSize:11, color:'var(--ok, #1f8a4f)', padding:12 }}>No gaps detected.</div>;
            return (
              <div style={{ border:'1px solid var(--rule)' }}>
                {sorted.map(([label, info], i) => (
                  <div key={label} style={{ display:'grid', gridTemplateColumns:'50px 1fr 100px 1.4fr', gap:12, padding:'12px 14px', borderTop: i === 0 ? 0 : '1px solid var(--rule)', alignItems:'center' }}>
                    <span className="ff-mono" style={{ fontSize:14, fontWeight:600, color: sevColor(info.severity) }}>×{info.count}</span>
                    <div style={{ fontSize:12.5 }}>{label}</div>
                    <span className="ff-mono upper" style={{ fontSize:9, fontWeight:600, letterSpacing:'.08em', color: sevColor(info.severity) }}>{info.severity}</span>
                    <div className="ff-mono" style={{ fontSize:10, color:'var(--ink-3)', lineHeight:1.5 }}>
                      {info.societies.slice(0, 4).join(', ')}{info.societies.length > 4 ? ' +' + (info.societies.length - 4) : ''}
                    </div>
                  </div>
                ))}
              </div>
            );
          })()}
        </Block>
      </div>
    );
  }

  // ──────────────────────────────────────────────────────────────────────
  // SUB-SECTION: Society rules
  // ──────────────────────────────────────────────────────────────────────
  function SocietySection({ fixtureSuite }) {
    if (!window.CwrSociety) return <div style={{ padding:40, color:'var(--ink-3)' }}>Society rules engine not loaded.</div>;

    const profiles = window.CwrSociety.SOCIETY_PROFILES;
    const codes = Object.keys(profiles);

    // Per-society fixture pass rate
    const fixtureBySoc = {};
    if (fixtureSuite) {
      fixtureSuite.results.forEach(r => {
        if (!fixtureBySoc[r.society]) fixtureBySoc[r.society] = { pass: 0, total: 0 };
        fixtureBySoc[r.society].pass += r.passed;
        fixtureBySoc[r.society].total += r.total;
      });
    }

    const totalRules = codes.reduce((s, c) => s + Object.keys(profiles[c].rules).length, 0);

    return (
      <div>
        <div style={{ display:'grid', gridTemplateColumns:'repeat(4, 1fr)', gap:1, background:'var(--rule)', border:'1px solid var(--rule)', marginBottom:24 }}>
          <Stat label="Society profiles" value={codes.length} />
          <Stat label="Encoded rules"    value={totalRules} />
          <Stat label="Versions covered" value="2.1 · 2.1r7 · 2.2 · 3.0 · 3.1" small />
          <Stat label="TIS / CISAC"      value="ISO + 3-digit" small />
        </div>

        <Block title="Society rule profiles">
          <div style={{ border:'1px solid var(--rule)' }}>
            <div className="ff-mono upper" style={{ display:'grid', gridTemplateColumns:'1.4fr 60px 70px 1fr 90px 80px', gap:14, padding:'10px 14px', background:'var(--ink-bg)', fontSize:9, color:'var(--ink-3)', letterSpacing:'.08em', fontWeight:600, borderBottom:'1px solid var(--rule)' }}>
              <span>Society</span>
              <span>CISAC</span>
              <span>Country</span>
              <span>Active rules</span>
              <span>Versions</span>
              <span style={{ textAlign:'right' }}>Fixtures</span>
            </div>
            {codes.map((c, i) => {
              const p = profiles[c];
              const rules = Object.keys(p.rules);
              const fix = fixtureBySoc[c];
              return (
                <div key={c} style={{ display:'grid', gridTemplateColumns:'1.4fr 60px 70px 1fr 90px 80px', gap:14, padding:'12px 14px', borderTop: i === 0 ? 0 : '1px solid var(--rule)', alignItems:'center' }}>
                  <div>
                    <div style={{ fontSize:13, fontWeight:500 }}>{p.name}</div>
                    <div className="ff-mono" style={{ fontSize:10, color:'var(--ink-3)', marginTop:2 }}>{c}</div>
                  </div>
                  <div className="ff-mono" style={{ fontSize:11, color:'var(--ink-2)' }}>{p.cisac}</div>
                  <div className="ff-mono" style={{ fontSize:11, color:'var(--ink-2)' }}>{p.country}</div>
                  <div style={{ display:'flex', flexWrap:'wrap', gap:4 }}>
                    {rules.length === 0 ? (
                      <span className="ff-mono" style={{ fontSize:10, color:'var(--ink-3)' }}>base spec only</span>
                    ) : rules.slice(0, 4).map(rk => (
                      <span key={rk} className="ff-mono" style={{ fontSize:9, padding:'2px 6px', background:'var(--ink-bg)', color:'var(--ink-2)', letterSpacing:'.02em' }}>{rk}</span>
                    ))}
                    {rules.length > 4 && <span className="ff-mono" style={{ fontSize:9, color:'var(--ink-3)' }}>+{rules.length - 4}</span>}
                  </div>
                  <div className="ff-mono" style={{ fontSize:10, color:'var(--ink-3)' }}>{p.versions.join(', ')}</div>
                  <div className="ff-mono" style={{ fontSize:11, textAlign:'right', color: fix && fix.pass === fix.total ? 'var(--ok, #1f8a4f)' : 'var(--ink-3)' }}>
                    {fix ? fix.pass + '/' + fix.total : '—'}
                  </div>
                </div>
              );
            })}
          </div>
        </Block>
      </div>
    );
  }

  // ──────────────────────────────────────────────────────────────────────
  // SUB-SECTION: Fixtures
  // ──────────────────────────────────────────────────────────────────────
  function FixtureSection({ suite }) {
    if (!suite) return <div style={{ padding:40, color:'var(--ink-3)' }}>Fixture suite not available.</div>;

    return (
      <div>
        <div style={{ display:'grid', gridTemplateColumns:'repeat(4, 1fr)', gap:1, background:'var(--rule)', border:'1px solid var(--rule)', marginBottom:24 }}>
          <Stat label="Fixtures"        value={suite.summary.fixtures} />
          <Stat label="Passing"         value={suite.summary.fixturesPass} accent={suite.summary.fixturesPass === suite.summary.fixtures ? 'good' : null} />
          <Stat label="Total checks"    value={suite.summary.checks} />
          <Stat label="Checks passed"   value={suite.summary.checksPass} accent={suite.summary.checksPass === suite.summary.checks ? 'good' : null} />
        </div>

        <Block title="Society reference fixtures">
          <div style={{ border:'1px solid var(--rule)' }}>
            {suite.results.map((r, i) => (
              <div key={r.id} style={{ borderTop: i === 0 ? 0 : '1px solid var(--rule)' }}>
                <div style={{ display:'grid', gridTemplateColumns:'1fr 80px 60px 80px 90px', gap:14, padding:'12px 14px', alignItems:'center' }}>
                  <div>
                    <div style={{ fontSize:12.5, fontWeight:500 }}>{r.id}</div>
                    {(() => {
                      const fx = window.CwrFixtures?.FIXTURES.find(f => f.id === r.id);
                      return fx ? <div className="ff-mono" style={{ fontSize:10, color:'var(--ink-3)', marginTop:2 }}>{fx.description}</div> : null;
                    })()}
                  </div>
                  <span className="ff-mono" style={{ fontSize:10, color:'var(--ink-2)' }}>{r.society}</span>
                  <span className="ff-mono" style={{ fontSize:10, color:'var(--ink-3)' }}>v{r.version}</span>
                  <span className="ff-mono" style={{ fontSize:11, color: r.allPass ? 'var(--ok, #1f8a4f)' : 'var(--bad, #b94a4a)', textAlign:'right' }}>
                    {r.passed}/{r.total}
                  </span>
                  <span className="ff-mono upper" style={{ fontSize:10, fontWeight:600, letterSpacing:'.08em', textAlign:'right',
                    color: r.allPass ? 'var(--ok, #1f8a4f)' : 'var(--bad, #b94a4a)',
                  }}>{r.allPass ? 'pass' : 'fail'}</span>
                </div>
                {!r.allPass && (
                  <div style={{ padding:'0 14px 10px 14px' }}>
                    {r.checks.filter(c => !c.pass).map((c, j) => (
                      <div key={j} className="ff-mono" style={{ fontSize:10, color:'var(--bad, #b94a4a)', padding:'2px 0' }}>
                        ✗ {c.name}{c.detail ? ' — ' + c.detail : ''}
                      </div>
                    ))}
                    {r.error && <div className="ff-mono" style={{ fontSize:10, color:'var(--bad, #b94a4a)', padding:'2px 0' }}>error: {r.error}</div>}
                  </div>
                )}
              </div>
            ))}
          </div>
        </Block>
      </div>
    );
  }

  // ──────────────────────────────────────────────────────────────────────
  // SUB-SECTION: Byte-diff  (per-society spec audit)
  // Runs cwr-byte-diff against every society × version, shows pass/fail
  // and any byte-level divergences from the published CWR field layout.
  // ──────────────────────────────────────────────────────────────────────
  function ByteDiffSection() {
    const [results, setResults] = useState(null);
    const [openSoc, setOpenSoc] = useState(null);

    useEffect(() => {
      if (!window.CwrByteDiff) return;
      const t = setTimeout(() => setResults(window.CwrByteDiff.auditAll()), 30);
      return () => clearTimeout(t);
    }, []);

    if (!window.CwrByteDiff) {
      return <div style={{padding:40, color:'var(--ink-3)'}}>Byte-diff module not loaded.</div>;
    }
    if (!results) {
      return <div style={{padding:80, textAlign:'center', color:'var(--ink-3)'}} className="ff-mono upper">running per-society byte-diff…</div>;
    }

    const totalChecks = results.results.reduce((s, r) => s + r.checksTotal, 0);
    const totalPass = results.results.reduce((s, r) => s + r.checksPass, 0);
    const cleanCount = results.summary.clean;
    const total = results.summary.total;
    const allClean = cleanCount === total;
    const passRate = totalChecks ? (totalPass / totalChecks * 100).toFixed(1) : '0';

    // Group results by society
    const bySoc = {};
    for (const r of results.results) {
      if (!bySoc[r.society]) bySoc[r.society] = [];
      bySoc[r.society].push(r);
    }

    return (
      <div>
        <div style={{ display:'grid', gridTemplateColumns:'repeat(4, 1fr)', gap:1, background:'var(--rule)', border:'1px solid var(--rule)', marginBottom:24 }}>
          <Stat label="Societies" value={Object.keys(bySoc).length} />
          <Stat label="Audits" value={cleanCount + '/' + total} accent={allClean ? 'good' : 'bad'} />
          <Stat label="Field checks" value={totalPass + '/' + totalChecks} accent={totalPass === totalChecks ? 'good' : 'bad'} />
          <Stat label="Pass rate" value={passRate + '%'} accent={allClean ? 'good' : 'info'} />
        </div>

        <div style={{ marginBottom:18 }}>
          <div className="ff-mono upper" style={{ fontSize:10, color:'var(--ink-3)', letterSpacing:'.08em', marginBottom:8 }}>About this audit</div>
          <div style={{ fontSize:13, color:'var(--ink-2)', lineHeight:1.55, maxWidth:780 }}>
            For each society, we build a representative NWR transmission and audit every record byte-by-byte against
            the published CWR field layout (HDR/GRH/NWR/SPU/SPT/SWR/SWT/PWR/PER/ORN/XRF/GRT/TRL) plus society-specific
            constraints. Society overlays encode mandatory records, allowed designation codes, value lists, and cross-record
            rules (e.g. "every controlled SWR has a matching PWR"). Failures pinpoint the exact record, field, and reason.
          </div>
        </div>

        <div style={{ border:'1px solid var(--rule)' }}>
          {Object.entries(bySoc).map(([soc, runs], i) => {
            const layout = window.CwrByteDiff.SOCIETY_LAYOUTS[soc];
            const allOk = runs.every(r => r.ok);
            const totalIssues = runs.reduce((s, r) => s + r.issues.length, 0);
            const open = openSoc === soc;
            return (
              <div key={soc} style={{ borderTop: i === 0 ? 0 : '1px solid var(--rule)', background:'var(--paper)' }}>
                <button onClick={() => setOpenSoc(open ? null : soc)} style={{
                  width:'100%', padding:'14px 18px', display:'grid',
                  gridTemplateColumns:'120px 70px 1fr 110px 60px',
                  gap:14, alignItems:'center', cursor:'pointer', background:'transparent', border:0, textAlign:'left',
                }}>
                  <div className="ff-mono" style={{ fontSize:13, fontWeight:600, letterSpacing:'.02em' }}>{soc}</div>
                  <div className="ff-mono" style={{ fontSize:10, color:'var(--ink-3)' }}>CISAC {layout.cisac}</div>
                  <div className="ff-mono" style={{ fontSize:11, color:'var(--ink-3)' }}>
                    {layout.mandatoryRecords.length} mandatory records · {Object.keys(layout.fieldConstraints || {}).length} field rules · {(layout.crossRecord || []).length} cross-record rules
                  </div>
                  <div className="ff-mono upper" style={{
                    fontSize:10, fontWeight:600, letterSpacing:'.08em',
                    color: allOk ? 'var(--ok, #1f8a4f)' : 'var(--bad, #b94a4a)',
                  }}>{allOk ? '✓ clean' : totalIssues + ' issues'}</div>
                  <div style={{ fontSize:11, color:'var(--ink-3)', textAlign:'right' }}>{open ? '▾' : '▸'}</div>
                </button>
                {open && (
                  <div style={{ padding:'4px 18px 16px', borderTop:'1px solid var(--rule)' }}>
                    {runs.map((r, ri) => (
                      <div key={ri} style={{ marginTop:14 }}>
                        <div className="ff-mono upper" style={{ fontSize:10, color:'var(--ink-3)', letterSpacing:'.08em', marginBottom:6 }}>
                          CWR v{r.version} · {r.checksPass}/{r.checksTotal} checks · {r.ok ? 'all clear' : r.issues.length + ' issues'}
                        </div>
                        {r.ok ? (
                          <div className="ff-mono" style={{ fontSize:11, color:'var(--ok, #1f8a4f)', padding:'6px 10px', background:'color-mix(in oklch, var(--ok, #1f8a4f) 8%, transparent)' }}>
                            ✓ All field positions, value-lists, and cross-record rules conform to the {soc} layout at v{r.version}.
                          </div>
                        ) : (
                          <div style={{ border:'1px solid var(--rule)' }}>
                            {r.issues.map((iss, ii) => (
                              <div key={ii} className="ff-mono" style={{
                                display:'grid', gridTemplateColumns:'60px 100px 60px 1fr',
                                gap:12, padding:'8px 10px', fontSize:11,
                                borderTop: ii === 0 ? 0 : '1px solid var(--rule)',
                                background: iss.severity === 'high' ? 'color-mix(in oklch, var(--bad, #b94a4a) 6%, transparent)' : 'transparent',
                              }}>
                                <span style={{ color: iss.severity === 'high' ? 'var(--bad, #b94a4a)' : '#c9871a', fontWeight:600 }}>{iss.severity}</span>
                                <span>{iss.record}</span>
                                <span style={{ color:'var(--ink-3)' }}>{iss.field || '—'}</span>
                                <span style={{ color:'var(--ink-2)' }}>{iss.message}</span>
                              </div>
                            ))}
                          </div>
                        )}
                      </div>
                    ))}
                  </div>
                )}
              </div>
            );
          })}
        </div>
      </div>
    );
  }

  // ──────────────────────────────────────────────────────────────────────
  // SUB-SECTION: ID validation (ISWC, IPI Name, IPI Base, ISRC, ISNI)
  // ──────────────────────────────────────────────────────────────────────
  function IdValidateSection() {
    const [selfTest, setSelfTest] = useState(null);
    const [audits, setAudits] = useState(null);

    useEffect(() => {
      if (!window.CwrIdValidate) return;
      const t = setTimeout(() => {
        setSelfTest(window.CwrIdValidate.selfTest());
        const a = {};
        if (window.CwrByteDiff) {
          for (const soc of Object.keys(window.CwrByteDiff.SOCIETY_LAYOUTS)) {
            const lines = window.CwrByteDiff.buildReferenceTransmission(soc, '3.1');
            if (lines) a[soc] = window.CwrIdValidate.auditTransmission(lines, '3.1');
          }
        }
        setAudits(a);
      }, 30);
      return () => clearTimeout(t);
    }, []);

    if (!window.CwrIdValidate) return <div style={{padding:40,color:'var(--ink-3)'}}>ID-validate module not loaded.</div>;
    if (!selfTest || !audits) return <div style={{padding:80,textAlign:'center',color:'var(--ink-3)'}} className="ff-mono upper">running ID audits…</div>;

    const totalIssues = Object.values(audits).reduce((s, a) => s + a.issues.length, 0);
    const cleanSocs = Object.values(audits).filter(a => a.ok).length;

    return (
      <div>
        <div style={{ display:'grid', gridTemplateColumns:'repeat(4, 1fr)', gap:1, background:'var(--rule)', border:'1px solid var(--rule)', marginBottom:24 }}>
          <Stat label="Self-test" value={selfTest.pass + '/' + selfTest.total} accent={selfTest.fail === 0 ? 'good' : 'bad'} />
          <Stat label="Societies clean" value={cleanSocs + '/' + Object.keys(audits).length} accent={cleanSocs === Object.keys(audits).length ? 'good' : 'bad'} />
          <Stat label="ID issues" value={totalIssues} accent={totalIssues === 0 ? 'good' : 'bad'} />
          <Stat label="Validators" value="5 ID kinds" accent="info" />
        </div>

        <div style={{ marginBottom:18 }}>
          <div className="ff-mono upper" style={{ fontSize:10, color:'var(--ink-3)', letterSpacing:'.08em', marginBottom:8 }}>What this catches</div>
          <div style={{ fontSize:13, color:'var(--ink-2)', lineHeight:1.55, maxWidth:780 }}>
            Field-position audits don't catch a malformed ISWC sitting at the right byte offset. These rules verify the
            <em> content</em> of identifiers: ISWC mod-10 check digits (ISO 15707), IPI Name 11-digit mod-101 check
            (CISAC IPI), IPI Base I-prefix + check, ISRC format CC-XXX-YY-NNNNN (ISO 3901), ISNI mod-11-2 check (ISO 27729),
            and submitter work-number length/charset.
          </div>
        </div>

        <Block title="Self-test (known-good and known-bad inputs)">
          <div style={{ border:'1px solid var(--rule)' }}>
            {selfTest.results.map((r, i) => (
              <div key={i} className="ff-mono" style={{
                display:'grid', gridTemplateColumns:'24px 1fr 200px 1fr',
                gap:10, padding:'8px 12px', fontSize:11,
                borderTop: i === 0 ? 0 : '1px solid var(--rule)',
                background: r.ok ? 'transparent' : 'color-mix(in oklch, var(--bad, #b94a4a) 6%, transparent)',
              }}>
                <span style={{ color: r.ok ? 'var(--ok, #1f8a4f)' : 'var(--bad, #b94a4a)', fontWeight:600 }}>{r.ok ? '✓' : '✗'}</span>
                <span>{r.label}</span>
                <span style={{ color:'var(--ink-3)', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{r.input || '(empty)'}</span>
                <span style={{ color:'var(--ink-3)' }}>{r.reason}</span>
              </div>
            ))}
          </div>
        </Block>

        <Block title="Per-society ID audit (NWR + SPU + SWR + PER reference build, v3.1)">
          <div style={{ border:'1px solid var(--rule)' }}>
            {Object.entries(audits).map(([soc, a], i) => (
              <div key={soc} className="ff-mono" style={{
                display:'grid', gridTemplateColumns:'120px 1fr 1fr 1fr 1fr 80px',
                gap:14, padding:'10px 14px', fontSize:11,
                borderTop: i === 0 ? 0 : '1px solid var(--rule)',
                background:'var(--paper)',
              }}>
                <span style={{ fontWeight:600 }}>{soc}</span>
                <span>SWN {a.stats.swn.ok}/{a.stats.swn.checked}</span>
                <span>ISWC {a.stats.iswc.ok}/{a.stats.iswc.checked}</span>
                <span>IPI {a.stats.ipiName.ok}/{a.stats.ipiName.checked}</span>
                <span style={{ color:'var(--ink-3)' }}>{a.issues.length === 0 ? 'no warnings' : a.issues.length + ' warnings'}</span>
                <span className="upper" style={{ color: a.ok ? 'var(--ok, #1f8a4f)' : '#c9871a', fontWeight:600, letterSpacing:'.08em' }}>
                  {a.ok ? '✓ clean' : 'review'}
                </span>
              </div>
            ))}
          </div>
        </Block>
      </div>
    );
  }

  // ──────────────────────────────────────────────────────────────────────
  // SUB-SECTION: Test-env submission flow
  // ──────────────────────────────────────────────────────────────────────
  function TestEnvSection() {
    const [matrix, setMatrix] = useState(null);
    const [selectedCycle, setSelectedCycle] = useState(null);

    useEffect(() => {
      if (!window.CwrTestEnv) return;
      const t = setTimeout(() => setMatrix(window.CwrTestEnv.runMatrix()), 30);
      return () => clearTimeout(t);
    }, []);

    if (!window.CwrTestEnv) return <div style={{padding:40,color:'var(--ink-3)'}}>Test-env module not loaded.</div>;
    if (!matrix) return <div style={{padding:80,textAlign:'center',color:'var(--ink-3)'}} className="ff-mono upper">running test-env cycles across all societies…</div>;

    const bySoc = {};
    for (const c of matrix.cycles) {
      if (!bySoc[c.society]) bySoc[c.society] = [];
      bySoc[c.society].push(c);
    }

    return (
      <div>
        <div style={{ display:'grid', gridTemplateColumns:'repeat(4, 1fr)', gap:1, background:'var(--rule)', border:'1px solid var(--rule)', marginBottom:24 }}>
          <Stat label="Cycles run" value={matrix.total} />
          <Stat label="AS (accepted)" value={matrix.accepted} accent="good" />
          <Stat label="AR (warn)" value={matrix.withWarnings} accent={matrix.withWarnings > 0 ? 'info' : 'good'} />
          <Stat label="RJ (rejected)" value={matrix.rejected} accent={matrix.rejected === 0 ? 'good' : 'bad'} />
        </div>

        <div style={{ marginBottom:18 }}>
          <div className="ff-mono upper" style={{ fontSize:10, color:'var(--ink-3)', letterSpacing:'.08em', marginBottom:8 }}>End-to-end cycle</div>
          <div style={{ fontSize:13, color:'var(--ink-2)', lineHeight:1.55, maxWidth:820 }}>
            For every society × supported version, we run a full submission cycle: <strong>build</strong> a reference NWR
            transmission, <strong>byte-diff audit</strong> against the society layout, <strong>identifier validation</strong>
            (ISWC/IPI/ISRC/ISNI), <strong>submit</strong> via the configured transport, <strong>receive</strong> a synthetic
            ACK, and <strong>reconcile</strong>. Production needs real credentials and the actual society endpoint;
            the simulator exercises the full pipeline so issues surface here, not after a real-world rejection.
          </div>
        </div>

        <div style={{ border:'1px solid var(--rule)' }}>
          {Object.entries(bySoc).map(([soc, cycles], i) => {
            const cfg = window.CwrTestEnv.CONFIGS[soc];
            const allAS = cycles.every(c => c.status === 'accepted');
            return (
              <div key={soc} style={{ borderTop: i === 0 ? 0 : '1px solid var(--rule)', background:'var(--paper)', padding:'14px 18px' }}>
                <div style={{ display:'grid', gridTemplateColumns:'140px 90px 1fr 130px', gap:14, alignItems:'baseline', marginBottom:8 }}>
                  <div className="ff-mono" style={{ fontSize:13, fontWeight:600 }}>{cfg.society}</div>
                  <div className="ff-mono" style={{ fontSize:10, color:'var(--ink-3)' }}>CISAC {cfg.cisac}</div>
                  <div className="ff-mono" style={{ fontSize:11, color:'var(--ink-3)' }}>
                    {cfg.transport.toUpperCase()} · {cfg.host} · ACK {cfg.ackTiming}
                  </div>
                  <div className="ff-mono upper" style={{ fontSize:10, fontWeight:600, letterSpacing:'.08em', color: allAS ? 'var(--ok, #1f8a4f)' : '#c9871a', textAlign:'right' }}>
                    {allAS ? '✓ all accepted' : cycles.filter(c => c.status === 'accepted').length + '/' + cycles.length + ' AS'}
                  </div>
                </div>
                <div style={{ display:'flex', gap:6, flexWrap:'wrap' }}>
                  {cycles.map((c, ci) => (
                    <button key={ci}
                      onClick={() => setSelectedCycle(selectedCycle && selectedCycle.cycleId === c.cycleId ? null : c)}
                      className="ff-mono"
                      style={{
                        padding:'6px 10px', fontSize:11, border:'1px solid var(--rule)',
                        background: c.status === 'accepted' ? 'color-mix(in oklch, var(--ok, #1f8a4f) 8%, var(--paper))' :
                                    c.status === 'accepted-with-warnings' ? 'color-mix(in oklch, #c9871a 8%, var(--paper))' :
                                    'color-mix(in oklch, var(--bad, #b94a4a) 8%, var(--paper))',
                        cursor:'pointer',
                        outline: selectedCycle && selectedCycle.cycleId === c.cycleId ? '2px solid var(--ink)' : 'none',
                      }}>
                      v{c.version} · {c.ackType} · {c.fileRecords}rec
                    </button>
                  ))}
                </div>
              </div>
            );
          })}
        </div>

        {selectedCycle && (
          <div style={{ marginTop:24, border:'1px solid var(--rule)', padding:'14px 18px', background:'var(--paper)' }}>
            <div className="ff-mono upper" style={{ fontSize:10, color:'var(--ink-3)', letterSpacing:'.08em', marginBottom:10 }}>
              Cycle {selectedCycle.cycleId} · {selectedCycle.society} v{selectedCycle.version} · {selectedCycle.filename}
            </div>
            <div style={{ border:'1px solid var(--rule)' }}>
              {selectedCycle.steps.map((s, si) => (
                <div key={si} className="ff-mono" style={{
                  display:'grid', gridTemplateColumns:'24px 240px 100px 1fr',
                  gap:10, padding:'8px 12px', fontSize:11,
                  borderTop: si === 0 ? 0 : '1px solid var(--rule)',
                }}>
                  <span style={{ color: s.ok ? 'var(--ok, #1f8a4f)' : 'var(--bad, #b94a4a)', fontWeight:600 }}>{s.ok ? '✓' : '✗'}</span>
                  <span>{s.step}</span>
                  <span style={{ color:'var(--ink-3)', textAlign:'right' }}>{s.durationMs ? s.durationMs.toFixed(1) + ' ms' : '—'}</span>
                  <span style={{ color:'var(--ink-2)' }}>{s.detail}</span>
                </div>
              ))}
            </div>
            <div className="ff-mono" style={{ fontSize:11, color:'var(--ink-3)', marginTop:10 }}>
              Total elapsed: {selectedCycle.totalMs ? selectedCycle.totalMs.toFixed(1) : 0} ms (simulated)
            </div>
          </div>
        )}
      </div>
    );
  }

  function Stat({ label, value, accent, small }) {
    const color = accent === 'good' ? 'var(--ok, #1f8a4f)' : accent === 'bad' ? 'var(--bad, #b94a4a)' : accent === 'info' ? '#1f6abd' : 'var(--ink)';
    return (
      <div style={{ background:'var(--paper)', padding: small ? '14px 16px' : '20px 22px' }}>
        <div className="ff-mono upper" style={{ fontSize:10, color:'var(--ink-3)', letterSpacing:'.08em' }}>{label}</div>
        <div style={{ fontSize: small ? 14 : 32, marginTop:6, fontWeight:300, color, fontVariantNumeric:'tabular-nums', whiteSpace: small ? 'nowrap' : 'normal' }}>{value}</div>
      </div>
    );
  }

  function Block({ title, right, children }) {
    return (
      <div style={{ marginBottom:28 }}>
        <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:10 }}>
          <h3 className="ff-mono upper" style={{ fontSize:11, letterSpacing:'.10em', color:'var(--ink-2)', margin:0, fontWeight:600 }}>{title}</h3>
          {right}
        </div>
        {children}
      </div>
    );
  }

  window.CwrComplianceTab = CwrComplianceTab;
})();
