/* ============================================================
   _componentes.css — FNN Plataforma
   Componentes reutilizables inferidos del Figma "Nadar es vida".
   Depende de los tokens definidos en _tema.css (cargar SIEMPRE
   _tema.css antes que este fichero). No define ningún color,
   tamaño o radio directamente: todo viene de var(--...).
   ============================================================ */

/* --- Reinicio base --- */
* {
    box-sizing: border-box;
}

html {
    scroll-behavior: smooth;
}

body {
    margin: 0;
    background: var(--color-fondo);
    color: var(--color-texto);
    font-family: var(--fuente-principal);
    font-size: var(--tamano-base);
    line-height: var(--altura-linea);
}

a {
    color: inherit;
}

h1, h2, h3, h4, p, dl, dd {
    margin: 0;
}

button, input, select, textarea {
    font-family: inherit;
}

/* fieldset/legend usados para agrupar radios/checkboxes accesiblemente
   (el lector de pantalla anuncia la leyenda al entrar al grupo) sin
   heredar el borde/relleno por defecto del navegador. */
fieldset {
    min-width: 0;
    margin: 0;
    padding: 0;
    border: 0;
}

legend {
    padding: 0;
}

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
.pastilla:focus-visible,
.pastilla-opcion__input:focus-visible + .pastilla {
    outline: 3px solid var(--color-primario-oscuro);
    outline-offset: 2px;
}

/* --- Layout / rejilla --- */
.contenedor {
    width: min(var(--ancho-contenido), 100%);
    margin: 0 auto;
    padding: 0 clamp(1rem, 4vw, 2rem);
}

.contenedor--ancho {
    width: min(var(--ancho-contenido-lg), 100%);
    margin: 0 auto;
    padding: 0 clamp(1rem, 4vw, 2rem);
}

.seccion {
    padding-block: var(--espaciado-xl);
}

.pila > * + * {
    margin-top: var(--espaciado-md);
}

.pila-ajustada > * + * {
    margin-top: var(--espaciado-sm);
}

/* Para secciones con pocos bloques pero visualmente sustanciosos (p. ej.
   grupos de filtros + barra de resultados + listado en Cursos/Index).
   Auditoría pág. 2 (2026-07-03): la separación entre grupos de filtros
   del PDF ronda 29-45px CSS — xl, no lg. */
.pila-amplia > * + * {
    margin-top: var(--espaciado-xl);
}

/* --- Cabecera de sitio ---
   Confirmado en las 13 páginas del PDF "Nadar es vida": "Home" a la
   izquierda, marca (icono + nombre federación) centrada, selector
   CAS/EUS a la derecha. Componente único compartido por todas las
   pantallas (antes vivía duplicado como CSS específico de _Layout.cshtml
   en site.css; movido aquí para que sea un componente real, no CSS de
   pantalla). Grid de 3 columnas para centrado exacto de la marca. */
.site-header {
    position: sticky;
    top: 0;
    z-index: 20;
    display: grid;
    /* Mobile-first: los extremos ("Home" / CAS-EUS) se ajustan a su
       contenido y la marca central ocupa el resto (puede encogerse y
       envolver texto) para no forzar overflow horizontal. En pantallas
       con más aire (ver media query) pasa a 1fr auto 1fr para un
       centrado visual exacto. */
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: var(--espaciado-sm);
    padding: var(--espaciado-md) clamp(1rem, 4vw, 4rem);
    background: var(--color-fondo-translucido);
    border-bottom: 1px solid var(--color-borde);
    backdrop-filter: blur(12px);
}

@media (min-width: 700px) {
    .site-header {
        grid-template-columns: 1fr auto 1fr;
    }
}

.site-header__inicio {
    justify-self: start;
    min-width: 0;
    color: var(--color-texto);
    /* Confirmado en el PDF: "Home" va en peso normal y a un tamaño
       notablemente mayor que el resto de la cabecera, no en negrita
       pequeña como se había estimado antes. */
    font-weight: var(--peso-normal);
    font-size: var(--tamano-xl);
    text-decoration: none;
    white-space: nowrap;
    transition: color var(--transicion-rapida);
}

.site-header__inicio:hover {
    text-decoration: underline;
}

.site-header__marca {
    display: inline-flex;
    align-items: center;
    justify-self: center;
    min-width: 0;
    gap: var(--espaciado-sm);
    color: var(--color-texto);
    text-decoration: none;
    text-align: center;
}

/* Logo oficial de cabecera (asset SVG en wwwroot/img/logo-cabecera.svg,
   lockup icono + nombre en castellano/euskera, tal cual el Figma —
   sustituye al antiguo placeholder "FNN" + texto en dos líneas, que ya
   no se usa). Solo se controla el tamaño por CSS (max-height/max-width),
   nunca el propio fichero: con width/height en "auto" el navegador
   mantiene la proporción real (626:83) en cualquier ancho de pantalla,
   sin deformarla. */
.site-header__marca-imagen {
    display: block;
    width: auto;
    height: auto;
    max-height: 40px;
    max-width: 100%;
}

/* Confirmado en el PDF: mismo tamaño y peso (normal, no negrita) que
   "Home"; el idioma activo se distingue solo con subrayado + color. */
.site-header__idioma {
    display: flex;
    align-items: center;
    justify-self: end;
    gap: 0.15rem;
    font-size: var(--tamano-xl);
    font-weight: var(--peso-normal);
    white-space: nowrap;
}

.site-header__idioma a {
    color: var(--color-texto-suave);
    text-decoration: none;
    transition: color var(--transicion-rapida);
}

.site-header__idioma a:hover {
    color: var(--color-texto);
}

.site-header__idioma a[aria-current="true"] {
    color: var(--color-texto);
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* --- Pie de sitio ---
   Confirmado en el PDF: 3 columnas (Pagos / Inscripción / Contacto y
   dudas) + icono de marca. Mismo motivo de traslado que la cabecera. */
.site-footer {
    margin-top: 4rem;
    color: var(--color-texto);
    border-top: 1px solid var(--color-borde);
    font-size: var(--tamano-sm);
}

.site-footer__grid {
    display: grid;
    width: min(var(--ancho-contenido-lg), 100%);
    grid-template-columns: auto repeat(3, minmax(0, 1fr));
    gap: var(--espaciado-xl);
    padding: var(--espaciado-xl) clamp(2rem, 5vw, 5rem) calc(var(--espaciado-xl) + var(--espaciado-sm));
}

.site-footer__marca {
    display: flex;
    align-items: flex-start;
}

/* Isotipo oficial de pie (asset SVG en wwwroot/img/isotipo-pie.svg, tal
   cual el Figma — sustituye al antiguo placeholder .brand-mark "FNN").
   Mismo criterio que el logo de cabecera: solo tamaño por CSS, nunca se
   toca el fichero, y width/height en "auto" mantiene la proporción real
   (126:106) sin deformarla. */
.site-footer__marca-imagen {
    display: block;
    width: auto;
    height: auto;
    /* pág. 1 del PDF: el isotipo es grande, aprox. 1,6 veces la altura
       del bloque de texto de las columnas (los 42px anteriores se
       quedaban claramente cortos al compararlo en paralelo). */
    max-height: 72px;
    max-width: 100%;
}

.site-footer__titulo {
    margin: 0 0 var(--espaciado-sm);
    font-size: var(--tamano-base);
    font-weight: var(--peso-bold);
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--color-texto);
}

