// Performance · Fase B
// NewCycleModal · stepper de 4 pasos para crear/configurar un ciclo de evaluación.
// Combina metodologías (mbo · competencias · 90/180/360 · escalas · incidentes).
// Auto-pobla la matriz de evaluadores desde el organigrama (jefe + reports + pares = mismo jefe).
// Aplica regla de anonimato N≥3 con bandera de degradación si no se alcanza.

const { useState: _pc_useState, useMemo: _pc_useMemo, useEffect: _pc_useEffect } = React;

// ─── Catálogo de metodologías combinables ─────────────────

const METODOLOGIAS_CATALOG = [
  { id: 'mbo',          label: 'MBO · Por objetivos',     desc: 'Cumplimiento de metas pactadas en cascada org → área → individuo.', tone: 'navy',   icon: 'IconStar'    },
  { id: 'competencias', label: 'Por competencias',         desc: 'Competencias conductuales con escala 1–5 e indicadores.',           tone: 'blue',   icon: 'IconShield'  },
  { id: '90',           label: '90° · Autoevaluación',     desc: 'Solo el colaborador. Útil en período de prueba y check-ins.',       tone: 'navy',   icon: 'IconUsers'   },
  { id: '180',          label: '180° · Jefe + Auto',       desc: 'Jefe directo + autoevaluación. Default para mandos medios.',         tone: 'blue',   icon: 'IconUsers'   },
  { id: '360',          label: '360° · Multi-perspectiva', desc: 'Auto + jefe + pares + reports. Recomendado para liderazgos.',       tone: 'amber',  icon: 'IconUsers'   },
  { id: 'escalas',      label: 'Escalas gráficas',         desc: 'Lista de factores con descriptor por nivel. Default operativos.',    tone: 'navy',   icon: 'IconBarChart'},
  { id: 'incidentes',   label: 'Incidentes críticos',      desc: 'Auto-feed de eventos relevantes del período al formulario.',        tone: 'rose',   icon: 'IconClock'   },
];

const METODOLOGIAS_BY_ID = METODOLOGIAS_CATALOG.reduce((m, x) => { m[x.id] = x; return m; }, {});
window.METODOLOGIAS_CATALOG = METODOLOGIAS_CATALOG;
window.METODOLOGIAS_BY_ID = METODOLOGIAS_BY_ID;

// ─── Chip reutilizable ────────────────────────────────────

const MetodologiaChip = ({ id, size = 'md' }) => {
  const m = METODOLOGIAS_BY_ID[id];
  if (!m) return null;
  return (
    <span className={`pc-meto-chip pc-meto-${m.tone} ${size === 'sm' ? 'sm' : ''}`} title={m.desc}>
      {m.label}
    </span>
  );
};

window.MetodologiaChip = MetodologiaChip;

// ─── Anonimato badge (regla N≥3) ──────────────────────────

const AnonimatoBadge = ({ n, minN = 3 }) => {
  const ok = n >= minN;
  return (
    <span className={`pc-anon-badge ${ok ? 'ok' : 'warn'}`} title={ok ? 'Anonimato preservado' : `N=${n} < ${minN} · resultado se omite por Habeas Data`}>
      <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
      {ok ? `N=${n} ≥ ${minN}` : `N=${n} < ${minN}`}
    </span>
  );
};

window.AnonimatoBadge = AnonimatoBadge;

// ─── Mini-organigrama mock (resolver evaluadores auto) ─────
// En operaciones esto se resuelve desde una tabla relación jefe-colaborador.
// Aquí mockeamos: cada cargo "liderazgo|directivo" tiene reportes; los pares
// son personas con el mismo jefe directo.

