/* =====================================================
   Akcadmia — Hoja de estilos principal

   COMPONENTES. Este archivo viste lo que ya existe: la barra, las tarjetas, las
   tablas, los botones, el chat, el horario y el remapeo de las variables de
   Bootstrap para cada tema.

   Lo que NO va aquí: la paleta, el reset y los estilos base del documento. Eso
   es css/sitio.css, que además se carga DESPUÉS que este archivo, así que a
   igual especificidad gana él — cualquier regla base escrita aquí se pierde sin
   avisar. De ahí que este archivo ya no declare ni :root ni body: tenía una
   paleta propia --color-* que quedó de antes del rediseño índigo, sin un solo
   uso, y un body que sitio.css pisaba entero.

   El orden de carga completo, del _Layout: bootstrap → akcadmia.css → sitio.css
   → Akcadmia.Web.styles.css (el CSS aislado de cada vista).
   ===================================================== */

/* ─── NAVBAR ──────────────────────────────────────── */
.navbar-brand {
    letter-spacing: -.5px;
}

/* Logotipo de la barra.

   Vive aquí y no en el CSS aislado del layout a propósito: el cromo del sitio
   (barra y pie) no puede depender de que el bundle de CSS isolation alcance al
   elemento. Cuando esta regla no llegaba, el SVG se pintaba a 150x150 px, estiraba
   la barra y su ancho tapaba la primera opción del menú.

   Se acota la ALTURA y no el ancho: la barra tiene su propia altura y con el ancho
   en automático el logo conserva su proporción sea cuadrado o alargado. */
.edu-navbar__logo {
    height: 2rem;
    width: auto;
    /* Baja un pelo el logo para alinear su centro óptico con el de la palabra, que
       las mayúsculas del texto dejan más arriba. */
    vertical-align: -0.25rem;
}

/* Rol con el que está abierta la sesión, bajo el nombre del menú de usuario.

   Píldora y no texto suelto: bajo el nombre, dos líneas de texto se leen como un
   nombre de dos renglones. Con fondo propio se distingue de un vistazo que es una
   etiqueta y no parte del nombre.

   El ancho lo da la clase badge de Bootstrap, que se ajusta al texto. Aquí solo se
   corrigen el tamaño y el relleno, que los de badge son los de una etiqueta normal y
   esta va debajo de un nombre.

   El color base es el gris translúcido de la opción activa del menú, y es el que
   queda si el rol no tuviera modificador. */
.edu-navbar__rol {
    font-size: .68rem;
    letter-spacing: .04em;
    padding: .15rem .5rem;
    background-color: rgba(255, 255, 255, .18);
    /* Alineada al inicio y no estirada: dentro de un contenedor flex en columna, un
       hijo sin esto ocupa todo el ancho del nombre y la píldora sale desbocada. */
    align-self: flex-start;
    margin-top: .15rem;
}

/* Un color por rol, para distinguirlos sin leer.

   Son los MISMOS cuatro colores con los que el listado de usuarios del área de
   administración pinta el badge de rol: azul el alumno, verde el profesor, rojo el
   administrador y oscuro el supervisor. Repetir ahí un juego y aquí otro obligaría a
   aprender dos códigos para el mismo dato.

   Van con alfa y no como color plano: la píldora vive sobre el azul de la barra en
   claro y sobre #0F172A en oscuro, y un color sólido de Bootstrap sobre ese azul
   pelea con él y ensucia la cabecera. Con transparencia el tinte se apoya en el
   fondo, se distingue igual y no rompe el diseño. Por eso tampoco hacen falta
   contrapartes para el tema oscuro: el mismo tinte funciona sobre los dos fondos,
   que son ambos oscuros.

   El alumno lleva más alfa que los demás: su azul es el más cercano al de la barra y
   con la misma opacidad apenas se separaba del fondo. */
.edu-navbar__rol--alumno {
    background-color: rgba(96, 165, 250, .45);
}

.edu-navbar__rol--profesor {
    background-color: rgba(52, 211, 153, .32);
}

.edu-navbar__rol--administrador {
    background-color: rgba(248, 113, 113, .32);
}

.edu-navbar__rol--supervisor {
    background-color: rgba(15, 23, 42, .55);
}

/* Opción activa del menú (sombreada) */
.navbar-nav .nav-link.active {
    background-color: rgba(255, 255, 255, .18);
    border-radius: 8px;
    font-weight: 600;
}

/* Menú desplegable de filtros con búsqueda */
.edu-preguntas-prof__menu {
    max-height: 250px;
    overflow-y: auto;
}

/* ─── COMBOBOX BUSCABLE (select con búsqueda) ────────── */
.combo-buscable {
    position: relative;
}

.combo-buscable__input {
    cursor: text;
}

.combo-buscable__menu {
    max-height: 250px;
    overflow-y: auto;
    list-style: none;
    padding-left: 0;
}

/* Cuadro de búsqueda dentro de un dropdown de items (p. ej. profesores) */
.edu-dropdown-buscar {
    position: sticky;
    top: 0;
    z-index: 2;
}

/* ─── MÓDULO CLASES (conversación) ─────────────────────
   Estilos globales: el chat se genera por JS y el CSS
   aislado de la vista no aplica a esos elementos. La lista de la izquierda y sus
   tarjetas viven en componentes/panel-lista.css, junto al panel que las contiene,
   y solo las cargan las pantallas que lo pintan. */

/* ─── Cuerpo de la conversación: material | hilo ───
   Por defecto se APILA —material arriba, hilo debajo—, que es el comportamiento
   de siempre y el que queda cuando el material está plegado o la clase no tiene.
   Cuando clases.js enciende --material-abierto, y solo de xl para arriba, pasa a
   dos columnas: 75% el material, 25% la conversación. Más abajo, con la lista de
   clases al lado, ese 25% se queda tan estrecho —unos 150 px en lg— que las
   burbujas se parten palabra a palabra.

   Los ajustes del bloque del material en ese modo viven en
   componentes/clases/material-clase.css, que es donde están sus clases, bajo el
   mismo punto de corte: si cambia aquí, cambia allí. */
.edu-clases__cuerpo {
    display: flex;
    flex-direction: column;
}

/* min-width: 0 en las dos columnas. Sin él una caja flex no baja del ancho
   mínimo de su contenido, y la hoja A4 del material —210mm— ensancharía su
   columna hasta romper el reparto. */
.edu-clases__material,
.edu-clases__conversacion {
    min-width: 0;
}

.edu-clases__conversacion {
    display: flex;
    flex-direction: column;
}