.site-footer__col p {
    margin: 0 0 var(--espaciado-xs);
    line-height: 1.25;
}

.site-footer__col a {
    color: var(--color-texto);
    text-decoration: none;
}

/* El pie mantiene SIEMPRE sus tres columnas de texto, igual que la
   cabecera mantiene sus tres zonas (Home / marca / CAS-EUS) en
   cualquier ancho — petición expresa de Fermín, sustituye al antiguo
   apilado a una columna en móvil. En estrecho, el isotipo (columna
   `auto`) se retira para dejar todo el ancho a las tres columnas, y
   el hueco y la letra se reducen un punto para que quepan. */
@media (max-width: 899px) {
    .site-footer__grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: var(--espaciado-md);
    }

    .site-footer__marca {
        display: none;
    }
}

@media (max-width: 549px) {
    .site-footer {
        font-size: var(--tamano-sm);
    }

    .site-footer__grid {
        gap: var(--espaciado-sm);
        padding-inline: var(--espaciado-md);
    }

    .site-footer__titulo {
        font-size: var(--tamano-sm);
        line-height: 1.15;
        letter-spacing: 0;
    }
}

/* --- Migas de pan ---
   "Adultos > Pasar lista", "Inicio > Inscripción Adultos > Completa
   tus datos". Título grande, sin decoración de enlace agresiva. Este
   tamaño grande asume que .migas ES el título de la pantalla (patrón
   confirmado en Inscripción/Pasar lista): cuando conviva con un <h1>
   propio debajo (ver .cabecera-pagina más abajo), se anula a un tamaño
   secundario para no competir con él. */
.migas {
    font-size: var(--tamano-titulo);
    font-weight: var(--peso-normal);
    line-height: 1.15;
}

.migas a {
    /* Sin esto, el enlace hereda el color de enlace global de site.css
       (--color-primario-oscuro sobre --color-fondo ronda 1.7:1 de
       contraste — no llega a AA). Igualando al color del texto que lo
       rodea, el contraste vuelve a ser el de .migas (>5:1) y el único
       indicio de que es interactivo es el subrayado al pasar el ratón. */
    color: inherit;
    text-decoration: none;
    transition: color var(--transicion-rapida);
}

.migas a:hover {
    text-decoration: underline;
}

/* --- Cabecera de pantalla (migas + título + resumen) ---
   Bloque compartido por cualquier vista con breadcrumb + título + una
   línea de resumen (hoy Cursos/Index; candidato también para Detalle/
   Inscripción cuando les llegue su turno). No specific a Cursos: solo
   depende de .migas y tokens de tipografía. */

/* Auditoría pág. 2 (2026-07-03): el PDF deja MUCHO aire alrededor del
   título — ≈159px CSS entre header y h1 y ≈70px entre h1 y el primer
   grupo de filtros (mismo patrón de aire superior en la pág. 3). El
   PDF solo da referencia de escritorio: en estrecho el clamp lo reduce
   proporcionalmente para no gastar media pantalla en vacío. Este
   padding sustituye al de .seccion (misma especificidad, definido
   después). */
.cabecera-pagina {
    padding-block: clamp(3rem, 11vw, 10rem) clamp(2rem, 5vw, 4.5rem);
}

.cabecera-pagina__resumen {
    color: var(--color-texto-suave);
    max-width: 60ch;
}

/* Cuando .migas convive con un <h1> propio (a diferencia de Pasar
   lista/Inscripción, donde .migas ES el título), debe leerse como
   navegación secundaria, no como otro título del mismo tamaño. Sin
   esto, en móvil el h1 fluido baja hasta su mínimo (2rem) y queda
   exactamente igual de grande que las migas — la jerarquía
   desaparece justo donde más se necesita (pantallas estrechas). */
.cabecera-pagina .migas {
    font-size: var(--tamano-base);
    font-weight: var(--peso-normal);
    color: var(--color-texto-suave);
}

/* El <h1> de esta cabecera no debe heredar el h1 global de site.css
   (pensado para el hero de Detalle/Inscripción, hasta clamp(2.35rem,
   8vw,4.75rem) — demasiado grande para un título de listado con
   breadcrumb encima). Especificidad de clase + elemento por encima del
   elemento global suelto. */
.cabecera-pagina h1 {
    max-width: none;
    font-size: var(--tamano-titulo-lg);
    font-weight: var(--peso-normal);
    line-height: 1.15;
}

/* --- Barra de resultados (recuento + chips activos) ---
   Reutilizable en cualquier listado con filtros (hoy Cursos/Index).
   flex-wrap evita el desbordamiento horizontal que tenía el
   .results-bar legacy cuando el recuento y los chips no cabían en una
   línea. */
.resultados-barra {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--espaciado-md);
    /* Auditoría pág. 2: entre el último grupo de filtros y "CURSOS
       DISPONIBLES" hay ≈74px CSS, bastante más que entre grupos —
       gana al margen de .pila-amplia por orden de aparición. */
    margin-block-start: calc(var(--espaciado-xxl) + var(--espaciado-lg));
}

/* --- Estado vacío (sin resultados) ---
   Reutilizable en cualquier listado filtrable. Borde discontinuo, igual
   criterio visual que el placeholder de imagen de .tarjeta-inicio: para
   que se note que es un estado, no un error de maquetación. */
.estado-vacio {
    display: grid;
    justify-items: center;
    gap: var(--espaciado-md);
    padding: var(--espaciado-xxl) var(--espaciado-lg);
    border: 1px dashed var(--color-borde-suave);
    border-radius: var(--radio-card);
    text-align: center;
    color: var(--color-texto-suave);
}

.estado-vacio__titulo {
    color: var(--color-texto);
    font-weight: var(--peso-bold);
}

.estado-vacio__acciones {
    display: flex;
    flex-wrap: wrap;
    gap: var(--espaciado-md);
    justify-content: center;
}

/* --- Aviso de carga (transversal) ---
   Indicación discreta de que la web está trabajando (filtros que
   recargan, envío de formularios, navegación a Inscripción…). Píldora
   fija bajo la cabecera con un giro fino y texto breve; solo tokens del
   Design System, nada de Bootstrap. El JS de _Layout.cshtml la muestra
   con un pequeño retardo para que las acciones instantáneas no
   parpadeen, y marca <body aria-busy="true"> mientras tanto. El propio
   elemento es role="status" (aria-live implícito "polite"). */
