// Reports & Analytics module — KPIs · charts · predefined reports · compliance
const { useState: _rp_useState, useMemo: _rp_useMemo } = React;

// ─── Mock data ───────────────────────────────────────────

const KPIS = [
  { id: 'head',  label: 'Headcount total',         value: '824',   delta: '+18',  deltaType: 'up',   foot: 'colaboradores activos',
    spark: [792, 798, 804, 808, 815, 818, 819, 822, 821, 823, 824, 824], tone: 'navy' },
  { id: 'rot',   label: 'Tasa de rotación',        value: '8.4%',  delta: '−0.7 pts', deltaType: 'down', foot: 'vs. 9.1% trimestre anterior',
    spark: [9.6, 9.4, 9.2, 9.1, 8.9, 8.8, 8.7, 8.5, 8.6, 8.5, 8.4, 8.4], tone: 'green' },
  { id: 'aus',   label: 'Ausentismo',              value: '1,247', delta: '+86 h',    deltaType: 'up',   foot: 'horas perdidas en el período',
    spark: [980, 1020, 1080, 1110, 1080, 1140, 1200, 1180, 1220, 1240, 1260, 1247], tone: 'amber' },
  { id: 'trn',   label: 'Cumplimiento capacitación', value: '87%', delta: '+4 pts',   deltaType: 'up',   foot: 'plan formativo Atica',
    spark: [76, 78, 79, 81, 80, 82, 83, 84, 84, 85, 86, 87], tone: 'blue' },
  { id: 'sst',   label: 'Cumplimiento SST',        value: '92%',   delta: '+1 pt',    deltaType: 'up',   foot: 'exámenes al día · plan SG-SST',
    spark: [86, 87, 87, 88, 89, 89, 90, 90, 91, 91, 92, 92], tone: 'green' },
  { id: 'pay',   label: 'Costo de nómina',         value: '$1,342M', delta: '+2.1%', deltaType: 'up',   foot: 'estimado mensual · COP',
    spark: [1280, 1290, 1295, 1300, 1310, 1308, 1315, 1320, 1325, 1330, 1338, 1342], tone: 'navy' },
];

// Headcount by area (stacked by contract)
const HEADCOUNT_AREAS = [
  { area: 'Operaciones',      indefinido: 312, fijo: 78, aprendizaje: 14 },
  { area: 'Aprovechamiento',         indefinido: 142, fijo: 38, aprendizaje: 8 },
  { area: 'Calidad',         indefinido: 28,  fijo: 12, aprendizaje: 6 },
  { area: 'Mantenimiento',   indefinido: 36,  fijo: 8,  aprendizaje: 2 },
  { area: 'Recolección',    indefinido: 64,  fijo: 6,  aprendizaje: 0 },
  { area: 'Administración',  indefinido: 30,  fijo: 0,  aprendizaje: 8 },
];

const HEADCOUNT_LEGEND = [
  { key: 'indefinido',  label: 'Indefinido',  color: 'var(--navy-800)' },
  { key: 'fijo',        label: 'Fijo',        color: 'var(--blue-600)' },
  { key: 'aprendizaje', label: 'Aprendizaje', color: 'var(--amber-600)' },
];

// Ingresos / retiros por mes (jun 2025 → may 2026)
const HIRES_EXITS = [
  { m: 'Jun', hires: 14, exits: 8 },
  { m: 'Jul', hires: 18, exits: 11 },
  { m: 'Ago', hires: 12, exits: 7 },
  { m: 'Sep', hires: 22, exits: 9 },
  { m: 'Oct', hires: 17, exits: 10 },
  { m: 'Nov', hires: 9,  exits: 6 },
  { m: 'Dic', hires: 6,  exits: 4 },
  { m: 'Ene', hires: 28, exits: 12 },
  { m: 'Feb', hires: 24, exits: 14 },
  { m: 'Mar', hires: 19, exits: 8 },
  { m: 'Abr', hires: 21, exits: 11 },
  { m: 'May', hires: 12, exits: 7 },
];

// Recolección por tipo de contrato (donut)
const CONTRACT_DIST = [
  { label: 'Indefinido',   value: 612, color: 'var(--navy-800)' },
  { label: 'Fijo',         value: 142, color: 'var(--blue-600)' },
  { label: 'Aprendizaje',  value: 38,  color: 'var(--amber-600)' },
  { label: 'Obra o labor', value: 32,  color: 'var(--rose-600)' },
];

// Top 5 causas de ausencia
const ABSENCE_CAUSES = [
  { label: 'Incapacidad común',           hours: 412, tone: 'rose' },
  { label: 'Permiso personal',            hours: 286, tone: 'amber' },
  { label: 'Cita médica',                 hours: 218, tone: 'navy' },
  { label: 'Licencia maternidad/paternidad', hours: 198, tone: 'blue' },
  { label: 'Calamidad doméstica',         hours: 133, tone: 'navy' },
];

// Onboarding por mes
const ONBOARDING_TREND = [
  { m: 'Dic 25', completed: 5, inProgress: 1 },
  { m: 'Ene 26', completed: 22, inProgress: 6 },
  { m: 'Feb 26', completed: 18, inProgress: 6 },
  { m: 'Mar 26', completed: 15, inProgress: 4 },
  { m: 'Abr 26', completed: 12, inProgress: 9 },
  { m: 'May 26', completed: 4,  inProgress: 8 },
];

const PREDEFINED_REPORTS = [
  { id: 'r-01', name: 'Listado de colaboradores activos',  desc: 'Datos completos: cargo, área, sede, contrato, salario, jefe directo.', formats: ['xlsx', 'pdf'] },
  { id: 'r-02', name: 'Contratos por vencer (90 días)',    desc: 'Contratos a término fijo con alertas de acción requerida (renovación / cierre).', formats: ['xlsx'] },
  { id: 'r-03', name: 'Exámenes médicos vencidos',         desc: 'Colaborador, tipo de examen, fecha de vencimiento y días vencido.', formats: ['xlsx', 'pdf'] },
  { id: 'r-04', name: 'Cumplimiento de capacitaciones',    desc: 'Por área y cargo, con cursos pendientes y obligatorios.', formats: ['xlsx', 'pdf'] },
  { id: 'r-05', name: 'Dotación pendiente de entrega',     desc: 'Ítems con stock, colaboradores en espera y bloqueos por inventario.', formats: ['xlsx'] },
  { id: 'r-06', name: 'Movimientos de personal',           desc: 'Ingresos, retiros, cambios de cargo y traslados del período.', formats: ['xlsx'] },
  { id: 'r-07', name: 'Reporte de ausentismo',             desc: 'Horas y días por tipo de ausencia, área y colaborador.', formats: ['xlsx', 'pdf'] },
];

const COMPLIANCE = [
  { id: 'hd',  label: 'Habeas Data',                     status: 'ok',     desc: 'Política actualizada · 824 consentimientos al día (100%)',  cta: 'Ver registro' },
  { id: 'sst', label: 'SST · exámenes médicos',          status: 'warn',   desc: '3 exámenes vencidos requieren atención · 4 por vencer',     cta: 'Programar exámenes' },
  { id: 'doc', label: 'Documentos laborales',            status: 'ok',     desc: '98% de contratos firmados electrónicamente · 16 pendientes', cta: 'Ver pendientes' },
  { id: 'trn', label: 'Capacitaciones obligatorias',     status: 'crit',   desc: '12% sin completar plan mínimo · 96 colaboradores afectados', cta: 'Plan de remediación' },
  { id: 'pila', label: 'PILA · aportes de seguridad',    status: 'ok',     desc: 'Último aporte radicado · 30/04/2026 · sin novedades pendientes', cta: 'Ver historial' },
  { id: 'arl',  label: 'Reporte ARL accidentalidad',     status: 'ok',     desc: '6 eventos reportados · todos dentro de plazo legal',          cta: 'Ver casos' },
];