@media (min-width: 1200px) {
    /* La fila NO tiene alto propio: se lo da la columna de la conversación, que mide
       lo mismo con el material abierto que plegado —el hilo con su alto fijo más el
       formulario—. Así abrir el material no le quita alto a la conversación. */
    .edu-clases__cuerpo--material-abierto {
        flex-direction: row;
        align-items: stretch;
        gap: .75rem;
    }

        /* La columna del material se estira hasta el alto de la fila y su bloque la
           llena en posición absoluta (componentes/clases/material-clase.css): fuera
           del flujo, una hoja de varias páginas no puede alargar la fila, y se
           desplaza por dentro. */
        .edu-clases__cuerpo--material-abierto .edu-clases__material {
            flex: 0 0 75%;
            max-width: 75%;
            position: relative;
        }

        .edu-clases__cuerpo--material-abierto .edu-clases__conversacion {
            flex: 1 1 25%;
            max-width: 25%;
        }

        /* En la columna estrecha la pista se parte en cuatro líneas y alarga el pie
           más que el propio formulario: ahí se oculta. Vuelve con el material
           plegado, cuando la conversación recupera todo el ancho. Va por id porque
           los elementos del pie no tienen clase propia: los pinta la parcial
           compartida y los maneja clases.js por esos mismos ids. */
        .edu-clases__cuerpo--material-abierto #chat-pista {
            display: none;
        }

        /* El formulario se apila: el cuadro de texto ocupa su propia línea con todo
           el ancho de la columna, y los dos botones bajan a la siguiente —adjuntar a
           la izquierda, enviar a la derecha—. En una sola fila, los dos botones se
           llevarían casi todo el ancho y del cuadro se verían unas pocas letras. */
        .edu-clases__cuerpo--material-abierto #chat-form {
            flex-wrap: wrap;
        }

        .edu-clases__cuerpo--material-abierto #chat-texto {
            order: -1;
            flex: 1 0 100%;
        }

        .edu-clases__cuerpo--material-abierto #btn-enviar {
            margin-left: auto;
        }
}

/* ─── Conversación ─── */
.edu-clases__chat {
    height: 60vh;
    min-height: 320px;
    overflow-y: auto;
    /* Sin anclaje automático: lo que entra por arriba —las páginas anteriores y las
       imágenes que cargan después— lo compensa js/compartido/clases/clases-hilo.js
       a mano, igual en todos los navegadores. Con el anclaje encendido, donde
       existe, la vista se corregiría dos veces. */
    overflow-anchor: none;
    background-color: #f8fafc;
    display: flex;
    flex-direction: column;
    gap: .5rem;
}

/* Envoltorio del hilo. La píldora de mensajes nuevos flota sobre su borde inferior,
   así que necesita un contenedor posicionado que NO se desplace con los mensajes. */
.edu-clases__hilo {
    position: relative;
}

.edu-clases__nuevos {
    position: absolute;
    bottom: .75rem;
    left: 50%;
    transform: translateX(-50%);
    z-index: 2;
    white-space: nowrap;
}

/* Hueco fijo en lo alto del hilo mientras quedan mensajes anteriores. El aviso de
   carga está siempre dentro y solo se ve mientras se pide la página: aparecer y
   desaparecer no cambia el alto ni mueve lo que se está leyendo. Lo pinta
   js/compartido/clases/clases-hilo.js. */
.edu-clases__anteriores {
    align-self: center;
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    min-height: 2rem;
    font-size: .8rem;
    color: var(--edu-texto-suave);
}

    .edu-clases__anteriores:not(.edu-clases__anteriores--cargando) > * {
        visibility: hidden;
    }

.edu-clases__fecha-sep {
    align-self: center;
    background-color: #e2e8f0;
    color: #475569;
    border-radius: 999px;
    padding: .1rem .75rem;
    margin: .35rem 0;
    text-transform: capitalize;
}

.edu-clases__msg {
    display: flex;
    justify-content: flex-start;
}

.edu-clases__msg--mio {
    justify-content: flex-end;
}