.aviso-carga {
    position: fixed;
    top: var(--espaciado-lg);
    left: 50%;
    translate: -50% 0;
    z-index: 100;
    display: inline-flex;
    align-items: center;
    gap: var(--espaciado-sm);
    padding: var(--espaciado-sm) var(--espaciado-md);
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-pastilla);
    background: var(--color-fondo-translucido);
    color: var(--color-texto);
    font-size: var(--tamano-sm);
    box-shadow: var(--sombra-card);
}

.aviso-carga[hidden] {
    display: none;
}

.aviso-carga::before {
    content: "";
    inline-size: 1em;
    block-size: 1em;
    flex: none;
    border: 2px solid var(--color-primario-oscuro);
    border-block-start-color: transparent;
    border-radius: 50%;
    animation: aviso-carga-giro 0.8s linear infinite;
}

@keyframes aviso-carga-giro {
    to { transform: rotate(360deg); }
}

/* Con animaciones reducidas, la señal es solo el texto (el aro estático
   podría confundirse con un adorno). */
@media (prefers-reduced-motion: reduce) {
    .aviso-carga::before {
        display: none;
    }
}

/* --- Grupo de filtro: etiqueta + pastillas ---
   align-content: start es imprescindible: sin él, cuando el grupo vive
   en una rejilla de columnas (.filtros--dos-columnas) el fieldset se
   estira a la altura de la fila y sus filas internas (etiqueta/chips)
   se reparten el hueco sobrante — el grupo NIVEL acababa pareciendo un
   bloque/tarjeta en vez de una etiqueta con sus pastillas. */
.grupo-filtro {
    display: grid;
    gap: var(--espaciado-sm);
    align-content: start;
}

.grupo-filtro__etiqueta {
    /* Auditoría pág. 2: la etiqueta (PISCINA/NIVEL/…) tiene el MISMO
       tamaño que el cuerpo (cap 18,7 vs 18 en px Figma), no el sm. */
    font-size: var(--tamano-base);
    font-weight: var(--peso-bold);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--color-texto);
}

.grupo-filtro__opciones {
    display: flex;
    flex-wrap: wrap;
    /* pág. 2: el hueco entre chips ronda medio chip de alto — md, no sm */
    gap: var(--espaciado-md);
}

.grupo-filtro__opciones--piscinas {
    align-items: flex-start;
}

.grupo-filtro__opciones--piscinas .pastilla {
    min-width: clamp(8.5rem, 13vw, 11rem);
}

.grupo-filtro__opciones--nivel {
    max-width: none;
}

.grupo-filtro__opciones--nivel .pastilla {
    min-width: clamp(9.5rem, 14vw, 13rem);
}

.filtros {
    display: grid;
    gap: var(--espaciado-lg);
    grid-template-columns: 1fr;
    /* Ambas columnas ancladas arriba: PISCINA y NIVEL alinean su
       etiqueta en la misma línea base aunque una envuelva más filas
       de chips que la otra (pág. 2). */
    align-items: start;
}

@media (min-width: 900px) {
    .filtros--dos-columnas {
        grid-template-columns: minmax(0, 1.05fr) minmax(27rem, 0.95fr);
        column-gap: var(--espaciado-xxl);
    }

    .grupo-filtro--nivel {
        justify-self: start;
    }
}

/* --- Pastilla (filtro por piscina / nivel / día / colegio / curso) ---
   Modificadores de estado: .pastilla--seleccionada / :disabled.
   Modificadores de color: .pastilla--piscina-color-{token} y
   .pastilla--categoria-{slug}; aplican solo el FONDO, el resto del
   estilo (borde, tipografía) es común. */
/* Auditoría pág. 2 (2026-07-03):
   - texto al tamaño del cuerpo (cap 18,7 px Figma = cap del texto de
     datos), no sm;
   - SIN text-transform: en el PDF solo DÍAS va en mayúsculas y viene
     ya así en el texto ("Aranzadi", "Iniciación", "10:00-10:45" van en
     caja normal) — las mayúsculas son contenido, no estilo;
   - fondo = fondo de página (los chips de HORARIO/DÍAS del PDF son
     crema, solo borde), no superficie blanca;
   - altura ≈51px CSS (80 px Figma a escala 0,64). */
.pastilla {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 3.25rem;
    padding: 0.5rem 1rem;
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-pastilla);
    background: transparent;
    color: var(--color-texto);
    font-size: var(--tamano-base);
    font-weight: var(--peso-normal);
    letter-spacing: 0.02em;
    cursor: pointer;
    transition: background var(--transicion-rapida), border-color var(--transicion-rapida);
}

/* Hover solo en dispositivos con puntero real (evita "hover pegajoso"
   al tocar en móvil, que dejaría la pastilla marcada tras el tap). */
@media (hover: hover) and (pointer: fine) {
    .pastilla:not(:disabled):not([aria-disabled="true"]):not(.pastilla--pendiente):hover {
        border-width: 2px;
    }
}

.pastilla:disabled,
.pastilla[aria-disabled="true"] {
    opacity: 0.45;
    cursor: not-allowed;
}

.pastilla--seleccionada,
.pastilla-opcion__input:checked + .pastilla {
    border-width: 2px;
    font-weight: var(--peso-bold);
}

/* --- Pastilla como control real de filtro (radio nativo oculto) ---
   Mismo <input type="radio" asp-for="..."> que antes eran <option> de un
   <select> (mismo name=/value=, mismo binding, mismo querystring): solo
   cambia cómo se ve. El radio se oculta de forma accesible (no display:none,
   que rompería foco/lector de pantalla) y la superficie visual es la misma
   .pastilla ya usada para mostrar filtros activos. Sin JS: clic/teclado en
   la pastilla = clic/teclado en el radio nativo. */
.pastilla-opcion {
    display: inline-flex;
}

