/* Tema default: lo poco que es nuestro y Bootstrap no trae.
   NO se regenera (base.css sí): este fichero se edita a mano.

   Son clases que usan las plantillas del proyecto y que hasta ahora venían de
   front.css, el CSS del tema base. Mientras el tema siga cargando front.css no
   se nota; el día que deje de cargarlo —que es el plan cuando estén todas las
   plantillas— sin esto el campo trampa del formulario se vería y el enlace de
   saltar al contenido aparecería en mitad de la página. */

/* ---------------------------------------------------------------- Encuadre

   Que todas las fotos de una fila midan lo mismo, sin tocar los ficheros: el
   hueco es 4:3 (la proporción de 1024x768) y la foto lo rellena recortándose
   por el centro. Hace falta porque el contenido real trae de todo, desde
   verticales de 0,31 hasta tiras de 10:1.

   NO se usan las utilidades .ratio de Bootstrap, y el motivo importa: .ratio
   posiciona en absoluto a su HIJO DIRECTO, que en nuestras figuras es el <a>
   que envuelve la imagen. El enlace se estiraba al hueco y la foto se quedaba
   dentro con su tamaño natural. Y aunque se le diera altura, el tema trae
   `figure img { height: auto !important }`, que gana a cualquier regla sin
   !important. De ahí los dos !important de abajo: no son pereza, son la única
   forma de ganar a esa declaración sin editar base.css, que se regenera. */
.encuadre-4x3 {
	position: relative;
	display: block;
	width: 100%;
	overflow: hidden;
	aspect-ratio: 4 / 3;
}

/* El enlace intermedio, si lo hay, ocupa todo el hueco. */
.encuadre-4x3 > a {
	display: block;
	width: 100%;
	height: 100%;
}

.encuadre-4x3 img {
	width: 100% !important;
	height: 100% !important;
	object-fit: cover;
	object-position: center;
	margin-bottom: 0;
}

/* Sección de la portada sin imagen (_carrusel-secciones.php, 17/10/2026): el
   hueco 4:3 del color clarito del tema con el logo del aula en medio,
   entero y pequeño, para que la tarjeta mida lo mismo que las demás. */