.edu-clases__burbuja {
    max-width: 75%;
    /* Hijo de un contenedor flex: sin esto no puede encoger por debajo del ancho
       de su contenido, y una imagen o un nombre de archivo más anchos que el
       75 % del panel la desbordaban en vez de ajustarse. */
    min-width: 0;
    background-color: #fff;
    border: 1px solid var(--bs-border-color, #dee2e6);
    border-radius: 12px;
    padding: .45rem .65rem;
    box-shadow: 0 1px 1px rgba(0, 0, 0, .04);
}

.edu-clases__msg--mio .edu-clases__burbuja {
    background-color: #dbeafe;
    border-color: #bfdbfe;
}

/* La variable era --color-primario, que NO existe en el proyecto: todas se llaman
   --edu-*. Con un valor inválido el nombre del autor se quedaba con el color
   heredado, sin distinguirse del texto del mensaje. */
.edu-clases__autor {
    color: var(--edu-primario);
    margin-bottom: .15rem;
}

.edu-clases__texto {
    white-space: pre-wrap;
    word-break: break-word;
}

.edu-clases__hora {
    font-size: .7rem;
    color: #94a3b8;
    text-align: right;
    margin-top: .15rem;
}

/* El tope en píxeles es el tamaño cómodo de una miniatura en escritorio, pero en
   un panel estrecho —la columna del 25 % con el material abierto, o el móvil— la
   burbuja mide menos que eso y la imagen se salía por la derecha. min() toma el
   menor de los dos: 220 px cuando caben, y el ancho de la burbuja cuando no. */
.edu-clases__img {
    max-width: min(220px, 100%);
    height: auto;
    max-height: 220px;
    border-radius: 8px;
    object-fit: cover;
    display: block;
}

.edu-clases__archivo {
    color: inherit;
    text-decoration: none;
    /* Mismo caso que la imagen: un nombre de archivo largo en un panel estrecho
       desbordaba la burbuja. */
    max-width: min(260px, 100%);
    overflow-wrap: anywhere;
}

    .edu-clases__archivo:hover {
        text-decoration: underline;
    }

/* Adjunto elegido en la entrada, antes de enviar: miniatura para imagen o icono
   para el resto. Lo pinta js/compartido/clases/clases-adjuntos.js, por eso vive
   aquí y no en el .cshtml.css de la vista. Pequeña a propósito: es una
   confirmación de qué se va a enviar, no una previsualización. */
.edu-clases__adjunto-miniatura {
    width: 36px;
    height: 36px;
    object-fit: cover;
    border-radius: 6px;
    border: 1px solid var(--bs-border-color, #dee2e6);
    vertical-align: middle;
    margin-right: .4rem;
    display: inline-block;
}

i.edu-clases__adjunto-miniatura {
    font-size: 1.4rem;
    line-height: 34px;
    text-align: center;
    color: var(--edu-primario);
}

/* El formulario mientras se arrastra un archivo encima: un borde discontinuo del
   color de marca que dice "suelta aquí". */
.edu-clases__form--soltar {
    outline: 2px dashed var(--edu-primario);
    outline-offset: 4px;
    border-radius: 8px;
}

/* ─── Encabezado de conversación: profesor ─── */
.edu-clases__prof-avatar img,
.edu-clases__prof-avatar span {
    width: 32px;
    height: 32px;
    font-size: .9rem;
}

#conv-profesor:hover .edu-clases__prof-nombre,
#conv-profesor:not(.edu-clases__prof--sin-enlace):hover #conv-profesor-nombre {
    text-decoration: underline;
}

.edu-clases__prof--sin-enlace {
    pointer-events: none;
    cursor: default;
}


/* ── Clases: horas (12h principal + 24h secundario) ───────────────────── */
.edu-clases__horas {
    display: inline-flex;
    flex-direction: column;
    line-height: 1.2;
}

.edu-clases__hora12 {
    font-size: .8125rem;
    font-weight: 600;
    color: var(--bs-body-color);
}

.edu-clases__hora24 {
    font-size: .6875rem;
    color: var(--bs-secondary-color, #6c757d);
    letter-spacing: .01em;
}

/* ── Clases: ganancia del profesor ────────────────────────────────────── */
.edu-clases__ganancia {
    background-color: #e8f5e9;
    color: #1b5e20;
    border: 1px solid #c8e6c9;
    font-weight: 600;
}

/* ── Clases: conversación en solo lectura ─────────────────────────────── */
.edu-clases__cerrado {
    padding: .625rem .75rem;
    background-color: var(--bs-tertiary-bg, #f8f9fa);
    border: 1px dashed var(--bs-border-color, #dee2e6);
    border-radius: .75rem;
}

/* ── Clases: insignia de la clase inactiva (al tema le faltan preguntas) ─ */
/* La pinta badgeEstado en la tarjeta de la lista y en la cabecera de la
   conversación. Conserva el ámbar de la tarjeta inactiva: aquí el color dice el
   estado. */
.edu-clases__badge-inactiva {
    background-color: #fef3c7;
    color: #92400e;
    border: 1px solid #fcd34d;
    font-weight: 600;
}

/* ── Clases: estrellas del modal de calificación ──────────────────────── */
.edu-clases__estrellas {
    font-size: 1.75rem;
    line-height: 1;
}

.edu-clases__estrella {
    cursor: pointer;
    margin-right: .25rem;
}

/* ─── BILLETERA DEL ALUMNO: bloque de saldo ─────────── */
/* === Bloque de saldo (billetera del alumno) ===
   La cifra y la moneda flotaban sobre el blanco de la tarjeta sin nada que las
   sostuviera, y la tarjeta entera se quedaba desangelada. Aquí van dentro de un
   bloque dorado suave: se conserva la nitidez que daba la cabecera amarilla, pero
   contenida donde está el dato en vez de teñir la tarjeta.

   El fondo es una versión muy diluida del oro de la píldora, para que las dos se
   reconozcan como lo mismo sin que el bloque compita con la cifra que contiene. */
.edu-saldo {
    background-color: var(--edu-moneda-suave);
    border: 1px solid var(--edu-moneda-suave-borde);
    border-radius: var(--edu-radio-grande);
    padding: 1.25rem 1rem 1rem;
}

/* La cifra manda; la moneda acompaña. Antes las dos iban al mismo cuerpo y el icono
   pesaba tanto como el número. La moneda mide en em, así que su tamaño sale del
   cuerpo de la cifra: .7em de 2.5rem la deja en la versión grande del dibujo, que
   es la que se lee a ese tamaño. */
.edu-saldo__cifra {
    font-size: 2.5rem;
    font-weight: 700;
    line-height: 1.1;
    display: inline-flex;
    align-items: center;
    gap: .5rem;
}

    .edu-saldo__cifra .edu-moneda {
        width: .7em;
        height: .7em;
    }

.edu-saldo__etiqueta {
    font-size: .85rem;
    color: var(--edu-texto-suave);
    margin-bottom: 0;
}

/* La equivalencia en soles: es un dato de apoyo, no parte del saldo. */
.edu-saldo__equivalencia {
    font-size: .78rem;
    color: var(--edu-texto-suave);
    margin: .35rem 0 0;
}

/* Cabecera de la tarjeta de la billetera. En blanco no se distinguía de ninguna otra
   tarjeta, y en amarillo sólido era lo más pesado de la columna: dorado suave, que
   la identifica como la tarjeta del dinero sin robarle protagonismo a la cifra. */
.edu-cabecera-monedas {
    background-color: var(--edu-moneda-relleno);
    border-bottom: 1px solid var(--edu-moneda-borde);
    color: var(--edu-moneda-texto);
}

    .edu-cabecera-monedas h1, .edu-cabecera-monedas h2, .edu-cabecera-monedas h3,
    .edu-cabecera-monedas h4, .edu-cabecera-monedas h5, .edu-cabecera-monedas h6 {
        color: var(--edu-moneda-texto);
    }

/* ─── QR (invitación): marco blanco para que se lea sobre fondos oscuros ── */
/* === QR: marco blanco para que se lea sobre fondos oscuros === */
.edu-qr-img,
#qr-invitacion-img {
    background-color: #fff;
    padding: 6px;
    border-radius: 8px;
}

/* ─── Campanita de mensajes sin leer ─── */
.edu-campana__menu {
    width: 340px;
    max-width: 92vw;
}

.edu-campana__lista {
    max-height: 360px;
    overflow-y: auto;
}

.edu-campana__item:hover {
    background-color: #f0f7ff;
}

/* ─── HORARIO SEMANAL ─────────────────────────────── */
.celda-horario {
    background-color: #fff;
    transition: background-color .15s ease;
}

    .celda-horario:hover {
        background-color: #f0f7ff;
    }

/* ─── MINIATURA EN TABLAS ──────────────── */
/* Imagen de una fila: catálogo de cursos, ciclos y cursos del ciclo. Cuadrada y
   recortada para que filas con imágenes de proporciones distintas no bailen. Vive
   en el CSS global porque estas celdas las pinta JavaScript. */
.edu-tabla__miniatura {
    height: 32px;
    width: 32px;
    object-fit: cover;
}

/* ─── RECORTE DE TEXTO EN LAS TABLAS DEL ÁRBOL DE CICLOS (Admin) ────────────── */
/* Un nombre o una descripción largos ensanchaban la celda y desplazaban las demás
   columnas. Misma técnica que la tabla de preguntas del profesor: la COLUMNA se
   acota y el TEXTO se recorta a una línea, con el contenido completo en su title,
   que es lo que el navegador muestra al pasar el ratón.

   Vive en el CSS global y no en el .cshtml.css de la vista por el mismo motivo que
   la miniatura de aquí arriba: estas tablas las pinta JavaScript, y a ese marcado
   Razor no le pone el atributo de scope, así que las reglas con scope nunca lo
   alcanzan. */
.edu-arbol__col-recorte {
    /* No es un ancho de 0: en una tabla, max-width impide que la celda crezca con
       su contenido, que es justo lo que hace falta para que el recorte se active.
       El ancho real lo fija el width en porcentaje de cada cabecera. */
    max-width: 0;
}

.edu-arbol__recorte {
    display: block;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    /* El cursor avisa de que hay más texto del que se ve y que se lee al posarse. */
    cursor: help;
}

/* Nombre del ciclo, del curso o del tema en la cabecera de cada panel. Sin tope,
   un nombre largo empuja los botones de la derecha fuera de la tarjeta. */
.edu-arbol__titulo {
    display: inline-block;
    max-width: 45ch;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    /* Alinea la base del texto con la del resto del encabezado: un inline-block se
       apoya en su margen inferior y quedaría un pelo alto. */
    vertical-align: bottom;
}

/* ─── ÁRBOL DE CICLOS (panel lateral) ────────────── */
#panel-arbol .btn {
    text-align: left;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ─── TABLA HORARIO ───────────────────────────────── */
#tabla-horario th {
    font-size: .85rem;
}

#tabla-horario td {
    vertical-align: top;
}

/* ─── PIE DE PÁGINA ─────────────────────────────── */
/* Mismo motivo que el logotipo de la barra: son estilos del cromo del sitio y
   tenían que dejar de depender del CSS aislado del layout. */
.edu-footer {
    font-size: 0.875rem;
}

    .edu-footer a:hover {
        color: #fff !important;
        transition: var(--edu-transicion);
    }

/* Listas de enlaces del pie. El interlineado justo va aquí y no con clases de
   Bootstrap porque son varios bloques y repetirlo en cada uno invita a que se
   descuadren entre ellos. */
.edu-footer__lista li + li {
    margin-top: 0.15rem;
}

/* Logotipo del pie, más pequeño que el de la barra: aquí es una firma, no la
   marca principal. La altura la marca la línea del texto que lleva al lado. */
.edu-footer__logo {
    height: 1.25rem;
    width: auto;
    flex-shrink: 0;
}

/* El aviso del Libro comparte renglón con el copyright, pero no debe estirarse
   hasta pegarse a él en pantallas medianas. */
.edu-footer__aviso {
    max-width: 70ch;
}

/* ─── PIE: REDES SOCIALES ───────────────────────── */
/* Franja «Síguenos» de la parcial _RedesSociales: las destacadas como iconos y el
   resto tras «Más redes». Va aquí con el resto del pie y no en un CSS aislado: las
   landings cargan este archivo pero no el bundle de CSS isolation.

   El color de cada red no está aquí: lo trae su entrada de Empresa:RedesSociales y
   llega en la hoja que arma el servidor (/css/generado/redes-sociales.css, ver
   ProveedorHojaRedes), que solo fija --edu-color-red en la clase de cada color. Aquí
   está cómo se usa: en el icono, en el borde y en el tinte al pasar el ratón.

   Ni ese color ni el gris del texto tienen variable en la paleta, y no llevan
   contraparte para el tema oscuro porque el pie es bg-dark en los dos temas: el fondo
   sobre el que se miden no cambia. El gris es el mismo #94a3b8 que el tema oscuro ya
   da a .text-secondary.

   align-items arriba y no al centro: al abrir «Más redes» su lista crece hacia abajo,
   y centrado bajaría el título y los iconos a la mitad de esa altura. */
.edu-redes {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: .5rem;
}

/* El título mide lo mismo que un icono para quedar centrado con la fila. */
.edu-redes__titulo {
    display: inline-flex;
    align-items: center;
    min-height: 2.75rem;
    margin-right: .25rem;
}

.edu-redes__destacadas,
.edu-redes__todas {
    list-style: none;
    margin: 0;
    padding: 0;
}

.edu-redes__destacadas {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
}

/* Círculo de un icono destacado. 2.75rem son los 44 px de zona táctil que el dedo
   acierta sin rozar el de al lado. Los selectores llevan delante .edu-redes para
   ganarle en especificidad al color de enlace de los temas. */
.edu-redes .edu-redes__icono {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, .15);
    background-color: rgba(255, 255, 255, .06);
    color: #94a3b8;
    font-size: 1.25rem;
    text-decoration: none;
    transition: var(--edu-transicion);
}

