/* ============================================================
   SYMPHO · K'IN — core: router, role context, cockpits, primitives
   exports: KinApp + KinHead, Gauge, LiveTile, KinBars, pfHue, fmtKW
   ============================================================ */

// ---- formatting helpers ----
window.fmtKW = (n) => (n < 0 ? "−" : "") + Math.abs(n).toLocaleString("es-MX") + " kW";
window.pfHue = (pf) => pf >= 0.95 ? "var(--ek)" : pf >= 0.90 ? "var(--kin)" : "var(--bad)";
const kinMoney = (n) => "$" + Math.round(n).toLocaleString("es-MX");
const kinMoneyK = (n) => n >= 1e6 ? "$" + (n/1e6).toFixed(2) + "M" : "$" + Math.round(n/1000) + "k";

// ============================================================
//  Shared K'in primitives
// ============================================================

// page header with role context
function KinHead({ title, sub, role, action, right }) {
  const a = window.APPS.find(x => x.id === "kin");
  const rc = role ? window.KIN_ROLES[role] : null;
  return (
    <div className="pagehead" style={{ marginBottom: 22 }}>
      <Glyph app={a} size={40} />
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ display: "flex", alignItems: "center", gap: 9, flexWrap: "wrap" }}>
          <h1 className="disp" style={{ fontSize: 23, fontWeight: 600, letterSpacing: "-0.02em" }}>{title}</h1>
          <span className="kin-live">en vivo · {window.KIN_SITE.site}</span>
        </div>
        {sub && <p className="muted" style={{ fontSize: 13, marginTop: 4 }}>{sub}</p>}
      </div>
      {right}
      {action && <button className="btn btn-primary" style={{ background: "var(--kin)" }}><Icon name={action.icon} size={15} /> {action.label}</button>}
    </div>
  );
}

// radial 270° gauge
function Gauge({ value, min = 0, max = 1, display, label, hue = "var(--kin)", size = 132, thickness = 11 }) {
  const pct = Math.max(0, Math.min(1, (value - min) / (max - min)));
  const r = (size - thickness) / 2 - 2;
  const circ = 2 * Math.PI * r;
  const track = circ * 0.75;
  return (
    <div className="kin-gauge-wrap">
      <div style={{ position: "relative", width: size, height: size }}>
        <svg width={size} height={size} style={{ transform: "rotate(135deg)" }}>
          <circle cx={size/2} cy={size/2} r={r} fill="none" stroke="var(--surface-3)" strokeWidth={thickness}
            strokeDasharray={`${track} ${circ}`} strokeLinecap="round" />
          <circle cx={size/2} cy={size/2} r={r} fill="none" stroke={hue} strokeWidth={thickness}
            strokeDasharray={`${track * pct} ${circ}`} strokeLinecap="round"
            style={{ transition: "stroke-dasharray 0.7s var(--ease)" }} />
        </svg>
        <div style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center", textAlign: "center" }}>
          <div>
            <div className="disp" style={{ fontSize: size * 0.21, fontWeight: 600, letterSpacing: "-0.02em", lineHeight: 1 }}>{display}</div>
          </div>
        </div>
      </div>
      {label && <div className="kin-gauge-cap">{label}</div>}
    </div>
  );
}

// big live metric tile
function LiveTile({ icon, label, value, unit, sub, accent, trend, hue = "var(--kin)" }) {
  return (
    <div className="kin-live-tile" data-accent={accent ? "true" : "false"}>
      <div className="kin-tile-top">
        <span className="kin-tile-ic" style={hue !== "var(--kin)" ? { background: `color-mix(in oklch, ${hue} 16%, transparent)`, color: hue, borderColor: `color-mix(in oklch, ${hue} 28%, transparent)` } : undefined}><Icon name={icon} size={17} /></span>
        {trend != null && <span className="mono" style={{ fontSize: 12, color: trend >= 0 ? "var(--ok)" : "var(--bad)" }}>{trend >= 0 ? "▲" : "▼"} {Math.abs(trend)}%</span>}
        {sub && trend == null && <span className="kin-live" style={{ fontSize: 10 }}>{sub}</span>}
      </div>
      <div className="kin-tile-val">{value}{unit && <small> {unit}</small>}</div>
      <div className="kin-tile-lbl">{label}</div>
    </div>
  );
}