const STATUS_META_CMP = {
  ok:   { tone: 'green', label: 'Al día',     dot: 'var(--green-600)', icon: 'IconCheck' },
  warn: { tone: 'amber', label: 'Atención',    dot: 'var(--amber-600)', icon: 'IconAlert' },
  crit: { tone: 'rose',  label: 'Crítico',     dot: 'var(--rose-600)',  icon: 'IconAlert' },
};

// ─── Root ────────────────────────────────────────────────

const Reports = () => {
  const [period, setPeriod] = _rp_useState('trimestre');
  const [section, setSection] = _rp_useState('general');

  return (
    <div className="main" data-screen-label="Reportes">
      <div className="page-head">
        <div>
          <h1 className="page-title">Reportes y Analytics</h1>
          <div className="page-subtitle">
            <b>Atica · Q2 2026</b> · datos agregados al 05/05/2026 · 824 colaboradores activos
          </div>
        </div>
        <div className="rp-period">
          {[
            ['mes',         'Último mes'],
            ['trimestre',   'Trimestre'],
            ['anio',        'Año'],
            ['custom',      'Personalizado'],
          ].map(([k, l]) => (
            <button key={k} className={period === k ? 'active' : ''} onClick={() => setPeriod(k)}>{l}</button>
          ))}
        </div>
      </div>

      <div className="doc-tabs">
        <button className={`doc-tab ${section === 'general' ? 'active' : ''}`} onClick={() => setSection('general')}>
          <IconBarChart size={14} /> General
        </button>
        <button className={`doc-tab ${section === 'icontec' ? 'active' : ''}`} onClick={() => setSection('icontec')}>
          <IconShield size={14} /> ICONTEC · Capacitaciones <span className="epp-tab-pill rose">5</span>
        </button>
      </div>

      {section === 'icontec' && <IcontecReportsSection />}

      {section === 'general' && <>

      {/* Row 1 — KPIs */}
      <div className="rp-kpi-row">
        {KPIS.map(k => <KpiCard key={k.id} k={k} />)}
      </div>

      {/* Row 2 — Two main charts */}
      <div className="rp-row-2">
        <div className="rp-chart-card">
          <div className="rp-chart-head">
            <div>
              <div className="muted-xs">Recolección</div>
              <h3 className="rp-chart-title">Headcount por área</h3>
            </div>
            <div className="rp-chart-legend">
              {HEADCOUNT_LEGEND.map(l => (
                <span key={l.key} className="rp-legend-item">
                  <span className="rp-legend-dot" style={{ background: l.color }} />
                  {l.label}
                </span>
              ))}
            </div>
          </div>
          <StackedBars data={HEADCOUNT_AREAS} />
          <div className="rp-chart-foot">
            <span className="muted" style={{ fontSize: 11.5 }}>
              Total: <b style={{ color: 'var(--text)' }}>{HEADCOUNT_AREAS.reduce((s, a) => s + a.indefinido + a.fijo + a.aprendizaje, 0)}</b> colaboradores · 6 áreas
            </span>
          </div>
        </div>

        <div className="rp-chart-card">
          <div className="rp-chart-head">
            <div>
              <div className="muted-xs">Movimiento mensual · 12 meses</div>
              <h3 className="rp-chart-title">Ingresos y retiros</h3>
            </div>
            <div className="rp-chart-legend">
              <span className="rp-legend-item"><span className="rp-legend-dot" style={{ background: 'var(--green-600)' }} /> Ingresos</span>
              <span className="rp-legend-item"><span className="rp-legend-dot" style={{ background: 'var(--rose-600)' }} /> Retiros</span>
            </div>
          </div>
          <DualLine data={HIRES_EXITS} />
          <div className="rp-chart-foot">
            <span className="muted" style={{ fontSize: 11.5 }}>
              Net YoY: <b style={{ color: 'var(--green-600)' }}>+95</b> · ingresos {HIRES_EXITS.reduce((s, m) => s + m.hires, 0)} · retiros {HIRES_EXITS.reduce((s, m) => s + m.exits, 0)}
            </span>
          </div>
        </div>
      </div>

      {/* Row 3 — Three charts */}
      <div className="rp-row-3">
        <div className="rp-chart-card">
          <div className="rp-chart-head">
            <div>
              <div className="muted-xs">Mix</div>
              <h3 className="rp-chart-title">Por tipo de contrato</h3>
            </div>
          </div>
          <DonutChart data={CONTRACT_DIST} />
          <div className="rp-donut-legend">
            {CONTRACT_DIST.map(d => {
              const total = CONTRACT_DIST.reduce((s, x) => s + x.value, 0);
              const pct = Math.round((d.value / total) * 100);
              return (
                <div key={d.label} className="rp-donut-row">
                  <span className="rp-legend-dot" style={{ background: d.color }} />
                  <span style={{ flex: 1, fontSize: 12 }}>{d.label}</span>
                  <span className="mono" style={{ fontSize: 12, fontWeight: 700 }}>{d.value}</span>
                  <span className="muted mono" style={{ fontSize: 11, width: 36, textAlign: 'right' }}>{pct}%</span>
                </div>
              );
            })}
          </div>
        </div>

        <div className="rp-chart-card">
          <div className="rp-chart-head">
            <div>
              <div className="muted-xs">Top 5 · horas perdidas</div>
              <h3 className="rp-chart-title">Causas de ausencia</h3>
            </div>
          </div>
          <HorizontalBars data={ABSENCE_CAUSES} />
        </div>

        <div className="rp-chart-card">
          <div className="rp-chart-head">
            <div>
              <div className="muted-xs">Últimos 6 meses</div>
              <h3 className="rp-chart-title">Onboardings</h3>
            </div>
            <div className="rp-chart-legend">
              <span className="rp-legend-item"><span className="rp-legend-dot" style={{ background: 'var(--green-600)' }} /> Completados</span>
              <span className="rp-legend-item"><span className="rp-legend-dot" style={{ background: 'var(--amber-600)' }} /> En progreso</span>
            </div>
          </div>
          <VerticalBars data={ONBOARDING_TREND} />
        </div>
      </div>

      {/* Predefined reports */}
      <div className="rp-section">
        <div className="rp-section-head">
          <h2 className="rp-section-title">Reportes predefinidos</h2>
          <span className="muted" style={{ fontSize: 12.5 }}>{PREDEFINED_REPORTS.length} reportes listos para exportar</span>
        </div>
        <div className="doc-list-card">
          <table className="doc-table">
            <thead>
              <tr>
                <th>Reporte</th>
                <th>Descripción</th>
                <th style={{ width: 200 }}>Exportar</th>
              </tr>
            </thead>
            <tbody>
              {PREDEFINED_REPORTS.map(r => (
                <tr key={r.id}>
                  <td>
                    <div style={{ fontWeight: 600, fontSize: 13 }}>{r.name}</div>
                    <div className="muted mono" style={{ fontSize: 11 }}>{r.id.toUpperCase()}</div>
                  </td>
                  <td className="muted" style={{ fontSize: 12.5, maxWidth: 480 }}>{r.desc}</td>
                  <td>
                    <div style={{ display: 'flex', gap: 6 }}>
                      {r.formats.includes('xlsx') && (
                        <button className="rp-export-btn xlsx">
                          <IconDoc size={12} /> Excel
                        </button>
                      )}
                      {r.formats.includes('pdf') && (
                        <button className="rp-export-btn pdf">
                          <IconDoc size={12} /> PDF
                        </button>
                      )}
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>

      {/* Compliance */}
      <div className="rp-section">
        <div className="rp-section-head">
          <h2 className="rp-section-title">Cumplimiento normativo</h2>
          <span className="muted" style={{ fontSize: 12.5 }}>
            <span className="rp-traffic ok">●</span> 4 al día ·
            <span className="rp-traffic warn"> ●</span> 1 atención ·
            <span className="rp-traffic crit"> ●</span> 1 crítico
          </span>
        </div>
        <div className="rp-compliance-grid">
          {COMPLIANCE.map(c => {
            const m = STATUS_META_CMP[c.status];
            const Ico = window[m.icon] || IconCheck;
            return (
              <div key={c.id} className={`rp-cmp-card ${m.tone}`}>
                <div className="rp-cmp-head">
                  <span className={`rp-cmp-light ${m.tone}`}>
                    <Ico size={13} />
                  </span>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div className="rp-cmp-name">{c.label}</div>
                    <div className={`rp-cmp-status ${m.tone}`}>
                      <span className="status-dot" style={{ background: m.dot }} /> {m.label}
                    </div>
                  </div>
                </div>
                <div className="rp-cmp-desc">{c.desc}</div>
                <button className="rp-cmp-cta">
                  <IconExternal size={12} /> {c.cta}
                </button>
              </div>
            );
          })}
        </div>
      </div>

      </>}
    </div>
  );
};

// ─── KPI card with sparkline ─────────────────────────────

const KpiCard = ({ k }) => {
  const w = 80, h = 28;
  const min = Math.min(...k.spark);
  const max = Math.max(...k.spark);
  const range = max - min || 1;
  const points = k.spark.map((v, i) => {
    const x = (i / (k.spark.length - 1)) * w;
    const y = h - ((v - min) / range) * (h - 4) - 2;
    return `${x.toFixed(1)},${y.toFixed(1)}`;
  }).join(' ');

  const colorMap = {
    navy:  'var(--navy-800)',
    blue:  'var(--blue-600)',
    green: 'var(--green-600)',
    amber: 'var(--amber-600)',
    rose:  'var(--rose-600)',
  };
  const stroke = colorMap[k.tone];

  return (
    <div className="rp-kpi">
      <div className="rp-kpi-top">
        <div className="muted-xs">{k.label}</div>
        <span className={`rp-kpi-delta ${k.deltaType}`}>
          {k.deltaType === 'up' ? '↑' : k.deltaType === 'down' ? '↓' : '·'} {k.delta}
        </span>
      </div>
      <div className="rp-kpi-val">{k.value}</div>
      <div className="rp-kpi-bottom">
        <span className="rp-kpi-foot">{k.foot}</span>
        <svg width={w} height={h} className="rp-spark" viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none">
          <defs>
            <linearGradient id={`grad-${k.id}`} x1="0" y1="0" x2="0" y2="1">
              <stop offset="0%" stopColor={stroke} stopOpacity="0.22" />
              <stop offset="100%" stopColor={stroke} stopOpacity="0" />
            </linearGradient>
          </defs>
          <polyline points={`0,${h} ${points} ${w},${h}`} fill={`url(#grad-${k.id})`} stroke="none" />
          <polyline points={points} fill="none" stroke={stroke} strokeWidth="1.4" strokeLinejoin="round" strokeLinecap="round" />
        </svg>
      </div>
    </div>
  );
};

// ─── Stacked bar chart ───────────────────────────────────

const StackedBars = ({ data }) => {
  const W = 600, H = 240, pad = { l: 100, r: 16, t: 12, b: 28 };
  const innerW = W - pad.l - pad.r;
  const innerH = H - pad.t - pad.b;
  const max = Math.max(...data.map(d => d.indefinido + d.fijo + d.aprendizaje));
  const niceMax = Math.ceil(max / 50) * 50;
  const barH = (innerH / data.length) * 0.7;
  const gap  = (innerH / data.length) * 0.3;

  return (
    <svg viewBox={`0 0 ${W} ${H}`} className="rp-chart" preserveAspectRatio="xMidYMid meet">
      {/* x grid */}
      {[0, 0.25, 0.5, 0.75, 1].map(f => {
        const x = pad.l + innerW * f;
        return <line key={f} x1={x} y1={pad.t} x2={x} y2={pad.t + innerH} stroke="var(--border)" strokeWidth="1" strokeDasharray={f === 0 ? '' : '2,3'} />;
      })}
      {/* bars */}
      {data.map((d, i) => {
        const y = pad.t + i * (barH + gap) + gap / 2;
        const wA = (d.indefinido / niceMax) * innerW;
        const wB = (d.fijo / niceMax) * innerW;
        const wC = (d.aprendizaje / niceMax) * innerW;
        const total = d.indefinido + d.fijo + d.aprendizaje;
        return (
          <g key={d.area}>
            <text x={pad.l - 10} y={y + barH / 2} dominantBaseline="middle" textAnchor="end" fontSize="11" fill="var(--text)" fontWeight="600">{d.area}</text>
            <rect x={pad.l}              y={y} width={wA}      height={barH} fill="var(--navy-800)" rx="2" />
            <rect x={pad.l + wA}         y={y} width={wB}      height={barH} fill="var(--blue-600)" />
            <rect x={pad.l + wA + wB}    y={y} width={wC}      height={barH} fill="var(--amber-600)" rx="0" />
            <text x={pad.l + wA + wB + wC + 6} y={y + barH / 2} dominantBaseline="middle" fontSize="11" fontFamily="JetBrains Mono" fill="var(--text)" fontWeight="700">{total}</text>
          </g>
        );
      })}
      {/* x labels */}
      {[0, 0.25, 0.5, 0.75, 1].map(f => {
        const x = pad.l + innerW * f;
        return <text key={f} x={x} y={H - 8} textAnchor="middle" fontSize="10" fill="var(--text-subtle)" fontFamily="JetBrains Mono">{Math.round(niceMax * f)}</text>;
      })}
    </svg>
  );
};

// ─── Dual line chart ─────────────────────────────────────

const DualLine = ({ data }) => {
  const W = 600, H = 240, pad = { l: 36, r: 16, t: 16, b: 28 };
  const innerW = W - pad.l - pad.r;
  const innerH = H - pad.t - pad.b;
  const max = Math.max(...data.flatMap(d => [d.hires, d.exits]));
  const niceMax = Math.ceil(max / 5) * 5;

  const path = (key, color) => {
    const points = data.map((d, i) => {
      const x = pad.l + (i / (data.length - 1)) * innerW;
      const y = pad.t + innerH - (d[key] / niceMax) * innerH;
      return [x, y];
    });
    const line = points.map((p, i) => `${i === 0 ? 'M' : 'L'} ${p[0].toFixed(1)} ${p[1].toFixed(1)}`).join(' ');
    return (
      <g>
        <path d={line} fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
        {points.map((p, i) => <circle key={i} cx={p[0]} cy={p[1]} r="2.5" fill="white" stroke={color} strokeWidth="1.4" />)}
      </g>
    );
  };

  return (
    <svg viewBox={`0 0 ${W} ${H}`} className="rp-chart" preserveAspectRatio="xMidYMid meet">
      {/* y grid */}
      {[0, 0.25, 0.5, 0.75, 1].map(f => {
        const y = pad.t + innerH - innerH * f;
        const v = Math.round(niceMax * f);
        return (
          <g key={f}>
            <line x1={pad.l} y1={y} x2={pad.l + innerW} y2={y} stroke="var(--border)" strokeWidth="1" strokeDasharray={f === 0 ? '' : '2,3'} />
            <text x={pad.l - 6} y={y + 3} textAnchor="end" fontSize="9.5" fill="var(--text-subtle)" fontFamily="JetBrains Mono">{v}</text>
          </g>
        );
      })}
      {/* x labels */}
      {data.map((d, i) => {
        const x = pad.l + (i / (data.length - 1)) * innerW;
        return <text key={d.m} x={x} y={H - 10} textAnchor="middle" fontSize="9.5" fill="var(--text-subtle)" fontFamily="JetBrains Mono">{d.m}</text>;
      })}
      {path('hires', 'var(--green-600)')}
      {path('exits', 'var(--rose-600)')}
    </svg>
  );
};

// ─── Donut chart ─────────────────────────────────────────

const DonutChart = ({ data }) => {
  const total = data.reduce((s, d) => s + d.value, 0);
  const cx = 100, cy = 100, r = 78, w = 22; // outer radius, ring width
  const inner = r - w;

  let acc = 0;
  const arcs = data.map(d => {
    const start = acc / total * Math.PI * 2 - Math.PI / 2;
    acc += d.value;
    const end = acc / total * Math.PI * 2 - Math.PI / 2;
    const large = end - start > Math.PI ? 1 : 0;
    const x1 = cx + r * Math.cos(start), y1 = cy + r * Math.sin(start);
    const x2 = cx + r * Math.cos(end),   y2 = cy + r * Math.sin(end);
    const xi1 = cx + inner * Math.cos(end),   yi1 = cy + inner * Math.sin(end);
    const xi2 = cx + inner * Math.cos(start), yi2 = cy + inner * Math.sin(start);
    const path = [
      `M ${x1.toFixed(2)} ${y1.toFixed(2)}`,
      `A ${r} ${r} 0 ${large} 1 ${x2.toFixed(2)} ${y2.toFixed(2)}`,
      `L ${xi1.toFixed(2)} ${yi1.toFixed(2)}`,
      `A ${inner} ${inner} 0 ${large} 0 ${xi2.toFixed(2)} ${yi2.toFixed(2)}`,
      'Z',
    ].join(' ');
    return { d: path, color: d.color };
  });

  return (
    <svg viewBox="0 0 200 200" className="rp-donut" preserveAspectRatio="xMidYMid meet">
      {arcs.map((a, i) => <path key={i} d={a.d} fill={a.color} />)}
      <text x={100} y={94} textAnchor="middle" fontSize="11" fill="var(--text-muted)" fontFamily="Inter" fontWeight="600">Total</text>
      <text x={100} y={120} textAnchor="middle" fontSize="32" fill="var(--text)" fontFamily="Inter" fontWeight="800" letterSpacing="-1">{total}</text>
    </svg>
  );
};

// ─── Horizontal bars ─────────────────────────────────────

const HorizontalBars = ({ data }) => {
  const W = 360, H = 220, pad = { l: 0, r: 60, t: 8, b: 8 };
  const innerH = H - pad.t - pad.b;
  const max = Math.max(...data.map(d => d.hours));
  const barH = (innerH / data.length) * 0.62;
  const gap  = (innerH / data.length) * 0.38;

  const colorMap = {
    rose:  'var(--rose-600)',
    amber: 'var(--amber-600)',
    blue:  'var(--blue-600)',
    navy:  'var(--navy-800)',
  };

  return (
    <svg viewBox={`0 0 ${W} ${H}`} className="rp-hbar" preserveAspectRatio="xMidYMid meet">
      {data.map((d, i) => {
        const y = pad.t + i * (barH + gap) + gap / 2;
        const w = (d.hours / max) * (W - pad.r);
        return (
          <g key={d.label}>
            <text x={4} y={y - 2} fontSize="10.5" fill="var(--text)" fontWeight="600">{d.label}</text>
            <rect x={0} y={y + 4} width={W - pad.r} height={barH - 4} rx="3" fill="var(--surface-2)" />
            <rect x={0} y={y + 4} width={w}         height={barH - 4} rx="3" fill={colorMap[d.tone]} />
            <text x={w + 6} y={y + 4 + (barH - 4) / 2 + 1} dominantBaseline="middle" fontSize="11" fontFamily="JetBrains Mono" fontWeight="700" fill="var(--text)">{d.hours} h</text>
          </g>
        );
      })}
    </svg>
  );
};

// ─── Vertical grouped bars ───────────────────────────────

const VerticalBars = ({ data }) => {
  const W = 360, H = 220, pad = { l: 26, r: 8, t: 14, b: 26 };
  const innerW = W - pad.l - pad.r;
  const innerH = H - pad.t - pad.b;
  const max = Math.max(...data.map(d => d.completed + d.inProgress));
  const niceMax = Math.ceil(max / 5) * 5;
  const groupW = innerW / data.length;
  const barW = groupW * 0.32;

  return (
    <svg viewBox={`0 0 ${W} ${H}`} className="rp-vbar" preserveAspectRatio="xMidYMid meet">
      {[0, 0.5, 1].map(f => {
        const y = pad.t + innerH - innerH * f;
        const v = Math.round(niceMax * f);
        return (
          <g key={f}>
            <line x1={pad.l} y1={y} x2={pad.l + innerW} y2={y} stroke="var(--border)" strokeWidth="1" strokeDasharray={f === 0 ? '' : '2,3'} />
            <text x={pad.l - 4} y={y + 3} textAnchor="end" fontSize="9.5" fill="var(--text-subtle)" fontFamily="JetBrains Mono">{v}</text>
          </g>
        );
      })}
      {data.map((d, i) => {
        const cx = pad.l + i * groupW + groupW / 2;
        const hC = (d.completed  / niceMax) * innerH;
        const hI = (d.inProgress / niceMax) * innerH;
        return (
          <g key={d.m}>
            <rect x={cx - barW - 2} y={pad.t + innerH - hC} width={barW} height={hC} rx="2" fill="var(--green-600)" />
            <rect x={cx + 2}        y={pad.t + innerH - hI} width={barW} height={hI} rx="2" fill="var(--amber-600)" />
            <text x={cx} y={H - 10} textAnchor="middle" fontSize="9.5" fill="var(--text-subtle)" fontFamily="JetBrains Mono">{d.m}</text>
          </g>
        );
      })}
    </svg>
  );
};

// ═══════════════════════════════════════════════════════════
// SECTION ICONTEC · 5 reportes auditables + dashboard
// ═══════════════════════════════════════════════════════════

const ICONTEC_KPIS = {
  cumplimiento: 78,
  vencimientos: 47,
  evaluaciones: 84,
  certificados: 712,
  noConformidades: 12,
};

// Cumplimiento por área
const ICONTEC_COMPLIANCE_AREAS = [
  { area: 'Operaciones',     total: 240, vigentes: 218, vencidos: 14, sinFormar: 8,  pct: 91 },
  { area: 'Aprovechamiento',        total: 188, vigentes: 158, vencidos: 22, sinFormar: 8,  pct: 84 },
  { area: 'Calidad',        total: 46,  vigentes: 44,  vencidos: 2,  sinFormar: 0,  pct: 96 },
  { area: 'Mantenimiento',  total: 46,  vigentes: 38,  vencidos: 5,  sinFormar: 3,  pct: 83 },
  { area: 'Recolección',   total: 70,  vigentes: 56,  vencidos: 8,  sinFormar: 6,  pct: 80 },
  { area: 'Administración', total: 38,  vigentes: 36,  vencidos: 1,  sinFormar: 1,  pct: 95 },
];

// Matriz cargo × competencia (heatmap)
const ICONTEC_HEATMAP_ROLES = [
  'Operario de Clasificación', 'Op. Aprovechamiento', 'Aux. Calidad', 'Téc. Mantenimiento', 'Conductor', 'Líder de Aprovechamiento', 'Aux. RRHH', 'Jefe de RRHH',
];
const ICONTEC_HEATMAP_CMPS = ['CMP-01', 'CMP-02', 'CMP-03', 'CMP-04', 'CMP-05', 'CMP-06', 'CMP-09', 'CMP-11', 'CMP-12'];
const ICONTEC_HEATMAP_DATA = {
  // role → cmp → { required, pct } | null si no requerido
  'Operario de Clasificación':  { 'CMP-01': 91, 'CMP-02': 84, 'CMP-03': 90, 'CMP-04': null, 'CMP-05': null, 'CMP-06': 96, 'CMP-09': 100, 'CMP-11': 88, 'CMP-12': null },
  'Op. Aprovechamiento':           { 'CMP-01': null, 'CMP-02': 92, 'CMP-03': 94, 'CMP-04': null, 'CMP-05': null, 'CMP-06': 98, 'CMP-09': 100, 'CMP-11': 86, 'CMP-12': null },
  'Aux. Calidad':          { 'CMP-01': null, 'CMP-02': 100, 'CMP-03': 100, 'CMP-04': null, 'CMP-05': null, 'CMP-06': 100, 'CMP-09': 100, 'CMP-11': 100, 'CMP-12': null },
  'Téc. Mantenimiento':    { 'CMP-01': 82, 'CMP-02': null, 'CMP-03': null, 'CMP-04': 75, 'CMP-05': null, 'CMP-06': 95, 'CMP-09': 100, 'CMP-11': 90, 'CMP-12': null },
  'Conductor':             { 'CMP-01': null, 'CMP-02': null, 'CMP-03': null, 'CMP-04': null, 'CMP-05': null, 'CMP-06': 100, 'CMP-09': 100, 'CMP-11': 88, 'CMP-12': 65 },
  'Líder de Aprovechamiento':      { 'CMP-01': 100, 'CMP-02': 100, 'CMP-03': null, 'CMP-04': null, 'CMP-05': 100, 'CMP-06': 100, 'CMP-09': 100, 'CMP-11': 100, 'CMP-12': null },
  'Aux. RRHH':             { 'CMP-01': null, 'CMP-02': null, 'CMP-03': null, 'CMP-04': null, 'CMP-05': null, 'CMP-06': 100, 'CMP-09': 100, 'CMP-11': 100, 'CMP-12': null },
  'Jefe de RRHH':          { 'CMP-01': null, 'CMP-02': null, 'CMP-03': null, 'CMP-04': null, 'CMP-05': null, 'CMP-06': 100, 'CMP-09': 100, 'CMP-11': 100, 'CMP-12': null },
};

const ICONTEC_VENCIDAS = [
  { cmp: 'CMP-01', cmpName: 'Manejo seguro de maquinaria de clasificación', area: 'Operaciones',     count: 11, criticidad: 'alta',  daysAvg: 14 },
  { cmp: 'CMP-12', cmpName: 'Manejo defensivo y seguridad vial',     area: 'Recolección',   count: 6,  criticidad: 'alta',  daysAvg: 21 },
  { cmp: 'CMP-04', cmpName: 'Trabajo seguro en alturas',             area: 'Mantenimiento',  count: 3,  criticidad: 'alta',  daysAvg: 8 },
  { cmp: 'CMP-02', cmpName: 'Buenas Prácticas de Manufactura · BPM', area: 'Aprovechamiento',        count: 12, criticidad: 'alta',  daysAvg: 32 },
  { cmp: 'CMP-11', cmpName: 'SG-SST · Sistema de Gestión SST',       area: 'Operaciones',     count: 8,  criticidad: 'alta',  daysAvg: 11 },
  { cmp: 'CMP-03', cmpName: 'Manipulación higiénica de alimentos',   area: 'Aprovechamiento',        count: 5,  criticidad: 'alta',  daysAvg: 6 },
  { cmp: 'CMP-06', cmpName: 'Reglamento Interno · RIT',              area: 'Operaciones',     count: 2,  criticidad: 'alta',  daysAvg: 5 },
];

// Evaluations
const ICONTEC_EVALS_BY_COURSE = [
  { course: 'Manejo seguro maquinaria',    avg: 87.4, sessions: 6, count: 142, distribution: [2, 4, 18, 76, 42], minScore: 80, noConformidades: 6 },
  { course: 'BPM',                          avg: 82.1, sessions: 12,count: 712, distribution: [12, 18, 88, 412, 182], minScore: 75, noConformidades: 30 },
  { course: 'Manipulación de alimentos',   avg: 84.6, sessions: 4, count: 412, distribution: [4, 8, 64, 224, 112], minScore: 70, noConformidades: 12 },
  { course: 'Brigada de emergencias',      avg: 89.2, sessions: 2, count: 38,  distribution: [0, 1, 4, 18, 15], minScore: 80, noConformidades: 1 },
  { course: 'Trabajo en alturas',          avg: 91.8, sessions: 3, count: 12,  distribution: [0, 0, 1, 6, 5], minScore: 85, noConformidades: 0 },
];

const IcontecReportsSection = () => {
  const [report, setReport] = _rp_useState('dashboard');

  return (
    <div className="ic-rp">
      {/* Subnav */}
      <div className="ic-rp-subnav">
        <button className={`ic-rp-tab ${report === 'dashboard' ? 'active' : ''}`} onClick={() => setReport('dashboard')}>
          <IconShield size={13} /> Dashboard ICONTEC
        </button>
        <button className={`ic-rp-tab ${report === 'areas' ? 'active' : ''}`} onClick={() => setReport('areas')}>
          1 · Cumplimiento por área
        </button>
        <button className={`ic-rp-tab ${report === 'matrix' ? 'active' : ''}`} onClick={() => setReport('matrix')}>
          2 · Matriz cargo × competencia
        </button>
        <button className={`ic-rp-tab ${report === 'historial' ? 'active' : ''}`} onClick={() => setReport('historial')}>
          3 · Historial individual
        </button>
        <button className={`ic-rp-tab ${report === 'vencidas' ? 'active' : ''}`} onClick={() => setReport('vencidas')}>
          4 · Capacitaciones vencidas
        </button>
        <button className={`ic-rp-tab ${report === 'evals' ? 'active' : ''}`} onClick={() => setReport('evals')}>
          5 · Evaluaciones
        </button>
      </div>

      {report === 'dashboard'  && <ICONTECDashboard onGo={setReport} />}
      {report === 'areas'      && <ICONTECComplianceByArea />}
      {report === 'matrix'     && <ICONTECRoleMatrix />}
      {report === 'historial'  && <ICONTECIndividualHistory />}
      {report === 'vencidas'   && <ICONTECExpired />}
      {report === 'evals'      && <ICONTECEvaluations />}
    </div>
  );
};

// ─── 0 · Dashboard ICONTEC ───────────────────────────────

const ICONTECDashboard = ({ onGo }) => {
  const status = 'warn';  // 'ready' | 'warn' | 'crit'
  const statusLabel = { ready: '✅ Listo para auditoría', warn: '⚠️ Atención · acciones pendientes', crit: '🔴 No listo · brechas críticas' }[status];
  const statusTone = { ready: 'green', warn: 'amber', crit: 'rose' }[status];

  return (
    <>
      <div className={`ic-rp-banner ${statusTone}`}>
        <div className="ic-rp-banner-shield">
          <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" /></svg>
        </div>
        <div style={{ flex: 1 }}>
          <div className="ic-rp-banner-title">{statusLabel}</div>
          <div className="ic-rp-banner-sub">
            12 acciones pendientes para alcanzar listo total ICONTEC. <b>3 son críticas</b> y deben resolverse antes del próximo ciclo.
          </div>
        </div>
        <button className="btn primary"><IconExternal size={14} /> Plan de remediación</button>
      </div>

      {/* 4 semáforos grandes */}
      <div className="ic-rp-traffic-grid">
        <div className="ic-rp-traffic green">
          <div className="ic-rp-traffic-icon"><IconCheck size={18} /></div>
          <div className="ic-rp-traffic-num">96<small>%</small></div>
          <div className="ic-rp-traffic-lbl">Asistencia firmada</div>
          <div className="muted" style={{ fontSize: 11 }}>vía OTP email/SMS · Ley 527/1999</div>
        </div>
        <div className="ic-rp-traffic amber">
          <div className="ic-rp-traffic-icon"><IconAlert size={18} /></div>
          <div className="ic-rp-traffic-num">84<small>%</small></div>
          <div className="ic-rp-traffic-lbl">Evaluación aplicada</div>
          <div className="muted" style={{ fontSize: 11 }}>16% sin captura completa</div>
        </div>
        <div className="ic-rp-traffic green">
          <div className="ic-rp-traffic-icon"><IconCheck size={18} /></div>
          <div className="ic-rp-traffic-num">92<small>%</small></div>
          <div className="ic-rp-traffic-lbl">Evidencia adjunta</div>
          <div className="muted" style={{ fontSize: 11 }}>acta + soporte mínimo · sesiones cerradas</div>
        </div>
        <div className="ic-rp-traffic rose">
          <div className="ic-rp-traffic-icon"><IconAlert size={18} /></div>
          <div className="ic-rp-traffic-num">{ICONTEC_KPIS.vencimientos}</div>
          <div className="ic-rp-traffic-lbl">Vigencias vencidas</div>
          <div className="muted" style={{ fontSize: 11 }}>requieren reasignación urgente</div>
        </div>
      </div>

      {/* Top problemas + checklist auditor */}
      <div className="ic-rp-2col">
        <div className="ic-rp-card">
          <div className="ic-rp-card-head">
            <h3>Top 5 áreas con brechas</h3>
            <span className="muted" style={{ fontSize: 12 }}>Foco de remediación inmediata</span>
          </div>
          <div className="ic-rp-top-list">
            {ICONTEC_COMPLIANCE_AREAS.slice().sort((a, b) => a.pct - b.pct).slice(0, 5).map((a, i) => (
              <div key={a.area} className="ic-rp-top-row">
                <span className="ic-rp-top-rank">{i + 1}</span>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontWeight: 600, fontSize: 13 }}>{a.area}</div>
                  <div className="muted" style={{ fontSize: 11.5 }}>{a.vencidos + a.sinFormar} colaboradores con brecha</div>
                </div>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, flex: 1 }}>
                  <div className="tr-prog-track" style={{ flex: 1 }}>
                    <div className={`tr-prog-fill ${a.pct >= 90 ? 'green' : a.pct >= 80 ? 'amber' : 'rose'}`} style={{ width: `${a.pct}%` }} />
                  </div>
                  <span className={`mono`} style={{ fontWeight: 800, fontSize: 13, minWidth: 40, textAlign: 'right', color: a.pct >= 90 ? 'var(--green-600)' : a.pct >= 80 ? 'var(--amber-600)' : 'var(--rose-600)' }}>{a.pct}%</span>
                </div>
              </div>
            ))}
          </div>
        </div>

        <div className="ic-rp-card">
          <div className="ic-rp-card-head">
            <h3>Checklist auditor</h3>
            <span className="muted" style={{ fontSize: 12 }}>10 ítems · simulación pre-auditoría</span>
          </div>
          <div className="ic-rp-checklist">
            {[
              { ok: true,  txt: 'Catálogo maestro de competencias publicado' },
              { ok: true,  txt: 'Versionado de contenido auditable activo' },
              { ok: true,  txt: 'Asistencia con firma electrónica · Ley 527' },
              { ok: true,  txt: 'Evidencia obligatoria para cierre de sesión' },
              { ok: false, txt: 'Hash criptográfico en todo certificado emitido', warn: '12 certificados sin hash (anteriores a v3.0)' },
              { ok: true,  txt: 'Bitácora append-only · acceso solo Admin' },
              { ok: false, txt: 'Reasignación automática al vencer · 100% cobertura', warn: '47 vencimientos sin reasignar' },
              { ok: true,  txt: 'Verificador público con QR + hash' },
              { ok: false, txt: 'Reportes consolidados por área · Q2', warn: '3 áreas con datos incompletos' },
              { ok: true,  txt: 'Norma legal vinculada a cada competencia' },
            ].map((c, i) => (
              <div key={i} className={`ic-rp-check ${c.ok ? 'ok' : 'pending'}`}>
                <span className={`ic-rp-check-mark ${c.ok ? 'ok' : 'pending'}`}>
                  {c.ok ? <IconCheck size={11} /> : ''}
                </span>
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: 12.5, fontWeight: 600, color: c.ok ? 'var(--text)' : 'var(--text)' }}>{c.txt}</div>
                  {c.warn && <div className="muted" style={{ fontSize: 11, marginTop: 1, color: 'var(--rose-600)' }}>{c.warn}</div>}
                </div>
              </div>
            ))}
          </div>
        </div>
      </div>

      <div className="ic-rp-quick">
        <h3>Reportes detallados</h3>
        <div className="ic-rp-quick-grid">
          {[
            { id: 'areas',    label: 'Cumplimiento por área',           desc: 'Cobertura de competencias por colaborador y área',    icon: 'IconBarChart', tone: 'navy' },
            { id: 'matrix',   label: 'Matriz cargo × competencia',      desc: 'Heatmap visual de cobertura por cargo',               icon: 'IconUsers',    tone: 'blue' },
            { id: 'historial',label: 'Historial individual',            desc: 'Línea de tiempo exportable a PDF · expediente',       icon: 'IconClock',    tone: 'green' },
            { id: 'vencidas', label: 'Capacitaciones vencidas',         desc: 'Por área y criticidad · plan de reasignación',         icon: 'IconAlert',    tone: 'rose' },
            { id: 'evals',    label: 'Evaluaciones de competencia',     desc: 'Promedios, distribución de notas, no conformidades',  icon: 'IconStar',     tone: 'amber' },
          ].map(r => {
            const Ico = window[r.icon] || IconBook;
            return (
              <button key={r.id} className={`ic-rp-quick-card ${r.tone}`} onClick={() => onGo(r.id)}>
                <span className="ic-rp-quick-icon"><Ico size={18} /></span>
                <div style={{ flex: 1, minWidth: 0, textAlign: 'left' }}>
                  <div style={{ fontWeight: 700, fontSize: 13 }}>{r.label}</div>
                  <div className="muted" style={{ fontSize: 11.5, marginTop: 2 }}>{r.desc}</div>
                </div>
                <IconChevronRight size={14} />
              </button>
            );
          })}
        </div>
      </div>
    </>
  );
};

