/* 2.1 — Caracterización */

function Caracterizacion({ role }) {
  const [tab, setTab] = useState("directorio");
  return (
    <div className="page" data-screen-label="2.1 Caracterización">
      <div className="page-head">
        <div>
          <div className="meta">MÓDULO 2.1 · NÚCLEO DE INFORMACIÓN DEL ECOSISTEMA</div>
          <h1>Caracterización de actores</h1>
          <div className="sub">Registro estandarizado y segmentación avanzada del ecosistema. Compatible con formato OAPES · MinTIC.</div>
        </div>
        <div className="flex gap-8">
          <button className="btn"><Icon name="download" size={13}/> Exportar CSV</button>
          <button className="btn"><Icon name="download" size={13}/> Exportar XLSX</button>
          <button className="btn btn-primary"><Icon name="plus" size={13}/> Nuevo actor</button>
        </div>
      </div>

      <div className="tabs">
        <div className={`tab ${tab === "directorio" ? "active" : ""}`} onClick={() => setTab("directorio")}>
          Directorio <span className="badge">7,075</span>
        </div>
        <div className={`tab ${tab === "perfil" ? "active" : ""}`} onClick={() => setTab("perfil")}>
          Ficha de perfil
        </div>
        <div className={`tab ${tab === "matching" ? "active" : ""}`} onClick={() => setTab("matching")}>
          Motor de matching
        </div>
        <div className={`tab ${tab === "reglas" ? "active" : ""}`} onClick={() => setTab("reglas")}>
          Reglas de focalización <span className="badge">8</span>
        </div>
        <div className={`tab ${tab === "cohortes" ? "active" : ""}`} onClick={() => setTab("cohortes")}>
          Cohortes & regiones
        </div>
      </div>

      {tab === "directorio" && <Directorio/>}
      {tab === "perfil" && <FichaPerfil/>}
      {tab === "matching" && <MatchingEngine/>}
      {tab === "reglas" && <ReglasFocalizacion/>}
      {tab === "cohortes" && <CohortesRegiones/>}
    </div>
  );
}