.pastilla-opcion__input {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Piscinas: color fijo por instalación (ver huecos: hoy se mapea por
   nombre; migrar a Piscina.Color en cuanto exista en el modelo).
   Estados confirmados en la pág. 2 del PDF: sin seleccionar = fondo
   de color, SIN borde y texto gris (San Jorge y Guelbenzu aparecen
   así); seleccionada = borde negro fino y texto negro (Aranzadi),
   que además cambia a su fondo intenso — única piscina con muestra
   de esa variante, el resto conserva su color base al seleccionar. */
.pastilla--piscina-color-azul     { background: var(--color-piscina-azul); }
.pastilla--piscina-color-verde    { background: var(--color-piscina-verde); }
.pastilla--piscina-color-naranja  { background: var(--color-piscina-naranja); }
.pastilla--piscina-color-amarillo { background: var(--color-piscina-amarillo); }
.pastilla--piscina-color-rosa     { background: var(--color-piscina-rosa); }
.pastilla--piscina-color-violeta  { background: var(--color-piscina-violeta); }
.pastilla--piscina-color-turquesa { background: var(--color-piscina-turquesa); }
.pastilla--piscina-color-celeste  { background: var(--color-piscina-celeste); }
.pastilla--piscina-color-salmon   { background: var(--color-piscina-salmon); }
.pastilla--piscina-color-lima     { background: var(--color-piscina-lima); }

[class*="pastilla--piscina-"]:not(.pastilla--seleccionada) {
    border-color: transparent;
    color: var(--color-texto-suave);
}

/* Excepción AA: sobre los fondos de piscina saturados el gris suave no
   llega a 4.5:1 (Zizur 3.0, Huarte 2.7, UPNA 3.8 — verificado con
   luminancia relativa). El PDF solo muestra texto gris sobre las tres
   piscinas pálidas de la pág. 2; para las saturadas se mantiene el
   texto normal. (Guelbenzu se queda en 4.44:1, al borde: es el color
   que el PDF muestra explícitamente, anotado en docs/CURSOS_INDEX.md.) */
.pastilla--piscina-color-amarillo:not(.pastilla--seleccionada),
.pastilla--piscina-color-salmon:not(.pastilla--seleccionada) {
    color: var(--color-texto);
}

/* La variante de categoría comparte esta regla: sin ella, un chip de
   color marcado a través del radio oculto (que no lleva la clase
   .pastilla--seleccionada) se quedaría con el texto gris y el borde
   invisible del estado sin seleccionar. */
.pastilla-opcion__input:checked + [class*="pastilla--piscina-"],
.pastilla-opcion__input:checked + [class*="pastilla--categoria-"] {
    border-color: var(--color-borde);
    color: var(--color-texto);
}

.pastilla--piscina-color-naranja.pastilla--seleccionada,
.pastilla-opcion__input:checked + .pastilla--piscina-color-naranja {
    background: var(--color-piscina-naranja-intenso);
}

/* Categoría: acento de la sección activa (Adultos = naranja,
   Campaña escolar = amarillo...). Se aplica a NIVEL / DÍAS / COLEGIO
   / CURSO, no a PISCINA. */
.pastilla--categoria-adultos.pastilla--seleccionada   { background: var(--color-categoria-adultos); }
.pastilla--categoria-adultos:not(.pastilla--seleccionada)   { background: var(--color-categoria-adultos-suave); border-color: var(--color-categoria-adultos-suave); color: var(--color-texto-suave); }
.pastilla--categoria-escolar.pastilla--seleccionada   { background: var(--color-categoria-escolar); }
.pastilla--categoria-escolar:not(.pastilla--seleccionada)   { background: var(--color-categoria-escolar-suave); border-color: var(--color-categoria-escolar-suave); color: var(--color-texto-suave); }
.pastilla--categoria-infantiles.pastilla--seleccionada   { background: var(--color-categoria-infantiles); }
.pastilla--categoria-infantiles:not(.pastilla--seleccionada)   { background: var(--color-categoria-infantiles-suave); border-color: var(--color-categoria-infantiles-suave); color: var(--color-texto-suave); }

/* En los chips DE COLOR (piscina y categoría) la selección se marca con
   la aparición del borde fino y el texto negro, tal cual muestra la
   pág. 2 (Aranzadi/Iniciación seleccionadas: borde 1px, peso normal).
   El engorde a 2px + negrita del .pastilla--seleccionada base queda
   solo para los chips neutros (HORARIO/DÍAS), que siempre tienen borde
   y necesitan otra señal de selección. */
[class*="pastilla--piscina-"].pastilla--seleccionada,
.pastilla-opcion__input:checked + [class*="pastilla--piscina-"],
[class*="pastilla--categoria-"].pastilla--seleccionada,
.pastilla-opcion__input:checked + [class*="pastilla--categoria-"] {
    border-width: 1px;
    font-weight: var(--peso-normal);
}

/* Auditoría pág. 2: los chips de color (PISCINA y NIVEL) comparten un
   ancho mínimo — Aranzadi, San Jorge, Guelbenzu e Iniciación miden
   exactamente lo mismo (195 px Figma ≈ 125 CSS) aunque su texto varíe;
   solo Perfeccionamiento lo desborda por contenido. Los chips neutros
   (HORARIO/DÍAS) no lo tienen: su ancho es contenido + padding. */
[class*="pastilla--piscina-"],
[class*="pastilla--categoria-"] {
    min-inline-size: 7.75rem;
}

/* Pastilla "pendiente": opción que el diseño ya define (pág. 2: NIVEL,
   HORARIO, combinaciones de DÍAS) pero cuyo filtrado real todavía no
   existe en el modelo/controlador. Se pinta EXACTAMENTE como la
   pastilla normal (nada de atenuarla: en el PDF no se distingue) pero
   sin cursor de acción ni hover, para no prometer una interacción que
   no responde. Cuando llegue la lógica, basta quitar el modificador. */
.pastilla--pendiente {
    cursor: default;
}

/* --- Botones ---
   .boton--categoria-* se usa para el CTA principal de cada sección
   (ENVIAR en Pasar lista/Evaluación); .boton--primario para acciones
   globales (INSCRIPCIÓN, INICIAR SESIÓN).

   Corregido contra las págs. 2 y 3 del PDF (INSCRIPCIÓN aparece igual
   en ambas, así que es el botón canónico, no un caso especial):
   borde negro fino SIEMPRE (antes solo en --secundario), texto en
   mayúsculas SIN negrita (antes bold [ESTIMADO]) y padding horizontal
   generoso. Auditoría 2026-07-03 (medido en px Figma sobre ambas
   páginas): texto 1,3 veces el cuerpo (cap 24 vs 18,7) → --tamano-xl;
   caja ≈50px de alto y ≈39px de padding lateral a escala 0,64. */
.boton {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: var(--alto-minimo-touch);
    width: 100%;
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-boton);
    padding: 0.85rem 2.5rem;
    font-size: var(--tamano-xl);
    font-weight: var(--peso-normal);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    text-decoration: none;
    cursor: pointer;
    transition: filter var(--transicion-rapida), background-color var(--transicion-rapida), color var(--transicion-rapida);
}

.boton:hover {
    filter: brightness(0.96);
}

.boton:disabled {
    cursor: not-allowed;
    opacity: 0.55;
}

.boton--primario {
    background: var(--color-primario);
    color: var(--color-sobre-primario);
}

.boton--categoria-adultos { background: var(--color-categoria-adultos); color: var(--color-sobre-primario); }
.boton--categoria-escolar { background: var(--color-categoria-escolar); color: var(--color-sobre-primario); }
.boton--categoria-infantiles { background: var(--color-categoria-infantiles); color: var(--color-sobre-primario); }

.boton--secundario {
    background: var(--color-superficie);
    border-color: var(--color-borde);
    color: var(--color-texto);
}

