/* ============================================================
   FLOWSHIELD — Normativa (compliance frameworks)
   ============================================================ */
function FrameworkCard({ f, onClick, active }) {
  const ref = useRefL(null);
  const onMove = (e)=>{ const el=ref.current; if(!el)return; const r=el.getBoundingClientRect(); el.style.setProperty('--mx',((e.clientX-r.left)/r.width)*100+'%'); el.style.setProperty('--my',((e.clientY-r.top)/r.height)*100+'%'); };
  const col = f.score>=80?'var(--ok)':f.score>=70?'var(--amber)':'var(--red)';
  return (
    <div ref={ref} onMouseMove={onMove} onClick={onClick} className={'tool-card theme-'+f.color} style={{ flexDirection:'column', borderColor: active?'var(--acc)':'var(--line)', boxShadow: active?'0 0 0 1px var(--acc),0 14px 40px -22px var(--acc-glow)':'none' }}>
      <span className="bracket tl" /><span className="bracket tr" /><span className="bracket bl" /><span className="bracket br" />
      <div style={{ display:'flex', justifyContent:'space-between', width:'100%', alignItems:'flex-start' }}>
        <div className="tool-ico"><Icon name={f.icon} size={24} /></div>
        <div style={{ textAlign:'right' }}>
          <div className="disp" style={{ fontSize:26, fontWeight:700, color:col, lineHeight:1 }}>{f.score}%</div>
          <div className="mono" style={{ fontSize:9, color:'var(--txt-mute)', marginTop:3 }}>CUMPLIMIENTO</div>
        </div>
      </div>
      <div className="tool-title" style={{ marginTop:14, fontSize:15 }}>{f.name}</div>
      <div className="tool-desc" style={{ marginBottom:14 }}>{f.full}</div>
      <div className="bar" style={{ width:'100%' }}><span style={{ width:f.score+'%', background:col, boxShadow:`0 0 8px ${col}` }} /></div>
      <div style={{ display:'flex', justifyContent:'space-between', width:'100%', marginTop:12 }}>
        <span className="mono" style={{ fontSize:10.5, color:'var(--ok)' }}>✓ {f.met} cumple</span>
        <span className="mono" style={{ fontSize:10.5, color:'var(--amber)' }}>◐ {f.partial} parcial</span>
        <span className="mono" style={{ fontSize:10.5, color:'var(--red)' }}>✕ {f.gap} brecha</span>
      </div>
    </div>
  );
}

function _compHost(t) {
  try { const u = (t||'').includes('://') ? new URL(t) : new URL('https://'+t); return u.hostname || t; }
  catch { return t || '—'; }
}

// Real per-site card (reuses the tool-card chrome; honest data from /posture).
function SiteCard({ s, onClick, active }) {
  const ref = useRefL(null);
  const onMove = (e)=>{ const el=ref.current; if(!el)return; const r=el.getBoundingClientRect(); el.style.setProperty('--mx',((e.clientX-r.left)/r.width)*100+'%'); el.style.setProperty('--my',((e.clientY-r.top)/r.height)*100+'%'); };
  const col = s.score>=80?'var(--ok)':s.score>=60?'var(--amber)':'var(--red)';
  return (
    <div ref={ref} onMouseMove={onMove} onClick={onClick} className="tool-card theme-amber" style={{ flexDirection:'column', borderColor: active?'var(--acc)':'var(--line)', boxShadow: active?'0 0 0 1px var(--acc),0 14px 40px -22px var(--acc-glow)':'none' }}>
      <span className="bracket tl" /><span className="bracket tr" /><span className="bracket bl" /><span className="bracket br" />
      <div style={{ display:'flex', justifyContent:'space-between', width:'100%', alignItems:'flex-start' }}>
        <div className="tool-ico"><Icon name="globe" size={24} /></div>
        <div style={{ textAlign:'right' }}>
          <div className="disp" style={{ fontSize:26, fontWeight:700, color:col, lineHeight:1 }}>{s.score}%</div>
          <div className="mono" style={{ fontSize:9, color:'var(--txt-mute)', marginTop:3 }}>CUMPLIMIENTO</div>
        </div>
      </div>
      <div className="tool-title" style={{ marginTop:14, fontSize:15, wordBreak:'break-all' }}>{_compHost(s.target)}</div>
      <div className="tool-desc" style={{ marginBottom:14 }}>{s.rating || '—'}{s.jurisdiction?` · ${s.jurisdiction}`:''}</div>
      <div className="bar" style={{ width:'100%' }}><span style={{ width:s.score+'%', background:col, boxShadow:`0 0 8px ${col}` }} /></div>
      <div style={{ display:'flex', justifyContent:'space-between', width:'100%', marginTop:12 }}>
        <span className="mono" style={{ fontSize:10.5, color:'var(--txt-mute)' }}>{window.rptDate?window.rptDate(s.date):s.date}</span>
        <span className="mono" style={{ fontSize:10.5, color: s.gaps?'var(--red)':'var(--ok)' }}>{s.gaps?`${s.gaps} brecha${s.gaps===1?'':'s'}`:'sin brechas'}</span>
      </div>
    </div>
  );
}