// ───── Directorio + filtros ─────
function Directorio() {
  const [filters, setFilters] = useState({ tipo: "", depto: "", sector: "", madurez: "", zona: "", q: "" });
  const [selected, setSelected] = useState(null);

  const filtered = useMemo(() => window.ACTORES.filter(a => {
    if (filters.tipo && a.tipo !== filters.tipo) return false;
    if (filters.depto && a.depto !== filters.depto) return false;
    if (filters.sector && a.sector !== filters.sector) return false;
    if (filters.madurez && a.madurez < parseInt(filters.madurez)) return false;
    if (filters.zona && a.zona !== filters.zona) return false;
    if (filters.q && !(a.nombre.toLowerCase().includes(filters.q.toLowerCase()) || a.repLegal.toLowerCase().includes(filters.q.toLowerCase()))) return false;
    return true;
  }), [filters]);

  const totalEmpleados = filtered.reduce((s, a) => s + a.empleados, 0);

  return (
    <>
      <div className="filterbar" style={{ marginBottom: 12 }}>
        <div className="field">
          <label>Buscar</label>
          <input placeholder="Razón social, NIT o representante…" value={filters.q} onChange={e => setFilters({ ...filters, q: e.target.value })} style={{ width: 220 }}/>
        </div>
        <div className="field">
          <label>Tipo de actor</label>
          <select value={filters.tipo} onChange={e => setFilters({ ...filters, tipo: e.target.value })}>
            <option value="">Todos</option>
            {window.TIPOS_ACTOR.map(t => <option key={t.id} value={t.id}>{t.label}</option>)}
          </select>
        </div>
        <div className="field">
          <label>Departamento</label>
          <select value={filters.depto} onChange={e => setFilters({ ...filters, depto: e.target.value })}>
            <option value="">Todos</option>
            {window.DEPARTAMENTOS.map(d => <option key={d.code} value={d.name}>{d.name}</option>)}
          </select>
        </div>
        <div className="field">
          <label>Sector CIIU</label>
          <select value={filters.sector} onChange={e => setFilters({ ...filters, sector: e.target.value })}>
            <option value="">Todos</option>
            {window.SECTORES_CIIU.map(s => <option key={s.code} value={s.code}>{s.code} · {s.short}</option>)}
          </select>
        </div>
        <div className="field">
          <label>Madurez ≥</label>
          <select value={filters.madurez} onChange={e => setFilters({ ...filters, madurez: e.target.value })}>
            <option value="">Cualquiera</option>
            <option value="1">1 — Inicial</option>
            <option value="2">2 — Repetible</option>
            <option value="3">3 — Definido</option>
            <option value="4">4 — Gestionado</option>
            <option value="5">5 — Optimizado</option>
          </select>
        </div>
        <div className="field">
          <label>Zona</label>
          <select value={filters.zona} onChange={e => setFilters({ ...filters, zona: e.target.value })}>
            <option value="">Todas</option>
            <option value="urbano">Urbano</option>
            <option value="rural">Rural</option>
          </select>
        </div>
        <button className="btn btn-sm btn-ghost" onClick={() => setFilters({ tipo: "", depto: "", sector: "", madurez: "", zona: "", q: "" })} style={{ alignSelf: "flex-end", marginBottom: 1 }}>
          <Icon name="x" size={11}/> Limpiar
        </button>
        <span className="count">{filtered.length} de {window.ACTORES.length} actores · {totalEmpleados.toLocaleString()} empleados agregados</span>
      </div>

      <div className="card">
        <table className="data">
          <thead>
            <tr>
              <th style={{ width: 40 }}></th>
              <th>Actor</th>
              <th>NIT / Cédula</th>
              <th>Tipo</th>
              <th>Sector CIIU</th>
              <th>Departamento</th>
              <th>Zona</th>
              <th className="num">Empleados</th>
              <th>Madurez</th>
              <th>Conexiones</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {filtered.map(a => (
              <tr key={a.id} onClick={() => setSelected(a)} style={{ cursor: "pointer" }}>
                <td><Swatch tipo={a.tipo} size={28}/></td>
                <td>
                  <div className="cell-strong">{a.nombre}</div>
                  <div className="cell-sub">{a.repLegal}</div>
                </td>
                <td className="mono">{a.nit}</td>
                <td><span className="chip" style={{ background: window.colorFor(a.tipo) + "22", color: window.colorFor(a.tipo), borderColor: "transparent" }}>{window.labelFor(a.tipo)}</span></td>
                <td>
                  <span className="mono" style={{ color: "var(--c-ink-4)", fontSize: 10 }}>{a.sector}</span>
                  <div className="cell-sub">{(window.SECTORES_CIIU.find(s => s.code === a.sector) || {}).short}</div>
                </td>
                <td>{a.depto}<div className="cell-sub">{a.municipio}</div></td>
                <td><span className="chip">{a.zona}</span></td>
                <td className="num">{a.empleados}</td>
                <td><MadurezBar value={a.madurez}/></td>
                <td className="mono num">{a.conexiones}</td>
                <td><button className="btn btn-sm btn-ghost"><Icon name="eye" size={12}/></button></td>
              </tr>
            ))}
            {filtered.length === 0 && (
              <tr><td colSpan={11} style={{ textAlign: "center", padding: 40, color: "var(--c-ink-5)" }}>
                Sin resultados. Ajusta los filtros.
              </td></tr>
            )}
          </tbody>
        </table>
      </div>

      <Modal open={!!selected} onClose={() => setSelected(null)} title={selected ? selected.nombre : ""} width={820}>
        {selected && <ActorDetail actor={selected}/>}
      </Modal>
    </>
  );
}

function MadurezBar({ value }) {
  return (
    <div style={{ display: "flex", gap: 2 }}>
      {[1,2,3,4,5].map(n => (
        <div key={n} style={{
          width: 12, height: 6, borderRadius: 1,
          background: n <= value ? (value >= 4 ? "var(--c-success)" : value >= 3 ? "var(--c-primary)" : "var(--c-accent)") : "var(--c-line)"
        }}/>
      ))}
    </div>
  );
}