/* Botón fantasma: sin relleno ni borde, solo texto. No aparece de forma
   explícita en el PDF (las 13 páginas solo muestran INSCRIPCIÓN/ENVIAR/
   INICIAR SESIÓN, todos rellenos) — [ESTIMADO], construido para
   acciones terciarias (p. ej. "Ver detalle" cuando ya hay una acción
   primaria y una secundaria en la misma fila) siguiendo la misma
   tipografía/mayúsculas que el resto de botones. */
.boton--fantasma {
    background: transparent;
    border-color: transparent;
    color: var(--color-texto);
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* Fondo celeste muy pálido en vez de cambiar el color del texto: usar
   --color-primario-oscuro como color de TEXTO aquí bajaba el contraste
   muy por debajo de AA (texto claro sobre fondo claro). El fondo tenue
   da la misma sensación de "resaltado" sin ese problema. */
.boton--fantasma:hover {
    filter: none;
    background: var(--color-primario-claro);
}

.boton--ancho-auto {
    width: auto;
}

/* --- Tarjetas de inicio (Home: Adultos / Infantiles / Escuela...) ---
   Confirmado en la página 1 del PDF: 3 columnas en escritorio + 2 en
   la fila siguiente (grid simple de 3, sin reglas extra), 1 columna
   en móvil. Ninguna tarjeta va marcada como activa por defecto: el
   celeste es EXCLUSIVAMENTE estado hover/focus/tap (confirmado: la
   captura con "Adultos" en celeste es el cursor sobre esa tarjeta,
   no un estado por defecto). */
.rejilla-inicio {
    display: grid;
    gap: var(--espaciado-lg);
    grid-template-columns: 1fr;
}

@media (min-width: 900px) {
    .rejilla-inicio {
        grid-template-columns: repeat(3, 1fr);
    }
}

.tarjeta-inicio {
    display: flex;
    flex-direction: column;
    gap: var(--espaciado-lg);
    min-height: 320px;
    padding: var(--espaciado-lg);
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-card);
    background: var(--color-superficie);
    text-decoration: none;
    color: var(--color-texto);
    transition: background-color var(--transicion-rapida), border-color var(--transicion-rapida);
}

.tarjeta-inicio__titulo {
    margin: 0;
    /* Confirmado en el PDF: el título de tarjeta usa peso normal, no
       negrita (a diferencia de las etiquetas de filtro en mayúsculas). */
    font-size: var(--tamano-titulo);
    font-weight: var(--peso-normal);
    line-height: 1.15;
}

.tarjeta-inicio__imagen {
    margin-top: auto;
    width: 100%;
    aspect-ratio: 16 / 10;
    border-radius: var(--radio-md);
    object-fit: cover;
    /* Cuando todavía no hay foto real: fondo neutro + borde discontinuo,
       para que se note que es un hueco y no un error (ver huecos). */
    background: var(--color-superficie-fondo);
    border: 1px dashed var(--color-borde-suave);
}

/* Estado activo/expandido persistente (distinto del hover de Home):
   lo usa, por ejemplo, el acordeón del Home de Monitor mientras una
   sección está desplegada (ver .acordeon-inicio--activo). No lo
   aplica nunca la Home pública. */
.tarjeta-inicio--activa,
.tarjeta-inicio:hover,
.tarjeta-inicio:focus-visible,
.tarjeta-inicio:active {
    background: var(--color-primario);
    border-color: var(--color-primario-oscuro);
    color: var(--color-sobre-primario);
}

.tarjeta-inicio:hover .tarjeta-inicio__imagen,
.tarjeta-inicio:focus-visible .tarjeta-inicio__imagen,
.tarjeta-inicio:active .tarjeta-inicio__imagen,
.tarjeta-inicio--activa .tarjeta-inicio__imagen {
    background: var(--color-primario-claro);
    border-style: solid;
    border-color: var(--color-primario-oscuro);
}

/* Variante en acordeón (misma tarjeta, pero expandible con sub-enlaces
   Pasar lista / Evaluación / Calendario). */
.acordeon-inicio {
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-card);
    overflow: hidden;
}

.acordeon-inicio__cabecera {
    display: flex;
    align-items: center;
    gap: var(--espaciado-md);
    padding: var(--espaciado-md);
    cursor: pointer;
    list-style: none;
    transition: background-color var(--transicion-rapida);
}

.acordeon-inicio__cabecera::-webkit-details-marker {
    display: none;
}

@media (hover: hover) and (pointer: fine) {
    /* Igual que .boton--fantasma:hover: un fondo tenue en vez de tocar el
       color del texto, para no arriesgar contraste sobre --color-primario. */
    .acordeon-inicio__cabecera:hover {
        background: var(--color-primario-claro);
    }
}

.acordeon-inicio--activo .acordeon-inicio__cabecera:hover {
    background: var(--color-primario);
}

.acordeon-inicio__miniatura {
    width: 56px;
    height: 56px;
    border-radius: var(--radio-md);
    object-fit: cover;
    flex-shrink: 0;
}

.acordeon-inicio__titulo {
    flex: 1;
    font-size: var(--tamano-xl);
    line-height: 1.3;
}

/* Indicador + / − de despliegue en <details> de categorías */
.acordeon-inicio__cabecera::after {
    content: "+";
    flex: none;
    font-size: var(--tamano-xl);
    font-weight: var(--peso-bold);
    line-height: 1;
    color: var(--color-texto);
    margin-left: auto;
}

.acordeon-inicio[open] > .acordeon-inicio__cabecera::after {
    content: "\2212"; /* signo menos unicode */
}

.acordeon-inicio--activo,
.acordeon-inicio--activo .acordeon-inicio__cabecera {
    background: var(--color-primario);
}

.acordeon-inicio__opciones a {
    display: block;
    padding: var(--espaciado-md);
    border-top: 1px solid var(--color-borde);
    text-decoration: none;
    color: var(--color-texto);
}

/* --- Tarjeta de curso (catálogo público) ---
   Confirmado contra "Nadar es vida.pdf" pág. 2 (Cursos Adultos): tarjeta
   a ANCHO COMPLETO apilada en columna (no rejilla de columnas), borde
   fino neutro, título grande de peso normal, y los datos con viñeta "■"
   en DOS líneas: la piscina sola en la primera y el resto (días,
   horario, tanda, plazas) en horizontal en la segunda. Un único botón
   celeste de ancho automático, separado de los datos por un hueco
   claramente mayor que el que separa título y datos. El precio no
   aparece en la maqueta; se mantiene como un dato más de la segunda
   línea porque es información necesaria antes de inscribirse (misma
   decisión deliberada validada en Fase 2). */
/* Auditoría pág. 2 (2026-07-03): interior del mismo crema que la página
   (#FDF8F3 pipeteado dentro y fuera: solo la delimita el borde — el
   cambio a --color-superficie-fondo ya lo aplicó Fermín). Padding
   asimétrico medido: ≈24 arriba / ≈28 lados / ≈50 abajo (px CSS a
   escala 0,64). Esquinas ≈8px → --radio-md, menos redondeadas que
   --radio-card. Separación entre tarjetas apiladas ≈51px →
   --espaciado-xxl, como regla propia del componente. */
