// Payroll module — Nómina (módulo crítico v2)
// Period header · 5 KPIs · 7 sections · 3 modals
const { useState: _py_useState, useMemo: _py_useMemo } = React;

// ─── Master data ─────────────────────────────────────────

const PERIODS = [
  { id: 'P-2026-05', label: 'Mayo 2026',     freq: 'Mensual', state: 'liquidacion', cufe: null,         range: '01/05/2026 → 31/05/2026', closes: '28/05/2026', current: true },
  { id: 'P-2026-04', label: 'Abril 2026',    freq: 'Mensual', state: 'transmitido', cufe: 'fa78c2e1d9b4',range: '01/04/2026 → 30/04/2026', closes: '28/04/2026' },
  { id: 'P-2026-03', label: 'Marzo 2026',    freq: 'Mensual', state: 'transmitido', cufe: 'a4f2c1e89b7d',range: '01/03/2026 → 31/03/2026', closes: '28/03/2026' },
  { id: 'P-2026-02', label: 'Febrero 2026',  freq: 'Mensual', state: 'transmitido', cufe: 'b7e3d8a1f9c4',range: '01/02/2026 → 28/02/2026', closes: '26/02/2026' },
  { id: 'P-2026-01', label: 'Enero 2026',    freq: 'Mensual', state: 'transmitido', cufe: 'c2a1f4e7b9d3',range: '01/01/2026 → 31/01/2026', closes: '28/01/2026' },
];

const STATE_PERIOD = {
  abierto:      { label: 'Abierto',          pill: 'navy',       dot: 'var(--navy-800)' },
  liquidacion:  { label: 'En liquidación',   pill: 'amber-soft', dot: '#854D0E' },
  cerrado:      { label: 'Cerrado',          pill: 'green',      dot: 'var(--green-600)' },
  transmitido:  { label: 'Transmitido DIAN', pill: 'green',      dot: 'var(--green-600)' },
};

const PY_KPIS = {
  devengado: '$1,438,742,500',
  deducciones: '$108,540,200',
  neto: '$1,330,202,300',
  empleados: { value: 824, delta: '+18 vs. abril' },
  novedades: 47,
};

const STEPS = [
  { id: 1, label: 'Novedades registradas',           state: 'done',     when: '24/05/2026 17:00', who: 'Patricia Gómez',     subtitle: 'Fecha límite: 25/05/2026',     action: null },
  { id: 2, label: 'Validaciones previas',            state: 'done',     when: '25/05/2026 09:30', who: 'Sistema · 0 errores', subtitle: 'Sin errores críticos',         action: 'Ver bitácora' },
  { id: 3, label: 'Liquidación calculada',           state: 'current',  when: 'En proceso',       who: 'Carolina Restrepo',  subtitle: 'Procesando 824 empleados…',    action: 'Ver progreso' },
  { id: 4, label: 'Revisión y aprobación',           state: 'pending',  when: '—',                who: 'Dirección',          subtitle: 'Pendiente · doble validación', action: 'Iniciar revisión' },
  { id: 5, label: 'Generación de comprobantes',      state: 'pending',  when: '—',                who: 'Sistema',            subtitle: 'PDF firmado por colaborador',  action: null },
  { id: 6, label: 'Transmisión DIAN',                state: 'pending',  when: '—',                who: 'Sistema',            subtitle: 'Webservice nómina electrónica', action: null },
  { id: 7, label: 'Archivo banco',                   state: 'pending',  when: '—',                who: 'Patricia Gómez',     subtitle: 'Layout PSE / ACH',             action: null },
  { id: 8, label: 'Período cerrado',                 state: 'pending',  when: '—',                who: 'Carolina Restrepo',  subtitle: 'Inmutable · contraseña admin', action: null },
];

// ─── Liquidation rows (12 employees, mixed states) ────────

const LIQ = [
  { id: 'E0205', initials: 'CV', name: 'Carlos Andrés Vélez',  role: 'Operario de Clasificación', area: 'Operaciones',     site: 'Cali',
    days: 30, daysExtra: '27t · 3i', salary: 1620000,
    devengado: 1877375, deducciones: 279600, neto: 1597775,
    state: 'ok', extra: { extras: 57375, aux: 200000, libranza: 150000 } },
  { id: 'E0247', initials: 'AM', name: 'Andrés Felipe Mejía',  role: 'Operario de Clasificación', area: 'Operaciones',     site: 'Cali',
    days: 28, daysExtra: '28t', salary: 1450000,
    devengado: 1539584, deducciones: 108333, neto: 1431251,
    state: 'ok', extra: { aux: 186667, prorrate: true } },
  { id: 'E0198', initials: 'MF', name: 'María Fernanda López', role: 'Op. Aprovechamiento',         area: 'Aprovechamiento',        site: 'Cali',
    days: 30, daysExtra: '30t', salary: 1450000,
    devengado: 1650000, deducciones: 116000, neto: 1534000,
    state: 'warn', extra: { aux: 200000, novedadPendiente: 'Bonificación no constitutiva $200.000' } },
  { id: 'E0142', initials: 'DT', name: 'Diego Andrés Toro',    role: 'Aux. Aprovechamiento',        area: 'Aprovechamiento',        site: 'Cali',
    days: 30, daysExtra: '20t · 10v', salary: 1450000,
    devengado: 1650000, deducciones: 116000, neto: 1534000,
    state: 'ok', extra: { aux: 200000, vacaciones: '10 días pre-pagados marzo' } },
  { id: 'E0156', initials: 'PV', name: 'Paula Valencia Ríos',  role: 'Téc. Mantenimiento',  area: 'Mantenimiento',  site: 'Cali',
    days: 30, daysExtra: '30t', salary: 2250000,
    devengado: 2450000, deducciones: 180000, neto: 2270000,
    state: 'ok', extra: { aux: 200000 } },
  { id: 'E0067', initials: 'LM', name: 'Luis Miguel Marín',    role: 'Líder de Aprovechamiento',    area: 'Aprovechamiento',        site: 'Cali',
    days: 30, daysExtra: '30t', salary: 2800000,
    devengado: 2800000, deducciones: 224000, neto: 2576000,
    state: 'warn', extra: { novedadPendiente: 'Cambio de salario $2.500.000 → $2.800.000 sin aprobar' } },
  { id: 'E0177', initials: 'JP', name: 'Jorge Iván Patiño',    role: 'Conductor',           area: 'Recolección',   site: 'Barranquilla',
    days: 30, daysExtra: '30t', salary: 1850000,
    devengado: 2092500, deducciones: 348000, neto: 1744500,
    state: 'ok', extra: { extras: 242500, aux: 200000, embargo: 200000 } },
  { id: 'E0128', initials: 'NC', name: 'Nicolás Cárdenas',     role: 'Conductor',           area: 'Recolección',   site: 'Barranquilla',
    days: 30, daysExtra: '30t', salary: 1850000,
    devengado: 2050000, deducciones: 164000, neto: 1886000,
    state: 'ok', extra: { aux: 200000 } },
  { id: 'E0094', initials: 'MT', name: 'María Trujillo Henao', role: 'Aux. RRHH',           area: 'Administración', site: 'Cali',
    days: 30, daysExtra: '30t', salary: 2100000,
    devengado: 2300000, deducciones: 168000, neto: 2132000,
    state: 'ok', extra: { aux: 200000 } },
  { id: 'E0023', initials: 'CR', name: 'Carolina Restrepo S.', role: 'Jefe de RRHH',        area: 'Administración', site: 'Cali',
    days: 30, daysExtra: '30t', salary: 5500000,
    devengado: 5500000, deducciones: 580000, neto: 4920000,
    state: 'ok', extra: { retefuente: 140000 } },
  { id: 'E0244', initials: 'SO', name: 'Sandra Milena Ortiz',  role: 'Coord. Compras',      area: 'Administración', site: 'Bogotá',
    days: 30, daysExtra: '30t', salary: 3200000,
    devengado: 3200000, deducciones: 256000, neto: 2944000,
    state: 'ok', extra: {} },
  { id: 'E0011', initials: 'FH', name: 'Fernando Henao',       role: 'Operario Clasificación',    area: 'Operaciones',     site: 'Cali',
    days: 0,  daysExtra: '—',   salary: 1620000,
    devengado: 0, deducciones: 0, neto: 0,
    state: 'suspended', extra: { reason: 'Suspensión disciplinaria · período completo' } },
  { id: 'E0298', initials: 'AR', name: 'Adriana Restrepo',     role: 'Aux. Calidad',        area: 'Calidad',        site: 'Cali',
    days: 30, daysExtra: '30t', salary: 711750,
    devengado: 711750, deducciones: 0, neto: 711750,
    state: 'ok', extra: { contrato: 'Aprendizaje SENA · sin cotización empleado' } },
  { id: 'E0266', initials: 'OM', name: 'Oscar Marín Quintero', role: 'Aux. Calidad',        area: 'Calidad',        site: 'Barranquilla',
    days: 30, daysExtra: '30t', salary: 1620000,
    devengado: 1820000, deducciones: 129600, neto: 1690400,
    state: 'error', extra: { error: 'Cuenta bancaria no validada · imposible generar transferencia' } },
];

const STATE_LIQ = {
  ok:        { label: 'Calculado',  pill: 'green',      dot: 'var(--green-600)' },
  warn:      { label: 'Revisar',    pill: 'amber-soft', dot: '#854D0E' },
  error:     { label: 'Error',      pill: 'rose',       dot: 'var(--rose-600)' },
  suspended: { label: 'Suspendido', pill: 'navy',       dot: 'var(--text-muted)' },
};

// ─── Novedades ───────────────────────────────────────────