function ActorDetail({ actor }) {
  const sector = window.SECTORES_CIIU.find(s => s.code === actor.sector) || {};
  return (
    <div>
      <div style={{ display: "flex", gap: 16, alignItems: "center", marginBottom: 16 }}>
        <Swatch tipo={actor.tipo} size={48}/>
        <div>
          <div style={{ fontFamily: "var(--font-serif)", fontSize: 20, fontWeight: 600 }}>{actor.nombre}</div>
          <div style={{ fontSize: 12, color: "var(--c-ink-4)" }}>
            <span className="chip" style={{ marginRight: 6, background: window.colorFor(actor.tipo) + "22", color: window.colorFor(actor.tipo), borderColor: "transparent" }}>{window.labelFor(actor.tipo)}</span>
            NIT {actor.nit} · {actor.municipio}, {actor.depto}
          </div>
        </div>
        <div style={{ marginLeft: "auto", display: "flex", gap: 6 }}>
          <button className="btn btn-sm"><Icon name="msg" size={12}/> Contactar</button>
          <button className="btn btn-sm btn-primary"><Icon name="network" size={12}/> Conectar</button>
        </div>
      </div>

      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16, marginBottom: 12 }}>
        <Detail label="Representante legal" value={actor.repLegal}/>
        <Detail label="Correo institucional" value={actor.email}/>
        <Detail label="Sector CIIU" value={`${actor.sector} · ${sector.name || ""}`}/>
        <Detail label="Zona / territorio" value={`${actor.zona} · ${actor.municipio}`}/>
        <Detail label="Empleados" value={actor.empleados}/>
        <Detail label="Ingresos anuales" value={actor.ingresos}/>
        <Detail label="Nivel de madurez digital" value={<MadurezBar value={actor.madurez}/>}/>
        <Detail label="Conexiones activas" value={`${actor.conexiones} · KPI articulación`}/>
      </div>

      <Detail label="Capacidades y oferta" value={actor.oferta} block/>
      <Detail label="Necesidades / demanda" value={actor.necesidad} block/>
      <Detail label="Arenas digitales de interés" block value={
        <div style={{ display: "flex", gap: 4, flexWrap: "wrap" }}>
          {actor.arenas.map(a => <span key={a} className="chip info">{a}</span>)}
        </div>
      }/>
    </div>
  );
}

function Detail({ label, value, block }) {
  return (
    <div style={{ padding: "8px 0", borderBottom: "1px solid var(--c-line-2)", ...(block ? { gridColumn: "1 / -1" } : {}) }}>
      <div style={{ fontSize: 10, textTransform: "uppercase", letterSpacing: "0.06em", color: "var(--c-ink-5)", fontWeight: 600, marginBottom: 3 }}>{label}</div>
      <div style={{ fontSize: 12.5, color: "var(--c-ink)" }}>{value}</div>
    </div>
  );
}

