// ============================================================
// app.jsx · Navigator shell · routing · toggles
// ============================================================

// ---- faux backdrop behind modal showcases ----
function FauxBehind() {
  return (
    <div style={{ position: "absolute", inset: 0, padding: 36, opacity: 0.5, filter: "saturate(0.6)" }}>
      <div className="xk-card" style={{ padding: 26, maxWidth: 760, margin: "40px auto" }}>
        <Sk w={220} h={20} style={{ marginBottom: 16 }} />
        <Sk w="100%" h={11} style={{ marginBottom: 8 }} /><Sk w="80%" h={11} style={{ marginBottom: 20 }} />
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
          <Sk h={48} /><Sk h={48} /><Sk h={48} /><Sk h={48} />
        </div>
      </div>
    </div>
  );
}
function ModalArtifact({ render }) {
  return (
    <div style={{ height: "100%", position: "relative", overflow: "hidden", background: "var(--xk-bg)" }}>
      <FauxBehind />
      {render(() => {})}
    </div>
  );
}

// ---- States showcase wrappers ----
function StateShowcase({ title, children }) {
  return (
    <div className="no-scrollbar" style={{ height: "100%", overflowY: "auto", background: "var(--xk-bg)" }}>
      <div style={{ maxWidth: 880, margin: "0 auto", padding: 36 }}>
        <WizardHead title={title} subtitle="Patrón reusable · se aplica en cualquier pantalla con este estado." />
        {children}
      </div>
    </div>
  );
}
function SLoadingArtifact() {
  return (
    <StateShowcase title="S-Loading · skeleton">
      <div style={{ display: "flex", flexDirection: "column", gap: 28 }}>
        <div><Eyebrow>KPIs</Eyebrow><SLoading variant="kpis" /></div>
        <div><Eyebrow>Cards</Eyebrow><SLoading variant="cards" rows={3} cols={3} /></div>
        <div><Eyebrow>Tabla</Eyebrow><SLoading variant="table" rows={4} /></div>
        <div><Eyebrow>Spinner · acción puntual</Eyebrow><div style={{ display: "flex", alignItems: "center", gap: 12 }}><Spinner /><span style={{ fontSize: 13, color: "var(--xk-text-secondary)" }}>Creando tenant…</span></div></div>
      </div>
    </StateShowcase>
  );
}
function SEmptyArtifact() {
  return (
    <StateShowcase title="S-Empty · empty state">
      <div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
        <SEmpty illustration="school" title="Aún no has creado escuelas" body="Empieza con la primera · el alta toma unos 5 minutos en 3 pasos." cta="Crear primera escuela" ctaIcon="plus" />
        <SEmpty illustration="filter" title="Ninguna fila pasó la validación" body="Revisa el mapeo del paso anterior · puede que falten columnas requeridas." cta="Volver a mapear" ctaIcon="arrow-left" />
      </div>
    </StateShowcase>
  );
}
function SErrorArtifact() {
  return (
    <StateShowcase title="S-Error · error con retry">
      <div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
        <SError title="No pudimos cargar las escuelas" body="Hubo un problema al conectar con el servidor. Revisa tu conexión e intenta de nuevo." technical="ERR_NETWORK · /api/v1/schools" />
        <Banner tone="danger" icon="alert-circle">Validación inline · cuando el error es de un campo, se muestra debajo del input — no en pantalla completa.</Banner>
      </div>
    </StateShowcase>
  );
}
Object.assign(window, { ModalArtifact, SLoadingArtifact, SEmptyArtifact, SErrorArtifact });