.tarjeta-curso {
    display: flex;
    flex-direction: column;
    gap: var(--espaciado-md);
    padding: var(--espaciado-lg) var(--espaciado-lg) var(--espaciado-xxl);
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-md);
    background: var(--color-superficie-fondo);
}

.tarjeta-curso + .tarjeta-curso {
    margin-top: var(--espaciado-xxl);
}

.tarjeta-curso__titulo {
    /* Auditoría pág. 2: 0,67 veces el h1 y 1,7 veces el cuerpo
       (em ≈42 px Figma → ≈27-28 CSS); los 32px de --tamano-titulo
       lo dejaban un punto grande respecto al PDF. */
    font-size: 1.75rem;
    font-weight: var(--peso-normal);
    line-height: 1.15;
}

/* Cada línea de datos es una .tarjeta-curso__lista (la pág. 2 muestra
   dos: piscina sola arriba, el resto en horizontal debajo). El hueco
   horizontal entre datos es notablemente mayor que el vertical. */
.tarjeta-curso__lista {
    display: flex;
    flex-wrap: wrap;
    gap: var(--espaciado-sm) var(--espaciado-xl);
    color: var(--color-texto);
}

.tarjeta-curso__dato::before {
    content: "■ ";
}

/* Estado de disponibilidad sobre el propio dato, en vez de una pill
   nueva: mismo lenguaje visual de viñeta, solo cambia el color. Usa
   directamente los mismos tokens de clase que ya devuelve
   CursoPublicoItemViewModel.EstadoPublicoClase ("success"/"warning"/
   "full"/"closed"), igual que hacía el _CursoCard.cshtml original con
   su pill de estado — no es una clase nueva que haya que mantener en
   paralelo con esa propiedad. "success" no necesita override: es el
   color de texto por defecto de la tarjeta. */
.tarjeta-curso__dato.warning {
    color: var(--color-aviso);
    font-weight: var(--peso-bold);
}

.tarjeta-curso__dato.full,
.tarjeta-curso__dato.closed {
    color: var(--color-peligro);
    font-weight: var(--peso-bold);
}

.tarjeta-curso__acciones {
    display: flex;
    flex-wrap: wrap;
    gap: var(--espaciado-md);
    /* La pág. 2 separa el botón de los datos con bastante más aire del
       que hay entre título y datos: ≈40px medidos = este margen + el
       gap md de la tarjeta. */
    margin-top: var(--espaciado-lg);
}

/* --- Panel resumen de selección (wizard de inscripción) --- */
.panel-resumen {
    padding: var(--espaciado-lg);
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-card);
}

.panel-resumen__titulo {
    font-size: var(--tamano-xl);
    margin-bottom: var(--espaciado-md);
}

/* Grid genérico para varios .panel-resumen en paralelo (Cursos/Detalle,
   migración Sprint 1, 2026-07-04) — a diferencia de .inscripcion-confirmar__grid
   (fracciones asimétricas, específico de esa pantalla), este es un grid
   simple de columnas iguales, reutilizable por cualquier pantalla que
   necesite paneles lado a lado. */
.rejilla-paneles {
    display: grid;
    gap: var(--espaciado-lg);
}

@media (min-width: 760px) {
    .rejilla-paneles {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* --- Inscripción pública (pág. 3 PDF) ---
   Pantalla sin detalle intermedio: breadcrumb/título grande, panel "Tu
   selección" a ancho completo y formulario directo debajo. Mantiene la
   lógica actual; los campos que no existen en el modelo no se inventan. */
.inscripcion-pagina {
    max-width: 74rem;
    padding-block: clamp(3rem, 11vw, 8.5rem) var(--espaciado-xxl);
}

.inscripcion-pagina > * + * {
    margin-top: var(--espaciado-xxl);
}

.inscripcion-seleccion {
    border-radius: var(--radio-md);
    background: var(--color-superficie-fondo);
}

.inscripcion-seleccion__titulo {
    margin-bottom: var(--espaciado-xl);
    font-size: var(--tamano-titulo);
    line-height: 1.15;
    font-weight: var(--peso-normal);
}

.inscripcion-seleccion__datos {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--espaciado-sm) clamp(2rem, 6vw, 5rem);
}

.inscripcion-seleccion__dato {
    display: flex;
    min-width: 0;
    align-items: baseline;
    gap: var(--espaciado-sm);
    line-height: 1.35;
}

.inscripcion-seleccion__dato::before {
    content: "■";
    flex: none;
    font-size: .65em;
}

.inscripcion-formulario {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--espaciado-lg);
    width: 100%;
}

.inscripcion-formulario__acciones {
    margin-top: var(--espaciado-sm);
}

.inscripcion-formulario__acciones .boton {
    min-width: 15rem;
}

.inscripcion-formulario__abonado .grupo-filtro__opciones {
    gap: var(--espaciado-sm);
}

.inscripcion-formulario__abonado .pastilla {
    min-width: 4rem;
}

.inscripcion-confirmar__grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--espaciado-lg);
    max-width: 60rem;
}

.inscripcion-confirmar__panel {
    background: var(--color-superficie-fondo);
}

.inscripcion-confirmar__titulo {
    margin-bottom: var(--espaciado-lg);
    font-size: var(--tamano-xl);
    line-height: 1.2;
    font-weight: var(--peso-normal);
}

.lista-revision {
    display: grid;
    gap: var(--espaciado-md);
    margin: 0;
}

.lista-revision div {
    display: grid;
    gap: var(--espaciado-xs);
    padding-bottom: var(--espaciado-md);
    border-bottom: 1px solid var(--color-borde);
}

.lista-revision div:last-child {
    padding-bottom: 0;
    border-bottom: 0;
}