// ─── 1 · Cumplimiento por área ────────────────────────────

const ICONTECComplianceByArea = () => {
  return (
    <>
      <div className="ic-rp-card">
        <div className="ic-rp-card-head">
          <div>
            <h3>Cumplimiento por área · Q2 2026</h3>
            <span className="muted" style={{ fontSize: 12.5 }}>% personal con todas sus competencias requeridas vigentes</span>
          </div>
          <div style={{ display: 'flex', gap: 6 }}>
            <button className="btn"><IconDoc size={13} /> Excel</button>
            <button className="btn"><IconDoc size={13} /> PDF auditor</button>
          </div>
        </div>
        <div className="doc-list-card" style={{ border: 'none', boxShadow: 'none', marginTop: 14 }}>
          <table className="doc-table">
            <thead>
              <tr>
                <th>Área</th>
                <th style={{ textAlign: 'center' }}>Total colaboradores</th>
                <th style={{ textAlign: 'center' }}>Competencias vigentes</th>
                <th style={{ textAlign: 'center' }}>Vencidos</th>
                <th style={{ textAlign: 'center' }}>Sin formar</th>
                <th>% Cumplimiento</th>
              </tr>
            </thead>
            <tbody>
              {ICONTEC_COMPLIANCE_AREAS.map(a => {
                const tone = a.pct >= 90 ? 'green' : a.pct >= 80 ? 'amber' : 'rose';
                return (
                  <tr key={a.area}>
                    <td data-label="Área" style={{ fontWeight: 700, fontSize: 13.5 }}>{a.area}</td>
                    <td data-label="Total" className="mono" style={{ textAlign: 'center', fontWeight: 700 }}>{a.total}</td>
                    <td data-label="Vigentes" className="mono" style={{ textAlign: 'center', color: 'var(--green-600)', fontWeight: 700 }}>{a.vigentes}</td>
                    <td data-label="Vencidos" className="mono" style={{ textAlign: 'center', color: a.vencidos > 0 ? 'var(--rose-600)' : 'var(--text-muted)', fontWeight: 700 }}>{a.vencidos}</td>
                    <td data-label="Sin formar" className="mono" style={{ textAlign: 'center', color: a.sinFormar > 0 ? 'var(--amber-600)' : 'var(--text-muted)', fontWeight: 700 }}>{a.sinFormar}</td>
                    <td data-label="% Cumplimiento">
                      <div style={{ display: 'flex', alignItems: 'center', gap: 10, minWidth: 240 }}>
                        <div className="tr-prog-track" style={{ flex: 1 }}>
                          <div className={`tr-prog-fill ${tone}`} style={{ width: `${a.pct}%` }} />
                        </div>
                        <span className="mono" style={{ fontWeight: 800, fontSize: 14, minWidth: 50, textAlign: 'right', color: tone === 'green' ? 'var(--green-600)' : tone === 'amber' ? 'var(--amber-600)' : 'var(--rose-600)' }}>{a.pct}%</span>
                      </div>
                    </td>
                  </tr>
                );
              })}
              <tr style={{ background: 'var(--navy-50)', fontWeight: 800 }}>
                <td><b>TOTAL ATICA</b></td>
                <td className="mono" style={{ textAlign: 'center' }}><b>628</b></td>
                <td className="mono" style={{ textAlign: 'center', color: 'var(--green-600)' }}><b>550</b></td>
                <td className="mono" style={{ textAlign: 'center', color: 'var(--rose-600)' }}><b>52</b></td>
                <td className="mono" style={{ textAlign: 'center', color: 'var(--amber-600)' }}><b>26</b></td>
                <td>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                    <div className="tr-prog-track" style={{ flex: 1 }}>
                      <div className="tr-prog-fill amber" style={{ width: '88%' }} />
                    </div>
                    <span className="mono" style={{ fontWeight: 800, fontSize: 14, color: 'var(--amber-600)' }}>88%</span>
                  </div>
                </td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </>
  );
};