// ============================================================
// REGISTRY
// ============================================================
const REG = [
  { group: "Sysadmin · alta de escuela", role: "sysadmin", items: [
    { id: "A1", label: "Dashboard sysadmin", comp: "A1", states: ["happy", "loading", "empty", "error"] },
    { id: "A2", label: "Crear escuela · datos fiscales", comp: "A2", states: ["happy", "validation"] },
    { id: "A3", label: "Crear escuela · billing", comp: "A3", states: ["happy"] },
    { id: "A4", label: "Crear escuela · invitar director", comp: "A4", states: ["happy", "error"] },
    { id: "A5", label: "Tenant creado · celebration", comp: "A5", states: ["happy"] },
  ]},
  { group: "Director · onboarding", role: "director", items: [
    { id: "B0", label: "Welcome del director", comp: "B0", states: ["happy"] },
    { id: "B1", label: "Perfil de la escuela", comp: "B1", states: ["happy", "validation"] },
    { id: "B2", label: "Branding white-label", comp: "B2", states: ["happy", "error"] },
    { id: "B3", label: "Estructura académica", comp: "B3", states: ["happy", "empty", "error"] },
    { id: "B4", label: "Ciclo escolar", comp: "B4", states: ["happy", "empty", "validation"] },
    { id: "B5", label: "Pickup semáforo", comp: "B5", states: ["happy", "empty", "error"] },
    { id: "B6", label: "Revisión · qué incluye", comp: "B6", states: ["happy"] },
    { id: "B7", label: "Onboarding completo · celebration", comp: "B7", states: ["happy"] },
  ]},
  { group: "Director · centro de carga", role: "director", items: [
    { id: "I0", label: "Hub del centro de carga", comp: "I0", states: ["happy", "loading"] },
    { id: "IP1", label: "Personal · 1 plantilla", comp: "IP1", states: ["happy"] },
    { id: "IP2", label: "Personal · 2 subir", comp: "IP2", states: ["happy", "empty", "error"] },
    { id: "IP3", label: "Personal · 3 mapear", comp: "IP3", states: ["happy"] },
    { id: "IP4", label: "Personal · 4 revisar", comp: "IP4", states: ["happy"] },
    { id: "IP5", label: "Personal · 5 listo · celebration", comp: "IP5", states: ["happy"] },
    { id: "IF4", label: "Familias · 4 revisar (variante)", comp: "IF4", states: ["happy"] },
    { id: "IA4", label: "Alumnos · 4 revisar (matching)", comp: "IA4", states: ["happy"] },
    { id: "I4", label: "Conceptos de cobro", comp: "I4", states: ["happy"] },
    { id: "I5", label: "Activación masiva · 614 padres", comp: "I5", states: ["happy", "sent"] },
  ]},
  { group: "Director · módulos operativos", role: "director", items: [
    { id: "AD1", label: "Admisiones · pipeline", comp: "AD1", states: ["happy", "loading", "empty"] },
    { id: "AD2", label: "Admisiones · detalle prospecto", comp: "AD2", states: ["happy"] },
    { id: "AD3", label: "Inscripción digital", comp: "AD3", states: ["happy", "validation"] },
    { id: "RE1", label: "Reinscripciones", comp: "RE1", states: ["happy"] },
    { id: "MC1", label: "Menú del comedor", comp: "MC1", states: ["happy"] },
    { id: "PRIV", label: "Centro de privacidad · ARCO", comp: "PrivacyCenter", states: ["happy"] },
  ]},
  { group: "Sistema · modales", role: "director", items: [
    { id: "M1", label: "Confirmar · cancelar wizard", modal: c => <MConfirmCancel onClose={c} onConfirm={c} /> },
    { id: "M2", label: "Confirmar · destructivo", modal: c => <MConfirmDestructive description="Esta acción crea 26 cuentas activas y no se puede deshacer." actionLabel="Sí, importar" confirmWord="IMPORTAR" affected={614} onClose={c} onConfirm={c} /> },
    { id: "M3", label: "Import · progreso", modal: c => <MImportProgress /> },
    { id: "M4", label: "Preview · email branded", modal: c => <MPreviewEmail branded={true} onClose={c} /> },
  ]},
  { group: "Sistema · estados universales", role: "director", items: [
    { id: "S1", label: "S-Loading · skeleton", comp: "SLoadingArtifact", states: ["happy"] },
    { id: "S2", label: "S-Empty · empty state", comp: "SEmptyArtifact", states: ["happy"] },
    { id: "S3", label: "S-Error · error + retry", comp: "SErrorArtifact", states: ["happy"] },
  ]},
];
const FLAT = REG.flatMap(g => g.items);
const FLOW = ["A1","A2","A3","A4","A5","B0","B1","B2","B3","B4","B5","B6","B7","I0","IP1","IP2","IP3","IP4","IP5","IF4","IA4","I4","I5"];
const STATE_LABELS = { happy: "Happy", loading: "Loading", empty: "Empty", error: "Error", validation: "Validación", sent: "Enviado" };