.lista-revision dt {
    font-size: var(--tamano-sm);
    font-weight: var(--peso-bold);
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.lista-revision dd {
    margin: 0;
    font-size: var(--tamano-lg);
}

.lista-revision--importe dd {
    font-size: var(--tamano-xl);
}

.inscripcion-confirmar__nota {
    margin-top: var(--espaciado-lg);
    max-width: 34rem;
    line-height: 1.35;
}

.inscripcion-confirmar__formulario {
    display: grid;
    gap: var(--espaciado-md);
    margin-top: var(--espaciado-lg);
}

.enlace-texto {
    display: inline-block;
    margin-top: var(--espaciado-lg);
    color: var(--color-texto);
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* --- Página de resultado (icono + mensaje central) ---
   Migración Sprint 1 (2026-07-04): patrón compartido por
   Inscripcion/Confirmacion.cshtml, PagoRetorno.cshtml y
   RedirigirRedsys.cshtml — antes cada una tenía su propia copia
   (.result-page/.result-icon/.eyebrow de site.css). Reutiliza .migas
   (mismo patrón "migas = título" ya usado en Inscripcion/Nueva),
   .panel-resumen (para la nota inferior, sin componente nuevo para
   eso) y .campo__etiqueta (para el "eyebrow" — mismo look de texto
   pequeño en mayúsculas, sin duplicar esa regla). Solo el icono
   circular de estado es genuinamente nuevo: no existía nada parecido
   en el sistema. */
.pagina-resultado {
    max-width: 34rem;
    margin-inline: auto;
    text-align: center;
    padding-block: clamp(3rem, 11vw, 8.5rem) var(--espaciado-xxl);
}

.pagina-resultado > * + * {
    margin-top: var(--espaciado-md);
}

.pagina-resultado .migas {
    text-align: center;
}

.pagina-resultado .panel-resumen {
    margin-top: var(--espaciado-xl);
    text-align: left;
}

.pagina-resultado__acciones {
    margin-top: var(--espaciado-lg);
}

.resultado-icono {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 3.5rem;
    height: 3.5rem;
    margin-inline: auto;
    border-radius: 50%;
    font-size: 1.5rem;
    font-weight: var(--peso-bold);
}

.resultado-icono--exito {
    background: var(--color-exito-fondo);
    color: var(--color-exito);
}

.resultado-icono--aviso {
    background: var(--color-aviso-fondo);
    color: var(--color-aviso);
}

.resultado-icono--peligro {
    background: var(--color-peligro-fondo);
    color: var(--color-peligro);
}

@media (min-width: 760px) {
    .inscripcion-seleccion__datos {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .inscripcion-seleccion__periodo {
        grid-column: 1 / -1;
    }

    .inscripcion-formulario {
        grid-template-columns: repeat(6, minmax(0, 1fr));
        column-gap: var(--espaciado-lg);
        row-gap: var(--espaciado-lg);
    }

    .inscripcion-formulario > .campo {
        grid-column: span 2;
    }

    .inscripcion-formulario__mitad,
    .inscripcion-formulario > .inscripcion-formulario__mitad {
        grid-column: span 3;
    }

    .inscripcion-formulario__abonado {
        grid-column: span 3;
    }

    .inscripcion-formulario__ancho-completo,
    .inscripcion-formulario > .inscripcion-formulario__ancho-completo {
        grid-column: 1 / -1;
    }

    .inscripcion-confirmar__grid {
        grid-template-columns: minmax(0, 1.15fr) minmax(18rem, 0.85fr);
        align-items: start;
    }
}

/* --- Formularios ---
   Etiquetas en mayúsculas con asterisco para obligatorios, campo con
   placeholder tenue, borde fino oscuro. */
.campo {
    display: grid;
    gap: var(--espaciado-sm);
}

.campo__etiqueta {
    font-size: var(--tamano-sm);
    font-weight: var(--peso-bold);
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.campo__etiqueta--requerido::after {
    content: "*";
    margin-left: 0.15em;
}

.campo input,
.campo select,
.campo textarea {
    min-height: var(--alto-minimo-touch);
    padding: 0.65rem 0.85rem;
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-md);
    background: var(--color-superficie);
    color: var(--color-texto);
    font-size: var(--tamano-base);
}

.campo input::placeholder,
.campo textarea::placeholder {
    color: var(--color-texto-muy-suave);
}

.campo input:disabled,
.campo select:disabled,
.campo textarea:disabled {
    background: var(--color-superficie-fondo);
    color: var(--color-texto-muy-suave);
    cursor: not-allowed;
}

/* Textarea: confirmado en el PDF (pág. 10, "Comentario para el
   alumno/a") — mismo estilo que el resto de campos, pero con más
   alto por defecto para texto de varias líneas. */
.campo textarea {
    min-height: 8em;
    resize: vertical;
}

/* Select: mismo estilo que input; el PDF no muestra ningún <select>
   nativo (usa pastillas para PISCINA/NIVEL), así que el aspecto del
   desplegable en sí [ESTIMADO] sigue el look general de inputs. */

/* Checkbox / radio: el PDF muestra círculos de selección simples en
   ALUMNADO y "Seleccionar todo" (págs. 7-10). Se usa el control nativo
   con --color-primario-oscuro como acento en vez de redibujar el
   círculo a mano, para no fijar un diseño custom que el PDF no detalla
   con precisión suficiente. */
.opcion {
    display: inline-flex;
    align-items: center;
    gap: var(--espaciado-sm);
    font-weight: var(--peso-normal);
    color: var(--color-texto);
    cursor: pointer;
}

.opcion input[type="checkbox"],
.opcion input[type="radio"] {
    width: 20px;
    height: 20px;
    min-height: 0;
    flex: none;
    accent-color: var(--color-primario-oscuro);
    cursor: pointer;
}

.opcion:has(input:disabled) {
    color: var(--color-texto-muy-suave);
    cursor: not-allowed;
}

/* (El antiguo .panel-filtros —<details> plegable con acciones Buscar/
   Limpiar— se eliminó en la Fase 4 de Cursos/Index: la pág. 2 del PDF
   muestra los grupos de pastillas sueltos sobre el fondo, actuando como
   filtros directos, y ninguna otra vista usaba el panel.) */

.formulario-rejilla {
    display: grid;
    gap: var(--espaciado-md);
    grid-template-columns: 1fr;
}

@media (min-width: 900px) {
    .formulario-rejilla--3 {
        grid-template-columns: repeat(3, 1fr);
    }

    .formulario-rejilla--2 {
        grid-template-columns: repeat(2, 1fr);
    }
}

/* Sí/No como pastillas de dos estados (¿Abonado?, ítems de evaluación) */
.toggle-si-no {
    display: inline-flex;
    gap: var(--espaciado-xs);
}

.toggle-si-no button {
    min-width: 64px;
    min-height: var(--alto-minimo-touch);
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-md);
    background: var(--color-superficie);
    font-weight: var(--peso-bold);
    cursor: pointer;
}

.toggle-si-no button[aria-pressed="true"].toggle-si-no__si {
    background: var(--color-exito);
    color: #fff;
    border-color: var(--color-exito);
}

.toggle-si-no button[aria-pressed="true"].toggle-si-no__no {
    background: var(--color-peligro);
    color: #fff;
    border-color: var(--color-peligro);
}

/* --- Calendario compacto (Pasar lista) --- */
.calendario {
    display: grid;
    gap: var(--espaciado-sm);
}

.calendario__cabecera {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--espaciado-md);
    font-weight: var(--peso-bold);
}

.calendario__cabecera button {
    border: none;
    background: none;
    font-size: var(--tamano-lg);
    cursor: pointer;
}

.calendario__rejilla {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: var(--espaciado-xs);
    text-align: center;
}

.calendario__dia {
    display: grid;
    place-items: center;
    aspect-ratio: 1;
    border-radius: 50%;
    cursor: pointer;
}

/* Confirmado en el PDF (pág. 7-8, "Adultos > Pasar lista"): el día
   seleccionado se resalta con el acento de la CATEGORÍA activa de la
   pantalla (naranja en Adultos), no con el color de una piscina.
   Por defecto usa --color-categoria-adultos; si esta pantalla se usa
   en otra categoría, sobrescribir con la variable de esa categoría. */
.calendario__dia--seleccionado {
    background: var(--color-categoria-adultos, var(--color-primario));
    font-weight: var(--peso-bold);
}

.lista-horarios {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
    gap: var(--espaciado-sm);
}

.horario {
    display: grid;
    place-items: center;
    min-height: var(--alto-minimo-touch);
    padding: 0.4rem;
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-md);
    background: var(--color-superficie-fondo);
    font-size: var(--tamano-sm);
    cursor: pointer;
}