.seccion-sin-imagen {
	background: var(--bs-soft-primary, #fef0f1);
}

.seccion-sin-imagen > a {
	display: flex;
	align-items: center;
	justify-content: center;
}

.seccion-sin-imagen img.seccion-logo {
	width: 35% !important;
	height: 50% !important;
	object-fit: contain;
}

/* Carrusel de carteles de la portada (_carrusel-carteles.php, 18/10/2026):
   hueco 2:3 de cartel impreso; el cartel entero, sin recortar, sobre el
   clarito del tema. */
.cartel-portada {
	display: block;
	aspect-ratio: 2 / 3;
	overflow: hidden;
	border-radius: .4rem;
	background: var(--bs-soft-primary, #f2f2f2);
	box-shadow: 0 .25rem 1.25rem rgba(30, 34, 40, .12);
}

.cartel-portada img {
	width: 100%;
	height: 100%;
	object-fit: contain;
}

/* El cartel junto al texto de su página (_cartel.php, 18/10/2026): entero,
   con sombra, y quieto al bajar mientras se lee el texto. */
.cartel-pagina {
	box-shadow: 0 .25rem 1.25rem rgba(30, 34, 40, .15);
}

.cartel-pagina img {
	display: block;
	width: 100%;
	height: auto;
}

@media (min-width: 992px) {
	.cartel-pagina {
		position: sticky;
		top: 7rem;
	}
}

.carrusel-carteles .swiper {
	padding: .5rem .25rem 1.5rem;
}

/* Al pie del cuerpo de una página (_hermanas.php), sin el margen de abajo del
   carrusel: ya está el relleno de la caja. */
.hermanas-pagina .carrusel-secciones {
	margin-bottom: 0 !important;
}

/* La sombra de la tarjeta no se corta contra el borde del carrusel. */
.carrusel-secciones .swiper {
	padding: .5rem .25rem 1.5rem;
}

/* El rótulo que el tema enseña al pasar por encima sigue centrado en el hueco. */
.encuadre-4x3 figcaption {
	z-index: 2;
}

/* El campo trampa del formulario de contacto: invisible para quien navega,
   pero presente para un robot que rellena todo lo que encuentra (P34).
   Fuera de pantalla, no display:none, para que los robots no lo descarten. */
.trampa {
	position: absolute;
	left: -10000px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

/* Texto solo para lectores de pantalla. */
.oculto-visual {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
}

/* Saltar al contenido: escondido hasta que se le da el foco con el tabulador. */
.saltar {
	position: absolute;
	left: -9999px;
	top: 8px;
	z-index: 100;
	padding: 8px 14px;
	background: var(--bs-white);
	color: var(--bs-primary);
	border-radius: .3rem;
}

.saltar:focus {
	left: 8px;
}

/*
 * Iconos grandes en la lista de enlaces y documentos de la ficha.
 *
 * Jordi los quería del tamaño de los de career.html (2,2 rem). Allí son SVG
 * inyectados por JavaScript, con un fichero por icono; aquí se consigue el
 * mismo efecto agrandando el círculo que ya trae `icon-list bullet-bg`, sin
 * dependencias nuevas y conservando los ocho iconos distintos de Unicons
 * (hoja, tabla, caja, trofeo...), que los SVG de Sandbox no cubren: de sus 126
 * solo cuatro valen para nuestras familias.
 *
 * Las tres medidas van juntas y por eso se cambian las tres: el círculo
 * (1rem -> 2rem), el icono de dentro (.8rem -> 1.1rem) y el hueco que el <li>
 * reserva a la izquierda (1.5rem -> 2.6rem). Si se cambia una sola, el icono se
 * sale de su sitio o pisa el texto.
 *
 * `top` baja a 0 para que el círculo quede alineado con la primera línea del
 * texto: `base.css` lo sube a .2rem porque allí el círculo es menor que la
 * línea, y al agrandarlo ese desplazamiento lo descuadra.
 *
 * Va con la clase propia `.iconos-grandes` y no pisando `.icon-list` a secas:
 * así el resto de listas del tema (la portada, el lateral) siguen como están.
 */
/*
 * Con iconos grandes no se posiciona el círculo «a tantos rem del borde»: se
 * centra de verdad. `base.css` lo saca del flujo (`position:absolute`) y lo
 * sitúa con un `top` fijo pensado para un círculo de 1 rem; a 2 rem eso
 * descuadra, y calcularlo a partir del `line-height` tampoco vale, porque el
 * texto de la tarjeta no hereda el del body y el número deja de cuadrar.
 *
 * Así que el <li> pasa a ser flex: el icono vuelve al flujo, `align-items:
 * center` lo alinea con el texto sea cual sea su altura, y el hueco lo da el
 * `gap` en vez de un `padding-left` calculado a mano. Sin números mágicos.
 */
.icon-list.iconos-grandes.bullet-bg li {
	display: flex;
	align-items: center;
	gap: .75rem;
	padding-left: 0;
}

.icon-list.iconos-grandes.bullet-bg i {
	/* Fuera del posicionamiento absoluto de base.css: ahora lo coloca el flex
	   del <li>. `flex-shrink` evita que el círculo se aplaste cuando el texto
	   del enlace es largo, que es el caso normal aquí. */
	position: static;
	flex-shrink: 0;
	width: 2rem;
	height: 2rem;
	font-size: 1.1rem;
}

/*
 * El enlace, en oscuro y sin resaltar; el color del tema se reserva para el
 * hover. Lo pidió Jordi el 18/09/2026, y el icono ya marca de qué va cada línea.
 *
 * Dos precisiones de lo que hay debajo, las dos medidas en base.css:
 *
 *   - El «negro» del tema no es #000. El texto del cuerpo es #60697b (gris
 *     azulado) y el de los títulos #343f52. Se usa el de los títulos: es el
 *     oscuro con el que la plantilla pinta lo importante.
 *   - Lo que parecía negrita no lo era: `--bs-body-font-weight` es **500** para
 *     todo el cuerpo, y ningún `a{}` lo sube. «Sin negrita» aquí es bajar a 400,
 *     el peso normal de Urbanist.
 *
 * El hover hay que escribirlo entero porque `--bs-link-color` y
 * `--bs-link-hover-color` son el mismo #3f78e0: de serie, el enlace no cambia al
 * pasar por encima. `var(--bs-primary)` lo hace seguir el color de cada aula.
 */
.icon-list.iconos-grandes a {
	color: var(--bs-heading-color);
	font-weight: 400;
}

.icon-list.iconos-grandes a:hover,
.icon-list.iconos-grandes a:focus-visible {
	color: var(--bs-primary);
}

/*
 * Migas de la ficha: más aire alrededor del separador.
 *
 * `base.css` deja .5rem a cada lado del chevron, y con el texto pegado se lee
 * apretado —Jordi: «no me gusta el espaciado del breadcrumbs»—. Se sube a
 * .7rem y se le da algo de altura a la línea, que es lo que separa las migas
 * de la fecha cuando las dos caen en la misma fila.
 *
 * El margen inferior no se toca aquí: el <ol> ya lleva `mb-0` (utilidad de
 * Bootstrap, con !important) y el hueco hasta la imagen lo pone el contenedor.
 */
.breadcrumb-nav .breadcrumb-item + .breadcrumb-item {
	padding-left: .7rem;
}

.breadcrumb-nav .breadcrumb-item + .breadcrumb-item::before {
	padding-right: .7rem;
}

.breadcrumb-nav .breadcrumb {
	line-height: 1.8;
}

/*
 * Galería de la ficha: todos los slides de la misma altura, y la foto dentro.
 *
 * Sin esto, una imagen vertical rompe la fila: `base.css` trae
 * `.swiper-container .swiper img{width:100%;height:auto}`, que fija el ancho y
 * deja el alto libre, así que `cartel.jpg` (1496 × 2181) ocupa 1,45 veces su
 * ancho de alto mientras las apaisadas ocupan 0,66. Jordi lo vio en cuanto
 * subió una foto en vertical (18/09/2026).
 *
 * La solución es la que él propuso: el slide manda, no la foto. El `figure`
 * lleva una altura fija y la imagen se encaja dentro con `object-fit:contain`,
 * que respeta la proporción y **no recorta** —una foto vertical enseña bandas a
 * los lados, que para un cartel es lo correcto: recortarlo se comería el texto—.
 *
 * Los dos `!important` no son capricho: `base.css` cierra el alto con
 * `figure img{height:auto!important}` y solo se le gana así. Es la misma pelea
 * que ya hubo con `.encuadre-4x3`.
 *
 * El `<a>` del visor necesita ser bloque y ocupar la altura completa, o la
 * imagen no tendría contra qué medirse: es un elemento en línea y se ajustaría
 * a su contenido. Tercera vez que este enlace da guerra.
 */
.swiper-container .galeria-ficha {
	height: 17rem;
	overflow: hidden;
	/* Un respiro alrededor de la foto, para que no toque los bordes del slide
	   (Jordi, 18/09/2026). Con `border-box` el relleno se descuenta de los
	   17rem en vez de sumarse, así que todos los slides siguen midiendo lo
	   mismo y la fila no se descuadra. */
	box-sizing: border-box;
	padding: .75rem;
	background: var(--bs-gray-200);
}

.swiper-container .galeria-ficha > a {
	display: block;
	height: 100%;
}

.swiper-container .galeria-ficha img {
	width: 100%;
	height: 100% !important;
	object-fit: contain;
	/* El gris lo pone el `figure`, que es quien tiene el relleno: si lo llevara
	   también la imagen, el marco se vería partido en dos tonos al ampliarse
	   con el `hover-scale`. */
}

/* ------------------------------------------------------------------ PRUEBA
 *
 * Fondo del aula a pantalla completa y fijo al hacer scroll.
 *
 * **Prueba visual del 18/09/2026, CONSERVADA y desactivada.** A Jordi «no le
 * desagrada» y pidió guardarla sin activarla: se ve SOLO con `?fondo=fijo` en
 * la URL y solo en entorno desarrollo, así que sin el parámetro la página es
 * exactamente la de siempre y en producción no existe.
 *
 * Para adoptarla de verdad: quitar el `?fondo=fijo` de `pagina.ficha.php` y
 * poner la clase en el <body> siempre. Para tirarla: borrar este bloque, el
 * <body> de `_cabecera.php`, `fondoFijoDePrueba()` de default.js y el bloque
 * de `pagina.ficha.php`.
 *
 * Qué hace falta tocar, y por qué:
 *
 *   - La foto va en el <body>, no en la cabecera. `.image-wrapper` la pone con
 *     `cover` y centrada; aquí se repite eso más `fixed`, que es lo que la deja
 *     quieta mientras el contenido se desplaza por encima.
 *   - La cabecera pierde su propia foto y su velo, o se verían dos capas de la
 *     misma imagen, una fija y otra no.
 *   - `.bg-light` pinta su color con `!important` y taparía el fondo justo
 *     donde empieza el contenido: se vuelve transparente.
 *   - La tarjeta blanca NO se toca: sobre una foto a pantalla completa el texto
 *     necesita su fondo para poder leerse.
 */
body.fondo-fijo {
	/* Sin imagen (17/10/2026), el color: el oscuro de la paleta
	   personalizada (--color-fondo-aula, Paleta.php) o, con las del tema,
	   el principal muy oscurecido. Con imagen, la imagen lo tapa. */
	background-color: var(--color-fondo-aula, color-mix(in srgb, var(--bs-primary) 30%, #12151b));
	background-image: var(--fondo-aula);
	background-repeat: no-repeat;
	background-position: center top;   /* como .image-wrapper, más abajo */
	background-size: cover;
	background-attachment: fixed;
}

/* Las páginas de aula64, fuera de toda aula (Jordi, 25/10/2026: «usa los
   colores de aula lúdica. No me gusta el negro»): el azul de la paleta
   `blue` (Aula::ESTILO_CONTENEDOR), apenas oscurecido para que la barra y el
   pie en blanco se lean, en vez del casi negro de arriba. */
body.fondo-fijo.sin-aula {
	--color-fondo-aula: color-mix(in srgb, var(--bs-primary) 78%, #0b2350);
	/* Su fondo (Jordi, 25/10/2026): juegos de colores sobre azul. Desde aquí y
	   no con `data-fondo-fijo`, así sale también en el instalador, que no
	   carga default.js. El color de arriba queda mientras se carga. */
	--fondo-aula: url("img/marca/aula64-bg.jpg");
}

/* La imagen de fondo del aula, arriba y no en el centro (Jordi,
   11/10/2026). base.css la centra en los dos ejes; con `cover` en una franja
   baja como la cabecera, eso recortaba la parte de arriba de la foto, que es
   donde suele estar lo que importa (caras, el cielo de un paisaje...).
   Centrada en horizontal, pegada arriba en vertical. `.image-wrapper` solo la
   usan las franjas con la foto del aula (cabeceras, pie, portada
   lateral, gestor) y la cabecera de un grupo con imagen propia. */
.image-wrapper {
	background-position: center top;
}

/* `section` y no `.wrapper` a secas: el menú es un <header class="wrapper
   bg-light"> y el selector amplio lo dejaba transparente también —Jordi lo vio
   enseguida: «el menú también es transparente y se ve mal»—. */
body.fondo-fijo section.wrapper.bg-light,
body.fondo-fijo section.wrapper.bg-image {
	background-color: transparent !important;
	background-image: none !important;
}

/* El velo de la cabecera sobra: el fondo ya va oscurecido por su cuenta.
   Solo el de las SECCIONES (cabeceras): las fotos del carrusel de destacadas
   (`.swiper-slide.bg-overlay`) lo necesitan, o su título no se lee sobre una
   foto clara (12/10/2026). */
body.fondo-fijo section.wrapper.bg-overlay:before {
	display: none;
}

/* Un velo único sobre toda la página, para que el texto blanco de la cabecera
   siga leyéndose sobre cualquier foto. A PRUEBA sin velo (Jordi, 13/10/2026:
   «quiero ver cómo queda»); antes, `rgba(30, 34, 40, .45)`. */
body.fondo-fijo::before {
	content: "";
	position: fixed;
	inset: 0;
	z-index: -1;
	background: rgba(30, 34, 40, 0);
}

/* ------------------------------------------------- Rejilla de tres por fila

   Retoques del 18/09/2026, cuando novedades pasó a tres tarjetas por fila
   dentro del cuerpo blanco. Solo se aplican donde la plantilla pide esas
   clases (_tarjetas.php con $porFila >= 3): la portada, la agenda y las
   subpáginas siguen con dos por fila y no se enteran de esto.

   El pie de la tarjeta: .grid-view article .card-footer lo deja en
   1.25rem 1.75rem, que para una sola fecha y una tarjeta estrecha es mucho.
   Se aprieta y se alinea con el relleno del cuerpo, que ahora es menor. */
.grid-view article .card-footer.pie-ajustado {
	padding: .6rem 1rem;
}

@media (min-width: 768px) {
	.grid-view article .card-footer.pie-ajustado {
		padding: .7rem 1.25rem;
	}
}

/* ------------------------------------------------------ Paginador sin marco

   .pagination lleva sombra propia, y dentro de la tarjeta blanca esa sombra se
   leía como una caja con marco cruzando el ancho entero (Jordi, 18/09/2026:
   «quítale el contenedor blanco con marco que cubre el ancho al 100%»).

   Se quita SOLO esa sombra, la del contenedor. Los números conservan su fondo
   blanco, su borde y su sombra, que es como los viste la plantilla: el primer
   intento se los quitó también y no era lo pedido (Jordi: «has quitado todos
   los bordes, solo quería quitar el de la caja»). De ahí que esta regla sea de
   una sola línea y no toque .page-link para nada. */
.paginador-limpio .pagination {
	box-shadow: none;
}

/* ------------------------------- Aire de la tarjeta con tres por fila

   Medido, no a ojo (Jordi, 18/09/2026: «demasiados márgenes y el interlineado
   enorme»). Lo que había, leído de base.css:

     - .grid-view article .card-body -> padding: 1.75rem 1.75rem 1rem
     - --bs-body-line-height: 1.7 sobre 0.8rem  = ~21,8px de línea
     - h5 -> line-height: 1.5, y la plantilla le pone mt-1 mb-3 (1rem abajo)
     - p  -> margin-bottom: 1rem, colgando del subtítulo sin nada detrás

   OJO con la especificidad: `.grid-view article .card-body` son dos clases mas
   un elemento, y le gana a una utilidad `p-4`. Por eso el relleno se aprieta
   desde aqui y con el mismo peso, no con clases de Bootstrap en la plantilla:
   se veian en el HTML sin hacer nada. Mismo motivo para el interlineado.

   Todo cuelga de .cuerpo-ajustado, que solo pone _tarjetas.php con
   $porFila >= 3: la portada, la agenda y las subpaginas no se enteran. */
.grid-view article .card-body.cuerpo-ajustado {
	padding: 1rem 1rem .75rem;
}

@media (min-width: 768px) {
	.grid-view article .card-body.cuerpo-ajustado {
		padding: 1.15rem 1.15rem .85rem;
	}
}

/* El titulo: 1.5 de interlineado es mucho para dos o tres lineas en una
   tarjeta estrecha, y 1rem de hueco debajo (el mb-3) tambien. */
.cuerpo-ajustado .post-title {
	line-height: 1.3;
	margin-bottom: .4rem !important;   /* gana al mb-3 de la plantilla */
}

/* El subtitulo: 1.7 es interlineado de texto largo, no de un resumen de dos
   lineas. Y el ultimo parrafo no necesita el 1rem de abajo: cierra el cuerpo. */
.cuerpo-ajustado .post-content p {
	line-height: 1.45;
	margin-bottom: 0;
}

/* --------------------------------- Tarjetas de la misma fila, del mismo alto

   Jordi, 18/09/2026: «¿se puede igualar el alto de las cajas que están en la
   misma línea?». Sí, y sin JavaScript ni alturas fijas: solo hay que dejar que
   el flex que ya existe haga su trabajo.

   Lo que ya venía dado de base.css, y por eso esto es tan corto:

     - .row -> display:flex; flex-wrap:wrap, con align-items:stretch por
       omisión, así que cada <article class="col-..."> YA tiene el alto de la
       fila más alta.
     - .card -> flex-direction:column, pero con height:var(--bs-card-height) y
       esa variable SIN definir en ninguna parte, así que se resuelve a auto:
       la tarjeta se queda a su contenido dentro de una columna ya estirada.
       Ese es el único eslabón que faltaba.
     - .card-body -> flex:1 1 auto, que en cuanto la tarjeta llene la columna
       absorbe el espacio sobrante.

   Consecuencia: al estirar la tarjeta, el cuerpo crece y el .card-footer (la
   fecha) baja al fondo, así que las fechas de una misma fila quedan alineadas
   entre sí. Eso es la mitad de lo que se ve como «cajas iguales».

   El desnivel no lo causa la foto —va encuadrada a 4:3 y mide siempre igual—
   sino el título, que ocupa dos o tres líneas según su largo, y las tarjetas
   sin subtítulo.

   La clase la pone _tarjetas.php cuando $porFila >= 3, NO un :has() desde
   aquí. Se probó con `:has(> .card-body.cuerpo-ajustado)` y un respaldo
   @supports, y se descartó: el respaldo tenía que ser más amplio que la regla
   y en navegadores sin :has() habría igualado también la agenda y la portada,
   que no lo piden. Un comportamiento distinto según el navegador es peor que
   uno uniforme. El dato de qué rejilla lleva el diseño nuevo ya lo tiene la
   plantilla; reconstruirlo desde el CSS era rehacer lo que ya se sabe. */
.grid-view article.item .card.alto-igualado {
	height: 100%;
}

/* ------------------------------------------- Actos ya celebrados, en gris

   Jordi, 18/09/2026: «la imagen de los eventos ya pasados la quiero en gris,
   pero al hacer hover que recupere el color».

   Se filtra la IMAGEN, no la tarjeta entera: el título y la fecha siguen
   legibles con su contraste de siempre. Apagar el texto de un acto pasado lo
   dejaría por debajo del 4,5:1 que pide la WCAG.

   La transición no hay que escribirla: `.hover-scale img` ya trae
   `transition:all .35s ease-in-out` en base.css, y el filtro entra en ese
   «all». Así el gris y el zoom del hover van acompasados.

   El hover se engancha en el <article>, no en la figura: así también devuelve
   el color quien llega al enlace del título con el tabulador, que es el mismo
   recorrido pero sin ratón. De ahí el :focus-within. */
.grid-view article.item.acto-pasado figure img {
	filter: grayscale(1);
}

.grid-view article.item.acto-pasado:hover figure img,
.grid-view article.item.acto-pasado:focus-within figure img {
	filter: grayscale(0);
}

/* Quien haya pedido «sin animaciones» en su sistema ve el gris fijo: el cambio
   al pasar por encima es decorativo y aquí no informa de nada que el texto no
   diga ya (la fecha del acto está debajo). */
@media (prefers-reduced-motion: reduce) {
	.grid-view article.item.acto-pasado figure img {
		transition: none;
	}
}

/* --------------------------------------------- Diagrama de ajedrez (FEN)

   Tablero estático a partir de la posición en FEN, para los problemas que
   cuelgan de una página (app/tablas/problema.php).

   Sin librería y sin JavaScript, y el motivo importa: la prueba de /board/ usa
   chessboardjs, que necesita jQuery (57 KB) y carga las piezas como PNG desde
   un CDN. La CSP del front es `script-src self` y `style-src self`, así que
   habría que servir las tres cosas desde public/. Para un diagrama que no se
   mueve, las piezas Unicode (♔♕♖♗♘♙) ya están en cualquier tipografía del
   sistema y pesan cero. chessboardjs se reserva para el día que el visitante
   tenga que mover las piezas, que es lo que esa librería sí sabe hacer.

   El tablero es una rejilla 8x8 con `aspect-ratio: 1`, así que es cuadrado a
   cualquier ancho y se encoge solo en el móvil. Las casillas salen en orden
   desde Front::casillasFen(): fila 8 a 1, columna a a h. */
.diagrama {
	display: grid;
	grid-template-columns: repeat(8, 1fr);
	/*
	 * Las OCHO FILAS declaradas, no implícitas: ese era el fallo por el que el
	 * tablero salía descuadrado (Jordi, 19/09/2026). Con solo
	 * `grid-template-columns`, las filas las crea la rejilla sobre la marcha y
	 * se dimensionan por su contenido —la altura de la glifa de la pieza—,
	 * mientras el ancho de columna sale de dividir el tablero entre ocho. Dos
	 * medidas que no tienen por qué coincidir: casillas rectangulares.
	 *
	 * El `aspect-ratio` del contenedor no lo arreglaba: reparte el alto entre
	 * filas flexibles, y unas filas automáticas no lo son.
	 */
	grid-template-rows: repeat(8, 1fr);
	/*
	 * El tablero se declara contenedor de consulta para que las piezas puedan
	 * medirse contra ÉL (`9cqw` en .diagrama-casilla) y no contra la ventana.
	 * Sin esta línea, `cqw` no tiene contra qué resolver y cae al viewport,
	 * que es justo el problema que se venía a arreglar.
	 */
	container-type: inline-size;
	width: 100%;
	/*
	 * Sin `max-width` fijo: dentro de un slide el tablero tiene que ocupar su
	 * columna entera, y el tope de 22rem lo dejaba pequeño y descentrado en
	 * pantalla ancha. Donde haga falta limitarlo, lo limita su columna.
	 */
	margin-inline: auto;
	/* El borde no es decorativo: sin el marco, la casilla clara del extremo se
	   confunde con el fondo blanco de la tarjeta. */
	border: 1px solid rgba(164, 174, 198, .45);
	border-radius: .2rem;
	overflow: hidden;
}

.diagrama-casilla {
	display: flex;
	align-items: center;
	justify-content: center;
	/*
	 * Cada casilla, cuadrada POR SÍ MISMA. Es lo que de verdad garantiza el
	 * tablero: la columna mide 1/8 del ancho y el `aspect-ratio` le da esa
	 * misma medida de alto, sin depender de la glifa que haya dentro.
	 *
	 * Con las filas a `1fr` arriba es redundante en un tablero completo, y se
	 * deja a propósito: si algún día una fila lleva coordenadas o un hueco
	 * vacío, la casilla sigue siendo cuadrada por su cuenta.
	 */
	aspect-ratio: 1;
	/*
	 * La pieza, relativa a SU CASILLA y no a la ventana. Antes iba con
	 * `clamp(1rem, 4.2vw, 1.9rem)`: `vw` mide el ancho del NAVEGADOR, así que
	 * dentro de la tarjeta —que es mucho más estrecha— las piezas salían
	 * desproporcionadas, grandes en pantalla ancha y pequeñas en móvil,
	 * justo al revés de lo que hace falta. `cqw` mide el ancho del tablero,
	 * que es el contenedor declarado abajo: 9 de cada 100 partes del tablero
	 * es aproximadamente 3/4 de la casilla, que es la proporción con la que
	 * se dibujan las piezas en un diagrama impreso.
	 */
	/*
	 * Ya no hay glifa que dimensionar —la pieza es un <img>, ver
	 * .diagrama-pieza—, pero el tamaño de letra se deja porque el tablero
	 * sigue pudiendo caer a Unicode si una pieza no tuviera imagen.
	 */
	font-size: 9cqw;
	line-height: 1;
	/* Los signos Unicode de ajedrez son negros de trazo; el color lo pone la
	   propia glifa, así que aqui solo se elige el fondo de la casilla. */
	color: #21262c;
	-webkit-user-select: none;
	user-select: none;
}

/*
 * El color de las casillas sale de la PALETA DE EL AULA, no de un par de
 * valores fijos (Jordi, 19/09/2026). Cada aula carga su hoja —red.css,
 * sky.css, green.css…— y lo único que esas hojas redefinen es `--bs-primary`
 * y su familia, así que las dos casillas se derivan de ahí con `color-mix()`:
 * DEMO sale rojiza, Aula Lúdica azulada y Open Marratxí verdosa, sin tocar
 * nada más.
 *
 * Las proporciones están medidas, no puestas a ojo: la casilla clara lleva muy
 * poco color sobre blanco para que la pieza blanca —que es un contorno negro
 * sobre relleno claro— siga recortándose, y la oscura se mezcla con un gris
 * cálido en vez de con negro, porque mezclar con negro apaga los tonos pastel
 * de estas paletas y deja las dos casillas casi iguales.
 *
 * `color-mix()` es de 2023 y lo entienden todos los navegadores al día. Si
 * alguno no lo soporta, se queda con la declaración de respaldo de arriba, que
 * es la madera de siempre: el tablero se ve, solo que sin el color del tema.
 */
.diagrama-clara {
	background: #f0d9b5;
	background: color-mix(in srgb, var(--bs-primary) 12%, #fbf6ef);
}

.diagrama-oscura {
	background: #b58863;
	background: color-mix(in srgb, var(--bs-primary) 55%, #8a7059);
}

/* El pie del diagrama: de quien es el turno y el FEN en crudo, por si alguien
   lo quiere copiar en su analizador. */
.diagrama-pie {
	font-size: .75rem;
	color: #60697b;
	word-break: break-all;
}

/*
 * La pieza, como imagen (mates/piezas, copiadas a img/piezas). Ocupan el 82 %
 * de la casilla: el resto es el aire que en un diagrama impreso separa la
 * pieza de la línea de la casilla. Van al 100 % de alto y ancho de ese hueco
 * con `object-fit: contain`, así que un PNG que no fuera cuadrado no se
 * deformaría.
 *
 * `pointer-events: none` para que arrastrar el carrusel no arrastre la imagen:
 * el navegador deja arrastrar cualquier <img> por omisión y eso se come el
 * gesto de pasar de slide en táctil.
 */
.diagrama-pieza {
	width: 82%;
	height: 82%;
	object-fit: contain;
	pointer-events: none;
	-webkit-user-drag: none;
}
/* El pie de cada diagrama en el carrusel: «Juegan blancas. Mate en 1». Va
   centrado bajo el tablero y con el mismo aire que el resto de pies del tema. */
.diagrama-texto {
	margin-top: .6rem;
	text-align: center;
	font-size: .8rem;
	font-weight: 500;
	color: var(--bs-heading-color);
}

/* ------------------------------- Tarjetas de igual alto DENTRO de un carrusel

   Jordi, 19/09/2026: «el alto de las cards de novedades y eventos no tienen la
   misma altura».

   En la rejilla basta con `height:100%` en la tarjeta, porque la fila de
   Bootstrap ya estira sus columnas. En un carrusel no: swiper.css trae
   `.swiper-wrapper{align-items:flex-start}`, así que cada slide mide lo que su
   contenido y un `height:100%` dentro no tiene contra qué resolverse. Por eso
   la clase `.alto-igualado` estaba en el HTML sin surtir efecto.

   Se arregla estirando los slides y dejando que el 100% baje por toda la
   cadena: wrapper -> slide -> item-inner -> article -> card. Si falta un
   eslabón, la tarjeta vuelve a medir su contenido.

   Acotado a `.blog.grid-view`, que es la clase de estos dos carruseles: el
   slider de destacadas (`swiper-hero`) tiene sus propias alturas y no se toca. */
.blog.grid-view .swiper-wrapper {
	align-items: stretch;
}

/* El slide, en `auto` y NO al 100% (13/10/2026): con `height:100%` (el de
   swiper.css o uno propio) el slide no se estira y cada tarjeta medía lo
   suyo. En `auto`, el `stretch` lo lleva al alto del más alto, y un hijo
   estirado cuenta como alto definido, así que el 100% de los de dentro sí
   resuelve. */
.blog.grid-view .swiper-slide {
	height: auto !important;
}

.blog.grid-view .swiper-slide > .item-inner,
.blog.grid-view .swiper-slide article.item {
	height: 100%;
}

/* El relleno de `.item-inner` (1rem .75rem en base.css) se queda, pero sin
   sumarse al alto: si no, la tarjeta sobresale del slide por abajo. */
.blog.grid-view .swiper-slide > .item-inner {
	box-sizing: border-box;
}

/* ------------------------- Fondo del titular y del pie, con el color del tema

   Jordi, 19/09/2026: «en lugar de negro en el fondo del titular y del pie, usa
   el color del tema, a ver qué tal queda».

   El color PLANO de la paleta no sirve: el blanco encima da 3,39 en `red` y
   2,17 en `sky` y `green`, cuando el texto normal pide 4,5. Por eso se mezcla
   con el oscuro del tema (#21262c) al 45 %, que es lo más saturado que deja
   todas las paletas por encima del mínimo: red 7,93 · blue 8,67 · green 6,02 ·
   sky 5,99. Se reconoce el aula —el rojo tira a granate, el sky a azul
   noche— sin dejar el texto por el camino.

   Son dos casos distintos:

     - `.fondo-tema`: sin imagen, el color mezclado a pelo.
     - `.velo-tema`: con imagen, el velo que va ENCIMA de la foto. Sustituye al
       gris azulado `rgba(30,34,40,.4)` de `bg-overlay-400` por el mismo color
       mezclado, a .72 de opacidad. Con menos alfa la foto clara se comía el
       texto: el velo del color al 40 % sobre una foto clara cae a 1,88.

   El respaldo para navegadores sin `color-mix()` es el oscuro de siempre: se
   pierde el matiz del aula, no la legibilidad. */
.fondo-tema {
	background-color: #21262c;
	background-color: color-mix(in srgb, var(--bs-primary) 45%, #21262c);
}

/* El velo vive en el `:before` de `.bg-overlay`, así que hay que ganarle a
   `.bg-overlay-400:before` con la misma especificidad más una clase. */
.bg-overlay.velo-tema:before {
	background: rgba(33, 38, 44, .72);
	background: color-mix(in srgb, var(--bs-primary) 45%, #21262c 55%);
	opacity: .72;
}

/* ------------------------------- Chaflán del titular y del pie (`.angled`)

   Jordi, 19/09/2026: «aplica el chaflán que hay en el bloque del titular en las
   páginas que lo llevan (no en la home). En el pie también».

   CÓMO FUNCIONA, que es lo que había que averiguar: `.wrapper.angled` se pone
   `position:relative` y el triángulo lo dibuja un pseudoelemento con BORDES, no
   con un SVG ni un `clip-path`. Un borde de `100vw` de ancho y `4rem` de alto,
   con los lados contiguos transparentes: eso deja una cuña que ocupa todo el
   ancho de la ventana. Se coloca justo fuera de la sección —`top:-4rem` en las
   variantes `upper-*`, `bottom:-4rem` en las `lower-*`— así que el chaflán
   invade la sección vecina, que es lo que produce el efecto de corte.

   Las cuatro variantes son `upper-start`, `upper-end`, `lower-start` y
   `lower-end`: «upper/lower» es el borde y «start/end» hacia qué lado baja la
   diagonal.

   POR QUÉ HACE FALTA ESTO Y NO BASTA CON PONER LA CLASE: el color del triángulo
   sale de `border-*-color`, y `base.css` lo resuelve con una lista fija de 55
   reglas `.wrapper.bg-X.angled` (bg-light, bg-dark, bg-primary...). Nuestras
   clases `velo-tema` y `fondo-tema` no están en esa lista, así que el borde se
   quedaría con el `transparent` de serie y el chaflán no se vería. Aquí se le da
   el mismo color que ya tiene el fondo —no se cambia ningún color, solo se
   repite el que hay—.

   En el titular CON foto el fondo real es la imagen más el velo, y un triángulo
   no puede reproducir ese degradado: se le pone el color mezclado sólido, que es
   lo más cercano y lo que hace la plantilla con sus fondos de imagen. */
.wrapper.velo-tema.angled.lower-end:after,
.wrapper.velo-tema.angled.upper-end:before,
.wrapper.fondo-tema.angled.lower-end:after,
.wrapper.fondo-tema.angled.upper-end:before {
	border-right-color: #21262c !important;
	border-right-color: color-mix(in srgb, var(--bs-primary) 45%, #21262c) !important;
}

.wrapper.velo-tema.angled.lower-start:after,
.wrapper.velo-tema.angled.upper-start:before,
.wrapper.fondo-tema.angled.lower-start:after,
.wrapper.fondo-tema.angled.upper-start:before {
	border-left-color: #21262c !important;
	border-left-color: color-mix(in srgb, var(--bs-primary) 45%, #21262c) !important;
}

/* El pie es un `<footer>`, no un `.wrapper`: `base.css` le da el
   `position:relative` y los bordes solo a través de `.wrapper.angled`, así que
   hay que repetir aquí la mecánica para el footer. `base.css` ya trae la pareja
   `footer.bg-dark.angled.*`, pero nuestro pie no es `bg-dark`. */
footer.angled {
	position: relative;
	border: 0;
}

footer.angled:before,
footer.angled:after {
	content: "";
	display: block;
	position: absolute;
	right: 0;
	z-index: 0;
	border-width: 0;
	border-style: solid;
	border-top-color: transparent !important;
	border-bottom-color: transparent !important;
}

footer.angled.upper-end:before {
	border-left-color: transparent !important;
	border-right-width: 100vw;
	border-top-width: 4rem;
	top: -4rem;
}

footer.angled.upper-start:before {
	border-right-color: transparent !important;
	border-left-width: 100vw;
	border-top-width: 4rem;
	top: -4rem;
}

footer.velo-tema.angled.upper-end:before,
footer.fondo-tema.angled.upper-end:before {
	border-right-color: #21262c !important;
	border-right-color: color-mix(in srgb, var(--bs-primary) 45%, #21262c) !important;
}

footer.velo-tema.angled.upper-start:before {
	border-left-color: #21262c !important;
	border-left-color: color-mix(in srgb, var(--bs-primary) 45%, #21262c) !important;
}

/* El chaflán se dibuja FUERA de la sección y sobre la vecina, así que hay que
   dejarle sitio: sin esto, el del pie se comería el final del cuerpo y el del
   titular pisaría la tarjeta que sube con `mt-n17`. */
.wrapper.angled.lower-end,
.wrapper.angled.lower-start {
	margin-bottom: 4rem;
}

footer.angled.upper-end,
footer.angled.upper-start {
	margin-top: 4rem;
}

/* ===================== Chaflán que SÍ deja ver la imagen (clip-path) =======

   Jordi, 19/09/2026: «el chaflán se ve en color sólido, no transparenta la
   imagen de fondo. Entiendo que eso no se podrá solucionar, ¿no?».

   Sí se puede, pero NO con el mecanismo de la plantilla. El `.angled` de
   Sandbox dibuja el triángulo con un BORDE (`border-right-width:100vw` y
   `border-top-width:4rem` en un pseudoelemento), y un borde solo admite un
   color plano: `border-color` no acepta imágenes. Por eso el chaflán salía
   sólido aunque la sección tuviera foto —el triángulo es un elemento aparte,
   pintado al lado de la sección, no un trozo de ella—.

   La solución es invertir el planteamiento: en vez de añadir un triángulo al
   lado, se RECORTA la sección misma con `clip-path`. Así la diagonal es el
   borde de la propia sección, con su imagen de fondo y su velo dentro, y por el
   hueco se ve lo que haya detrás. Es la técnica que usan los diseños modernos
   de Sandbox, y no necesita ningún pseudoelemento.

   `polygon()` toma las cuatro esquinas en orden. Para un corte abajo a la
   derecha (el `lower-end` del titular): arriba recto y abajo en diagonal, de
   100% menos la altura del chaflán hasta el 100%.

   Compatibilidad: `clip-path` con `polygon()` lo soportan todos los navegadores
   desde 2016. El `@supports` deja fuera a los que no, y ahí la sección se queda
   recta —sin chaflán, pero entera y legible—.

   Se usan las clases propias `chaflan-abajo` y `chaflan-arriba` en vez de
   `angled lower-end` / `upper-end`, para no pisar la mecánica de la plantilla:
   las demos que usan `.angled` siguen funcionando igual. */
@supports (clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%)) {

	/*
	 * CURVAS y no diagonales (Jordi, 27/09/2026), para hacer juego con el
	 * borde curvo del slider de la portada (demo19).
	 *
	 * La forma es la misma que dibuja aquel SVG, escrita aqui como `path()`:
	 * un rectangulo cuyo lado de fuera se arquea 4rem. Se sigue usando
	 * `clip-path`, asi que el corte deja ver la imagen de fondo igual que la
	 * diagonal de antes.
	 *
	 * `ellipse()` en vez del `path()` literal: las coordenadas de un `path`
	 * son fijas en pixeles y no se estiran con el ancho de la pantalla,
	 * mientras que una elipse al 100% de ancho se adapta sola.
	 */

	/* El titular: recto arriba, curvado abajo.

	   La elipse se ancla al BORDE de abajo y mide 4rem de alto, los mismos
	   que recortaba la diagonal. Con `at 50% calc(100% - 4rem)` su centro
	   queda justo esos 4rem por encima del filo, asi que la curva nace en
	   las esquinas y baja hasta el borde por el centro.

	   El ancho (200%) es lo que la hace suave: cuanto mas ancha la elipse,
	   mas abierta la curva. */
	.wrapper.chaflan-abajo {
		clip-path: ellipse(200% calc(100% - 4rem) at 50% 0%);
	}

	/* El pie: curvado arriba, recto abajo. Es el corte complementario. */
	footer.chaflan-arriba {
		clip-path: ellipse(200% calc(100% - 4rem) at 50% 100%);
	}

	/*
	 * El recorte se come 4rem de la sección, así que hay que devolvérselos por
	 * dentro o el contenido queda pegado al filo. En el titular es relleno
	 * abajo; en el pie, arriba.
	 */
	.wrapper.chaflan-abajo > [class*="container"] {
		padding-bottom: 4rem;
	}

	/* La curva se come el borde de arriba, asi que el contenido necesita ese
	   hueco ADEMAS del suyo. Lleva `!important` porque el `py-13` del
	   contenedor tambien lo lleva y si no gana el suyo: se quedaban 4rem
	   contando la curva, y los modulos salian pegados al filo (Jordi,
	   27/09/2026). */
	footer.chaflan-arriba > [class*="container"] {
		padding-top: 8rem !important;
	}
}

/* Aquí estuvo `.logo-pie`, el logo del aula presidiendo el pie sobre una
   banda clara (Jordi, 19/09/2026). Se quitó el 27/09/2026: esa banda es ahora
   la franja de logos de la página, y el del aula repetía el de la
   cabecera. El detalle, en el comentario de `_pie.php`. */


/* ------------------------------------------- Tablero jugable (problemas.php)

   Jordi, 19/09/2026: «usa los mismos colores y las mismas piezas que en los
   tableros de los mates», y «que el diseño sea lo más minimalista y ajustado al
   diseño de la página».

   chessboard.js trae su propia hoja (chessboard.css) con la madera de siempre:
   #f0d9b5 y #b58863 sobre un borde gris de 2px. Aquí se pisan sus tres reglas
   de color con LAS MISMAS de `.diagrama-clara` y `.diagrama-oscura`, así que el
   tablero jugable y los diagramas estáticos son el mismo tablero y cada aula
   lo ve en su paleta.

   Los nombres de clase con sufijo (`white-1e1d7`, `board-b72b1`) no son un
   despiste: los genera chessboard.js y son los que escribe en el HTML. */
/*
 * TODAS LAS MEDIDAS VIENEN DE AQUÍ, y el motivo hay que dejarlo escrito porque
 * no es evidente y costó media tarde (19/09/2026).
 *
 * La CSP del front es `style-src 'self'`, sin `unsafe-inline`. chessboard.js
 * escribe el tamaño de casilla y de pieza como ATRIBUTO `style=` en el HTML
 * —líneas 822 y 879 de la librería—, y el navegador los descarta sin decir
 * nada. Casilla sin ancho + `float: left` = las 64 apiladas en una columna.
 * Los otros once ajustes de la librería van por `.css()` de jQuery, que es
 * CSSOM y sí pasa la política; solo estos dos se pierden.
 *
 * Y hay un tercero que la librería no dimensiona NUNCA, ni en línea ni en su
 * hoja: `.row-5277c`, la fila. No tiene una sola regla en chessboard.css
 * —comprobado: cero apariciones— porque da por hecho que la rellenan los float
 * de sus casillas. Con las casillas sin alto, el `clearfix` del final quedaba
 * como una banda suelta y cada fila ocupaba el doble.
 *
 * TODO EN RELATIVO, para que el tablero ocupe el ancho que le den (Jordi,
 * 19/09/2026: «me gustaría que el tablero ocupe el 100% del espacio
 * disponible»). La casilla NO puede llevar `height` en porcentaje —no hay
 * contra qué resolverlo—, así que el cuadrado lo hace `aspect-ratio`, que es
 * exactamente como están montados los diagramas estáticos de `.diagrama`.
 *
 * No hay @media de móvil: siendo fluido se adapta solo, y una segunda vara de
 * medir solo podría pelearse con esta.
 */
.tablero-encaje {
	width: 100%;
	margin-inline: auto;
}

/*
 * El marco, como el del diagrama: el borde de 2px de la librería se cambia por
 * el mismo hilo tenue y se redondean las esquinas.
 *
 * `box-sizing: content-box` se repite a propósito: chessboard.css lo declara
 * para este elemento porque suma el borde por fuera de las 8 casillas, pero
 * `base.css` trae `*,::after,::before{box-sizing:border-box}`.
 */
.board-b72b1 {
	box-sizing: content-box;
	width: 100%;
	border: 1px solid rgba(164, 174, 198, .45);
	border-radius: .2rem;
}

/* La fila, lo que la librería se deja sin dimensionar: ancho completo y alto
   igual a un octavo de ese ancho. */
.row-5277c {
	width: 100%;
	aspect-ratio: 8 / 1;
}

/* El divisor de float: solo corta, no debe ocupar. */
.clearfix-7da63 {
	height: 0;
	line-height: 0;
	font-size: 0;
}

/* La casilla: un octavo del ancho, y cuadrada por su cuenta. El
   `position: relative` que ancla la notación lo trae la hoja de la librería. */
.square-55d63 {
	width: 12.5%;
	height: 100%;
	aspect-ratio: 1;
}

/* Las piezas llenan su casilla. */
.board-b72b1 img.piece-417db {
	width: 100%;
	height: 100%;
}

/*
 * LA PIEZA QUE SE ARRASTRA, y es el caso más enrevesado de todo este bloque
 * (Jordi, 19/09/2026: «al arrastrar una pieza, esta desaparece hasta que no se
 * suelta»).
 *
 * La librería la crea una sola vez, colgada del <body> y oculta, con
 * `buildPieceHTML(pieza, hidden = true)`: mete `width`, `height` **y**
 * `display:none` dentro del mismo atributo `style=`. La CSP descarta ese
 * atributo ENTERO, así que la pieza se queda sin tamaño y sin el `display:none`
 * a la vez.
 *
 * Al empezar el arrastre, la librería hace (línea 1303):
 *
 *     $draggedPiece.css({ display: '', position: 'absolute', left: x, top: y })
 *
 * Eso es CSSOM y sí pasa la política, pero `display: ''` significa «quita el
 * estilo en línea y usa el de la hoja» —y el estilo en línea nunca llegó a
 * existir—. O sea: quien decide si la pieza se ve es ESTA regla, no la
 * librería. Sin un `display` explícito aquí, al arrastrar no se veía nada.
 *
 * Por eso van juntas las cuatro cosas: que se vea, que no estorbe cuando no se
 * usa, que tenga tamaño y que flote sobre el resto.
 *
 * `position: absolute` lo pone la librería junto con `left`/`top` en cada
 * movimiento del ratón; aquí solo se declara el apilado.
 */
/*
 * Una sola regla, con las cinco cosas que la librería ya no puede darle.
 *
 * El `left`/`top` a -9999px es lo que la mantiene fuera de la vista mientras no
 * se usa. No vale `display: none`: la librería la enseña con `display: ''`
 * —«lo que diga la hoja»—, así que volvería a ocultarla justo al agarrarla. La
 * posición, en cambio, la sobrescribe ella misma con las coordenadas del
 * puntero (línea 1303), y entonces aparece donde toca.
 *
 * Este mismo selector alcanza también a la pieza ANIMADA: las líneas 918 y 958
 * la cuelgan igual del <body> con `buildPieceHTML(piece, true, …)`, y la
 * librería le asigna `left`/`top` antes de animarla, así que sale del escondite
 * por el mismo camino.
 */
body > img.piece-417db {
	display: block;
	position: absolute;
	left: -9999px;
	top: -9999px;
	width: 11vw;
	max-width: 110px;
	height: 11vw;
	max-height: 110px;
	/* Sobre la tarjeta y sobre el pie mientras se arrastra. */
	z-index: 20;
	/* Que el puntero atraviese la pieza: si no, el `mousemove` lo recibe ella y
	   no la casilla de debajo, y la jugada no se suelta donde toca. */
	pointer-events: none;
}

/* Aquí había un @media que bajaba la casilla a 36px en móvil. Sobra desde que
   el tablero es fluido (19/09/2026): las medidas relativas se adaptan solas, y
   una segunda vara de medir solo podría pelearse con la de arriba. */

/*
 * Los colores de casilla, y con ellos el de las coordenadas.
 *
 * El `color` no es decorativo ni sobra: es de donde la notación saca su tinta.
 * La librería no le pone color propio a las coordenadas —hereda el de la
 * casilla—, y usa el truco clásico de darle a cada casilla el color de la
 * contraria, que es lo que las hace legibles sobre ambos fondos. Al redefinir
 * aquí estas dos clases (19/09/2026) me quedé solo con `background-color` y tiré
 * el `color` que traía chessboard.css; con `showNotation: false` no se notaba,
 * pero al encenderlas (20/09/2026) las letras habrían salido en negro heredado.
 */
.white-1e1d7 {
	background-color: #f0d9b5;
	background-color: color-mix(in srgb, var(--bs-primary) 12%, #fbf6ef);
	color: color-mix(in srgb, var(--bs-primary) 55%, #8a7059);
}

.black-3c85d {
	background-color: #b58863;
	background-color: color-mix(in srgb, var(--bs-primary) 55%, #8a7059);
	color: color-mix(in srgb, var(--bs-primary) 12%, #fbf6ef);
}

/* La casilla marcada al soltar una pieza: la librería la pinta con un recuadro
   amarillo fijo (#ff0), que no pega con ninguna paleta. Se deja el mismo gesto
   con el color del tema. */
.highlight1-32417,
.highlight2-9c5d2 {
	box-shadow: inset 0 0 3px 3px var(--bs-primary);
}

/* «Mate» o «No es mate»: las dos únicas palabras que no vienen del problema.
   Sin fondo ni icono —un cartel de alerta aquí sería mucho—, solo el peso y el
   color que distinguen acertar de fallar. */
.resultado-problema {
	min-height: 1.5rem;
	font-weight: 600;
}

.resultado-problema.es-mate {
	color: #2fa76b;
}

.resultado-problema.no-es-mate {
	color: #60697b;
}

/* El diagrama del slider es un enlace entero: hereda el color del texto en vez
   del azul de los enlaces, y solo se mueve un poco al pasar por encima. */
.enlace-diagrama {
	display: block;
	color: inherit;
	text-decoration: none;
}

.enlace-diagrama:hover .diagrama {
	border-color: var(--bs-primary);
}

.enlace-diagrama:hover .diagrama-texto {
	color: var(--bs-primary);
}

@media (prefers-reduced-motion: no-preference) {
	.enlace-diagrama .diagrama,
	.enlace-diagrama .diagrama-texto {
		transition: border-color .2s ease, color .2s ease;
	}
}

/* ------------------------- El aviso de problema resuelto (problemas.php)

   Jordi, 19/09/2026: «cada vez que completamos un mate, tiene que aparecer un
   mensaje flotando con un botón y al pulsarlo se carga el siguiente problema».

   Flota sobre el tablero, centrado, sin tapar del todo la posición que se acaba
   de resolver: el visitante quiere ver el mate que ha dado. Por eso no es un
   modal a pantalla completa ni lleva velo.

   Nace con el atributo `hidden` y lo quita el JS. El reset de la plantilla trae
   `[hidden]{display:none}`, así que no hace falta declararlo aquí. */
.aviso-resuelto {
	/*
	 * `fixed` y no `absolute`: centrado en la PÁGINA, no sobre el tablero
	 * (Jordi, 19/09/2026: «sale muy abajo, tiene que aparecer centrado en la
	 * página»). Con `absolute` se anclaba a `.tablero-encaje`, así que bajaba
	 * con el tablero; `fixed` lo ancla a la ventana y queda a la vista sin
	 * importar dónde esté el tablero ni cuánto scroll haya.
	 */
	position: fixed;
	left: 50%;
	top: 50%;
	transform: translate(-50%, -50%);
	/*
	 * Por encima de TODO, incluido el menú fijo (Jordi, 20/09/2026). Estaba en
	 * 30, que basta dentro del cuerpo pero no contra la plantilla: `base.css`
	 * usa 1030 para la barra de navegación y llega hasta 9999. Se pone justo por
	 * encima de ese tope.
	 */
	z-index: 10000;
	padding: 1.5rem 2rem;
	text-align: center;
	background: #fff;
	border-radius: .4rem;
	box-shadow: 0 .5rem 2rem rgba(30, 34, 40, .25);
}

.aviso-resuelto-texto {
	font-size: 1.25rem;
	font-weight: 600;
	color: #2fa76b;
}

/* Aquí `.tablero-encaje` llevaba `position: relative`, que era el ancla del
   aviso cuando se centraba sobre el tablero. Desde que el aviso es `fixed`
   —centrado en la página— ya no ancla nada, y se quita para no dejar una regla
   que no hace nada (19/09/2026). */

/* Que aparezca con un gesto, no de golpe. Se salta si el visitante ha pedido
   menos movimiento. */
@media (prefers-reduced-motion: no-preference) {
	.aviso-resuelto {
		animation: aviso-resuelto-entra .25s ease-out;
	}

	@keyframes aviso-resuelto-entra {
		from { opacity: 0; transform: translate(-50%, -45%); }
		to   { opacity: 1; transform: translate(-50%, -50%); }
	}
}

/* ------------------------------ Paginador de ejercicios (problemas.php)

   Jordi, 20/09/2026: «a la izquierda el título del problema y un paginador que
   muestre el ejercicio en el que estamos».

   NO se reaprovecha `Front::paginacion()`: ese navega con `?p=<número de
   página>` sobre un listado, y aquí cada ejercicio es un `?n=<id>` distinto.

   Vive sobre la cabecera oscura, así que los colores son los del texto
   invertido y no los del cuerpo. */
.paginador-problema {
	display: inline-flex;
	align-items: center;
	gap: .5rem;
	padding: .35rem .5rem;
	/* Un fondo apenas insinuado: separa el paginador de la foto sin dibujar una
	   caja, que en una cabecera con imagen quedaría pesada. */
	background: rgba(255, 255, 255, .1);
	border-radius: 2rem;
}

.paginador-problema-cuenta {
	padding-inline: .5rem;
	font-size: .9rem;
	font-weight: 600;
	color: #fff;
	white-space: nowrap;
}

/* Las flechas: círculo tenue que se enciende al pasar por encima. */
.paginador-problema-salto {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2rem;
	height: 2rem;
	border-radius: 50%;
	color: #fff;
	font-size: 1.1rem;
	line-height: 1;
	text-decoration: none;
	background: rgba(255, 255, 255, .12);
}

.paginador-problema-salto:hover,
.paginador-problema-salto:focus-visible {
	background: var(--bs-primary);
	color: #fff;
}

/* En el primero y en el último la flecha se queda, apagada: así el bloque no
   cambia de ancho al pasar de ejercicio. */
.paginador-problema-salto.inactivo {
	opacity: .3;
	background: rgba(255, 255, 255, .06);
	cursor: default;
}

/* ------- El resultado y el marco del tablero, ahora sobre fondo OSCURO

   Los dos vivían dentro de la tarjeta blanca hasta el 20/09/2026, cuando el
   tablero subió a la cabecera. Las casillas no hace falta tocarlas: su
   `color-mix` va sobre tonos opacos (#fbf6ef y #8a7059) y no hereda el fondo. */

/* El verde de «Mate» se mantiene —sobre oscuro sigue leyéndose—, pero el gris
   de «No es mate» era #60697b, el color del texto del cuerpo: sobre la cabecera
   se hundía. Se sube a un blanco apagado. */
.resultado-problema.no-es-mate {
	color: rgba(255, 255, 255, .75);
}

/* El marco del tablero estaba pensado para despegarlo del blanco de la tarjeta.
   Sobre la foto oscura hace falta al revés: un hilo claro. */
.board-b72b1 {
	border-color: rgba(255, 255, 255, .25);
}

/* ---------------------------- Elegir pieza al coronar (problemas.php)

   Jordi, 20/09/2026: «no me deja seleccionar qué quiero coronar». Y no era un
   detalle: en el ejercicio n.º 11 el mate es g8=C, y con dama el rey negro
   queda ahogado, así que forzando la dama el problema no tenía solución.

   Flota centrado como el aviso de «¡Mate!» y por el mismo motivo va fuera de la
   sección de la cabecera: `clip-path` atrapa a los descendientes `fixed`.
   Un escalón por debajo del aviso en el apilado: nunca coinciden en pantalla,
   pero si algo fallara conviene que el que cierra la partida quede encima. */
.coronacion {
	position: fixed;
	left: 50%;
	top: 50%;
	transform: translate(-50%, -50%);
	z-index: 9999;
	padding: 1.25rem 1.5rem;
	text-align: center;
	background: #fff;
	border-radius: .4rem;
	box-shadow: 0 .5rem 2rem rgba(30, 34, 40, .25);
}

.coronacion-titulo {
	font-size: 1rem;
	font-weight: 600;
	color: var(--bs-heading-color);
}

.coronacion-piezas {
	display: flex;
	gap: .5rem;
}

/* Cada opción: la pieza grande y su nombre debajo, en un botón de verdad
   —no un <div> con onclick— para que funcione con teclado. */
.coronacion-pieza {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: .25rem;
	width: 4.5rem;
	padding: .5rem .25rem;
	background: transparent;
	border: 1px solid rgba(164, 174, 198, .45);
	border-radius: .3rem;
	font-size: .75rem;
	color: var(--bs-heading-color);
	cursor: pointer;
}

.coronacion-pieza img {
	width: 2.5rem;
	height: 2.5rem;
	object-fit: contain;
}

.coronacion-pieza:hover,
.coronacion-pieza:focus-visible {
	border-color: var(--bs-primary);
	background: color-mix(in srgb, var(--bs-primary) 10%, #fff);
}

/* ---------------------------------------------------------------- 404 --
 *
 * La ilustración del error (img/ilustraciones/404.svg) no lleva color: lo
 * pone la paleta de cada aula, así que es roja en megaescacs y verde en
 * un aula con `green` sin tocar el SVG.
 *
 * El «404» usa `.svg-fill`, que ya resuelve `.shape.pale-primary` de
 * base.css. El rey necesita su propia clase porque va ENCIMA del cero: con
 * el mismo tono pálido no se vería. Se oscurece mezclando la paleta con
 * negro, que mantiene el tono y da contraste suficiente.
 */
.ilustracion-404 {
	max-width: 34rem;
}

.ilustracion-404 .svg-fill-rey {
	fill: color-mix(in srgb, var(--bs-primary) 65%, #1e2a3a);
}

/* color-mix es reciente. Sin él, el rey queda en el gris oscuro del tema:
   se ve perfectamente, solo pierde el matiz de la paleta. */
@supports not (color: color-mix(in srgb, red 50%, blue)) {
	.ilustracion-404 .svg-fill-rey { fill: #34435a; }
}

/* ------------------------------------------------------------ perfil --
 *
 * La inicial del alias en un círculo del color del aula, y la tabla de
 * datos sin el borde superior que Bootstrap pone a la primera fila (aquí no
 * hay cabecera de tabla: la primera fila ya es un dato).
 */
.avatar-perfil {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 4rem;
	height: 4rem;
	border-radius: 50%;
	background: var(--bs-primary);
	color: #fff;
	/* Hasta tres iniciales: con 1,75rem se salían del círculo. 1,25rem con
	   algo de espaciado negativo las mete sin apretarlas. */
	font-size: 1.25rem;
	letter-spacing: -.02em;
	font-weight: 700;
	line-height: 1;
}

.tabla-perfil th {
	width: 12rem;
	font-weight: 600;
	color: var(--bs-heading-color);
}

.tabla-perfil tr:first-child th,
.tabla-perfil tr:first-child td {
	border-top: 0;
}

/* ============================================================== gestor ==
 *
 * El gestor usa el tema, no admin.css (Jordi, 22/09/2026). Aquí van las
 * pocas piezas que Bootstrap no trae y que el backoffice necesita.
 */

/* Sandbox las define en plugins.css, que no importamos. Sin el wrapper, el
   <select> pierde la flecha del tema y se queda con la del navegador. */
.form-select-wrapper {
	position: relative;
}

.widget-title {
	font-weight: 700;
	color: var(--bs-heading-color);
}

/* Las pinta Tabla::mostrar() desde el motor, así que salen en cualquier
   pantalla. Antes eran .miniatura / .imagen-ficha / .html de admin.css y se
   quedaban sin estilo donde no se cargaba esa hoja. */
.miniatura-tabla {
	width: 64px;
	height: 48px;
	object-fit: cover;
	border-radius: .25rem;
}

.imagen-ficha-tabla {
	max-width: 320px;
	max-height: 240px;
	object-fit: contain;
	border-radius: .25rem;
}

/* El HTML de una página dentro de una ficha: recortado, o una noticia larga
   empuja el resto de la pantalla fuera de la vista. */
.html-recortado {
	max-height: 420px;
	overflow: auto;
	padding: .75rem;
	border: 1px solid var(--bs-border-color);
	border-radius: .25rem;
	background: #fff;
}

/* Las tablas del gestor: rayadas y con bordes (Jordi, 22/09/2026). Bootstrap
   trae las dos por separado; juntarlas necesita reponer el borde interior,
   que .table-striped pisa con su fondo. */
.table-gestor > :not(caption) > * > * {
	border-width: 1px;
}

.table-gestor th {
	font-size: .8rem;
	text-transform: uppercase;
	letter-spacing: .03em;
	color: var(--bs-heading-color);
}

/* Filas clicables (Jordi, 22/09/2026): toda la fila lleva a la ficha, así que
   el texto va en negro. El enlace de una sola columna en color sugería que el
   resto de la fila no se podía pulsar. */
.fila-clicable {
	cursor: pointer;
}

/* El realce del hover gana a .table-striped, que pinta fondo en las impares:
   sin el !important la mitad de las filas no se iluminarían. */
.table-gestor > tbody > tr.fila-clicable:hover > * {
	background-color: var(--bs-pale-primary) !important;
}

/* El enlace de la primera celda existe para el teclado y los lectores de
   pantalla; visualmente es texto normal. */
.fila-clicable .enlace-fila {
	color: inherit;
	text-decoration: none;
}

/* El foco del teclado SÍ se ve, y se dibuja sobre toda la fila: es la pista de
   que lo que se va a activar es la fila entera, no solo esa palabra. */
.fila-clicable:focus-within > * {
	background-color: var(--bs-pale-primary) !important;
}

.fila-clicable .enlace-fila:focus-visible {
	outline: 2px solid var(--bs-primary);
	outline-offset: 2px;
}

/* ----------------------------------------- El árbol de páginas, en el Inicio

   Migrado desde admin.css al tema (22/09/2026). La sangría de cada nivel va
   por `--nivel`, que el HTML pone con un `style=` inline: es un dato, no un
   estilo, y por eso el gestor añade 'unsafe-inline' a style-src. */
.arbol-paginas {
	list-style: none;
	margin: 0;
	padding: 0;
}

.arbol-paginas .nodo {
	display: flex;
	align-items: center;
	gap: .5rem;
	flex-wrap: wrap;
	padding: .3rem .75rem .3rem calc(.75rem + var(--nivel, 0) * 1.5rem);
	border-bottom: 1px solid var(--bs-border-color);
}

.arbol-paginas .nodo:last-child {
	border-bottom: 0;
}

.arbol-paginas .nodo:hover {
	background-color: var(--bs-pale-primary);
}

/* La página de la que se viene, al volver de verla o editarla. */
.arbol-paginas .nodo.marcada {
	background-color: var(--bs-pale-yellow);
}

.arbol-paginas .nodo.inactiva .titulo-nodo {
	color: var(--bs-secondary-color);
	text-decoration: line-through;
}

/* El triángulo de plegar. Es un enlace: la rama abierta viaja en la URL. */
.arbol-paginas .plegar {
	width: 1.25rem;
	text-align: center;
	text-decoration: none;
	color: var(--bs-primary);
	font-size: .9rem;
	flex: none;
}

.arbol-paginas .plegar.sin-hijas {
	color: var(--bs-border-color);
}

.arbol-paginas .titulo-nodo {
	color: var(--bs-body-color);
	text-decoration: none;
	font-weight: 500;
}

.arbol-paginas .titulo-nodo:hover {
	color: var(--bs-primary);
}

/* Las acciones se atenúan hasta que el ratón entra en la fila: con 573 páginas,
   cinco iconos por fila a plena opacidad tapan los títulos. Con el foco del
   teclado dentro (`:focus-within`) también se ven, o no habría forma de saber
   dónde se está al tabular. */
.arbol-paginas .acciones-nodo {
	display: flex;
	align-items: center;
	gap: .15rem;
	margin-left: auto;
	opacity: .45;
}

.arbol-paginas .nodo:hover .acciones-nodo,
.arbol-paginas .acciones-nodo:focus-within {
	opacity: 1;
}

.arbol-paginas .acciones-nodo form {
	display: flex;
	gap: .15rem;
	margin: 0;
}

/* Los botones de ordenar: mismo tamaño que los .btn-circle de las tablas, pero
   sin fondo hasta que se pasa por encima. */
.arbol-paginas .acciones-nodo .btn[disabled] {
	opacity: .25;
	pointer-events: none;
}

/* --------------------------- El logo de la cabecera (Jordi, 27/09/2026)

   La plantilla sirve su logo ya recortado a 26px de alto y no lo dimensiona
   por CSS. Aqui no se puede: el logo lo sube cada aula.

   Se guarda a 52px (Imagen::ALTO_LOGO) y se enseña a 26: el doble en el
   fichero es lo que lo hace verse nitido en pantallas de alta densidad, que
   es para lo que la plantilla trae su logo@2x.

   `width:auto` conserva la proporcion sea cual sea la forma del logo. */
.navbar-brand img {
	height: 26px;
	width: auto;
}

/* ------------------- Cabecera de dos filas (Jordi, 12/10/2026)

   Fila 1 (`.barra-aula64`, la topbar de demo12): logo de aula64 y la cuenta,
   transparente y con letras claras sobre la foto. Fila 2: la barra blanca de
   el aula (`fancy`, demo16). Ver _cabecera.php. */
/* Márgenes ajustados (Jordi, 12/10/2026: «excesivos»): la fila medía 65px
   y había 18px más hasta la barra blanca. Lo que la engordaba era el botón
   «Entrar» (45px): aquí va más bajo. */
.barra-aula64 {
	padding-top: .35rem;
	padding-bottom: 0;
}

/* `.btn.btn-sm`: más peso que `.btn-sm.boton-claro`, que va más abajo. */
.barra-aula64 .btn.btn-sm {
	--bs-btn-font-size: .8rem;
	--bs-btn-line-height: 1.4;
	padding: .2rem .85rem;
	font-size: .8rem;
	line-height: 1.4;
}

.barra-aula64 .nav-link {
	padding-top: .3rem;
	padding-bottom: .3rem;
}

/* El logo de la AULA, en la barra blanca. Se guarda a 80 px
   (Imagen::ALTO_LOGO).

   Más grande desde el 17/10/2026 (Jordi: «queda muy pequeño y tiene mucho
   margen alrededor»), SIN que la barra crezca: su alto lo marcan los enlaces
   del menú (77 px de 83 en ancho), no el logo. 40 → 64 px en ancho; en la
   barra fija al bajar, 32 → 56 (mide 78 px con cualquier logo hasta 64:
   también la marcan los enlaces); en el móvil, 32 → 52, cambiando por logo el
   margen de 24 px que tenía arriba y abajo. Antes: 40 (12/10/2026; el de
   aulaludica lleva lema y a 26 no se leía). */
.cabecera-doble .navbar-brand img {
	height: 64px;
}

.cabecera-doble.fixed .navbar-brand img {
	height: 56px;
}

@media (max-width: 991.98px) {
	.cabecera-doble .navbar-brand {
		padding-top: .5rem;
		padding-bottom: .5rem;
	}

	.cabecera-doble .navbar-brand img {
		height: 52px;
	}
}

/* El logo de aula64: guardado a 52px y enseñado a 26. */
.marca-aula64 img {
	display: block;
	height: 26px;
	width: auto;
}

.barra-aula64 .nav-link,
.barra-aula64 .nav-link:hover,
.barra-aula64 .nav-link:focus {
	color: #fff;
}

/* La barra blanca, más cerca de la fila 1: la plantilla deja 2,25rem por
   encima porque en demo16 no hay nada arriba. */
.navbar-expand-lg.fancy.cabecera-doble:not(.fixed) .navbar-collapse-wrapper {
	margin-top: .5rem;
}

/* En el móvil la plantilla quita a la barra de `fancy` su fondo y su sombra
   (se funde con el fondo gris de demo16). Aquí va sobre una foto: si se
   quita, el logo del aula y las tres rayas quedan sobre la imagen. Se
   conserva blanca (Jordi, 12/10/2026, opción A del móvil). */
@media (max-width: 991.98px) {
	/* Y a la barra entera le pone fondo blanco (`navbar-bg-light`): con el
	   velo oscuro encima quedaba una franja gris sobre la foto. La fija
	   (`.fixed`, al bajar) sí lo conserva. */
	.navbar.cabecera-doble:not(.fixed) {
		background-color: transparent !important;
	}

	.navbar-expand-lg.fancy.cabecera-doble:not(.fixed) .navbar-collapse-wrapper {
		background: #fff !important;
		box-shadow: 0 .25rem .75rem rgba(30, 34, 40, .08) !important;
		border-radius: .4rem;
		padding: .6rem 1rem;
		margin-top: .4rem;
	}

	.marca-aula64 img {
		height: 22px;
	}
}

/* En las páginas de aula64 (fuera de toda aula), el logo más grande (Jordi,
   25/10/2026): ahí la barra es solo suya. El fichero mide 52 px de alto, así
   que hasta ahí no pierde nitidez. `header`: el del pie se queda como está. */
body.sin-aula header .marca-aula64 img {
	height: 44px;
}

@media (max-width: 991.98px) {
	body.sin-aula header .marca-aula64 img {
		height: 34px;
	}
}

/* Y centrado, con aire arriba y abajo (Jordi, 25/10/2026). La cuenta (alias,
   «Salir», «Entrar») sale del flujo y se queda a la derecha, a la altura del
   logo: así no lo empuja fuera del centro. `!important` contra las clases
   de Bootstrap del marcado (`justify-content-between`, `ms-auto`). */
body.sin-aula .barra-aula64 {
	justify-content: center !important;
	padding-top: 2rem;
	padding-bottom: 1rem;
}

/* Respecto al contenedor de la cabecera, que ocupa todo el ancho (la barra,
   en una columna flex, se encoge al logo). */
body.sin-aula .cabecera-doble > .container {
	position: relative;
}

/* `!important`: en ancho, una regla del tema para `.navbar-nav` le devolvía
   la posición normal y empujaba el logo a la izquierda. */
body.sin-aula .barra-aula64 > .navbar-nav {
	position: absolute !important;
	right: var(--bs-gutter-x, .75rem);
	top: calc(50% + .5rem);
	transform: translateY(-50%);
	margin: 0 !important;
}

/* La caja, un poco más abajo: ahora la barra es más alta. */
body.sin-aula #contenido > section.wrapper:first-of-type > .container {
	padding-top: 9.5rem !important;
}

@media (max-width: 991.98px) {
	body.sin-aula .barra-aula64 {
		padding-top: 1.25rem;
		padding-bottom: .5rem;
	}

	body.sin-aula .barra-aula64 > .navbar-nav {
		top: calc(50% + .375rem);
	}

	body.sin-aula #contenido > section.wrapper:first-of-type > .container {
		padding-top: 7rem !important;
	}
}

/* Las cabeceras de las páginas (la foto con el título) dejaban sitio para un
   menú de una fila; con dos, el título quedaba debajo de la barra blanca.
   Se añade el alto de la fila 1 a la primera sección de cada página, como
   RELLENO: un margen se colapsaba con el de la sección, la bajaba entera y
   dejaba arriba una franja blanca sin foto. */
#contenido > section.wrapper:first-of-type:not(.foto-bajo-menu) {
	padding-top: 3rem;
}

@media (max-width: 991.98px) {
	#contenido > section.wrapper:first-of-type:not(.foto-bajo-menu) {
		padding-top: 2.5rem;
	}
}

/* Los carruseles de foto de las portadas y la imagen de portada
   (`.foto-bajo-menu`) NO llevan ese relleno: la foto tiene que subir por
   detrás de las dos barras, como en demo15. Con él quedaba una franja oscura
   (el `bg-dark` de la sección) bajo la fila de aula64. */

/* El titular, compensado (Jordi, 12/10/2026: «los márgenes del titular no
   están bien»). La caja blanca sube 7rem (`mt-n17`) sobre una cabecera que
   acaba con 7rem de relleno (`pb-17`): el subtítulo quedaba PEGADO a la
   caja (medido: 0px) y había 45px entre la barra y el título. Se dan 2rem
   más abajo (40px, la plantilla tiene la letra base a 20px) y el último
   elemento del titular pierde su margen, para que el hueco sea el mismo
   haya subtítulo o no. */
#contenido > section.wrapper:first-of-type > .container.pb-17 {
	padding-bottom: 9rem !important;
}

#contenido > section.wrapper:first-of-type .post-header > :last-child {
	margin-bottom: 0 !important;
}

/* El pie sobre el fondo fijo (Jordi, 12/10/2026: sin foto propia ni curva).
   Su relleno de arriba era para la diagonal; sin ella, sumado al de abajo de
   la página, dejaba 220px vacíos entre la caja blanca y el pie. */
.pie-sobre-fondo > .container {
	padding-top: 0 !important;
}

/* Y el de abajo de la última sección de la página (`pb-14 pb-md-16`):
   dejaba 120px; «demasiado grande» (Jordi). 2rem, los mismos 40px que hay
   entre el titular y la caja. Solo con el fondo fijo: sin él, ese hueco
   blanco es el que separa el cuerpo de la diagonal del pie. */
body.fondo-fijo #contenido > section.wrapper:last-of-type > .container {
	padding-bottom: 2rem !important;
}

/* En las cajas blancas, el último bloque sin margen debajo: en la portada,
   el texto de bienvenida (`row mb-10`) dejaba 4rem vacíos al final cuando no
   había novedades ni agenda detrás. */
#contenido .card-body > :last-child {
	margin-bottom: 0 !important;
}

/* Y el primero sin margen encima: una página sin texto empieza directamente
   por sus subpáginas (`.bloque`, 36px de margen en front.css), y dejaba un
   hueco en lo alto de la caja (12/10/2026). Las filas no: su margen
   negativo de arriba es el que compensa el `gy-*` de sus columnas. */
#contenido .card-body > :first-child:not(.row) {
	margin-top: 0 !important;
}

/* El carrusel de la portada en una caja (Jordi, 12/10/2026): del ancho del
   menú, con sus esquinas y su sombra. Dentro de una caja, los 750px de alto
   de `.swiper-hero` eran demasiados: 520 (420 en el móvil). El `overflow`
   recorta la foto de cada slide a las esquinas redondeadas. */
.caja-destacadas {
	border-radius: .4rem;
	overflow: hidden;
	box-shadow: 0 .25rem 1.75rem rgba(30, 34, 40, .2);
}

/* A 4:3 desde el 18/10/2026, como la tarjeta ancha y las imágenes de página
   (Jordi: «quiero que sea homogéneo»; antes 3:2, y antes aún 520 px fijos).
   El contenedor manda con `aspect-ratio` y lo de dentro lo llena. */
.swiper-hero.caja-destacadas {
	height: auto !important;
	aspect-ratio: 4 / 3;
}

.swiper-hero.caja-destacadas .swiper,
.swiper-hero.caja-destacadas .swiper-slide {
	height: 100% !important;
}

/* El texto, apartado de las flechas: dentro de la caja quedaba pegado al
   borde y la flecha izquierda se montaba sobre el subtítulo. */
.caja-destacadas .swiper-slide > .container {
	padding-left: 5.5rem;
	padding-right: 5.5rem;
}

@media (max-width: 767px) {
	/* En el móvil no hay flechas (base.css las esconde). */
	.caja-destacadas .swiper-slide > .container {
		padding-left: 1.5rem;
		padding-right: 1.5rem;
	}
}

/* En el móvil, alto fijo: a 3:2 se quedaría en ~310 px y el título no
   cabría. */
@media (max-width: 767px) {
	.swiper-hero.caja-destacadas {
		aspect-ratio: auto;
	}

	.swiper-hero.caja-destacadas,
	.swiper-hero.caja-destacadas .swiper-slide {
		height: 420px !important;
	}
}

/* Las destacadas a dos columnas EN CAJA (`inicio-caja.php`, 12/10/2026).
   Recortadas a la caja: sin esto asomaba por el borde derecho la sombra de
   la foto del slide siguiente. El margen de abajo de la sombra de la foto,
   dentro: `overflow` la cortaría. */
.hero-en-caja .swiper {
	overflow: hidden;
}

/* Desde que la caja es la tarjeta del título (12/10/2026): base.css pone los
   puntos en absoluto 2.8rem POR DEBAJO del carrusel (con !important), así
   que no ocupan sitio y se salían de la tarjeta. Se les reserva ese hueco
   con RELLENO y no con margen: el carrusel es el último hijo de la tarjeta y
   `#contenido .card-body > :last-child` le quita el margen con !important.
   Los controles miden el 100 % del contenedor, relleno incluido, así que
   los puntos bajarían con él: se suben al fondo de ese relleno (su `bottom`
   no lleva !important). La foto ya no lleva sombra: el relleno de abajo que
   la protegía sobra. */
.hero-en-caja .swiper-container {
	padding-bottom: 2.5rem;
}

.hero-en-caja .swiper-controls .swiper-pagination {
	bottom: 0;
}

/* DESDE EL 18/10/2026, la foto a sangre en la mitad derecha (las clases
   `titulo-caja-sangre`, `-foto` y `-texto` de la cabecera de pagina.php) y
   los puntos a la izquierda, debajo del texto. En móvil, la foto arriba y
   los puntos centrados debajo, en el hueco de abajo de siempre. */
.hero-caja-texto {
	align-items: flex-start;
	padding: 2rem 2rem 1rem;
}

/* Todas las diapositivas del alto de la más alta, y la foto con ellas: sin
   esto, Swiper deja cada una con su propio alto y, en las de texto corto, la
   foto (que toma el alto de su diapositiva) se quedaba más baja que la caja
   y asomaba el clarito por debajo (Jordi, 18/10/2026). */
.hero-en-caja .swiper-wrapper {
	align-items: stretch;
}

.hero-en-caja .swiper-slide {
	height: auto !important;
}

/* En móvil, apiladas: la foto, siempre en 4:3 y arriba; lo que sobre de
   alto queda debajo del texto, no repartido entre foto y texto. */
@media (max-width: 991.98px) {
	.hero-en-caja .swiper-slide .row {
		align-content: flex-start;
	}
}

@media (min-width: 992px) {
	.hero-en-caja .swiper-container {
		padding-bottom: 0;
	}

	.hero-caja-texto {
		padding: 3rem 3rem 5rem;
	}

	/* Los puntos, en la mitad izquierda y alineados con el texto. */
	.hero-en-caja .swiper-controls .swiper-pagination {
		left: 0 !important;
		width: 50% !important;
		padding-left: 3rem;
		text-align: left;
		bottom: 2.5rem;
	}
}

@media (min-width: 1200px) {
	.hero-caja-texto {
		padding: 3.5rem 4.5rem 5.5rem;
	}

	.hero-en-caja .swiper-controls .swiper-pagination {
		padding-left: 4.5rem;
		bottom: 3rem;
	}
}

/* Las destacadas EN TARJETAS (`inicio-tarjetas.php`, demo25, 12/10/2026).
   Todas las fotos al mismo encuadre, como las de demo25: las destacadas
   vienen de cualquier proporción y, sin esto, las dos tarjetas de una fila
   saldrían de alturas distintas. */
.tarjeta-destacada img {
	width: 100%;
	aspect-ratio: 16 / 10;
	object-fit: cover;
}

/* Una sola tarjeta ancha (`inicio-tarjeta-ancha.php`, Jordi, 12/10/2026).

   ALTO FIJO y la foto SIEMPRE A TODO ESE ALTO: nunca se recorta por arriba
   ni por abajo, solo por los lados. Se llegó aquí tras probar tres cosas el
   mismo día: 12:5 con `cover` (cortaba arriba y abajo las fotos poco
   apaisadas), 4:3 y 3:2 con la foto entera (demasiado alta). Las
   destacadas de megaescacs van de 1,33 a 3,01 de proporción:

     - más anchas que la caja (Memorial, 2,66): se recortan los lados;
     - más estrechas (Super Campeones, 1,51): quedan centradas y los lados
       los rellena su miniatura ampliada y difuminada, detrás.

   La caja es el `<a>`: 4:3 en todos los tamaños desde el 18/10/2026, la
   misma proporción que las imágenes de página, que es la que usan las
   destacadas sin imagen propia (Jordi: «pon que el carrusel vaya a 4/3; quiero
   que sea homogéneo»). Antes 3:2 en ancho y 16:10 en móvil; se probó también
   12:5. La foto se cuelga del centro con su ancho natural para ese
   alto; `.swiper img{width:100%}` de base.css la estiraría, de ahí el
   !important. */
.hero-tarjeta-ancha .tarjeta-destacada > a {
	position: relative;
	display: block;
	overflow: hidden;
	aspect-ratio: 4 / 3;
}

/* LA FOTO LLENA LA CAJA (Jordi, 18/10/2026: «no me gustan las franjas...
   estira las imágenes aunque se recorten»): `cover`, recortando lo que sobre
   por el centro. Ese mismo día se probó `contain`, entera con franjas
   difuminadas, y antes la foto a todo el alto con difuminado a los lados.
   La copia difuminada de detrás ya no se ve: queda tapada. Las destacadas
   van mejor en 4:3, la proporción de la caja, y así no pierden nada. */
.hero-tarjeta-ancha .tarjeta-destacada img:not(.tarjeta-destacada-fondo) {
	position: absolute;
	inset: 0;
	width: 100% !important;
	height: 100% !important;   /* base.css: figure img{height:auto!important} */
	max-width: none !important;
	aspect-ratio: auto;
	object-fit: cover;
}

.hero-tarjeta-ancha .tarjeta-destacada .tarjeta-destacada-fondo {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100% !important;
	aspect-ratio: auto;
	object-fit: cover;
	filter: blur(28px) brightness(.85);
	transform: scale(1.15);
}

/* El velo, por encima de las dos fotos. */
.hero-tarjeta-ancha .tarjeta-destacada span.bg {
	z-index: 1;
}

.hero-tarjeta-ancha .tarjeta-destacada figcaption {
	padding: 2.5rem;
}

@media (max-width: 991.98px) {
	.hero-tarjeta-ancha .tarjeta-destacada figcaption {
		padding: 1.5rem;
	}
}

/* Los puntos, en el blanco del fondo del aula: el gris de base.css no
   se veía sobre la foto. */
.hero-tarjetas .swiper-controls .swiper-pagination .swiper-pagination-bullet {
	background: #fff;
	opacity: .7;
}

.hero-tarjetas .swiper-controls .swiper-pagination .swiper-pagination-bullet.swiper-pagination-bullet-active {
	background: none;
	border-color: #fff;
}

/* Sitio para los puntos (que base.css pone en absoluto por debajo), SOLO
   cuando se ven: con dos destacadas en ancho caben las dos y Swiper los
   bloquea (`swiper-pagination-lock`); en móvil, con una por pantalla, sí
   salen. */
.hero-tarjetas .swiper-container:has(.swiper-pagination:not(.swiper-pagination-lock)) {
	padding-bottom: 2.5rem;
}

.hero-tarjetas .swiper-controls .swiper-pagination {
	bottom: 0;
}

/* En la tarjeta ancha, los puntos DENTRO, sobre la foto, abajo y centrados,
   como en el primer hero (Jordi, 13/10/2026): así el hueco hasta la caja
   del cuerpo es el de todos los bloques. El pie de foto gana aire abajo
   para que el subtítulo no los toque. */
.hero-tarjeta-ancha .swiper-container:has(.swiper-pagination:not(.swiper-pagination-lock)) {
	padding-bottom: 0;
}

.hero-tarjeta-ancha .swiper-controls .swiper-pagination {
	bottom: 1.1rem !important;
	z-index: 2;
}

/* La portada en DOS tarjetas, igual cuando se ve una por fila (tableta y
   móvil, 18/10/2026): los puntos dentro de la foto, como en la ancha. En
   pantalla ancha, con dos fotos, siguen debajo: centrados caerían en el
   hueco entre las dos. */
@media (max-width: 991.98px) {
	.hero-tarjetas:not(.hero-tarjeta-ancha) .swiper-container:has(.swiper-pagination:not(.swiper-pagination-lock)) {
		padding-bottom: 0;
	}

	.hero-tarjetas:not(.hero-tarjeta-ancha) .swiper-controls .swiper-pagination {
		bottom: 1.1rem !important;
		z-index: 2;
	}

	.hero-tarjetas:not(.hero-tarjeta-ancha) .tarjeta-destacada figcaption {
		padding-bottom: 3.5rem;
	}
}

.hero-tarjeta-ancha .tarjeta-destacada figcaption {
	padding-bottom: 3.5rem;
}

/* El subrayado de brocha de demo19 (`underline-3 style-2`), DEL COLOR DEL
   TEMA de cada aula (Jordi, 12/10/2026: rojo en megaescacs, azul en
   aulaludica, y el que toque en las nuevas). base.css trae el trazo como un
   SVG con el color fijo dentro —hasta su `.primary` es azul a pelo—, así que
   aquí el mismo trazo se usa de MÁSCARA y se pinta con `--bs-primary`, que
   cada hoja de color define. El `data:` lo permite la CSP (img-src). */
.underline-3.style-2.subrayado-tema:after {
	background-image: none;
	background-color: var(--bs-primary);
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 208.01 8.3'%3E%3Cpath d='M64.42,2.42Q42.78,1.46,21.19,0c-2.8-.19-4.09.89-3.87,2L3.92,1.87c-5.13-.05-5.28,3.87-.12,3.92l60.49.55c46.63,2.08,93.34,2.51,139.81,1.27,5-.13,5.39-3.87.13-3.92Z'/%3E%3C/svg%3E") no-repeat bottom / 100% 100%;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 208.01 8.3'%3E%3Cpath d='M64.42,2.42Q42.78,1.46,21.19,0c-2.8-.19-4.09.89-3.87,2L3.92,1.87c-5.13-.05-5.28,3.87-.12,3.92l60.49.55c46.63,2.08,93.34,2.51,139.81,1.27,5-.13,5.39-3.87.13-3.92Z'/%3E%3C/svg%3E") no-repeat bottom / 100% 100%;
}

/* La caja blanca de las portadas, 40px por debajo de las destacadas o de la
   imagen de portada: pegada a la imagen parecía cortada. */
.caja-portada {
	padding-top: 2rem;
}

/* La caja de los logos, entre el cuerpo y el pie: los mismos 40px debajo. */
.franja-sobre-fondo > .container {
	padding-bottom: 2rem;
}

/* La curva blanca de debajo del carrusel de la portada lateral imitaba el
   blanco de la sección siguiente. Con el fondo fijo ya no hay blanco: sobra. */
body.fondo-fijo .hero-lateral .curva-abajo {
	display: none;
}

/* ------------- Los iconos de contacto y redes (Jordi, 27/09/2026)

   Todos con el MISMO color, el del menu. El del telefono salia distinto
   porque un `tel:` no es un enlace normal para el navegador: Safari y algun
   otro le aplican su propio color de enlace, que ignora el del tema.

   Se usa la MISMA variable que `.nav-link` (`--bs-navbar-color`), no
   `inherit`: el <a> hereda de su <li>, que no la define, asi que con
   `inherit` caia al color de enlace del navegador y el icono salia distinto.
   La variable la redefine cada variante del menu —blanca en `navbar-dark`,
   oscura en `navbar-light`—, asi que vale para los dos casos.

   `-webkit-text-fill-color` hace falta aparte: es lo que de verdad pinta el
   texto en los motores WebKit, y un `color` a secas no siempre lo pisa. */
.navbar-nav .nav-link[href^="tel:"],
.navbar-nav .nav-link[href^="https://wa.me/"] {
	color: var(--bs-navbar-color);
	-webkit-text-fill-color: var(--bs-navbar-color);
}

.navbar-nav .nav-link[href^="tel:"] i,
.navbar-nav .nav-link[href^="https://wa.me/"] i {
	color: currentColor;
	-webkit-text-fill-color: currentColor;
}

.navbar-nav .nav-link[href^="tel:"]:hover,
.navbar-nav .nav-link[href^="https://wa.me/"]:hover {
	color: var(--bs-navbar-hover-color);
	-webkit-text-fill-color: var(--bs-navbar-hover-color);
}


/* ------------------------ La lupa del menu (Jordi, 27/09/2026)

   Demo8 abre un panel con Bootstrap. Aqui el campo se ensancha al enfocarlo,
   con CSS y sin JavaScript: funciona bajo la CSP y con el teclado.

   El icono NO se superpone al campo (era la version anterior): iba en
   `position:absolute` con `pointer-events:none`, y el clic caia en el relleno
   izquierdo del campo, que no enfoca. Ahora la lupa es un <label> del propio
   campo, asi que pulsarla lo enfoca por definicion, y ademas se puede tabular
   hasta el. */
/* `row-reverse`: en el HTML el campo va antes que el boton, pero en pantalla
   la lupa tiene que verse a la izquierda, como los demas iconos.

   `gap` solo cuando el campo esta abierto: asi la lupa y el campo no se
   tocan, y cerrado no queda un hueco suelto empujando a «Entrar». */
.buscador-menu form {
	position: relative;   /* ancla del campo cuando esta cerrado (absolute) */
	display: flex;
	flex-direction: row-reverse;
	align-items: center;
}

.buscador-menu form:hover,
.buscador-menu form:focus-within {
	gap: .5rem;
}

/* La lupa es el boton de enviar. Se le quita el aspecto de <button> y se le
   deja el de los demas iconos del menu, para que la fila quede pareja. */
.buscador-menu .lupa {
	display: flex;
	align-items: center;
	/* Sin relleno lateral, como el sobre: dentro de `.navbar-nav` la variable
	   `--bs-nav-link-padding-x` vale 0, asi que un `.nav-link` del menu no
	   tiene padding-x y toda su separacion sale del `ms-2` del <li>. Ponerle
	   1rem aqui era lo que hacia el hueco el doble de grande. */
	padding: .25rem 0;
	border: 0;
	background: none;
	cursor: pointer;                 /* el puntero de "esto se pulsa" */
	color: var(--bs-navbar-color);
	font-size: 1.1rem;
	line-height: 1;
}

.buscador-menu .lupa:hover {
	color: var(--bs-navbar-hover-color);
}

/* En reposo el campo casi no ocupa: la fila se ve como un icono mas. Se abre
   al pasar el raton por el formulario o al enfocarlo con el teclado.

   Ancho 1px y no 0: con 0 el navegador lo trata como no enfocable y el
   <label> no tenia a que dar el foco, asi que pulsar la lupa no hacia nada.
   `opacity` lo esconde mientras tanto. */
.buscador-menu input[type="search"] {
	/* Cerrado no ocupa NADA. `width:0` no bastaba: Chrome sigue reservando
	   sitio para el aspa de «borrar» de un campo de busqueda, y ese resto
	   empujaba a «Entrar». `position:absolute` lo saca del flujo, asi que la
	   lupa queda pegada al boton como cualquier otro icono. */
	position: absolute;
	width: 0;
	min-width: 0;
	padding: 0;
	border: 0;
	margin: 0;
	opacity: 0;
	pointer-events: none;   /* cerrado no se puede pulsar por error */
	background-color: transparent;
	color: var(--bs-navbar-color);
	transition: width .25s ease-in-out, padding .25s ease-in-out, margin .25s ease-in-out, opacity .2s ease-in-out;
}

.buscador-menu form:hover input[type="search"],
.buscador-menu form:focus-within input[type="search"],
.buscador-menu input[type="search"]:focus {
	position: static;   /* vuelve al flujo y empuja a la lupa */
	width: 12rem;
	padding: .3rem .75rem;
	border: 1px solid rgba(255, 255, 255, .35);
	margin: 0;
	opacity: 1;
	pointer-events: auto;
	background-color: rgba(255, 255, 255, .15);
	border-radius: 2rem;
	box-shadow: none;
	outline: none;
}

/* El aspa de «borrar» que pintan Chrome y Safari es OSCURA, y sobre el menu
   —que va en claro sobre la foto— no se veia (Jordi, 27/09/2026). No se
   puede recolorear, asi que se sustituye por una propia en blanco: se quita
   la del navegador y se dibuja con una mascara, que toma el color del texto.

   Va en el mismo tono que el resto del menu (`currentColor`), asi que en la
   barra flotante, donde el menu es oscuro, sale oscura sin tocar nada. */
.buscador-menu input[type="search"]::-webkit-search-cancel-button {
	-webkit-appearance: none;
	appearance: none;
	width: .7rem;
	height: .7rem;
	cursor: pointer;
	background-color: currentColor;
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 4l8 8M12 4l-8 8' stroke='%23000' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 4l8 8M12 4l-8 8' stroke='%23000' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* La otra decoracion de WebKit no se usa y sí reserva hueco. */
.buscador-menu input[type="search"]::-webkit-search-decoration {
	-webkit-appearance: none;
	appearance: none;
}

.buscador-menu input[type="search"]::placeholder {
	color: var(--bs-navbar-color);
	opacity: .65;
}

/* En la barra flotante el menu es claro: el campo necesita el contraste al
   reves para que se lea lo que se escribe. */
.navbar-light .buscador-menu form:hover input[type="search"],
.navbar-light .buscador-menu input[type="search"]:focus {
	border-color: rgba(0, 0, 0, .15);
	background-color: rgba(0, 0, 0, .05);
}

/* En movil el menu se recoge en el panel lateral y no hay sitio para esto. */
@media (max-width: 991.98px) {
	.buscador-menu {
		display: none;
	}
}

/* ------------- Velo oscuro bajo el menu de la cabecera (Jordi, 27/09/2026)

   El menu flota sobre la foto (`position-absolute`, demo15). Del todo
   transparente cuesta leerlo segun la imagen que haya detras, asi que lleva
   un velo oscuro: se sigue viendo la foto y el texto claro se lee.

   Solo el menu FIJO de la cabecera, no la barra flotante que aparece al
   bajar: esa es `.navbar-clone` y la excluye el `:not()`. Aquella conserva
   el fondo blanco de la plantilla.

   Es un DEGRADADO vertical: 35% arriba, donde estan el logo y los enlaces, y
   transparente abajo, para que se funda con la foto sin dejar un corte.

   Va en `background-image` y no en `background-color`: la clase `transparent`
   de la plantilla fija `background-color:transparent!important`, asi que por
   ahi no se puede. Un degradado es una imagen, y esa propiedad la tenemos
   libre.

   Sin `backdrop-filter`: el desenfoque se aplica por igual a toda la barra y
   no se puede degradar, asi que abajo —donde el velo ya no esta— quedaria un
   corte nitido justo donde se busca que se funda. */
.navbar.transparent.position-absolute:not(.navbar-clone) {
	/* De .35 a .55 arriba (12/10/2026): con la foto del carrusel subiendo
	   por detrás de la fila de aula64, su logo blanco y «Entrar» no se leían
	   sobre las zonas claras. */
	background-image: linear-gradient(
		to bottom,
		rgba(30, 34, 40, .55) 0%,
		rgba(30, 34, 40, 0) 100%
	);
}

/* --------- «Salir» dentro del desplegable del usuario (Jordi, 27/09/2026)

   Cerrar sesion es un POST con CSRF, asi que no puede ser un enlace: va como
   <button> de su formulario. `.dropdown-item` ya trae `border:0` y fondo
   transparente, pero el <form> que lo envuelve si mete su propia caja. */
.dropdown-menu form {
	margin: 0;
}

.dropdown-menu button.dropdown-item {
	cursor: pointer;
	font: inherit;   /* un <button> no hereda la tipografia del menu */
}

/* ---------- La portada con el hero a dos columnas (Jordi, 27/09/2026)

   `inicio-lateral.php`: el modulo de cabecera de demo3 convertido en
   carrusel de destacadas. Texto a la izquierda, foto a la derecha.

   El carrusel NO lleva `swiper-hero`, que es el de la otra portada y fija
   alturas de 750px: aqui cada slide mide lo que su contenido.

   La foto se sale por abajo (`mb-n18`, 8rem sobre la seccion siguiente),
   que es el efecto del original, pero Swiper recorta por defecto. Se abre
   SOLO en vertical: con `overflow:visible` a secas se verian los slides de
   al lado asomando por los costados.

   Esto y las FLECHAS son incompatibles: declarar `overflow` en un eje hace
   que el navegador trate el otro como recorte, y eso descoloca lo que esta
   en absoluto —las flechas acababan en la esquina superior izquierda—. Por
   eso el carrusel lleva `data-nav="false"` y solo tiene puntos (Jordi,
   27/09/2026). */
.hero-lateral .swiper {
	overflow-x: clip;
	overflow-y: visible;
}

/* Los puntos, por encima de todo lo demas: de la curva y de la foto, que
   sobresale por abajo. Se pulsan, asi que no pueden quedar tapados.

   El apilado de este bloque: curva 2, foto 4, puntos 5. */
.hero-lateral .swiper-controls {
	z-index: 5;
}

/* Los controles NO se tocan: la plantilla ya les da `position:absolute`,
   `width:100%` y `height:100%` sobre el `.swiper-container`, que es lo que
   coloca las flechas a los lados y centradas. Cada intento de ajustarlos
   —`position:relative`, `height:auto`, `bottom`— las mandaba a la esquina
   superior izquierda (Jordi, 27/09/2026). */

/* El borde inferior CURVO de demo19.

   Lo dibuja un SVG dentro de la seccion, no `border-radius`: aquello
   redondea las esquinas y esto es una curva suave a todo lo ancho.

   El SVG va pegado abajo y con el color de la seccion siguiente, asi que
   tapa la parte baja del hero con la forma de lo que viene despues.
   `preserveAspectRatio:none` lo estira al ancho que haga falta sin que la
   curva cambie de altura. */
.hero-lateral .curva-abajo {
	position: absolute;
	bottom: 0;
	left: 0;
	width: 100%;
	line-height: 0;   /* sin esto el <svg> deja un hueco bajo la linea base */
	pointer-events: none;
	z-index: 2;
}

.hero-lateral .curva-abajo svg {
	display: block;
	width: 100%;
	height: 3.5rem;
}

/* La seccion es el ancla de la curva. */
.hero-lateral {
	position: relative;
}

/* La foto, POR DELANTE de la curva (Jordi, 27/09/2026): sobresale 8rem por
   debajo del slider y la cruza, asi que se ven las dos cosas —el borde
   curvo y la foto asomando sobre la seccion siguiente—.

   El z-index va en la columna y no en la <figure>: la que se sale es
   aquella, con su `mb-n18`. */
.hero-lateral .col-lg-5 {
	position: relative;
	z-index: 4;
}

/* Que llene su columna sea cual sea su tamano, sin deformarse. */
.hero-lateral figure img {
	width: 100%;
	height: auto;
	display: block;
}

/* ------- La imagen a sangre de la pagina (Jordi, 27/09/2026)

   `pagina.php` pinta la foto con `card-img-top`, fuera del `card-body`, para
   que llegue a los bordes de la tarjeta como en blog-post.html.

   La plantilla solo le da `width:100%`: sin redondear, las esquinas de
   arriba salen cuadradas y asoman por fuera de la tarjeta, que si es
   redonda. El radio es el de `.card`, asi que las dos coinciden. */
.blog.single .card > .card-img-top {
	margin: 0;
	overflow: hidden;
	border-top-left-radius: var(--bs-card-border-radius, .4rem);
	border-top-right-radius: var(--bs-card-border-radius, .4rem);
}

.blog.single .card > .card-img-top img {
	display: block;
	width: 100%;
	height: auto;
}

/* ---------- Los modulos de listado del pie (Jordi, 27/09/2026)

   Destacado, Novedades y Agenda usan `_pie-lista.php`, que es el primer
   bloque del pie de demo25: miniatura a la izquierda, titulo y fecha.

   `.image-list` ya viene en la plantilla; lo unico que falta es el hueco de
   las paginas SIN foto. Sin esto, su figure mide cero y el titulo se pega al
   borde, desalineado respecto a las filas que si tienen imagen. */
.image-list figure.sin-foto {
	background-color: rgba(255, 255, 255, .08);
}

/* La miniatura, CUADRADA siempre (Jordi, 27/09/2026).

   El <figure> ya lo era —base.css le da 3.5rem de lado—, pero la foto se
   salia por dos motivos, y el segundo era el de verdad:

   1. Dentro hay un <a> sin tamano, asi que un `height:100%` en la <img> se
      media contra el enlace y no contra el figure.
   2. base.css lleva `figure img{height:auto !important}`, que ganaba a
      cualquier altura que se le pusiera. Ver la regla de la <img> abajo.

   Aqui solo se recorta lo que sobresalga. */
.image-list figure {
	overflow: hidden;
}

.image-list figure a {
	display: block;
	width: 100%;
	height: 100%;
}


/* El `!important` es obligado: base.css lleva `figure img{height:auto
   !important}`, y con altura automatica la foto conserva su proporcion y se
   sale del cuadro. Era lo que impedia ver las miniaturas cuadradas. */
.image-list figure img {
	width: 100% !important;
	height: 100% !important;
	max-width: none !important;
	object-fit: cover;   /* llena el cuadro recortando, sin deformar */
}

/* El titulo de cada fila, en claro: `link-body` lo pinta oscuro, que es lo
   suyo sobre fondo blanco pero no sobre el pie. */
footer .image-list .post-content a {
	color: #fff;
}

footer .image-list .post-content a:hover {
	color: var(--bs-primary);
}


/* ---------- El panel de los modulos del pie (Jordi, 27/09/2026)

   El pie lleva de fondo la imagen del aula, que tiene zonas claras: el
   texto en blanco perdia contraste segun por donde cayera. Un velo oscuro
   semitransparente lo iguala sin tapar la foto, que se sigue intuyendo.

   El velo NO se pone en el <footer> entero: la linea de derechos queda
   fuera, y asi el panel se lee como un bloque y no como un cambio de fondo
   a media altura.

   `backdrop-filter` desenfoca lo que pasa por debajo, lo que ayuda a
   despegar el texto de una foto con mucho detalle. Donde no se soporte
   queda el velo liso, que tambien vale. */
.panel-pie {
	padding: 2.5rem;
	border-radius: 1rem;
	background-color: rgba(20, 22, 26, .55);
	backdrop-filter: blur(6px);
	-webkit-backdrop-filter: blur(6px);
}

/* El pie BLANCO (Jordi, 12/10/2026; la otra versión, la oscura de arriba, se
   conserva: ver `$estiloPie` en _pie.php). Una caja como el cuerpo de la
   página: blanca, con sus esquinas y su sombra, sin el desenfoque. */
.panel-pie.panel-pie-blanco {
	border-radius: .4rem;
	/* Un poco transparente, para que se intuya el fondo (Jordi, 12/10/2026):
	   se probó al 90% y quedaba demasiado teñido; al 95%. Sin desenfoque: con
	   él, el blanco se ensucia del color de la foto. */
	background-color: rgba(255, 255, 255, .95);
	backdrop-filter: none;
	-webkit-backdrop-filter: none;
	box-shadow: 0 .25rem 1.75rem rgba(30, 34, 40, .07);
}

/* Los títulos de los listados: el pie oscuro los fuerza a blanco
   (`footer .image-list .post-content a`, más arriba). */
footer .panel-pie-blanco .image-list .post-content a {
	color: var(--bs-heading-color, #343f52);
}

footer .panel-pie-blanco .image-list .post-content a:hover {
	color: var(--bs-primary);
}

/* El hueco de las filas sin foto: el blanco translúcido no se veía. */
.panel-pie-blanco .image-list figure.sin-foto {
	background-color: var(--bs-pale-primary);
}

/* La línea de derechos, dentro de la caja tras un filete. */
.panel-pie-blanco .pie-derechos {
	border-top: 1px solid rgba(164, 174, 198, .2);
}

/* SIN EL CONTENEDOR GENERAL (Jordi, 12/10/2026): desde que cada módulo va
   en su mini-tarjeta, la caja blanca de fuera sobraba. El panel queda
   transparente y las cuatro tarjetas van directamente sobre el fondo de la
   aula. La línea de derechos, también sobre el fondo, en blanco y con
   una sombra suave para leerse sobre las zonas claras de la foto. Va
   después de las reglas de arriba para ganarles. */
.panel-pie.panel-pie-blanco {
	padding: 0;
	background-color: transparent;
	box-shadow: none;
}

.panel-pie-blanco .pie-derechos {
	border-top: 0;
	margin-top: 2rem !important;
	padding-top: 0 !important;
}

/* La línea de derechos sobre el fondo, en blanco: la del pie de cuatro
   módulos y la del pie en slider (13/10/2026). */
.panel-pie-blanco .pie-derechos,
.pie-slider .pie-derechos {
	color: #fff;
	text-shadow: 0 1px 3px rgba(0, 0, 0, .6);
}

.panel-pie-blanco .pie-derechos a,
.panel-pie-blanco .pie-derechos a:hover,
.pie-slider .pie-derechos a,
.pie-slider .pie-derechos a:hover {
	color: #fff;
}

.panel-pie-blanco .pie-derechos a:hover,
.pie-slider .pie-derechos a:hover {
	text-decoration: underline;
}

/* El icono delante del título de Miembros, Grupos, Sesiones, Novedades y
   Agenda (Jordi, 13/10/2026), en un CÍRCULO BLANCO con el icono del color
   del tema, y con más aire hasta el texto. Las medidas van en `em` del
   propio icono, que es el 60 % del título: el círculo mide algo menos que
   la altura de las mayúsculas más el hueco de arriba y abajo. Va DETRÁS
   del texto, a la derecha (Jordi, 13/10/2026; primero estuvo delante). */
.titulo-icono {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 1.7em;
	height: 1.7em;
	margin-left: .6em;
	font-size: .6em;
	line-height: 1;
	border-radius: 50%;
	background-color: #fff;
	color: var(--bs-primary);
	vertical-align: middle;
	position: relative;
	top: -.1em;
}

/* EL TÍTULO DENTRO DE LA CAJA (Jordi, 13/10/2026, opción A; a prueba en
   Grupos). Una franja del color clarito del tema en lo alto de la caja
   blanca, con el título en el color del tema oscurecido un 25 % —así se lee
   también con las paletas claras: amarillo, cielo, verde— y el icono al
   revés que sobre el fondo: círculo del color del tema, icono en blanco. */
.caja-con-franja {
	overflow: hidden;
}

.titulo-franja {
	padding: 2.25rem 1.5rem;
	text-align: center;
	background-color: var(--bs-soft-primary, rgba(var(--bs-primary-rgb), .08));
}

.titulo-franja-texto {
	font-size: calc(1.365rem + 1.38vw);
	font-weight: 700;
	line-height: 1.2;
	/* El oscuro de la paleta personalizada si lo hay (17/10/2026; también lo
	   pone en vivo la vista previa de Configuración); si no, el principal
	   oscurecido, como siempre. */
	color: var(--color-oscuro, color-mix(in srgb, var(--bs-primary) 75%, #000));
}

/* El título de la tarjeta clarita (pagina.php, y las destacadas en caja de la
   portada), del mismo color que el de la franja (Jordi, 18/10/2026: «el
   título tendría que estar en el color del tema»). */
.titulo-caja h1,
.titulo-caja h2.display-3 {
	color: var(--color-oscuro, color-mix(in srgb, var(--bs-primary) 75%, #000));
}

@media (min-width: 1200px) {
	.titulo-franja-texto {
		font-size: 2.4rem;
	}
}

.titulo-franja .titulo-icono {
	background-color: var(--bs-primary);
	color: #fff;
}

/* El subtítulo y las migas, centrados y en el color del texto. */
.titulo-franja-sub {
	margin-top: .6rem;
	font-size: 1rem;
	color: #60697b;
}

.titulo-franja .breadcrumb {
	justify-content: center;
	font-size: .75rem;
}

/* El título de sección encima de una tarjeta de ficha (la de un miembro):
   la misma distancia hasta la caja que en los listados. */
.titulo-seccion {
	margin-bottom: 2.25rem;
}

/* ------------------------------------------------ Doble pie (13/10/2026)

   Reflejo de la cabecera de dos filas (Jordi): primero la barra blanca de la
   AULA (`.pie-aula`, como su barra del menú) y debajo, sobre el fondo y
   en blanco, el pie de AULA64 (`.pie-aula64`, como la barra de arriba). */
/* La parte del aula, en una CAJA BLANCA como el pie blanco de antes
   (Jordi, 13/10/2026), con su línea. El carrusel va fuera, encima. */
.pie-caja {
	padding: 2rem;
	border-radius: .4rem;
	/* Opaca, como la caja del cuerpo: al 95 % de antes se teñía del fondo
	   (rosa sobre el rojo de megaescacs). */
	background-color: #fff;
	box-shadow: 0 .25rem 1.75rem rgba(30, 34, 40, .07);
}

/* De lado, el mismo relleno que las cajas del cuerpo (`p-md-11`, 55 px;
   18/10/2026): así el texto del pie arranca en la misma vertical que el de
   arriba. Arriba y abajo se queda en 40: es una sola línea. */
@media (min-width: 768px) {
	.pie-caja {
		padding-left: 2.75rem;
		padding-right: 2.75rem;
	}
}

.pie-aula {
	font-size: .8rem;
}

.pie-aula-filete {
	margin-top: 1.5rem;
	padding-top: 1.5rem;
	border-top: 1px solid rgba(164, 174, 198, .2);
}

/* El logo, al tamaño del de la barra del menú. */
.pie-aula-logo img {
	display: block;
	height: 40px;
	width: auto;
}

.pie-aula-iconos a {
	font-size: 1.1rem;
}

/* Tres columnas: derechos a la izquierda, logo en el centro exacto (las dos
   de los lados miden lo mismo, `1fr`), iconos a la derecha. */
.pie-aula-fila {
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	align-items: center;
	gap: 1rem;
}

.pie-aula-iconos {
	justify-content: flex-end;
}

@media (max-width: 767.98px) {
	.pie-aula-fila {
		grid-template-columns: 1fr;
		justify-items: center;
		text-align: center;
	}

	.pie-aula-logo {
		order: -1;
	}

	.pie-aula-iconos {
		justify-content: center;
	}
}

@media (max-width: 575.98px) {
	.pie-caja {
		padding: 1.25rem;
	}

	.pie-aula-logo img {
		height: 32px;
	}
}

.pie-aula64 {
	padding: 1.25rem 0 1.75rem;
	color: #fff;
	font-size: .8rem;
	text-shadow: 0 1px 3px rgba(0, 0, 0, .6);
	position: relative;
}

/* Degradado que oscurece esta franja (Jordi, 13/10/2026): sin el velo
   general, el texto blanco dependía del dibujo de detrás. Desde el mismo
   día, un 50 % más alto que la franja, para que se desvanezca más suave:
   sube por detrás de la caja blanca del pie sin mover el texto. */
.pie-aula64::before {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 150%;
	background: linear-gradient(to top, rgba(20, 22, 26, .6), rgba(20, 22, 26, 0));
	pointer-events: none;
}

.pie-aula64 > .container {
	position: relative;
	z-index: 1;
}

.pie-caja {
	position: relative;
	z-index: 1;
}

/* Lo mismo arriba, detrás de la fila de aula64 de la cabecera (logo y
   «Entrar»): una franja oscura que se desvanece hacia abajo. A todo el
   ancho de la ventana; en la barra fija no (allí no hay fila de aula64). */
body.fondo-fijo .content-wrapper {
	position: relative;
}

body.fondo-fijo .content-wrapper::before {
	content: "";
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	/* 5.5rem hasta el 13/10/2026; un 50 % más para que se desvanezca más
	   suave (Jordi). */
	height: 8.25rem;
	background: linear-gradient(to bottom, rgba(20, 22, 26, .6), rgba(20, 22, 26, 0));
	pointer-events: none;
}

.pie-aula64 a {
	color: #fff;
	text-decoration: underline;
	text-underline-offset: 2px;
}

.pie-aula64 a:hover {
	color: #fff;
	opacity: .85;
}

/* El logo, al tamaño de la barra de arriba. */
.pie-aula64 .marca-aula64 img {
	display: block;
	height: 26px;
	width: auto;
}

/* El lightbox de textos (aviso legal de aula64): ancho de lectura, alto
   acotado y con su propio scroll. El relleno va dentro, para que solo el
   fondo oscuro cuente como «fuera» al pulsar. */
.dialogo-texto {
	width: min(48rem, calc(100vw - 2rem));
	max-height: 85vh;
	padding: 0;
	border: 0;
	border-radius: .5rem;
	box-shadow: 0 1rem 3rem rgba(30, 34, 40, .3);
	overflow: auto;
}

.dialogo-texto::backdrop {
	background-color: rgba(30, 34, 40, .6);
}

.dialogo-texto-dentro {
	padding: 2rem;
}

/* Contacto (contacto.php, 18/10/2026, contact3 de Sandbox): la tarjeta en dos
   mitades; la de los datos, del clarito del tema y redondeada por su lado.
   El título, del color de los títulos de página. El mensaje, 150 px. */
.contacto-tarjeta {
	overflow: hidden;
}

.contacto-datos {
	background-color: var(--bs-soft-primary, #fef0f1);
}

.contacto-titulo {
	color: var(--color-oscuro, color-mix(in srgb, var(--bs-primary) 75%, #000));
}

.contacto-datos address {
	font-style: normal;
}

.contacto-mensaje.form-control {
	height: 150px;
}

/* El nombre en las fichas de miembro, grupo y sesión, del mismo tamaño
   (18/10/2026): antes el alias iba en `display-2` y los otros dos en `h2`. */
.nombre-ficha {
	font-size: calc(1.3rem + .9vw);
	font-weight: 700;
	line-height: 1.2;
}

@media (min-width: 1200px) {
	.nombre-ficha {
		font-size: 2.2rem;
	}
}

/* El ELO FIDE estándar de un miembro, en una pastilla del color del tema
   (18/10/2026): en su tarjeta y, más grande, en su ficha. */
.elo-miembro {
	padding: .15rem .65rem;
	border-radius: 2rem;
	background-color: var(--bs-soft-primary, #fef0f1);
	color: var(--color-oscuro, color-mix(in srgb, var(--bs-primary) 75%, #000));
	font-size: .8rem;
	font-weight: 700;
	letter-spacing: .02rem;
}

.elo-miembro-grande {
	padding: .3rem .9rem;
	font-size: 1rem;
}

/* La página de entrar (respaldo del popup), al ancho del popup. */
.entrar-centrado {
	max-width: 30rem;
}

/* El formulario «Invitar» de la página de un grupo (01/11/2026): estrecho,
   como el de entrar, pero alineado a la izquierda con el resto de la caja. */
.formulario-invitar {
	max-width: 36rem;
}

/* El campo trampa del registro (01/11/2026): fuera de la vista, pero no con
   display:none, que algunos robots saben saltarse. */
.campo-trampa {
	position: absolute;
	left: -10000px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

/* Formularios de aula64 más largos que entrar (crear un aula, el
   instalador; 25/10/2026): algo más anchos, centrados. */
.formulario-centrado {
	max-width: 42rem;
}

/* Portada del dominio (public/index.php, 25/10/2026): el logo junto al
   nombre de cada aula en «Tus grupos», y el de cada tarjeta de Aulas,
   todos a la misma altura aunque lleguen con proporciones muy distintas. */
.logo-bloque-portada {
	height: 2.2rem;
	width: auto;
}

.logo-aula-portada {
	height: 3.5rem;
	max-width: 100%;
	width: auto;
	object-fit: contain;
}

.tarjeta-aula-portada {
	border: 1px solid rgba(8, 60, 130, .07);
}

/* El buscador de la página de error (404.php, 18/10/2026). */
.buscar-404 {
	max-width: 28rem;
}

/* «Escribes como …», en lugar de nombre y email cuando hay sesión. */
.contacto-quien {
	padding: .85rem 1rem;
	border-radius: .4rem;
	background-color: var(--bs-soft-primary, #fef0f1);
}

.contacto-quien .uil {
	margin-right: .35rem;
	font-size: 1.15rem;
	vertical-align: -.15rem;
}

/* «O búscanos en redes sociales», separado del formulario por una raya fina. */
.contacto-redes {
	border-top: 1px solid rgba(164, 174, 198, .2);
}

/* La ventana de entrar (_dialogo-entrar.php, 18/10/2026): el ancho del modal
   de acceso de Sandbox (`modal-dialog-centered` de 500 px), su relleno y el
   aspa arriba a la derecha. */
.dialogo-entrar {
	width: min(30rem, calc(100vw - 2rem));
	border-radius: .8rem;
}

.dialogo-entrar .dialogo-texto-dentro {
	position: relative;
	padding: 2.75rem 2.5rem 2.25rem;
}

@media (max-width: 575.98px) {
	.dialogo-entrar .dialogo-texto-dentro {
		padding: 2.5rem 1.5rem 1.75rem;
	}
}

@media (max-width: 575.98px) {
	.dialogo-texto-dentro {
		padding: 1.25rem;
	}
}

/* ------------------------------------------- El pie en slider (13/10/2026)

   Las tarjetas son las de los carruseles de la portada
   (`_carrusel-tarjetas.php`, la tarjeta de blog de demo25), en un módulo
   APARTE sobre el fondo, antes de la caja del pie (Jordi, 13/10/2026). Por
   eso los puntos van en blanco. Hueco debajo para ellos solo cuando Swiper
   no los bloquea (con tres páginas o menos caben todas). */
.pie-slider {
	margin-bottom: 2.5rem;
}

.pie-slider .swiper-container:has(.swiper-pagination:not(.swiper-pagination-lock)) {
	padding-bottom: 2.5rem;
}

.pie-slider .swiper-controls .swiper-pagination {
	bottom: 0;
}

.pie-slider .swiper-pagination .swiper-pagination-bullet {
	background: rgba(255, 255, 255, .6);
}

.pie-slider .swiper-pagination .swiper-pagination-bullet-active {
	background: #fff;
}

/* Las tarjetas de los extremos, a ras del relleno de la caja: cada slide
   lleva `.item-inner`, con .75rem a los lados (base.css), que se compensa
   sacando el carrusel esos mismos .75rem por cada lado. */
/* Las flechas, a media altura de la FOTO (18/10/2026), como en el carrusel
   de destacadas; antes, a media altura de la tarjeta entera, que caía en el
   borde de abajo de la foto. La foto mide 3/4 de su ancho (encuadre 4:3) y
   el ancho sale del carrusel entre las tarjetas por fila, menos el relleno
   de `.item-inner` (.75rem por lado, 1rem arriba). Lo calcula Swiper con
   esta variable, con el ancho del carrusel en `cqw`. */
.pie-slider .swiper-container {
	container-type: inline-size;
	--fotos-por-fila: 1;
	--swiper-navigation-top-offset: calc(1rem + (100cqw / var(--fotos-por-fila) - 1.5rem) * .375);
}

@media (min-width: 768px) {
	.pie-slider .swiper-container { --fotos-por-fila: 2; }
}

@media (min-width: 1200px) {
	.pie-slider .swiper-container { --fotos-por-fila: 3; }
}

.pie-slider .swiper-container {
	margin-left: -.75rem;
	margin-right: -.75rem;
	/* Aquí el hueco de los puntos lo da el relleno de arriba: fuera el
	   `mb-12` que el carrusel lleva para la portada. */
	margin-bottom: 0 !important;
}

/* ------------------------------------------------ Móvil (13/10/2026)

   - Letra algo más pequeña: el tema mide todo en rem sobre 20 px; en el
     móvil, 18. Todo baja un 10 % a la vez (texto y huecos), sin romper
     proporciones.
   - En la tarjeta ancha de la portada, sin flechas: tapaban el título. Se
     pasa con el dedo o con los puntos. */
@media (max-width: 575.98px) {
	:root {
		--bs-root-font-size: 18px;
	}
}

@media (max-width: 767.98px) {
	.hero-tarjeta-ancha .swiper-navigation {
		display: none;
	}
}

/* CADA MÓDULO EN SU MINI-TARJETA (Jordi, 12/10/2026, «opción B»: el pie se
   veía soso). Las cuatro columnas del panel —Destacado, Novedades, Agenda,
   Contacto— como las cajas de cifras del perfil: esquinas redondeadas,
   sombra suave y todas del mismo alto (`height: 100%` sobre la columna).
   En el pie oscuro, un blanco casi transparente: el texto es blanco. */
.panel-pie .row > [class*="col-"] > .widget {
	height: 100%;
	padding: 1.25rem;
	border-radius: .6rem;
	background-color: rgba(255, 255, 255, .07);
}

.panel-pie-blanco .row > [class*="col-"] > .widget {
	background-color: #fff;
	border: 1px solid rgba(164, 174, 198, .18);
	box-shadow: 0 .25rem 1.25rem rgba(30, 34, 40, .08);
}

/* Con tarjetas, el panel necesita menos relleno: el de las tarjetas ya
   separa del borde, y los dos juntos estrechaban tanto las columnas que los
   títulos de las listas partían en seis líneas. */
.panel-pie {
	padding: 1.5rem;
}

.panel-pie > .row {
	--bs-gutter-x: 1.25rem;
}

/* En movil el relleno se come demasiado ancho de una pantalla estrecha. */
@media (max-width: 575.98px) {
	.panel-pie {
		padding: 1.5rem;
	}

	.panel-pie .row > [class*="col-"] > .widget {
		padding: 1.25rem;
	}
}

/* ----------------------------------------------------------------- Botones

   Jordi, 27/09/2026: de los cinco estilos de botón que traía la plantilla
   —`btn-primary` de relleno, `btn-outline-white`, `btn-soft-ash`,
   `btn-soft-red`, `btn-red`— se unifica en UNO: cuadrado (esquina apenas
   redondeada), con borde y fondo del color del tema. Las plantillas dejan de
   llevar `rounded-pill`, que era el ovalado.

   Son DOS variantes de la misma idea, y la diferencia es sobre qué fondo cae:

   - `.boton` sobre fondo claro: borde y texto del color del tema, fondo
     transparente. Al pasar por encima se rellena del color y el texto pasa a
     blanco.
   - `.boton-claro` sobre foto o panel oscuro: borde y texto blancos, fondo
     transparente. Al pasar por encima se rellena de blanco y el texto toma el
     color del tema.

   En las dos el hover cambia el FONDO y nada más: Jordi no quiere el salto de
   unos píxeles que hace la plantilla. Ese salto vive en base.css, que se
   regenera y no se edita:

       .btn:not(.btn-link):hover { transform: translateY(-.15rem); box-shadow: ... }

   Como es un selector con la misma especificidad que `.boton:hover` pero llega
   antes en la cascada, bastaría con el orden; se anula de forma explícita en
   una regla propia para que no dependa de qué fichero se cargue primero. */
.boton,
.boton-claro,
.boton-apagado {
	--bs-btn-bg: transparent;
	--bs-btn-active-shadow: none;
	border-radius: .25rem;
	border-width: 2px;
}

/* El salto vertical, fuera. El `box-shadow` se va con él: era la sombra que
   acompañaba al relieve y sin el movimiento queda fuera de sitio. */
.btn.boton:hover,
.btn.boton-claro:hover,
.btn.boton-apagado:hover,
.btn.boton:focus-visible,
.btn.boton-claro:focus-visible,
.btn.boton-apagado:focus-visible,
.btn.boton:active,
.btn.boton-claro:active,
.btn.boton-apagado:active {
	transform: translateY(0);
	box-shadow: none;
}

/* Sobre claro: el color del tema. `--bs-primary` lo redefine la paleta que
   tenga puesta el aula (red.css, blue.css...), así que esto vale para
   todas sin repetirlo por color. */
.boton {
	--bs-btn-color: var(--bs-primary);
	--bs-btn-border-color: var(--bs-primary);
	--bs-btn-hover-color: var(--bs-white);
	--bs-btn-hover-bg: var(--bs-primary);
	--bs-btn-hover-border-color: var(--bs-primary);
	--bs-btn-active-color: var(--bs-white);
	--bs-btn-active-bg: var(--bs-primary);
	--bs-btn-active-border-color: var(--bs-primary);
	--bs-btn-disabled-color: var(--bs-primary);
	--bs-btn-disabled-bg: transparent;
	--bs-btn-disabled-border-color: var(--bs-primary);
}

/* Sobre foto o panel oscuro: blanco. Es el que sale en la cabecera, en el pie
   y en el «Ver más» de las tres portadas. */
.boton-claro {
	--bs-btn-color: var(--bs-white);
	--bs-btn-border-color: var(--bs-white);
	--bs-btn-hover-color: var(--bs-primary);
	--bs-btn-hover-bg: var(--bs-white);
	--bs-btn-hover-border-color: var(--bs-white);
	--bs-btn-active-color: var(--bs-primary);
	--bs-btn-active-bg: var(--bs-white);
	--bs-btn-active-border-color: var(--bs-white);
	--bs-btn-disabled-color: var(--bs-white);
	--bs-btn-disabled-bg: transparent;
	--bs-btn-disabled-border-color: var(--bs-white);
}

/* La tercera variante, gris: misma forma, pero apagada. Es para las acciones
   secundarias que van al lado de una principal y no deben competir con ella
   —hoy solo «Quitar filtros», junto al «Buscar» de novedades—. Sustituye al
   `btn-soft-ash` de la plantilla, que era de relleno gris claro. */
.boton-apagado {
	--bs-btn-color: var(--bs-gray-600);
	--bs-btn-border-color: var(--bs-gray-400);
	--bs-btn-hover-color: var(--bs-white);
	--bs-btn-hover-bg: var(--bs-gray-600);
	--bs-btn-hover-border-color: var(--bs-gray-600);
	--bs-btn-active-color: var(--bs-white);
	--bs-btn-active-bg: var(--bs-gray-600);
	--bs-btn-active-border-color: var(--bs-gray-600);
	--bs-btn-disabled-color: var(--bs-gray-400);
	--bs-btn-disabled-bg: transparent;
	--bs-btn-disabled-border-color: var(--bs-gray-400);
}

/* El borde de 2px engorda el botón respecto al de relleno, que no lo tenía.
   En los pequeños —el «Entrar» de la cabecera, el «Contactar» del pie— se
   nota, así que se les recorta el alto para que sigan cuadrando con los
   iconos que tienen al lado. */
.btn-sm.boton,
.btn-sm.boton-claro,
.btn-sm.boton-apagado {
	padding-top: .35rem;
	padding-bottom: .35rem;
}


/* --------------------------------------------------- Franja de logos del pie

   Patrocinadores y aulas colaboradoras de una página (Jordi, 27/09/2026),
   en una banda blanca justo encima del pie.

   El reparto es `flex-wrap` con `justify-content: center`, y eso resuelve solo
   los dos casos que pidió Jordi: uno queda centrado, y varios se reparten y
   saltan de línea cuando no caben. No hace falta contar cuántos hay ni elegir
   anchos en PHP. */
.franja-logos {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	align-items: flex-start;
	gap: 2rem;
}

.logo-item {
	/* Ancho fijo, y por eso no encoge: los logos de una franja tienen que
	   verse todos del mismo tamaño, que es lo que los convierte en una fila
	   y no en un montón de imágenes sueltas. Con `flex: 1` el último de una
	   línea se estiraría hasta ocupar el hueco sobrante.

	   180 px para que entren SEIS por fila (Jordi, 27/09/2026). La cuenta, en
	   la pantalla más ancha que da la plantilla: el `.container` llega a
	   1320 px y se queda en 1296 útiles tras su relleno; menos los cinco
	   huecos de 2rem entre seis logos (160 px) quedan 1136, a 189 por logo.
	   Se bajan a 180 para que la fila no se parta por unos pocos píxeles
	   —una barra de desplazamiento, un borde— y sobre un poco de aire. */
	flex: 0 0 auto;
	width: 180px;
	text-align: center;
}

/* El marco: es el ancla del velo y lo que recibe el hover.

   Existe como elemento aparte porque tiene que poder ser un `<a>` cuando el
   logo lleva enlace y un `<span>` cuando no, sin que el CSS cambie. Lleva el
   `position: relative` del que cuelga el velo, y el `overflow: hidden` que
   recorta el velo a las esquinas redondeadas. */
.logo-marco {
	position: relative;
	display: block;
	overflow: hidden;
	border-radius: .35rem;
	/* Los logos van sobre blanco; el fondo importa cuando el velo se retira. */
	background-color: #fff;
}

/* Con enlace el cursor lo dice, y el foco de teclado se ve: es un enlace de
   verdad y hay que poder llegar a él tabulando. */
a.logo-marco {
	text-decoration: none;
}

a.logo-marco:focus-visible {
	outline: 2px solid var(--bs-primary);
	outline-offset: 2px;
}

/* El velo con el título y el subtítulo (Jordi, 27/09/2026: «el título y el
   subtítulo deben aparecer en un hover»).

   Está SIEMPRE en el HTML y se esconde con `opacity`, no con `display: none`.
   Dos razones: `display` no transiciona, y sobre todo un lector de pantalla
   lee igual el contenido oculto por opacidad, así que quien no usa ratón no
   se queda sin el dato. El hover es un adorno, no la única vía.

   `pointer-events: none` para que el velo no se interponga entre el ratón y
   el enlace que hay debajo. */
.logo-velo {
	position: absolute;
	inset: 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: .15rem;
	padding: .5rem;
	background-color: rgba(20, 22, 26, .82);
	border-radius: inherit;
	opacity: 0;
	transition: opacity .2s ease-in-out;
	pointer-events: none;
}

/* Se enseña al pasar el ratón y al llegar con el teclado. `focus-within`
   cubre el caso del enlace: al tabular hasta él, el velo aparece y se ve a
   dónde lleva. */
.logo-con-texto .logo-marco:hover .logo-velo,
.logo-con-texto .logo-marco:focus-within .logo-velo {
	opacity: 1;
}

/* Quien haya pedido menos movimiento ve el velo aparecer de golpe, sin el
   fundido. Sigue funcionando: solo se va la transición. */
@media (prefers-reduced-motion: reduce) {
	.logo-velo {
		transition: none;
	}
}

/* La caja cuadrada, que es el meollo.

   Los logos llegan como los manda cada aula: uno es una tira de 5:1 y el
   siguiente casi un cuadrado. Puestos en fila sin más, el apaisado se ve
   enorme y el vertical diminuto, y la franja queda desordenada.

   El cuadrado le da a todos el MISMO hueco, y `object-fit: contain` mete cada
   logo dentro respetando su proporción: el apaisado toca los lados y le sobra
   arriba y abajo, el vertical al revés. Ninguno se deforma ni se recorta.

   El relleno es lo que pidió Jordi («con el padding suficiente»): sin él, un
   logo cuadrado tocaría los bordes y se vería más grande que los demás aunque
   midan lo mismo.

   Va en PORCENTAJE y no en rem: un porcentaje de relleno se mide contra el
   ancho del propio elemento, así que el aire se mantiene en proporción si
   mañana la caja crece o encoge. Con rem habría que retocarlo a mano cada vez
   —y de hecho hubo que hacerlo al pasar de 140 a 180 px—. El 10% son 18 px en
   una caja de 180. */
.logo-caja {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	aspect-ratio: 1 / 1;
	padding: 10%;
}

/* `base.css` trae `figure img { height: auto !important }`, que gana a
   cualquier regla sin `!important`. Es la misma piedra con la que ya
   tropezaron las miniaturas del pie: sin estos dos, el logo ignora el alto de
   la caja y se sale por abajo. */
.logo-caja img {
	width: 100% !important;
	height: 100% !important;
	max-width: 100%;
	object-fit: contain;
}

/* Los textos van DENTRO del velo, sobre oscuro, así que son claros. Antes
   estaban debajo del logo sobre blanco y eran grises; cambió el 27/09/2026,
   al pasar al hover.

   `overflow-wrap` porque un nombre largo («Agora Portals International
   School») se sale del velo si no se le deja partir. */
.logo-titulo,
.logo-subtitulo {
	display: block;
	line-height: 1.3;
	overflow-wrap: anywhere;
	color: #fff;
}

.logo-titulo {
	font-size: .85rem;
	font-weight: 600;
}

.logo-subtitulo {
	font-size: .75rem;
	/* Algo más apagado que el título: se lee después, no compite con él. */
	color: rgba(255, 255, 255, .8);
}

/* En móvil los 180 px no caben de dos en dos: en una pantalla de 320 (un
   iPhone SE) quedan 296 útiles, y dos logos más su hueco piden 380. Se bajan
   a 138, que es el mayor ancho con el que entran dos en esos 296 contando el
   hueco de 1.25rem. De 360 px en adelante sobra sitio. */
@media (max-width: 575.98px) {
	.franja-logos {
		gap: 1.25rem;
	}

	.logo-item {
		width: 138px;
	}
}


/* --------------------------------------------- Listado de miembros (P?)

   La página de Miembros (Jordi, 27/09/2026): avatar, alias y año de
   nacimiento.

   `auto-fill` con un mínimo por ficha, en vez de elegir cuántas columnas van
   en cada tamaño de pantalla: el navegador mete las que quepan y reparte el
   sobrante. Con cincuenta fichas iguales es lo que menos reglas necesita —no
   hay media queries— y se adapta solo si mañana son diez o doscientas. */
.rejilla-miembros {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
	gap: 1.5rem 1rem;
	list-style: none;
	margin: 0;
	padding: 0;
}

/* La ficha es un <a>: toda ella lleva al perfil, que es un blanco mucho mayor
   que el alias solo y se acierta con el dedo en un móvil. */
.miembro {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	text-decoration: none;
}

/* Al pasar por encima solo se mueve el avatar, no la ficha entera: con
   cincuenta juntas, que cada una salte al rozarla marea. */
.miembro:hover .miembro-avatar,
.miembro:focus-visible .miembro-avatar {
	transform: scale(1.06);
}

.miembro:hover .miembro-alias {
	color: var(--bs-primary);
}

.miembro:focus-visible {
	outline: 2px solid var(--bs-primary);
	outline-offset: 4px;
	border-radius: .5rem;
}

/* El avatar, en círculo. Los ficheros son cuadrados con fondo transparente, y
   el fondo claro de debajo es lo que hace que se vea el círculo: sin él, un
   peón oscuro sobre la tarjeta blanca queda flotando sin forma. */
.miembro-avatar {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 88px;
	height: 88px;
	margin-bottom: .6rem;
	/* Margen interior: el dibujo no toca el borde del circulo (28/09/2026). */
	padding: 10px;
	border-radius: 50%;
	/* El palido de la paleta, como en la lista de miembros (28/09/2026). */
	background-color: var(--bs-pale-primary);
	overflow: hidden;
	transition: transform .15s ease-in-out;
}

/* Quien haya pedido menos movimiento no ve el crecer del avatar. */
@media (prefers-reduced-motion: reduce) {
	.miembro-avatar {
		transition: none;
	}

	.miembro:hover .miembro-avatar,
	.miembro:focus-visible .miembro-avatar {
		transform: none;
	}
}

/* `base.css` trae `figure img { height: auto !important }`. Aquí el padre es un
   <span> y no un <figure>, así que esa regla no aplica y no hacen falta
   !important: basta con dar la medida. */
.miembro-avatar img {
	width: 100%;
	height: 100%;
	object-fit: contain;
}

/* Sin avatar, la inicial. El mismo círculo, con el color del tema. */
.miembro-sin-avatar {
	font-size: 2rem;
	font-weight: 600;
	line-height: 1;
	color: #fff;
	background-color: var(--bs-primary);
}

.miembro-alias {
	display: block;
	font-size: .9rem;
	font-weight: 600;
	line-height: 1.25;
	/* Un alias largo («UnicornioMagico») no cabe en 120 px de ficha: se parte
	   en vez de desbordar y descuadrar la rejilla. */
	overflow-wrap: anywhere;
	color: var(--bs-gray-800);
}

.miembro-anyo {
	display: block;
	font-size: .8rem;
	color: var(--bs-gray-600);
}

/* En móvil entran tres por fila con fichas algo menores. */
@media (max-width: 575.98px) {
	.rejilla-miembros {
		grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
		gap: 1.25rem .75rem;
	}

	.miembro-avatar {
		width: 72px;
		height: 72px;
	}
}

/* ------------------------------------ Lista de miembros, en tarjetas

   El modulo de equipo de demo8.html de Sandbox (Jordi, 12/10/2026): avatar
   arriba a todo el ancho y una placa de color suave asomando por detras. La
   tarjeta entera es un enlace: sin subrayado y con el color del texto;
   `lift` levanta la tarjeta (no la placa) al pasar el raton. */
.tarjeta-miembro {
	color: inherit;
	text-decoration: none;
}

.tarjeta-miembro:hover .h4 {
	color: var(--bs-primary);
}

.tarjeta-miembro:focus-visible {
	outline: 2px solid var(--bs-primary);
	outline-offset: 3px;
	border-radius: .4rem;
}

/* La foto, CUADRADA. Los avatares son dibujos con fondo transparente: el
   hueco lleva el color palido de la paleta del aula, para que se vean
   sobre la tarjeta blanca (como el circulo de antes, Jordi 28/09/2026), con
   margen para que el dibujo no toque el borde y `contain` para que quepa
   entero. Las esquinas de arriba las redondea `.card-img-top`, pero la
   imagen se sale si el `figure` no recorta. */
.tarjeta-miembro-foto {
	aspect-ratio: 1;
	overflow: hidden;
	background-color: var(--bs-pale-primary);
}

.tarjeta-miembro-foto img {
	width: 100%;
	height: 100%;
	padding: 1.25rem;
	object-fit: contain;
}

/* La presentación de un grupo (grupos.php, módulo «Let's Talk» de demo4,
   18/10/2026): la foto a sangre en la mitad izquierda, recortada para llenar
   su alto; en móvil, arriba en 4:3. */
.grupo-presentacion {
	overflow: hidden;
}

.grupo-presentacion-foto {
	position: relative;
	aspect-ratio: 4 / 3;
}

.grupo-presentacion-foto img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

@media (min-width: 992px) {
	.grupo-presentacion-foto {
		aspect-ratio: auto;
		min-height: 20rem;
	}
}

/* Dos por fila en el móvil (18/10/2026): la tarjeta mide la mitad, así que
   menos relleno y letra más pequeña para que el alias quepa. */
@media (max-width: 575.98px) {
	.tarjeta-miembro-foto img {
		padding: .6rem;
	}

	.tarjeta-miembro .card-body {
		padding: .75rem .5rem !important;
	}

	.tarjeta-miembro .h4 {
		font-size: .95rem;
		overflow-wrap: anywhere;
	}

	.tarjeta-miembro .meta,
	.tarjeta-miembro .fs-15 {
		font-size: .75rem !important;
	}
}

/* Sin avatar, la inicial, ocupando el cuadro con el color del tema. */
.tarjeta-miembro-inicial {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 100%;
	font-size: 4.5rem;
	font-weight: 700;
	color: #fff;
	background-color: var(--bs-primary);
}

/* ------------------------------------------------ El perfil de un miembro

   La ficha de uno, a la que se llega desde el listado con `?m=<id>`. Desde el
   12/10/2026 la preside la tarjeta del primer módulo de demo8.html (Jordi):
   avatar a la izquierda, datos a la derecha (sin la placa flotante del
   original: se probó y Jordi la quitó).

   Los avatares son recortes con fondo transparente, como la foto del
   original: van sueltos, sin círculo, a 320 px como mucho. */
.perfil-hero-foto {
	display: block;
	width: 100%;
	max-width: 320px;
	aspect-ratio: 1;
}

.perfil-hero-foto img {
	width: 100%;
	height: 100%;
	object-fit: contain;
}

/* Sin avatar, la inicial en un círculo del color del tema. */
.perfil-hero-inicial {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 100%;
	border-radius: 50%;
	font-size: 6rem;
	font-weight: 700;
	color: #fff;
	background-color: var(--bs-primary);
}

.perfil-hero-grupos {
	display: flex;
	flex-wrap: wrap;
	gap: .4rem;
}

@media (max-width: 991.98px) {
	.perfil-hero-grupos {
		justify-content: center;
	}

	.perfil-hero-foto {
		max-width: 240px;
	}
}

/* ------------------------------------------- El título de una página normal

   La misma tarjeta que la ficha de un miembro (Jordi, 12/10/2026), con la
   imagen de la página a la derecha. Son fotos, no recortes: redondeadas y
   con un tope de alto, para que una vertical no estire la tarjeta. */
.titulo-caja-imagen img {
	display: block;
	width: 100%;
	max-height: 24rem;
	object-fit: cover;
	border-radius: .8rem;
}

/* EL TEXTO A UN ANCHO CÓMODO (Jordi, 18/10/2026): en las páginas largas las
   líneas pasaban de 120 caracteres. Los bloques de texto del cuerpo, a unos
   75 caracteres y centrados en la caja; las imágenes, tablas, vídeos y
   galerías que haya dentro del texto siguen a todo el ancho. */
.texto-legible > p,
.texto-legible > ul,
.texto-legible > ol,
.texto-legible > h2,
.texto-legible > h3,
.texto-legible > h4,
.texto-legible > h5,
.texto-legible > blockquote,
.texto-legible > dl {
	/* 720 px son unos 75 caracteres con la letra del cuerpo. Fijo y no en
	   `ch`: el `ch` se mide con la letra de cada bloque y los subtítulos,
	   más grandes, quedaban más anchos que los párrafos. */
	max-width: 720px;
	margin-left: auto;
	margin-right: auto;
}

/* LA LETRA DEL CUERPO A 18 PX (Jordi, 18/10/2026: «el tamaño de la letra
   dentro del cuerpo lo veo algo pequeño»). Solo el texto de las páginas y
   noticias (párrafos, listas y citas); tarjetas, listados y formularios
   siguen a 16 px. Interlineado en proporción. Con los 720 px de
   `.texto-legible`, unos 70 caracteres por línea. */
.texto-cuerpo > p,
.texto-cuerpo > ul,
.texto-cuerpo > ol,
.texto-cuerpo > blockquote,
.texto-cuerpo > dl {
	font-size: 18px;
	line-height: 1.7;
}

.texto-cuerpo > ul li,
.texto-cuerpo > ol li {
	font-size: inherit;
	line-height: inherit;
}

/* La imagen bajo la franja del título (pagina-clasica.php, 18/10/2026): a todo
   el ancho de la caja blanca, sin relleno. Con tope de alto para que una foto
   4:3 no ocupe la pantalla entera; lo que sobra se recorta por arriba y por
   abajo, centrado. */
.imagen-bajo-franja img {
	display: block;
	width: 100%;
	max-height: 34rem;
	object-fit: cover;
}

/* La foto A SANGRE en la cabecera de una página (pagina.php, 18/10/2026): la
   mitad derecha entera, sin relleno; la tarjeta recorta las esquinas. En
   ancho, la foto toma el alto de la tarjeta (el que pida el texto, con un
   mínimo para que no quede una franja); en móvil va arriba en 4:3. */
.titulo-caja-sangre {
	overflow: hidden;
}

.titulo-caja-foto {
	position: relative;
	aspect-ratio: 4 / 3;
}

/* Los `!important`, por el carrusel de la portada en caja (18/10/2026):
   base.css deja las imágenes de un Swiper a su altura natural con una regla
   que ganaba a esta, y cada foto se quedaba con su proporción en vez de
   llenar la columna (Jordi lo vio en las de texto corto). */
.titulo-caja-foto img {
	position: absolute;
	inset: 0;
	width: 100% !important;
	height: 100% !important;
	max-width: none !important;
	object-fit: cover;
}

.titulo-caja-texto {
	display: flex;
	flex-direction: column;
	justify-content: center;
}

@media (min-width: 992px) {
	.titulo-caja-foto {
		aspect-ratio: auto;
		min-height: 22rem;
	}
}

/* ---------------------------------------- Intentos de problemas (la ficha)

   Los ultimos problemas que ha intentado un miembro (Jordi, 27/09/2026).
   Se guardan TODOS los intentos, acertados o no, asi que la marca de la
   izquierda es lo que distingue de un vistazo unos de otros. */
.lista-intentos {
	list-style: none;
	margin: 0;
	padding: 0;
}

.intento {
	display: flex;
	align-items: flex-start;
	gap: .75rem;
	padding: .6rem 0;
	border-bottom: 1px solid var(--bs-gray-300);
}

.intento:last-child {
	border-bottom: 0;
}

/* La marca: un circulo con la cruz o el visto. Rojo apagado por defecto, que
   es lo que ve un intento fallido, y verde cuando se resolvio. No se fia solo
   del color —lleva icono distinto— para quien no distinga ambos. */
.intento-marca {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 28px;
	height: 28px;
	border-radius: 50%;
	font-size: .9rem;
	color: #fff;
	background-color: var(--bs-gray-500);
}

.intento-ok .intento-marca {
	background-color: #2fa76b;
}

.intento-datos {
	flex: 1 1 auto;
	min-width: 0;
}

.intento-titulo {
	display: block;
	font-size: .95rem;
	line-height: 1.3;
}

/* Las jugadas, en monoespaciada: son notacion, no prosa, y asi se leen mejor.
   `break-all` porque una partida larga no cabe en la columna del movil. */
.intento-jugadas {
	display: block;
	margin-top: .15rem;
	font-family: var(--bs-font-monospace, monospace);
	font-size: .78rem;
	color: var(--bs-gray-600);
	word-break: break-all;
}

.intento-fecha {
	flex: 0 0 auto;
	font-size: .78rem;
	color: var(--bs-gray-600);
	white-space: nowrap;
}

@media (max-width: 575.98px) {
	/* En movil la fecha baja bajo el titulo: en una sola linea no cabe con la
	   notacion de la partida al lado. */
	.intento {
		flex-wrap: wrap;
	}

	.intento-fecha {
		width: 100%;
		padding-left: calc(28px + .75rem);
	}
}

/* ------------------------------- Ejercicios de la ficha de un miembro

   Los doce ultimos ejercicios que ha hecho, con su tablero, la fecha del
   ultimo intento y un icono de resuelto o no (Jordi, 27/09/2026).

   Van en UNA SOLA LINEA, en carrusel (Jordi, 27/09/2026). Antes era una
   rejilla que envolvia a varias filas y con doce ejercicios ocupaba media
   ficha. Cuantos caben por pantalla lo decide Swiper con los `data-items-*`
   de la plantilla; aqui solo queda el aire de debajo, que el carrusel necesita
   para su paginador. */
.carrusel-ejercicios {
	margin-bottom: 2.5rem;
}

.ejercicio-enlace {
	display: block;
	text-decoration: none;
	color: inherit;
}

/* El tablero y su icono: el `relative` es el ancla del icono, que va encima. */
.ejercicio-tablero {
	position: relative;
	display: block;
}

/* La variante pequenya del diagrama. `.diagrama` ya trae la rejilla de 8x8 y
   las casillas cuadradas; aqui solo se acota el ancho y se redondea. */
.diagrama-mini {
	width: 100%;
	border-radius: .35rem;
	overflow: hidden;
}

/* El icono, sobre la esquina inferior derecha del tablero. Gris cuando no se
   resolvio y verde cuando si; el icono TAMBIEN cambia (cruz o visto), que es
   lo que lo hace legible para quien no distinga los dos colores. */
.ejercicio-marca {
	position: absolute;
	right: -.35rem;
	bottom: -.35rem;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 26px;
	height: 26px;
	border-radius: 50%;
	font-size: .85rem;
	color: #fff;
	background-color: var(--bs-gray-500);
	/* El borde claro lo despega del tablero, que tiene casillas oscuras. */
	box-shadow: 0 0 0 2px #fff;
}

.ejercicio-ok .ejercicio-marca {
	background-color: #2fa76b;
}

.ejercicio-pie {
	display: block;
	margin-top: .6rem;
	font-size: .78rem;
	line-height: 1.3;
	color: var(--bs-gray-600);
	text-align: center;
}

/* Aqui estuvo `.ejercicio-veces`, el «N intentos» bajo la fecha. Se quito el
   27/09/2026: Jordi solo quiere ver el resultado del ultimo intento. */

/* Al pasar por encima, solo el tablero se levanta un poco: es el gesto que
   dice que se puede pulsar, sin mover la fecha de debajo. */
.ejercicio-enlace:hover .diagrama-mini {
	box-shadow: 0 .25rem .75rem rgba(30, 34, 40, .2);
}

.ejercicio-enlace:focus-visible {
	outline: 2px solid var(--bs-primary);
	outline-offset: 3px;
	border-radius: .35rem;
}

/* Aqui habia una media query para la rejilla, que ya no existe: cuantos
   tableros caben lo decide ahora Swiper con `data-items-xs`, y son dos en
   movil por la misma razon que antes —con tres, el tablero es ilegible—. */

/* ------------------------------------------------------------- Grupos

   Las clases o niveles del aula, con su pagina propia (Jordi,
   27/09/2026). El listado son tarjetas; la pagina de un grupo reutiliza la
   rejilla de miembros, que es lo que hace que se reconozcan como las mismas
   fichas. */
.tarjeta-grupo {
	display: flex;
	align-items: center;
	gap: 1rem;
	height: 100%;
	padding: 1rem;
	border: 1px solid var(--bs-gray-300);
	border-radius: .5rem;
	text-decoration: none;
	color: inherit;
	transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
}

.tarjeta-grupo:hover {
	border-color: var(--bs-primary);
	box-shadow: 0 .25rem .75rem rgba(30, 34, 40, .1);
}

.tarjeta-grupo:focus-visible {
	outline: 2px solid var(--bs-primary);
	outline-offset: 2px;
}

.tarjeta-grupo-foto {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 72px;
	height: 72px;
	border-radius: .4rem;
	background-color: var(--bs-gray-200);
	overflow: hidden;
}

.tarjeta-grupo-foto img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.tarjeta-grupo-texto {
	display: block;
	min-width: 0;
}

.tarjeta-grupo-nombre {
	display: block;
	margin-bottom: .25rem;
	font-size: 1.05rem;
	font-weight: 600;
	line-height: 1.25;
	color: var(--bs-gray-800);
}

.tarjeta-grupo:hover .tarjeta-grupo-nombre {
	color: var(--bs-primary);
}

.tarjeta-grupo-dato {
	display: block;
	font-size: .8rem;
	line-height: 1.4;
	color: var(--bs-gray-600);
}

/* El listado de grupos con los modulos largos de career2.html (Jordi,
   28/09/2026). La imagen del grupo ocupa el circulo de las iniciales del
   original; sin imagen, las iniciales en el color del tema. */
.tarjeta-grupo-larga {
	text-decoration: none;
}

/* Todo círculo de las tarjetas largas (grupos y sesiones), círculo de verdad
   (Jordi, 11/10/2026). Los de iniciales e icono salían como elipse de 88×45:
   el `.avatar` VIEJO de front.css (el de la ficha de perfil anterior al
   tema) pone `flex: 0 0 88px`, y esa base de 88 px le gana al ancho de
   `w-9`. Medido en Chrome, no supuesto. Con `auto` manda el ancho de la
   clase, y sin encogerse junto a un nombre largo. Los de logo ya lo tenían
   por `.avatar-grupo`. */
.tarjeta-grupo-larga .avatar {
	flex: 0 0 auto;
}

.avatar-grupo {
	flex: 0 0 auto;
	overflow: hidden;
	background-color: var(--bs-pale-primary);
}

.avatar-grupo img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Un logo (11/10/2026): entero, sin recortar, sobre blanco y con un poco de
   aire dentro del círculo. `cover` le cortaba los lados a uno apaisado. Un
   borde fino del color de la paleta, para que un logo con fondo blanco no se
   pierda sobre la tarjeta blanca. */
.avatar-grupo.avatar-logo {
	background-color: #fff;
	border: 1px solid var(--bs-pale-primary);
	padding: 6px;
}

.avatar-grupo.avatar-logo img {
	object-fit: contain;
}

.tarjeta-grupo-larga .nombre-grupo {
	font-weight: 700;
	color: var(--bs-gray-800);
}

.tarjeta-grupo-larga:hover .nombre-grupo {
	color: var(--bs-primary);
}

.tarjeta-grupo-larga:focus-visible {
	outline: 2px solid var(--bs-primary);
	outline-offset: 2px;
}

/* Un subgrupo bajo su padre en la lista de grupos (Jordi, 11/10/2026):
   sangrado y con una línea del color del tema a la izquierda, para que se lea
   «esto cuelga de lo de arriba». En el móvil, sin sangría: no sobra ancho. */
.tarjeta-subgrupo {
	border-left: 3px solid var(--bs-primary);
}

@media (min-width: 768px) {
	.tarjeta-subgrupo {
		margin-left: 3rem;
	}
}

.tarjeta-subgrupo .nombre-grupo {
	font-weight: 600;
}

/* Desplegables con jerarquía (grupo → subgrupo), Jordi 11/10/2026: el grupo
   en negrita y el subgrupo sangrado. El padding solo lo aplican algunos
   navegadores dentro de un <option>; por eso la opción lleva además unos
   espacios delante (Grupos::estiloOpcion). */
option.opcion-principal {
	font-weight: 700;
}

option.opcion-sangrada {
	font-weight: 400;
	padding-left: 1.25rem;
}

/* El distintivo del monitor, en el sitio donde los demas llevan el anyo: es un
   dato mas de la ficha, no una medalla. */
.miembro-monitor {
	display: inline-block;
	padding: .05rem .45rem;
	border-radius: 1rem;
	font-size: .68rem;
	font-weight: 600;
	color: #fff;
	background-color: var(--bs-primary);
}

@media (max-width: 575.98px) {
	.tarjeta-grupo-foto {
		width: 56px;
		height: 56px;
	}
}

/* ---------------------------------------------------- Sesiones de juego

   La pagina de una sesion (Jordi, 27/09/2026): mesas en juego, clasificacion
   y partidas, a la vista de cualquiera para proyectarla en la sala. Quien la
   administra ve ademas los botones. Las tarjetas del listado son las de los
   grupos, sin foto. */

/* El estado, como pastilla: sobre la cabecera oscura y en las tarjetas. */
.estado-sesion {
	display: inline-block;
	padding: .2rem .7rem;
	border-radius: 1rem;
	font-size: .75rem;
	font-weight: 600;
	letter-spacing: .02em;
	text-transform: uppercase;
	color: #fff;
	background-color: var(--bs-gray-600);
	white-space: nowrap;
}

.estado-en-marcha {
	background-color: var(--bs-primary);
}

.tarjeta-sesion {
	min-height: 100%;
}

/* La barra de acciones de quien administra. */
.barra-sesion {
	display: flex;
	flex-wrap: wrap;
	gap: .5rem;
}

/* Las tablas de la ficha (Jordi, 28/09/2026): partidas en juego, finalizadas,
   lista de espera y clasificacion. Filas altas, porque cada jugador ocupa dos
   lineas junto a su avatar. */
.tabla-sesion td {
	vertical-align: middle;
}

.tabla-sesion th {
	font-size: .75rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: .03em;
	color: var(--bs-gray-600);
	white-space: nowrap;
}

/* La clasificacion del Masnou (12/10/2026) tiene una columna mas que la del
   Carrusel (puntos y perdidos) y va en la columna estrecha de la derecha:
   menos margen a los lados para que quepa sin barra de desplazamiento. */
.tabla-masnou > :not(caption) > * > * {
	padding-left: .35rem;
	padding-right: .35rem;
}

/* El numero de mesa, en su circulo. Para quien administra es un <button> (la
   entrada del teclado al lightbox): se le quita el aspecto de boton. */
.mesa-numero {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2.25rem;
	height: 2.25rem;
	padding: 0;
	border: 0;
	border-radius: 50%;
	font-size: 1rem;
	font-weight: 700;
	line-height: 1;
	color: #fff;
	background-color: var(--bs-primary);
}

button.mesa-numero {
	cursor: pointer;
}

button.mesa-numero:focus-visible {
	outline: 2px solid var(--bs-primary);
	outline-offset: 2px;
}

/* Un jugador: avatar de dos lineas de alto; a su lado, el alias arriba y la
   categoria debajo. */
.jugador-celda {
	display: flex;
	align-items: center;
	gap: .6rem;
	min-width: 0;
}

.jugador-avatar {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 2.6rem;
	height: 2.6rem;
	/* Margen interior: el dibujo no toca el borde del circulo (28/09/2026). */
	padding: .3rem;
	border-radius: 50%;
	overflow: hidden;
	/* El palido de la paleta, como en la lista de miembros (28/09/2026). */
	background-color: var(--bs-pale-primary);
}

/* `base.css` trae `figure img { height: auto !important }`; aqui no hay
   figure, pero se fija igual para que el avatar no se deforme. */
.jugador-avatar img {
	width: 100%;
	height: 100%;
	object-fit: contain;
}

.jugador-sin-avatar {
	font-weight: 700;
	color: #fff;
	background-color: var(--bs-primary);
}

.jugador-texto {
	display: flex;
	flex-direction: column;
	min-width: 0;
	line-height: 1.25;
}

.jugador-alias {
	font-weight: 600;
	color: var(--bs-gray-800);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.jugador-categoria {
	font-size: .78rem;
	color: var(--bs-gray-600);
	white-space: nowrap;
}

.jugador-inactivo .jugador-alias {
	color: var(--bs-gray-500);
}

/* Las filas que abren el lightbox: se ve que se pueden pulsar. */
.fila-resultado {
	cursor: pointer;
}

.tabla-sesion > tbody > tr.fila-resultado:hover > * {
	background-color: var(--bs-pale-primary);
}

/* El lightbox de resultados: un <dialog> nativo, centrado, sobre fondo
   oscuro. */
.dialogo-resultado {
	width: min(32rem, calc(100vw - 2rem));
	padding: 1.75rem;
	border: 0;
	border-radius: .5rem;
	box-shadow: 0 1rem 3rem rgba(30, 34, 40, .3);
}

.dialogo-resultado::backdrop {
	background-color: rgba(30, 34, 40, .6);
}

.opciones-resultado {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: .5rem;
}

.opcion-resultado {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: .15rem;
	margin: 0;
	padding: .75rem .5rem;
	white-space: normal;
}

.opcion-marcador {
	font-size: 1.35rem;
	font-weight: 700;
	line-height: 1;
}

.opcion-texto {
	font-size: .78rem;
	line-height: 1.2;
}

/* Las incomparecencias caen solas en la segunda fila (3 columnas, 5 botones),
   y se ven menos: son la excepcion. */
.opcion-secundaria .opcion-marcador {
	font-size: 1.1rem;
}

@media (max-width: 575.98px) {
	.opciones-resultado {
		grid-template-columns: 1fr;
	}
}

/* Las partidas en la ficha de un miembro: una sesion por bloque, y sus
   partidas con una marca de color a la izquierda segun lo que saco. */
.sesion-miembro + .sesion-miembro {
	margin-top: 1.5rem;
}

.partidas-miembro {
	list-style: none;
	padding: 0;
	margin: 0;
}

.partidas-miembro li {
	padding: .15rem 0 .15rem .75rem;
	border-left: 3px solid var(--bs-gray-300);
}

.partidas-miembro .saca-gana {
	border-left-color: var(--bs-primary);
}

.partidas-miembro .saca-tablas {
	border-left-color: var(--bs-gray-500);
}

.partida-saca {
	display: inline-block;
	min-width: 4rem;
	font-weight: 600;
	color: var(--bs-gray-800);
}

.jugador-inactivo {
	color: var(--bs-gray-500);
}

/* Los jugadores, para activar y desactivar: en columnas, compactos. */
.lista-jugadores {
	list-style: none;
	padding: 0;
	columns: 2 18rem;
	column-gap: 2rem;
}

.lista-jugadores li {
	display: flex;
	align-items: center;
	gap: .5rem;
	padding: .3rem 0;
	break-inside: avoid;
}

.lista-jugadores-alias {
	flex: 1 1 auto;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.inscribir > summary {
	list-style: none;
}

.inscribir > summary::-webkit-details-marker {
	display: none;
}

.casillas-inscribir {
	columns: 3 11rem;
	column-gap: 1.5rem;
}

.casillas-inscribir .form-check {
	break-inside: avoid;
}

/* El porque de un emparejamiento incompleto: es un registro, se lee mejor en
   monoespaciada. */
.registro-emparejamiento {
	max-height: 20rem;
	overflow: auto;
	font-size: .75rem;
	white-space: pre-wrap;
}

/* Avisos tras guardar (_cabecera.php): NOTIFICACIONES EN LA ESQUINA INFERIOR
   DERECHA (Jordi, 18/10/2026, opción A; antes flotaban arriba en el centro,
   pegadas al menú). Por encima de la barra pegajosa (1020) y por debajo del
   menú lateral (1045). En el gestor suben por encima de la barra de Guardar,
   que también va abajo. En el móvil, a todo el ancho con su margen. */
.avisos-flotantes {
	position: fixed;
	right: 1.5rem;
	bottom: 1.5rem;
	z-index: 1035;
	display: flex;
	flex-direction: column;
	gap: .75rem;
	width: min(24rem, calc(100% - 2rem));
}

body:has(.barra-guardar) .avisos-flotantes {
	bottom: 6rem;
}

@media (max-width: 575.98px) {
	.avisos-flotantes {
		right: 1rem;
		bottom: 1rem;
	}
}

.aviso {
	position: relative;
	display: flex;
	align-items: flex-start;
	gap: .75rem;
	padding: .9rem 2.75rem .9rem 1rem;
	overflow: hidden;
	background: #fff;
	border-left: 4px solid var(--aviso-color);
	border-radius: .5rem;
	box-shadow: 0 .5rem 2rem rgba(30, 34, 40, .18);
	font-size: .9rem;
	line-height: 1.45;
	color: #343f52;
	opacity: 0;
	transform: translateY(.75rem);
	transition: opacity .25s ease, transform .25s ease;
}

.aviso.show {
	opacity: 1;
	transform: none;
}

.aviso-exito    { --aviso-color: #45c4a0; --aviso-fondo: #e7f8f3; }
.aviso-atencion { --aviso-color: #e6a700; --aviso-fondo: #fdf5dc; }
.aviso-error    { --aviso-color: #e2626b; --aviso-fondo: #fcebec; }

.aviso-icono {
	flex-shrink: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 1.9rem;
	height: 1.9rem;
	border-radius: 50%;
	background: var(--aviso-fondo);
	color: var(--aviso-color);
	font-size: 1.1rem;
}

.aviso-texto {
	align-self: center;
}

.aviso-cerrar {
	position: absolute;
	top: .55rem;
	right: .55rem;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 1.75rem;
	height: 1.75rem;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: transparent;
	color: #959ca9;
	font-size: 1.1rem;
	line-height: 1;
	cursor: pointer;
}

.aviso-cerrar:hover,
.aviso-cerrar:focus-visible {
	background: #f1f3f6;
	color: #343f52;
}

/* La barrita de abajo: se vacía en los 5 s que tarda en irse (default.js). */
.aviso-tiempo {
	position: absolute;
	left: 0;
	bottom: 0;
	height: 3px;
	width: 100%;
	background: var(--aviso-color);
	transform-origin: left;
	animation: aviso-tiempo 5s linear forwards;
}

@keyframes aviso-tiempo {
	to { transform: scaleX(0); }
}

@media (prefers-reduced-motion: reduce) {
	.aviso { transition: none; }
	.aviso-tiempo { animation: none; }
}

/* ------------------------------------------ Huecos entre bloques (13/10/2026)

   Jordi: «revisa los márgenes entre el menú, el cuerpo, las cards y el pie;
   no les veo relación». Medidos, iban de 30 a 70 px sin regla. Ahora UN solo
   hueco, `--hueco` (30 px en ancho), en todos: menú → primer bloque, entre
   bloques del cuerpo, cuerpo → tarjetas del pie, tarjetas → caja del pie,
   caja → línea de aula64, y entre tarjeta y tarjeta del carrusel del pie
   (`$juntas` en _carrusel-tarjetas.php: el relleno de `.item-inner`).

   Solo con el fondo fijo (siempre que hay aula): es donde los bloques
   flotan sobre la foto y el hueco se ve. Se hace con !important porque pisa
   los `pt-16`, `pt-8`, `pb-14`… que cada plantilla lleva puestos. */
:root {
	--hueco: 1.5rem;
	/* Lo que mide el menú de dos filas desde arriba de la página, hasta el
	   borde de abajo de la barra blanca. */
	--alto-menu: 7rem;
	/* El aire que el carrusel deja arriba y abajo de las tarjetas (medido). */
	--aire-tarjetas: 20px;
}

/* En tableta y móvil el menú es otro (barra de una pieza con las tres
   rayas) y llega más abajo. */
@media (max-width: 991.98px) {
	:root {
		--alto-menu: 7.65rem;   /* 153 px, medido a 800 */
	}
}

/* En el móvil, la mitad: unos 14 px, lo mismo que el margen de los lados. */
@media (max-width: 575.98px) {
	:root {
		--hueco: .75rem;
		--alto-menu: 7.9rem;    /* 142 px con la letra a 18 px, medido a 500 */
	}
}

/* La barra blanca, del mismo alto en todas las aulas: con el
   desplegable del aula (megaescacs) medía 5px más que sin él. */
@media (min-width: 992px) {
	.navbar-expand-lg.fancy.cabecera-doble:not(.fixed) .navbar-collapse-wrapper {
		min-height: 4.15rem;
	}
}

body.fondo-fijo #contenido > section.wrapper > .container,
body.fondo-fijo #contenido > section.wrapper:last-of-type > .container {
	padding-top: var(--hueco) !important;
	padding-bottom: 0 !important;
}

body.fondo-fijo #contenido > section.wrapper:first-of-type:not(.foto-bajo-menu) {
	padding-top: 0 !important;
}

body.fondo-fijo #contenido > section.wrapper:first-of-type:not(.foto-bajo-menu) > .container {
	padding-top: calc(var(--alto-menu) + var(--hueco)) !important;
}

/* El pie: tarjetas, caja y línea de aula64, separadas por el mismo hueco.
   Las tarjetas del carrusel llevan su propio aire arriba y abajo para la
   sombra (`--aire-tarjetas`): se descuenta. */
body.fondo-fijo .pie-sobre-fondo > .container {
	padding-top: var(--hueco) !important;
	padding-bottom: 0 !important;
}

body.fondo-fijo .pie-slider {
	margin-top: calc(-1 * var(--aire-tarjetas, 0px));
	margin-bottom: calc(var(--hueco) - var(--aire-tarjetas, 0px));
}

body.fondo-fijo .pie-aula64 {
	margin-top: 0;
	padding-top: var(--hueco);
	padding-bottom: var(--hueco);
}

/* Problemas, dentro de la caja blanca (13/10/2026): el paginador, el
   resultado y el marco del tablero vuelven a los colores para fondo claro
   (estaban pensados para la cabecera oscura). */
.caja-problema .paginador-problema {
	background: var(--bs-soft-primary, rgba(var(--bs-primary-rgb), .08));
}

.caja-problema .paginador-problema-cuenta,
.caja-problema .paginador-problema-salto {
	color: var(--bs-primary);
}

.caja-problema .paginador-problema-salto:hover,
.caja-problema .paginador-problema-salto:focus-visible {
	color: #fff;
}

.caja-problema .paginador-problema-salto.inactivo {
	background: transparent;
}

.caja-problema .resultado-problema.no-es-mate {
	color: #60697b;
}

.caja-problema .board-b72b1 {
	border-color: rgba(164, 174, 198, .35);
}

/* -------------------------------------------- Buscador global (13/10/2026)

   Los resultados van por apartados (páginas, grupos, sesiones, miembros),
   separados como los bloques de la portada. Las páginas, en el módulo largo
   de grupos y sesiones con una miniatura 3:2 en vez del círculo. Lo buscado,
   marcado con el color clarito del tema. */
.resultados-apartado + .resultados-apartado {
	margin-top: 3rem;
}

.resultado-miniatura {
	flex-shrink: 0;
	width: 5.25rem;
	aspect-ratio: 3 / 2;
	overflow: hidden;
	border-radius: .4rem;
}

.resultado-miniatura img {
	width: 100%;
	height: 100% !important;   /* base.css: figure img{height:auto!important} */
	object-fit: cover;
}

.resultado-pagina mark,
.caja-con-franja mark {
	padding: 0 .1em;
	border-radius: .2rem;
	color: inherit;
	background-color: rgba(var(--bs-primary-rgb), .18);
}

/* ------------------------------------ Jugadas ilegales (13/10/2026)

   En el lightbox del resultado, dos botones más, «Ilegal de las blancas» e
   «Ilegal de las negras», en la misma rejilla que los seis de resultado
   (Jordi). La rejilla pasa a seis columnas: cada resultado ocupa dos (tres
   por fila, como antes) y cada ilegal tres (media fila).

   En las mesas, junto al nombre de quien la hizo, un círculo rojo; con más
   de una, el número dentro (Jordi). */
.opciones-resultado {
	grid-template-columns: repeat(6, 1fr);
}

.opciones-resultado > .opcion-resultado {
	grid-column: span 2;
}

.opciones-resultado > .opcion-ilegal {
	grid-column: span 3;
	/* Sin marcador encima: el «+» va en línea con el texto. */
	flex-direction: row;
}

@media (max-width: 575.98px) {
	.opciones-resultado {
		grid-template-columns: 1fr;
	}

	.opciones-resultado > .opcion-resultado,
	.opciones-resultado > .opcion-ilegal {
		grid-column: auto;
	}
}

.marca-ilegal {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	/* Siempre con el número dentro, también el 1 (Jordi, 13/10/2026). */
	width: 1.1rem;
	height: 1.1rem;
	margin-left: .3rem;
	border-radius: 50%;
	background-color: #e2282b;
	color: #fff;
	font-size: .62rem;
	font-weight: 700;
	line-height: 1;
	vertical-align: middle;
}

/* «Quitar ilegal de las …», justo debajo de su «Ilegal de las …» (Jordi,
   13/10/2026): media fila cada uno, como ellos. */
.opciones-resultado > .opcion-quitar-ilegal {
	grid-column: span 3;
	margin: 0;
}

@media (max-width: 575.98px) {
	.opciones-resultado > .opcion-quitar-ilegal {
		grid-column: auto;
	}
}

/* En el móvil, a una columna: cada «Quitar» justo debajo de su «Ilegal». */
@media (max-width: 575.98px) {
	.opciones-resultado > .opcion-lado-A  { order: 1; }
	.opciones-resultado > .opcion-quitar-A { order: 2; }
	.opciones-resultado > .opcion-lado-B  { order: 3; }
	.opciones-resultado > .opcion-quitar-B { order: 4; }
}

/* Los dos jugadores en la cabecera del lightbox del resultado (13/10/2026):
   la celda de las mesas, cada una bajo su bando, en dos columnas. */
.dialogo-jugadores {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 1rem;
}

.dialogo-bando {
	display: block;
	margin-bottom: .4rem;
	font-size: .7rem;
	font-weight: 700;
	letter-spacing: .02rem;
	text-transform: uppercase;
	color: #959ca9;
}

@media (max-width: 575.98px) {
	.dialogo-jugadores {
		grid-template-columns: 1fr;
	}
}

/* Pestañas «Resultados» / «Ilegales» del lightbox (13/10/2026). Sin JS: el
   radio marcado enseña su panel. Las etiquetas, en línea, subrayadas con el
   color del tema la activa, como las pestañas de la plantilla. */
.pestanas-resultado {
	display: flex;
	flex-wrap: wrap;
	column-gap: 1.5rem;
}

.pestana-radio {
	position: absolute;
	opacity: 0;
	pointer-events: none;
}

.pestana-etiqueta {
	margin-bottom: 1.25rem;
	padding-bottom: .4rem;
	border-bottom: 2px solid transparent;
	font-weight: 700;
	color: #959ca9;
	cursor: pointer;
}

.pestana-radio:checked + .pestana-etiqueta {
	color: var(--bs-primary);
	border-bottom-color: var(--bs-primary);
}

.pestana-radio:focus-visible + .pestana-etiqueta {
	outline: 2px solid var(--bs-primary);
	outline-offset: 2px;
}

.pestana-panel {
	display: none !important;
	flex-basis: 100%;
}

.pestana-radio-resultados:checked ~ .pestana-panel-resultados,
.pestana-radio-ilegales:checked ~ .pestana-panel-ilegales {
	display: grid !important;
}

/* El título recibe el foco al abrir el lightbox; sin recuadro. */
.titulo-dialogo:focus {
	outline: none;
}

/* Pestaña «Acciones» (13/10/2026): su panel, y la marca de quien ya está
   inactivo mientras juega (deja la sesión al acabar), junto al nombre. */
.pestana-radio-acciones:checked ~ .pestana-panel-acciones {
	display: grid !important;
}

.marca-se-va {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 1.1rem;
	height: 1.1rem;
	margin-left: .3rem;
	border-radius: 50%;
	background-color: #959ca9;
	color: #fff;
	font-size: .7rem;
	vertical-align: middle;
}

/* ---------------------- Lightbox de resultados, con el modal de Sandbox
   (Jordi, 13/10/2026, opciones A y A; docs/08-catalogo-sandbox.md). */
.dialogo-resultado {
	position: relative;
	width: min(36rem, calc(100vw - 2rem));
	padding: 2rem 2rem 1.5rem;
	border-radius: .8rem;
}

/* El aspa de Sandbox (`btn-close`), arriba a la derecha. */
.dialogo-cerrar {
	position: absolute;
	top: 1rem;
	right: 1rem;
}

/* La mesa, en una pastilla del color del tema. */
.mesa-pastilla {
	display: inline-block;
	margin: 0;
	padding: .3rem .9rem;
	border-radius: 2rem;
	font-size: .75rem;
	font-weight: 700;
	letter-spacing: .03rem;
	text-transform: uppercase;
	color: var(--bs-primary);
	background-color: rgba(var(--bs-primary-rgb), .1);
}

/* Cara a cara: los dos jugadores y el «VS» en medio. */
.enfrentamiento {
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	align-items: center;
	gap: .75rem;
}

.enfrentamiento-jugador {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	min-width: 0;
}

.enfrentamiento-avatar {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 5rem;
	height: 5rem;
	margin-bottom: .6rem;
	/* Aire dentro del círculo (Jordi, 13/10/2026): el avatar tocaba el borde. */
	padding: .55rem;
	overflow: hidden;
	border-radius: 50%;
	background-color: rgba(var(--bs-primary-rgb), .08);
}

.enfrentamiento-avatar img {
	width: 100%;
	height: 100% !important;
	object-fit: contain;
}

.enfrentamiento-sin-avatar {
	font-size: 2rem;
	font-weight: 700;
	color: #fff;
	background-color: var(--bs-primary);
}

.enfrentamiento-nombre {
	font-weight: 700;
	line-height: 1.25;
	color: #343f52;
	overflow-wrap: anywhere;
}

.enfrentamiento-detalle {
	margin-top: .15rem;
	font-size: .75rem;
	color: #959ca9;
}

.enfrentamiento-vs {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 2.6rem;
	height: 2.6rem;
	border-radius: 50%;
	font-size: .8rem;
	font-weight: 800;
	color: #fff;
	background-color: var(--bs-primary);
	box-shadow: 0 0 0 .35rem rgba(var(--bs-primary-rgb), .12);
}

/* Las pestañas «básicas» de Sandbox: raya gris bajo cada una, la activa en
   el color del tema. */
.pestana-etiqueta {
	margin-bottom: 1.25rem;
	padding-bottom: .5rem;
	border-bottom: 2px solid rgba(164, 174, 198, .25);
	font-size: .85rem;
}

/* MISMA ALTURA EN TODAS LAS PESTAÑAS (Jordi, 13/10/2026: «al cambiar de
   pestaña cambia la altura del lightbox»). Rejilla: las etiquetas en la
   fila 1 y TODOS los paneles en la misma celda de la fila 2, apilados; el
   de la pestaña marcada es el único visible. La celda mide lo que el más
   alto, así que la ventana no cambia de tamaño. `visibility: hidden` saca
   del recorrido del teclado los botones de los paneles ocultos. */
.pestanas-resultado {
	display: grid;
	grid-template-columns: repeat(3, max-content) 1fr;
	column-gap: 1.25rem;
}

.pestanas-resultado > .pestana-panel {
	display: grid !important;
	grid-row: 2;
	grid-column: 1 / -1;
	align-self: start;
	visibility: hidden;
}

.pestana-radio-resultados:checked ~ .pestana-panel-resultados,
.pestana-radio-ilegales:checked ~ .pestana-panel-ilegales,
.pestana-radio-acciones:checked ~ .pestana-panel-acciones {
	visibility: visible;
}

/* Las tres de siempre, en baldosas suaves que suben al pasar por encima. */
.baldosas-resultado {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: .6rem;
}

.baldosa-resultado {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: .3rem;
	padding: 1rem .5rem;
	border: 0;
	border-radius: .6rem;
	color: var(--bs-primary);
	background-color: rgba(var(--bs-primary-rgb), .08);
	cursor: pointer;
	transition: transform .15s ease, box-shadow .15s ease, background-color .15s ease;
}

.baldosa-resultado:hover,
.baldosa-resultado:focus-visible {
	transform: translateY(-3px);
	background-color: rgba(var(--bs-primary-rgb), .14);
	box-shadow: 0 .4rem 1rem rgba(30, 34, 40, .1);
}

.baldosa-resultado.es-actual {
	color: #fff;
	background-color: var(--bs-primary);
	cursor: default;
	transform: none;
	box-shadow: none;
}

.baldosa-marcador {
	font-size: 1.6rem;
	font-weight: 800;
	line-height: 1;
}

.baldosa-texto {
	font-size: .75rem;
	font-weight: 600;
	line-height: 1.2;
	overflow-wrap: anywhere;
}

/* Las incomparecencias: la excepción, en una línea discreta. */
.incomparecencias {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: .35rem;
	margin-top: 1rem;
	font-size: .78rem;
	color: #959ca9;
}

.incomparecencias-titulo {
	margin-right: .15rem;
}

.incomparecencia {
	padding: .2rem .65rem;
	border: 1px solid rgba(164, 174, 198, .4);
	border-radius: 2rem;
	font-size: .75rem;
	font-weight: 600;
	color: #60697b;
	background: #fff;
	cursor: pointer;
}

.incomparecencia:hover,
.incomparecencia:focus-visible {
	color: var(--bs-primary);
	border-color: var(--bs-primary);
}

.incomparecencia.es-actual {
	color: #fff;
	border-color: var(--bs-primary);
	background-color: var(--bs-primary);
	cursor: default;
}

/* El pie: eliminar en rojo discreto a la izquierda; a la derecha, lo demás. */
.dialogo-pie {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: .5rem;
	margin-top: 1.5rem;
	padding-top: 1rem;
	border-top: 1px solid rgba(164, 174, 198, .2);
}

.boton-texto-peligro {
	padding: 0;
	border: 0;
	font-size: .8rem;
	font-weight: 600;
	color: #e2626b;
	background: none;
	cursor: pointer;
}

.boton-texto-peligro:hover,
.boton-texto-peligro:focus-visible {
	color: #c7363f;
	text-decoration: underline;
}

@media (max-width: 575.98px) {
	.dialogo-resultado {
		padding: 1.5rem 1.25rem 1.25rem;
	}

	.enfrentamiento-avatar {
		width: 3.8rem;
		height: 3.8rem;
	}

	.baldosas-resultado {
		grid-template-columns: 1fr;
	}

	.baldosa-resultado {
		flex-direction: row;
		gap: .75rem;
		padding: .75rem 1rem;
	}
}

/* PIE PEGADO ABAJO (Jordi, 14/10/2026): en una página con poco contenido,
   la franja oscura de aula64 se quedaba a media pantalla. El contenedor
   mide al menos lo que la ventana y el <main> se estira para empujar el pie
   hasta abajo. Con contenido de sobra no cambia nada. */
.content-wrapper {
	display: flex;
	flex-direction: column;
	min-height: 100vh;
	min-height: 100dvh;
}

.content-wrapper > main {
	flex: 1 0 auto;
}

/* ====================================== Gestor con la cabecera de la web ==
 *
 * Jordi, 17/10/2026: el gestor usa la cabecera de dos filas, el fondo fijo y
 * el pie de la web; cada pantalla va en una caja blanca con el título en su
 * franja (`app/vistas/admin/tema/cabecera.php`). Aquí, lo que solo hace
 * falta en él. Sustituye a la barra propia del 14/10 (.logo-gestor,
 * .firma-aula64) y al menú lateral (.menu-gestor), que ya no existen.
 */

/* «Salir» es un botón (cierra la sesión por POST) que tiene que parecer un
   enlace de la barra: sin fondo, sin borde, con el color y el tamaño de los
   iconos de al lado. */
.boton-icono {
	background: none;
	border: 0;
	color: inherit;
	cursor: pointer;
	font: inherit;
	line-height: inherit;
}

.navbar .boton-icono.nav-link {
	padding: 0;
}

/* La caja blanca, hasta el pie (Jordi, 17/10/2026, opción B tras probarla):
   en las pantallas cortas del gestor no queda hueco de fondo entre la caja y
   el pie. El <main> ya crece hasta el pie (`.content-wrapper` en columna);
   aquí se encadena el estiramiento hasta la caja. Solo en el gestor: la web
   sigue con el hueco, que allí se pidió así (14/10). */
main:has(> .wrapper > .gestor-cuerpo) {
	display: flex;
	flex-direction: column;
}

main > .wrapper:has(> .gestor-cuerpo) {
	flex: 1 0 auto;
	display: flex;
	flex-direction: column;
}

.gestor-cuerpo {
	flex: 1 0 auto;
	display: flex;
	flex-direction: column;
}

.gestor-cuerpo > .caja-con-franja {
	flex: 1 0 auto;
}

/* La franja del título, algo más baja que en la web: es una herramienta, y
   los títulos de edición («Editar: Agora Megaescacs campeón de…») son largos. */
.gestor-cuerpo .titulo-franja {
	padding: 1.6rem 1.5rem;
}

.gestor-cuerpo .titulo-franja-texto {
	font-size: calc(1.2rem + .9vw);
}

@media (min-width: 1200px) {
	.gestor-cuerpo .titulo-franja-texto {
		font-size: 1.9rem;
	}
}

/* La barra de filtros de los listados: el buscador se lleva el sitio que
   sobre y los desplegables no pasan de 16rem. Sin el tope, el de «Sección»
   (con títulos de páginas largos) se comía la fila y el buscador quedaba en
   una «B». */
/* Más justos desde que el botón de alta comparte fila (17/10/2026): con los
   tres filtros de Páginas, a 16rem el botón saltaba a otra línea. */
.filtros-gestor .filtro-buscar {
	min-width: 10rem;
}

.filtros-gestor .form-select {
	max-width: 13rem;
}

@media (max-width: 575.98px) {
	.filtros-gestor .form-select {
		max-width: none;
	}
}

/* Filas más bajas: con 25 por pantalla, el relleno de la tabla del tema las
   dejaba en 73 px. */
.table-gestor > :not(caption) > * > * {
	padding: .55rem .85rem;
}

.table-gestor .btn-circle.btn-sm {
	width: 1.9rem;
	height: 1.9rem;
}

/* Las cajas que quedan DENTRO de la caja del gestor (los paneles plegables de
   una ficha, los apartados de Configuración): con borde y sin sombra, que
   sobre blanco la sombra del tema apenas se ve y la caja parecía flotar. */
.gestor-cuerpo .card-body .card {
	border: 1px solid var(--bs-border-color);
	box-shadow: none;
}

.gestor-cuerpo .card-body details.card[open] > summary {
	border-bottom: 1px solid var(--bs-border-color);
	margin-bottom: 1.25rem;
}

/* Los apartados del formulario (Contenido, Publicación, Lugar en la web):
   un rótulo con filete encima, en una sola columna. */
.apartado-gestor {
	margin: 0 0 2rem;
	padding: 0;
	border: 0;
}

/* Sobre una franja del clarito del aula (Jordi, 17/10/2026: «los
   subtítulos podrían tener un fondo clarito para destacar»): el mismo tono
   que la franja del título de la caja, así se ven de un vistazo. */
.apartado-gestor-titulo {
	float: none;
	width: 100%;
	margin-bottom: 1.25rem;
	padding: .65rem 1rem;
	border-radius: .4rem;
	background-color: var(--bs-soft-primary, rgba(var(--bs-primary-rgb), .08));
	font-size: .8rem;
	font-weight: 700;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--color-oscuro, color-mix(in srgb, var(--bs-primary) 75%, #000));
}

/* `clip` y no el `hidden` de la caja de la web: recorta igual las esquinas,
   pero no la convierte en contenedor de desplazamiento, que es lo que
   impedía a la barra de Guardar pegarse al pie de la ventana. */
.gestor-cuerpo .caja-con-franja {
	overflow: clip;
}

/* El campo de imagen (17/10/2026): la imagen a 240 px, a la izquierda, y las
   acciones a su lado; en el móvil, una debajo de otra. */
.campo-imagen {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 1rem 1.5rem;
}

.campo-imagen-vista {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 240px;
	min-height: 120px;
	max-width: 100%;
	overflow: hidden;
	border: 1px solid var(--bs-border-color);
	border-radius: .4rem;
	background: #f6f7f9;
}

.campo-imagen-vista img {
	display: block;
	width: 100%;
	height: auto;
	max-height: 240px;
	object-fit: contain;
}

/* Con proporción fija (las destacadas): igual que la tarjeta ancha de la
   portada (`.hero-tarjeta-ancha`, más arriba). Caja 4:3 (antes 3:2, hasta el
   18/10/2026); la foto a todo el alto y centrada, que solo pierde los lados
   si es más apaisada; detrás, su copia ampliada y difuminada rellena los
   lados si es más estrecha. */
.campo-imagen-vista.proporcion-4-3 {
	width: 300px;
	aspect-ratio: 4 / 3;
	min-height: 0;
	display: block;
}

/* Llenando el recuadro y recortando, como en la portada (18/10/2026, `cover`). */
.campo-imagen-vista.proporcion-4-3 .campo-imagen-foto {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	max-width: none;
	max-height: none;
	object-fit: cover;
}

.campo-imagen-vista.proporcion-4-3 .campo-imagen-fondo {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	max-height: none;
	object-fit: cover;
	filter: blur(14px) brightness(.85);
	transform: scale(1.15);
}

.campo-imagen-vista.proporcion-4-3 .campo-imagen-vacia {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
}

.campo-imagen-vista.proporcion-4-3 .campo-imagen-nueva {
	z-index: 1;
}

/* `hidden` manda en toda la zona de imagen: sin esto, los `display` de
   arriba (block, flex) lo pisaban y salían la imagen vacía o «Sin imagen». */
.campo-imagen [hidden] {
	display: none !important;
}

.campo-imagen-vacia {
	font-size: .7rem;
	color: #5a6270;
}

/* «Nueva, sin guardar», sobre la esquina de la imagen. */
.campo-imagen-nueva {
	position: absolute;
	top: .5rem;
	left: .5rem;
	padding: .15rem .55rem;
	border-radius: 1rem;
	background: var(--bs-primary);
	color: #fff;
	font-size: .6rem;
	font-weight: 700;
}

.campo-imagen-acciones {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: .75rem 1.25rem;
}

.campo-imagen-acciones label.btn {
	cursor: pointer;
}

/* El teclado llega al <input> oculto: el foco se dibuja en su botón. */
.campo-imagen-acciones:has(input[type=file]:focus-visible) label.btn {
	outline: 2px solid var(--bs-primary);
	outline-offset: 2px;
}

.campo-imagen-fichero {
	font-size: .7rem;
	color: #5a6270;
	word-break: break-all;
}

/* Las miniaturas de un panel de imágenes, a la vista con el panel cerrado
   (17/10/2026): una tira bajo su rótulo. */
.miniaturas-panel {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: .4rem;
	margin-top: .75rem;
	font-weight: 400;
}

.miniaturas-panel img {
	width: 64px;
	height: 48px;
	object-fit: cover;
	border-radius: .25rem;
	border: 1px solid var(--bs-border-color);
}

.miniaturas-mas {
	font-size: .7rem;
	color: #5a6270;
}

/* Cabeceras de listado que ordenan (17/10/2026): como el texto de la
   cabecera, con una flecha tenue; la columna activa, en el color de la
   aula y con la flecha del sentido. */
.orden-columna {
	color: inherit;
	text-decoration: none;
	white-space: nowrap;
}

.orden-columna i {
	margin-left: .2rem;
	opacity: .35;
}

.orden-columna:hover,
.orden-columna.activa {
	color: var(--bs-primary);
}

.orden-columna:hover i,
.orden-columna.activa i {
	opacity: 1;
}

/* Ordenar arrastrando en Estructura web (17/10/2026): el asa, la fila que se
   arrastra (atenuada) y la línea donde caerá. */
.arbol-paginas .asa-arrastre {
	flex: none;
	color: #aab0bc;
	cursor: grab;
	font-size: .9rem;
}

.arbol-paginas li[draggable]:hover .asa-arrastre {
	color: var(--bs-primary);
}

.arbol-paginas li.arrastrando {
	opacity: .45;
}

.arbol-paginas li.soltar-aqui {
	box-shadow: inset 0 2px 0 var(--bs-primary), inset 0 -2px 0 var(--bs-primary);
	background-color: var(--bs-soft-primary, rgba(var(--bs-primary-rgb), .08));
}

/* La casilla que filtra un desplegable largo («Dentro de»), justo encima. */
.buscador-lista {
	max-width: 22rem;
	margin-bottom: .5rem;
}

/* La casilla del código de un color, junto a su selector (17/10/2026): se
   puede teclear. */
.campo-hex {
	width: 6.5rem;
	font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
	font-size: .7rem;
	text-transform: lowercase;
}

/* Configuración (17/10/2026): el índice de apartados, arriba, y cada
   apartado con su franja clarita. `scroll-margin-top` deja sitio a la barra
   fija de arriba al saltar a un ancla, o el rótulo quedaba tapado. */
.indice-config {
	display: flex;
	flex-wrap: wrap;
	gap: .5rem;
	margin-bottom: 2.25rem;
}

.indice-config a {
	padding: .35rem .9rem;
	border: 1px solid var(--bs-border-color);
	border-radius: 2rem;
	font-size: .7rem;
	font-weight: 600;
	color: var(--color-oscuro, color-mix(in srgb, var(--bs-primary) 75%, #000));
	text-decoration: none;
}

.indice-config a:hover {
	border-color: var(--bs-primary);
	background-color: var(--bs-soft-primary, rgba(var(--bs-primary-rgb), .08));
}

.apartado-config {
	margin-bottom: 2.5rem;
	scroll-margin-top: 7rem;
}

/* Los textos atenuados del gestor (introducciones de apartado, recuentos),
   con el gris legible de las ayudas: el de Bootstrap da 3,7:1. */
.gestor-cuerpo .text-muted {
	color: #5a6270 !important;
}

/* «Cambiar contraseña» (17/10/2026): un <summary> con aspecto de botón, sin
   el triangulito del navegador. */
.cambiar-contrasena > summary {
	list-style: none;
}

.cambiar-contrasena > summary::-webkit-details-marker {
	display: none;
}

/* La frase de estado de un apartado («Novedad del 27/05/2026 · activa · en
   la agenda…», 17/10/2026), justo bajo su rótulo. */
.resumen-apartado {
	margin: -.5rem 0 1.25rem;
	padding: 0 1rem;
	font-size: .75rem;
	font-weight: 600;
	color: var(--bs-heading-color, #343f52);
}

.resumen-apartado i {
	margin-right: .4rem;
	color: var(--bs-primary);
}

/* Las acciones de la fila, bajo el título de la franja (17/10/2026): enlaces
   pequeños con icono, en el oscuro del aula. */
.titulo-franja-acciones {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: .4rem 1.5rem;
	margin-top: .75rem;
	font-size: .75rem;
	font-weight: 600;
}

.titulo-franja-acciones a,
.titulo-franja-acciones .boton-icono {
	color: var(--color-oscuro, color-mix(in srgb, var(--bs-primary) 75%, #000));
	text-decoration: none;
	font-weight: 600;
}

.titulo-franja-acciones a:hover,
.titulo-franja-acciones .boton-icono:hover {
	color: var(--bs-primary);
}

.titulo-franja-acciones i {
	margin-right: .3rem;
}

/* Los rótulos que van ENCIMA del campo (texto con formato, imagen, fichero,
   solo lectura), oscuros y con algo de peso (Jordi, 17/10/2026, opción A):
   antes, grises y sin peso, apenas se leían junto a los flotantes. La letra
   base del tema es de 20 px: .75rem son 15 px. */
.rotulo-campo {
	display: block;
	margin-bottom: .45rem;
	font-size: .75rem;
	font-weight: 600;
	color: var(--bs-heading-color, #343f52);
}

/* Las ayudas de los campos, legibles (Jordi, 17/10/2026, opción A): el tema
   las pone a 12 px en gris claro; aquí, 13,5 px y un gris que da 6,1:1 sobre
   blanco. Son lo que explica cada campo. */
.gestor-cuerpo .form-text {
	margin-top: .35rem;
	font-size: .675rem;
	line-height: 1.45;
	color: #5a6270;
}

/* Guardar, siempre a mano: la barra se pega al pie de la ventana mientras
   se baja por el formulario y se queda en su sitio al llegar al final. */
.barra-guardar {
	position: sticky;
	bottom: 0;
	z-index: 5;
	margin: 2rem -1rem 0;
	padding: 1rem;
	background: rgba(255, 255, 255, .96);
	border-top: 1px solid var(--bs-border-color);
	border-radius: 0 0 .4rem .4rem;
}

/* El menú «⋯» de cada fila del árbol. Lo abre default.js con `.show`; se
   alinea a la derecha del botón para no salirse de la caja. */
.menu-nodo {
	position: relative;
	display: inline-flex;
}

.menu-nodo .dropdown-menu {
	right: 0;
	left: auto;
	top: 100%;
	margin-top: .25rem;
	padding: .5rem 0;
	min-width: 11rem;
}

.menu-nodo .dropdown-item {
	display: block;
	font-size: .85rem;
	padding: .35rem 1.1rem;
}

/* Sin la flechita de Bootstrap: el botón ya es un «⋯». */
.dropdown-toggle.sin-flecha::after {
	display: none;
}

/* El panel de avisos de Estructura web. */
.aviso-inicio {
	padding: 1.25rem 1.4rem;
	border: 1px solid var(--bs-border-color);
	border-radius: .4rem;
	background: #fff;
}

.aviso-inicio-icono {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2.2rem;
	height: 2.2rem;
	flex: none;
	border-radius: 50%;
	background: var(--bs-soft-primary, rgba(var(--bs-primary-rgb), .1));
	color: var(--bs-primary);
	font-size: 1.1rem;
}

.aviso-inicio li + li {
	margin-top: .2rem;
}

.avisos-al-dia {
	color: #60697b;
	font-size: .9rem;
}

/* Vista previa de una página inactiva en la web (solo la ve quien la
   administra): una franja fija abajo, imposible de confundir con la web. */
.aviso-vista-previa {
	position: fixed;
	left: 50%;
	bottom: 1rem;
	z-index: 1050;
	transform: translateX(-50%);
	max-width: calc(100% - 2rem);
	padding: .7rem 1.25rem;
	border-radius: 2rem;
	background: #343f52;
	color: #fff;
	font-size: .9rem;
	box-shadow: 0 .5rem 1.5rem rgba(0, 0, 0, .25);
}