const NOVEDADES = [
  { id: 'N-2026-0421', type: 'incapacidad', emp: 'Carlos Andrés Vélez',  empId: 'E0205', period: '02-04/05/2026',  value: '3 días',     state: 'aplicada',   by: 'Patricia Gómez',  when: '04/05/2026 11:30' },
  { id: 'N-2026-0422', type: 'extras',      emp: 'Jorge Iván Patiño',    empId: 'E0177', period: 'Mayo 2026',      value: '6 horas',    state: 'aplicada',   by: 'Carolina Restrepo', when: '15/05/2026 16:42' },
  { id: 'N-2026-0423', type: 'salario',     emp: 'Luis Miguel Marín',    empId: 'E0067', period: 'Desde 01/05',    value: '+$300.000',  state: 'pendiente',  by: 'Carlos A. Gómez',   when: '20/05/2026 09:00' },
  { id: 'N-2026-0424', type: 'libranza',    emp: 'Carlos Andrés Vélez',  empId: 'E0205', period: '12 cuotas',      value: '$150.000/mes', state: 'aplicada', by: 'Patricia Gómez',  when: '01/02/2026 10:15' },
  { id: 'N-2026-0425', type: 'embargo',     emp: 'Jorge Iván Patiño',    empId: 'E0177', period: 'Hasta 12/2026',  value: '$200.000/mes', state: 'aplicada', by: 'Carolina Restrepo', when: '15/03/2026 14:00' },
  { id: 'N-2026-0426', type: 'vacaciones',  emp: 'Diego Andrés Toro',    empId: 'E0142', period: 'Marzo (informativa)', value: '10 días', state: 'aplicada', by: 'Patricia Gómez',  when: '02/03/2026 09:00' },
  { id: 'N-2026-0427', type: 'bonificacion',emp: 'María Fernanda López', empId: 'E0198', period: 'Mayo 2026',      value: '$200.000',   state: 'pendiente',  by: 'Luis Miguel Marín', when: '22/05/2026 17:30' },
  { id: 'N-2026-0428', type: 'suspension',  emp: 'Fernando Henao',       empId: 'E0011', period: 'Mayo 2026',      value: 'Período completo', state: 'aplicada', by: 'Carolina Restrepo', when: '30/04/2026 10:00' },
  { id: 'N-2026-0429', type: 'extras',      emp: 'Paula Valencia Ríos',  empId: 'E0156', period: 'Mayo 2026',      value: '8 horas',    state: 'pendiente',  by: 'Carlos A. Gómez',   when: '23/05/2026 11:00' },
];

const NOV_META = {
  incapacidad:  { label: 'Incapacidad',          tone: 'rose',  icon: 'IconAlert' },
  vacaciones:   { label: 'Vacaciones',           tone: 'blue',  icon: 'IconStar' },
  extras:       { label: 'Hora extra',           tone: 'amber', icon: 'IconClock' },
  prestamo:     { label: 'Préstamo',             tone: 'navy',  icon: 'IconDoc' },
  libranza:     { label: 'Libranza',             tone: 'navy',  icon: 'IconDoc' },
  embargo:      { label: 'Embargo judicial',     tone: 'rose',  icon: 'IconShield' },
  salario:      { label: 'Cambio de salario',    tone: 'amber', icon: 'IconBarChart' },
  suspension:   { label: 'Suspensión',           tone: 'rose',  icon: 'IconAlert' },
  bonificacion: { label: 'Bonificación',         tone: 'green', icon: 'IconStar' },
};

const STATE_NOV = {
  aplicada:   { label: 'Aplicada',   pill: 'green',      dot: 'var(--green-600)' },
  pendiente:  { label: 'Pendiente',  pill: 'amber-soft', dot: '#854D0E' },
  rechazada:  { label: 'Rechazada',  pill: 'rose',       dot: 'var(--rose-600)' },
};

// ─── Prestaciones sociales ────────────────────────────────

const PRESTACIONES = [
  { id: 'E0023', initials: 'CR', name: 'Carolina Restrepo S.', cesantias: 2291667, intCes: 91667,  prima: 2291667, vacaciones: 1145833, total: 5821000 },
  { id: 'E0067', initials: 'LM', name: 'Luis Miguel Marín',    cesantias: 1166667, intCes: 46667,  prima: 1166667, vacaciones: 583333,  total: 2963334 },
  { id: 'E0244', initials: 'SO', name: 'Sandra Milena Ortiz',  cesantias: 1333333, intCes: 53333,  prima: 1333333, vacaciones: 666667,  total: 3386666 },
  { id: 'E0156', initials: 'PV', name: 'Paula Valencia Ríos',  cesantias: 937500,  intCes: 37500,  prima: 937500,  vacaciones: 468750,  total: 2381250 },
  { id: 'E0094', initials: 'MT', name: 'María Trujillo Henao', cesantias: 875000,  intCes: 35000,  prima: 875000,  vacaciones: 437500,  total: 2222500 },
  { id: 'E0205', initials: 'CV', name: 'Carlos Andrés Vélez',  cesantias: 675000,  intCes: 27000,  prima: 675000,  vacaciones: 337500,  total: 1714500 },
  { id: 'E0177', initials: 'JP', name: 'Jorge Iván Patiño',    cesantias: 770833,  intCes: 30833,  prima: 770833,  vacaciones: 385417,  total: 1957916 },
  { id: 'E0198', initials: 'MF', name: 'María Fernanda López', cesantias: 604167,  intCes: 24167,  prima: 604167,  vacaciones: 302083,  total: 1534584 },
];

const PRESTACIONES_DEADLINES = [
  { date: '14/02/2026', label: 'Consignación cesantías al fondo',   detail: 'Plazo legal · Ley 50 de 1990 · todos los empleados con corte 31/12/2025', past: true },
  { date: '30/06/2026', label: 'Primera quincena de prima',          detail: 'Pago primer semestre · todos los empleados causados', past: false, days: 56 },
  { date: '20/12/2026', label: 'Segunda quincena de prima',          detail: 'Pago segundo semestre · todos los empleados causados', past: false, days: 229 },
];

// ─── DIAN ─────────────────────────────────────────────────

const DIAN_TIMELINE = [
  { when: '23/05/2026 10:15', text: 'XML generado por Patricia Gómez',       state: 'done', icon: 'IconDoc' },
  { when: '23/05/2026 10:17', text: 'Vista previa aprobada por Carolina Restrepo', state: 'done', icon: 'IconCheck' },
  { when: '23/05/2026 10:18', text: 'Documento firmado digitalmente',         state: 'done', icon: 'IconShield' },
  { when: '23/05/2026 10:18', text: 'Transmitido al webservice DIAN',         state: 'done', icon: 'IconExternal' },
  { when: '23/05/2026 10:19', text: 'Aceptado · CUFE generado',                state: 'done', icon: 'IconCheck' },
];

const DIAN_HIST = [
  { period: 'Abril 2026',   when: '23/04/2026 11:42', cufe: 'fa78c2e1d9b4a3f8c5e2b9d7f1a4c6e8b3d2f9a7c1e5', state: 'aceptado' },
  { period: 'Marzo 2026',   when: '24/03/2026 09:55', cufe: 'a4f2c1e89b7d3f5e26c8d4b1a9f3e7c5d8b2a4f6e9c1', state: 'aceptado' },
  { period: 'Febrero 2026', when: '22/02/2026 14:28', cufe: 'b7e3d8a1f9c4e2b6d8a3f5e7c9b1d4f6e8a2c5b7d9e1', state: 'aceptado' },
];

// ─── Banco · layout de pago ──────────────────────────────

const BANK_FILES = [
  { id: 'BNK-2026-04-001', period: 'Abril 2026',  bank: 'Davivienda · ACH', file: 'pago-2026-04.txt', count: 824, total: '$1,309,847,250', when: '28/04/2026 16:45', state: 'confirmed' },
  { id: 'BNK-2026-03-001', period: 'Marzo 2026',  bank: 'Davivienda · ACH', file: 'pago-2026-03.txt', count: 821, total: '$1,295,420,800', when: '28/03/2026 17:02', state: 'confirmed' },
  { id: 'BNK-2026-02-001', period: 'Febrero 2026',bank: 'Bancolombia · PSE',file: 'pago-2026-02.csv', count: 818, total: '$1,278,950,400', when: '26/02/2026 15:38', state: 'confirmed' },
];

const BANK_DIST = [
  { bank: 'Davivienda', count: 612, share: 74 },
  { bank: 'Bancolombia', count: 142, share: 17 },
  { bank: 'Banco de Bogotá', count: 48, share: 6 },
  { bank: 'AV Villas',     count: 22, share: 3 },
];

// ─── Historial ────────────────────────────────────────────

const HISTORY = [
  { period: 'Abril 2026',   count: 824, neto: '$1,309,847,250', state: 'transmitido', cufe: 'fa78c2e1d9b4a3f8' },
  { period: 'Marzo 2026',   count: 821, neto: '$1,295,420,800', state: 'transmitido', cufe: 'a4f2c1e89b7d3f5e' },
  { period: 'Febrero 2026', count: 818, neto: '$1,278,950,400', state: 'transmitido', cufe: 'b7e3d8a1f9c4e2b6' },
  { period: 'Enero 2026',   count: 815, neto: '$1,272,388,200', state: 'transmitido', cufe: 'c2a1f4e7b9d3a5c8' },
  { period: 'Diciembre 2025',count: 814, neto: '$1,820,440,500', state: 'transmitido', cufe: 'd5b8c2f9a3e7d1b4', note: 'Incluye prima diciembre' },
  { period: 'Noviembre 2025',count: 812, neto: '$1,261,884,300', state: 'transmitido', cufe: 'e1d4a7c2b5f9e3d6' },
];

// ─── Helpers ──────────────────────────────────────────────

const fmt = (n) => '$' + Math.round(n).toLocaleString('es-CO');

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