// ─── 2 · Matriz cargo × competencia (heatmap) ─────────────

const ICONTECRoleMatrix = () => {
  const cellTone = (pct) => {
    if (pct === null) return 'na';
    if (pct >= 95) return 'top';
    if (pct >= 80) return 'good';
    if (pct >= 60) return 'warn';
    return 'crit';
  };
  return (
    <div className="ic-rp-card">
      <div className="ic-rp-card-head">
        <div>
          <h3>Matriz cargo × competencia</h3>
          <span className="muted" style={{ fontSize: 12.5 }}>Heatmap de cobertura · cada celda muestra el % vigente del cargo en esa competencia</span>
        </div>
        <button className="btn"><IconDoc size={13} /> Excel</button>
      </div>

      <div className="ic-rp-heatmap-wrap">
        <table className="ic-rp-heatmap">
          <thead>
            <tr>
              <th></th>
              {ICONTEC_HEATMAP_CMPS.map(cmp => <th key={cmp} title={cmp}><span className="mono">{cmp}</span></th>)}
            </tr>
          </thead>
          <tbody>
            {ICONTEC_HEATMAP_ROLES.map(role => (
              <tr key={role}>
                <th>{role}</th>
                {ICONTEC_HEATMAP_CMPS.map(cmp => {
                  const pct = ICONTEC_HEATMAP_DATA[role]?.[cmp];
                  const tone = cellTone(pct);
                  return (
                    <td key={cmp} className={`ic-rp-cell ic-rp-cell-${tone}`}>
                      {pct === null ? <span className="muted">—</span> : <span className="mono">{pct}%</span>}
                    </td>
                  );
                })}
              </tr>
            ))}
          </tbody>
        </table>
        <div className="ic-rp-heatmap-legend">
          <span><span className="ic-rp-cell-swatch top" /> ≥ 95% Excelente</span>
          <span><span className="ic-rp-cell-swatch good" /> 80-94% Aceptable</span>
          <span><span className="ic-rp-cell-swatch warn" /> 60-79% Atención</span>
          <span><span className="ic-rp-cell-swatch crit" /> &lt; 60% Crítico</span>
          <span><span className="ic-rp-cell-swatch na" /> No aplica</span>
        </div>
      </div>
    </div>
  );
};