/* «Más redes» ocupa lo que queda de la fila: su lista se abre justo debajo del botón
   sin mover nada de lo que ya estaba. Si no le caben 9rem —en móvil— baja entera a
   la fila siguiente y la lista usa todo el ancho. */
.edu-redes__mas {
    flex: 1 1 0;
    min-width: 9rem;
}

/* El resumen del <details> hace de botón. Se le quita el triángulo del navegador
   —con list-style donde lo pinta como viñeta, con el pseudoelemento en WebKit—
   porque lo sustituye el chevron, que gira al abrir. */
.edu-redes .edu-redes__boton {
    display: inline-flex;
    align-items: center;
    gap: .375rem;
    min-height: 2.75rem;
    padding: 0 .875rem;
    border: 1px solid rgba(255, 255, 255, .15);
    border-radius: 999px;
    color: #94a3b8;
    cursor: pointer;
    list-style: none;
    user-select: none;
    transition: var(--edu-transicion);
}

    .edu-redes .edu-redes__boton::-webkit-details-marker {
        display: none;
    }

    .edu-redes .edu-redes__boton:hover {
        color: #fff;
        border-color: rgba(255, 255, 255, .35);
    }

.edu-redes__boton .bi-chevron-down {
    transition: transform .2s ease;
}

.edu-redes__mas[open] .edu-redes__boton .bi-chevron-down {
    transform: rotate(180deg);
}

/* Fichas del desplegable: tantas columnas de 10rem como quepan, dos en móvil.
   10rem es lo que pide «Grupo de Facebook», la ficha más larga, para caber en un
   renglón en escritorio; en las dos columnas del móvil se parte en dos. */
.edu-redes__todas {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
    gap: .5rem;
    margin-top: .5rem;
}

.edu-redes .edu-redes__ficha {
    display: flex;
    align-items: center;
    gap: .5rem;
    min-height: 2.75rem;
    padding: 0 .875rem;
    border: 1px solid rgba(255, 255, 255, .15);
    border-radius: 999px;
    background-color: rgba(255, 255, 255, .04);
    color: #94a3b8;
    text-decoration: none;
    transition: var(--edu-transicion);
}

    .edu-redes .edu-redes__ficha i {
        font-size: 1.1rem;
        flex-shrink: 0;
    }

/* El color de cada red va en el icono y no en el enlace: la regla del pie que pone
   el enlace en blanco al pasar el ratón ilumina así el nombre de la ficha, y el icono
   conserva su color. Una red sin color sigue al enlace. */
.edu-redes__icono i,
.edu-redes__ficha i {
    color: var(--edu-color-red, currentColor);
}