const Payroll = () => {
  const [section, setSection]       = _py_useState('panel');
  const [selectedEmp, setSelectedEmp] = _py_useState(null);
  const [novedadOpen, setNovedadOpen] = _py_useState(false);
  const [closeOpen, setCloseOpen]     = _py_useState(false);
  const [comprobante, setComprobante] = _py_useState(null);
  const [periodId, setPeriodId]       = _py_useState('P-2026-05');

  const period = PERIODS.find(p => p.id === periodId);
  const ps = STATE_PERIOD[period.state];

  const novedadesPendientes = NOVEDADES.filter(n => n.state === 'pendiente');

  return (
    <div className="main" data-screen-label="Nómina">
      <div className="page-head">
        <div>
          <h1 className="page-title">Nómina</h1>
          <div className="page-subtitle">
            <b>Período activo:</b> {period.label} · {period.freq} · cierra el {period.closes}
          </div>
        </div>
        <div className="py-period-bar">
          <span className={`pill ${ps.pill}`}>
            <span className="status-dot" style={{ background: ps.dot }} /> {ps.label}
          </span>
          <select className="py-period-select" value={periodId} onChange={(e) => setPeriodId(e.target.value)}>
            {PERIODS.map(p => (
              <option key={p.id} value={p.id}>
                {p.id} · {p.label} · {STATE_PERIOD[p.state].label}
              </option>
            ))}
          </select>
        </div>
      </div>

      {/* Critical alert if pending novedades close to deadline */}
      {novedadesPendientes.length > 0 && section !== 'novedades' && (
        <div className="py-alert" onClick={() => setSection('novedades')}>
          <span className="py-alert-icon"><IconAlert size={16} /></span>
          <div style={{ flex: 1 }}>
            <div className="py-alert-title">
              Hay {novedadesPendientes.length} novedades pendientes de aprobación
            </div>
            <div className="py-alert-sub">
              El período cierra el <b>{period.closes}</b>. Las novedades no aprobadas no se incluirán en la liquidación de {period.label}.
            </div>
          </div>
          <button className="btn danger solid" style={{ padding: '6px 12px', fontSize: 12.5 }} onClick={(e) => { e.stopPropagation(); setSection('novedades'); }}>
            Ver novedades
          </button>
        </div>
      )}

      {/* 5 KPIs */}
      <div className="py-kpis">
        <div className="py-kpi">
          <div className="muted-xs">Total devengado</div>
          <div className="py-kpi-num">{PY_KPIS.devengado}</div>
          <div className="muted" style={{ fontSize: 11.5 }}>{period.label} · COP</div>
        </div>
        <div className="py-kpi">
          <div className="muted-xs">Total deducciones</div>
          <div className="py-kpi-num neg">−{PY_KPIS.deducciones}</div>
          <div className="muted" style={{ fontSize: 11.5 }}>Salud + pensión + retención + libranzas</div>
        </div>
        <div className="py-kpi highlight">
          <div className="muted-xs" style={{ color: 'rgba(255,255,255,0.7)' }}>Neto a pagar</div>
          <div className="py-kpi-num pos">{PY_KPIS.neto}</div>
          <div style={{ fontSize: 11.5, color: 'rgba(255,255,255,0.85)' }}>Suma de transferencias bancarias</div>
        </div>
        <div className="py-kpi">
          <div className="muted-xs">Colaboradores</div>
          <div className="py-kpi-num">{PY_KPIS.empleados.value}</div>
          <div className="py-kpi-foot up">↑ {PY_KPIS.empleados.delta}</div>
        </div>
        <div className="py-kpi">
          <div className="muted-xs">Novedades del período</div>
          <div className="py-kpi-num">{PY_KPIS.novedades}</div>
          <div className="muted" style={{ fontSize: 11.5 }}>{novedadesPendientes.length} pendientes de aprobación</div>
        </div>
      </div>

      {/* Section tabs */}
      <div className="doc-tabs py-tabs">
        <button className={`doc-tab ${section === 'panel' ? 'active' : ''}`}        onClick={() => setSection('panel')}><IconBarChart size={14} /> Panel</button>
        <button className={`doc-tab ${section === 'liquidation' ? 'active' : ''}`}  onClick={() => setSection('liquidation')}><IconUsers size={14} /> Liquidación <span className="epp-tab-pill">{LIQ.length}</span></button>
        <button className={`doc-tab ${section === 'novedades' ? 'active' : ''}`}    onClick={() => setSection('novedades')}><IconAlert size={14} /> Novedades {novedadesPendientes.length > 0 && <span className="epp-tab-pill rose">{novedadesPendientes.length}</span>}</button>
        <button className={`doc-tab ${section === 'prestaciones' ? 'active' : ''}`} onClick={() => setSection('prestaciones')}><IconStar size={14} /> Prestaciones</button>
        <button className={`doc-tab ${section === 'dian' ? 'active' : ''}`}         onClick={() => setSection('dian')}><IconShield size={14} /> Nómina DIAN</button>
        <button className={`doc-tab ${section === 'banco' ? 'active' : ''}`}        onClick={() => setSection('banco')}><IconExternal size={14} /> Archivo banco</button>
        <button className={`doc-tab ${section === 'historial' ? 'active' : ''}`}    onClick={() => setSection('historial')}><IconClock size={14} /> Historial</button>
      </div>

      {section === 'panel'        && <PanelSection onClose={() => setCloseOpen(true)} onLiquidation={() => setSection('liquidation')} />}
      {section === 'liquidation'  && <LiquidationSection onSelect={(e) => setSelectedEmp(e)} onComprobante={(e) => setComprobante(e)} />}
      {section === 'novedades'    && <NovedadesSection onNew={() => setNovedadOpen(true)} period={period} />}
      {section === 'prestaciones' && <PrestacionesSection />}
      {section === 'dian'         && <DianSection />}
      {section === 'banco'        && <BankSection />}
      {section === 'historial'    && <HistorialSection />}

      {selectedEmp && <EmployeeDrawer emp={selectedEmp} period={period} onClose={() => setSelectedEmp(null)} onComprobante={() => setComprobante(selectedEmp)} />}
      {novedadOpen && <NovedadModal onClose={() => setNovedadOpen(false)} />}
      {closeOpen   && <CloseModal period={period} onClose={() => setCloseOpen(false)} />}
      {comprobante && <ComprobanteModal emp={comprobante} period={period} onClose={() => setComprobante(null)} />}
    </div>
  );
};

// ─── Panel section (8-step progress + summary) ───────────

const PanelSection = ({ onClose, onLiquidation }) => {
  const completed = STEPS.filter(s => s.state === 'done').length;
  const pct = Math.round((completed / STEPS.length) * 100);

  return (
    <>
      <div className="py-card">
        <div className="py-card-head">
          <div>
            <div className="muted-xs">Estado del proceso</div>
            <h3 className="py-card-title">Liquidación · {pct}% completado</h3>
            <div className="muted" style={{ fontSize: 12.5, marginTop: 3 }}>{completed} de {STEPS.length} pasos completados · 5 pasos pendientes para cerrar el período</div>
          </div>
          <button className="btn primary" onClick={onLiquidation}><IconExternal size={14} /> Ir a liquidación</button>
        </div>

        <div className="py-progress-bar">
          <div className="py-progress-fill" style={{ width: `${pct}%` }} />
        </div>

        <div className="py-steps">
          {STEPS.map(s => (
            <div key={s.id} className={`py-step py-step-${s.state}`}>
              <div className="py-step-num">
                {s.state === 'done'    ? <IconCheck size={13} />
                 : s.state === 'current' ? <span className="py-step-spin" />
                 : s.id}
              </div>
              <div className="py-step-body">
                <div className="py-step-label">{s.label}</div>
                <div className="muted" style={{ fontSize: 11.5, marginTop: 2 }}>
                  {s.subtitle}
                </div>
                <div className="py-step-meta">
                  {s.state === 'done' && <><IconCheck size={11} /> {s.when} · {s.who}</>}
                  {s.state === 'current' && <><IconClock size={11} /> {s.who} · {s.when}</>}
                  {s.state === 'pending' && <><span className="muted">Pendiente · {s.who}</span></>}
                </div>
              </div>
              {s.action && (
                <button className={`btn ${s.state === 'current' ? 'primary' : ''}`} style={{ padding: '5px 11px', fontSize: 12 }}>
                  {s.action}
                </button>
              )}
            </div>
          ))}
        </div>

        <div className="py-panel-actions">
          <button className="btn"><IconExternal size={13} /> Recalcular liquidación</button>
          <div style={{ flex: 1 }} />
          <button className="btn danger solid" onClick={onClose}>
            <IconShield size={13} /> Cerrar período
          </button>
        </div>
      </div>

      {/* Resumen de validaciones */}
      <div className="py-card">
        <div className="py-card-head">
          <div>
            <h3 className="py-card-title">Validaciones de integridad</h3>
            <div className="muted" style={{ fontSize: 12.5, marginTop: 3 }}>Reglas de negocio que el sistema verifica antes de cada liquidación</div>
          </div>
        </div>
        <div className="py-checks">
          <div className="py-check ok"><span className="py-check-dot"><IconCheck size={11} /></span><div><div style={{ fontWeight: 600, fontSize: 12.5 }}>Salarios no inferiores a SMMLV</div><div className="muted" style={{ fontSize: 11.5 }}>824 verificados · ninguno por debajo del mínimo legal</div></div></div>
          <div className="py-check ok"><span className="py-check-dot"><IconCheck size={11} /></span><div><div style={{ fontWeight: 600, fontSize: 12.5 }}>Cuentas bancarias activas</div><div className="muted" style={{ fontSize: 11.5 }}>823 verificadas · 1 con error de validación bancaria</div></div></div>
          <div className="py-check ok"><span className="py-check-dot"><IconCheck size={11} /></span><div><div style={{ fontWeight: 600, fontSize: 12.5 }}>EPS y AFP afiliaciones vigentes</div><div className="muted" style={{ fontSize: 11.5 }}>824 verificadas · todas activas en RUAF</div></div></div>
          <div className="py-check warn"><span className="py-check-dot warn"><IconAlert size={11} /></span><div><div style={{ fontWeight: 600, fontSize: 12.5 }}>Novedades dentro del plazo</div><div className="muted" style={{ fontSize: 11.5 }}>3 novedades pendientes de aprobación · cierre 28/05</div></div></div>
          <div className="py-check ok"><span className="py-check-dot"><IconCheck size={11} /></span><div><div style={{ fontWeight: 600, fontSize: 12.5 }}>Topes legales (IBC máx 25 SMMLV)</div><div className="muted" style={{ fontSize: 11.5 }}>4 empleados con tope aplicado · cálculo correcto</div></div></div>
          <div className="py-check ok"><span className="py-check-dot"><IconCheck size={11} /></span><div><div style={{ fontWeight: 600, fontSize: 12.5 }}>Retención en la fuente</div><div className="muted" style={{ fontSize: 11.5 }}>Tabla 2026 vigente · cálculo automático verificado</div></div></div>
        </div>
      </div>
    </>
  );
};

// ─── Liquidation table ───────────────────────────────────