function Normativa() {
  const [mode, setMode] = useStateL('panel');
  const [post, setPost] = useStateL(null);      // null = cargando
  const [sel, setSel] = useStateL(null);         // sitio seleccionado
  const [detail, setDetail] = useStateL(null);   // {groups,...} | 'na' | null
  const [gaps, setGaps] = useStateL([]);          // brechas (findings) del sitio

  const load = () => {
    window.fsApi('/api/compliance/posture', { method:'GET' })
      .then(d => { setPost(d); if (d.sites && d.sites.length && !sel) setSel(d.sites[0]); })
      .catch(() => setPost({ sites:[], score:0, counts:{}, total_scans:0 }));
  };
  useEffectL(() => { if (mode==='panel') load(); }, [mode]);

  // Cargar detalle (checks reales) + brechas del sitio seleccionado.
  useEffectL(() => {
    if (!sel) { setDetail(null); setGaps([]); return; }
    if (sel.scan_id) {
      window.fsApi('/api/compliance/scans/'+sel.scan_id, { method:'GET' })
        .then(d => setDetail(d)).catch(() => setDetail('na'));
    } else { setDetail('na'); }
    // brechas reales del objetivo desde el store de hallazgos
    window.fsApi('/api/results/findings', { method:'GET' })
      .then(d => setGaps(((d&&d.findings)||[]).filter(f => f.module==='compliance' && f.target && _compHost(f.target)===_compHost(sel.target))))
      .catch(() => setGaps([]));
  }, [sel && sel.scan_id, sel && sel.target]);

  if (mode === 'scan') return <ComplianceScanner onBack={()=>setMode('panel')} />;

  const sites = (post && post.sites) || [];
  const avg = post ? post.score : 0;
  const counts = (post && post.counts) || { pass:0, partial:0, fail:0 };
  const hasVerdicts = (counts.pass||0)+(counts.partial||0)+(counts.fail||0) > 0;
  const totalGaps = sites.reduce((a,s)=>a+(s.gaps||0),0);
  const empty = post && post.total_scans === 0;

  return (
    <div className="enter theme-amber">
      <PageHeader title="Normativa y cumplimiento" crumb="NORMATIVA / CUMPLIMIENTO"
        sub="Postura real de cumplimiento por sitio analizado: RGPD/LOPDGDD, cookies, CMP, terceros y avisos legales detectados en vivo."
        right={<Btn variant="primary" icon="bolt" className="theme-amber" onClick={()=>setMode('scan')} glitch>Nuevo scan web</Btn>} />

      {empty && <DemoBanner what="análisis de cumplimiento" />}

      {/* global posture */}
      <div className="panel" style={{ padding:24, marginBottom:30, display:'flex', gap:30, alignItems:'center', flexWrap:'wrap', background:'linear-gradient(110deg,var(--bg-panel-2),var(--bg-panel))' }}>
        <Gauge value={avg} size={130} color="var(--amber)" sub="GLOBAL" />
        <div style={{ flex:1, minWidth:260 }}>
          <div className="eyebrow" style={{ marginBottom:10 }}>Postura de cumplimiento</div>
          <div style={{ fontSize:14, color:'var(--txt)', lineHeight:1.6, marginBottom:16 }}>
            {sites.length
              ? <>Cumplimiento medio del <strong style={{ color:'var(--txt-hi)' }}>{avg}%</strong> sobre <strong style={{ color:'var(--txt-hi)' }}>{sites.length}</strong> sitio(s) analizado(s){totalGaps?<> · <strong style={{ color:'var(--red)' }}>{totalGaps} brecha(s)</strong> abiertas</>:null}.</>
              : <>Aún no hay análisis de cumplimiento. Lanza un <strong style={{ color:'var(--txt-hi)' }}>Nuevo scan web</strong> y la postura aparecerá aquí.</>}
          </div>
          {hasVerdicts && (
            <div style={{ display:'flex', gap:10, flexWrap:'wrap' }}>
              <span className="badge sev-ok"><Icon name="check" size={11} />{counts.pass} cumplen</span>
              <span className="badge sev-med"><Icon name="alert" size={11} />{counts.partial} parciales</span>
              <span className="badge sev-crit"><Icon name="x" size={11} />{counts.fail} brechas</span>
            </div>
          )}
        </div>
      </div>

      {sites.length > 0 && <>
        <div className="eyebrow">Sitios analizados</div>
        <div style={{ display:'grid', gridTemplateColumns:'repeat(auto-fill,minmax(310px,1fr))', gap:14, marginBottom:32 }}>
          {sites.map((s,i) => <SiteCard key={s.scan_id||s.target||i} s={s} active={sel && sel.target===s.target} onClick={()=>setSel(s)} />)}
        </div>
      </>}

      {/* detail */}
      {sel && (
      <div className="panel theme-amber" style={{ overflow:'hidden' }}>
        <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', flexWrap:'wrap', gap:14, padding:'18px 22px', borderBottom:'1px solid var(--line)', background:'var(--bg-panel-2)' }}>
          <div style={{ display:'flex', gap:14, alignItems:'center' }}>
            <div className="tool-ico"><Icon name="globe" size={22} /></div>
            <div>
              <div className="disp" style={{ fontSize:17, fontWeight:700, color:'var(--txt-hi)' }}>{_compHost(sel.target)}</div>
              <div className="mono" style={{ fontSize:11, color:'var(--txt-mute)', marginTop:2 }}>{sel.jurisdiction||sel.framework} · {sel.rating||'—'} · {sel.score}%</div>
            </div>
          </div>
          {detail && detail!=='na' && detail.meta && detail.meta.screenshot_pre &&
            <Btn variant="ghost" size="sm" icon="download" onClick={()=>window.open('/api/compliance/screenshot/'+sel.scan_id+'/pre','_blank')}>Exportar evidencias</Btn>}
        </div>

        {detail && detail!=='na' && (detail.groups||[]).map(g => (
          <div key={g.g}>
            <div className="mono upper" style={{ fontSize:10, color:'var(--amber)', letterSpacing:'.14em', padding:'12px 22px 6px', background:'var(--bg-panel-2)' }}>{g.g}</div>
            {(g.checks||[]).map(c => (
              <div key={c.id} style={{ display:'flex', alignItems:'center', gap:14, padding:'12px 22px', borderTop:'1px solid var(--line)' }}>
                <CompVerdict v={c.verdict} />
                <div style={{ flex:1, minWidth:0 }}>
                  <div style={{ fontSize:13, color:'var(--txt-hi)' }}>{c.t}</div>
                  {c.note && <div style={{ fontSize:11.5, color:'var(--txt-dim)', marginTop:2 }}>{c.note}</div>}
                </div>
              </div>
            ))}
          </div>
        ))}

        {detail === 'na' && (
          <div style={{ padding:'18px 22px' }}>
            <div style={{ fontSize:12.5, color:'var(--txt-dim)', marginBottom: gaps.length?14:0 }}>
              El detalle por comprobación no está guardado para este análisis (escaneo anterior). Vuelve a lanzar el scan para ver el desglose completo.{gaps.length?' Brechas registradas:':''}
            </div>
            {gaps.map((f,i) => (
              <div key={f.id||i} style={{ display:'flex', alignItems:'center', gap:14, padding:'12px 0', borderTop:i?'1px solid var(--line)':'none' }}>
                <Sev level={f.sev} />
                <div style={{ flex:1, minWidth:0 }}><div style={{ fontSize:13, color:'var(--txt-hi)' }}>{f.name}</div></div>
              </div>
            ))}
          </div>
        )}
      </div>
      )}
    </div>
  );
}