.horario--seleccionado {
    background: var(--color-primario);
    border-width: 2px;
}

/* --- Lista de alumnado (acordeón simple con contacto) --- */
.lista-alumnado {
    border-top: 1px solid var(--color-borde-suave);
}

.alumno {
    display: flex;
    align-items: center;
    gap: var(--espaciado-sm);
    padding: var(--espaciado-md) 0;
    border-bottom: 1px solid var(--color-borde-suave);
    cursor: pointer;
}

.alumno__nombre {
    flex: 1;
    font-size: var(--tamano-lg);
}

.alumno__detalle {
    padding: 0 0 var(--espaciado-md) calc(var(--espaciado-md) + 24px);
    color: var(--color-texto-suave);
    font-size: var(--tamano-sm);
}

/* --- Rúbrica 1-10 (evaluación técnica) --- */
.rubrica {
    display: grid;
    gap: var(--espaciado-xs);
}

.rubrica__titulo {
    font-weight: var(--peso-bold);
}

.rubrica__opciones {
    display: flex;
    flex-wrap: wrap;
    gap: var(--espaciado-xs);
}

.rubrica__opciones button {
    width: var(--alto-minimo-touch);
    height: var(--alto-minimo-touch);
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-sm);
    background: var(--color-superficie);
    font-weight: var(--peso-bold);
    cursor: pointer;
}

.rubrica__opciones button[aria-pressed="true"] {
    background: var(--color-primario);
}

/* --- Banner de fase de evaluación ---
   Cabecera de color de fase + lista de ítems Sí/No. El color viene
   de --color-fase-{orden}-{slug} vía atributo data-fase="1".."7". */
.fase {
    border-radius: var(--radio-md);
    overflow: hidden;
}

.fase__cabecera {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--espaciado-sm) var(--espaciado-md);
    color: var(--color-sobre-fase);
    font-weight: var(--peso-bold);
    text-transform: uppercase;
    cursor: pointer;
    transition: filter var(--transicion-rapida);
}

@media (hover: hover) and (pointer: fine) {
    /* Cada .fase__cabecera ya tiene su propio color de fondo (1..7), así
       que oscurecer con filter es seguro aquí (a diferencia de tocar el
       color de texto): funciona igual sobre cualquiera de los 7 colores. */
    .fase__cabecera:hover {
        filter: brightness(0.95);
    }
}

.fase__cabecera::after {
    content: "\25BE";
    flex: none;
    margin-inline-start: var(--espaciado-sm);
    transition: transform var(--transicion-rapida);
}

.fase[open] > .fase__cabecera::after {
    transform: rotate(180deg);
}

.fase[data-fase="1"] .fase__cabecera { background: var(--color-fase-1-adaptacion); }
.fase[data-fase="2"] .fase__cabecera { background: var(--color-fase-2-descubrimiento); }
.fase[data-fase="3"] .fase__cabecera { background: var(--color-fase-3-confianza); }
.fase[data-fase="4"] .fase__cabecera { background: var(--color-fase-4-autonomia); }
.fase[data-fase="5"] .fase__cabecera { background: var(--color-fase-5-dominio); }
.fase[data-fase="6"] .fase__cabecera { background: var(--color-fase-6-tecnica); }
.fase[data-fase="7"] .fase__cabecera { background: var(--color-fase-7-competicion); }

.fase__item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--espaciado-md);
    padding: var(--espaciado-sm) var(--espaciado-md);
    background: var(--color-superficie);
    border-bottom: 1px solid var(--color-borde-suave);
}

/* --- Stepper / wizard --- */
.stepper {
    display: flex;
    gap: var(--espaciado-sm);
    flex-wrap: wrap;
}

.stepper__paso {
    border: 1px solid var(--color-borde);
    border-radius: 999px;
    padding: 0.35rem 0.85rem;
    color: var(--color-texto-suave);
    font-weight: var(--peso-bold);
}

.stepper__paso--activo,
.stepper__paso--hecho {
    background: var(--color-primario);
    border-color: var(--color-primario);
    color: var(--color-sobre-primario);
}

/* --- Tarjeta de acceso (login) --- */
.tarjeta-acceso {
    display: grid;
    gap: var(--espaciado-md);
    max-width: 480px;
    margin: var(--espaciado-xxl) auto;
}

.tarjeta-acceso input {
    min-height: var(--alto-minimo-touch);
    padding: 0.85rem;
    border: 1px solid var(--color-borde);
    border-radius: var(--radio-md);
}

.tarjeta-acceso__olvido {
    text-align: center;
    color: var(--color-texto-suave);
    text-decoration: none;
}

/* --- Estado vacío / avisos --- */
.aviso {
    border: 1px dashed var(--color-borde-suave);
    border-radius: var(--radio-md);
    padding: var(--espaciado-lg);
    color: var(--color-texto-suave);
}

/* --- Utilidades de acciones al pie del formulario --- */
.acciones-formulario {
    display: flex;
    flex-wrap: wrap;
    gap: var(--espaciado-md);
    align-items: center;
}

.acciones-formulario--reparto {
    justify-content: space-between;
}

/* ============================================================
   Sistema responsive
   Mobile-first: las reglas base sirven para <600px. A partir de ahí
   se añaden columnas / rejillas más anchas. Estos dos puntos de
   corte son los únicos que deben usarse en todo el proyecto (ver
   documentación de --ancho-contenido en _tema.css).
   ============================================================ */
@media (min-width: 600px) {
    .formulario-rejilla {
        grid-template-columns: 1fr 1fr;
    }

    .grupo-filtro__opciones {
        row-gap: var(--espaciado-md);
    }
}

@media (min-width: 900px) {
    .filtros {
        grid-template-columns: repeat(2, 1fr);
    }

    .boton {
        width: auto;
    }
}

@media (max-width: 599px) {
    .cabecera-sitio {
        flex-wrap: wrap;
    }

    .acciones-formulario {
        flex-direction: column;
        align-items: stretch;
    }

    .lista-horarios {
        grid-template-columns: repeat(2, 1fr);
    }
}
