/* Compartido entre las 14 páginas de src/web/.
   Cada página conserva su propio <style> para lo específico (p. ej. el
   max-width de .contenedor difiere por página y se sobreescribe ahí). */

/* Tipografías alojadas en la propia plataforma (2026-10-02): antes se pedían a Google Fonts, lo que enviaba la IP de cada
   visitante a Google. Son las mismas fuentes (variables, WOFF2) que sirve Google Fonts, solo los subconjuntos latin y
   latin-ext (español, inglés, portugués, francés...). Licencia: SIL Open Font License 1.1 — copia en /fuentes/OFL-*.txt
   (Unbounded: The Unbounded Project Authors; Plus Jakarta Sans: The Plus Jakarta Sans Project Authors / Tokotype;
   JetBrains Mono: The JetBrains Mono Project Authors). */
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 400 600; font-display: swap; src: url("/fuentes/jetbrains-mono-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 400 600; font-display: swap; src: url("/fuentes/jetbrains-mono-latin-ext.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "Plus Jakarta Sans"; font-style: italic; font-weight: 500; font-display: swap; src: url("/fuentes/plus-jakarta-sans-italic-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Plus Jakarta Sans"; font-style: italic; font-weight: 500; font-display: swap; src: url("/fuentes/plus-jakarta-sans-italic-latin-ext.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "Plus Jakarta Sans"; font-style: normal; font-weight: 400 800; font-display: swap; src: url("/fuentes/plus-jakarta-sans-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Plus Jakarta Sans"; font-style: normal; font-weight: 400 800; font-display: swap; src: url("/fuentes/plus-jakarta-sans-latin-ext.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "Unbounded"; font-style: normal; font-weight: 600 800; font-display: swap; src: url("/fuentes/unbounded-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Unbounded"; font-style: normal; font-weight: 600 800; font-display: swap; src: url("/fuentes/unbounded-latin-ext.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }

/* ============================================================
   SISTEMA DE DISEÑO — identidad visual de SonIA Kontent, dark-first.
   Paso base: solo variables + fondo/tipografía globales. Los componentes
   de abajo (.boton-primario, .tarjeta-resumen, nav, tablas...) TODAVÍA
   consumen las variables antiguas (--azul, --texto, --fondo...) y se
   rediseñarán en un paso posterior — por ahora conviven ambos sistemas.
   Patrón de temas: :root sin atributo = oscuro (identidad por defecto);
   prefers-color-scheme:light lo cambia a claro salvo que data-theme="dark"
   lo fuerce; data-theme="light"/"dark" en <html> siempre gana en ambos
   sentidos sobre la preferencia del sistema.
   ============================================================ */
:root {
    --bg: #0A0A14;
    --bg-soft: #0D0E1C;
    --surface: #14151F;
    --surface-2: #1B1C2E;
    --surface-hover: #1F2133;
    --border: #262838;
    --border-strong: #383A52;
    --text: #F2F1F8;
    --text-muted: #9694AC;
    --text-faint: #5D5C74;
    --accent-blue: #4C7CFF;
    --accent-blue-strong: #6E93FF;
    --accent-violet: #C13CE0;
    --accent-grad: linear-gradient(135deg, #4C7CFF 0%, #9457EE 55%, #C13CE0 100%);
    --accent-grad-soft: linear-gradient(135deg, rgba(76,124,255,0.16) 0%, rgba(193,60,224,0.16) 100%);
    --on-accent: #05060F;
    --success: #34D399;
    --success-bg: rgba(52,211,153,0.13);
    --warning: #FBBF24;
    --warning-bg: rgba(251,191,36,0.13);
    --danger: #F87171;
    --danger-bg: rgba(248,113,113,0.15);
    --info: #4C7CFF;
    --info-bg: rgba(76,124,255,0.14);
    --shadow-sm: 0 1px 2px rgba(0,0,0,0.35);
    --shadow-md: 0 8px 24px -8px rgba(0,0,0,0.55), 0 2px 6px rgba(0,0,0,0.3);
    --shadow-lg: 0 24px 48px -16px rgba(0,0,0,0.6);
    --ring: 0 0 0 3px rgba(76,124,255,0.35);
    --font-display: 'Unbounded', 'Plus Jakarta Sans', system-ui, sans-serif;
    --font-body: 'Plus Jakarta Sans', system-ui, -apple-system, sans-serif;
    --font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;
    --radius-sm: 8px;
    --radius-md: 14px;
    --radius-lg: 20px;
    --radius-pill: 999px;
    color-scheme: dark;
}
@media (prefers-color-scheme: light) {
    :root:not([data-theme="dark"]) {
        --bg: #F4F4FB;
        --bg-soft: #ECECF6;
        --surface: #FFFFFF;
        --surface-2: #EFEFF7;
        --surface-hover: #E7E7F3;
        --border: #E1E1EC;
        --border-strong: #CACADC;
        --text: #15162A;
        --text-muted: #5F607A;
        --text-faint: #9393AC;
        --accent-blue: #3358E0;
        --accent-blue-strong: #2645BE;
        --accent-violet: #9B2FD1;
        --accent-grad: linear-gradient(135deg, #3358E0 0%, #7A3FDC 55%, #9B2FD1 100%);
        --accent-grad-soft: linear-gradient(135deg, rgba(51,88,224,0.10) 0%, rgba(155,47,209,0.10) 100%);
        --on-accent: #FFFFFF;
        --success: #0E9A63;
        --success-bg: rgba(14,154,99,0.10);
        --warning: #A5700A;
        --warning-bg: rgba(165,112,10,0.10);
        --danger: #C4372A;
        --danger-bg: rgba(196,55,42,0.10);
        --info: #3358E0;
        --info-bg: rgba(51,88,224,0.10);
        --shadow-sm: 0 1px 2px rgba(20,20,40,0.06);
        --shadow-md: 0 8px 24px -8px rgba(20,20,40,0.14), 0 2px 6px rgba(20,20,40,0.06);
        --shadow-lg: 0 24px 48px -16px rgba(20,20,40,0.18);
        color-scheme: light;
    }
}
:root[data-theme="light"] {
    --bg: #F4F4FB; --bg-soft: #ECECF6; --surface: #FFFFFF; --surface-2: #EFEFF7; --surface-hover: #E7E7F3;
    --border: #E1E1EC; --border-strong: #CACADC; --text: #15162A; --text-muted: #5F607A; --text-faint: #9393AC;
    --accent-blue: #3358E0; --accent-blue-strong: #2645BE; --accent-violet: #9B2FD1;
    --accent-grad: linear-gradient(135deg, #3358E0 0%, #7A3FDC 55%, #9B2FD1 100%);
    --accent-grad-soft: linear-gradient(135deg, rgba(51,88,224,0.10) 0%, rgba(155,47,209,0.10) 100%);
    --on-accent: #FFFFFF;
    --success: #0E9A63; --success-bg: rgba(14,154,99,0.10);
    --warning: #A5700A; --warning-bg: rgba(165,112,10,0.10);
    --danger: #C4372A; --danger-bg: rgba(196,55,42,0.10);
    --info: #3358E0; --info-bg: rgba(51,88,224,0.10);
    --shadow-sm: 0 1px 2px rgba(20,20,40,0.06); --shadow-md: 0 8px 24px -8px rgba(20,20,40,0.14), 0 2px 6px rgba(20,20,40,0.06); --shadow-lg: 0 24px 48px -16px rgba(20,20,40,0.18);
    color-scheme: light;
}
:root[data-theme="dark"] {
    --bg: #0A0A14; --bg-soft: #0D0E1C; --surface: #14151F; --surface-2: #1B1C2E; --surface-hover: #1F2133;
    --border: #262838; --border-strong: #383A52; --text: #F2F1F8; --text-muted: #9694AC; --text-faint: #5D5C74;
    --accent-blue: #4C7CFF; --accent-blue-strong: #6E93FF; --accent-violet: #C13CE0;
    --accent-grad: linear-gradient(135deg, #4C7CFF 0%, #9457EE 55%, #C13CE0 100%);
    --accent-grad-soft: linear-gradient(135deg, rgba(76,124,255,0.16) 0%, rgba(193,60,224,0.16) 100%);
    --on-accent: #05060F;
    --success: #34D399; --success-bg: rgba(52,211,153,0.13);
    --warning: #FBBF24; --warning-bg: rgba(251,191,36,0.13);
    --danger: #F87171; --danger-bg: rgba(248,113,113,0.15);
    --info: #4C7CFF; --info-bg: rgba(76,124,255,0.14);
    --shadow-sm: 0 1px 2px rgba(0,0,0,0.35); --shadow-md: 0 8px 24px -8px rgba(0,0,0,0.55), 0 2px 6px rgba(0,0,0,0.3); --shadow-lg: 0 24px 48px -16px rgba(0,0,0,0.6);
    color-scheme: dark;
}

/* Colores con contraste verificado (2026-10-04). Botón primario: blanco sobre #2F55D4 = 6.2:1 (antes 3.7:1 con #4C7CFF).
   Mensajes de confirmación: verde claro sobre fondo oscuro (11:1; el #166534 de antes daba 2.8:1) y verde oscuro sobre
   fondo claro (5:1 sobre la nebulosa lila). Las páginas lo usan con var(--texto-exito). */
:root { --boton-primario: #2F55D4; --boton-primario-hover: #2645BE; --texto-exito: #4ADE80; }
:root[data-theme="light"] { --texto-exito: #166534; }
@media (prefers-color-scheme: light) { :root:not([data-theme="dark"]) { --texto-exito: #166534; } }

/* Variables antiguas — siguen vivas porque los componentes de abajo (y los
   <style> propios de cada página) todavía las consumen tal cual. Se
   retiran cuando esos componentes se rediseñen con el sistema nuevo. */
:root {
    --azul: #1f6feb;
    --azul-oscuro: #1552b0;
    --texto: #1f2937;
    --texto-suave: #6b7280;
    --fondo: #f4f6fb;
    --borde: #e5e7eb;
    --rojo: #b42318;
    --verde: #166534;
    --naranja: #b45309;
}
* { box-sizing: border-box; }
body { font-family: var(--font-body); background: var(--bg); color: var(--text); margin: 0; }

header.encabezado h1 { margin: 0 0 .5rem; font-size: 1.75rem; }
header.encabezado .subtexto { margin: .5rem 0 0; color: var(--texto-suave); font-size: .9rem; }

nav.nav-autenticada { display: flex; gap: 1.25rem; flex-wrap: wrap; align-items: center; margin: .75rem 0; }
nav.nav-autenticada a, nav.nav-autenticada button { font: inherit; font-size: .9rem; color: var(--azul); background: none; border: 0; padding: 0; cursor: pointer; text-decoration: none; }
nav.nav-autenticada a:hover, nav.nav-autenticada button:hover { text-decoration: underline; }
#nav-mensaje { min-height: 1.25rem; color: var(--rojo); font-size: .85rem; }

/* Marca — ícono + wordmark "SonIA Kontent", inyectados por renderNavAutenticada
   (src/index.ts) delante del <nav class="nav-autenticada">. Compartido por
   todas las páginas autenticadas vía {{NAV}}, no se duplica por página. */
.fila-marca { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-bottom: .5rem; }
.marca { display: flex; align-items: center; gap: 0.75rem; flex-shrink: 0; }
.marca .marco-logo {
    width: 52px; height: 52px; border-radius: 12px; padding: 2px; flex-shrink: 0;
    background: var(--accent-grad); display: flex; align-items: center; justify-content: center;
}
.marca .marco-logo img { width: 100%; height: 100%; border-radius: 12px; display: block; }

.marca-texto { display: flex; flex-direction: column; align-items: center; gap: 0.1rem; line-height: 1; }
.marca-wordmark {
    font-family: var(--font-display); font-weight: 800; letter-spacing: -0.005em;
    display: inline-flex; align-items: baseline; font-size: 1.5rem;
}
.marca-wordmark .letra-inicial, .marca-wordmark .segmento-acento {
    font-size: 1.65em;
    background: var(--accent-grad); background-size: 260% 100%;
    -webkit-background-clip: text; background-clip: text; color: transparent;
    animation: marca-recorre 6s linear infinite;
}
.marca-wordmark .segmento-muted { font-size: 0.98em; color: #B4B3C6; }
:root[data-theme="light"] .marca-wordmark .segmento-muted,
:root:not([data-theme="dark"]) .marca-wordmark .segmento-muted { color: #8887A0; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .marca-wordmark .segmento-muted { color: #B4B3C6; } }
.marca-espaciador { width: 0.28em; display: inline-block; }
@keyframes marca-recorre { to { background-position: -260% 0; } }
@media (prefers-reduced-motion: reduce) { .marca-wordmark .letra-inicial, .marca-wordmark .segmento-acento { animation: none; } }

.marca-eslogan {
    font-size: 0.62rem; letter-spacing: 0.13em; text-transform: uppercase; font-weight: 600;
    color: #B4B3C6; display: flex; align-items: center; gap: 0.4rem;
}
:root[data-theme="light"] .marca-eslogan,
:root:not([data-theme="dark"]) .marca-eslogan { color: #8887A0; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .marca-eslogan { color: #B4B3C6; } }
.marca-eslogan::before, .marca-eslogan::after { content: ""; height: 1px; width: 16px; background: linear-gradient(90deg, transparent, var(--accent-blue)); }
.marca-eslogan::after { background: linear-gradient(90deg, var(--accent-violet), transparent); }
@media (max-width: 640px) { .marca-eslogan { display: none; } }
/* Celulares: logo + wordmark (~360px) + botones (~82px) no caben en una fila y empujaban la página a ~476px de
   ancho (los botones de tema y cuenta quedaban fuera de pantalla). Aquí los botones pasan a su propia fila,
   arriba y a la derecha, y la marca se reduce con el ancho de la pantalla para caber completa. */
@media (max-width: 520px) {
    .fila-marca { flex-wrap: wrap; row-gap: .4rem; }
    .topbar-acciones { order: -1; margin-left: auto; }
    .marca { flex-shrink: 1; min-width: 0; max-width: 100%; gap: .5rem; }
    .marca .marco-logo { width: 44px; height: 44px; }
    .marca-wordmark { font-size: clamp(.9rem, 5.2vw, 1.5rem); }
}

/* Grupo de acciones a la derecha de la topbar: instalar app, tema, cuenta. */
.topbar-acciones { display: flex; align-items: center; gap: .6rem; flex-shrink: 0; }

/* Botón "Instalar app" — a diferencia de los circulares de al lado, lleva
   texto, así que es un chip con el mismo lenguaje de color (info) que
   .badge-info, no una superficie neutra como .boton-icono-topbar. */
.boton-instalar-app {
    font: inherit; font-size: .8rem; font-weight: 600; flex-shrink: 0;
    color: var(--info); background: var(--info-bg); border: 1px solid transparent;
    border-radius: 999px; padding: .35rem .85rem; cursor: pointer;
}
.boton-instalar-app:hover { border-color: var(--accent-blue); }

/* Base compartida de los botones circulares de ícono en la topbar
   (sol/luna y cuenta). */
.boton-icono-topbar {
    display: inline-flex; align-items: center; justify-content: center;
    width: 36px; height: 36px; border-radius: 999px; flex-shrink: 0;
    border: 1px solid var(--border); background: var(--surface); color: var(--text-muted); cursor: pointer;
}
.boton-icono-topbar:hover { background: var(--surface-hover); color: var(--text); }

/* Switch de tema sol/luna. Un solo botón: muestra el sol cuando el tema
   activo es oscuro (clic para pasar a claro) y la luna cuando el tema
   activo es claro (clic para pasar a oscuro). */
.boton-tema .icono-luna { display: none; }
:root[data-theme="light"] .boton-tema .icono-sol { display: none; }
:root[data-theme="light"] .boton-tema .icono-luna { display: block; }

/* Menú de cuenta — desplegable anclado bajo el ícono de perfil, con
   Recuperación de cuenta / Cambiar contraseña / Cerrar sesión. Antes
   vivían como enlaces sueltos mezclados con las áreas de trabajo
   (Panel/Admin/Simulación/Operación) en nav.nav-autenticada. */
.menu-cuenta { position: relative; }
.lista-menu-cuenta {
    position: absolute; top: calc(100% + .5rem); right: 0; z-index: 30;
    min-width: 220px; flex-direction: column; gap: .1rem; padding: .4rem;
    background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-md); box-shadow: var(--shadow-md);
}
.lista-menu-cuenta:not([hidden]) { display: flex; }
.lista-menu-cuenta a, .lista-menu-cuenta button {
    display: block; width: 100%; text-align: left; font: inherit; font-size: .88rem;
    padding: .55rem .7rem; border-radius: var(--radius-sm); border: 0; background: none; cursor: pointer;
    color: var(--text); text-decoration: none;
}
.lista-menu-cuenta a:hover, .lista-menu-cuenta button:hover { background: var(--surface-hover); }
.menu-cuenta-correo { margin: 0; padding: .45rem .7rem .55rem; border-bottom: 1px solid var(--border); font-size: .78rem; line-height: 1.35; color: var(--text-muted); overflow-wrap: anywhere; }
.menu-cuenta-correo strong { display: block; font-size: .85rem; color: var(--text); font-weight: 600; }

/* Cuadro de confirmación propio (reemplaza al cuadro nativo del navegador en acciones delicadas). "Cancelar" es el botón
   que queda seleccionado al abrirse: un Enter accidental NO confirma. */
dialog.dialogo-confirmar { max-width: 460px; width: calc(100% - 32px); padding: 1.3rem 1.4rem; border: 1px solid var(--border-strong, var(--border)); border-radius: 14px; background: var(--surface); color: var(--text); box-shadow: var(--shadow-lg, 0 24px 48px -16px rgba(0,0,0,.6)); }
dialog.dialogo-confirmar::backdrop { background: rgba(5, 6, 15, .75); }
dialog.dialogo-confirmar h2 { margin: 0 0 .6rem; font-size: 1.1rem; }
dialog.dialogo-confirmar p { margin: 0 0 1.1rem; line-height: 1.5; overflow-wrap: anywhere; }
dialog.dialogo-confirmar .acciones-dialogo { display: flex; flex-wrap: wrap; gap: .6rem; justify-content: flex-end; }
dialog.dialogo-confirmar .acciones-dialogo button { min-height: 44px; padding: 0 1.1rem; font: inherit; font-weight: 600; border-radius: 8px; cursor: pointer; }
dialog.dialogo-confirmar .acciones-dialogo .boton-cancelar { background: var(--surface-2); color: var(--text); border: 1px solid var(--border-strong, var(--border)); }
dialog.dialogo-confirmar .acciones-dialogo .boton-confirmar { background: var(--boton-primario); color: #fff; border: 1px solid transparent; }
dialog.dialogo-confirmar .acciones-dialogo button:focus-visible { outline: 3px solid var(--accent-blue-strong); outline-offset: 2px; }

/* Ayuda corta bajo un campo (requisitos de la contraseña). */
.ayuda-campo { display: block; margin: .3rem 0 0; font-size: .82rem; line-height: 1.35; color: var(--text-muted, #6b7280); font-weight: 400; }

/* Campo de texto cuyo contenido se muestra como puntos (la respuesta de seguridad), con ojito para verlo. Es un campo de
   texto normal (no de contraseña) para que el navegador no le ofrezca contraseñas guardadas ni el correo. */
.texto-oculto { -webkit-text-security: disc; text-security: disc; }

/* Aviso de recuperación de cuenta (panel principal y administración). */
.aviso-recuperacion { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; margin: 0 0 .9rem; padding: .45rem .75rem; border: 1px solid var(--border); border-radius: 10px; background: var(--surface-2); color: var(--text-muted); font-size: .85rem; line-height: 1.4; }
.aviso-recuperacion-icono { flex: 0 0 auto; width: 16px; height: 16px; color: var(--accent-blue); }
.aviso-recuperacion-texto { flex: 1 1 14rem; margin: 0; }
.aviso-recuperacion-boton { display: inline-flex; align-items: center; min-height: 44px; padding: 0 .85rem; border: 1px solid var(--border-strong); border-radius: 8px; background: var(--surface); color: var(--text); font-weight: 600; font-size: .85rem; text-decoration: none; }
.aviso-recuperacion-boton:hover { background: var(--surface-hover); }
.aviso-recuperacion-boton:focus-visible { outline: 2px solid var(--accent-blue); outline-offset: 2px; }

table.tabla-datos { width: 100%; border-collapse: collapse; font-size: .85rem; }
table.tabla-datos th, table.tabla-datos td { text-align: left; padding: .45rem .6rem; border-bottom: 1px solid var(--borde); }
table.tabla-datos th { color: var(--texto-suave); font-weight: 600; font-size: .78rem; text-transform: uppercase; letter-spacing: .02em; }

table.tabla-usuarios { width: 100%; border-collapse: collapse; font-size: .9rem; }
table.tabla-usuarios th, table.tabla-usuarios td { text-align: left; padding: .6rem .5rem; border-bottom: 1px solid var(--borde); }
table.tabla-usuarios th { color: var(--texto-suave); font-weight: 600; font-size: .8rem; text-transform: uppercase; }

/* Envoltorio para que las tablas anchas se desplacen horizontalmente en vez
   de romper el layout o forzar zoom en pantallas angostas. El forzado de
   min-width va SOLO dentro de la media query de abajo (no aquí, sin
   condición): en escritorio la tabla debe seguir comprimiéndose a
   width:100% exactamente como antes, sin scrollbar nuevo. */
.tabla-scroll { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }

.boton-primario, .boton-secundario { font: inherit; font-size: .85rem; padding: .5rem .9rem; border-radius: 8px; cursor: pointer; border: 1px solid transparent; }
.boton-primario { background: var(--boton-primario); color: #fff; }
.boton-primario:hover { background: var(--boton-primario-hover); }
.boton-secundario { background: var(--surface); border-color: var(--border); color: var(--text); }
.boton-secundario:hover { background: var(--surface-hover); }
.boton-peligro { color: var(--danger); border-color: var(--danger); background: var(--surface); }
.boton-peligro:hover { background: var(--danger-bg); }

.tarjetas-resumen { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: .75rem; margin-bottom: 1rem; }
.tarjeta-resumen { border: 1px solid var(--border); border-radius: 10px; padding: .85rem 1rem; }
.tarjeta-resumen .valor { font-size: 1.4rem; font-weight: 700; }
.tarjeta-resumen .etiqueta { font-size: .78rem; color: var(--text-muted); }
.tarjeta-resumen.destacada { border-color: var(--accent-blue); border-width: 2px; background: var(--info-bg); }
.tarjeta-resumen.destacada .valor { color: var(--accent-blue-strong); }

/* Tarjeta contenedora — patrón "A" que hoy repiten con valores fijos las
   10 páginas de formulario simple (login, registro, recuperar...) en su
   propio <style> como "main { background:#fff; box-shadow:...; }". Solo
   define identidad visual (fondo/borde/radio/sombra); cada página sigue
   controlando su propio padding/max-width, igual que con .contenedor.
   Todavía ninguna página usa esta clase — migración es el siguiente paso. */
.tarjeta-formulario {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
}

/* Tarjeta de contenido — patrón "B" que hoy repiten con valores fijos
   section.usuarios (admin), section.panel (adminSimulacion, operacion) y
   section.conexiones/nichos/generaciones (app), cada una con su propio
   nombre de selector para el mismo diseño. El padding es igual en las 6
   instancias (1.5rem) así que va incluido aquí; el margin varía según la
   posición de cada sección en su página y se queda a cargo de esa página.
   Todavía ninguna página usa esta clase — migración es el siguiente paso. */
.tarjeta-contenido {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: 1.5rem;
}

.fila-filtros { display: flex; gap: .6rem; flex-wrap: wrap; align-items: end; margin-bottom: 1rem; }
.fila-filtros label { display: flex; flex-direction: column; gap: .25rem; font-size: .8rem; color: var(--texto-suave); }
.fila-filtros select, .fila-filtros input { font: inherit; font-size: .85rem; padding: .45rem .6rem; border: 1px solid var(--borde); border-radius: 8px; }

.fila-busqueda { display: flex; gap: .5rem; }
.fila-busqueda input[type="text"] { flex: 1; font: inherit; font-size: .9rem; padding: .5rem .6rem; border: 1px solid var(--borde); border-radius: 8px; }

/* A partir de aquí, todo selector va prefijado con "body " a propósito: cada
   página conserva su propia versión SIN media query de varias de estas
   clases (.contenedor, .pestana, .resumen, button.boton-primario...),
   declarada más abajo en su propio <style> (que en el HTML carga después de
   este archivo). Con la misma especificidad, esa regla posterior sin media
   query gana siempre — pase lo que pase con el viewport — así que estas
   reglas responsive necesitan una especificidad mayor (0,1,1 en vez de
   0,1,0) para de verdad ganar en pantallas angostas. */

/* --- Tableta / pantallas medianas --- */
@media (max-width: 700px) {
    body .contenedor { padding-left: 1.1rem; padding-right: 1.1rem; }
    body header.encabezado h1 { font-size: 1.5rem; }
    body .tarjetas-resumen, body .resumen { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
    /* Recién aquí (pantallas angostas) la tabla conserva su ancho natural y
       se desplaza dentro de .tabla-scroll, en vez de comprimirse ilegible. */
    body .tabla-scroll > table { min-width: max-content; }
}

/* --- Celular (375-400px) --- */
@media (max-width: 480px) {
    body .contenedor { padding-left: .9rem; padding-right: .9rem; padding-bottom: 3rem; }
    body header.encabezado h1 { font-size: 1.3rem; }
    body nav.nav-autenticada { gap: .85rem 1rem; }

    /* Objetivo de tamaño táctil (~44px) en los controles principales, sin
       tocar botones/íconos pequeños de uso puntual (boton-ayuda, cerrar
       chip, mostrar contraseña, etc.) que no están en esta lista. */
    body .boton-primario, body .boton-secundario, body .boton-peligro,
    body button.boton-primario, body button.boton-secundario,
    body .pestana, body .tab-app {
        min-height: 44px;
        padding-top: .7rem;
        padding-bottom: .7rem;
    }
    body .fila-filtros select, body .fila-filtros input,
    body .fila-busqueda input[type="text"],
    body table.tabla-datos input, body table.tabla-datos select,
    body table.tabla-usuarios select {
        min-height: 44px;
    }

    /* Filas de filtros/búsqueda: de lado a lado en escritorio, apiladas en
       celular para que cada campo tenga ancho completo y sea fácil de tocar. */
    body .fila-filtros { flex-direction: column; align-items: stretch; }
    body .fila-filtros label { width: 100%; }
    body .fila-filtros select, body .fila-filtros input,
    body .fila-filtros .boton-primario, body .fila-filtros .boton-secundario { width: 100%; }
    body .fila-busqueda { flex-direction: column; }
    body .fila-busqueda .boton-primario, body .fila-busqueda .boton-secundario { width: 100%; }

    body .tarjetas-resumen, body .resumen { grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: .6rem; }

    /* Encabezados de sección con botón a la derecha: apilar para que el
       botón quede con ancho completo (más fácil de tocar) en vez de
       comprimirse junto al título. */
    body section.conexiones > header, body section.nichos > header, body section.generaciones > header,
    body .encabezado-muro {
        flex-direction: column;
        align-items: stretch;
    }
    body section.conexiones > header .boton-primario, body section.nichos > header .boton-primario,
    body section.generaciones > header .boton-primario, body .encabezado-muro .boton-primario {
        width: 100%;
        text-align: center;
    }

    body table.tabla-datos, body table.tabla-usuarios { font-size: .8rem; }
}

/* ============================================================
   PALETA DEFINITIVA DE MODO CLARO — solo app.html por ahora.
   Todo va prefijado con "body.pagina-app" (agregada solo en app.html)
   porque .tarjeta-resumen, .tarjeta-contenido y .fila-nicho también
   viven en admin/adminSimulacion/operacion — sin este prefijo, estas
   reglas se colarían ahí antes de tiempo. El modo oscuro no se toca.
   ============================================================ */
@media (prefers-color-scheme: light) {
    :root:not([data-theme="dark"]) body.pagina-app { --bg: linear-gradient(160deg, #E0D4FA 0%, #DCE4FB 45%, #F2E4F7 100%); }
}
:root[data-theme="light"] body.pagina-app { --bg: linear-gradient(160deg, #E0D4FA 0%, #DCE4FB 45%, #F2E4F7 100%); }

@media (prefers-color-scheme: light) {
    :root:not([data-theme="dark"]) body.pagina-app .tarjeta-resumen:not(.destacada) {
        background: var(--reflejo-claro);
        -webkit-backdrop-filter: blur(12px) saturate(1.3); backdrop-filter: blur(12px) saturate(1.3);
        border: 1px solid rgba(122,95,224,0.4);
        border-top: 3px solid #7A5FE0;
        border-radius: 14px;
    }
    :root:not([data-theme="dark"]) body.pagina-app .tarjeta-resumen:not(.destacada) .numero { color: #2A1B5C; }
    :root:not([data-theme="dark"]) body.pagina-app .tarjeta-resumen:not(.destacada) .etiqueta { color: #524480; }
    :root:not([data-theme="dark"]) body.pagina-app .tarjeta-resumen.destacada {
        background: var(--reflejo-claro), rgba(51,88,224,0.07); -webkit-backdrop-filter: blur(12px) saturate(1.3); backdrop-filter: blur(12px) saturate(1.3);
        box-shadow: 0 6px 18px -4px rgba(193,60,224,0.45);
        border-radius: 14px;
    }
    :root:not([data-theme="dark"]) body.pagina-app .fila-nicho,
    :root:not([data-theme="dark"]) body.pagina-app .tarjeta-contenido {
        background: var(--reflejo-claro);
        -webkit-backdrop-filter: blur(12px) saturate(1.3); backdrop-filter: blur(12px) saturate(1.3);
        border: 1.5px solid rgba(122,95,224,0.45);
        box-shadow: 0 8px 22px -8px rgba(148,87,238,0.35), inset 0 0 0 1px rgba(255,255,255,0.65);
        border-radius: 18px;
    }
    :root:not([data-theme="dark"]) body.pagina-app .fila-nicho .descripcion-nicho { color: #5B5378; }
    :root:not([data-theme="dark"]) body.pagina-app .fila-nicho .nombre-nicho { color: #2A1B5C; }
    :root:not([data-theme="dark"]) body.pagina-app .acciones-tema [data-accion="editar"] {
        border: 1px solid rgba(148,87,238,0.7); background: rgba(148,87,238,0.08); color: #5B21A6; font-weight: 700; border-radius: 9px;
    }
    :root:not([data-theme="dark"]) body.pagina-app .acciones-tema [data-accion="alternar"] {
        border-color: rgba(122,95,224,0.35); background: transparent; color: #3F3A58; border-radius: 9px;
    }
    :root:not([data-theme="dark"]) body.pagina-app .acciones-tema [data-accion="eliminar"] {
        border-color: rgba(196,55,42,0.5); background: rgba(196,55,42,0.06); color: #A8281D; border-radius: 9px;
    }
}
:root[data-theme="light"] body.pagina-app .tarjeta-resumen:not(.destacada) {
    background: var(--reflejo-claro);
    -webkit-backdrop-filter: blur(12px) saturate(1.3); backdrop-filter: blur(12px) saturate(1.3);
    border: 1px solid rgba(122,95,224,0.4);
    border-top: 3px solid #7A5FE0;
    border-radius: 14px;
}
:root[data-theme="light"] body.pagina-app .tarjeta-resumen:not(.destacada) .numero { color: #2A1B5C; }
:root[data-theme="light"] body.pagina-app .tarjeta-resumen:not(.destacada) .etiqueta { color: #524480; }
:root[data-theme="light"] body.pagina-app .tarjeta-resumen.destacada {
    background: var(--reflejo-claro), rgba(51,88,224,0.07); -webkit-backdrop-filter: blur(12px) saturate(1.3); backdrop-filter: blur(12px) saturate(1.3);
    box-shadow: 0 6px 18px -4px rgba(193,60,224,0.45);
    border-radius: 14px;
}
:root[data-theme="light"] body.pagina-app .fila-nicho,
:root[data-theme="light"] body.pagina-app .tarjeta-contenido {
    background: var(--reflejo-claro);
    -webkit-backdrop-filter: blur(12px) saturate(1.3); backdrop-filter: blur(12px) saturate(1.3);
    border: 1.5px solid rgba(122,95,224,0.45);
    box-shadow: 0 8px 22px -8px rgba(148,87,238,0.35), inset 0 0 0 1px rgba(255,255,255,0.65);
    border-radius: 18px;
}
:root[data-theme="light"] body.pagina-app .fila-nicho .descripcion-nicho { color: #5B5378; }
:root[data-theme="light"] body.pagina-app .fila-nicho .nombre-nicho { color: #2A1B5C; }
:root[data-theme="light"] body.pagina-app .acciones-tema [data-accion="editar"] {
    border: 1px solid rgba(148,87,238,0.7); background: rgba(148,87,238,0.08); color: #5B21A6; font-weight: 700; border-radius: 9px;
}
:root[data-theme="light"] body.pagina-app .acciones-tema [data-accion="alternar"] {
    border-color: rgba(122,95,224,0.35); background: transparent; color: #3F3A58; border-radius: 9px;
}
:root[data-theme="light"] body.pagina-app .acciones-tema [data-accion="eliminar"] {
    border-color: rgba(196,55,42,0.5); background: rgba(196,55,42,0.06); color: #A8281D; border-radius: 9px;
}

/* ============================================================
   FONDO ESPACIAL — canvas de estrellas de las páginas autenticadas
   (public/fondo-espacial.js). z-index:-1 lo deja detrás del contenido,
   que no está posicionado; con 0 se pintaría encima de tarjetas y texto.
   Solo modo oscuro: en claro se oculta.
   ============================================================ */
.fondo-espacial {
    position: fixed; inset: 0; z-index: -1; pointer-events: none; width: 100%; height: 100%; display: block;
}
@media (prefers-color-scheme: light) { :root:not([data-theme="dark"]) .fondo-espacial { display: none; } }
:root[data-theme="light"] .fondo-espacial { display: none; }

/* Vidrio del modo claro: casi sin relleno; solo "visos" de reflejo (una franja diagonal de brillo en la esquina
   superior izquierda, una segunda más tenue y un destello en la esquina opuesta) para dar sensación de cristal flotando. */
body.pagina-app {
    --reflejo-claro: linear-gradient(115deg, rgba(255,255,255,0.22) 0%, rgba(255,255,255,0.05) 16%, rgba(255,255,255,0) 34%, rgba(255,255,255,0.07) 35.5%, rgba(255,255,255,0) 38%, rgba(255,255,255,0) 74%, rgba(255,255,255,0.10) 100%);
    --campo-claro: rgba(255,255,255,0.16);
}

/* ============================================================
   PÁGINAS AUTENTICADAS (body.pagina-app) — ajustes comunes a las 7 páginas
   Cada página con sesión lleva <body class="pagina-app">: degradado lila en claro,
   paneles lila (.tarjeta-contenido), fondo de nebulosa y los retoques de contraste de abajo.
   ============================================================ */
/* Si el contenido es más bajo que la ventana, el degradado (que mide lo que el documento)
   se repetía y dejaba una franja visible: el cuerpo llena al menos la ventana. */
body.pagina-app { min-height: 100vh; }

/* MODO CLARO — texto que queda directamente sobre el fondo (con la nebulosa detrás, los grises
   y azules de antes bajaban de 3:1). Contrastes calculados con las manchas al 65%:
   gris #34354E 5.0:1, azul #1E3AA0 4.9:1, rojo #8F1D12 4.5:1 (con una mancha detrás). */
:root[data-theme="light"] body.pagina-app { --text-muted: #34354E; --texto-suave: #34354E; }
:root[data-theme="light"] body.pagina-app nav.nav-autenticada a,
:root[data-theme="light"] body.pagina-app .volver a,
:root[data-theme="light"] body.pagina-app footer.pie-app a { color: #1E3AA0; }
:root[data-theme="light"] body.pagina-app #nav-mensaje { color: #8F1D12; }

/* Páginas simples (contrasena, eliminar-cuenta, recuperacion-config): su <main> era una tarjeta
   blanca fija. Claro: vidrio con borde lila, como los demás paneles. */
:root[data-theme="light"] body.pagina-app main {
    background: var(--reflejo-claro); -webkit-backdrop-filter: blur(12px) saturate(1.3); backdrop-filter: blur(12px) saturate(1.3);
    border: 1.5px solid rgba(122,95,224,0.45); border-radius: 18px;
    box-shadow: 0 8px 22px -8px rgba(148,87,238,0.35), inset 0 0 0 1px rgba(255,255,255,0.65);
}
/* Oscuro: antes el <main> seguía blanco con texto claro (ilegible). Ahora vidrio, como el resto. */
:root:not([data-theme="light"]) body.pagina-app main {
    background: linear-gradient(180deg, rgba(76,124,255,0.08) 0%, rgba(20,22,35,0.55) 100%);
    -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
    border: 1px solid rgba(150,205,255,0.35); border-radius: 14px;
    box-shadow: 0 0 0 1px rgba(20,22,35,0.45), 0 0 18px -2px rgba(120,195,255,0.25);
    color: var(--text);
}
:root:not([data-theme="light"]) body.pagina-app main input,
:root:not([data-theme="light"]) body.pagina-app main select {
    background: rgba(10,12,28,0.55); color: var(--text); border: 1px solid rgba(150,205,255,0.35); border-radius: 8px;
    transition: border-color .2s, box-shadow .2s;
}
:root:not([data-theme="light"]) body.pagina-app main input:focus,
:root:not([data-theme="light"]) body.pagina-app main select:focus {
    outline: none; border-color: rgba(180,220,255,0.95); box-shadow: 0 0 0 3px rgba(76,124,255,0.28), 0 0 14px rgba(120,195,255,0.35);
}
:root:not([data-theme="light"]) body.pagina-app main ::placeholder { color: rgba(159,183,214,0.55); }
:root:not([data-theme="light"]) body.pagina-app main option { background: #12131C; color: #F2F1F8; }
:root:not([data-theme="light"]) body.pagina-app main p.estado { color: var(--text); }
:root:not([data-theme="light"]) body.pagina-app main #mensaje,
:root:not([data-theme="light"]) body.pagina-app main #nav-mensaje { color: #FCA5A5; }
:root:not([data-theme="light"]) body.pagina-app main .aviso:not(.info):not(.advertencia) {
    background: rgba(248,113,113,0.12); border: 1px solid rgba(248,113,113,0.4); color: var(--text);
}
:root:not([data-theme="light"]) body.pagina-app main .boton-mostrar-password { color: var(--text-muted); }
:root:not([data-theme="light"]) body.pagina-app main .boton-mostrar-password:hover { color: var(--text); }
:root:not([data-theme="light"]) body.pagina-app main a.cancelar { color: var(--text-muted); }
:root:not([data-theme="light"]) body.pagina-app main button[type="submit"]:disabled { background: rgba(148,163,184,0.25); color: var(--text-muted); }

/* ============================================================
   MODO CLARO — vidrio translúcido en las 7 páginas (mismo criterio que el modo oscuro):
   los recuadros dejan ver la nebulosa en vez de ser cajas blancas sólidas.
   Casi sin relleno: paneles, formularios, filas, tarjetas de lista y de resumen usan var(--reflejo-claro)
   (definida arriba): solo franjas de brillo diagonales (máx. .22 en una esquina, ~.05 en el resto) sobre
   blur 12px + saturate(1.3), SIN brightness. Campos var(--campo-claro) (.16) · botones de la barra .10 ·
   menú de cuenta .85 (flotante, necesita fondo). Texto medido en píxeles reales sobre la nebulosa (6 a 19
   momentos del ciclo, percentil 3 para ignorar estrellas y bordes vecinos): páginas de administración
   >= 4.5:1; Nichos/Generaciones >= 4.4:1; carrusel: descripción 7.1, número 4.6, título 4.2 (texto grande).
   Gris de texto #34354E. Hay que volver a medir si se regeneran las texturas de la nebulosa con más
   densidad (ver scripts/generar-nebulosa.py) o si se baja más la opacidad.
   ============================================================ */
/* Filas y tarjetas de lista (radio menor que los paneles). */
:root[data-theme="light"] body.pagina-app .fila-nicho,
:root[data-theme="light"] body.pagina-app .fila-simulacion,
:root[data-theme="light"] body.pagina-app .tarjeta-publicacion {
    background: var(--reflejo-claro);
    -webkit-backdrop-filter: blur(12px) saturate(1.3); backdrop-filter: blur(12px) saturate(1.3);
    border: 1px solid rgba(122,95,224,0.3); border-radius: 10px;
    box-shadow: 0 4px 14px -8px rgba(122,95,224,0.35), inset 0 0 0 1px rgba(255,255,255,0.45);
}
:root[data-theme="light"] body.pagina-app .tarjeta-publicacion { border-radius: 12px; }

/* Campos de formulario: vidrio blanco más opaco para que lo escrito se lea con claridad. */
:root[data-theme="light"] body.pagina-app input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="range"]):not([type="color"]):not([type="hidden"]),
:root[data-theme="light"] body.pagina-app select,
:root[data-theme="light"] body.pagina-app textarea {
    background-color: var(--campo-claro); border-color: rgba(122,95,224,0.45);
}
:root[data-theme="light"] body.pagina-app input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="range"]):not([type="color"]):not([type="hidden"]):focus,
:root[data-theme="light"] body.pagina-app select:focus,
:root[data-theme="light"] body.pagina-app textarea:focus {
    outline: none; border-color: #3358E0; box-shadow: 0 0 0 3px rgba(51,88,224,0.2);
}
:root[data-theme="light"] body.pagina-app ::placeholder { color: rgba(63,64,96,0.8); }
:root[data-theme="light"] body.pagina-app input[type="file"]::file-selector-button {
    background: rgba(51,88,224,0.12); color: #1E3AA0; border: 1px solid rgba(51,88,224,0.4);
    border-radius: 6px; padding: .3rem .7rem; margin-right: .75rem; cursor: pointer; font: inherit;
}

/* Botones secundarios (los primarios conservan su azul sólido: son el énfasis). */
:root[data-theme="light"] body.pagina-app .boton-secundario,
:root[data-theme="light"] body.pagina-app .boton-peligro { background: var(--campo-claro); color: #96231A; }
:root[data-theme="light"] body.pagina-app .boton-secundario { border-color: rgba(122,95,224,0.35); }
:root[data-theme="light"] body.pagina-app .boton-secundario:hover,
:root[data-theme="light"] body.pagina-app .boton-peligro:hover { background: rgba(255,255,255,0.5); }

/* Barra superior: botones circulares en vidrio; el menú de cuenta es un popover sobre contenido
   y se queda casi opaco (.92) para que siempre se lea. */
:root[data-theme="light"] body.pagina-app .boton-icono-topbar {
    background: rgba(255,255,255,0.10); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
    border-color: rgba(122,95,224,0.3);
}
:root[data-theme="light"] body.pagina-app .boton-icono-topbar:hover { background: rgba(255,255,255,0.5); }
:root[data-theme="light"] body.pagina-app .lista-menu-cuenta {
    background: rgba(255,255,255,0.85); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
    border-color: rgba(122,95,224,0.3);
}

/* Alertas: conservan su color semántico, algo translúcidas. */
:root[data-theme="light"] body.pagina-app .alerta-correo { background: rgba(254,243,199,0.6); color: #7C2D12; }
:root[data-theme="light"] body.pagina-app .alerta-correo.critico { background: rgba(253,226,225,0.6); }
:root[data-theme="light"] body.pagina-app main .aviso:not(.info):not(.advertencia) { background: rgba(253,226,225,0.55); }
:root[data-theme="light"] body.pagina-app .aviso.info { background: rgba(51,88,224,0.10); color: #1E3AA0; }
:root[data-theme="light"] body.pagina-app .aviso.advertencia { background: rgba(217,119,6,0.12); color: #6B210F; }

/* ============================================================
   MÓDULOS DE ADMINISTRACIÓN (admin, adminSimulacion, operacion) — mismo diseño que app.html
   Vidrio en ambos modos, insignias translúcidas y pestañas de operación como franja de vidrio.
   Estas páginas traían colores del tema viejo (fondos opacos, campos blancos o grises sólidos,
   bordes casi blancos): aquí se llevan al sistema actual sin tocar su marcado ni su JS.
   ============================================================ */
/* Tokens heredados del tema viejo (--borde, --fondo, --azul, --verde, --rojo, --naranja): traían
   valores de modo claro TAMBIÉN en oscuro (líneas blancas, pistas gris claro). Se redefinen por tema. */
:root:not([data-theme="light"]) body.pagina-app { --borde: rgba(150,205,255,0.25); --fondo: rgba(150,205,255,0.08); --texto-suave: var(--text-muted); --azul: #6E93FF; --azul-oscuro: #A9C4FF; --verde: #6EE7B7; --rojo: #FCA5A5; --naranja: #FDBA74; }
:root[data-theme="light"] body.pagina-app { --borde: rgba(122,95,224,0.28); --fondo: rgba(122,95,224,0.08); --azul: #1E3AA0; --rojo: #8F1D12; }

/* Aire entre el título de la página y la barra de marca que la sigue */
body.pagina-app header.encabezado { margin-bottom: 1rem; }

/* ---------------- MODO OSCURO ---------------- */
/* Paneles (las tres secciones de app.html ya se resuelven en app.html) */
:root:not([data-theme="light"]) body.pagina-app .tarjeta-contenido:not(.nichos):not(.generaciones):not(.conexiones) {
    background: linear-gradient(180deg, rgba(76,124,255,0.08) 0%, rgba(20,22,35,0.34) 100%);
    -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
    border: 1px solid rgba(150,205,255,0.35); border-radius: 14px;
    box-shadow: 0 0 0 1px rgba(20,22,35,0.45), 0 0 14px -2px rgba(120,195,255,0.22);
}
/* Filas y tarjetas de lista */
:root:not([data-theme="light"]) body.pagina-app .fila-nicho, :root:not([data-theme="light"]) body.pagina-app .fila-simulacion, :root:not([data-theme="light"]) body.pagina-app .tarjeta-publicacion {
    background: linear-gradient(180deg, rgba(76,124,255,0.06) 0%, rgba(20,22,35,0.26) 100%);
    border: 1px solid rgba(150,205,255,0.28); border-radius: 10px; box-shadow: 0 0 10px -3px rgba(120,195,255,0.2);
}
:root:not([data-theme="light"]) body.pagina-app .tarjeta-publicacion { border-radius: 12px; }
:root:not([data-theme="light"]) body.pagina-app details.generacion, :root:not([data-theme="light"]) body.pagina-app .lista-items li, :root:not([data-theme="light"]) body.pagina-app .lista-pendientes li { background: rgba(10,12,28,0.35); border-color: rgba(150,205,255,0.25); }
/* Campos */
:root:not([data-theme="light"]) body.pagina-app input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="range"]):not([type="color"]):not([type="hidden"]):not([type="file"]),
:root:not([data-theme="light"]) body.pagina-app select, :root:not([data-theme="light"]) body.pagina-app textarea {
    background: rgba(10,12,28,0.55); color: var(--text); border: 1px solid rgba(150,205,255,0.35); border-radius: 8px;
    transition: border-color .2s, box-shadow .2s;
}
:root:not([data-theme="light"]) body.pagina-app input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="range"]):not([type="color"]):not([type="hidden"]):not([type="file"]):focus,
:root:not([data-theme="light"]) body.pagina-app select:focus, :root:not([data-theme="light"]) body.pagina-app textarea:focus {
    outline: none; border-color: rgba(180,220,255,0.95); box-shadow: 0 0 0 3px rgba(76,124,255,0.28), 0 0 14px rgba(120,195,255,0.35);
}
:root:not([data-theme="light"]) body.pagina-app ::placeholder { color: rgba(159,183,214,0.6); }
:root:not([data-theme="light"]) body.pagina-app select option { background: #12131C; color: #F2F1F8; }
/* Botones secundarios */
:root:not([data-theme="light"]) body.pagina-app .boton-secundario { background: rgba(150,205,255,0.06); border-color: rgba(150,205,255,0.35); color: var(--text); }
:root:not([data-theme="light"]) body.pagina-app .boton-secundario:hover { background: rgba(150,205,255,0.14); }
:root:not([data-theme="light"]) body.pagina-app .boton-peligro { background: rgba(248,113,113,0.08); border-color: rgba(248,113,113,0.5); color: #FCA5A5; }
:root:not([data-theme="light"]) body.pagina-app .boton-peligro:hover { background: rgba(248,113,113,0.16); }
/* Avisos y alertas: color semántico como tinte translúcido */
:root:not([data-theme="light"]) body.pagina-app .alerta-correo { background: rgba(251,191,36,0.12); border-color: rgba(251,191,36,0.5); color: #FDE68A; }
:root:not([data-theme="light"]) body.pagina-app .alerta-correo.critico { background: rgba(248,113,113,0.14); border-color: rgba(248,113,113,0.55); color: #FCA5A5; }
:root:not([data-theme="light"]) body.pagina-app .aviso.info { border-color: rgba(76,124,255,0.45); }
:root:not([data-theme="light"]) body.pagina-app .aviso.advertencia { border-color: rgba(251,191,36,0.45); }
/* Tarjetas de resumen de operación (misma receta que las de app.html) */
:root:not([data-theme="light"]) body.pagina-app .tarjetas-resumen .tarjeta-resumen {
    background: linear-gradient(180deg, rgba(76,124,255,0.10) 0%, rgba(20,22,35,0.22) 55%, rgba(20,22,35,0.30) 100%);
    -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
    border: 1px solid rgba(150,205,255,0.5); border-radius: 12px;
    box-shadow: 0 0 0 1px rgba(20,22,35,0.5), 0 0 12px rgba(120,195,255,0.32), 0 0 28px -6px rgba(76,124,255,0.45);
}
:root:not([data-theme="light"]) body.pagina-app .tarjetas-resumen .tarjeta-resumen .valor { color: #EAF4FF; text-shadow: 0 0 10px rgba(120,190,255,0.55); }
:root:not([data-theme="light"]) body.pagina-app .tarjetas-resumen .tarjeta-resumen .etiqueta { color: #9FB7D6; }
:root:not([data-theme="light"]) body.pagina-app .tarjetas-resumen .tarjeta-resumen.destacada {
    background: linear-gradient(180deg, rgba(76,124,255,0.24) 0%, rgba(30,40,100,0.30) 55%, rgba(20,22,35,0.34) 100%);
    border-color: rgba(180,220,255,0.85);
    box-shadow: 0 0 0 1px rgba(20,22,35,0.5), 0 0 20px rgba(120,195,255,0.6), 0 0 44px -4px rgba(76,124,255,0.6);
}
:root:not([data-theme="light"]) body.pagina-app .tarjetas-resumen .tarjeta-resumen.destacada .valor { color: #FFFFFF; text-shadow: 0 0 12px rgba(140,200,255,0.9), 0 0 26px rgba(76,124,255,0.6); }
/* Insignias (mismos colores semánticos, como tinte translúcido con borde) */
:root:not([data-theme="light"]) body.pagina-app .badge-activo, :root:not([data-theme="light"]) body.pagina-app .etiqueta-badge.vivo, :root:not([data-theme="light"]) body.pagina-app .estado-completada { background: rgba(52,211,153,0.14); color: #A7F3D0; box-shadow: inset 0 0 0 1px rgba(52,211,153,0.4); }
:root:not([data-theme="light"]) body.pagina-app .estado-fallida, :root:not([data-theme="light"]) body.pagina-app .grupo-contenido_a_revisar { background: rgba(248,113,113,0.14); color: #FCA5A5; box-shadow: inset 0 0 0 1px rgba(248,113,113,0.4); }
:root:not([data-theme="light"]) body.pagina-app .estado-parcial, :root:not([data-theme="light"]) body.pagina-app .grupo-posible_configuracion_nicho { background: rgba(250,204,21,0.14); color: #FDE68A; box-shadow: inset 0 0 0 1px rgba(250,204,21,0.4); }
:root:not([data-theme="light"]) body.pagina-app .grupo-tecnico_o_plataforma { background: rgba(76,124,255,0.16); color: #A9C4FF; box-shadow: inset 0 0 0 1px rgba(76,124,255,0.45); }
:root:not([data-theme="light"]) body.pagina-app .grupo-otro, :root:not([data-theme="light"]) body.pagina-app .estado-cancelada, :root:not([data-theme="light"]) body.pagina-app .estado-iniciada, :root:not([data-theme="light"]) body.pagina-app .etiqueta-badge.fijo { background: rgba(148,163,184,0.12); color: #A9B4C7; box-shadow: inset 0 0 0 1px rgba(148,163,184,0.3); }

/* ---------------- MODO CLARO ---------------- */
:root[data-theme="light"] body.pagina-app details.generacion, :root[data-theme="light"] body.pagina-app .lista-items li, :root[data-theme="light"] body.pagina-app .lista-pendientes li { background: var(--reflejo-claro); border-color: rgba(122,95,224,0.3); }
:root[data-theme="light"] body.pagina-app .badge-activo, :root[data-theme="light"] body.pagina-app .etiqueta-badge.vivo, :root[data-theme="light"] body.pagina-app .estado-completada { background: rgba(22,163,74,0.14); color: #14532D; }
:root[data-theme="light"] body.pagina-app .estado-fallida, :root[data-theme="light"] body.pagina-app .grupo-contenido_a_revisar { background: rgba(196,55,42,0.12); color: #8F1D12; }
:root[data-theme="light"] body.pagina-app .estado-parcial, :root[data-theme="light"] body.pagina-app .grupo-posible_configuracion_nicho { background: rgba(217,119,6,0.14); color: #92400E; }
:root[data-theme="light"] body.pagina-app .grupo-tecnico_o_plataforma { background: rgba(51,88,224,0.12); color: #1E3AA0; }
:root[data-theme="light"] body.pagina-app .grupo-otro, :root[data-theme="light"] body.pagina-app .estado-cancelada, :root[data-theme="light"] body.pagina-app .estado-iniciada, :root[data-theme="light"] body.pagina-app .etiqueta-badge.fijo { background: rgba(122,95,224,0.10); color: #34354E; }
:root[data-theme="light"] body.pagina-app .aviso.info { border-color: rgba(51,88,224,0.4); }
:root[data-theme="light"] body.pagina-app .aviso.advertencia { border-color: rgba(217,119,6,0.4); }

/* ---------------- PESTAÑAS DE OPERACIÓN (ambos modos): franja de vidrio con chips ---------------- */
body.pagina-app .pestanas {
    display: flex; flex-wrap: nowrap; gap: .25rem; padding: .4rem; margin-top: 1.5rem; border-bottom: 0; border-radius: 999px;
    width: fit-content; max-width: 100%; overflow-x: auto; scrollbar-width: none;
}
body.pagina-app .pestanas::-webkit-scrollbar { display: none; }
body.pagina-app .pestana {
    position: relative; padding: .5rem 1.05rem; margin-bottom: 0; border: 1px solid transparent; border-radius: 999px;
    font-weight: 600; white-space: nowrap; transition: color .2s, background .2s, border-color .2s, box-shadow .2s;
}
body.pagina-app .pestana:focus-visible { outline: 2px solid #FFC738; outline-offset: 2px; }
/* Indicador luminoso dorado bajo la pestaña activa */
body.pagina-app .pestana.activa::after {
    content: ""; position: absolute; left: 24%; right: 24%; bottom: -1px; height: 2px; border-radius: 2px;
    background: #FFC738; box-shadow: 0 0 8px rgba(255,190,60,0.9), 0 0 16px rgba(255,165,20,0.6);
}
:root:not([data-theme="light"]) body.pagina-app .pestanas {
    background: linear-gradient(180deg, rgba(76,124,255,0.10) 0%, rgba(20,22,35,0.30) 100%);
    -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
    border: 1px solid rgba(150,205,255,0.4);
    box-shadow: 0 0 0 1px rgba(20,22,35,0.5), 0 0 16px rgba(120,195,255,0.25), 0 0 34px -8px rgba(76,124,255,0.4);
}
:root:not([data-theme="light"]) body.pagina-app .pestana { color: #9FB7D6; }
:root:not([data-theme="light"]) body.pagina-app .pestana:hover { color: #FFFFFF; background: rgba(120,195,255,0.10); border-color: rgba(150,205,255,0.25); }
:root:not([data-theme="light"]) body.pagina-app .pestana.activa {
    color: #FFFFFF; text-shadow: 0 0 8px rgba(140,200,255,0.8);
    background: linear-gradient(180deg, rgba(76,124,255,0.40) 0%, rgba(76,124,255,0.12) 100%);
    border-color: rgba(180,220,255,0.8); box-shadow: 0 0 10px rgba(120,195,255,0.45), inset 0 0 10px rgba(150,205,255,0.15);
}
:root[data-theme="light"] body.pagina-app .pestanas {
    background: var(--reflejo-claro); -webkit-backdrop-filter: blur(12px) saturate(1.3); backdrop-filter: blur(12px) saturate(1.3);
    border: 1px solid rgba(122,95,224,0.45); box-shadow: 0 8px 22px -10px rgba(148,87,238,0.4), inset 0 0 0 1px rgba(255,255,255,0.65);
}
:root[data-theme="light"] body.pagina-app .pestana { color: #34354E; }
:root[data-theme="light"] body.pagina-app .pestana:hover { color: #2A1B5C; background: rgba(122,95,224,0.12); border-color: rgba(122,95,224,0.3); }
:root[data-theme="light"] body.pagina-app .pestana:focus-visible { outline-color: #7A3FDC; }
:root[data-theme="light"] body.pagina-app .pestana.activa {
    color: #FFFFFF; background: linear-gradient(135deg, #3358E0 0%, #7A3FDC 55%, #9B2FD1 100%);
    border-color: #5B47D6; box-shadow: 0 4px 14px -4px rgba(122,63,220,0.6);
}

/* ============================================================
   INSIGNIAS, CHIPS Y AVISOS EN LÍNEA de Nichos / Generaciones / Conexiones
   Tenían pasteles opacos (#dcfce7, #ddd6fe, #eff6ff…) que en claro se veían como recuadros blancos y en oscuro
   (avisos en línea de src/index.ts) como cajas claras con texto claro. Ahora son tintes translúcidos.
   ============================================================ */
:root[data-theme="light"] body.pagina-app .badge.activo, :root[data-theme="light"] body.pagina-app .badge-estado.conectada, :root[data-theme="light"] body.pagina-app .badge-estado.completada { background: rgba(22,163,74,0.14); color: #14532D; }
:root[data-theme="light"] body.pagina-app .badge.inactivo, :root[data-theme="light"] body.pagina-app .badge-estado.no-conectada, :root[data-theme="light"] body.pagina-app .badge-estado.cancelada { background: rgba(122,95,224,0.10); color: #34354E; }
:root[data-theme="light"] body.pagina-app .badge-estado.revocada, :root[data-theme="light"] body.pagina-app .badge-estado.expirada, :root[data-theme="light"] body.pagina-app .badge-estado.error, :root[data-theme="light"] body.pagina-app .badge-estado.fallida { background: rgba(196,55,42,0.12); color: #8F1D12; }
:root[data-theme="light"] body.pagina-app .badge-estado.en-proceso { background: rgba(51,88,224,0.12); color: #1E3AA0; }
:root[data-theme="light"] body.pagina-app .badge-estado.parcial { background: rgba(217,119,6,0.14); color: #92400E; }
:root[data-theme="light"] body.pagina-app .chip-horario { background: rgba(217,154,0,0.12); border: 1px solid rgba(201,134,10,0.5); color: #6B3B00; }
:root[data-theme="light"] body.pagina-app .tarjeta-resultado-miniatura-vacia { background: rgba(122,95,224,0.06); }
/* Avisos en línea (estilos inline en src/index.ts: por eso !important) */
:root[data-theme="light"] body.pagina-app #nav-instalar-instrucciones-ios { background: rgba(51,88,224,0.08) !important; border-color: rgba(51,88,224,0.4) !important; -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); }
:root[data-theme="light"] body.pagina-app .aviso-cuenta-prueba { background: rgba(217,119,6,0.10) !important; border-color: rgba(217,119,6,0.5) !important; color: #6B3B00; -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); }
:root[data-theme="light"] body.pagina-app .aviso-cuenta-prueba button { color: #6B3B00 !important; border-color: #6B3B00 !important; }
:root:not([data-theme="light"]) body.pagina-app #nav-instalar-instrucciones-ios { background: rgba(76,124,255,0.12) !important; border-color: rgba(150,205,255,0.4) !important; color: #A9C4FF !important; }
:root:not([data-theme="light"]) body.pagina-app #nav-instalar-instrucciones-ios button { color: #A9C4FF !important; border-color: rgba(150,205,255,0.6) !important; }
:root:not([data-theme="light"]) body.pagina-app .aviso-cuenta-prueba { background: rgba(251,191,36,0.12) !important; border-color: rgba(251,191,36,0.5) !important; color: #FDE68A; }
:root:not([data-theme="light"]) body.pagina-app .aviso-cuenta-prueba button { color: #FDE68A !important; border-color: rgba(251,191,36,0.6) !important; }

/* Botón primario en modo oscuro: el azul de acento (#4C7CFF) con texto blanco daba 3.73:1; este azul más profundo
   llega a 4.8:1 (mínimo 4.5) sin perder el tono de marca. Solo afecta a las páginas autenticadas en oscuro. */
:root:not([data-theme="light"]) body.pagina-app .boton-primario, :root:not([data-theme="light"]) body.pagina-app button.boton-primario { background: var(--boton-primario); }
:root:not([data-theme="light"]) body.pagina-app .boton-primario:hover, :root:not([data-theme="light"]) body.pagina-app button.boton-primario:hover { background: var(--boton-primario-hover); }


/* ============================================================
   FONDO NEBULOSA — equivalente en modo claro del fondo de estrellas
   Solo body.pagina-app en claro; en oscuro no se muestra (display:none: costo cero, y el
   navegador ni siquiera descarga las imágenes).
   Son DOS texturas orgánicas prerenderizadas (public/nebulosa/*.webp, generadas con
   scripts/generar-nebulosa.py): "a" = nubes grandes de violeta/azul/magenta con bordes que se
   disuelven; "b" = filamentos, zonas más y menos densas, núcleos brillantes rosado-blancos,
   vetas de polvo y estrellas. Se animan en paralaje (velocidad y dirección distintas) solo con
   transform/opacity: lo resuelve la GPU, sin JS por fotograma. Mezcla normal (sin multiply).
   El marcado (dos <div>) lo inserta public/fondo-espacial.js. En pantallas angostas se usan
   las versiones pequeñas. Con prefers-reduced-motion quedan visibles y quietas.
   DENSIDAD: afinada midiendo el contraste del texto que va directo sobre la página (gris, enlaces,
   error): menos del ~1% de la pantalla queda bajo 4.5:1. Si se regeneran las texturas con más
   opacidad o polvo, hay que volver a medirlo.
   ============================================================ */
.fondo-nebulosa { display: none; }
@media (prefers-color-scheme: light) {
    :root:not([data-theme="dark"]) body.pagina-app .fondo-nebulosa {
        display: block; position: fixed; inset: 0; z-index: -1; overflow: hidden; pointer-events: none;
    }
}
:root[data-theme="light"] body.pagina-app .fondo-nebulosa {
    display: block; position: fixed; inset: 0; z-index: -1; overflow: hidden; pointer-events: none;
}
/* Las capas son más grandes que la ventana (inset:-16%) para poder moverse sin mostrar bordes. */
.fondo-nebulosa .capa {
    position: absolute; inset: -16%; background-size: cover; background-position: center; will-change: transform;
    animation-timing-function: ease-in-out; animation-iteration-count: infinite; animation-direction: alternate;
}
.fondo-nebulosa .capa-a { background-image: url('nebulosa/capa-a.webp'); animation-name: nebulosa-a; animation-duration: 12s; }
.fondo-nebulosa .capa-b { background-image: url('nebulosa/capa-b.webp'); animation-name: nebulosa-b; animation-duration: 10s; }
@media (max-width: 700px) {
    .fondo-nebulosa .capa-a { background-image: url('nebulosa/capa-a-m.webp'); }
    .fondo-nebulosa .capa-b { background-image: url('nebulosa/capa-b-m.webp'); }
}
@keyframes nebulosa-a { from { transform: translate3d(3vw, 2vh, 0) scale(1); } to { transform: translate3d(-7vw, -3vh, 0) scale(1.07); } }
@keyframes nebulosa-b { from { transform: translate3d(-5vw, -3vh, 0) scale(1.03); opacity: 0.82; } to { transform: translate3d(8vw, 4vh, 0) scale(1.1); opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
    .fondo-nebulosa .capa { animation: none; }
}