/* ============================================================
   Compliance Scanner — escaneo de cumplimiento web
   ============================================================ */
// Scope groups for the selection panel. The real verdicts/notes come from the
// live Playwright engine; these labels + check counts mirror what it returns.
const COMP_GROUPS = [
  { g:'RGPD / LOPDGDD', n:4 },
  { g:'Cookies', n:5 },
  { g:'Políticas y avisos legales', n:4 },
  { g:'Seguridad técnica', n:5 },
];
// UI jurisdiction label -> backend jurisdiction code.
const REGION_MAP = {
  'UE · España (RGPD + LOPDGDD)':'ES',
  'UE · General (RGPD)':'EU',
  'Reino Unido (UK-GDPR)':'UK',
  'EE.UU. · California (CCPA/CPRA)':'US-CA',
  'Global (best practices)':'GLOBAL',
};

function CompVerdict({ v }) {
  const m = { pass:{c:'var(--ok)',t:'Cumple',i:'check'}, partial:{c:'var(--amber)',t:'Parcial',i:'alert'}, fail:{c:'var(--red)',t:'Incumple',i:'x'} }[v];
  return <span className="badge" style={{ color:m.c, borderColor:`color-mix(in srgb,${m.c} 38%,transparent)`, background:`color-mix(in srgb,${m.c} 12%,transparent)` }}><Icon name={m.i} size={11} />{m.t}</span>;
}