// ============================================================
// APP
// ============================================================
function App() {
  const [activeId, setActiveId] = useState("A1");
  const [stateMode, setStateMode] = useState("happy");
  const [bindMode, setBindMode] = useState("values");
  const [modal, setModal] = useState(null);
  const [navOpen, setNavOpen] = useState(true);
  const [landing, setLanding] = useState(true);
  const [revealed, setRevealed] = useState(false);
  const [support, setSupport] = useState(null);
  const [role, setRole] = useState("sysadmin");
  const [appView, setAppView] = useState("cover");
  const [pendingSection, setPendingSection] = useState(null);
  const iframeRef = useRef(null);

  const ROLES = [
    { id: "sysadmin", label: "Sysadmin", sub: "Xokai · alta de escuela", icon: "shield", n: 1 },
    { id: "director", label: "Director · alta", sub: "Onboarding + carga", icon: "monitor", n: 2 },
    { id: "director-op", label: "Director · consola", sub: "Operación diaria", icon: "layout-dashboard", n: 3, src: "roles/director-op/index.html" },
    { id: "coordinador", label: "Coordinador", sub: "Coordinación académica", icon: "clipboard-list", n: 4, src: "roles/coordinador/index.html" },
    { id: "admisiones", label: "Admisiones", sub: "Inscripciones · pipeline", icon: "user-plus", n: 5, src: "roles/admisiones/index.html" },
    { id: "finanzas", label: "Finanzas", sub: "Colegiaturas · CFDI", icon: "wallet", n: 6, src: "roles/finanzas/index.html" },
    { id: "maestro", label: "Maestro", sub: "App móvil", icon: "smartphone", n: 7, src: "roles/maestro/index.html" },
    { id: "portero", label: "Portero", sub: "Kiosko pickup", icon: "scan-line", n: 8, src: "roles/portero/index.html" },
    { id: "padre", label: "Padre", sub: "App móvil", icon: "smartphone", n: 9, src: "roles/padre/index.html" },
  ];
  const activeRole = ROLES.find(r => r.id === role);
  const isConsole = role === "sysadmin" || role === "director";
  const guide = window.ROLE_GUIDE[role];
  const roleFirstId = { sysadmin: "A1", director: "B0" };
  const [frameReady, setFrameReady] = useState(false);
  function switchRole(id) {
    setRole(id);
    setAppView("cover");
    setPendingSection(null);
    setFrameReady(false);
    if (roleFirstId[id]) setActiveId(roleFirstId[id]);
  }
  // send deep-link section into the iframe
  function postSection(section) {
    if (!section) return;
    const fr = iframeRef.current;
    if (fr && fr.contentWindow) fr.contentWindow.postMessage({ type: "xk-nav", section }, "*");
  }
  // iframe announces ready → post whatever section is pending
  useEffect(() => {
    const onMsg = (e) => {
      if (e.data && e.data.type === "xk-ready") {
        setFrameReady(true);
        if (pendingSection) { postSection(pendingSection); setTimeout(() => postSection(pendingSection), 120); }
      }
    };
    window.addEventListener("message", onMsg);
    return () => window.removeEventListener("message", onMsg);
  }, [pendingSection]);
  // already-live and the section changes → post directly
  useEffect(() => {
    if (appView === "live" && frameReady && pendingSection) postSection(pendingSection);
  }, [pendingSection, frameReady, appView]);
  function enterApp(section) {
    // console roles: jump to an internal screen and go live
    if (isConsole) {
      if (section) setActiveId(section);
      else if (roleFirstId[role]) setActiveId(roleFirstId[role]);
      setAppView("live");
      return;
    }
    // null → go to the prototype's dashboard (deep-link consoles)
    const target = section || (guide && guide.deepLink ? guide.dashId : null);
    setPendingSection(target);
    setAppView("live");
  }
  useEffect(() => { if (appView !== "live") setFrameReady(false); }, [appView]);

  window.__XK_BINDMODE = bindMode;
  window.__XK_GO = setActiveId;
  window.__XK_FLOW = FLOW;
  window.__XK_CUR = activeId;
  window.enterSupport = (name) => { setSupport(name); setRole("director"); setActiveId("I0"); setAppView("live"); };

  // Reveal lock: after each screen mounts, force entrance animations to
  // their final visible state (robust to frozen animation timelines).
  useEffect(() => {
    setRevealed(false);
    setModal(null);
    const t = setTimeout(() => setRevealed(true), 1300);
    return () => clearTimeout(t);
  }, [activeId, stateMode, bindMode]);

  const active = FLAT.find(x => x.id === activeId);
  const openModal = (node) => setModal(node);
  openModal.close = () => setModal(null);

  // reset state when artifact changes if unsupported
  useEffect(() => {
    if (active && active.states && !active.states.includes(stateMode)) setStateMode(active.states[0]);
  }, [activeId]);

  useEffect(() => { window.lucide && window.lucide.createIcons(); });

  // keyboard nav
  useEffect(() => {
    const onKey = e => {
      if (modal) return;
      if (!isConsole || appView !== "live") return;
      if (e.target.tagName === "INPUT" || e.target.tagName === "SELECT" || e.target.tagName === "TEXTAREA") return;
      const roleItems = REG.filter(g => g.role === role).flatMap(g => g.items);
      const idx = roleItems.findIndex(x => x.id === activeId);
      if (e.key === "ArrowRight" && idx >= 0 && idx < roleItems.length - 1) setActiveId(roleItems[idx + 1].id);
      if (e.key === "ArrowLeft" && idx > 0) setActiveId(roleItems[idx - 1].id);
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [activeId, modal, role, isConsole, appView]);

  let content = null;
  if (active) {
    if (active.modal) content = <ModalArtifact render={active.modal} />;
    else {
      const Comp = window[active.comp];
      content = Comp ? <Comp state={stateMode} openModal={openModal} /> : <div style={{ padding: 40 }}>Sin componente</div>;
    }
  }

  return (
    <div style={{ display: "flex", height: "100vh", overflow: "hidden", background: "#1a1816" }}>
      {landing && <LandingHero roles={ROLES} onEnter={(rid) => { if (rid) switchRole(rid); setLanding(false); }} />}
      {/* Navigator rail */}
      <aside style={{ width: navOpen ? 256 : 0, flexShrink: 0, background: "var(--xk-surface)", borderRight: "1px solid var(--xk-border)", display: "flex", flexDirection: "column", transition: "width 200ms ease", overflow: "hidden" }}>
        <div style={{ padding: "14px 16px", borderBottom: "1px solid var(--xk-border)" }}>
          <div style={{ display: "flex", alignItems: "center", gap: 9, marginBottom: 12 }}>
            <button onClick={() => setLanding(true)} title="Volver al inicio" className="xk-btn-press" style={{ display: "flex", alignItems: "center", gap: 9, border: "none", background: "transparent", cursor: "pointer", padding: 0, flex: 1, textAlign: "left" }}>
              <XokaiIso size={24} />
              <div style={{ lineHeight: 1.2 }}>
                <div style={{ fontSize: 12.5, fontWeight: 700, letterSpacing: "-0.01em" }}>Xokai · Plataforma E2E</div>
                <div style={{ fontSize: 10.5, color: "var(--xk-text-muted)" }}>Demo de venta · MVP-V1</div>
              </div>
            </button>
            <button onClick={() => setLanding(true)} title="Volver al inicio" className="xk-btn-press" style={{ flexShrink: 0, width: 28, height: 28, borderRadius: 8, border: "1px solid var(--xk-border)", background: "var(--xk-surface)", cursor: "pointer", display: "inline-flex", alignItems: "center", justifyContent: "center", color: "var(--xk-text-secondary)" }}>
              <Icon name="house" size={15} />
            </button>
          </div>
          <div className="xk-overline" style={{ fontSize: 9, marginBottom: 6, color: "var(--xk-text-muted)" }}>Rol · flujo cronológico</div>
          <div style={{ display: "flex", flexDirection: "column", gap: 3 }}>
            {ROLES.map(r => {
              const on = r.id === role;
              return (
                <button key={r.id} onClick={() => switchRole(r.id)} style={{ display: "flex", alignItems: "center", gap: 9, padding: "7px 9px", borderRadius: 8, cursor: "pointer", textAlign: "left",
                  border: "1px solid " + (on ? "var(--xk-accent)" : "var(--xk-border)"),
                  background: on ? "var(--xk-accent-light)" : "transparent" }}>
                  <span style={{ width: 18, height: 18, borderRadius: 999, flexShrink: 0, display: "inline-flex", alignItems: "center", justifyContent: "center", fontSize: 10, fontWeight: 700, fontFamily: "var(--xk-font-mono)",
                    background: on ? "var(--xk-accent)" : "var(--xk-surface-3)", color: on ? "#fff" : "var(--xk-text-muted)" }}>{r.n}</span>
                  <Icon name={r.icon} size={15} color={on ? "var(--xk-accent)" : "var(--xk-text-muted)"} />
                  <div style={{ lineHeight: 1.25 }}>
                    <div style={{ fontSize: 12, fontWeight: on ? 600 : 500, color: on ? "var(--xk-accent)" : "var(--xk-text)" }}>{r.label}</div>
                    <div style={{ fontSize: 10, color: "var(--xk-text-muted)" }}>{r.sub}</div>
                  </div>
                </button>
              );
            })}
          </div>
        </div>
        <nav className="no-scrollbar" style={{ flex: 1, overflowY: "auto", padding: "8px 10px 20px", display: isConsole ? "block" : "none" }}>
          <button onClick={() => setAppView("cover")} style={{ width: "100%", textAlign: "left", display: "flex", alignItems: "center", gap: 9, padding: "7px 8px", border: "none", borderRadius: 7, marginBottom: 4, cursor: "pointer",
            background: appView === "cover" ? "var(--xk-accent-light)" : "transparent", color: appView === "cover" ? "var(--xk-accent)" : "var(--xk-text-secondary)" }}>
            <Icon name="book-open" size={15} color={appView === "cover" ? "var(--xk-accent)" : "var(--xk-text-muted)"} />
            <span style={{ fontSize: 12.5, fontWeight: appView === "cover" ? 600 : 500 }}>Portada · guía</span>
          </button>
          {REG.filter(g => g.role === role).map((g, gi) => (
            <div key={gi} style={{ marginTop: gi === 0 ? 4 : 14 }}>
              <div className="xk-overline" style={{ fontSize: 9.5, padding: "6px 8px", color: "var(--xk-text-muted)" }}>{g.group}</div>
              {g.items.map(it => {
                const on = appView === "live" && it.id === activeId;
                return (
                  <button key={it.id} onClick={() => { setActiveId(it.id); setAppView("live"); }} style={{ width: "100%", textAlign: "left", display: "flex", alignItems: "center", gap: 9, padding: "6px 8px", border: "none", borderRadius: 7, marginBottom: 1, cursor: "pointer",
                    background: on ? "var(--xk-accent-light)" : "transparent", color: on ? "var(--xk-accent)" : "var(--xk-text-secondary)" }}>
                    <span className="xk-mono" style={{ fontSize: 10, fontWeight: 600, width: 30, flexShrink: 0, color: on ? "var(--xk-accent)" : "var(--xk-text-muted)" }}>{it.id}</span>
                    <span style={{ fontSize: 12.5, fontWeight: on ? 600 : 400, lineHeight: 1.3 }}>{it.label}</span>
                  </button>
                );
              })}
            </div>
          ))}
        </nav>
        {!isConsole && guide && (
          <nav className="no-scrollbar" style={{ flex: 1, overflowY: "auto", padding: "8px 10px 20px" }}>
            <div style={{ marginTop: 4 }}>
              <div className="xk-overline" style={{ fontSize: 9.5, padding: "6px 8px", color: "var(--xk-text-muted)" }}>{guide.title}</div>
              <button onClick={() => setAppView("cover")} style={{ width: "100%", textAlign: "left", display: "flex", alignItems: "center", gap: 9, padding: "7px 8px", border: "none", borderRadius: 7, marginBottom: 2, cursor: "pointer",
                background: appView === "cover" ? "var(--xk-accent-light)" : "transparent", color: appView === "cover" ? "var(--xk-accent)" : "var(--xk-text-secondary)" }}>
                <Icon name="book-open" size={15} color={appView === "cover" ? "var(--xk-accent)" : "var(--xk-text-muted)"} />
                <span style={{ fontSize: 12.5, fontWeight: appView === "cover" ? 600 : 500 }}>Portada · guía</span>
              </button>
              <button onClick={() => enterApp(null)} style={{ width: "100%", textAlign: "left", display: "flex", alignItems: "center", gap: 9, padding: "7px 8px", border: "none", borderRadius: 7, marginBottom: 2, cursor: "pointer",
                background: appView === "live" && !pendingSection ? "var(--xk-accent-light)" : "transparent", color: appView === "live" && !pendingSection ? "var(--xk-accent)" : "var(--xk-text-secondary)" }}>
                <Icon name="play" size={15} color={appView === "live" && !pendingSection ? "var(--xk-accent)" : "var(--xk-text-muted)"} />
                <span style={{ fontSize: 12.5, fontWeight: 500 }}>Entrar al prototipo</span>
              </button>
            </div>
            {guide.deepLink && guide.sections.length > 0 && (
              <div style={{ marginTop: 14 }}>
                <div className="xk-overline" style={{ fontSize: 9.5, padding: "6px 8px", color: "var(--xk-text-muted)" }}>Pantallas</div>
                {guide.sections.map((s, i) => {
                  const on = appView === "live" && pendingSection === s.id;
                  return (
                    <button key={i} onClick={() => enterApp(s.id)} style={{ width: "100%", textAlign: "left", display: "flex", alignItems: "center", gap: 9, padding: "6px 8px", border: "none", borderRadius: 7, marginBottom: 1, cursor: "pointer",
                      background: on ? "var(--xk-accent-light)" : "transparent", color: on ? "var(--xk-accent)" : "var(--xk-text-secondary)" }}>
                      <Icon name={s.icon} size={14} color={on ? "var(--xk-accent)" : "var(--xk-text-muted)"} />
                      <span style={{ fontSize: 12.5, fontWeight: on ? 600 : 400, lineHeight: 1.3 }}>{s.label}</span>
                    </button>
                  );
                })}
              </div>
            )}
            {!guide.deepLink && (
              <div style={{ marginTop: 12, padding: "10px 10px", fontSize: 11, color: "var(--xk-text-muted)", lineHeight: 1.5 }}>
                Este prototipo trae su propia navegación interna · entra y explora desde su menú.
              </div>
            )}
          </nav>
        )}
        <div style={{ padding: "10px 14px", borderTop: "1px solid var(--xk-border)", fontSize: 10.5, color: "var(--xk-text-muted)" }}>
          {isConsole ? "← → para navegar" : (appView === "cover" ? "Portada · guía de venta" : "Prototipo en vivo")}
        </div>
      </aside>

      {/* Main */}
      <div style={{ flex: 1, display: "flex", flexDirection: "column", minWidth: 0 }}>
        {/* Top control bar */}
        <div style={{ height: 48, flexShrink: 0, display: "flex", alignItems: "center", gap: 12, padding: "0 16px", background: "#23201d", color: "#e7e5e0" }}>
          <button onClick={() => setNavOpen(!navOpen)} style={{ border: "none", background: "transparent", cursor: "pointer", color: "#bdb9b2", display: "inline-flex" }}><Icon name="panel-left" size={18} /></button>
          {isConsole ? (
            appView === "cover" ? (
              <span style={{ display: "inline-flex", alignItems: "center", gap: 8, fontSize: 13, fontWeight: 600 }}>
                <Icon name="book-open" size={15} color="#bdb9b2" />Xokai · {activeRole.label} · portada
              </span>
            ) : (
              <React.Fragment>
                <span className="xk-mono" style={{ fontSize: 11, color: "#8a867e" }}>{active && active.id}</span>
                <span style={{ fontSize: 13, fontWeight: 600 }}>{active && active.label}</span>
              </React.Fragment>
            )
          ) : (
            <span style={{ display: "inline-flex", alignItems: "center", gap: 8, fontSize: 13, fontWeight: 600 }}>
              <Icon key={appView === "cover" ? "book-open" : activeRole.icon} name={appView === "cover" ? "book-open" : activeRole.icon} size={15} color="#bdb9b2" />
              Xokai · {activeRole.label}{appView === "cover" ? " · portada" : (pendingSection ? " · " + pendingSection : "")}
            </span>
          )}

          <div style={{ flex: 1 }}></div>

          {/* state segmented — web console only */}
          {isConsole && appView === "live" && active && active.states && active.states.length > 1 && (
            <div style={{ display: "inline-flex", background: "#15130f", borderRadius: 8, padding: 3, gap: 2 }}>
              {active.states.map(s => (
                <button key={s} onClick={() => setStateMode(s)} style={{ border: "none", cursor: "pointer", padding: "4px 11px", borderRadius: 6, fontSize: 11.5, fontWeight: 500,
                  background: stateMode === s ? "var(--xk-accent)" : "transparent", color: stateMode === s ? "#fff" : "#bdb9b2" }}>{STATE_LABELS[s]}</button>
              ))}
            </div>
          )}

          {/* bind toggle — web console only */}
          {isConsole && (
            <button onClick={() => setBindMode(bindMode === "values" ? "tokens" : "values")} style={{ display: "inline-flex", alignItems: "center", gap: 7, padding: "5px 11px", borderRadius: 8, cursor: "pointer", fontSize: 11.5, fontWeight: 500,
              border: "1px solid " + (bindMode === "tokens" ? "var(--xk-accent)" : "#3a3631"),
              background: bindMode === "tokens" ? "var(--xk-accent)" : "transparent", color: "#fff", fontFamily: "var(--xk-font-mono)" }}>
              <Icon name="braces" size={14} />{bindMode === "tokens" ? "Variables" : "Valores"}
            </button>
          )}
        </div>

        {/* Canvas */}
        <div style={{ flex: 1, position: "relative", overflow: "hidden", background: "var(--xk-bg)", display: "flex", flexDirection: "column" }}>
          {!isConsole ? (
            <div className={revealed ? "xk-revealed" : ""} style={{ flex: 1, minHeight: 0, display: "flex", flexDirection: "column" }}>
              {appView === "cover"
                ? <RoleCover key={role} guide={guide} roleId={role} onEnter={() => enterApp(null)} onSection={(s) => enterApp(s)} />
                : <iframe ref={iframeRef} key={role} src={activeRole.src} title={activeRole.label}
                    onLoad={() => { if (pendingSection) { postSection(pendingSection); setTimeout(() => postSection(pendingSection), 400); } }}
                    style={{ flex: 1, width: "100%", height: "100%", border: "none", background: "#0E0D11" }}></iframe>}
            </div>
          ) : appView === "cover" ? (
            <div className={revealed ? "xk-revealed" : ""} style={{ flex: 1, minHeight: 0, display: "flex", flexDirection: "column" }}>
              <RoleCover key={role} guide={guide} roleId={role} onEnter={() => enterApp(null)} onSection={(s) => enterApp(s)} />
            </div>
          ) : (
          <React.Fragment>
          {support && /^(I|AD|RE|MC)/.test(activeId) && (
            <div style={{ flexShrink: 0, display: "flex", alignItems: "center", gap: 10, padding: "8px 18px", background: "var(--xk-warning-tint)", borderBottom: "1px solid color-mix(in oklab, var(--xk-warning) 30%, transparent)", color: "var(--xk-warning)", fontSize: 12.5, fontWeight: 600 }}>
              <Icon name="shield-alert" size={15} />
              Modo soporte · {support} · estás viendo el tenant como Xokai
              <span style={{ flex: 1 }}></span>
              <button onClick={() => { setSupport(null); setRole("sysadmin"); setActiveId("A1"); }} style={{ border: "none", background: "transparent", cursor: "pointer", color: "var(--xk-warning)", fontWeight: 600, fontSize: 12.5, display: "inline-flex", alignItems: "center", gap: 4 }}>Salir <Icon name="arrow-right" size={13} /></button>
            </div>
          )}
          <div style={{ flex: 1, position: "relative", overflow: "hidden" }}>
            <div key={activeId + stateMode + bindMode} className={revealed ? "xk-revealed" : ""} style={{ height: "100%" }}>
              {content}
            </div>
            {modal && <div className="xk-revealed" style={{ position: "absolute", inset: 0 }}>{modal}</div>}
          </div>
          </React.Fragment>
          )}
        </div>
      </div>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