// 24h demand bars (with solar overlay + tariff coloring)
function KinBars({ height = 130, showSolar = true }) {
  const prof = window.KIN_PROFILE, solar = window.KIN_SOLAR_PROFILE, hours = window.KIN_TARIFF_HOURS;
  const max = Math.max(...prof) * 1.05;
  const nowH = 18;
  return (
    <div>
      <div className="kin-livebars" style={{ height }}>
        {prof.map((v, i) => (
          <div key={i} style={{ flex: 1, display: "flex", flexDirection: "column", justifyContent: "flex-end", position: "relative", minWidth: 0 }} title={`${String(i).padStart(2,"0")}:00 · ${v} kW`}>
            <div className="kin-livebar" data-now={i === nowH} data-period={hours[i]} style={{ height: (v / max * height) + "px" }} />
            {showSolar && solar[i] > 0 && (
              <div style={{ position: "absolute", left: 1, right: 1, bottom: 0, height: (solar[i] / max * height) + "px", background: "color-mix(in oklch, var(--ek) 60%, transparent)", borderRadius: "3px 3px 0 0" }} />
            )}
          </div>
        ))}
      </div>
      <div style={{ display: "flex", justifyContent: "space-between", marginTop: 6 }}>
        {["00","06","12","18","23"].map(h => <span key={h} className="mono" style={{ fontSize: 10, color: "var(--text-4)" }}>{h}h</span>)}
      </div>
    </div>
  );
}

// ============================================================
//  ROUTER
// ============================================================
function KinApp({ role, sub }) {
  const r = role || "fm";
  switch (sub) {
    case "cockpit":    return <KinCockpit role={r} />;
    case "monitor":    return <KinMonitor role={r} />;
    case "twin":       return <KinTwin role={r} />;
    case "quality":    return <KinQuality role={r} />;
    case "analytics":  return <KinAnalytics role={r} />;
    case "finance":    return <KinFinance role={r} />;
    case "der":        return <KinDER role={r} />;
    case "alerts":     return <KinAlerts role={r} />;
    case "copilot":    return <KinCopilot role={r} />;
    case "automation": return <KinAutomation role={r} />;
    case "reports":    return <KinReports role={r} />;
    case "carbon":     return <KinCarbon role={r} />;
    case "devices":    return <KinDevices role={r} />;
    case "connectors": return <KinConnectors role={r} />;
    case "rbac":       return <KinRBAC role={r} />;
    default:           return <KinCockpit role={r} />;
  }
}

// ============================================================
//  COCKPIT — el dashboard cambia por persona (PRD §12.1)
// ============================================================
function KinCockpit({ role }) {
  if (role === "cfo")   return <CockpitCFO />;
  if (role === "op")    return <CockpitOP />;
  if (role === "eng")   return <CockpitEng />;
  if (role === "admin") return <CockpitAdmin />;
  return <CockpitFM />;
}

// pequeña tarjeta "ir a recomendaciones"
function RecTeaser() {
  const nav = useNav();
  const top = window.KIN_RECS[0];
  return (
    <div className="card" style={{ padding: 18, background: "linear-gradient(150deg, color-mix(in oklch, var(--kin) 14%, var(--surface)), var(--surface) 65%)", borderColor: "color-mix(in oklch, var(--kin) 28%, var(--line))" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 9, marginBottom: 10 }}>
        <span className="kin-tile-ic"><Icon name="sparkle" size={16} /></span>
        <b className="disp" style={{ fontSize: 14 }}>K'in Copilot recomienda</b>
      </div>
      <div style={{ fontSize: 13.5, color: "var(--text)", lineHeight: 1.5 }}>{top.title}</div>
      <div style={{ display: "flex", alignItems: "baseline", gap: 8, marginTop: 10 }}>
        <span className="kin-rec-impact" style={{ fontSize: 20 }}>{kinMoney(top.impact)}</span>
        <span className="mono" style={{ fontSize: 11, color: "var(--text-4)" }}>{top.unit} · {Math.round(top.conf*100)}% confianza</span>
      </div>
      <button className="btn btn-sm" style={{ marginTop: 14, width: "100%", justifyContent: "center" }} onClick={() => nav.openApp("kin", "copilot")}>
        Ver con Copilot <Icon name="arrowr" size={13} />
      </button>
    </div>
  );
}