function ComplianceScanner({ onBack }) {
  const [url, setUrl] = useStateL('https://www.flowia.es');
  const [region, setRegion] = useStateL('UE · España (RGPD + LOPDGDD)');
  const [groups, setGroups] = useStateL(() => COMP_GROUPS.map(g=>g.g));
  const [opts, setOpts] = useStateL({ crawl:true, subpages:false, screenshot:true });
  const [phase, setPhase] = useStateL('idle'); // idle | running | done
  const [lines, setLines] = useStateL([]);
  const [prog, setProg] = useStateL(0);
  const [result, setResult] = useStateL(null);
  const termRef = useRefL(null);

  const toggleGroup = (g) => setGroups(s => s.includes(g) ? s.filter(x=>x!==g) : [...s, g]);

  const scan = async () => {
    if (!groups.length || phase==='running') return;
    setPhase('running'); setResult(null); setProg(8);
    setLines([
      { t:'> compliance-engine · Playwright headless', c:'acc' },
      { t:`> objetivo: ${url}`, c:'dim' },
      { t:`> jurisdicción: ${region}`, c:'dim' },
      { t:'[*] lanzando navegador headless (Chromium)…', c:'' },
      { t:'[*] cargando página e interceptando red…', c:'' },
      { t:'[*] capturando cookies previas al consentimiento…', c:'' },
    ]);
    let p=8; const creep=setInterval(()=>{ p=Math.min(p+4,88); setProg(p); }, 350);
    try {
      const data = await window.fsApi('/api/compliance/scan', { body:{
        url, jurisdiction: REGION_MAP[region] || 'EU',
        interact_consent: true, screenshot: opts.screenshot, groups,
        max_pages: opts.subpages ? 6 : 0,
      }});
      clearInterval(creep);
      const raw = data.raw || {}; const meta = raw.meta || {};
      const real = [];
      real.push(meta.cmp ? { t:`[+] CMP detectado: ${meta.cmp}`, c:'ok' }
                         : { t:'[!] sin banner de consentimiento detectado', c:'warn' });
      real.push(meta.non_essential_pre
        ? { t:`[!] ${meta.non_essential_pre} cookie(s) no esenciales antes de aceptar`, c:'warn' }
        : { t:'[+] sin cookies no esenciales en la carga inicial', c:'ok' });
      real.push((meta.trackers_pre && meta.trackers_pre.length)
        ? { t:`[!] terceros sin consentimiento: ${meta.trackers_pre.join(', ')}`, c:'err' }
        : { t:'[+] sin terceros antes del consentimiento', c:'ok' });
      if (meta.cmp_clicked)
        real.push({ t:`[*] 'Aceptar' pulsado · cookies ${meta.cookies_pre}→${meta.cookies_post} · terceros ${(meta.third_parties_pre||[]).length}→${(meta.third_parties_post||[]).length}`, c:'' });
      if (meta.pages_scanned > 1) real.push({ t:`[*] crawl: ${meta.pages_scanned} páginas analizadas · ${meta.forms_personal||0} formulario(s) con datos personales`, c:'' });
      if (meta.screenshot_pre) real.push({ t:'[*] evidencias (screenshots) capturadas', c:'' });
      real.push({ t:`> evaluación completada · cumplimiento ${raw.compliance_score}%`, c:'ok' });
      setLines(l => [...l, ...real]);
      setProg(100); setResult(raw); setPhase('done');
    } catch (e) {
      clearInterval(creep);
      setLines(l => [...l, { t:`[x] error: ${e.message || e}`, c:'err' }]);
      setProg(100); setPhase('idle');
    }
  };
  useEffectL(()=>{ if(termRef.current) termRef.current.scrollTop=termRef.current.scrollHeight; }, [lines]);

  const resultGroups = result ? (result.groups||[]).filter(g=>groups.includes(g.g)) : [];
  const activeChecks = resultGroups.flatMap(g=>g.checks);
  const counts = activeChecks.reduce((a,c)=>{a[c.verdict]=(a[c.verdict]||0)+1;return a;},{});
  const score = result ? result.compliance_score
                       : (activeChecks.length ? Math.round(((counts.pass||0)+(counts.partial||0)*0.5)/activeChecks.length*100) : 0);
  const exportEvidence = () => {
    if (result && result.scan_id && result.meta && result.meta.screenshot_pre)
      window.open('/api/compliance/screenshot/'+result.scan_id+'/pre', '_blank');
  };
  const [reporting, setReporting] = useStateL(false);
  const downloadReport = async () => {
    if (!result || reporting) return;
    setReporting(true);
    try {
      await window.fsDownloadPdf('/api/report/compliance', result);
    } catch (e) {
      setLines(l => [...l, { t:'[x] no se pudo generar el informe: ' + (e.message || e), c:'err' }]);
    } finally {
      setReporting(false);
    }
  };

  return (
    <div className="enter theme-amber">
      <PageHeader title="Nuevo scan · Cumplimiento web" crumb="NORMATIVA / CUMPLIMIENTO / NUEVO SCAN" />
      <button onClick={onBack} style={{ display:'inline-flex', alignItems:'center', gap:7, background:'none', border:'none', color:'var(--txt-dim)', cursor:'pointer', fontSize:12.5, marginBottom:18, fontFamily:'var(--font-mono)' }}>← volver al panel</button>

      <div style={{ display:'grid', gridTemplateColumns:'1fr 1.1fr', gap:18, alignItems:'start' }}>
        {/* config */}
        <div className="panel" style={{ padding:22 }}>
          <div className="eyebrow" style={{ marginBottom:16 }}>Objetivo y alcance</div>
          <label className="mono" style={{ fontSize:11, color:'var(--txt-dim)', display:'block', marginBottom:7 }}>URL DEL SITIO WEB</label>
          <div className="field" style={{ marginBottom:16 }}>
            <Icon name="globe" size={16} style={{ position:'absolute', left:13, top:13, color:'var(--amber)' }} />
            <input className="input input-prefix" value={url} onChange={e=>setUrl(e.target.value)} disabled={phase==='running'} />
          </div>

          <label className="mono" style={{ fontSize:11, color:'var(--txt-dim)', display:'block', marginBottom:7 }}>JURISDICCIÓN</label>
          <select className="comp-sel" value={region} onChange={e=>setRegion(e.target.value)} disabled={phase==='running'} style={{ marginBottom:18 }}>
            <option>UE · España (RGPD + LOPDGDD)</option><option>UE · General (RGPD)</option><option>Reino Unido (UK-GDPR)</option><option>EE.UU. · California (CCPA/CPRA)</option><option>Global (best practices)</option>
          </select>

          <label className="mono" style={{ fontSize:11, color:'var(--txt-dim)', display:'block', marginBottom:9 }}>ÁMBITOS A EVALUAR</label>
          <div style={{ display:'grid', gap:9, marginBottom:18 }}>
            {COMP_GROUPS.map(g => (
              <button key={g.g} onClick={()=>toggleGroup(g.g)} disabled={phase==='running'} style={{ display:'flex', alignItems:'center', justifyContent:'space-between', background:'none', border:'none', cursor:'pointer', padding:0, opacity: phase==='running'?0.6:1 }}>
                <span style={{ display:'flex', alignItems:'center', gap:10 }}>
                  <span style={{ width:17, height:17, borderRadius:5, border:'1.5px solid '+(groups.includes(g.g)?'var(--amber)':'var(--line-bright)'), background: groups.includes(g.g)?'var(--amber)':'var(--bg-void)', display:'grid', placeItems:'center', boxShadow: groups.includes(g.g)?'0 0 8px var(--amber-glow)':'none' }}>{groups.includes(g.g) && <Icon name="check" size={11} style={{ color:'#04110D' }} />}</span>
                  <span style={{ fontSize:13, color: groups.includes(g.g)?'var(--txt-hi)':'var(--txt-dim)' }}>{g.g}</span>
                </span>
                <span className="mono" style={{ fontSize:10.5, color:'var(--txt-mute)' }}>{g.n} checks</span>
              </button>
            ))}
          </div>

          <div style={{ display:'grid', gap:10, marginBottom:20, paddingTop:16, borderTop:'1px solid var(--line)' }}>
            <Toggle label="Rastrear subpáginas enlazadas" on={opts.subpages} onClick={()=>setOpts(o=>({...o,subpages:!o.subpages}))} disabled={phase==='running'} />
            <Toggle label="Capturar evidencias (screenshots)" on={opts.screenshot} onClick={()=>setOpts(o=>({...o,screenshot:!o.screenshot}))} disabled={phase==='running'} />
          </div>

          {phase==='done'
            ? <div style={{ display:'flex', gap:10 }}><Btn variant="ghost" icon="play" onClick={scan} style={{ flex:1 }}>Re-escanear</Btn><Btn variant="solid" icon="report" className="theme-amber" onClick={downloadReport} style={{ flex:1 }}>{reporting ? 'Generando…' : 'Informe PDF'}</Btn></div>
            : <Btn variant="solid" size="block" icon={phase==='running'?null:'bolt'} className="theme-amber" onClick={scan} glitch style={{ opacity: groups.length?1:0.5 }}>{phase==='running'?'ESCANEANDO…':'ANALIZAR CUMPLIMIENTO'}</Btn>}
        </div>

        {/* terminal + score */}
        <div style={{ display:'flex', flexDirection:'column', gap:18 }}>
          <div className="panel" style={{ padding:0, overflow:'hidden' }}>
            <div style={{ display:'flex', alignItems:'center', gap:8, padding:'10px 14px', borderBottom:'1px solid var(--line)', background:'var(--bg-panel-2)' }}>
              <span className="dot" style={{ background:'#FF5F57', width:10, height:10 }} /><span className="dot" style={{ background:'#FEBC2E', width:10, height:10 }} /><span className="dot" style={{ background:'#28C840', width:10, height:10 }} />
              <span className="mono" style={{ fontSize:11, color:'var(--txt-mute)', marginLeft:8 }}>flowshield@normativa: ~/compliance</span>
            </div>
            <div ref={termRef} className="terminal" style={{ height:206, borderRadius:0, border:'none' }}>
              {phase==='idle' && <div className="t-dim">// selecciona ámbitos y pulsa ANALIZAR CUMPLIMIENTO…<span className="cursor-blink" /></div>}
              {lines.map((l,i)=>l && <div key={i} className={'t-'+(l.c||'')} style={{ animation:'enter .2s forwards' }}>{l.t}</div>)}
              {phase==='running' && <div className="cursor-blink" />}
            </div>
            <div style={{ padding:'8px 14px', borderTop:'1px solid var(--line)' }}>
              <div className="bar"><span style={{ width:prog+'%' }} /></div>
            </div>
          </div>

          {phase==='done' && (
            <div className="panel enter" style={{ padding:20, display:'flex', gap:22, alignItems:'center', flexWrap:'wrap' }}>
              <Gauge value={score} size={112} color={score>=80?'var(--ok)':score>=60?'var(--amber)':'var(--red)'} sub="CUMPLIMIENTO" />
              <div style={{ flex:1, minWidth:200, display:'grid', gap:9 }}>
                <ResBar label="Cumple" v={counts.pass||0} total={activeChecks.length} color="var(--ok)" />
                <ResBar label="Parcial" v={counts.partial||0} total={activeChecks.length} color="var(--amber)" />
                <ResBar label="Incumple" v={counts.fail||0} total={activeChecks.length} color="var(--red)" />
              </div>
            </div>
          )}
        </div>
      </div>

      {phase==='done' && (
        <div className="panel enter" style={{ overflow:'hidden', marginTop:18 }}>
          <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', padding:'16px 20px', borderBottom:'1px solid var(--line)', flexWrap:'wrap', gap:12 }}>
            <div className="eyebrow" style={{ margin:0 }}>Resultados por comprobación · {url}</div>
            <Btn variant="ghost" size="sm" icon="download" onClick={exportEvidence}>Exportar evidencias</Btn>
          </div>
          {resultGroups.map(g => (
            <div key={g.g}>
              <div className="mono upper" style={{ fontSize:10, color:'var(--amber)', letterSpacing:'.14em', padding:'12px 20px 6px', background:'var(--bg-panel-2)' }}>{g.g}</div>
              {g.checks.map(c => (
                <div key={c.id} style={{ display:'flex', alignItems:'center', gap:14, padding:'12px 20px', borderTop:'1px solid var(--line)' }}>
                  <CompVerdict v={c.verdict} />
                  <div style={{ flex:1, minWidth:0 }}>
                    <div style={{ fontSize:13, color:'var(--txt-hi)' }}>{c.t}</div>
                    {c.note && <div style={{ fontSize:11.5, color:'var(--txt-dim)', marginTop:2 }}>{c.note}</div>}
                  </div>
                </div>
              ))}
            </div>
          ))}
        </div>
      )}

      <style>{`
        .comp-sel{width:100%;font-family:var(--font-mono);font-size:12.5px;color:var(--txt-hi);background:var(--bg-void);border:1px solid var(--line-bright);border-radius:6px;padding:11px 13px;outline:none;cursor:pointer;transition:border-color .2s}
        .comp-sel:focus,.comp-sel:hover{border-color:var(--amber)}
      `}</style>
    </div>
  );
}

Object.assign(window, { Normativa, ComplianceScanner });