const ORG_RELATIONS = {
  // empId → { jefeId, reportsIds[] }
  E0023: { jefeId: null,    reportsIds: ['E0094', 'E0067', 'E0177', 'E0244'] },
  E0067: { jefeId: 'E0023', reportsIds: ['E0247', 'E0205', 'E0198', 'E0142', 'E0246'] },
  E0094: { jefeId: 'E0023', reportsIds: [] },
  E0177: { jefeId: 'E0023', reportsIds: ['E0128'] },
  E0244: { jefeId: 'E0023', reportsIds: [] },
  E0247: { jefeId: 'E0067', reportsIds: [] },
  E0205: { jefeId: 'E0067', reportsIds: [] },
  E0198: { jefeId: 'E0067', reportsIds: [] },
  E0142: { jefeId: 'E0067', reportsIds: [] },
  E0246: { jefeId: 'E0067', reportsIds: [] },
  E0128: { jefeId: 'E0177', reportsIds: [] },
  E0156: { jefeId: 'E0023', reportsIds: [] },
};
window.ORG_RELATIONS = ORG_RELATIONS;

// Resuelve la matriz para un evaluado: { self, manager, peers[], reports[] }
const matrizDesdeOrganigrama = (evaluadoId) => {
  const rel = ORG_RELATIONS[evaluadoId] || { jefeId: null, reportsIds: [] };
  const self = [evaluadoId];
  const manager = rel.jefeId ? [rel.jefeId] : [];
  // pares = los demás reportes del mismo jefe (excluyendo al evaluado)
  const peers = rel.jefeId
    ? (ORG_RELATIONS[rel.jefeId]?.reportsIds || []).filter(id => id !== evaluadoId)
    : [];
  const reports = rel.reportsIds || [];
  return { self, manager, peers, reports };
};
window.matrizDesdeOrganigrama = matrizDesdeOrganigrama;

// Determina si una matriz cumple regla de anonimato N≥3 para una perspectiva.
// Retorna { peer: 'ok'|'omitir', report: 'ok'|'omitir', degradado360a180: bool }
const evaluarAnonimatoMatriz = (matriz, minN = 3) => {
  const peerOk   = matriz.peers.length >= minN;
  const reportOk = matriz.reports.length >= minN;
  return {
    peer:   peerOk   ? 'ok' : 'omitir',
    report: reportOk ? 'ok' : 'omitir',
    degradado360a180: !peerOk && !reportOk,
  };
};
window.evaluarAnonimatoMatriz = evaluarAnonimatoMatriz;

// ─── IndividualPicker · selector de colaboradores con buscador ─

const IndividualPicker = ({ selectedIds, onChange }) => {
  const [q, setQ] = _pc_useState('');
  const personas = window.PERSONAS_DESEMPENO || {};
  const cargos = window.CARGOS || [];
  const entries = Object.entries(personas);

  const norm = (s) => (s || '').toLowerCase().normalize('NFD').replace(/[̀-ͯ]/g, '');
  const filtered = entries.filter(([id, p]) => {
    if (!q.trim()) return true;
    const cargo = cargos.find(c => c.id === p.cargoId);
    const hay = `${p.nombre} ${cargo?.nombre || ''} ${id}`;
    return norm(hay).includes(norm(q));
  });

  const toggle = (id) => {
    onChange(selectedIds.includes(id) ? selectedIds.filter(x => x !== id) : [...selectedIds, id]);
  };
  const allSelected = filtered.length > 0 && filtered.every(([id]) => selectedIds.includes(id));
  const toggleAll = () => {
    if (allSelected) {
      onChange(selectedIds.filter(id => !filtered.some(([fid]) => fid === id)));
    } else {
      const next = new Set(selectedIds);
      filtered.forEach(([id]) => next.add(id));
      onChange([...next]);
    }
  };

  return (
    <div className="pc-individual-picker">
      <div className="pc-ind-head">
        <div className="pc-ind-search">
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>
          <input
            type="text"
            value={q}
            onChange={(e) => setQ(e.target.value)}
            placeholder="Buscar por nombre, cargo o ID…"
            autoFocus
          />
        </div>
        <button type="button" className="link-btn" onClick={toggleAll}>
          {allSelected ? 'Deseleccionar visibles' : 'Seleccionar todos'}
        </button>
      </div>
      <div className="pc-ind-count">
        <span><b>{selectedIds.length}</b> seleccionados</span>
        <span className="muted">· {filtered.length} de {entries.length} visibles</span>
      </div>
      <div className="pc-ind-list">
        {filtered.length === 0 && (
          <div className="muted" style={{ fontSize: 12, padding: 12, textAlign: 'center' }}>
            Sin resultados para "<b>{q}</b>"
          </div>
        )}
        {filtered.map(([id, p]) => {
          const cargo = cargos.find(c => c.id === p.cargoId);
          const sel = selectedIds.includes(id);
          return (
            <label key={id} className={`pc-ind-row ${sel ? 'active' : ''}`}>
              <input type="checkbox" checked={sel} onChange={() => toggle(id)} />
              <div className="doc-avatar" style={{ width: 28, height: 28, fontSize: 11 }}>{p.initials || '??'}</div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div className="pc-ind-name">{p.nombre}</div>
                <div className="muted mono" style={{ fontSize: 10.5, marginTop: 1 }}>{id} · {cargo?.nombre || '—'}</div>
              </div>
            </label>
          );
        })}
      </div>
    </div>
  );
};