// ─── 3 · Historial individual ─────────────────────────────

const ICONTECIndividualHistory = () => {
  const [pdfOpen, setPdfOpen] = _rp_useState(false);
  return (
    <div className="ic-rp-card">
      <div className="ic-rp-card-head">
        <div>
          <h3>Historial individual del colaborador</h3>
          <span className="muted" style={{ fontSize: 12.5 }}>Selecciona un colaborador para generar su expediente exportable a PDF</span>
        </div>
      </div>

      <div className="ic-rp-search-bar">
        <div className="ob-search" style={{ width: '100%' }}>
          <IconSearch size={15} />
          <input placeholder="Buscar por nombre, ID o cargo…" defaultValue="Carlos Andrés Vélez" />
        </div>
        <button className="btn primary" onClick={() => setPdfOpen(true)}><IconDoc size={14} /> Generar PDF expediente</button>
      </div>

      {pdfOpen && <ExpedientePDFModal onClose={() => setPdfOpen(false)} />}

      <div className="ic-rp-individual-card">
        <div className="ic-rp-individual-head">
          <div className="doc-avatar" style={{ width: 56, height: 56, fontSize: 18, borderRadius: 14 }}>CV</div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 17, fontWeight: 800 }}>Carlos Andrés Vélez</div>
            <div className="muted" style={{ fontSize: 13 }}>Operario de Clasificación · Operaciones · Cali</div>
            <div className="muted mono" style={{ fontSize: 11.5, marginTop: 4 }}>E0205 · ingresó 14/03/2024</div>
          </div>
          <div className="ic-rp-individual-stats">
            <div><div className="muted-xs">Vigentes</div><div className="mono" style={{ fontSize: 22, fontWeight: 800, color: 'var(--green-600)' }}>4</div></div>
            <div><div className="muted-xs">En curso</div><div className="mono" style={{ fontSize: 22, fontWeight: 800, color: 'var(--amber-600)' }}>1</div></div>
            <div><div className="muted-xs">Vencidas</div><div className="mono" style={{ fontSize: 22, fontWeight: 800, color: 'var(--rose-600)' }}>1</div></div>
            <div><div className="muted-xs">Cumplimiento</div><div className="mono" style={{ fontSize: 22, fontWeight: 800, color: 'var(--green-600)' }}>83%</div></div>
          </div>
        </div>

        <div className="ic-rp-individual-explain">
          <IconShield size={14} />
          <span>El PDF generado incluye: timeline inmutable, certificados, hashes criptográficos, evidencias de cada sesión, y la cadena completa de auditoría conforme ICONTEC. <b>Documento firmado electrónicamente · entregable directo al auditor.</b></span>
        </div>

        <div className="ic-rp-individual-preview">
          <div className="muted-xs" style={{ marginBottom: 8 }}>Vista previa del expediente</div>
          <div className="ic-rp-doc-pages">
            {[1, 2, 3, 4].map(p => (
              <div key={p} className="ic-rp-doc-page">
                <div className="ic-rp-doc-page-head">
                  <span className="cv-brand-mark plataforma" style={{ width: 14, height: 14, fontSize: 9, borderRadius: 3, display: 'inline-grid', placeItems: 'center' }}><AticaMark size={10} tri="#fff" leaf="var(--sky-500)" /></span>
                  <span className="muted mono" style={{ fontSize: 8 }}>p. {p}</span>
                </div>
                <div className="ic-rp-doc-page-lines">
                  {Array.from({ length: 18 }).map((_, i) => (
                    <span key={i} style={{ width: `${65 + ((i * 7 + p) % 30)}%` }} />
                  ))}
                </div>
              </div>
            ))}
          </div>
          <div className="muted" style={{ fontSize: 11.5, textAlign: 'center', marginTop: 10 }}>
            12 páginas · timeline + 4 certificados + cadena de evidencia + bitácora
          </div>
        </div>
      </div>
    </div>
  );
};