// ───── Ficha de perfil (form OAPES) ─────
function FichaPerfil() {
  const t = useToast();
  const [form, setForm] = useState({
    nombre: "Mercadia Logística", nit: "901.347.882-4", email: "contacto@mercadia.co",
    telefono: "+57 601 555 0184", repLegal: "Juliana Restrepo M.",
    tipo: "startup_crecimiento", depto: "Bogotá D.C.", municipio: "Bogotá", zona: "urbano",
    sector: "H5320", actividad: "Plataforma SaaS de optimización de logística de última milla",
    empleados: "84", ingresos: "1.2B - 5B COP",
    oferta: "Software de ruteo dinámico, ventana de entregas y trazabilidad para flotas urbanas. APIs para WMS y TMS.",
    necesidad: "Capital Serie A para expansión Andina + México · Aliados con flotas > 200 vehículos.",
    objetivos: "Cerrar Serie A en Q3 · Llegar a 25 ciudades · Certificación ISO 27001.",
    madurez: "4",
    arenas: ["IoT", "IA"],
    visibilidad: "publico",
  });
  const [errors, setErrors] = useState({});

  const validate = () => {
    const e = {};
    if (!form.nombre) e.nombre = "Requerido";
    if (!/^\d{3}\.\d{3}\.\d{3}-\d$/.test(form.nit)) e.nit = "Formato esperado: 901.234.567-8";
    if (!/^\S+@\S+\.\S+$/.test(form.email)) e.email = "Correo inválido";
    if (!form.telefono) e.telefono = "Requerido";
    if (!form.sector) e.sector = "Requerido";
    setErrors(e);
    return Object.keys(e).length === 0;
  };

  const save = () => {
    if (validate()) t.push("Perfil guardado · Auditoría registrada", "success");
    else t.push("Hay campos por corregir", "info");
  };

  const completitud = useMemo(() => {
    const fields = Object.values(form).filter(v => v && (Array.isArray(v) ? v.length : true));
    return Math.round((fields.length / Object.keys(form).length) * 100);
  }, [form]);

  return (
    <div className="grid-2">
      <div className="card">
        <div className="card-head">
          <h3>Ficha completa · OAPES compatible</h3>
          <span className="chip success"><span className="dot"/> Validado MinTIC</span>
        </div>
        <div className="card-body">
          <Section title="Información general">
            <Row label="Nombre / Razón social" req error={errors.nombre}>
              <input className={`input ${errors.nombre ? "error" : ""}`} value={form.nombre} onChange={e => setForm({ ...form, nombre: e.target.value })}/>
            </Row>
            <Row label="NIT / Cédula" req error={errors.nit} help="Formato 999.999.999-9">
              <input className={`input ${errors.nit ? "error" : ""}`} value={form.nit} onChange={e => setForm({ ...form, nit: e.target.value })}/>
            </Row>
            <Row label="Correo institucional" req error={errors.email}>
              <input className={`input ${errors.email ? "error" : ""}`} value={form.email} onChange={e => setForm({ ...form, email: e.target.value })}/>
            </Row>
            <Row label="Teléfono" req error={errors.telefono}>
              <input className={`input ${errors.telefono ? "error" : ""}`} value={form.telefono} onChange={e => setForm({ ...form, telefono: e.target.value })}/>
            </Row>
            <Row label="Representante legal">
              <input className="input" value={form.repLegal} onChange={e => setForm({ ...form, repLegal: e.target.value })}/>
            </Row>
            <Row label="Tipo de actor" req>
              <select className="select" value={form.tipo} onChange={e => setForm({ ...form, tipo: e.target.value })}>
                {window.TIPOS_ACTOR.map(t => <option key={t.id} value={t.id}>{t.label}</option>)}
              </select>
            </Row>
          </Section>

          <Section title="Ubicación y territorio">
            <Row label="Departamento" req>
              <select className="select" value={form.depto} onChange={e => setForm({ ...form, depto: e.target.value })}>
                {window.DEPARTAMENTOS.map(d => <option key={d.code} value={d.name}>{d.name}</option>)}
              </select>
            </Row>
            <Row label="Municipio">
              <input className="input" value={form.municipio} onChange={e => setForm({ ...form, municipio: e.target.value })}/>
            </Row>
            <Row label="Zona">
              <div className="flex gap-8">
                {["urbano", "rural"].map(z => (
                  <label key={z} style={{ display: "flex", alignItems: "center", gap: 4, fontSize: 12 }}>
                    <input type="radio" checked={form.zona === z} onChange={() => setForm({ ...form, zona: z })}/>{z}
                  </label>
                ))}
              </div>
            </Row>
          </Section>

          <Section title="Sector económico y tamaño">
            <Row label="Código CIIU" req error={errors.sector}>
              <select className={`select ${errors.sector ? "error" : ""}`} value={form.sector} onChange={e => setForm({ ...form, sector: e.target.value })}>
                <option value="">Selecciona…</option>
                {window.SECTORES_CIIU.map(s => <option key={s.code} value={s.code}>{s.code} — {s.name}</option>)}
              </select>
            </Row>
            <Row label="Actividad económica">
              <textarea className="textarea" rows={2} value={form.actividad} onChange={e => setForm({ ...form, actividad: e.target.value })}/>
            </Row>
            <Row label="Número de empleados">
              <input className="input" type="number" value={form.empleados} onChange={e => setForm({ ...form, empleados: e.target.value })}/>
            </Row>
            <Row label="Rango de ingresos anuales">
              <select className="select" value={form.ingresos} onChange={e => setForm({ ...form, ingresos: e.target.value })}>
                <option>&lt;60M COP</option><option>60M - 180M COP</option><option>180M - 600M COP</option>
                <option>600M - 1.2B COP</option><option>1.2B - 5B COP</option><option>&gt;5B COP</option>
              </select>
            </Row>
          </Section>

          <Section title="Capacidades, demanda y madurez">
            <Row label="Capacidades / oferta">
              <textarea className="textarea" rows={2} value={form.oferta} onChange={e => setForm({ ...form, oferta: e.target.value })}/>
            </Row>
            <Row label="Necesidades / demanda">
              <textarea className="textarea" rows={2} value={form.necesidad} onChange={e => setForm({ ...form, necesidad: e.target.value })}/>
            </Row>
            <Row label="Objetivos estratégicos">
              <textarea className="textarea" rows={2} value={form.objetivos} onChange={e => setForm({ ...form, objetivos: e.target.value })}/>
            </Row>
            <Row label="Madurez digital y tecnológica">
              <div className="flex gap-8 items-center">
                <input type="range" min="1" max="5" value={form.madurez} onChange={e => setForm({ ...form, madurez: e.target.value })} style={{ flex: 1 }}/>
                <span className="mono" style={{ width: 60 }}>{form.madurez} / 5</span>
              </div>
            </Row>
            <Row label="Arenas digitales">
              <div style={{ display: "flex", gap: 4, flexWrap: "wrap" }}>
                {window.ARENAS_DIGITALES.map(a => {
                  const on = form.arenas.includes(a);
                  return (
                    <button key={a} type="button" onClick={() => setForm({ ...form, arenas: on ? form.arenas.filter(x => x !== a) : [...form.arenas, a] })}
                      className="chip" style={{
                        background: on ? "var(--c-primary)" : "var(--c-line-2)",
                        color: on ? "#fff" : "var(--c-ink-3)",
                        borderColor: on ? "var(--c-primary)" : "var(--c-line)",
                        cursor: "pointer"
                      }}>{a}</button>
                  );
                })}
              </div>
            </Row>
            <Row label="Visibilidad del perfil" help="Controla quién puede ver tu ficha completa">
              <div className="flex gap-8">
                {[{v:"publico", l:"Público en directorio"},{v:"red", l:"Solo conexiones"},{v:"privado", l:"Privado"}].map(o => (
                  <label key={o.v} style={{ display: "flex", alignItems: "center", gap: 4, fontSize: 12 }}>
                    <input type="radio" checked={form.visibilidad === o.v} onChange={() => setForm({ ...form, visibilidad: o.v })}/>{o.l}
                  </label>
                ))}
              </div>
            </Row>
          </Section>

          <div style={{ display: "flex", justifyContent: "flex-end", gap: 8, paddingTop: 14 }}>
            <button className="btn btn-ghost">Descartar</button>
            <button className="btn">Guardar borrador</button>
            <button className="btn btn-primary" onClick={save}><Icon name="check" size={12}/> Guardar y publicar</button>
          </div>
        </div>
      </div>

      <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
        <div className="card">
          <div className="card-head"><h3>Completitud de perfil</h3></div>
          <div className="card-body">
            <div style={{ display: "flex", alignItems: "baseline", gap: 8, marginBottom: 8 }}>
              <span style={{ fontFamily: "var(--font-serif)", fontSize: 32, fontWeight: 600 }}>{completitud}%</span>
              <span className="text-xs muted">de campos completos</span>
            </div>
            <div className="bar" style={{ height: 8 }}>
              <div className="fill success" style={{ width: `${completitud}%` }}/>
            </div>
            <div style={{ fontSize: 11, color: "var(--c-ink-4)", marginTop: 8 }}>Los perfiles completos reciben +40% más recomendaciones y prioridad en convocatorias.</div>
          </div>
        </div>
        <div className="card">
          <div className="card-head"><h3>Información del registro</h3></div>
          <div className="card-body" style={{ fontSize: 11.5 }}>
            <KV k="ID interno" v="ACT-A01-2026"/>
            <KV k="Creado" v="2025-09-14 09:22"/>
            <KV k="Última actualización" v="2026-05-26 14:28"/>
            <KV k="Verificación NIT" v={<span className="chip success"><Icon name="check" size={11}/> Cruzado con RUES</span>}/>
            <KV k="Validación correo" v={<span className="chip success">Verificado</span>}/>
            <KV k="Auditoría" v="12 ediciones · log completo"/>
          </div>
        </div>
        <div className="card">
          <div className="card-head"><h3>Campos OAPES (Anexo A1)</h3></div>
          <div className="card-body" style={{ fontSize: 11.5 }}>
            <KV k="Bloque 1 · Identificación" v="6/6 ✓"/>
            <KV k="Bloque 2 · Territorio" v="3/3 ✓"/>
            <KV k="Bloque 3 · CIIU & tamaño" v="4/4 ✓"/>
            <KV k="Bloque 4 · Capacidades" v="3/3 ✓"/>
            <KV k="Bloque 5 · Madurez" v="2/2 ✓"/>
            <KV k="Bloque 6 · Articulación" v="3/4"/>
          </div>
        </div>
      </div>
    </div>
  );
}