// ---- Facility Manager ----
function CockpitFM() {
  const L = window.KIN_LIVE;
  return (
    <div className="canvas-in wide rise kin">
      <KinHead role="fm" title="Cockpit" sub="Operación, costo y estado del sitio en tiempo real · Facility Manager" />
      <div className="grid-4" style={{ marginBottom: 14 }}>
        <LiveTile icon="activity" label="Demanda actual" value={L.demandKW.toLocaleString("es-MX")} unit="kW" accent sub={`pico hoy ${L.peakTodayKW} kW`} />
        <LiveTile icon="bolt" label="Energía hoy" value={L.energyTodayMWh} unit="MWh" trend={4} />
        <LiveTile icon="dollar" label="Costo mes a la fecha" value={kinMoneyK(L.costMTD)} trend={6} />
        <LiveTile icon="warn" label="Alertas activas" value="5" sub="1 crítica" hue="var(--bad)" />
      </div>

      <div className="grid-2" style={{ alignItems: "start", marginBottom: 14, gridTemplateColumns: "minmax(0,1.6fr) minmax(0,1fr)" }}>
        <div className="card" style={{ padding: 20 }}>
          <Section title="Perfil de demanda · 24 h" sub="Barras grises = consumo de red · verde = aporte solar · rojo = horario punta CFE"
            right={<span className="badge">contratada {window.KIN_SITE.contractedKW} kW</span>} style={{ marginBottom: 18 }} />
          <KinBars height={150} />
        </div>
        <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          <div className="card" style={{ padding: 18, display: "flex", gap: 16, alignItems: "center", justifyContent: "space-around" }}>
            <Gauge value={L.pf} min={0.8} max={1} display={L.pf.toFixed(2)} label="Factor de potencia" hue={window.pfHue(L.pf)} size={118} />
            <Gauge value={L.demandKW} max={window.KIN_SITE.contractedKW} display={Math.round(L.demandKW/window.KIN_SITE.contractedKW*100)+"%"} label="Uso de demanda" size={118} />
          </div>
          <RecTeaser />
        </div>
      </div>

      <PanelMixCard />
    </div>
  );
}