/* Al pasar el ratón, el círculo o la ficha se tiñen del color de su red. */
.edu-redes .edu-redes__icono:hover,
.edu-redes .edu-redes__ficha:hover {
    border-color: var(--edu-color-red, rgba(255, 255, 255, .35));
    background-color: color-mix(in srgb, var(--edu-color-red, #fff) 18%, transparent);
}

/* Foco de teclado en blanco y separado del borde: el anillo por defecto del
   navegador apenas se ve sobre el pie oscuro. */
.edu-redes__icono:focus-visible,
.edu-redes__ficha:focus-visible,
.edu-redes__boton:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 2px;
}

/* Sin movimiento para quien lo pidió en su sistema: el chevron cambia de golpe y los
   tintes no se animan. */
@media (prefers-reduced-motion: reduce) {
    .edu-redes .edu-redes__icono,
    .edu-redes .edu-redes__ficha,
    .edu-redes .edu-redes__boton,
    .edu-redes__boton .bi-chevron-down {
        transition: none;
    }
}

/* ─── MIGA DE PAN ───────────────────────────────── */
.edu-breadcrumb {
    background-color: transparent;
    padding: 0;
    margin-bottom: 0;
    font-size: 0.85rem;
}

    .edu-breadcrumb .breadcrumb-item + .breadcrumb-item::before {
        color: var(--edu-texto-suave);
    }

html:not([data-tema="oscuro"]) .btn-primary {
    --bs-btn-bg: #4F46E5;
    --bs-btn-border-color: #4F46E5;
    --bs-btn-hover-bg: #4338CA;
    --bs-btn-hover-border-color: #4338CA;
    --bs-btn-active-bg: #3730A3;
    --bs-btn-active-border-color: #3730A3;
    --bs-btn-disabled-bg: #4F46E5;
    --bs-btn-disabled-border-color: #4F46E5;
}

html:not([data-tema="oscuro"]) .btn-outline-primary {
    --bs-btn-color: #4F46E5;
    --bs-btn-border-color: #4F46E5;
    --bs-btn-hover-bg: #4F46E5;
    --bs-btn-hover-border-color: #4F46E5;
    --bs-btn-active-bg: #4338CA;
    --bs-btn-active-border-color: #4338CA;
    --bs-btn-disabled-color: #4F46E5;
    --bs-btn-disabled-border-color: #4F46E5;
}

/* En claro, el gris con que Bootstrap compila .btn-outline-secondary se queda en
   3,8:1 sobre la lavanda de las cabeceras de tarjeta, por debajo del mínimo del
   texto, y el texto suave de la paleta tampoco llega (4,2:1). Va ese mismo tono un
   escalón más oscuro: 5,7:1 sobre la lavanda y 7:1 sobre blanco. Con el ratón encima
   se rellena de ese gris con el texto blanco de Bootstrap, y pulsado baja otro
   escalón, como el primario. El tema oscuro tiene su propia regla más abajo. */
html:not([data-tema="oscuro"]) .btn-outline-secondary {
    --bs-btn-color: #55557A;
    --bs-btn-border-color: #55557A;
    --bs-btn-hover-bg: #55557A;
    --bs-btn-hover-border-color: #55557A;
    --bs-btn-active-bg: #424263;
    --bs-btn-active-border-color: #424263;
    --bs-btn-disabled-color: #55557A;
    --bs-btn-disabled-border-color: #55557A;
}

/* El anillo de foco de los botones de marca sale de --bs-btn-focus-shadow-rgb, que
   Bootstrap fija al compilar con su azul y que ninguna regla de color toca. Se toma
   de --bs-primary-rgb, que sitio.css remapea en cada tema: una sola regla vale para
   los dos y sigue a la paleta si cambia. */
.btn-primary,
.btn-outline-primary {
    --bs-btn-focus-shadow-rgb: var(--bs-primary-rgb);
}

/* El foco de los campos hereda el azul de Bootstrap por la sombra, que no sale de
   ninguna variable de color: se reescribe con el índigo. */
html:not([data-tema="oscuro"]) .form-control:focus,
html:not([data-tema="oscuro"]) .form-select:focus,
html:not([data-tema="oscuro"]) .form-check-input:focus {
    border-color: #A5A0F0;
    box-shadow: 0 0 0 .25rem rgba(79, 70, 229, .25);
}

html:not([data-tema="oscuro"]) .form-check-input:checked {
    background-color: #4F46E5;
    border-color: #4F46E5;
}

/* ─── TABLAS EN MODO CLARO ──────────────────────────
   Las tablas eran blanco sobre blanco: cabecera casi del color del papel, filas sin
   alternar y bordes grises. Aquí toman el tinte azul de la paleta clara.

   El selector excluye el tema oscuro en vez de ir después de él: así el bloque de
   abajo no tiene que deshacer nada de lo de aquí, y cada tema se lee de un vistazo
   en su propio sitio.

   Se trabaja con las variables --bs-table-* de Bootstrap y no con reglas sobre las
   celdas, porque son las que respetan .table-hover, .table-striped y las variantes
   de color sin pelearse con ellas. */
html:not([data-tema="oscuro"]) .table {
    --bs-table-color: #2A2A45;
    --bs-table-border-color: #E0DFF7;
    --bs-table-striped-bg: #FAFAFF;
    --bs-table-striped-color: #2A2A45;
    --bs-table-hover-bg: #F0EEFE;
    --bs-table-hover-color: #312E81;
}

    /* Filas alternas sin tocar el marcado: la mayoría de las tablas del proyecto no
       llevan .table-striped, y añadírsela una a una sería el mismo efecto con más
       trabajo. El tono es el mismo que usa striped, así que las que sí la tienen no
       cambian. */
    html:not([data-tema="oscuro"]) .table > tbody > tr:nth-child(even) > * {
        background-color: #FAFAFF;
    }

    /* Cabecera sin variante de color. Las que ya traen .table-light, .table-dark o
       .table-primary se respetan: eligieron su color a propósito.

       Lavanda SUAVE a propósito: el índigo sólido que probamos antes competía con la
       cabecera de la tarjeta que tiene justo encima y volvía la tabla más pesada de lo
       que aporta. Lo que la separa del cuerpo no es la intensidad del fondo, sino el
       subrayado y las mayúsculas pequeñas. */
    html:not([data-tema="oscuro"]) .table > thead:not([class*="table-"]) > tr > th {
        background-color: #EDEBFD;
        color: #312E81;
        border-bottom: 2px solid #C7D2FE;
        text-transform: uppercase;
        font-size: .78rem;
        letter-spacing: .04em;
        font-weight: 700;
    }

    /* .table-light es la variante más usada del proyecto y en claro es casi blanca:
       se lleva a la misma cabecera que las de arriba, para que todas las tablas de la
       plataforma se lean igual. */
    html:not([data-tema="oscuro"]) .table > thead.table-light > tr > th,
    html:not([data-tema="oscuro"]) .table-light > th,
    html:not([data-tema="oscuro"]) .table-light > td {
        --bs-table-bg: #EDEBFD;
        --bs-table-color: #312E81;
        border-bottom: 2px solid #C7D2FE;
        text-transform: uppercase;
        font-size: .78rem;
        letter-spacing: .04em;
        font-weight: 700;
    }

    /* Enlaces y botones de la cabecera, que en algunas tablas son el propio rótulo
           ordenable: heredan el blanco en vez del color de enlace del tema. */
    html:not([data-tema="oscuro"]) .table > thead > tr > th a,
    html:not([data-tema="oscuro"]) .table > thead > tr > th .btn-link {
        color: inherit;
    }

    /* Los iconos de ordenar y los badges que viven dentro de un <th> NO heredan las
           mayúsculas ni el cuerpo reducido: son marcado, no rótulo. */
    html:not([data-tema="oscuro"]) .table > thead > tr > th .badge {
        text-transform: none;
        letter-spacing: normal;
    }

    /* La primera fila de la tabla pega con la cabecera sólida: una línea la separa sin
       tener que dejar hueco. */
    html:not([data-tema="oscuro"]) .table > tbody > tr:first-child > * {
        border-top-color: #C7D2FE;
    }

/* La tarjeta que envuelve las tablas y el resto de paneles: su borde gris neutro
   desentonaba con las superficies azuladas. */
html:not([data-tema="oscuro"]) .card {
    border-color: #E0DFF7;
}

html:not([data-tema="oscuro"]) .card-header {
    border-bottom-color: #E0DFF7;
}

    /* Cabecera de tarjeta: la que lleva el NOMBRE del bloque ("Referidos", "Historial
       de movimientos"...). En blanco no se distinguía del cuerpo y la tarjeta se leía
       como una hoja suelta.

       DOS COSAS que hicieron falta y que el primer intento no tenía:

       1. El selector excluía cualquier bg-*, y estas cabeceras llevan JUSTAMENTE
          bg-white en el marcado, así que la regla no las alcanzaba. Ahora solo se
          excluyen los fondos de COLOR, que sí eligieron su tono a propósito.

       2. bg-white declara el fondo con !important, así que aunque el selector acertara
          perdería igual. De ahí el !important de aquí: no es un atajo, es la única
          forma de ganarle a una utilidad de Bootstrap.

       Quedan tres niveles: nombre del bloque en índigo suave, cabecera de columnas en
       lavanda con su subrayado, y el cuerpo en blanco. */
    html:not([data-tema="oscuro"]) .card-header:not(.bg-primary):not(.bg-secondary):not(.bg-success):not(.bg-danger):not(.bg-warning):not(.bg-info):not(.bg-dark):not(.edu-cabecera-monedas) {
        background-color: #E0E7FF !important;
        border-bottom: 1px solid #C7D2FE;
    }

    /* El título hereda el índigo oscuro; el icono que lo precede va en el índigo de
           marca, un punto más vivo, que es lo que lo separa del texto. */
    html:not([data-tema="oscuro"]) .card-header:not(.bg-primary):not(.bg-dark):not(.edu-cabecera-monedas) > h1,
    html:not([data-tema="oscuro"]) .card-header:not(.bg-primary):not(.bg-dark):not(.edu-cabecera-monedas) > h2,
    html:not([data-tema="oscuro"]) .card-header:not(.bg-primary):not(.bg-dark):not(.edu-cabecera-monedas) > h3,
    html:not([data-tema="oscuro"]) .card-header:not(.bg-primary):not(.bg-dark):not(.edu-cabecera-monedas) > h4,
    html:not([data-tema="oscuro"]) .card-header:not(.bg-primary):not(.bg-dark):not(.edu-cabecera-monedas) > h5,
    html:not([data-tema="oscuro"]) .card-header:not(.bg-primary):not(.bg-dark):not(.edu-cabecera-monedas) > h6 {
        color: #312E81;
    }

html:not([data-tema="oscuro"]) .card-footer {
    border-top-color: #E0DFF7;
}

/* Títulos y encabezados de secciones legibles (claro suave, no blanco) */
[data-tema="oscuro"] h1,
[data-tema="oscuro"] h2,
[data-tema="oscuro"] h3,
[data-tema="oscuro"] h4,
[data-tema="oscuro"] h5,
[data-tema="oscuro"] h6,
[data-tema="oscuro"] .h1,
[data-tema="oscuro"] .h2,
[data-tema="oscuro"] .h3,
[data-tema="oscuro"] .h4,
[data-tema="oscuro"] .h5,
[data-tema="oscuro"] .h6,
[data-tema="oscuro"] .card-title,
[data-tema="oscuro"] .modal-title {
    color: #f1f5f9;
}

[data-tema="oscuro"] .card {
    background-color: #1e293b;
    border-color: #334155;
    color: #cbd5e1;
}

[data-tema="oscuro"] .table {
    --bs-table-bg: transparent;
    --bs-table-color: #e2e8f0;
    --bs-table-color-type: initial;
    --bs-table-striped-color: #e2e8f0;
    --bs-table-hover-color: #f1f5f9;
    --bs-table-hover-bg: rgba(255, 255, 255, .06);
    --bs-table-border-color: #334155;
    color: #e2e8f0;
}

[data-tema="oscuro"] .navbar {
    background-color: #0f172a !important;
}

/* Sobre el fondo oscuro el botón usa un índigo más luminoso que el de marca, para que
   no se apague contra la página: el más claro que aún deja su texto blanco en 4,5:1.
   Al pasar el ratón y al pulsar baja un escalón cada vez, como en el tema claro:
   aclararlo dejaría el blanco ilegible. */
[data-tema="oscuro"] .btn-primary {
    --bs-btn-bg: #5F60EF;
    --bs-btn-border-color: #5F60EF;
    --bs-btn-hover-bg: #4F46E5;
    --bs-btn-hover-border-color: #4F46E5;
    --bs-btn-active-bg: #4338CA;
    --bs-btn-active-border-color: #4338CA;
    /* Deshabilitado, el mismo índigo que en reposo, que .btn ya atenúa con su
       opacidad: sin estas dos variables toma el azul con que Bootstrap compila
       .btn-primary. */
    --bs-btn-disabled-bg: #5F60EF;
    --bs-btn-disabled-border-color: #5F60EF;
}

/* Pulsado —también la opción marcada de un grupo .btn-check— y deshabilitado tienen
   sus propias variables, que sin reescribir salen con el azul de Bootstrap. Con el
   ratón encima se rellena con el índigo del .btn-primary y, pulsado, baja al escalón
   siguiente, como en el tema claro; los dos con texto blanco. */
[data-tema="oscuro"] .btn-outline-primary {
    --bs-btn-color: #A5B4FC;
    --bs-btn-border-color: #5F60EF;
    --bs-btn-hover-bg: #5F60EF;
    --bs-btn-hover-border-color: #5F60EF;
    --bs-btn-hover-color: #fff;
    --bs-btn-active-bg: #4F46E5;
    --bs-btn-active-border-color: #4F46E5;
    --bs-btn-active-color: #fff;
    --bs-btn-disabled-color: #A5B4FC;
    --bs-btn-disabled-border-color: #5F60EF;
}

/* El gris con que Bootstrap compila .btn-outline-secondary está pensado para papel
   blanco: sobre las superficies de este tema su texto se queda en 3:1. Toma el texto
   suave de la paleta, que ya se voltea; con el ratón encima se rellena de ese mismo
   gris y el texto pasa al fondo de la página, porque el blanco sobre ese gris no se
   leería. */
[data-tema="oscuro"] .btn-outline-secondary {
    --bs-btn-color: var(--edu-texto-suave);
    --bs-btn-border-color: var(--edu-texto-suave);
    --bs-btn-hover-color: var(--edu-fondo);
    --bs-btn-hover-bg: var(--edu-texto-suave);
    --bs-btn-hover-border-color: var(--edu-texto-suave);
    --bs-btn-active-color: var(--edu-fondo);
    --bs-btn-active-bg: var(--edu-texto-suave);
    --bs-btn-active-border-color: var(--edu-texto-suave);
    --bs-btn-disabled-color: var(--edu-texto-suave);
    --bs-btn-disabled-border-color: var(--edu-texto-suave);
}

/* El aspa de cerrar es un dibujo negro que Bootstrap aclara con un filtro solo bajo
   data-bs-theme="dark". Aquí el interruptor es data-tema, así que seguía negra y a
   media opacidad sobre los modales, las alertas y los paneles oscuros, donde no se
   veía. Lleva el mismo filtro que la librería usa en su tema oscuro, con su valor de
   respaldo por si la variable faltara. */
[data-tema="oscuro"] .btn-close {
    filter: var(--bs-btn-close-white-filter, invert(1) grayscale(100%) brightness(200%));
}

/* Salvo sobre los rellenos que el tema no oscurece: el amarillo de aviso y el cian
   de información siguen siendo claros en oscuro, y ahí el aspa blanca no se ve.
   Sobre ellos conserva su dibujo negro. */
[data-tema="oscuro"] .bg-warning .btn-close,
[data-tema="oscuro"] .bg-info .btn-close {
    filter: none;
}

/* === Cabeceras de marca en tema oscuro ===
       El valor es el índigo PROFUNDO de la marca, el mismo que --edu-oscuro en la
       paleta clara. Lleva !important porque las utilidades de fondo de Bootstrap lo
       llevan; la especificidad sola no les gana. */
[data-tema="oscuro"] .card-header.bg-primary,
[data-tema="oscuro"] .modal-header.bg-primary {
    background-color: #312E81 !important;
}

/* Rellenos de marca en tema oscuro. sitio.css aclara el índigo para que el texto y
   los enlaces se lean sobre el fondo oscuro, pero un relleno lleva texto blanco
   encima —insignias, avatares, el aviso de información— y sobre ese índigo claro el
   blanco se queda en 3:1. Toman el índigo del .btn-primary de este tema, #5F60EF,
   que lo sostiene en 4,8:1.

   El alfa sale de --bs-bg-opacity para que bg-opacity-* siga dando un tinte suave y
   no un relleno sólido, y va con !important porque la utilidad de Bootstrap lo
   lleva. La barra y las cabeceras de tarjeta y de modal quedan fuera: tienen su
   propio fondo en este tema. */
[data-tema="oscuro"] .bg-primary:not(.navbar):not(.card-header):not(.modal-header),
[data-tema="oscuro"] .text-bg-primary {
    background-color: rgba(95, 96, 239, var(--bs-bg-opacity, 1)) !important;
}

/* Etiquetas y textos de formularios legibles sobre fondo oscuro */
[data-tema="oscuro"] .form-label,
[data-tema="oscuro"] .col-form-label,
[data-tema="oscuro"] .form-check-label,
[data-tema="oscuro"] label {
    color: #e2e8f0;
}

/* Textos secundarios. Bootstrap fija el gris de .text-secondary al compilar, pensado
   para papel blanco: sobre las superficies de este tema da 3:1, por debajo del
   contraste mínimo del texto, así que va al mismo tono que .text-muted. */
[data-tema="oscuro"] .form-text,
[data-tema="oscuro"] .text-muted,
[data-tema="oscuro"] .text-secondary {
    color: #94a3b8 !important;
}

/* Los inputs permanecen blancos: el texto escrito debe ser oscuro y visible */
[data-tema="oscuro"] .form-control,
[data-tema="oscuro"] .form-select,
[data-tema="oscuro"] .form-control:focus,
[data-tema="oscuro"] .form-select:focus {
    color: #212529;
}

    [data-tema="oscuro"] .form-control::placeholder {
        color: #6c757d;
    }

/* Texto "body" legible sobre tarjetas oscuras */
[data-tema="oscuro"] .text-body,
[data-tema="oscuro"] .text-dark:not(.badge):not(.bg-warning):not(.bg-info):not(.bg-light) {
    color: #e2e8f0 !important;
}

/* Superficies claras reutilizadas como oscuras */
[data-tema="oscuro"] .bg-white {
    background-color: #1e293b !important;
    color: #e2e8f0;
}

/* Paneles y celdas con .bg-light (paneles de modales, celdas de horario,
   secciones, etc.). Se excluyen los inputs .form-control, cuyo texto
   permanece oscuro y por tanto deben conservar fondo claro. */
[data-tema="oscuro"] .bg-light:not(.form-control):not(.badge) {
    background-color: #1e293b !important;
    color: #e2e8f0;
}

/* Badges .bg-light: fondo oscuro suave con texto legible */
[data-tema="oscuro"] .badge.bg-light {
    background-color: #334155 !important;
    color: #e2e8f0 !important;
    border-color: #475569 !important;
}

[data-tema="oscuro"] .card-header.bg-white {
    border-color: #334155;
}

/* Cabeceras de tabla claras */
[data-tema="oscuro"] .table-light,
[data-tema="oscuro"] .table-light > th,
[data-tema="oscuro"] .table-light > td,
[data-tema="oscuro"] .table > thead.table-light th {
    background-color: #334155;
    color: #e2e8f0;
    border-color: #475569;
}

/* Menús y ventanas emergentes */
[data-tema="oscuro"] .dropdown-menu {
    background-color: #1e293b;
    border-color: #334155;
}

[data-tema="oscuro"] .dropdown-item {
    color: #e2e8f0;
}

    [data-tema="oscuro"] .dropdown-item:hover,
    [data-tema="oscuro"] .dropdown-item:focus {
        background-color: #334155;
        color: #fff;
    }

[data-tema="oscuro"] .modal-content {
    background-color: #1e293b;
    color: #e2e8f0;
}

[data-tema="oscuro"] .list-group-item {
    background-color: #1e293b;
    border-color: #334155;
    color: #e2e8f0;
}

/* Las dos líneas de la hora salen de variables de Bootstrap y ninguna de las
       dos acaba donde debería en este tema: --bs-body-color sí se remapea, pero a
       #cbd5e1, un punto por debajo del texto de la tarjeta; y --bs-secondary-color
       NO se remapea en ningún sitio, sigue siendo el rgba oscuro del tema claro, o
       sea texto casi negro sobre la tarjeta. Es la línea que se perdía del todo. */
[data-tema="oscuro"] .edu-clases__hora12 {
    color: #E2E8F0;
}

[data-tema="oscuro"] .edu-clases__hora24 {
    color: #94A3B8;
}

/* La ganancia es un pastel claro con texto oscuro, escrito para papel blanco: aquí
       se invierte, fondo profundo y texto claro, conservando su verde para que se
       siga reconociendo de un vistazo. */
[data-tema="oscuro"] .edu-clases__ganancia {
    background-color: #14532D;
    color: #BBF7D0;
    border-color: #166534;
}

/* ─── Conversación en modo oscuro ───────────────────
   El hilo se escribió con blancos y azules pastel fijos, pensados para página
   clara. En oscuro el texto sí se aclaraba —lo hereda del body— pero el fondo de
   las burbujas seguía siendo blanco: letras claras sobre blanco, ilegibles. Cada
   superficie fija necesita aquí su equivalente oscuro. */
[data-tema="oscuro"] .edu-clases__chat {
    background-color: #0f172a;
}

[data-tema="oscuro"] .edu-clases__burbuja {
    background-color: #1e293b;
    border-color: #334155;
    color: #e2e8f0;
}

/* La burbuja propia mantiene el azul que la distingue, pero oscurecido hasta que
   el texto claro contrasta encima. */
[data-tema="oscuro"] .edu-clases__msg--mio .edu-clases__burbuja {
    background-color: #1e3a5f;
    border-color: #2c5282;
    color: #e2e8f0;
}

/* El azul de marca sobre la burbuja oscura queda apagado: se sube un tono. */
[data-tema="oscuro"] .edu-clases__autor {
    color: #7dd3fc;
}

[data-tema="oscuro"] .edu-clases__hora {
    color: #94a3b8;
}

/* Separador de fecha: la píldora clara con texto gris desaparecía sobre el hilo
   oscuro. */
[data-tema="oscuro"] .edu-clases__fecha-sep {
    background-color: #334155;
    color: #cbd5e1;
}

/* ─── Avisos (.alert-*) en modo oscuro ──────────────────
   Bootstrap 5.3 fija el color, el fondo y el borde de cada variante al COMPILAR,
   y solo los voltea con data-bs-theme="dark". Aquí el interruptor es data-tema,
   así que ninguna alerta conmutaba: seguían siendo los pasteles pensados para
   papel blanco, con su texto oscuro, sobre las superficies del tema oscuro. Se
   veía en el modal de retiro, pero le pasaba a TODAS las pantallas.

   Cada variante se redefine con las variables -text-emphasis / -bg-subtle /
   -border-subtle, que sitio.css ya remapea a los valores del tema oscuro de la
   propia librería. Así estas reglas no inventan ni un color: reutilizan los que
   ya están, y el día que cambie la paleta oscura cambian con ella.

   Las alertas propias del proyecto —.edu-alerta-*— no entran aquí: tienen su
   contraparte en sitio.css, junto a su definición clara.
   ─────────────────────────────────────────────────────── */
[data-tema="oscuro"] .alert-primary {
    --bs-alert-color: var(--bs-primary-text-emphasis);
    --bs-alert-bg: var(--bs-primary-bg-subtle);
    --bs-alert-border-color: var(--bs-primary-border-subtle);
    --bs-alert-link-color: var(--bs-primary-text-emphasis);
}

[data-tema="oscuro"] .alert-secondary {
    --bs-alert-color: var(--bs-secondary-text-emphasis);
    --bs-alert-bg: var(--bs-secondary-bg-subtle);
    --bs-alert-border-color: var(--bs-secondary-border-subtle);
    --bs-alert-link-color: var(--bs-secondary-text-emphasis);
}

[data-tema="oscuro"] .alert-success {
    --bs-alert-color: var(--bs-success-text-emphasis);
    --bs-alert-bg: var(--bs-success-bg-subtle);
    --bs-alert-border-color: var(--bs-success-border-subtle);
    --bs-alert-link-color: var(--bs-success-text-emphasis);
}

[data-tema="oscuro"] .alert-danger {
    --bs-alert-color: var(--bs-danger-text-emphasis);
    --bs-alert-bg: var(--bs-danger-bg-subtle);
    --bs-alert-border-color: var(--bs-danger-border-subtle);
    --bs-alert-link-color: var(--bs-danger-text-emphasis);
}

[data-tema="oscuro"] .alert-warning {
    --bs-alert-color: var(--bs-warning-text-emphasis);
    --bs-alert-bg: var(--bs-warning-bg-subtle);
    --bs-alert-border-color: var(--bs-warning-border-subtle);
    --bs-alert-link-color: var(--bs-warning-text-emphasis);
}

[data-tema="oscuro"] .alert-info {
    --bs-alert-color: var(--bs-info-text-emphasis);
    --bs-alert-bg: var(--bs-info-bg-subtle);
    --bs-alert-border-color: var(--bs-info-border-subtle);
    --bs-alert-link-color: var(--bs-info-text-emphasis);
}

[data-tema="oscuro"] .alert-light {
    --bs-alert-color: var(--bs-light-text-emphasis);
    --bs-alert-bg: var(--bs-light-bg-subtle);
    --bs-alert-border-color: var(--bs-light-border-subtle);
    --bs-alert-link-color: var(--bs-light-text-emphasis);
}

[data-tema="oscuro"] .alert-dark {
    --bs-alert-color: var(--bs-dark-text-emphasis);
    --bs-alert-bg: var(--bs-dark-bg-subtle);
    --bs-alert-border-color: var(--bs-dark-border-subtle);
    --bs-alert-link-color: var(--bs-dark-text-emphasis);
}

/* ─── Pestañas (.nav-tabs) en modo oscuro ───────────────
   Bootstrap pinta la pestaña ACTIVA con background-color: var(--bs-body-bg) —que
   aquí no se remapea y sigue siendo blanco— y su texto con var(--bs-emphasis-color),
   que arriba sí pasa a #f1f5f9. Resultado: pastilla blanca con letras casi blancas,
   ilegible. Se ve en Preguntas y en Editar mi perfil, y en cualquier pantalla con
   pestañas, porque son las clases de la librería.

   Se resuelve dándole a la pestaña sus colores y NO remapeando --bs-body-bg: esa
   variable la usan además modales, menús, tarjetas y campos, que este archivo ya
   resuelve uno a uno más arriba, y las dos versiones se pisarían.

   La activa se pinta con el mismo #1e293b de las tarjetas: la pestaña y el panel
   que abre son la misma superficie, y así se leen como una sola pieza. */
[data-tema="oscuro"] .nav-tabs {
    border-bottom-color: #334155;
}

    /* Inactiva: legible pero en segundo plano. */
    [data-tema="oscuro"] .nav-tabs .nav-link {
        color: #94a3b8;
        background-color: transparent;
        border-color: transparent;
    }

        [data-tema="oscuro"] .nav-tabs .nav-link:hover,
        [data-tema="oscuro"] .nav-tabs .nav-link:focus {
            color: #e2e8f0;
            /* El borde superior y los laterales insinúan la pastilla antes de
               pulsarla; el de abajo se deja transparente para no cortar la línea
               de la fila. */
            border-color: #334155 #334155 transparent;
        }

        [data-tema="oscuro"] .nav-tabs .nav-link.active {
            color: #f1f5f9;
            background-color: #1e293b;
            /* El borde inferior desaparece contra el fondo de la pastilla: es lo que
           une visualmente la pestaña con su panel. */
            border-color: #334155 #334155 #1e293b;
        }

        /* Deshabilitada: se distingue de la inactiva sin llegar a perderse. */
        [data-tema="oscuro"] .nav-tabs .nav-link.disabled {
            color: #64748b;
            background-color: transparent;
            border-color: transparent;
        }