window.IndividualPicker = IndividualPicker;

// ─── NewCycleModal · Stepper 4 pasos ──────────────────────

const NewCycleModal = ({ onClose, onSave }) => {
  const [step, setStep] = _pc_useState(1);
  const [form, setForm] = _pc_useState({
    nombre: '',
    metodologias: ['mbo', 'competencias', '180', 'incidentes'],
    audienciaTipo: 'todos',         // todos | cargo | area | individual | liderazgos
    audienciaCriterio: { cargosIds: [], areas: [], empleadosIds: [], niveles: ['liderazgo', 'directivo'] },
    periodoInicio: '01/07/2026',
    periodoFin: '31/12/2026',
    apertura: '01/07/2026',
    cierre: '15/01/2027',
    pondCompetencias: 0.6,
    pondObjetivos: 0.4,
    requireFirma: true,
    anonimatoMinN: 3,
    notificarPorEmail: true,
    notificarPorPortal: true,
  });

  _pc_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 update = (patch) => setForm(f => ({ ...f, ...patch }));
  const toggleMet = (id) => {
    const has = form.metodologias.includes(id);
    let next = has ? form.metodologias.filter(m => m !== id) : [...form.metodologias, id];
    // Mutex 90 / 180 / 360 (no convive más de uno)
    if (!has && (id === '90' || id === '180' || id === '360')) {
      next = next.filter(m => m === id || (m !== '90' && m !== '180' && m !== '360'));
    }
    update({ metodologias: next });
  };

  // Audiencia · estimación de población
  const _emp = window.PERSONAS_DESEMPENO || {};
  const audienciaResolved = _pc_useMemo(() => {
    const todos = Object.entries(_emp);
    if (form.audienciaTipo === 'todos') return todos.map(([id]) => id);
    if (form.audienciaTipo === 'liderazgos') {
      return todos.filter(([_, p]) => {
        const c = (window.CARGOS || []).find(c => c.id === p.cargoId);
        return c && (c.nivel === 'liderazgo' || c.nivel === 'directivo');
      }).map(([id]) => id);
    }
    if (form.audienciaTipo === 'cargo') {
      return todos.filter(([_, p]) => form.audienciaCriterio.cargosIds.includes(p.cargoId)).map(([id]) => id);
    }
    if (form.audienciaTipo === 'area') {
      return todos.filter(([_, p]) => {
        const c = (window.CARGOS || []).find(c => c.id === p.cargoId);
        return c && form.audienciaCriterio.areas.includes(c.area);
      }).map(([id]) => id);
    }
    if (form.audienciaTipo === 'individual') {
      return form.audienciaCriterio.empleadosIds || [];
    }
    return [];
  }, [form.audienciaTipo, form.audienciaCriterio]);

  // Análisis matriz · cuántos reciben 360, cuántos degradan a 180 por anonimato
  const matricesAnalisis = _pc_useMemo(() => {
    if (!form.metodologias.includes('360')) return null;
    const out = audienciaResolved.map(empId => {
      const matriz = matrizDesdeOrganigrama(empId);
      const anon = evaluarAnonimatoMatriz(matriz, form.anonimatoMinN);
      return { empId, matriz, anon };
    });
    return {
      total: out.length,
      con360: out.filter(o => !o.anon.degradado360a180).length,
      degradadosA180: out.filter(o => o.anon.degradado360a180).length,
      detalle: out,
    };
  }, [audienciaResolved, form.metodologias, form.anonimatoMinN]);

  const canNext = () => {
    if (step === 1) return form.nombre.trim().length >= 4 && form.metodologias.length >= 1;
    if (step === 2) return audienciaResolved.length > 0;
    if (step === 3) return true;
    return true;
  };
  const next = () => { if (canNext() && step < 4) setStep(step + 1); };
  const prev = () => { if (step > 1) setStep(step - 1); };

  const submit = () => {
    if (!canNext()) return;
    const id = `CY-${Date.now().toString(36).toUpperCase()}`;
    const nuevo = {
      id, nombre: form.nombre,
      metodologias: form.metodologias,
      audiencia: { tipo: form.audienciaTipo, criterio: form.audienciaCriterio },
      periodo: { inicio: form.periodoInicio, fin: form.periodoFin },
      apertura: form.apertura, cierre: form.cierre,
      estado: 'configurando', completitudPct: 0,
      invitados: audienciaResolved.length, completados: 0, evaluadores: 0,
      responsable: 'Carolina Restrepo Salazar',
      pondCompetencias: form.pondCompetencias, pondObjetivos: form.pondObjetivos,
      requireFirmaElectronica: form.requireFirma, anonimatoMinN: form.anonimatoMinN,
    };
    (window.CICLOS_EVALUACION || []).unshift(nuevo);
    onSave && onSave(nuevo);
    onClose();
  };

  return (
    <div className="modal-overlay" onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="modal" style={{ maxWidth: 920, height: 'calc(100vh - 64px)' }}>
        <div className="modal-head">
          <div>
            <div className="muted mono" style={{ fontSize: 11 }}>Nuevo ciclo · {step}/4</div>
            <div className="modal-title">Crear ciclo de evaluación</div>
            <div className="modal-sub">Combina las metodologías que apliquen al alcance del ciclo. Las decisiones quedan registradas para Modo Auditoría.</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>

        {/* Stepper */}
        <div className="pc-stepper">
          {['Qué', 'Quiénes', 'Evaluadores', 'Cuándo + firma'].map((l, i) => (
            <div key={i} className={`pc-step ${step === i + 1 ? 'active' : ''} ${step > i + 1 ? 'done' : ''}`}>
              <span className="pc-step-num">{i + 1}</span>
              <span className="pc-step-lbl">{l}</span>
            </div>
          ))}
        </div>

        <div className="modal-body" style={{ padding: '20px 24px' }}>
          {/* Step 1 · Qué */}
          {step === 1 && (
            <div className="pc-step-body">
              <div className="form-field">
                <label>Nombre del ciclo *</label>
                <input
                  type="text" value={form.nombre}
                  onChange={(e) => update({ nombre: e.target.value })}
                  placeholder="Ej. Evaluación Semestral S2 2026"
                  autoFocus
                />
              </div>

              <div className="muted-xs" style={{ marginTop: 16, marginBottom: 8 }}>Metodologías combinadas</div>
              <div className="pc-meto-grid">
                {METODOLOGIAS_CATALOG.map(m => {
                  const active = form.metodologias.includes(m.id);
                  const Ico = window[m.icon] || (window.IconStar);
                  return (
                    <button key={m.id} type="button"
                      className={`pc-meto-card pc-meto-${m.tone} ${active ? 'active' : ''}`}
                      onClick={() => toggleMet(m.id)}
                    >
                      <div className="pc-meto-card-head">
                        <span className={`pc-meto-card-icon ${m.tone}`}><Ico size={14} /></span>
                        <span className="pc-meto-card-name">{m.label}</span>
                        {active && <span className="pc-meto-card-tick">✓</span>}
                      </div>
                      <div className="pc-meto-card-desc">{m.desc}</div>
                    </button>
                  );
                })}
              </div>

              <div className="pc-form-row">
                <div className="form-field">
                  <label>Peso competencias</label>
                  <input type="number" min="0" max="1" step="0.05"
                    value={form.pondCompetencias}
                    onChange={(e) => {
                      const v = Math.max(0, Math.min(1, Number(e.target.value)));
                      update({ pondCompetencias: v, pondObjetivos: Math.round((1 - v) * 100) / 100 });
                    }} />
                </div>
                <div className="form-field">
                  <label>Peso objetivos</label>
                  <input type="number" min="0" max="1" step="0.05"
                    value={form.pondObjetivos}
                    onChange={(e) => {
                      const v = Math.max(0, Math.min(1, Number(e.target.value)));
                      update({ pondObjetivos: v, pondCompetencias: Math.round((1 - v) * 100) / 100 });
                    }} />
                </div>
              </div>
              <div className="muted" style={{ fontSize: 11.5, marginTop: 8 }}>
                Los pesos suman 1.0 · si solo aplica una metodología, el otro queda en 0.
              </div>
            </div>
          )}

          {/* Step 2 · Quiénes */}
          {step === 2 && (
            <div className="pc-step-body">
              <div className="muted-xs" style={{ marginBottom: 8 }}>Audiencia del ciclo</div>
              <div className="pc-audiencia-grid">
                {[
                  ['todos',     'Todos los colaboradores', 'Ciclo organizacional'],
                  ['liderazgos','Solo liderazgos',         'Cargos liderazgo + directivo (recomendado para 360°)'],
                  ['cargo',     'Por cargo(s)',            'Selección manual de cargos específicos'],
                  ['area',      'Por área(s)',             'Selección manual de áreas'],
                  ['individual','Selección individual',     'Casos puntuales (período de prueba, etc.)'],
                ].map(([k, l, desc]) => (
                  <button key={k} type="button"
                    className={`pc-aud-card ${form.audienciaTipo === k ? 'active' : ''}`}
                    onClick={() => update({ audienciaTipo: k })}
                  >
                    <div className="pc-aud-name">{l}</div>
                    <div className="muted" style={{ fontSize: 11.5, marginTop: 3 }}>{desc}</div>
                  </button>
                ))}
              </div>

              {form.audienciaTipo === 'cargo' && (
                <div style={{ marginTop: 16 }}>
                  <div className="muted-xs">Cargos incluidos</div>
                  <div className="pc-cargos-pick">
                    {(window.CARGOS || []).map(c => {
                      const sel = form.audienciaCriterio.cargosIds.includes(c.id);
                      return (
                        <button key={c.id} type="button"
                          className={`pc-cargo-pill ${sel ? 'active' : ''}`}
                          onClick={() => {
                            const ids = sel
                              ? form.audienciaCriterio.cargosIds.filter(x => x !== c.id)
                              : [...form.audienciaCriterio.cargosIds, c.id];
                            update({ audienciaCriterio: { ...form.audienciaCriterio, cargosIds: ids } });
                          }}
                        >
                          {c.nombre} <span className="muted">· {c.headcount}</span>
                        </button>
                      );
                    })}
                  </div>
                </div>
              )}

              {form.audienciaTipo === 'area' && (
                <div style={{ marginTop: 16 }}>
                  <div className="muted-xs">Áreas incluidas</div>
                  <div className="pc-cargos-pick">
                    {Array.from(new Set((window.CARGOS || []).map(c => c.area))).map(a => {
                      const sel = form.audienciaCriterio.areas.includes(a);
                      return (
                        <button key={a} type="button"
                          className={`pc-cargo-pill ${sel ? 'active' : ''}`}
                          onClick={() => {
                            const ids = sel
                              ? form.audienciaCriterio.areas.filter(x => x !== a)
                              : [...form.audienciaCriterio.areas, a];
                            update({ audienciaCriterio: { ...form.audienciaCriterio, areas: ids } });
                          }}
                        >
                          {a}
                        </button>
                      );
                    })}
                  </div>
                </div>
              )}

              {form.audienciaTipo === 'individual' && (
                <IndividualPicker
                  selectedIds={form.audienciaCriterio.empleadosIds || []}
                  onChange={(ids) => update({ audienciaCriterio: { ...form.audienciaCriterio, empleadosIds: ids } })}
                />
              )}

              <div className="pc-aud-summary">
                <div>
                  <div className="muted-xs">Población resuelta</div>
                  <div className="pc-aud-num">{audienciaResolved.length}</div>
                  <div className="muted" style={{ fontSize: 11 }}>colaboradores · de {Object.keys(_emp).length} en el demo</div>
                </div>
                {form.metodologias.includes('360') && matricesAnalisis && (
                  <div>
                    <div className="muted-xs">Compatibilidad con 360°</div>
                    <div className="pc-aud-num">
                      <span style={{ color: 'var(--green-600)' }}>{matricesAnalisis.con360}</span>
                      <small> / {matricesAnalisis.total}</small>
                    </div>
                    <div className="muted" style={{ fontSize: 11 }}>
                      {matricesAnalisis.degradadosA180} degradan a 180° por anonimato N&lt;{form.anonimatoMinN}
                    </div>
                  </div>
                )}
              </div>
            </div>
          )}

          {/* Step 3 · Evaluadores */}
          {step === 3 && (
            <div className="pc-step-body">
              <div className="pc-info-banner">
                <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4M12 8h.01"/></svg>
                <div>
                  <b>Auto-poblado desde el organigrama.</b> El jefe directo y los reportes se asignan automáticamente.
                  Los pares = quienes comparten jefe directo. <b>Política:</b> el jefe puede ajustar pares · RRHH valida.
                </div>
              </div>

              <div className="pc-form-row" style={{ marginTop: 12 }}>
                <div className="form-field">
                  <label>Anonimato mínimo (N)</label>
                  <input type="number" min="2" max="10"
                    value={form.anonimatoMinN}
                    onChange={(e) => update({ anonimatoMinN: Math.max(2, Math.min(10, Number(e.target.value))) })}
                  />
                  <div className="muted" style={{ fontSize: 11.5, marginTop: 4 }}>
                    Habeas Data Ley 1581/2012 · si una perspectiva tiene menos de N evaluadores, los resultados se omiten.
                  </div>
                </div>
                <div className="form-field">
                  <label>Si N &lt; mínimo</label>
                  <div className="pc-mini-pill">Degradar 360° → 180° automáticamente</div>
                </div>
              </div>

              {form.metodologias.includes('360') && matricesAnalisis && (
                <>
                  <div className="muted-xs" style={{ marginTop: 16, marginBottom: 8 }}>
                    Análisis matriz · {matricesAnalisis.total} evaluados
                  </div>
                  <div className="pc-matriz-list">
                    {matricesAnalisis.detalle.slice(0, 8).map((d) => {
                      const persona = _emp[d.empId];
                      return (
                        <div key={d.empId} className={`pc-matriz-row ${d.anon.degradado360a180 ? 'degrad' : ''}`}>
                          <div className="doc-avatar" style={{ width: 28, height: 28, fontSize: 11 }}>
                            {persona?.initials || '??'}
                          </div>
                          <div style={{ flex: 1, minWidth: 0 }}>
                            <div style={{ fontSize: 12.5, fontWeight: 700 }}>{persona?.nombre || d.empId}</div>
                            <div className="muted mono" style={{ fontSize: 10.5, marginTop: 2 }}>
                              jefe: {d.matriz.manager.length || 0} · pares: {d.matriz.peers.length} · reportes: {d.matriz.reports.length}
                            </div>
                          </div>
                          <div style={{ display: 'flex', gap: 4 }}>
                            <AnonimatoBadge n={d.matriz.peers.length} minN={form.anonimatoMinN} />
                            <AnonimatoBadge n={d.matriz.reports.length} minN={form.anonimatoMinN} />
                          </div>
                          <span className={`pill ${d.anon.degradado360a180 ? 'amber-soft' : 'green'}`} style={{ fontSize: 10 }}>
                            {d.anon.degradado360a180 ? '180°' : '360°'}
                          </span>
                        </div>
                      );
                    })}
                    {matricesAnalisis.total > 8 && (
                      <div className="muted" style={{ fontSize: 11.5, marginTop: 6 }}>
                        + {matricesAnalisis.total - 8} más · revisables tras crear el ciclo en el modal "Diseñar matriz"
                      </div>
                    )}
                  </div>
                </>
              )}
            </div>
          )}

          {/* Step 4 · Cuándo + firma */}
          {step === 4 && (
            <div className="pc-step-body">
              <div className="pc-form-row">
                <div className="form-field">
                  <label>Período evaluado · inicio</label>
                  <input type="text" value={form.periodoInicio} onChange={(e) => update({ periodoInicio: e.target.value })} placeholder="DD/MM/AAAA" />
                </div>
                <div className="form-field">
                  <label>Período evaluado · fin</label>
                  <input type="text" value={form.periodoFin} onChange={(e) => update({ periodoFin: e.target.value })} placeholder="DD/MM/AAAA" />
                </div>
              </div>
              <div className="pc-form-row">
                <div className="form-field">
                  <label>Apertura del ciclo</label>
                  <input type="text" value={form.apertura} onChange={(e) => update({ apertura: e.target.value })} placeholder="DD/MM/AAAA" />
                </div>
                <div className="form-field">
                  <label>Cierre del ciclo</label>
                  <input type="text" value={form.cierre} onChange={(e) => update({ cierre: e.target.value })} placeholder="DD/MM/AAAA" />
                </div>
              </div>

              <div className="pc-firma-box">
                <label className="pc-check-line">
                  <input type="checkbox" checked={form.requireFirma} onChange={(e) => update({ requireFirma: e.target.checked })} />
                  <div>
                    <b>Requerir firma electrónica al cierre de cada evaluación</b>
                    <div className="muted" style={{ fontSize: 11.5 }}>
                      Ley 527/1999 + Dec. 2364/2012. Sustenta debido proceso ante MinTrabajo / tutela.
                    </div>
                  </div>
                </label>
                <label className="pc-check-line">
                  <input type="checkbox" checked={form.notificarPorEmail} onChange={(e) => update({ notificarPorEmail: e.target.checked })} />
                  <div>
                    <b>Notificar por correo electrónico</b>
                    <div className="muted" style={{ fontSize: 11.5 }}>Invitación inicial + 3 recordatorios automáticos.</div>
                  </div>
                </label>
                <label className="pc-check-line">
                  <input type="checkbox" checked={form.notificarPorPortal} onChange={(e) => update({ notificarPorPortal: e.target.checked })} />
                  <div>
                    <b>Notificar dentro del Portal del colaborador</b>
                    <div className="muted" style={{ fontSize: 11.5 }}>Aparece en "Mi desempeño" · pendientes.</div>
                  </div>
                </label>
              </div>

              <div className="pc-summary-card">
                <div className="muted-xs" style={{ marginBottom: 8 }}>Resumen</div>
                <div className="pc-summary-grid">
                  <div><div className="muted-xs">Nombre</div><div style={{ fontWeight: 700 }}>{form.nombre || '—'}</div></div>
                  <div><div className="muted-xs">Población</div><div style={{ fontWeight: 700 }}>{audienciaResolved.length} colaboradores</div></div>
                  <div><div className="muted-xs">Período</div><div className="mono" style={{ fontSize: 12.5 }}>{form.periodoInicio} → {form.periodoFin}</div></div>
                  <div>
                    <div className="muted-xs">Metodologías</div>
                    <div style={{ display: 'flex', gap: 4, flexWrap: 'wrap', marginTop: 4 }}>
                      {form.metodologias.map(m => <MetodologiaChip key={m} id={m} size="sm" />)}
                    </div>
                  </div>
                </div>
              </div>
            </div>
          )}
        </div>

        <div className="modal-foot">
          {step > 1
            ? <button className="btn" onClick={prev}>← Atrás</button>
            : <button className="btn" onClick={onClose}>Cancelar</button>}
          <span style={{ marginLeft: 'auto' }} />
          {step < 4
            ? <button className="btn primary" disabled={!canNext()} onClick={next}>Continuar →</button>
            : <button className="btn primary" onClick={submit}>Crear ciclo</button>}
        </div>
      </div>
    </div>
  );
};

window.NewCycleModal = NewCycleModal;