function Section({ title, children }) {
  return (
    <div style={{ marginBottom: 4 }}>
      <div style={{ fontSize: 11, textTransform: "uppercase", letterSpacing: "0.08em", color: "var(--c-primary)", fontWeight: 600, padding: "12px 0 6px", borderBottom: "1px solid var(--c-primary-100)", marginBottom: 4 }}>{title}</div>
      {children}
    </div>
  );
}

function Row({ label, req, error, help, children }) {
  return (
    <div className="form-row">
      <div className="label">{label}{req && <span className="req">*</span>}</div>
      <div>
        {children}
        {help && !error && <div className="help">{help}</div>}
        {error && <div className="error-msg"><Icon name="info" size={11}/> {error}</div>}
      </div>
    </div>
  );
}

function KV({ k, v }) {
  return (
    <div style={{ display: "flex", justifyContent: "space-between", padding: "6px 0", borderBottom: "1px solid var(--c-line-2)" }}>
      <span style={{ color: "var(--c-ink-4)" }}>{k}</span>
      <span style={{ color: "var(--c-ink-2)", fontWeight: 500 }}>{v}</span>
    </div>
  );
}

// ───── Motor de matching ─────
function MatchingEngine() {
  const [source, setSource] = useState("a01"); // Mercadia
  const [criteria, setCriteria] = useState({ sector: true, territorio: true, madurez: true, oferta_demanda: true, arenas: true });

  const sourceActor = window.ACTORES.find(a => a.id === source);
  const scored = useMemo(() => {
    if (!sourceActor) return [];
    return window.ACTORES.filter(a => a.id !== source).map(a => {
      let score = 0, signals = [];
      if (criteria.sector && a.sector === sourceActor.sector) { score += 22; signals.push("Mismo CIIU"); }
      if (criteria.territorio && a.depto === sourceActor.depto) { score += 16; signals.push("Mismo territorio"); }
      if (criteria.madurez && Math.abs(a.madurez - sourceActor.madurez) <= 1) { score += 14; signals.push("Madurez compatible"); }
      if (criteria.arenas) {
        const overlap = a.arenas.filter(x => sourceActor.arenas.includes(x)).length;
        if (overlap > 0) { score += overlap * 12; signals.push(`${overlap} arena${overlap > 1 ? "s" : ""} en común`); }
      }
      if (criteria.oferta_demanda) {
        // Heuristic: investor ↔ startup needing capital
        if ((a.tipo === "inversionista" && sourceActor.necesidad.toLowerCase().includes("capital")) ||
            (sourceActor.tipo === "inversionista" && a.necesidad.toLowerCase().includes("capital"))) {
          score += 26; signals.push("Demanda de capital ↔ inversión");
        }
        if (a.tipo === "mentor") { score += 14; signals.push("Mentor disponible"); }
        if (a.tipo === "corporativo" && sourceActor.tipo.startsWith("startup")) { score += 18; signals.push("Innovación abierta corporativa"); }
      }
      // base
      score += Math.random() * 8;
      score = Math.min(100, Math.round(score));
      return { actor: a, score, signals };
    }).sort((a, b) => b.score - a.score);
  }, [source, criteria, sourceActor]);

  return (
    <div style={{ display: "grid", gridTemplateColumns: "320px 1fr", gap: 16 }}>
      <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
        <div className="card">
          <div className="card-head"><h3>Actor base</h3></div>
          <div className="card-body">
            <select className="select" value={source} onChange={e => setSource(e.target.value)}>
              {window.ACTORES.map(a => <option key={a.id} value={a.id}>{a.nombre}</option>)}
            </select>
            {sourceActor && (
              <div style={{ marginTop: 12, padding: 12, background: "var(--c-primary-50)", borderRadius: 6, fontSize: 11.5 }}>
                <div style={{ fontWeight: 600, marginBottom: 4 }}>{sourceActor.nombre}</div>
                <div style={{ color: "var(--c-ink-3)" }}>{window.labelFor(sourceActor.tipo)} · {sourceActor.depto}</div>
                <div style={{ color: "var(--c-ink-4)", marginTop: 6, lineHeight: 1.4 }}><b>Necesita:</b> {sourceActor.necesidad}</div>
              </div>
            )}
          </div>
        </div>
        <div className="card">
          <div className="card-head"><h3>Atributos de matching</h3><span className="chip info">{Object.values(criteria).filter(Boolean).length} activos</span></div>
          <div className="card-body" style={{ display: "flex", flexDirection: "column", gap: 8 }}>
            {[
              { k: "sector", l: "Sector económico (CIIU)" },
              { k: "territorio", l: "Territorio (depto/región)" },
              { k: "madurez", l: "Nivel de madurez" },
              { k: "oferta_demanda", l: "Oferta ↔ demanda" },
              { k: "arenas", l: "Arenas digitales" },
            ].map(c => (
              <label key={c.k} style={{ display: "flex", justifyContent: "space-between", alignItems: "center", fontSize: 12, padding: "6px 0", borderBottom: "1px solid var(--c-line-2)" }}>
                <span>{c.l}</span>
                <input type="checkbox" checked={criteria[c.k]} onChange={e => setCriteria({ ...criteria, [c.k]: e.target.checked })}/>
              </label>
            ))}
          </div>
        </div>
      </div>

      <div className="card">
        <div className="card-head"><h3>Recomendaciones · matching en vivo</h3><span className="chip info">{scored.length} candidatos</span></div>
        <div className="card-body" style={{ padding: 0 }}>
          {scored.slice(0, 12).map(s => (
            <div key={s.actor.id} style={{ display: "flex", alignItems: "center", gap: 12, padding: "12px 16px", borderBottom: "1px solid var(--c-line-2)" }}>
              <ScoreRing score={s.score}/>
              <Swatch tipo={s.actor.tipo} size={32}/>
              <div style={{ flex: 1 }}>
                <div style={{ fontWeight: 600, fontSize: 13 }}>{s.actor.nombre}</div>
                <div style={{ fontSize: 11, color: "var(--c-ink-4)" }}>{window.labelFor(s.actor.tipo)} · {s.actor.depto} · {(window.SECTORES_CIIU.find(c => c.code === s.actor.sector)||{}).short}</div>
                <div style={{ display: "flex", gap: 4, flexWrap: "wrap", marginTop: 4 }}>
                  {s.signals.map((sig, i) => <span key={i} className="chip info" style={{ fontSize: 10 }}>{sig}</span>)}
                </div>
              </div>
              <div style={{ display: "flex", gap: 6 }}>
                <button className="btn btn-sm"><Icon name="eye" size={11}/></button>
                <button className="btn btn-sm btn-primary"><Icon name="network" size={11}/> Conectar</button>
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

function ScoreRing({ score }) {
  const c = 50 - 4;
  const dash = (score / 100) * 2 * Math.PI * c;
  const color = score >= 80 ? "var(--c-success)" : score >= 60 ? "var(--c-primary)" : "var(--c-accent)";
  return (
    <div style={{ position: "relative", width: 42, height: 42 }}>
      <svg width={42} height={42}>
        <circle cx={21} cy={21} r={c / 2 - 1 + 16} fill="none" stroke="var(--c-line-2)" strokeWidth="3"/>
        <circle cx={21} cy={21} r={c / 2 - 1 + 16} fill="none" stroke={color} strokeWidth="3"
          strokeDasharray={`${(score / 100) * 2 * Math.PI * (c / 2 - 1 + 16)} 999`}
          transform="rotate(-90 21 21)"/>
      </svg>
      <div style={{ position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", fontFamily: "var(--font-mono)", fontSize: 11, fontWeight: 600, color }}>
        {score}
      </div>
    </div>
  );
}

// ───── Reglas de focalización ─────
function ReglasFocalizacion() {
  const reglas = [
    { id: "R-01", nombre: "Convocatoria Aceleración Andina 2026-II", filtros: ["region=Andina", "tipo∈{startup_temprana, startup_crecimiento}", "madurez≥3"], destinos: 2412, estado: "activa" },
    { id: "R-02", nombre: "Programa Mujer Emprendedora Caribe", filtros: ["region=Caribe", "tipo=emprendedor", "género=F"], destinos: 384, estado: "activa" },
    { id: "R-03", nombre: "Pilotos IoT Industrial · Corporativos", filtros: ["arenas∋IoT", "tipo=corporativo"], destinos: 47, estado: "borrador" },
    { id: "R-04", nombre: "Mentoría fintech temprana", filtros: ["sector=K6492", "madurez≤3"], destinos: 184, estado: "activa" },
    { id: "R-05", nombre: "Rurales · Conectividad", filtros: ["zona=rural", "madurez≤2"], destinos: 1218, estado: "activa" },
    { id: "R-06", nombre: "Spin-offs académicos", filtros: ["tipo=academica", "interés∋transferencia"], destinos: 28, estado: "pausada" },
    { id: "R-07", nombre: "Deal flow Capital Andino", filtros: ["proyecto.necesita∋capital", "etapa∈{Seed,SerieA}"], destinos: 64, estado: "activa" },
    { id: "R-08", nombre: "Demo Day Bogotá", filtros: ["depto=Bogotá", "tipo∈{startup_*}", "diagnóstico=completo"], destinos: 412, estado: "activa" },
  ];
  return (
    <div className="card">
      <div className="card-head">
        <h3>Reglas de focalización · motor de convocatorias</h3>
        <button className="btn btn-sm btn-primary"><Icon name="plus" size={12}/> Nueva regla</button>
      </div>
      <table className="data">
        <thead><tr><th>ID</th><th>Nombre</th><th>Filtros combinados</th><th className="num">Destinatarios</th><th>Estado</th><th></th></tr></thead>
        <tbody>
          {reglas.map(r => (
            <tr key={r.id}>
              <td className="mono">{r.id}</td>
              <td><span className="cell-strong">{r.nombre}</span></td>
              <td>
                <div style={{ display: "flex", gap: 4, flexWrap: "wrap" }}>
                  {r.filtros.map((f, i) => <span key={i} className="chip mono" style={{ fontSize: 10 }}>{f}</span>)}
                </div>
              </td>
              <td className="num mono">{r.destinos.toLocaleString()}</td>
              <td>
                <span className={`chip ${r.estado === "activa" ? "success" : r.estado === "pausada" ? "warn" : ""}`}>{r.estado}</span>
              </td>
              <td><button className="btn btn-sm btn-ghost"><Icon name="edit" size={11}/></button></td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

// ───── Cohortes & regiones ─────
function CohortesRegiones() {
  return (
    <div className="grid-2">
      <div className="card">
        <div className="card-head"><h3>Análisis agregado por departamento</h3></div>
        <div className="card-body">
          <HBarChart data={window.DEPARTAMENTOS.slice(0, 12).map(d => ({ label: d.name, value: d.actores }))} format={v => v.toLocaleString()}/>
        </div>
      </div>
      <div className="card">
        <div className="card-head"><h3>Cohortes activas</h3></div>
        <div className="card-body" style={{ padding: 0 }}>
          {[
            { id: "2026-I", actores: 1842, estado: "activa", inicio: "Feb 2026", fin: "Jul 2026" },
            { id: "2025-II", actores: 1647, estado: "cerrada", inicio: "Ago 2025", fin: "Dic 2025" },
            { id: "2025-I", actores: 1218, estado: "cerrada", inicio: "Feb 2025", fin: "Jul 2025" },
            { id: "Caribe-Pilot", actores: 384, estado: "activa", inicio: "Mar 2026", fin: "Sep 2026" },
            { id: "Mujer-2026", actores: 718, estado: "activa", inicio: "Ene 2026", fin: "Dic 2026" },
          ].map(c => (
            <div key={c.id} style={{ display: "grid", gridTemplateColumns: "1fr auto auto auto", gap: 12, padding: "14px 16px", borderBottom: "1px solid var(--c-line-2)", alignItems: "center" }}>
              <div>
                <div style={{ fontWeight: 600, fontSize: 13 }}>Cohorte {c.id}</div>
                <div style={{ fontSize: 11, color: "var(--c-ink-4)" }}>{c.inicio} → {c.fin}</div>
              </div>
              <div className="mono" style={{ fontSize: 12 }}>{c.actores.toLocaleString()} actores</div>
              <span className={`chip ${c.estado === "activa" ? "success" : ""}`}>{c.estado}</span>
              <button className="btn btn-sm"><Icon name="eye" size={11}/></button>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

window.Caracterizacion = Caracterizacion;