// shared panel-mix table used by several cockpits
function PanelMixCard() {
  const nav = useNav();
  const tgd = window.KIN_HIER[0];
  return (
    <div className="card" style={{ padding: 0, overflow: "hidden" }}>
      <div className="card-head"><b style={{ fontSize: 14 }}>Reparto por tablero</b>
        <button className="btn btn-ghost btn-sm" onClick={() => nav.openApp("kin", "twin")}>Abrir Digital Twin <Icon name="arrowr" size={13} /></button></div>
      <table className="tbl">
        <thead><tr><th>Tablero</th><th>Carga</th><th>Factor de potencia</th><th>Utilización</th><th style={{ textAlign: "right" }}>Demanda</th></tr></thead>
        <tbody>
          {tgd.children.filter(c => c.kind !== "DER").map((c, i) => (
            <tr key={i} style={{ cursor: "pointer" }} onClick={() => nav.openApp("kin", "twin")}>
              <td style={{ color: "var(--text)", fontWeight: 500 }}><span className="kin-dot-sm" style={{ background: c.hue, display: "inline-block", marginRight: 8 }} />{c.name}</td>
              <td>{c.kind}</td>
              <td><span className="mono" style={{ color: window.pfHue(c.pf) }}>{c.pf.toFixed(2)}</span>{c.pf < 0.9 && <span className="badge warn dot" style={{ marginLeft: 8 }}>bajo</span>}</td>
              <td style={{ width: 160 }}><div className="bar"><i style={{ width: c.load + "%", background: c.hue }} /></div></td>
              <td className="num">{c.kw.toLocaleString("es-MX")} kW</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

// ---- Director / CFO ----
function CockpitCFO() {
  const L = window.KIN_LIVE, F = window.KIN_FORECAST;
  const maxC = Math.max(...F.costK);
  return (
    <div className="canvas-in wide rise kin">
      <KinHead role="cfo" title="Dashboard ejecutivo" sub="ROI, ahorro verificado y proyección de costo · Dirección / CFO" />
      <div className="grid-4" style={{ marginBottom: 14 }}>
        <LiveTile icon="dollar" label="Costo proyectado del mes" value={kinMoneyK(L.costForecast)} accent trend={8} />
        <LiveTile icon="check" label="Ahorro verificado (año)" value={kinMoneyK(L.savingsYTD)} sub="M&V · IPMVP" hue="var(--ek)" />
        <LiveTile icon="trend" label="Ahorro del mes" value={kinMoneyK(L.savingsMTD)} hue="var(--ek)" />
        <LiveTile icon="leaf" label="CO₂ Alcance 2 (mes)" value={L.co2MonthT} unit="tCO₂e" hue="var(--manik)" />
      </div>

      <div className="grid-2" style={{ alignItems: "start", marginBottom: 14, gridTemplateColumns: "minmax(0,1.5fr) minmax(0,1fr)" }}>
        <div className="card" style={{ padding: 20 }}>
          <Section title="Proyección de costo · próximos 7 días" sub={`Confianza del pronóstico ${Math.round(F.confidence*100)}% · cierre estimado ${kinMoney(F.monthEndMXN)}`} style={{ marginBottom: 18 }} />
          <div style={{ display: "flex", alignItems: "flex-end", gap: 14, height: 150 }}>
            {F.costK.map((c, i) => (
              <div key={i} style={{ flex: 1, display: "flex", flexDirection: "column", alignItems: "center", gap: 8, justifyContent: "flex-end" }}>
                <span className="mono" style={{ fontSize: 11, color: "var(--text-2)" }}>${c}k</span>
                <div style={{ width: "100%", height: (c/maxC*110)+"px", borderRadius: "6px 6px 0 0", background: i > 4 ? "var(--surface-3)" : "linear-gradient(var(--kin), color-mix(in oklch, var(--kin) 55%, var(--surface-3)))" }} />
                <span className="mono" style={{ fontSize: 10.5, color: "var(--text-4)" }}>{F.days[i]}</span>
              </div>
            ))}
          </div>
        </div>
        <RecTeaser />
      </div>

      <div className="card" style={{ padding: 0, overflow: "hidden" }}>
        <div className="card-head"><b style={{ fontSize: 14 }}>Proyectos de eficiencia · ROI y M&V</b><span className="mono" style={{ fontSize: 11, color: "var(--text-4)" }}>IPMVP</span></div>
        <table className="tbl">
          <thead><tr><th>Proyecto</th><th>CapEx</th><th>Ahorro / año</th><th>Payback</th><th>Protocolo</th><th>Estado</th></tr></thead>
          <tbody>
            {window.KIN_PROJECTS.map((p, i) => (
              <tr key={i}>
                <td style={{ color: "var(--text)", fontWeight: 500 }}>{p.name}</td>
                <td className="mono">{p.capex ? kinMoney(p.capex) : "—"}</td>
                <td className="num" style={{ color: "var(--ek)" }}>{kinMoney(p.savingYr)}</td>
                <td className="mono">{p.payback ? p.payback + " meses" : "inmediato"}</td>
                <td className="mono" style={{ fontSize: 11.5, color: "var(--text-3)" }}>{p.mv}</td>
                <td><Pill status={p.status === "Verificado" ? "Aprobado" : p.status === "En medición" ? "En proceso" : "Pendiente"} /></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

// ---- Operador ----
function CockpitOP() {
  const nav = useNav();
  const L = window.KIN_LIVE;
  const open = window.KIN_ALERTS.filter(a => a.state !== "Cerrada");
  return (
    <div className="canvas-in wide rise kin">
      <KinHead role="op" title="Centro de operación" sub="Alertas, estado de equipos y acciones pendientes · Operador de turno" />
      <div className="grid-4" style={{ marginBottom: 14 }}>
        <LiveTile icon="warn" label="Alertas abiertas" value={open.filter(a=>a.state==="Abierta").length} sub="1 crítica" hue="var(--bad)" accent />
        <LiveTile icon="activity" label="Demanda actual" value={L.demandKW.toLocaleString("es-MX")} unit="kW" />
        <LiveTile icon="battery" label="Batería · SoC" value={L.batterySoC} unit="%" sub={`SoH ${L.batterySoH}%`} hue="var(--ek)" />
        <LiveTile icon="sliders" label="Acciones por aprobar" value="1" sub="recorte de pico 19h" hue="var(--kin)" />
      </div>
      <div className="grid-2" style={{ alignItems: "start", gridTemplateColumns: "minmax(0,1.5fr) minmax(0,1fr)" }}>
        <div className="card" style={{ padding: 0, overflow: "hidden" }}>
          <div className="card-head"><b style={{ fontSize: 14 }}>Alertas activas</b>
            <button className="btn btn-ghost btn-sm" onClick={() => nav.openApp("kin", "alerts")}>Centro de alertas <Icon name="arrowr" size={13} /></button></div>
          <div style={{ padding: 12, display: "flex", flexDirection: "column", gap: 10 }}>
            {open.slice(0, 4).map(a => (
              <div key={a.id} className="kin-alert" data-sev={a.sev} onClick={() => nav.openApp("kin", "alerts")} style={{ cursor: "pointer" }}>
                <div className="kin-alert-spine" />
                <div className="kin-alert-body">
                  <div style={{ display: "flex", alignItems: "center", gap: 9 }}>
                    <span className="kin-sev-tag" data-sev={a.sev}>{a.sev === "crit" ? "crítica" : a.sev === "high" ? "alta" : a.sev === "med" ? "media" : "baja"}</span>
                    <b style={{ fontSize: 13.5 }}>{a.title}</b>
                  </div>
                  <div className="muted" style={{ fontSize: 12, marginTop: 5 }}>{a.node} · {a.time}</div>
                </div>
                <div className="kin-alert-side"><Pill status={a.state} /></div>
              </div>
            ))}
          </div>
        </div>
        <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          <div className="card" style={{ padding: 18 }}>
            <Section title="Acción por aprobar" style={{ marginBottom: 14 }} />
            <div className="kin-flow-node" data-kind="trigger" style={{ marginBottom: 10 }}>
              <span className="kin-flow-ic" style={{ background: "var(--kin-dim)", color: "var(--kin)" }}><Icon name="flash" size={18} /></span>
              <div style={{ flex: 1 }}><b style={{ fontSize: 13 }}>Recorte de pico con BESS</b><div className="muted" style={{ fontSize: 11.5, marginTop: 3 }}>Descargar 110 kW · 19:00–21:00 · ahorro ~$680</div></div>
            </div>
            <div style={{ display: "flex", gap: 8 }}>
              <button className="btn btn-primary" style={{ flex: 1, justifyContent: "center", background: "var(--kin)" }}><Icon name="check" size={15} /> Aprobar</button>
              <button className="btn" style={{ flex: 1, justifyContent: "center" }}>Posponer</button>
            </div>
            <p className="mono" style={{ fontSize: 10.5, color: "var(--text-4)", marginTop: 10, textAlign: "center" }}>Nivel 2 · requiere aprobación humana</p>
          </div>
          <div className="card" style={{ padding: 18, display: "flex", gap: 16, justifyContent: "space-around" }}>
            <Gauge value={L.batterySoC/100} display={L.batterySoC+"%"} label="SoC batería" hue="var(--ek)" size={108} />
            <Gauge value={L.ups ? 0.42 : 0.42} display="42%" label="Carga UPS" hue="var(--pakal)" size={108} />
          </div>
        </div>
      </div>
    </div>
  );
}

// ---- Ingeniero eléctrico ----
function CockpitEng() {
  const nav = useNav();
  const L = window.KIN_LIVE;
  return (
    <div className="canvas-in wide rise kin">
      <KinHead role="eng" title="Cockpit técnico" sub="Calidad de energía, riesgo y diagnóstico · Ingeniero eléctrico" />
      <div className="grid-4" style={{ marginBottom: 14 }}>
        <LiveTile icon="gauge" label="Factor de potencia" value={L.pf.toFixed(3)} sub="objetivo ≥ 0.90" hue={window.pfHue(L.pf)} accent />
        <LiveTile icon="wave" label="THD de corriente" value={L.thd} unit="%" sub="VFDs 8.2%" hue="var(--warn)" />
        <LiveTile icon="bolt" label="Desbalance de tensión" value={L.voltImbalance} unit="%" />
        <LiveTile icon="activity" label="Frecuencia" value={L.freq} unit="Hz" hue="var(--ek)" />
      </div>
      <div className="grid-2" style={{ alignItems: "start", gridTemplateColumns: "minmax(0,1fr) minmax(0,1.4fr)" }}>
        <div className="card" style={{ padding: 20 }}>
          <Section title="Calidad por tablero" right={<button className="btn btn-ghost btn-sm" onClick={() => nav.openApp("kin", "quality")}>Detalle <Icon name="arrowr" size={13} /></button>} style={{ marginBottom: 16 }} />
          <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
            {window.KIN_QUALITY.map((q, i) => (
              <div key={i} style={{ display: "flex", alignItems: "center", gap: 12 }}>
                <span style={{ flex: 1, fontSize: 12.5, color: "var(--text-2)" }}>{q.panel}</span>
                <span className="mono" style={{ fontSize: 12, color: window.pfHue(q.pf), width: 48, textAlign: "right" }}>{q.pf.toFixed(2)}</span>
                <div className="bar" style={{ width: 80 }}><i style={{ width: (q.thd/10*100)+"%", background: q.thd > 7 ? "var(--bad)" : "var(--kin)" }} /></div>
                <span className="mono" style={{ fontSize: 11, color: "var(--text-4)", width: 44 }}>THD {q.thd}%</span>
                {q.status === "warn" && <span className="dot" style={{ background: "var(--warn)" }} />}
              </div>
            ))}
          </div>
        </div>
        <div className="card" style={{ padding: 20 }}>
          <Section title="Espectro armónico · bancada de VFDs" sub="Armónicos impares de corriente — 5ª y 7ª dominantes" style={{ marginBottom: 18 }} />
          <div className="kin-harm">
            {window.KIN_HARMONICS.map((h, i) => (
              <div key={i} className="kin-harm-col">
                <span className="mono" style={{ fontSize: 10.5, color: "var(--text-2)" }}>{h.v}%</span>
                <div className="kin-harm-bar" data-hot={h.v > 5} style={{ height: (h.v/8*100)+"%" }} />
                <span className="mono" style={{ fontSize: 10, color: "var(--text-4)" }}>{h.h}</span>
              </div>
            ))}
          </div>
        </div>
      </div>
      <div style={{ marginTop: 14 }}><PanelMixCard /></div>
    </div>
  );
}

// ---- Administrador ----
function CockpitAdmin() {
  const nav = useNav();
  const online = window.KIN_DEVICES.filter(d => d.status === "En línea").length;
  return (
    <div className="canvas-in wide rise kin">
      <KinHead role="admin" title="Salud del sistema" sub="Dispositivos, conectores y aprovisionamiento · Administrador del tenant" />
      <div className="grid-4" style={{ marginBottom: 14 }}>
        <LiveTile icon="thermo" label="Dispositivos en línea" value={`${online}/${window.KIN_DEVICES.length}`} sub="1 en alerta" accent />
        <LiveTile icon="antenna" label="Conectores activos" value="3" sub="Modbus · MQTT · SNMP" hue="var(--pakal)" />
        <LiveTile icon="cpu" label="Gateway de borde" value="En línea" sub={window.KIN_SITE.gatewayId} hue="var(--ek)" />
        <LiveTile icon="users" label="Usuarios del tenant" value={window.KIN_USERS.length} sub="5 roles" hue="var(--manik)" />
      </div>
      <div className="grid-2" style={{ alignItems: "start" }}>
        <div className="card" style={{ padding: 0, overflow: "hidden" }}>
          <div className="card-head"><b style={{ fontSize: 14 }}>Dispositivos</b>
            <button className="btn btn-ghost btn-sm" onClick={() => nav.openApp("kin", "devices")}>Provisión <Icon name="arrowr" size={13} /></button></div>
          <table className="tbl">
            <thead><tr><th>Dispositivo</th><th>Protocolo</th><th>Estado</th></tr></thead>
            <tbody>
              {window.KIN_DEVICES.slice(0, 6).map((d, i) => (
                <tr key={i}>
                  <td style={{ color: "var(--text)", fontWeight: 500 }}>{d.name}<div className="mono" style={{ fontSize: 10.5, color: "var(--text-4)" }}>{d.id} · {d.node}</div></td>
                  <td className="mono" style={{ fontSize: 12 }}>{d.proto}</td>
                  <td><Pill status={d.status === "En línea" ? "Activo" : d.status === "Alerta" ? "Error" : "Pendiente"} /></td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <div className="card" style={{ padding: 0, overflow: "hidden" }}>
          <div className="card-head"><b style={{ fontSize: 14 }}>Conectores</b>
            <button className="btn btn-ghost btn-sm" onClick={() => nav.openApp("kin", "connectors")}>Catálogo <Icon name="arrowr" size={13} /></button></div>
          <div style={{ padding: 12, display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10 }}>
            {window.KIN_CONNECTORS.slice(0, 4).map((c, i) => (
              <div key={i} className="kin-conn" data-on={c.devices > 0} style={{ padding: 13 }}>
                <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
                  <span className="kin-tile-ic" style={{ width: 28, height: 28 }}><Icon name={c.icon} size={15} /></span>
                  <span className="badge" style={c.devices > 0 ? { background: "var(--kin-dim)", color: "var(--kin)" } : undefined}>{c.phase}</span>
                </div>
                <b style={{ fontSize: 13 }}>{c.name}</b>
                <span className="mono" style={{ fontSize: 11, color: "var(--text-4)" }}>{c.devices} dispositivos</span>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { KinApp, KinHead, Gauge, LiveTile, KinBars, PanelMixCard, kinMoney, kinMoneyK });