// ─── 4 · Capacitaciones vencidas ──────────────────────────

const ICONTECExpired = () => {
  return (
    <>
      <div className="ic-rp-banner rose">
        <div className="ic-rp-banner-shield">
          <IconAlert size={28} />
        </div>
        <div style={{ flex: 1 }}>
          <div className="ic-rp-banner-title" style={{ color: 'var(--rose-600)' }}>{ICONTEC_VENCIDAS.reduce((a, v) => a + v.count, 0)} capacitaciones vencidas requieren reasignación</div>
          <div className="ic-rp-banner-sub">
            <b>Todas son críticas (criticidad alta · ICONTEC).</b> El motor de automatización ya generó las nuevas asignaciones; las sesiones deben programarse antes de que la auditoría descubra la brecha.
          </div>
        </div>
        <button className="btn primary"><IconRocket size={14} /> Programar 7 sesiones</button>
      </div>

      <div className="ic-rp-card">
        <div className="ic-rp-card-head">
          <h3>Vencidas por competencia y área</h3>
          <span className="muted" style={{ fontSize: 12 }}>Ordenado por días vencidos promedio</span>
        </div>
        <div className="doc-list-card" style={{ border: 'none', boxShadow: 'none' }}>
          <table className="doc-table">
            <thead>
              <tr>
                <th>Competencia</th>
                <th>Área</th>
                <th style={{ textAlign: 'center' }}>Colaboradores</th>
                <th>Criticidad</th>
                <th style={{ textAlign: 'center' }}>Días vencidos (promedio)</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {ICONTEC_VENCIDAS.sort((a, b) => b.daysAvg - a.daysAvg).map((v, i) => (
                <tr key={i}>
                  <td data-label="Competencia">
                    <div style={{ fontWeight: 700, fontSize: 13 }}>{v.cmpName}</div>
                    <div className="muted mono" style={{ fontSize: 11 }}>{v.cmp}</div>
                  </td>
                  <td data-label="Área" className="muted" style={{ fontSize: 12.5 }}>{v.area}</td>
                  <td data-label="Colaboradores" style={{ textAlign: 'center' }} className="mono"><span style={{ color: 'var(--rose-600)', fontWeight: 800, fontSize: 16 }}>{v.count}</span></td>
                  <td data-label="Criticidad">
                    <span className="pill rose"><span className="status-dot" style={{ background: 'var(--rose-600)' }} /> Alta</span>
                  </td>
                  <td data-label="Días" style={{ textAlign: 'center' }}>
                    <span className="mono" style={{ fontWeight: 800, fontSize: 14, color: v.daysAvg > 20 ? 'var(--rose-600)' : 'var(--amber-600)' }}>{v.daysAvg} días</span>
                  </td>
                  <td>
                    <button className="btn primary" style={{ padding: '5px 11px', fontSize: 12 }}>
                      <IconRocket size={13} /> Programar
                    </button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </>
  );
};

// ─── 5 · Evaluaciones de competencia ──────────────────────

const ICONTECEvaluations = () => {
  return (
    <>
      <div className="ic-rp-stats-row">
        <div className="ic-rp-stat-card">
          <div className="muted-xs">Promedio global</div>
          <div className="ic-rp-stat-num">85.4 <small>/ 100</small></div>
          <div className="muted" style={{ fontSize: 11 }}>{ICONTEC_KPIS.evaluaciones}% de evaluaciones aplicadas</div>
        </div>
        <div className="ic-rp-stat-card">
          <div className="muted-xs">Aprobaron</div>
          <div className="ic-rp-stat-num pos">{ICONTEC_KPIS.certificados}</div>
          <div className="muted" style={{ fontSize: 11 }}>certificados emitidos · 82% del total</div>
        </div>
        <div className="ic-rp-stat-card">
          <div className="muted-xs">No conformidades</div>
          <div className="ic-rp-stat-num neg">{ICONTEC_KPIS.noConformidades}</div>
          <div className="muted" style={{ fontSize: 11 }}>colaboradores reprobaron · plan en curso</div>
        </div>
        <div className="ic-rp-stat-card">
          <div className="muted-xs">Cursos evaluados</div>
          <div className="ic-rp-stat-num">{ICONTEC_EVALS_BY_COURSE.length}</div>
          <div className="muted" style={{ fontSize: 11 }}>con preguntas configuradas</div>
        </div>
      </div>

      <div className="ic-rp-card">
        <div className="ic-rp-card-head">
          <h3>Evaluaciones por curso · distribución de notas</h3>
          <span className="muted" style={{ fontSize: 12 }}>Buckets: 0-40 / 41-60 / 61-75 / 76-90 / 91-100</span>
        </div>
        <div className="ic-rp-evals-list">
          {ICONTEC_EVALS_BY_COURSE.map(e => {
            const total = e.distribution.reduce((a, b) => a + b, 0);
            const pctOk = e.avg >= e.minScore;
            return (
              <div key={e.course} className="ic-rp-eval-row">
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontWeight: 700, fontSize: 13.5 }}>{e.course}</div>
                  <div className="muted" style={{ fontSize: 11.5, marginTop: 2 }}>
                    {e.sessions} sesiones · {e.count} evaluaciones aplicadas · mín. {e.minScore}/100
                  </div>
                </div>

                <div className="ic-rp-eval-bars">
                  {e.distribution.map((count, i) => {
                    const pct = (count / total) * 100;
                    const isReprob = i < 2;
                    return (
                      <div key={i} className="ic-rp-eval-bar-col" style={{ flex: count || 0.3 }}>
                        <div className={`ic-rp-eval-bar ${isReprob ? 'rose' : i < 3 ? 'amber' : 'green'}`} style={{ height: `${4 + pct * 0.7}px`, minHeight: 4 }} />
                        <div className="ic-rp-eval-bar-num mono">{count}</div>
                      </div>
                    );
                  })}
                </div>

                <div className="ic-rp-eval-avg">
                  <div className="muted-xs">Promedio</div>
                  <div className={`mono ${pctOk ? 'pos' : 'neg'}`} style={{ fontWeight: 800, fontSize: 18 }}>{e.avg}</div>
                </div>

                {e.noConformidades > 0 && (
                  <div className="ic-rp-eval-nc">
                    <span className="muted-xs">No conformidades</span>
                    <span className="mono" style={{ fontWeight: 800, fontSize: 16, color: 'var(--rose-600)' }}>{e.noConformidades}</span>
                  </div>
                )}
              </div>
            );
          })}
        </div>
      </div>
    </>
  );
};

window.Reports = Reports;