const LiquidationSection = ({ onSelect, onComprobante }) => {
  const [filter, setFilter] = _py_useState('todos');
  const counts = {
    todos:     LIQ.length,
    ok:        LIQ.filter(e => e.state === 'ok').length,
    warn:      LIQ.filter(e => e.state === 'warn').length,
    error:     LIQ.filter(e => e.state === 'error').length,
    suspended: LIQ.filter(e => e.state === 'suspended').length,
  };
  const list = filter === 'todos' ? LIQ : LIQ.filter(e => e.state === filter);

  return (
    <>
      <div className="sst-quickfilter">
        <button className={`sst-chip ${filter === 'todos' ? 'active' : ''}`}      onClick={() => setFilter('todos')}>Todos <span className="sst-chip-count">{counts.todos}</span></button>
        <button className={`sst-chip green ${filter === 'ok' ? 'active' : ''}`}   onClick={() => setFilter('ok')}>Calculados <span className="sst-chip-count">{counts.ok}</span></button>
        <button className={`sst-chip amber ${filter === 'warn' ? 'active' : ''}`} onClick={() => setFilter('warn')}>A revisar <span className="sst-chip-count">{counts.warn}</span></button>
        <button className={`sst-chip rose ${filter === 'error' ? 'active' : ''}`} onClick={() => setFilter('error')}>Con error <span className="sst-chip-count">{counts.error}</span></button>
        <button className={`sst-chip ${filter === 'suspended' ? 'active' : ''}`}  onClick={() => setFilter('suspended')}>Suspendidos <span className="sst-chip-count">{counts.suspended}</span></button>
        <div style={{ flex: 1 }} />
        <div className="ob-search" style={{ maxWidth: 260 }}>
          <IconSearch size={14} />
          <input placeholder="Buscar empleado o ID…" />
        </div>
        <button className="btn"><IconExternal size={14} /> Exportar</button>
      </div>

      <div className="doc-list-card">
        <table className="doc-table py-liq-table">
          <thead>
            <tr>
              <th>Empleado</th>
              <th>Cargo</th>
              <th style={{ textAlign: 'center' }}>Días</th>
              <th style={{ textAlign: 'right' }}>Salario base</th>
              <th style={{ textAlign: 'right' }}>Devengado</th>
              <th style={{ textAlign: 'right' }}>Deducciones</th>
              <th style={{ textAlign: 'right' }}>Neto</th>
              <th>Estado</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {list.map(e => {
              const s = STATE_LIQ[e.state];
              return (
                <tr key={e.id} className={`py-liq-row py-liq-${e.state}`} onClick={() => onSelect(e)}>
                  <td data-label="Empleado">
                    <div className="doc-cell-emp">
                      <div className="doc-avatar">{e.initials}</div>
                      <div>
                        <div style={{ fontWeight: 600, fontSize: 13 }}>{e.name}</div>
                        <div className="muted mono" style={{ fontSize: 11 }}>{e.id} · {e.site}</div>
                      </div>
                    </div>
                  </td>
                  <td data-label="Cargo" className="muted" style={{ fontSize: 12.5 }}>{e.role}</td>
                  <td data-label="Días" style={{ textAlign: 'center' }}>
                    <span className="py-days-num">{e.days}</span>
                    <div className="muted mono" style={{ fontSize: 10.5 }}>{e.daysExtra}</div>
                  </td>
                  <td data-label="Salario" style={{ textAlign: 'right' }} className="mono">{fmt(e.salary)}</td>
                  <td data-label="Devengado" style={{ textAlign: 'right' }} className="mono">{fmt(e.devengado)}</td>
                  <td data-label="Deducciones" style={{ textAlign: 'right' }} className="mono">
                    <span className="py-amount-neg">−{fmt(e.deducciones)}</span>
                  </td>
                  <td data-label="Neto" style={{ textAlign: 'right' }}>
                    <span className="py-net">{fmt(e.neto)}</span>
                  </td>
                  <td data-label="Estado">
                    <span className={`pill ${s.pill}`} title={e.extra.error || e.extra.novedadPendiente || e.extra.reason || ''}>
                      <span className="status-dot" style={{ background: s.dot }} /> {s.label}
                    </span>
                    {e.state === 'error' && (
                      <div className="py-error-tooltip"><IconAlert size={10} /> {e.extra.error}</div>
                    )}
                    {e.state === 'warn' && (
                      <div className="py-warn-tooltip">{e.extra.novedadPendiente}</div>
                    )}
                  </td>
                  <td data-label="Acciones">
                    <div className="doc-actions">
                      <button className="icon-action" title="Ver detalle"><IconExternal size={14} /></button>
                      <button className="icon-action" title="Comprobante" onClick={(ev) => { ev.stopPropagation(); onComprobante(e); }}>
                        <IconDoc size={14} />
                      </button>
                    </div>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
        <div className="doc-table-foot">
          <span className="muted" style={{ fontSize: 12 }}>{list.length} de 824 colaboradores · vista filtrada</span>
          <div style={{ display: 'flex', gap: 14, fontSize: 12 }}>
            <span className="muted">Suma devengado: <b className="mono" style={{ color: 'var(--text)' }}>{fmt(list.reduce((s, e) => s + e.devengado, 0))}</b></span>
            <span className="muted">Suma neto: <b className="mono" style={{ color: 'var(--green-600)' }}>{fmt(list.reduce((s, e) => s + e.neto, 0))}</b></span>
          </div>
        </div>
      </div>
    </>
  );
};

// ─── Employee detail drawer (4 tabs) ─────────────────────

const EmployeeDrawer = ({ emp, period, onClose, onComprobante }) => {
  const [tab, setTab] = _py_useState('devengados');

  React.useEffect(() => {
    document.body.style.overflow = 'hidden';
    const onEsc = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onEsc);
    return () => { document.body.style.overflow = ''; window.removeEventListener('keydown', onEsc); };
  }, []);

  // Reasonable mock breakdowns
  const aux = emp.salary < 2847000 ? 200000 : 0; // 2 SMMLV cap for transport allowance
  const horasDiu = (emp.extra.extras && emp.id === 'E0205') ? 33750 : 0;
  const horasNoc = (emp.extra.extras && emp.id === 'E0205') ? 23625 : 0;
  const horasJP  = emp.id === 'E0177' ? 242500 : 0;
  const ibc = Math.round(emp.salary);
  const salud = Math.round(ibc * 0.04);
  const pension = Math.round(ibc * 0.04);
  const fsp = ibc > 5694000 ? Math.round(ibc * 0.01) : 0;
  const retefuente = emp.extra.retefuente || 0;
  const libranza  = emp.extra.libranza || 0;
  const embargo   = emp.extra.embargo || 0;

  return (
    <div className="tr-side-overlay" onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="tr-side-panel" style={{ width: 720 }}>
        <div className="tr-side-head">
          <div style={{ display: 'flex', gap: 12, minWidth: 0, flex: 1 }}>
            <div className="doc-avatar" style={{ width: 48, height: 48, fontSize: 14, borderRadius: 12 }}>{emp.initials}</div>
            <div style={{ minWidth: 0 }}>
              <div className="tr-side-title">{emp.name}</div>
              <div className="muted" style={{ fontSize: 12, marginTop: 4 }}>
                {emp.role} · {emp.site} · <span className="mono">{emp.id}</span>
              </div>
              <div className="muted" style={{ fontSize: 11.5, marginTop: 4 }}>
                Período {period.label} · {emp.daysExtra} · contrato según matriz de cargo
              </div>
            </div>
          </div>
          <button className="icon-btn" onClick={onClose} title="Cerrar">
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M18 6 6 18M6 6l12 12" /></svg>
          </button>
        </div>

        <div className="py-drawer-net">
          <div>
            <div className="muted-xs" style={{ color: 'rgba(255,255,255,0.7)' }}>Neto a pagar este período</div>
            <div className="py-drawer-net-num">{fmt(emp.neto)}</div>
          </div>
          <div className="py-drawer-net-side">
            <div><div className="muted-xs" style={{ color: 'rgba(255,255,255,0.7)' }}>Devengado</div><div className="mono" style={{ fontWeight: 700, fontSize: 14 }}>{fmt(emp.devengado)}</div></div>
            <div><div className="muted-xs" style={{ color: 'rgba(255,255,255,0.7)' }}>Deducciones</div><div className="mono" style={{ fontWeight: 700, fontSize: 14 }}>−{fmt(emp.deducciones)}</div></div>
          </div>
        </div>

        <div className="py-drawer-tabs">
          <button className={`py-drawer-tab ${tab === 'devengados' ? 'active' : ''}`} onClick={() => setTab('devengados')}>Devengados</button>
          <button className={`py-drawer-tab ${tab === 'deducciones' ? 'active' : ''}`} onClick={() => setTab('deducciones')}>Deducciones</button>
          <button className={`py-drawer-tab ${tab === 'aportes' ? 'active' : ''}`} onClick={() => setTab('aportes')}>Aportes empleador</button>
          <button className={`py-drawer-tab ${tab === 'ibc' ? 'active' : ''}`} onClick={() => setTab('ibc')}>IBC</button>
        </div>

        <div className="tr-side-body" style={{ padding: '16px 22px' }}>

          {tab === 'devengados' && (
            <table className="py-detail-table">
              <thead>
                <tr><th>Concepto</th><th style={{ textAlign: 'right' }}>Días/Unidad</th><th style={{ textAlign: 'right' }}>Valor</th></tr>
              </thead>
              <tbody>
                <tr><td>Salario básico</td><td className="mono">{emp.days} días</td><td className="mono">{fmt(emp.salary * emp.days / 30)}</td></tr>
                {aux > 0 && <tr><td>Auxilio de transporte</td><td className="mono">{emp.days} días</td><td className="mono">{fmt(aux * emp.days / 30)}</td></tr>}
                {horasDiu > 0 && <tr><td>Horas extras diurnas</td><td className="mono">4 horas</td><td className="mono">{fmt(horasDiu)}</td></tr>}
                {horasNoc > 0 && <tr><td>Horas extras nocturnas</td><td className="mono">2 horas</td><td className="mono">{fmt(horasNoc)}</td></tr>}
                {horasJP > 0 && <tr><td>Horas extras (incluye recargo nocturno)</td><td className="mono">6 horas</td><td className="mono">{fmt(horasJP)}</td></tr>}
                {emp.id === 'E0205' && <tr><td className="muted">Incapacidad común (66%)</td><td className="mono">3 días</td><td className="mono muted">incluido en salario</td></tr>}
                <tr className="py-detail-total">
                  <td><b>TOTAL DEVENGADO</b></td>
                  <td></td>
                  <td className="mono"><b>{fmt(emp.devengado)}</b></td>
                </tr>
              </tbody>
            </table>
          )}

          {tab === 'deducciones' && (
            <table className="py-detail-table">
              <thead>
                <tr><th>Concepto</th><th style={{ textAlign: 'right' }}>Base</th><th style={{ textAlign: 'right' }}>%</th><th style={{ textAlign: 'right' }}>Valor</th></tr>
              </thead>
              <tbody>
                {emp.state === 'suspended' || emp.id === 'E0298' ? (
                  <tr><td colSpan={4} style={{ textAlign: 'center', padding: 24, color: 'var(--text-muted)', fontSize: 12.5 }}>
                    {emp.id === 'E0298' ? 'Aprendizaje SENA · sin cotización empleado' : 'Empleado suspendido · no aplica deducción'}
                  </td></tr>
                ) : (
                  <>
                    <tr><td>Salud empleado</td><td className="mono">IBC {fmt(ibc)}</td><td className="mono">4%</td><td className="mono">{fmt(salud)}</td></tr>
                    <tr><td>Pensión empleado</td><td className="mono">IBC {fmt(ibc)}</td><td className="mono">4%</td><td className="mono">{fmt(pension)}</td></tr>
                    {fsp > 0 && <tr><td>FSP · Fondo solidaridad pensional</td><td className="mono">IBC</td><td className="mono">1%</td><td className="mono">{fmt(fsp)}</td></tr>}
                    {retefuente > 0 && <tr><td>Retención en la fuente</td><td className="mono">Base {fmt(emp.devengado * 0.75)}</td><td>—</td><td className="mono">{fmt(retefuente)}</td></tr>}
                    {libranza > 0 && <tr><td>Libranza Banco · cuota 4 de 12</td><td>—</td><td>—</td><td className="mono">{fmt(libranza)}</td></tr>}
                    {embargo > 0 && <tr><td>Embargo judicial · pensión alimenticia</td><td>—</td><td>—</td><td className="mono">{fmt(embargo)}</td></tr>}
                  </>
                )}
                <tr className="py-detail-subtotal">
                  <td><b>TOTAL DEDUCCIONES</b></td><td></td><td></td>
                  <td className="mono"><b>−{fmt(emp.deducciones)}</b></td>
                </tr>
                <tr className="py-detail-net">
                  <td><b>NETO A PAGAR</b></td><td></td><td></td>
                  <td className="mono"><b>{fmt(emp.neto)}</b></td>
                </tr>
              </tbody>
            </table>
          )}

          {tab === 'aportes' && (
            <>
              <div className="muted" style={{ fontSize: 12, marginBottom: 10 }}>
                <IconShield size={11} /> Estos valores los paga el empleador y <b>no afectan el neto del colaborador</b>. Sirven para calcular el costo total del empleado.
              </div>
              <table className="py-detail-table">
                <thead>
                  <tr><th>Concepto</th><th style={{ textAlign: 'right' }}>Base</th><th style={{ textAlign: 'right' }}>%</th><th style={{ textAlign: 'right' }}>Valor</th></tr>
                </thead>
                <tbody>
                  <tr><td>Salud empleador</td><td className="mono">IBC {fmt(ibc)}</td><td className="mono">8.5%</td><td className="mono">{fmt(ibc * 0.085)}</td></tr>
                  <tr><td>Pensión empleador</td><td className="mono">IBC {fmt(ibc)}</td><td className="mono">12%</td><td className="mono">{fmt(ibc * 0.12)}</td></tr>
                  <tr><td>ARL · Sura · clase {emp.role.includes('Mantenimiento') ? 'V' : emp.role.includes('Clasificación') ? 'III' : 'I'}</td><td className="mono">IBC</td><td className="mono">{emp.role.includes('Mantenimiento') ? '6.960%' : emp.role.includes('Clasificación') ? '2.436%' : '0.522%'}</td><td className="mono">{fmt(ibc * (emp.role.includes('Mantenimiento') ? 0.0696 : emp.role.includes('Clasificación') ? 0.02436 : 0.00522))}</td></tr>
                  <tr><td>SENA</td><td className="mono">Nómina</td><td className="mono">2%</td><td className="mono">{fmt(emp.salary * 0.02)}</td></tr>
                  <tr><td>ICBF</td><td className="mono">Nómina</td><td className="mono">3%</td><td className="mono">{fmt(emp.salary * 0.03)}</td></tr>
                  <tr><td>Caja Compensación · Comfamiliar</td><td className="mono">Nómina</td><td className="mono">4%</td><td className="mono">{fmt(emp.salary * 0.04)}</td></tr>
                  <tr className="py-detail-total">
                    <td><b>COSTO TOTAL EMPLEADO</b></td><td></td><td></td>
                    <td className="mono"><b>{fmt(emp.devengado + ibc * 0.205 + emp.salary * 0.09 + ibc * (emp.role.includes('Mantenimiento') ? 0.0696 : emp.role.includes('Clasificación') ? 0.02436 : 0.00522))}</b></td>
                  </tr>
                </tbody>
              </table>
            </>
          )}

          {tab === 'ibc' && (
            <>
              <div className="py-ibc-card">
                <div className="muted-xs">Ingreso Base de Cotización · IBC</div>
                <div className="py-ibc-num">{fmt(ibc)}</div>
                <div className="muted" style={{ fontSize: 11.5, marginTop: 2 }}>
                  Tope legal: 25 SMMLV · {fmt(1423500 * 25)} · {ibc > 1423500 * 25 ? 'tope aplicado' : 'sin tope · cotiza al 100%'}
                </div>
              </div>

              <div className="py-card-title" style={{ fontSize: 13.5, marginTop: 18, marginBottom: 6 }}>Conceptos que ENTRAN al IBC</div>
              <ul className="py-ibc-list">
                <li><IconCheck size={11} /> Salario básico</li>
                <li><IconCheck size={11} /> Comisiones</li>
                <li><IconCheck size={11} /> Horas extras</li>
                <li><IconCheck size={11} /> Recargos nocturnos, dominicales, festivos</li>
                <li><IconCheck size={11} /> Bonificaciones constitutivas de salario (pactadas)</li>
              </ul>

              <div className="py-card-title" style={{ fontSize: 13.5, marginTop: 18, marginBottom: 6 }}>Conceptos que NO entran al IBC</div>
              <ul className="py-ibc-list muted-list">
                <li>Auxilio de transporte (no es salario · Ley 15 de 1959)</li>
                <li>Bonificaciones no constitutivas de salario (con acuerdo escrito · Art. 128 CST)</li>
                <li>Gastos de representación (con justificación)</li>
                <li>Viáticos ocasionales</li>
                <li>Indemnizaciones</li>
              </ul>

              {emp.salary <= 2847000 && (
                <div className="py-ibc-banner ok">
                  <IconCheck size={14} />
                  <div>
                    <div style={{ fontWeight: 700, fontSize: 12.5 }}>Aplica exoneración de aportes parafiscales</div>
                    <div className="muted" style={{ fontSize: 11.5, marginTop: 2 }}>
                      Salario inferior a 10 SMMLV · empleador exonerado de SENA, ICBF y salud (8.5%) según Art. 114-1 ET.
                    </div>
                  </div>
                </div>
              )}
              {ibc > 1423500 * 25 && (
                <div className="py-ibc-banner warn">
                  <IconAlert size={14} />
                  <div>
                    <div style={{ fontWeight: 700, fontSize: 12.5 }}>IBC supera el tope de 25 SMMLV</div>
                    <div className="muted" style={{ fontSize: 11.5, marginTop: 2 }}>
                      Cotización limitada al tope legal · {fmt(1423500 * 25)}
                    </div>
                  </div>
                </div>
              )}
            </>
          )}

        </div>

        <div className="tr-side-foot">
          <button className="btn"><IconExternal size={13} /> Ver historial de novedades</button>
          <div style={{ flex: 1 }} />
          <button className="btn primary" onClick={onComprobante}>
            <IconDoc size={13} /> Ver comprobante de pago
          </button>
        </div>
      </div>
    </div>
  );
};

// ─── Novedades section ───────────────────────────────────

const NovedadesSection = ({ onNew, period }) => {
  const [filter, setFilter] = _py_useState('todas');
  const list = filter === 'todas' ? NOVEDADES : NOVEDADES.filter(n => n.state === filter);
  const pendCount = NOVEDADES.filter(n => n.state === 'pendiente').length;

  return (
    <>
      {pendCount > 0 && (
        <div className="py-alert">
          <span className="py-alert-icon"><IconAlert size={16} /></span>
          <div style={{ flex: 1 }}>
            <div className="py-alert-title">{pendCount} novedades pendientes de aprobación</div>
            <div className="py-alert-sub">El período <b>{period.label}</b> cierra el <b>{period.closes}</b>. Las novedades no aprobadas no se incluirán en la liquidación.</div>
          </div>
        </div>
      )}

      <div className="sst-quickfilter">
        <button className={`sst-chip ${filter === 'todas' ? 'active' : ''}`}      onClick={() => setFilter('todas')}>Todas <span className="sst-chip-count">{NOVEDADES.length}</span></button>
        <button className={`sst-chip amber ${filter === 'pendiente' ? 'active' : ''}`} onClick={() => setFilter('pendiente')}>Pendientes <span className="sst-chip-count">{pendCount}</span></button>
        <button className={`sst-chip green ${filter === 'aplicada' ? 'active' : ''}`}  onClick={() => setFilter('aplicada')}>Aplicadas <span className="sst-chip-count">{NOVEDADES.filter(n => n.state === 'aplicada').length}</span></button>
        <button className={`sst-chip rose ${filter === 'rechazada' ? 'active' : ''}`}  onClick={() => setFilter('rechazada')}>Rechazadas <span className="sst-chip-count">0</span></button>
        <div style={{ flex: 1 }} />
        <button className="btn primary" onClick={onNew}><IconPlus size={14} /> Nueva novedad</button>
      </div>

      <div className="doc-list-card">
        <table className="doc-table">
          <thead>
            <tr>
              <th>Tipo</th>
              <th>Empleado</th>
              <th>Período</th>
              <th>Valor / Días</th>
              <th>Estado</th>
              <th>Registró</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {list.map(n => {
              const m = NOV_META[n.type];
              const s = STATE_NOV[n.state];
              const Ico = window[m.icon] || IconAlert;
              return (
                <tr key={n.id}>
                  <td data-label="Tipo">
                    <span className={`tr-cat-badge ${m.tone}`}><Ico size={11} /> {m.label}</span>
                    <div className="muted mono" style={{ fontSize: 10.5, marginTop: 4 }}>{n.id}</div>
                  </td>
                  <td data-label="Empleado">
                    <div style={{ fontWeight: 600, fontSize: 13 }}>{n.emp}</div>
                    <div className="muted mono" style={{ fontSize: 11 }}>{n.empId}</div>
                  </td>
                  <td data-label="Período" className="mono" style={{ fontSize: 12 }}>{n.period}</td>
                  <td data-label="Valor" className="mono" style={{ fontSize: 12.5, fontWeight: 700, color: 'var(--text)' }}>{n.value}</td>
                  <td data-label="Estado">
                    <span className={`pill ${s.pill}`}>
                      <span className="status-dot" style={{ background: s.dot }} /> {s.label}
                    </span>
                  </td>
                  <td data-label="Registró" className="muted" style={{ fontSize: 11.5 }}>
                    {n.by}
                    <div className="mono" style={{ fontSize: 10.5, marginTop: 2 }}>{n.when}</div>
                  </td>
                  <td data-label="Acciones">
                    {n.state === 'pendiente' ? (
                      <div style={{ display: 'flex', gap: 4 }}>
                        <button className="btn danger" style={{ padding: '4px 10px', fontSize: 11.5 }}>Rechazar</button>
                        <button className="btn primary" style={{ padding: '4px 10px', fontSize: 11.5 }}><IconCheck size={11} /> Aprobar</button>
                      </div>
                    ) : (
                      <button className="icon-action" title="Ver detalle"><IconExternal size={14} /></button>
                    )}
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    </>
  );
};

// ─── Prestaciones sociales ───────────────────────────────

const PrestacionesSection = () => {
  const totals = PRESTACIONES.reduce((acc, p) => ({
    cesantias: acc.cesantias + p.cesantias,
    intCes:    acc.intCes + p.intCes,
    prima:     acc.prima + p.prima,
    vacaciones: acc.vacaciones + p.vacaciones,
    total:     acc.total + p.total,
  }), { cesantias: 0, intCes: 0, prima: 0, vacaciones: 0, total: 0 });

  return (
    <>
      <div className="py-card">
        <div className="py-card-head">
          <div>
            <div className="muted-xs">Fechas críticas legales</div>
            <h3 className="py-card-title">Calendario de pagos legales 2026</h3>
          </div>
        </div>
        <div className="py-deadlines">
          {PRESTACIONES_DEADLINES.map((d, i) => (
            <div key={i} className={`py-deadline ${d.past ? 'past' : ''}`}>
              <div className="py-deadline-date mono">{d.date}</div>
              <div className="py-deadline-icon"><IconAlert size={14} /></div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div className="py-deadline-label">{d.label}</div>
                <div className="muted" style={{ fontSize: 11.5, marginTop: 2 }}>{d.detail}</div>
              </div>
              {d.past
                ? <span className="pill green" style={{ fontSize: 11 }}>Cumplido</span>
                : <span className="pill amber-soft" style={{ fontSize: 11 }}>En {d.days} días</span>
              }
            </div>
          ))}
        </div>
      </div>

      <div className="py-card">
        <div className="py-card-head">
          <div>
            <div className="muted-xs">Causación al corte · 31/05/2026</div>
            <h3 className="py-card-title">Provisión de prestaciones sociales</h3>
          </div>
          <button className="btn"><IconExternal size={13} /> Exportar provisión</button>
        </div>
        <div className="doc-list-card" style={{ border: 'none', boxShadow: 'none' }}>
          <table className="doc-table">
            <thead>
              <tr>
                <th>Empleado</th>
                <th style={{ textAlign: 'right' }}>Cesantías</th>
                <th style={{ textAlign: 'right' }}>Int. cesantías</th>
                <th style={{ textAlign: 'right' }}>Prima causada</th>
                <th style={{ textAlign: 'right' }}>Vacaciones</th>
                <th style={{ textAlign: 'right' }}>Total causado</th>
              </tr>
            </thead>
            <tbody>
              {PRESTACIONES.map(p => (
                <tr key={p.id}>
                  <td data-label="Empleado">
                    <div className="doc-cell-emp">
                      <div className="doc-avatar">{p.initials}</div>
                      <div>
                        <div style={{ fontWeight: 600, fontSize: 13 }}>{p.name}</div>
                        <div className="muted mono" style={{ fontSize: 11 }}>{p.id}</div>
                      </div>
                    </div>
                  </td>
                  <td data-label="Cesantías" style={{ textAlign: 'right' }} className="mono">{fmt(p.cesantias)}</td>
                  <td data-label="Int. cesantías" style={{ textAlign: 'right' }} className="mono">{fmt(p.intCes)}</td>
                  <td data-label="Prima" style={{ textAlign: 'right' }} className="mono">{fmt(p.prima)}</td>
                  <td data-label="Vacaciones" style={{ textAlign: 'right' }} className="mono">{fmt(p.vacaciones)}</td>
                  <td data-label="Total" style={{ textAlign: 'right' }}><span className="py-net">{fmt(p.total)}</span></td>
                </tr>
              ))}
              <tr className="py-detail-total">
                <td><b>TOTAL · 8 empleados mostrados</b></td>
                <td style={{ textAlign: 'right' }} className="mono"><b>{fmt(totals.cesantias)}</b></td>
                <td style={{ textAlign: 'right' }} className="mono"><b>{fmt(totals.intCes)}</b></td>
                <td style={{ textAlign: 'right' }} className="mono"><b>{fmt(totals.prima)}</b></td>
                <td style={{ textAlign: 'right' }} className="mono"><b>{fmt(totals.vacaciones)}</b></td>
                <td style={{ textAlign: 'right' }} className="mono"><b>{fmt(totals.total)}</b></td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </>
  );
};

// ─── DIAN section ────────────────────────────────────────

const DianSection = () => {
  return (
    <>
      <div className="py-card">
        <div className="py-card-head">
          <div>
            <div className="muted-xs">Período Mayo 2026</div>
            <h3 className="py-card-title">Transmisión nómina electrónica · DIAN</h3>
            <div className="muted" style={{ fontSize: 12.5, marginTop: 4 }}>5 pasos · firmado y radicado · CUFE generado</div>
          </div>
          <span className="pill green"><span className="status-dot" style={{ background: 'var(--green-600)' }} /> Aceptado</span>
        </div>

        <div className="py-dian-steps">
          {[
            ['1', 'Generación XML',     'XML 2.1 generado con 824 documentos individuales',                                              'done'],
            ['2', 'Vista previa',       'Validaciones internas pasaron · 0 errores · 0 advertencias',                                    'done'],
            ['3', 'Firma digital',      'Documento firmado con certificado digital de Carolina Restrepo · vigente hasta 12/2027',       'done'],
            ['4', 'Transmisión DIAN',   'Webservice DIAN · respuesta en 1.4 segundos',                                                  'done'],
            ['5', 'Respuesta DIAN',     'Aceptado · CUFE generado · ningún error de validación',                                        'done'],
          ].map(([n, t, d, st]) => (
            <div key={n} className={`py-dian-step py-dian-${st}`}>
              <div className="py-dian-step-num">{st === 'done' ? <IconCheck size={12} /> : n}</div>
              <div style={{ flex: 1 }}>
                <div className="py-dian-step-label">{t}</div>
                <div className="muted" style={{ fontSize: 11.5, marginTop: 2 }}>{d}</div>
              </div>
            </div>
          ))}
        </div>

        <div className="py-cufe-box">
          <div>
            <div className="muted-xs">CUFE generado</div>
            <div className="py-cufe mono">abc123fa78c2e1d9b4a3f8c5e2b9d7f1a4c6e8b3d2f9a7c1e5d8b2a4f6e9c1</div>
          </div>
          <button className="btn" style={{ padding: '6px 12px', fontSize: 12 }}>
            <IconCheck size={13} /> Copiar CUFE
          </button>
          <button className="btn"><IconExternal size={13} /> Verificar en DIAN</button>
        </div>

        <div style={{ display: 'flex', gap: 8, marginTop: 16, justifyContent: 'space-between', alignItems: 'center', paddingTop: 14, borderTop: '1px dashed var(--border)' }}>
          <span className="muted" style={{ fontSize: 12 }}>
            <IconShield size={11} /> Si encuentras algún error, genera una <b>nota de ajuste</b> en el siguiente período · nunca se reedita el original
          </span>
          <button className="btn"><IconExternal size={13} /> Generar nota de ajuste</button>
        </div>
      </div>

      <div className="py-card">
        <div className="py-card-head">
          <div>
            <h3 className="py-card-title">Timeline de transmisión</h3>
          </div>
        </div>
        <div className="doc-timeline">
          {DIAN_TIMELINE.map((t, i) => {
            const Ico = window[t.icon] || IconCheck;
            return (
              <div key={i} className="doc-tl-row doc-tl-signed">
                <div className="doc-tl-rail">
                  <div className="doc-tl-dot"><Ico size={11} /></div>
                  {i < DIAN_TIMELINE.length - 1 && <div className="doc-tl-line" />}
                </div>
                <div className="doc-tl-body">
                  <div className="doc-tl-label">{t.text}</div>
                  <div className="doc-tl-detail muted mono">{t.when}</div>
                </div>
              </div>
            );
          })}
        </div>
      </div>

      <div className="py-card">
        <div className="py-card-head">
          <div>
            <h3 className="py-card-title">Períodos transmitidos · histórico</h3>
          </div>
        </div>
        <table className="doc-table">
          <thead>
            <tr><th>Período</th><th>Transmitido</th><th>CUFE</th><th>Estado</th><th></th></tr>
          </thead>
          <tbody>
            {DIAN_HIST.map(h => (
              <tr key={h.period}>
                <td data-label="Período" style={{ fontWeight: 600, fontSize: 13 }}>{h.period}</td>
                <td data-label="Transmitido" className="mono" style={{ fontSize: 12 }}>{h.when}</td>
                <td data-label="CUFE" className="mono" style={{ fontSize: 11.5 }}>{h.cufe.slice(0, 16)}…</td>
                <td data-label="Estado"><span className="pill green"><span className="status-dot" style={{ background: 'var(--green-600)' }} /> Aceptado</span></td>
                <td><button className="icon-action"><IconExternal size={14} /></button></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </>
  );
};

// ─── Bank file section ───────────────────────────────────

const BankSection = () => {
  const [applyDate, setApplyDate] = _py_useState('30/05/2026');
  return (
    <>
      <div className="py-card">
        <div className="py-card-head">
          <div>
            <div className="muted-xs">Layout de pago · período Mayo 2026</div>
            <h3 className="py-card-title">Archivo banco</h3>
            <div className="muted" style={{ fontSize: 12.5, marginTop: 4 }}>Genera el archivo plano para subir al portal del banco principal</div>
          </div>
          <span className="pill amber-soft"><span className="status-dot" style={{ background: '#854D0E' }} /> Pendiente de generar</span>
        </div>

        <div className="py-bank-summary">
          <div>
            <div className="muted-xs">Total transferencias</div>
            <div className="py-bank-num">823</div>
            <div className="muted" style={{ fontSize: 11.5 }}>de 824 colaboradores · 1 con error de cuenta</div>
          </div>
          <div>
            <div className="muted-xs">Monto total</div>
            <div className="py-bank-num">{PY_KPIS.neto}</div>
            <div className="muted" style={{ fontSize: 11.5 }}>Suma de netos a pagar</div>
          </div>
          <div>
            <div className="muted-xs">Banco principal</div>
            <div style={{ fontSize: 16, fontWeight: 700, marginTop: 4 }}>Davivienda</div>
            <div className="muted" style={{ fontSize: 11.5 }}>Formato ACH · convenio 008-451</div>
          </div>
          <div>
            <div className="muted-xs">Programación</div>
            <div style={{ fontSize: 14, fontWeight: 700, marginTop: 4 }}>30/05/2026 · 06:00</div>
            <div className="muted" style={{ fontSize: 11.5 }}>Aplicación en cuentas</div>
          </div>
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14, marginTop: 16 }}>
          <div>
            <div className="muted-xs" style={{ marginBottom: 8 }}>Recolección por banco</div>
            {BANK_DIST.map(b => (
              <div key={b.bank} className="py-bank-row">
                <span style={{ flex: 1, fontSize: 12.5 }}>{b.bank}</span>
                <span className="mono" style={{ fontSize: 12 }}>{b.count}</span>
                <div className="tr-prog-track" style={{ width: 80 }}>
                  <div className="tr-prog-fill green" style={{ width: `${b.share}%` }} />
                </div>
                <span className="mono muted" style={{ fontSize: 11, width: 32, textAlign: 'right' }}>{b.share}%</span>
              </div>
            ))}
          </div>
          <div>
            <div className="muted-xs" style={{ marginBottom: 8 }}>Generar archivo</div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
              <select style={{ font: 'inherit', fontSize: 13, padding: '8px 11px', background: 'white', border: '1px solid var(--border)', borderRadius: 8 }}>
                <option>ACH · Davivienda · pagos masivos</option>
                <option>PSE · Bancolombia</option>
                <option>Excel · planilla manual</option>
              </select>
              <window.DatePickerCO value={applyDate} onChange={setApplyDate} placeholder="Fecha de aplicación" />
              <button className="btn primary"><IconExternal size={13} /> Generar archivo plano</button>
            </div>
          </div>
        </div>
      </div>

      <div className="py-card">
        <div className="py-card-head">
          <div>
            <h3 className="py-card-title">Archivos generados · historial</h3>
          </div>
        </div>
        <table className="doc-table">
          <thead>
            <tr>
              <th>Archivo</th>
              <th>Período</th>
              <th>Banco</th>
              <th style={{ textAlign: 'right' }}>Transferencias</th>
              <th style={{ textAlign: 'right' }}>Monto</th>
              <th>Generado</th>
              <th>Estado</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {BANK_FILES.map(f => (
              <tr key={f.id}>
                <td data-label="Archivo">
                  <div className="mono" style={{ fontSize: 12, fontWeight: 600 }}>{f.file}</div>
                  <div className="muted mono" style={{ fontSize: 10.5 }}>{f.id}</div>
                </td>
                <td data-label="Período" style={{ fontSize: 12.5 }}>{f.period}</td>
                <td data-label="Banco" className="muted" style={{ fontSize: 12 }}>{f.bank}</td>
                <td data-label="Transferencias" style={{ textAlign: 'right' }} className="mono">{f.count}</td>
                <td data-label="Monto" style={{ textAlign: 'right' }} className="mono">{f.total}</td>
                <td data-label="Generado" className="mono muted" style={{ fontSize: 11.5 }}>{f.when}</td>
                <td data-label="Estado">
                  <span className="pill green"><span className="status-dot" style={{ background: 'var(--green-600)' }} /> Confirmado</span>
                </td>
                <td><button className="icon-action"><IconExternal size={14} /></button></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </>
  );
};

// ─── Historial section ───────────────────────────────────

const HistorialSection = () => {
  return (
    <>
      <div className="sst-quickfilter">
        <select>
          <option>Año 2026</option>
          <option>Año 2025</option>
          <option>Año 2024</option>
        </select>
        <div style={{ flex: 1 }} />
        <button className="btn"><IconExternal size={14} /> Descargar comprobantes masivos · ZIP</button>
      </div>

      <div className="doc-list-card">
        <table className="doc-table">
          <thead>
            <tr>
              <th>Período</th>
              <th style={{ textAlign: 'center' }}>Colaboradores</th>
              <th style={{ textAlign: 'right' }}>Total neto pagado</th>
              <th>Estado</th>
              <th>CUFE DIAN</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {HISTORY.map(h => (
              <tr key={h.period}>
                <td data-label="Período">
                  <div style={{ fontWeight: 700, fontSize: 13 }}>{h.period}</div>
                  {h.note && <div className="muted" style={{ fontSize: 11, marginTop: 2 }}>{h.note}</div>}
                </td>
                <td data-label="Colaboradores" style={{ textAlign: 'center', fontFamily: 'JetBrains Mono', fontSize: 13, fontWeight: 700 }}>{h.count}</td>
                <td data-label="Neto" style={{ textAlign: 'right' }}>
                  <span className="py-net">{h.neto}</span>
                </td>
                <td data-label="Estado">
                  <span className="pill green"><span className="status-dot" style={{ background: 'var(--green-600)' }} /> Transmitido DIAN</span>
                </td>
                <td data-label="CUFE" className="mono" style={{ fontSize: 11.5 }}>{h.cufe}…</td>
                <td>
                  <div style={{ display: 'flex', gap: 4 }}>
                    <button className="icon-action" title="Ver período"><IconExternal size={14} /></button>
                    <button className="icon-action" title="Descargar ZIP"><IconDoc size={14} /></button>
                  </div>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      <div className="py-immutable">
        <IconShield size={14} />
        <span>
          <b>Los períodos cerrados son inmutables.</b> Las correcciones se aplican mediante notas de ajuste en el siguiente período, conforme a la normativa de nómina electrónica DIAN.
        </span>
      </div>
    </>
  );
};

// ─── Comprobante PDF modal ───────────────────────────────

const ComprobanteModal = ({ emp, period, onClose }) => {
  React.useEffect(() => {
    document.body.style.overflow = 'hidden';
    const onEsc = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onEsc);
    return () => { document.body.style.overflow = ''; window.removeEventListener('keydown', onEsc); };
  }, []);

  const aux = emp.salary < 2847000 ? 200000 : 0;
  const ibc = emp.salary;
  const salud = Math.round(ibc * 0.04);
  const pension = Math.round(ibc * 0.04);

  return (
    <div className="modal-overlay" onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="modal" style={{ maxWidth: 880 }}>
        <div className="modal-head">
          <div>
            <div className="modal-title">Comprobante de pago</div>
            <div className="modal-sub">Vista previa del PDF que recibe el colaborador · firmado electrónicamente</div>
          </div>
          <button className="icon-btn" onClick={onClose} title="Cerrar">
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M18 6 6 18M6 6l12 12" /></svg>
          </button>
        </div>

        <div className="cert-stage" style={{ background: 'linear-gradient(180deg, #ECEEF5 0%, #E1E5F0 100%)' }}>
          <div className="py-paystub">
            {/* Header */}
            <div className="py-stub-head">
              <div className="py-stub-brand">
                <div className="cert-logo-mark client" style={{ width: 40, height: 40, fontSize: 20 }}>a</div>
                <div>
                  <div style={{ fontWeight: 800, fontSize: 13, letterSpacing: '0.02em' }}>ATICA S.A.S.</div>
                  <div className="muted mono" style={{ fontSize: 10.5 }}>NIT 900.123.456-7 · Cra. 12 #34-56, Cali</div>
                </div>
              </div>
              <div style={{ textAlign: 'right' }}>
                <div className="muted-xs">Comprobante</div>
                <div className="mono" style={{ fontSize: 11.5, fontWeight: 700 }}>CMP-{period.id}-{emp.id}</div>
                <div className="muted mono" style={{ fontSize: 11, marginTop: 4 }}>Fecha pago: 30/05/2026</div>
              </div>
            </div>

            <h2 className="py-stub-title">Comprobante de pago de salario</h2>
            <div className="py-stub-period">{period.label} · {period.range}</div>

            {/* Empleado info */}
            <div className="py-stub-emp">
              <div><div className="muted-xs">Nombre</div><div className="py-stub-val">{emp.name}</div></div>
              <div><div className="muted-xs">Documento</div><div className="py-stub-val mono">CC 1.087.456.231</div></div>
              <div><div className="muted-xs">Cargo</div><div className="py-stub-val">{emp.role}</div></div>
              <div><div className="muted-xs">Área</div><div className="py-stub-val">{emp.area}</div></div>
              <div><div className="muted-xs">Fecha ingreso</div><div className="py-stub-val mono">12/05/2024</div></div>
              <div><div className="muted-xs">Tipo contrato</div><div className="py-stub-val">Indefinido</div></div>
              <div><div className="muted-xs">Días trabajados</div><div className="py-stub-val mono">{emp.days}</div></div>
              <div><div className="muted-xs">Salario base</div><div className="py-stub-val mono">{fmt(emp.salary)}</div></div>
            </div>

            {/* Devengados */}
            <div className="py-stub-section">
              <h3 className="py-stub-h3">Devengados</h3>
              <table className="py-stub-table">
                <tbody>
                  <tr><td>Salario básico</td><td className="mono">{emp.days} días</td><td className="mono">{fmt(emp.salary * emp.days / 30)}</td></tr>
                  {aux > 0 && <tr><td>Auxilio de transporte</td><td className="mono">{emp.days} días</td><td className="mono">{fmt(aux * emp.days / 30)}</td></tr>}
                  {emp.id === 'E0205' && <tr><td>Horas extras diurnas + nocturnas</td><td className="mono">6 horas</td><td className="mono">{fmt(57375)}</td></tr>}
                  <tr className="py-stub-subtotal">
                    <td colSpan={2}><b>Total devengado</b></td>
                    <td className="mono"><b>{fmt(emp.devengado)}</b></td>
                  </tr>
                </tbody>
              </table>
            </div>

            {/* Deducciones */}
            <div className="py-stub-section">
              <h3 className="py-stub-h3">Deducciones</h3>
              <table className="py-stub-table">
                <tbody>
                  <tr><td>Salud empleado · 4%</td><td className="mono">IBC {fmt(ibc)}</td><td className="mono">{fmt(salud)}</td></tr>
                  <tr><td>Pensión empleado · 4%</td><td className="mono">IBC {fmt(ibc)}</td><td className="mono">{fmt(pension)}</td></tr>
                  {emp.extra.libranza && <tr><td>Libranza Banco</td><td>—</td><td className="mono">{fmt(emp.extra.libranza)}</td></tr>}
                  <tr className="py-stub-subtotal">
                    <td colSpan={2}><b>Total deducciones</b></td>
                    <td className="mono"><b>−{fmt(emp.deducciones)}</b></td>
                  </tr>
                </tbody>
              </table>
            </div>

            {/* Net summary */}
            <div className="py-stub-net">
              <div className="py-stub-net-grid">
                <div><div className="muted-xs">Total devengado</div><div className="py-stub-net-num">{fmt(emp.devengado)}</div></div>
                <div><div className="muted-xs">Total deducciones</div><div className="py-stub-net-num neg">−{fmt(emp.deducciones)}</div></div>
                <div className="highlight">
                  <div className="muted-xs" style={{ color: 'rgba(255,255,255,0.7)' }}>NETO A PAGAR</div>
                  <div className="py-stub-net-num pos">{fmt(emp.neto)}</div>
                </div>
              </div>
            </div>

            {/* Aportes seguridad social info */}
            <div className="py-stub-section">
              <h3 className="py-stub-h3">Aportes a seguridad social</h3>
              <table className="py-stub-table py-stub-table-alt">
                <thead><tr><th>Entidad</th><th style={{ textAlign: 'right' }}>Empleado</th><th style={{ textAlign: 'right' }}>Empleador</th><th style={{ textAlign: 'right' }}>Total</th></tr></thead>
                <tbody>
                  <tr><td>EPS Sura · salud</td><td className="mono">{fmt(salud)}</td><td className="mono">{fmt(ibc * 0.085)}</td><td className="mono">{fmt(salud + ibc * 0.085)}</td></tr>
                  <tr><td>Protección · pensión</td><td className="mono">{fmt(pension)}</td><td className="mono">{fmt(ibc * 0.12)}</td><td className="mono">{fmt(pension + ibc * 0.12)}</td></tr>
                  <tr><td>ARL Sura</td><td className="mono">—</td><td className="mono">{fmt(ibc * 0.02436)}</td><td className="mono">{fmt(ibc * 0.02436)}</td></tr>
                </tbody>
              </table>
            </div>

            <div className="py-stub-foot">
              <div style={{ flex: 1 }}>
                <div className="muted" style={{ fontSize: 10.5 }}>Este comprobante fue generado electrónicamente por <b>Atica SOMOS</b>. Su validez no requiere firma manuscrita.</div>
                <div className="muted mono" style={{ fontSize: 10, marginTop: 4 }}>SHA-256 · a4f2c1e89b7d3f5e26c8d4b1a9f3e7c5d8b2a4f6e9c1d3b5a7f8e0c2d4b6a9f1</div>
                <div className="muted" style={{ fontSize: 10, marginTop: 2 }}>Verifica autenticidad en: <span className="mono">atica.co/verificar/CMP-{period.id}-{emp.id}</span></div>
              </div>
            </div>
          </div>
        </div>

        <div className="modal-foot">
          <button className="btn" onClick={onClose}>Cerrar</button>
          <div style={{ flex: 1 }} />
          <button className="btn"><IconMegaphone size={13} /> Enviar al colaborador</button>
          <button className="btn primary"><IconExternal size={13} /> Descargar PDF firmado</button>
        </div>
      </div>
    </div>
  );
};

// ─── Nueva novedad modal ─────────────────────────────────

const NovedadModal = ({ onClose }) => {
  const [type, setType] = _py_useState('extras');
  const [from, setFrom] = _py_useState('');
  const [to, setTo]     = _py_useState('');

  React.useEffect(() => {
    document.body.style.overflow = 'hidden';
    const onEsc = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onEsc);
    return () => { document.body.style.overflow = ''; window.removeEventListener('keydown', onEsc); };
  }, []);

  return (
    <div className="modal-overlay" onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="modal" style={{ maxWidth: 720 }}>
        <div className="modal-head">
          <div>
            <div className="modal-title">Nueva novedad de nómina</div>
            <div className="modal-sub">Registra novedades que afecten la liquidación del período. Las que requieran aprobación pasan al flujo correspondiente.</div>
          </div>
          <button className="icon-btn" onClick={onClose} title="Cerrar">
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M18 6 6 18M6 6l12 12" /></svg>
          </button>
        </div>

        <div className="modal-body">
          <div className="furat-row">
            <label className="furat-label">Tipo de novedad</label>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 6 }}>
              {Object.entries(NOV_META).map(([k, m]) => {
                const Ico = window[m.icon] || IconAlert;
                return (
                  <button key={k} className={`co-value-pick ${m.tone} ${type === k ? 'active' : ''}`} onClick={() => setType(k)}>
                    <Ico size={12} /> {m.label}
                  </button>
                );
              })}
            </div>
          </div>

          <div className="furat-grid-2" style={{ marginTop: 14 }}>
            <div className="furat-row">
              <label className="furat-label">Colaborador afectado</label>
              <select>
                <option value="">Selecciona…</option>
                {LIQ.map(e => <option key={e.id} value={e.id}>{e.name}</option>)}
              </select>
            </div>
            <div className="furat-row">
              <label className="furat-label">Período</label>
              <input type="text" defaultValue="Mayo 2026" />
            </div>
          </div>

          <div className="furat-grid-2" style={{ marginTop: 14 }}>
            <div className="furat-row">
              <label className="furat-label">Desde</label>
              <window.DatePickerCO value={from} onChange={setFrom} />
            </div>
            <div className="furat-row">
              <label className="furat-label">Hasta</label>
              <window.DatePickerCO value={to} onChange={setTo} min={from} />
            </div>
          </div>

          <div className="furat-row" style={{ marginTop: 14 }}>
            <label className="furat-label">Valor / Cantidad</label>
            <input type="text" placeholder={type === 'extras' ? 'Ej: 6 horas' : type === 'bonificacion' ? 'Ej: $200.000' : ''} />
          </div>

          <div className="furat-row" style={{ marginTop: 14 }}>
            <label className="furat-label">Justificación / soporte</label>
            <textarea rows={3} placeholder="Describe el motivo y referencias del soporte adjunto…" />
          </div>
        </div>

        <div className="modal-foot">
          <span className="muted" style={{ fontSize: 12, marginRight: 'auto' }}>
            <IconShield size={12} /> Esta novedad pasará al flujo de aprobación si excede límites establecidos
          </span>
          <button className="btn" onClick={onClose}>Cancelar</button>
          <button className="btn primary"><IconCheck size={14} /> Registrar novedad</button>
        </div>
      </div>
    </div>
  );
};

// ─── Cierre de período modal ─────────────────────────────

const CloseModal = ({ period, onClose }) => {
  const [pwd, setPwd] = _py_useState('');
  const [confirmed, setConfirmed] = _py_useState(false);

  React.useEffect(() => {
    document.body.style.overflow = 'hidden';
    const onEsc = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onEsc);
    return () => { document.body.style.overflow = ''; window.removeEventListener('keydown', onEsc); };
  }, []);

  const checks = [
    { label: 'Todas las novedades aprobadas',                         done: false, hint: '3 novedades pendientes' },
    { label: 'Liquidación calculada y revisada',                      done: true,  hint: '824 colaboradores · 0 errores' },
    { label: 'Comprobantes generados',                                done: false, hint: 'Pendiente · 0 / 824 comprobantes' },
    { label: 'Nómina electrónica DIAN transmitida y aceptada',         done: false, hint: 'Pendiente generación XML' },
    { label: 'Archivo banco generado',                                 done: false, hint: 'Pendiente generación' },
    { label: 'Contabilización exportada al ERP',                       done: false, hint: 'Manual · pendiente' },
  ];
  const ready = checks.every(c => c.done) && pwd.length >= 6 && confirmed;

  return (
    <div className="modal-overlay" onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="modal" style={{ maxWidth: 640 }}>
        <div className="modal-head">
          <div>
            <div className="modal-title">Cerrar período · {period.label}</div>
            <div className="modal-sub">Revisión final antes de cerrar definitivamente el período</div>
          </div>
          <button className="icon-btn" onClick={onClose} title="Cerrar">
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M18 6 6 18M6 6l12 12" /></svg>
          </button>
        </div>

        <div className="modal-body">
          <div className="muted-xs" style={{ marginBottom: 8 }}>Checklist de verificación</div>
          <div className="py-close-checks">
            {checks.map((c, i) => (
              <div key={i} className={`py-close-check ${c.done ? 'done' : 'pending'}`}>
                <span className="py-close-check-mark">
                  {c.done ? <IconCheck size={11} /> : ''}
                </span>
                <div style={{ flex: 1 }}>
                  <div style={{ fontSize: 13, fontWeight: 600 }}>{c.label}</div>
                  <div className="muted" style={{ fontSize: 11.5, marginTop: 1 }}>{c.hint}</div>
                </div>
              </div>
            ))}
          </div>

          <div className="py-close-warn">
            <IconAlert size={14} />
            <div>
              <div style={{ fontWeight: 700, fontSize: 13, color: 'var(--rose-600)' }}>Cierre irreversible</div>
              <div style={{ fontSize: 12, color: 'var(--text)', marginTop: 4, lineHeight: 1.5 }}>
                Una vez cerrado, el período <b>{period.label}</b> no podrá modificarse. Las correcciones deberán hacerse mediante <b>notas de ajuste</b> en el siguiente período, conforme a la normativa de nómina electrónica DIAN.
              </div>
            </div>
          </div>

          <label className="sig-accept" style={{ marginTop: 14 }}>
            <input type="checkbox" checked={confirmed} onChange={(e) => setConfirmed(e.target.checked)} />
            <span>Confirmo que revisé toda la liquidación y autorizo el cierre definitivo del período {period.label}.</span>
          </label>

          <div className="furat-row" style={{ marginTop: 14 }}>
            <label className="furat-label">Contraseña de administrador</label>
            <input type="password" value={pwd} onChange={(e) => setPwd(e.target.value)} placeholder="Ingresa tu contraseña para confirmar" />
            <div className="muted" style={{ fontSize: 11, marginTop: 4 }}>
              Solo administradores con permiso <code className="mono">payroll.close</code> pueden cerrar el período.
            </div>
          </div>
        </div>

        <div className="modal-foot">
          <button className="btn" onClick={onClose}>Cancelar</button>
          <div style={{ flex: 1 }} />
          <button className="btn danger solid" disabled={!ready}>
            <IconShield size={14} /> Cerrar período definitivamente
          </button>
        </div>
      </div>
    </div>
  );
};

window.Payroll = Payroll;
