/*
  LA FUENTE PROPIA (Inter, licencia SIL OFL — ver LICENCIA-Inter.txt).
  Decisión de Sergio del 16/08/2026: era la web entera en la letra por defecto
  del navegador, y esa letra es el 60 % de parecer una plantilla. Un fichero
  variable de 344 KB, servido desde nuestro dominio (sin Google Fonts), con
  swap para que el texto pinte al instante con la del sistema mientras llega.
*/
@font-face {
  font-family: 'Inter';
  src: url('/InterVariable.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
/*
  Oposiciones.red — hoja de estilo única.

  TRES DECISIONES QUE MANDAN SOBRE TODAS LAS DEMÁS

  1. NO HAY JAVASCRIPT. Ni aquí ni en el HTML. Quien se prepara una oposición
     entra desde el móvil en el metro, desde el ordenador de una biblioteca o
     desde un portátil de hace ocho años. Todo —filtros, buscador, paginación,
     menú— funciona con enlaces y formularios. Eso además permite una política de
     seguridad estricta de verdad, sin `unsafe-inline`.

  2. TIPOGRAFÍA DEL SISTEMA. Una fuente de Google son dos peticiones a otro
     dominio, un salto de maquetación al cargar y un dato de navegación que se
     va a un tercero. La del sistema se ve bien en todas partes y se pinta en el
     primer fotograma.

  3. EL ESTADO DEL PLAZO ES LO PRIMERO QUE SE VE. Un opositor tiene una sola
     pregunta al llegar: «¿llego a tiempo?». El color y la posición contestan
     antes de que empiece a leer. Y nunca solo el color: siempre hay texto, o
     quien no distingue el rojo del verde se queda sin la mitad de la respuesta.
*/

:root {
  color-scheme: light dark;

  /*
    LOS GRISES ESTÁN MEDIDOS, NO ELEGIDOS A OJO.

    Medido en el navegador sobre el sitio real: `--tinta-tenue` valía #7c8798 y
    daba **3,64** de contraste sobre el lienzo blanco y **3,42** sobre el fondo,
    cuando el mínimo de la WCAG para texto normal es 4,5. Y es justo el color de
    lo más pequeño de la página: las fechas del BOE, las notas de las cifras y
    el rótulo «plaza». Un gris que se ve bien en la pantalla de quien lo elige y
    no se lee en la de un móvil viejo al sol.

    Ahora #646d7e: 4,93 sobre blanco y 4,72 sobre el fondo. Sigue siendo un gris
    secundario —se distingue perfectamente de la tinta principal— y se lee.
  */
  --tinta:        #12161f;
  --tinta-suave:  #545d6e;
  --tinta-tenue:  #646d7e;
  --fondo:        #f7f8fb;
  --lienzo:       #ffffff;
  --lienzo-2:     #f1f3f8;
  --borde:        #e2e6ee;
  /*
    EL BORDE DE UN CAMPO NO ES DECORACIÓN: ES EL CONTROL.

    #cfd5e1 daba 1,47 de contraste sobre el blanco. La WCAG 1.4.11 exige 3,0 al
    contorno de un control, y con razón: si no se ve el borde, no se ve dónde
    hay que escribir. Ahora 3,44 sobre blanco y 3,23 sobre el fondo.

    `--borde` sigue siendo suave a propósito: ese sí es decorativo —el canto de
    una tarjeta— y la norma no se lo exige. Son dos cosas distintas, y por eso
    son dos variables.
  */
  --borde-fuerte: #818b9d;

  --marca:        #4338ca;
  --marca-viva:   #5b4fe0;
  --marca-tenue:  #eef0fe;
  --marca-borde:  #d3d6fa;

  --acento:       #b45309;
  --acento-tenue: #fef3e2;

  --abierto:      #0a7145;
  --abierto-tenue:#e5f6ee;
  --pronto:       #a35a00;
  --pronto-tenue: #fdf1de;
  --urgente:      #b42318;
  --urgente-tenue:#fdecea;
  /* 4,19 sobre su propio fondo: se quedaba corto. #5a6373 da 5,05. */
  --cerrado:      #5a6373;
  --cerrado-tenue:#eef0f4;

  --sombra:    0 1px 2px rgb(16 24 40 / .05), 0 1px 3px rgb(16 24 40 / .06);
  --sombra-md: 0 4px 8px -2px rgb(16 24 40 / .08), 0 2px 4px -2px rgb(16 24 40 / .05);
  --sombra-lg: 0 12px 24px -6px rgb(16 24 40 / .1), 0 4px 8px -4px rgb(16 24 40 / .06);

  --radio:    12px;
  --radio-sm: 8px;
  --radio-lg: 18px;
  --ancho:    1180px;

  --tipo: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
}

@media (prefers-color-scheme: dark) {
  :root {
    --tinta:        #e7ebf3;
    --tinta-suave:  #a3adbe;
    /* 4,39 sobre la cabecera de una tabla, con 4,5 exigidos. Ahora 4,88. */
    --tinta-tenue:  #838ea0;
    --fondo:        #0c0f15;
    --lienzo:       #141922;
    --lienzo-2:     #1b212c;
    --borde:        #262d3a;
    /* Sin transparencia: con alfa, el contraste real dependía de lo que
       hubiera detrás y no se podía medir. Opaco da 3,13 sobre el lienzo. */
    --borde-fuerte: #5a6880;

    --marca:        #a5b0ff;
    --marca-viva:   #b9c1ff;
    --marca-tenue:  #1c2140;
    --marca-borde:  #303a6b;

    --acento:       #f0b357;
    --acento-tenue: #2c2314;

    --abierto:      #5fd39b;
    --abierto-tenue:#10281f;
    --pronto:       #f0b357;
    --pronto-tenue: #2c2314;
    --urgente:      #ff8b7e;
    --urgente-tenue:#2e1a18;
    --cerrado:      #8b95a6;
    --cerrado-tenue:#1c222c;

    --sombra:    0 1px 2px rgb(0 0 0 / .4);
    --sombra-md: 0 4px 12px -2px rgb(0 0 0 / .5);
    --sombra-lg: 0 16px 32px -8px rgb(0 0 0 / .6);
  }
}

/* ── Base ─────────────────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; }

/*
  ⚠ `overflow-x: clip` HACE FALTA AQUÍ Y EN EL BODY, y se comprobó midiendo.

  Con el clip solo en el `body`, el `html` seguía propagando el desbordamiento:
  medido a 1.440 px de ventana, `scrollWidth` daba 1.433 sobre un `clientWidth`
  de 1.425 —ocho píxeles— porque la capa de fondo a `100vw` cuenta la barra de
  desplazamiento, que aquí mide 15. El recorte visual sí funcionaba; el
  desbordamiento del documento, no.

  `clip` y no `hidden`: `hidden` crearía un contexto de desplazamiento y la
  cabecera `position: sticky` dejaría de pegarse arriba.
*/
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; overflow-x: clip; }

body {
  margin: 0;
  /*
    ⚠ `clip`, NUNCA `hidden`. Absorbe los ~15 px que se pasa una capa de fondo
    a `100vw` —porque `100vw` cuenta la barra de desplazamiento— sin crear un
    contexto de desplazamiento. Con `hidden` lo crearía, y la cabecera
    `position: sticky` dejaría de pegarse arriba. Ver `.a-sangre`.
  */
  overflow-x: clip;
  background: var(--fondo);
  color: var(--tinta);
  font-family: var(--tipo);
  font-size: 16.5px;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 { line-height: 1.2; margin: 0 0 .5em; font-weight: 700; letter-spacing: -.018em; }
h1 { font-size: clamp(1.95rem, 4.6vw, 3rem); letter-spacing: -.03em; }
h2 { font-size: clamp(1.35rem, 2.7vw, 1.85rem); }
h3 { font-size: 1.15rem; }
h4 { font-size: 1rem; }
p  { margin: 0 0 1em; }

a { color: var(--marca); text-decoration-color: color-mix(in srgb, var(--marca) 35%, transparent); text-underline-offset: 3px; }
a:hover { text-decoration-color: currentColor; }

:focus-visible { outline: 3px solid var(--marca); outline-offset: 2px; border-radius: 4px; }

img, svg { max-width: 100%; height: auto; }

.contenedor { width: 100%; max-width: var(--ancho); margin-inline: auto; padding-inline: 20px; }
.estrecho   { max-width: 760px; }

/*
  ═══════════════════════════════════════════════════════════════════════════
  EL ANCHO NO PUEDE DEPENDER DE QUE CADA VISTA SE ACUERDE
  ═══════════════════════════════════════════════════════════════════════════

  `pagina()` mete el contenido en un `<main>` pelado y deja que cada vista se
  envuelva en `.contenedor` por su cuenta. La mitad lo hacía y la mitad no, así
  que las páginas de materias, de oficios y toda el área de estudio salían **de
  borde a borde** en una pantalla ancha: el título pegado al cristal y las filas
  de mil quinientos píxeles con el número en la otra punta.

  Y no se veía en ninguna prueba: el rastreador comprueba que la página
  responde y que los enlaces van a algún sitio, no que se pueda leer. Yo
  escribí el CSS del área de estudio y no lo miré ni una vez. Se ve mirando.

  ⚠ Y este comentario se comió su propia regla en el primer intento. Al citar
  una ruta detrás de dos asteriscos quedó escrita la secuencia que CIERRA un
  comentario, así que se cerró aquí mismo: el resto del texto pasó a ser CSS
  inválido, el navegador descartó en silencio la regla de abajo —solo la
  primera; la segunda sí entró— y la página siguió saliendo igual de ancha, con
  código 200 y sin una sola queja.

  Dentro de un comentario no se escribe nunca un asterisco seguido de barra.
  Hay una prueba en `test/estilos.test.js` que lo comprueba buscando prosa en
  español fuera de los comentarios, que es lo que deja un corte de estos.

  Se arregla en el `<main>`, que es por donde pasa todo, y así no hay nada que
  recordar. Los `.contenedor` que ya estaban dentro se quedan: su `max-width`
  es el mismo y solo hay que quitarles el relleno para que no se sume dos
  veces. `.estrecho` sigue funcionando porque su `max-width` es menor.
*/
main#principal {
  width: 100%;
  max-width: var(--ancho);
  margin-inline: auto;
  padding-inline: 20px;
}
main#principal .contenedor { padding-inline: 0; }

.saltar {
  position: absolute; left: -9999px; top: 0; z-index: 99;
  background: var(--marca); color: #fff; padding: .7em 1.2em; border-radius: 0 0 var(--radio-sm) 0;
}
.saltar:focus { left: 0; }

/* ── Cabecera ─────────────────────────────────────────────────────────── */

.cabecera {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--lienzo) 86%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--borde);
}
.cabecera-fila { display: flex; align-items: center; gap: 1.4rem; min-height: 62px; }


.marca { display: inline-flex; align-items: center; gap: .45rem; font-weight: 800; font-size: 1.12rem; letter-spacing: -.03em; color: var(--tinta); text-decoration: none; white-space: nowrap; }
.marca b { color: var(--marca); font-weight: 800; }
/* El símbolo del favicon, en la cabecera: la marca se reconoce igual en la
   pestaña, en la barra y en la tarjeta de WhatsApp. */
.marca-simbolo { width: 26px; height: 26px; border-radius: 7px; flex-shrink: 0; }
.marca span { color: var(--tinta-tenue); font-weight: 600; }

.nav { display: flex; gap: .15rem; flex-wrap: wrap; margin-left: auto; align-items: center; }
/*
  La acción y el acceso, fuera del `<nav>` y fuera de la tira que se desliza.
  Ver el porqué en `pagina()`: con todo dentro, a 360 px «Estudiar» quedaba
  cortado por la mitad y el acceso, fuera de la pantalla.
*/
.cabecera-acciones { display: flex; gap: .4rem; align-items: center; flex: none; }
/* En escritorio el orden visual es marca · navegación · acciones, aunque en el
   HTML las acciones vayan antes (ver el comentario de la cabecera). */
@media (min-width: 861px) {
  .nav { order: 1; }
  .cabecera-acciones { order: 2; margin-left: .5rem; }
  /* Aquí manda el botón destacado, que no se desliza. Ver el comentario de
     `nav` en vistas.js: el enlace se pinta en los dos sitios y cada ancho
     enseña el suyo, para que no haya dos «Estudiar» a la vez. */
  .nav-estudiar { display: none; }
}
/*
  ⚠ EL RELLENO ESTUVO AJUSTADO AL PÍXEL, Y YA NO HACE FALTA.

  Con once enlaces el menú medía 983 px y cabían 972 a 1.180 px: se pasaba en
  **11 px** y se partía en dos líneas en todo el escritorio, subiendo la
  cabecera fija de 63 a 81 px. Se bajó el relleno de .72 a .6 rem para ganar 21
  px, y aquí quedó escrito que **la solución buena era quitar enlaces**.

  Hecho: el menú tiene cinco tareas y el acceso (ver `NAV` en `vistas.js`), así
  que el relleno vuelve a ser holgado. Ahora hay sitio de sobra, y esa holgura
  es el margen que protege de la próxima vez.

  Al añadir un enlace: **medir a 360 px y a 1.180**. Por debajo de 861 px la
  barra se desliza de lado y el problema no se ve.
*/
/* Los dos bloques comparten estilo: para el visitante es una sola barra, que
   se parta en dos contenedores es asunto del ancho de pantalla. */
.nav a, .cabecera-acciones a {
  color: var(--tinta-suave); text-decoration: none; font-weight: 600; font-size: .935rem;
  padding: .42rem .8rem; border-radius: var(--radio-sm); white-space: nowrap;
}
.nav a:hover, .cabecera-acciones a:hover { background: var(--lienzo-2); color: var(--tinta); }
.nav a[aria-current="page"], .cabecera-acciones a[aria-current="page"] { color: var(--marca); background: var(--marca-tenue); }
/*
  ⚠ DOS CLASES EN EL SELECTOR, NO UNA. Escrito como `.destacado` a secas
  perdía contra `.cabecera-acciones a` —que tiene una clase y un elemento— y el
  botón salía con el texto GRIS SOBRE MORADO, ilegible. Es el fallo 5 del
  CLAUDE.md: en CSS gana la especificidad, y si empata, el orden.
*/
.nav .destacado, .cabecera-acciones .destacado {
  background: var(--marca); color: #fff; padding: .45rem .95rem;
}
.nav .destacado:hover, .cabecera-acciones .destacado:hover,
.nav .destacado[aria-current="page"], .cabecera-acciones .destacado[aria-current="page"] {
  background: var(--marca-viva); color: #fff;
}
@media (prefers-color-scheme: dark) {
  .nav .destacado, .cabecera-acciones .destacado,
  .nav .destacado:hover, .cabecera-acciones .destacado:hover,
  .nav .destacado[aria-current="page"], .cabecera-acciones .destacado[aria-current="page"] { color: #10131c; }
}

/*
  ═══════════════════════════════════════════════════════════════════════════
  LA CABECERA OCUPABA 228 PÍXELES EN UN MÓVIL, Y ERA FIJA
  ═══════════════════════════════════════════════════════════════════════════

  Medido renderizando el sitio a 390 px: los seis enlaces del menú se partían en
  seis líneas junto al logotipo y la cabecera crecía hasta **228 px**. En una
  pantalla de 844 px eso es el 27 %, ocupado de forma permanente porque la
  cabecera está fijada arriba. En todas las páginas, antes de ver nada.

  La cura sin JavaScript es una tira de una sola línea que se desliza con el
  dedo. No se esconde ningún enlace —esconderlos es la otra salida fácil y deja
  medio sitio inalcanzable— y la cabecera vuelve a medir 62 px.

  El degradado del borde derecho es lo que avisa de que ahí sigue habiendo cosas:
  una tira que se corta en seco parece un menú completo.
*/
/*
  ── Y LA TIRA SE QUEDÓ CORTA PORQUE EL MENÚ CRECIÓ ───────────────────────────

  Aquello se midió con seis enlaces. Hoy hay once, y el logotipo se lleva la
  mitad del renglón: medido a 360 px, la tira mide **161 px de los 910 que
  ocupa el menú, el 18 %**. Se ven «Plazo abierto» y media palabra más, y llegar
  a «Estudiar» exige descubrir que aquello se arrastra de lado.

  El degradado avisaba de que había más, pero avisar de que el 82 % está fuera
  no es lo mismo que dejarlo a mano.

  La tira baja a su propio renglón. Medido después, a 360 px: pasa de 161 a
  305 px útiles y del 18 % al **34 % del menú a la vista**, y la cabecera crece
  de 63 a 89 px —muy lejos de los 228 que costaba partir el menú en varias
  líneas—. Se paga altura una vez y se gana navegación en todas las páginas.

  (Las tres cifras son medidas después del cambio. La primera vez escribí aquí
  «320 px y 105 de cabecera», que era lo que yo esperaba: un número previsto
  puesto en pasado se lee igual que uno medido y ya no hay forma de
  distinguirlos.)
*/
@media (max-width: 860px) {
  .cabecera-fila { gap: .35rem .8rem; flex-wrap: wrap; }
  .nav {
    /* Renglón propio: `margin-left:auto` lo empujaba a la derecha del logotipo
       y hay que anularlo, o la tira arranca desplazada. */
    flex-basis: 100%; margin-left: 0;
    /* `min-width: 0` es lo que de verdad hace que funcione: un hijo flexible
       no encoge por debajo del ancho de su contenido salvo que se le diga, así
       que sin esto la tira sigue partiéndose en varias líneas y el desbordamiento
       no llega a existir. Sin esa línea la cabecera pasó de 228 px a 191, que
       sigue siendo un cuarto de la pantalla. */
    min-width: 0;
    flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: contain;
    scrollbar-width: none; -ms-overflow-style: none;
    /* Sitio para que el contorno de foco no quede cortado por el recorte. */
    padding: .3rem .2rem;
    mask-image: linear-gradient(to right, #000 calc(100% - 26px), transparent);
  }
  .nav::-webkit-scrollbar { display: none; }
  .nav a { flex: none; }
  /* La acción y el acceso comparten fila con la marca, pegados a la derecha:
     ocupan el hueco que deja el logotipo en vez de gastar una fila, y nunca
     caen fuera de la tira que se desliza.

     ⚠ El empujón lo da la MARCA creciendo, no un `margin-left: auto` en las
     acciones. Medido: marca 131 px + acciones 171 en 345 disponibles —caben de
     sobra— y aun así el margen automático las mandaba a una segunda línea,
     dejando la cabecera en tres filas y 132 px de alto. */
  /*
    ⚠ EL ANCHO ÚTIL SON 305 px, NO 345: el contenedor lleva 20 px de relleno a
    cada lado. Con la marca a 131 px y las acciones a 171, la suma daba 315 y
    se pasaba por **diez píxeles**, así que las acciones caían a una línea
    propia y la cabecera se iba a tres filas y 132 px de alto.

    Se recorta por los dos lados —la marca un punto y el acceso una palabra,
    «Panel» en vez de «Tu panel»— y quedan ~274 px: caben con holgura, que es
    lo que hay que dejar para que el próximo cambio no vuelva a partirla.
  */
  .marca { flex: 0 0 auto; font-size: 1rem; }
  .cabecera-acciones { margin-left: auto; }
  .cabecera-acciones a { padding: .38rem .6rem; font-size: .9rem; }
  /*
    ⚠ Y VOLVIÓ A PARTIRSE, POR UN TERCER BOTÓN.

    Al añadir «Suscribirse» —que hacía falta: en toda la web no había otro sitio
    donde pagar— las acciones pasaron de 171 px a ~260 y se repitió exactamente
    lo que este bloque describe: caían a su propia fila, descentradas, y la
    cabecera se iba a tres renglones.

    La salida no es quitar el botón nuevo, es quitar el que **sobra**:
    «Estudiar» ya está en la tira que se desliza, dos centímetros más abajo. Un
    duplicado no puede ocupar el sitio de lo único que no está en ninguna otra
    parte.

    Y el relleno del destacado baja aquí a propósito: `.cabecera-acciones a` no
    le gana en especificidad —dos clases contra una clase y un elemento—, así
    que sin esta regla el botón de comprar conserva sus .95rem de escritorio.
  */
  .accion-estudiar { display: none; }
  .cabecera-acciones .destacado { padding: .38rem .7rem; }
}

/*
  ═══════════════════════════════════════════════════════════════════════════
  FONDOS QUE LLEGAN DE LADO A LADO, CON EL CONTENIDO CENTRADO
  ═══════════════════════════════════════════════════════════════════════════

  El héroe y la franja de venta son `<section>` dentro de `main#principal`, que
  lleva `max-width: 1180px`. Su fondo medía como el main y no como la ventana,
  así que quedaban bandas sin color a los lados. Medido: 20 px hasta 1.180 de
  ventana, **143 px a 1.425, 383 a 1.905 y 703 a 2.545** —el 40 % del ancho en
  un monitor de 1920, el 55 % en uno de 2560—. Y cantaba porque la cabecera y
  el pie **sí** llegan al cristal: color arriba, color abajo y una caja en
  medio, con el borde inferior cortado a la mitad del ancho.

  La cura NO es quitarle el `max-width` al main: **seis de las doce páginas
  cuelgan su contenido directamente de él, sin `.contenedor`** —temarios,
  oficios, materias, estudio, acceso y entrar—, y se irían de borde a borde.
  Es el fallo que ya se sufrió cuando esa regla se perdió, y hay una prueba
  vigilándola.

  Así que el fondo se despega de la caja: una capa detrás, a ancho de ventana.
  Tres cosas que hay que saber si se toca:

  1. **Nada de `overflow: hidden` en la sección**: recortaría justo la capa que
     tiene que sobresalir. Ya no está.
  2. `100vw` incluye la barra de desplazamiento, así que la capa se pasa unos
     15 px. `overflow-x: clip` en el `body` los absorbe **sin crear contexto de
     desplazamiento**, que es la diferencia con `hidden`: con `hidden` la
     cabecera `sticky` dejaría de pegarse.
  3. Los **radios de los degradados van en porcentaje**. Estaban en píxeles
     fijos (1100 y 760) con los centros en porcentaje: a 1.140 px las dos
     manchas se solapan 211 px y se ve continuo, pero al ensanchar el elemento
     los centros se separan sin que las manchas crezcan. Calculado: hueco
     pálido de 413 px a 1.920 (22 %), 925 a 2.560 y 1.629 a 3.440 (47 %). Con
     los radios en `%` el solape es siempre el mismo ~18 % del ancho.
*/
.a-sangre { position: relative; }
.a-sangre::before {
  content: ''; position: absolute; z-index: -1;
  top: 0; bottom: 0; left: 50%; width: 100vw; transform: translateX(-50%);
}

/* ── Héroe ────────────────────────────────────────────────────────────── */

.heroe {
  padding: clamp(2.6rem, 7vw, 5rem) 0 clamp(2rem, 4vw, 3rem);
}
.heroe::before {
  background:
    radial-gradient(96% 460px at 12% -8%, color-mix(in srgb, var(--marca) 16%, transparent), transparent 62%),
    radial-gradient(67% 380px at 92% 4%, color-mix(in srgb, var(--acento) 13%, transparent), transparent 58%);
  border-bottom: 1px solid var(--borde);
}
/*
  ─── EL HÉROE OCUPABA MEDIA PANTALLA Y DEJABA LA OTRA MEDIA EN BLANCO ────────

  Con el titular a 17 caracteres por línea y todo alineado a la izquierda, en un
  monitor de 1.920 px la mitad derecha quedaba literalmente vacía. Se veía en la
  primera captura del sitio ya en producción.

  Ahora es una rejilla de dos columnas a partir de 1.020 px: el mensaje y el
  buscador a la izquierda, y **las cifras a la derecha**, que es donde miran los
  ojos en cuanto entran. Por debajo de ese ancho se apila, que es lo correcto en
  un móvil: primero se lee para qué sirve esto y después los números.
*/
.heroe .contenedor { display: grid; gap: 2rem; align-items: start; }
@media (min-width: 1020px) {
  .heroe .contenedor { grid-template-columns: minmax(0, 1.05fr) minmax(300px, .95fr); gap: 3.5rem; align-items: center; }
  .heroe .cifras { grid-template-columns: repeat(2, 1fr); margin: 0; gap: 1rem; }
  /* Las cifras son el mejor argumento del sitio y estaban presentadas como
     notas: más cuerpo, y la de plazo abierto —la que trae a la gente— con el
     acento arriba. Solo en el héroe: las cifras de las demás páginas son
     información, no escaparate. */
  .heroe .cifra { padding: 1.35rem 1.4rem; }
  .heroe .cifra .valor { font-size: clamp(1.9rem, 2.6vw, 2.6rem); }
  .heroe .cifra.acento { border-top: 3px solid var(--marca); }
}
.heroe h1 { max-width: 19ch; margin-bottom: .35em; }
.heroe .entradilla { font-size: clamp(1.02rem, 1.9vw, 1.2rem); color: var(--tinta-suave); max-width: 56ch; margin-bottom: 1.6rem; }
.heroe .entradilla strong { color: var(--tinta); font-weight: 700; }

.sello {
  display: inline-flex; align-items: center; gap: .5rem; margin-bottom: 1.1rem;
  background: var(--lienzo); border: 1px solid var(--borde); box-shadow: var(--sombra);
  color: var(--tinta-suave); font-size: .84rem; font-weight: 600;
  padding: .34rem .78rem; border-radius: 999px;
}
.sello .punto { width: 7px; height: 7px; border-radius: 50%; background: var(--abierto); box-shadow: 0 0 0 3px color-mix(in srgb, var(--abierto) 22%, transparent); }

/* ── Buscador grande ──────────────────────────────────────────────────── */

.buscador-grande { display: flex; gap: .5rem; max-width: 640px; margin-bottom: 1rem; }
.buscador-grande input[type="search"] {
  flex: 1; min-width: 0;
  padding: .92rem 1.1rem; font-size: 1.02rem; font-family: inherit;
  border: 1px solid var(--borde-fuerte); border-radius: var(--radio);
  background: var(--lienzo); color: var(--tinta); box-shadow: var(--sombra);
}
.buscador-grande input::placeholder { color: var(--tinta-tenue); }
.buscador-grande input:focus { outline: none; border-color: var(--marca); box-shadow: 0 0 0 4px var(--marca-tenue); }

.sugerencias { display: flex; flex-wrap: wrap; gap: .42rem; align-items: center; font-size: .88rem; color: var(--tinta-tenue); }
.sugerencias a {
  background: var(--lienzo); border: 1px solid var(--borde); color: var(--tinta-suave);
  padding: .26rem .68rem; border-radius: 999px; text-decoration: none; font-weight: 600;
}
.sugerencias a:hover { border-color: var(--marca); color: var(--marca); background: var(--marca-tenue); }

/* ── Botones ──────────────────────────────────────────────────────────── */

.boton {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  font: inherit; font-weight: 700; font-size: .95rem;
  padding: .68rem 1.25rem; border-radius: var(--radio-sm);
  border: 1px solid transparent; cursor: pointer; text-decoration: none;
  background: var(--marca); color: #fff; box-shadow: var(--sombra);
}
.boton:hover { background: var(--marca-viva); color: #fff; }
@media (prefers-color-scheme: dark) { .boton, .boton:hover { color: #10131c; } }
.boton.secundario { background: var(--lienzo); color: var(--tinta); border-color: var(--borde-fuerte); }
.boton.secundario:hover { background: var(--lienzo-2); color: var(--tinta); border-color: var(--marca); }
.boton.pequeno { padding: .42rem .85rem; font-size: .88rem; }

/* ── Cifras ───────────────────────────────────────────────────────────── */

.cifras { display: grid; grid-template-columns: repeat(auto-fit, minmax(158px, 1fr)); gap: .9rem; margin: 1.8rem 0; }
.cifra {
  background: var(--lienzo); border: 1px solid var(--borde); border-radius: var(--radio);
  padding: 1.05rem 1.15rem; box-shadow: var(--sombra);
}
.cifra .valor { display: block; font-size: clamp(1.5rem, 3.4vw, 2.05rem); font-weight: 800; letter-spacing: -.035em; line-height: 1.1; font-variant-numeric: tabular-nums; }
.cifra .rotulo { display: block; font-size: .845rem; color: var(--tinta-suave); font-weight: 600; margin-top: .18rem; }
.cifra .nota { display: block; font-size: .82rem; color: var(--tinta-tenue); margin-top: .3rem; }
.cifra.acento .valor { color: var(--marca); }
.cifra.urgencia .valor { color: var(--urgente); }

/* ── Secciones ────────────────────────────────────────────────────────── */

.seccion { padding: clamp(2.2rem, 5vw, 3.4rem) 0; }
.seccion + .seccion { border-top: 1px solid var(--borde); }
.seccion-cab { display: flex; align-items: flex-end; justify-content: space-between; gap: 1rem; margin-bottom: 1.4rem; flex-wrap: wrap; }
.seccion-cab h2 { margin: 0; }
.seccion-cab p { margin: .3rem 0 0; color: var(--tinta-suave); font-size: .95rem; max-width: 62ch; }
.seccion-cab .enlace-mas { font-weight: 700; font-size: .92rem; white-space: nowrap; text-decoration: none; }
.seccion-cab .enlace-mas:hover { text-decoration: underline; }

/* ── Rejillas y tarjetas ──────────────────────────────────────────────── */

.rejilla { display: grid; gap: 1rem; }
.rejilla.c2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.rejilla.c3 { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.rejilla.c4 { grid-template-columns: repeat(auto-fit, minmax(205px, 1fr)); }

.tarjeta {
  background: var(--lienzo); border: 1px solid var(--borde); border-radius: var(--radio);
  padding: 1.15rem 1.25rem; box-shadow: var(--sombra);
  display: flex; flex-direction: column; gap: .55rem;
  transition: border-color .12s ease, box-shadow .12s ease, transform .12s ease;
}
a.tarjeta { text-decoration: none; color: inherit; }
a.tarjeta:hover { border-color: var(--marca-borde); box-shadow: var(--sombra-md); transform: translateY(-1px); }

.tarjeta .titulo { font-weight: 700; font-size: 1.03rem; line-height: 1.32; color: var(--tinta); letter-spacing: -.012em; }
.tarjeta .meta { font-size: .875rem; color: var(--tinta-suave); display: flex; flex-wrap: wrap; gap: .3rem .7rem; }
.tarjeta .meta b { color: var(--tinta); font-weight: 700; }
.tarjeta .pie-tarjeta { margin-top: auto; padding-top: .6rem; display: flex; align-items: center; justify-content: space-between; gap: .6rem; flex-wrap: wrap; }

/* Familia: tarjetas de navegación por vocación */
.familia {
  display: flex; flex-direction: column; gap: .3rem;
  background: var(--lienzo); border: 1px solid var(--borde); border-radius: var(--radio);
  padding: 1.05rem 1.1rem; text-decoration: none; color: inherit; box-shadow: var(--sombra);
}
.familia:hover { border-color: var(--marca-borde); box-shadow: var(--sombra-md); transform: translateY(-1px); }
.familia .icono { font-size: 1.5rem; line-height: 1; margin-bottom: .28rem; }
.familia .nombre { font-weight: 700; font-size: 1rem; color: var(--tinta); letter-spacing: -.012em; }
.familia .cuenta { font-size: .84rem; color: var(--tinta-suave); font-variant-numeric: tabular-nums; }
.familia .cuenta b { color: var(--abierto); font-weight: 700; }

/* ── Pastillas de estado ──────────────────────────────────────────────── */

/*
  NADA POR DEBAJO DE 12,5 PÍXELES.

  Medido sobre la página real: el rótulo «plaza» salía a 11,2 px y las pastillas
  a 12,4. Son los dos textos que contestan a «¿cuántas hay?» y «¿me da tiempo?»,
  o sea lo que más se mira, y estaban en el tamaño más pequeño del sitio.
*/
.pastilla {
  display: inline-flex; align-items: center; gap: .34rem;
  font-size: .81rem; font-weight: 700; letter-spacing: .012em;
  padding: .24rem .62rem; border-radius: 999px; white-space: nowrap;
  border: 1px solid transparent;
}
.pastilla::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }
.pastilla.abierto  { color: var(--abierto); background: var(--abierto-tenue); border-color: color-mix(in srgb, var(--abierto) 25%, transparent); }
.pastilla.pronto   { color: var(--pronto);  background: var(--pronto-tenue);  border-color: color-mix(in srgb, var(--pronto) 28%, transparent); }
.pastilla.urgente  { color: var(--urgente); background: var(--urgente-tenue); border-color: color-mix(in srgb, var(--urgente) 30%, transparent); }
.pastilla.cerrado  { color: var(--cerrado); background: var(--cerrado-tenue); border-color: var(--borde); }
.pastilla.neutra   { color: var(--tinta-suave); background: var(--lienzo-2); border-color: var(--borde); }
.pastilla.neutra::before { display: none; }
.pastilla.marca    { color: var(--marca); background: var(--marca-tenue); border-color: var(--marca-borde); }
.pastilla.marca::before { display: none; }

.etiquetas { display: flex; flex-wrap: wrap; gap: .35rem; }

/* ── La cabecera de una página de sección ─────────────────────────────── */
/*
  ⚠ ESTABA SIN UNA SOLA REGLA, EN LAS ONCE PÁGINAS QUE LA USAN.

  No se ve como un fallo porque el h1 y el <p> tienen estilo por su cuenta y la
  página «sale». Lo que salía era la entradilla a **1.140 px de ancho y 16,5 px
  de cuerpo**: unos 140 caracteres por renglón, el doble de lo que un ojo sigue
  sin perder la línea. Un texto así se salta, y era el primer párrafo de cada
  sección.

  Lo encontró la prueba que saca las clases del HTML y comprueba que cada una
  tenga regla. La lista escrita a mano que había antes no podía encontrarlo:
  solo comprobaba las clases que yo me acordé de escribir en ella.
*/
.cabecera-seccion { margin-bottom: 1.5rem; }
.cabecera-seccion h1 { margin-bottom: .55rem; }
.cabecera-seccion .entradilla {
  font-size: 1.06rem; line-height: 1.6; color: var(--tinta-suave);
  max-width: 68ch; margin: 0;
}
.cabecera-seccion .entradilla strong { color: var(--tinta); font-weight: 650; }

/* ── Listado de convocatorias ─────────────────────────────────────────── */
/*
  ⚠ `.lista` y `.listado` son lo mismo y estaban escritas las dos: siete
  páginas usan `.lista` —temarios, oficios, materias, organismos, y el área de
  estudio— y solo una `.listado`, que era la única con regla. Resultado medido
  en /temarios: fila a 549 px de alto 146 y la siguiente a 695. **Cero píxeles
  de separación** en la mayoría del sitio, mientras la única página que yo
  miraba salía bien.
*/
.listado, .lista { display: flex; flex-direction: column; gap: .7rem; }

/*
  ─── LA FILA SE REHIZO PORQUE TENÍA UN AGUJERO EN MEDIO ──────────────────────

  Era `1fr auto`: el título a la izquierda y un bloque con las plazas, el estado
  y la fecha pegado a la derecha. En una pantalla ancha eso deja **medio metro
  de nada** entre las dos cosas, y el ojo tiene que cruzarlo en cada fila para
  emparejar un puesto con su plazo. Se veía en la primera captura del sitio ya
  publicado.

  Ahora el estado y la fecha viven **debajo del título**, que es donde se leen
  de corrido, y a la derecha queda solo la cifra de plazas, que funciona como
  columna numérica. De paso el orden de lectura es el de la decisión: qué plaza,
  dónde, cuánto tiempo queda.

  Y se corrigió la jerarquía al revés: el «1» de las plazas estaba más grande y
  más gordo que el nombre del puesto, así que en una lista de veinte lo primero
  que se veía era una columna de unos.
*/
.fila {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .5rem 1.5rem; align-items: center;
  background: var(--lienzo); border: 1px solid var(--borde); border-radius: var(--radio);
  padding: 1rem 1.2rem; text-decoration: none; color: inherit; box-shadow: var(--sombra);
  transition: border-color .12s ease, box-shadow .12s ease;
}
.fila:hover { border-color: var(--marca-borde); box-shadow: var(--sombra-md); }
.fila .principal { min-width: 0; }
.fila .titulo { font-weight: 700; font-size: 1.1rem; line-height: 1.3; color: var(--tinta); letter-spacing: -.015em; margin-bottom: .22rem; }
.fila .donde { font-size: .9rem; color: var(--tinta-suave); }
.fila .donde b { color: var(--tinta); font-weight: 650; }
.fila .marcas { display: flex; align-items: center; flex-wrap: wrap; gap: .45rem .7rem; margin-top: .55rem; }
.fila .cuando { font-size: .82rem; color: var(--tinta-tenue); font-variant-numeric: tabular-nums; }
.fila .lateral { display: flex; flex-direction: column; align-items: flex-end; text-align: right; flex: none; }
.fila .plazas { font-size: 1.6rem; font-weight: 800; letter-spacing: -.035em; font-variant-numeric: tabular-nums; line-height: 1; color: var(--tinta); }
.fila .plazas small { display: block; font-size: .78rem; font-weight: 600; color: var(--tinta-tenue); letter-spacing: 0; margin-top: .2rem; }

@media (max-width: 560px) {
  .fila { grid-template-columns: 1fr; gap: .2rem; }
  /* En móvil la cifra va arriba del todo, antes que el título: es lo que
     distingue de un vistazo una plaza de cuarenta. */
  .fila .lateral { order: -1; flex-direction: row; align-items: baseline; gap: .35rem; text-align: left; }
  .fila .plazas { font-size: 1.25rem; }
  .fila .plazas small { display: inline; margin: 0; }
  .fila .titulo { font-size: 1.04rem; }
}

/* ── Filtros ──────────────────────────────────────────────────────────── */

.filtros {
  background: var(--lienzo); border: 1px solid var(--borde); border-radius: var(--radio);
  padding: 1.05rem 1.15rem; box-shadow: var(--sombra); margin-bottom: 1.3rem;
}
.filtros-fila { display: flex; flex-wrap: wrap; gap: .65rem; align-items: flex-end; }
.campo { display: flex; flex-direction: column; gap: .28rem; min-width: 0; }
.campo label { font-size: .78rem; font-weight: 700; color: var(--tinta-suave); text-transform: uppercase; letter-spacing: .045em; }
.campo select, .campo input {
  font: inherit; font-size: .92rem; padding: .5rem .7rem;
  border: 1px solid var(--borde-fuerte); border-radius: var(--radio-sm);
  background: var(--lienzo); color: var(--tinta); min-width: 8.5rem; max-width: 100%;
}
.campo select:focus, .campo input:focus { outline: none; border-color: var(--marca); box-shadow: 0 0 0 3px var(--marca-tenue); }
.campo.ancho { flex: 1 1 240px; }
.campo.ancho input { width: 100%; }

/*
  ── «Más filtros»: plegado en el móvil, abierto en el escritorio ─────────

  Medido a 360 px en /abiertas: los nueve controles ocupaban 786 px de una
  pantalla de 855 y el primer resultado quedaba a 1,4 pantallas. Arriba se
  queda la búsqueda; los ocho selectores entran en un `<details>`.

  En escritorio no se pliega nada —allí caben de sobra—, y para eso se esconde
  el `<summary>` y se fuerza el contenido visible aunque el `details` esté
  cerrado. Se hace así, y no con el atributo `open`, porque el estado tiene que
  depender del ancho de la ventana y no de lo que decidiera el servidor.
*/
/*
  ── La nota de método: qué hay detrás del dato, sin taparlo ──────────────

  Este sitio explica cómo mide cada cosa, y esas explicaciones se habían ido
  colocando ENCIMA de lo que explican. Medido a 360 px: en /temarios había que
  bajar 1.209 px para ver el primer temario, y en /estudio/oficio el botón
  quedaba a 738. Una nota se lee una vez; el contenido, cada visita.

  El resumen lleva **la cifra**, así que lo que la web dice en voz alta se
  sigue viendo sin abrir nada. Lo que se pliega es el porqué, no el qué.
*/
.nota-metodo {
  margin: 1rem 0 0; padding: .7rem .85rem;
  background: var(--lienzo-2); border: 1px solid var(--borde); border-radius: var(--radio-sm);
  font-size: .9rem; color: var(--tinta-suave);
}
.nota-metodo > summary { cursor: pointer; font-weight: 600; line-height: 1.45; }
.nota-metodo > summary:hover { color: var(--tinta); }
.nota-metodo > summary:focus-visible { outline: 2px solid var(--marca); outline-offset: 3px; border-radius: var(--radio-sm); }
.nota-metodo[open] > summary { margin-bottom: .5rem; }
.nota-metodo p { margin: .5rem 0 0; max-width: 68ch; line-height: 1.6; }
/* Las listas de dentro de una nota: sin viñeta de más ni sangría heredada. */
.nota-metodo ul { margin: .5rem 0 0; padding-left: 1.1rem; max-width: 68ch; }
.nota-metodo li { margin: .2rem 0; line-height: 1.5; }
.nota-metodo p:first-of-type { margin-top: 0; }

/*
  El índice de organismos de una provincia. Hasta 273 nombres, así que en una
  columna serían metros de página: `columns` los reparte según quepan y en móvil
  se queda en una sola sin necesidad de media query.

  `break-inside: avoid` porque sin él un nombre largo —«Ayuntamiento de Santa
  María del Páramo»— se parte entre dos columnas y se lee como dos entradas.
*/
.columnas-enlaces {
  columns: 15rem auto; column-gap: 1.6rem;
  margin: .6rem 0 0; padding: 0; list-style: none;
}
.columnas-enlaces li { break-inside: avoid; margin: 0 0 .3rem; line-height: 1.45; }
.columnas-enlaces .matiz { font-size: .82rem; }

/* El mismo aviso, repetido donde se toma la decisión: una línea, no una caja,
   para que no compita con la advertencia grande de arriba. */
.aviso-linea {
  margin: .6rem 0 0; padding: .55rem .8rem; font-size: .92rem;
  /* El mismo color que `.aviso.cautela`, que es la caja grande de arriba: es
     el mismo aviso y tiene que reconocerse como tal. */
  border-left: 3px solid var(--pronto); background: var(--pronto-tenue);
  border-radius: 0 var(--radio-sm) var(--radio-sm) 0;
}

.filtros-cabeza { margin-bottom: 0; }
.filtros-mas { margin-top: .7rem; }
.filtros-mas > summary {
  cursor: pointer; font-size: .88rem; font-weight: 700; color: var(--tinta-suave);
  padding: .35rem 0; list-style-position: inside; user-select: none;
}
.filtros-mas > summary:hover { color: var(--marca); }
.filtros-mas > summary:focus-visible { outline: 2px solid var(--marca); outline-offset: 3px; border-radius: var(--radio-sm); }
.filtros-mas[open] > summary { margin-bottom: .5rem; }
.filtros-mas .cuantos {
  font-weight: 700; font-size: .76rem; color: var(--marca);
  background: var(--marca-tenue); padding: .1rem .45rem; border-radius: 999px;
}

/*
  ⚠ SE PLIEGA IGUAL EN ESCRITORIO, Y ES UNA DECISIÓN.

  El primer intento escondía el `<summary>` a partir de 721 px y forzaba el
  contenido con `display: flex`. **No funciona**: un `<details>` cerrado no
  oculta a sus hijos con `display`, sino el bloque de contenido entero, así
  que en escritorio no salía ningún filtro y el CSS decía que sí. Se veía
  mirando la página, no leyendo la regla.

  Se puede rodear con `::details-content`, pero es de hace cuatro versiones de
  Chrome y dejaría fuera a cualquiera con un navegador de empresa. Y mirando
  qué es mejor para quien usa esto: en escritorio los ocho selectores también
  eran ruido delante de los resultados. Un solo comportamiento en los dos
  anchos —lo que se busca arriba, lo que se afina detrás de «Más filtros»— es
  más simple de entender y de mantener.
*/
@media (min-width: 721px) {
  .filtros-mas { margin-top: .55rem; }
}

.resumen-busqueda { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin-bottom: .9rem; }
.resumen-busqueda .cuenta { font-size: 1.02rem; }
.resumen-busqueda .cuenta b { font-size: 1.25rem; font-weight: 800; font-variant-numeric: tabular-nums; }

/* ── Paginación ───────────────────────────────────────────────────────── */

.paginacion { display: flex; gap: .4rem; align-items: center; justify-content: center; margin-top: 1.8rem; flex-wrap: wrap; }
.paginacion a, .paginacion span {
  min-width: 2.4rem; text-align: center; padding: .45rem .7rem;
  border: 1px solid var(--borde); border-radius: var(--radio-sm);
  background: var(--lienzo); color: var(--tinta-suave); text-decoration: none; font-weight: 600; font-size: .9rem;
}
.paginacion a:hover { border-color: var(--marca); color: var(--marca); }
.paginacion .actual { background: var(--marca); border-color: var(--marca); color: #fff; }
@media (prefers-color-scheme: dark) { .paginacion .actual { color: #10131c; } }
.paginacion .puntos { border: 0; background: none; }

/* ── Ficha ────────────────────────────────────────────────────────────── */

.migas { font-size: .86rem; color: var(--tinta-tenue); margin: 1.2rem 0 .8rem; display: flex; flex-wrap: wrap; gap: .35rem; }
.migas a { color: var(--tinta-suave); text-decoration: none; }
.migas a:hover { color: var(--marca); text-decoration: underline; }
.migas span[aria-hidden] { color: var(--borde-fuerte); }

.ficha-cabecera { padding-bottom: 1.4rem; border-bottom: 1px solid var(--borde); margin-bottom: 1.6rem; }
.ficha-cabecera h1 { font-size: clamp(1.55rem, 3.6vw, 2.3rem); margin-bottom: .45rem; }
.ficha-cabecera .subtitulo { color: var(--tinta-suave); font-size: 1.02rem; margin-bottom: .9rem; }

/*
  El plazo y la venta van PRIMERO en el documento (móvil y lector de pantalla
  los leen antes que el temario) y el escritorio los coloca en la columna
  derecha con grid-area —la técnica del fallo 74: la colocación no depende del
  orden del HTML—. A una columna no hay áreas y manda el orden natural.
*/
.ficha-cuerpo {
  display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 0 2rem; align-items: start;
  grid-template-areas: 'principal lado' 'principal resto' 'principal .';
  grid-template-rows: auto auto 1fr;
}
.ficha-lado-alto { grid-area: lado; min-width: 0; }
.ficha-principal { grid-area: principal; min-width: 0; }
.ficha-cuerpo aside { grid-area: resto; min-width: 0; }
@media (max-width: 900px) {
  .ficha-cuerpo { grid-template-columns: 1fr; grid-template-areas: none; grid-template-rows: none; }
  .ficha-lado-alto, .ficha-principal, .ficha-cuerpo aside { grid-area: auto; }
}

.panel {
  background: var(--lienzo); border: 1px solid var(--borde); border-radius: var(--radio);
  padding: 1.2rem 1.3rem; box-shadow: var(--sombra); margin-bottom: 1.1rem;
}
.panel h2, .panel h3 { font-size: .82rem; text-transform: uppercase; letter-spacing: .05em; color: var(--tinta-suave); margin-bottom: .8rem; }

/*
  EL RETRATO DE UN ORGANISMO. Dos columnas en escritorio y una en móvil, con
  los paneles repartidos por altura: son de tamaños muy distintos —el de los
  años tiene tres filas y el de los vecinos ocho— y en una sola columna la
  página se hacía larguísima antes de llegar al histórico, que es lo que la
  gente viene a ver. `masonry` no está en todos los navegadores, así que se
  hace con columnas CSS, que degradan solas.
*/
.retrato { margin: 1.6rem 0 .5rem; }
.retrato .panel { break-inside: avoid; margin-bottom: 1rem; }
.retrato .panel .matiz { font-size: .8rem; color: var(--tinta-tenue); margin-top: .7rem; line-height: 1.5; }
.retrato .panel.acento { border-color: color-mix(in srgb, var(--acento) 35%, var(--borde)); }
.retrato .tabla { margin: 0; }
@media (min-width: 820px) { .retrato { columns: 2; column-gap: 1rem; } }

.panel.plazo { border-width: 1.5px; }
.panel.plazo.abierto { border-color: color-mix(in srgb, var(--abierto) 40%, var(--borde)); }
.panel.plazo.pronto  { border-color: color-mix(in srgb, var(--pronto) 45%, var(--borde)); background: var(--pronto-tenue); }
.panel.plazo.urgente { border-color: color-mix(in srgb, var(--urgente) 50%, var(--borde)); background: var(--urgente-tenue); }
.panel.plazo .dias { font-size: 2.5rem; font-weight: 800; letter-spacing: -.045em; line-height: 1; font-variant-numeric: tabular-nums; }
.panel.plazo .dias small { font-size: .95rem; font-weight: 600; letter-spacing: 0; }
.panel.plazo .fecha { font-size: .95rem; color: var(--tinta-suave); margin-top: .35rem; }
.panel.plazo .matiz { font-size: .8rem; color: var(--tinta-tenue); margin-top: .7rem; line-height: 1.5; }

.datos { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: .95rem 1.3rem; }
.dato .etiqueta { font-size: .76rem; text-transform: uppercase; letter-spacing: .045em; color: var(--tinta-tenue); font-weight: 700; }
.dato .valor { font-size: 1rem; font-weight: 650; color: var(--tinta); }
.dato .valor.grande { font-size: 1.5rem; font-weight: 800; letter-spacing: -.03em; font-variant-numeric: tabular-nums; }
.dato .valor.ausente { color: var(--tinta-tenue); font-weight: 500; font-style: italic; }

/* Línea de tiempo del expediente */
.linea { list-style: none; margin: 0; padding: 0; position: relative; }
.linea::before { content: ""; position: absolute; left: 7px; top: .55rem; bottom: .55rem; width: 2px; background: var(--borde); }
.linea li { position: relative; padding: 0 0 1rem 2rem; }
.linea li::before {
  content: ""; position: absolute; left: 2px; top: .48rem; width: 12px; height: 12px;
  border-radius: 50%; background: var(--lienzo); border: 2px solid var(--borde-fuerte);
}
.linea li.aqui::before { background: var(--marca); border-color: var(--marca); box-shadow: 0 0 0 4px var(--marca-tenue); }
.linea li.fin::before { background: var(--abierto); border-color: var(--abierto); }
.linea .cuando { font-size: .78rem; color: var(--tinta-tenue); font-variant-numeric: tabular-nums; }
.linea .que { font-weight: 650; font-size: .95rem; }
.linea a { text-decoration: none; }
.linea a:hover { text-decoration: underline; }

/* ── Tablas ───────────────────────────────────────────────────────────── */

.tabla-envoltorio { overflow-x: auto; border: 1px solid var(--borde); border-radius: var(--radio); background: var(--lienzo); box-shadow: var(--sombra); }
table { width: 100%; border-collapse: collapse; font-size: .92rem; }
thead th {
  text-align: left; font-size: .76rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--tinta-suave); font-weight: 700; padding: .75rem 1rem;
  border-bottom: 1px solid var(--borde); background: var(--lienzo-2); white-space: nowrap;
}
tbody td { padding: .72rem 1rem; border-bottom: 1px solid var(--borde); vertical-align: middle; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: var(--lienzo-2); }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
td a { text-decoration: none; font-weight: 650; }
td a:hover { text-decoration: underline; }

/* Barras dentro de tabla, sin JavaScript ni imágenes */
.barra { display: block; height: 7px; border-radius: 999px; background: var(--marca); min-width: 3px; }
.barra-fondo { display: block; background: var(--lienzo-2); border-radius: 999px; width: 100%; min-width: 70px; }

/* ── Prosa ────────────────────────────────────────────────────────────── */

/*
  ═══════════════════════════════════════════════════════════════════════════
  UNA COLUMNA DE LECTURA SE ESTRECHA, PERO NO SE MUEVE DE SITIO
  ═══════════════════════════════════════════════════════════════════════════

  `.prosa` limita el renglón a 72 caracteres, que es lo correcto para leer. El
  problema era que además quedaba CENTRADA dentro del contenedor: el título de
  la guía empezaba en x=632 y el de cualquier otra página en x=383. Al navegar
  de /materias a /guia la página entera daba un salto de 250 píxeles.

  Estrecho está bien; descolocado, no. Se alinea con el resto del sitio, así
  que el título, el menú y el contenido caen siempre sobre la misma vertical.

  ⚠ Y ojo con `margin-inline: auto`: lo hereda de `.contenedor`, así que aquí
  hay que anularlo a mano. Poner solo el `max-width` no basta.
*/
/*
  ═══════════════════════════════════════════════════════════════════════════
  EL ANCHO DE RENGLÓN, QUE ES LA MITAD DE QUE UN TEXTO SE LEA
  ═══════════════════════════════════════════════════════════════════════════

  `.prosa` estaba acotada a 72ch desde el principio, y por eso los módulos se leen:
  medidos a 1.440 px dan **620-640 px de ancho y una mediana de 73 caracteres por
  renglón**, con ninguno por encima de 80. Eso es tipografía de libro.

  ⚠ Y `.matiz` —el párrafo de explicación secundaria, **53 usos en las vistas**— NO TENÍA
  REGLA BASE. Solo tres reglas contextuales (`.panel.plazo .matiz`, `.indice-modulo
  .matiz`, `.curso-avance .matiz`), así que fuera de esos tres sitios se quedaba con el
  ancho del contenedor. Medido a 1.440 px en las páginas del área de estudio:

      /estudio                        1.140 px de ancho · hasta 147 caracteres por renglón
      /estudio/oficio/administrativo  1.140 px de ancho · hasta 139
      .matiz-linea de /estudio        1.096 px de ancho · **168**

  El máximo legible está en 75-80 y el cómodo en 66. **168 es más del doble**, y pasaba
  justo en las páginas de entrada del producto que se cobra.

  Es el fallo 18 con otra cara: la prueba de estilos exige que toda clase usada tenga
  **alguna** regla, y `.matiz` la tenía —en tres contextos—, así que daba verde. Tener una
  regla en algún sitio no es tener una regla donde se usa.

  ⚠ Lo que aquí se arregla es SOLO el ancho y el interlineado, que es lo medido. El color
  y la talla se dejan como están: son 53 sitios y no puedo comprobarlos de un vistazo, y
  las tres reglas contextuales ya los fijan donde hacía falta. Cambiar 53 apariencias a
  ciegas para arreglar un ancho de renglón sería justo lo contrario de medir antes de tocar.
*/
/*
  ═══════════════════════════════════════════════════════════════════════════
  ⚠ `ch` NO SON CARACTERES: 72ch daban 84 CARACTERES POR RENGLÓN
  ═══════════════════════════════════════════════════════════════════════════

  La unidad `ch` es el ancho del glifo «0», y en una fuente proporcional el carácter medio
  es más estrecho que el cero. Así que un `max-width: 72ch` no da 72 caracteres: da **84**.
  Por eso los módulos, que parecían acotados a 72, tenían párrafos de 80 y la guía de 84.

  Medido en el módulo de derechos fundamentales a 1.440 px, párrafo a párrafo:

      ch    ancho    mediana   p90   máx   pasan de 75   alto total
      72    640 px      73      78    80        9          10.741
      70    623         71      77    80        7          10.843
      68    605         70      77    80        6          10.968
      66    587         68      75    78        3          11.201   ← elegido
      64    569         64      73    76        1          11.542
      62    551         60      67    72        0          11.805

  Se elige **66ch**: deja la mediana en 68 —el óptimo clásico son 66— y el percentil 90
  exactamente en 75, que es el techo de la banda cómoda (45-75). Cuesta **460 px más de
  alto, un 4,3 %**, y ese es el precio que se paga a cambio.

  No se baja a 62ch, que sería el único valor con CERO párrafos por encima de 75: costaría
  un 10 % más de scroll para ganar tres párrafos, y a 60 caracteres de mediana el texto
  empieza a saltar de línea demasiado y se lee peor, no mejor.

  ⚠ La lección de método: **el número que hay que mirar es el carácter medido, no la
  unidad de la hoja de estilos**. Fijar «72ch» y creer que son 72 caracteres es el mismo
  error que dar por bueno un dato sin comprobarlo.
*/
.prosa { max-width: 66ch; margin-inline: 0; }
.matiz { max-width: 62ch; line-height: 1.62; }
/* Y dentro de un panel, lo mismo para el párrafo sin clase: 1.096 px daban 115. */
.panel > p { max-width: 62ch; }
/*
  `.matiz-linea` es una ENUMERACIÓN separada por «·» —«Servicios sociales (108) ·
  Espectáculos públicos…»—, no prosa corrida: cortarla a 68ch la haría cuatro veces más
  alta sin que se lea mejor, porque el ojo salta de punto a punto y no sigue el renglón.
  Se acota a 90ch, que a 0,86rem son ~700 px: sigue siendo una lista y ya no un renglón de
  168 caracteres.
*/
.matiz-linea { max-width: 90ch; }
.prosa h2 { margin-top: 2.2rem; }
.prosa h3 { margin-top: 1.7rem; }
.prosa ul, .prosa ol { padding-left: 1.3rem; margin: 0 0 1.1em; }
.prosa li { margin-bottom: .42em; }
.prosa blockquote {
  margin: 1.3em 0; padding: .85em 1.2em; border-left: 3px solid var(--marca);
  background: var(--lienzo); border-radius: 0 var(--radio-sm) var(--radio-sm) 0; color: var(--tinta-suave);
}
.prosa code { font-family: var(--mono); font-size: .88em; background: var(--lienzo-2); padding: .12em .38em; border-radius: 4px; }

/*
  ═══ EL ÍNDICE DE UN MÓDULO ═══

  Un módulo de los grandes mide 16.497 px a 360 px: 25,8 pantallas seguidas sin
  saber dónde estás. Esto es lo que las convierte en un documento.

  Plegado a propósito. La cifra va en el resumen —«9 secciones · 12 min»—, así que
  cerrado ya informa de lo único que hace falta antes de empezar: cuánto pesa. Y
  así no se come 250 px de la primera pantalla delante de la primera línea.

  ⚠ `scroll-margin-top` en los títulos de la prosa NO es un adorno. La cabecera es
  `sticky` y mide **97 px a 360 px** y **63 px en escritorio**: sin esto, pulsar una
  entrada del índice deja el título DEBAJO de la cabecera y parece que el enlace ha
  ido a otro sitio. Es el enlace roto que no da ningún error.

  El valor está medido, no elegido: con 6,5rem (104 px) el título aterrizaba a 104 y
  quedaban **41 px libres en escritorio pero solo 7 en móvil**, que es donde más se
  usa. Con 7,5rem (120 px) quedan 57 y 23. Comprobado saltando a tres secciones
  distintas y midiendo la distancia entre el título y el borde de abajo de la
  cabecera.
*/
.indice-modulo {
  margin: 1.4rem 0 2rem; padding: 0; border: 1px solid var(--borde);
  border-radius: var(--radio-sm); background: var(--lienzo); max-width: 72ch;
}
.indice-modulo > summary {
  cursor: pointer; padding: .8rem 1rem; display: flex; flex-wrap: wrap;
  gap: .2rem .7rem; align-items: baseline; list-style-position: inside;
}
.indice-modulo > summary:hover { background: var(--lienzo-2); }
.indice-que { font-weight: 700; font-size: .95rem; }
.indice-cifras { color: var(--tinta-suave); font-size: .86rem; }
.indice-lista { margin: 0; padding: 0 1rem .4rem 2.4rem; }
.indice-lista li { margin-bottom: .45em; line-height: 1.4; }
.indice-lista a { text-decoration: none; border-bottom: 1px solid transparent; }
.indice-lista a:hover, .indice-lista a:focus-visible { border-bottom-color: currentColor; }
.indice-modulo .matiz { padding: 0 1rem .9rem; margin: 0; }
.prosa h2[id], .prosa h3[id] { scroll-margin-top: 7.5rem; }

/*
  El cuadro de motores del panel. El color va en la FILA y además el estado se
  escribe con palabra e icono: un panel que solo distingue por color no lo puede
  leer quien no distingue el rojo del verde, que es entre el 4 y el 8 % de los
  hombres. Y el icono no sustituye a la palabra: «⚠» solo, sin «atrasado» al lado,
  obliga a recordar una leyenda.
*/
.motor-bien td:nth-child(2) { color: var(--abierto); font-weight: 700; }
.motor-mal { background: color-mix(in srgb, var(--cerrado) 8%, transparent); }
.motor-mal td:nth-child(2) { color: var(--cerrado); font-weight: 700; }
.motor-duda { background: color-mix(in srgb, var(--tinta-tenue) 10%, transparent); }
.motor-duda td:nth-child(2) { font-weight: 700; }
.motor-nuevo td:nth-child(2) { color: var(--tinta-suave); }

.aviso {
  display: flex; gap: .8rem; align-items: flex-start;
  background: var(--marca-tenue); border: 1px solid var(--marca-borde);
  border-radius: var(--radio); padding: .95rem 1.15rem; font-size: .92rem; color: var(--tinta-suave);
  margin: 1.2rem 0;
}
.aviso strong { color: var(--tinta); }
.aviso.cautela { background: var(--pronto-tenue); border-color: color-mix(in srgb, var(--pronto) 30%, transparent); }

.vacio { text-align: center; padding: 3.5rem 1.5rem; color: var(--tinta-suave); }
.vacio h3 { color: var(--tinta); }

/* ── Pie ──────────────────────────────────────────────────────────────── */

.pie { border-top: 1px solid var(--borde); background: var(--lienzo); margin-top: 3rem; padding: 2.6rem 0 2rem; font-size: .91rem; }
.pie-rejilla { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 1.8rem; margin-bottom: 2rem; }
/* Son h2 por jerarquía —ver `vistas.js`— y se pintan como rótulos pequeños. */
.pie h2 { font-size: .78rem; text-transform: uppercase; letter-spacing: .05em; color: var(--tinta-tenue); margin-bottom: .7rem; font-weight: 700; }
.pie ul { list-style: none; margin: 0; padding: 0; }
.pie li { margin-bottom: .38rem; }
.pie a { color: var(--tinta-suave); text-decoration: none; }
.pie a:hover { color: var(--marca); text-decoration: underline; }
.pie-legal { border-top: 1px solid var(--borde); padding-top: 1.4rem; color: var(--tinta-tenue); font-size: .85rem; display: flex; flex-wrap: wrap; gap: .6rem 1.4rem; justify-content: space-between; }

/* ── Zonas táctiles ───────────────────────────────────────────────────── */

/*
  Medido sobre la página real: los enlaces del pie y los «ver todo →» tenían
  entre 20 y 24 píxeles de alto. Con el dedo eso es un intento y medio, y quien
  falla vuelve atrás y lo intenta otra vez, si no se va.
*/
@media (hover: none), (max-width: 720px) {
  .pie li { margin-bottom: 0; }
  .pie a, .seccion-cab .enlace-mas, .migas a {
    display: inline-block; min-height: 44px; line-height: 44px;
  }
  .sugerencias a { padding-block: .5rem; }
  .nav a { padding-block: .6rem; }
}

/* ── Detalles de accesibilidad y movimiento ───────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; scroll-behavior: auto !important; }
  a.tarjeta:hover, .familia:hover { transform: none; }
}

@media print {
  .cabecera, .pie, .nav, .filtros, .paginacion { display: none; }
  body { background: #fff; color: #000; font-size: 11pt; }
  .panel, .tarjeta, .fila { border: 1px solid #ccc; box-shadow: none; }
}

/* ── El desglose de puestos de una convocatoria con varios oficios ──────────
   Con scroll propio: hay convocatorias de 45 puestos y cuatro columnas no
   caben en 390 px. El que se desborda es el contenedor de la tabla, nunca la
   página. */
.tabla-ancha{overflow-x:auto}
.puestos{width:100%;border-collapse:collapse;font-size:.92rem}
.puestos thead th{text-align:left;font-size:.74rem;letter-spacing:.05em;text-transform:uppercase;
  color:var(--tinta-suave);font-weight:600;padding:.4rem .7rem .4rem 0;border-bottom:1px solid var(--borde-fuerte);white-space:nowrap}
.puestos td{padding:.55rem .7rem .55rem 0;border-bottom:1px solid var(--borde);vertical-align:top}
.puestos tbody tr:last-child td{border-bottom:0}
.puestos td.n{font-variant-numeric:tabular-nums;font-weight:700;white-space:nowrap}
.puestos .sub{display:block;color:var(--tinta-suave);font-size:.82rem;font-weight:400}

/* ── El temario ─────────────────────────────────────────────────────────────
   Una lista larga —hay convocatorias de 90 temas— que tiene que leerse de un
   tirón en el móvil. Número fuera del texto para que el enunciado quede en un
   bloque limpio y se pueda seguir con el dedo. */
.temas{list-style:none;margin:0 0 1.2rem;padding:0;counter-reset:none}
.temas li{display:flex;gap:.9rem;padding:.62rem 0;border-bottom:1px solid var(--borde);font-size:.94rem;line-height:1.5}
.temas li:last-child{border-bottom:0}
.temas .num{flex:0 0 2.1rem;font-variant-numeric:tabular-nums;font-weight:700;color:var(--tinta-suave);text-align:right}
.temas .enunciado{flex:1 1 auto;min-width:0}
h3.bloque-temas{font-size:.78rem;letter-spacing:.06em;text-transform:uppercase;color:var(--tinta-suave);
  margin:1.3rem 0 .5rem;padding-bottom:.35rem;border-bottom:1px solid var(--borde-fuerte)}
h3.bloque-temas:first-of-type{margin-top:0}
/*
   Las materias de un tema. Debajo del enunciado y en pequeño: el tema es lo que
   se lee, la materia es por dónde se sigue. Si pesaran igual que el enunciado,
   una lista de noventa temas sería ilegible.
*/
.temas-materias{display:block;margin-top:.3rem;line-height:1.9}
.temas-materias a{display:inline-block;margin:0 .35rem .15rem 0;padding:.08rem .5rem;
  font-size:.72rem;border:1px solid var(--borde);border-radius:999px;
  color:var(--tinta-suave);text-decoration:none}
.temas-materias a:hover{color:var(--tinta);border-color:var(--tinta-suave);text-decoration:none}
/*
   El reparto de materias de un oficio. Se lee de arriba abajo y lo que importa
   es el porcentaje, así que va alineado a la derecha y con cifras tabulares:
   con anchos distintos por dígito la columna baila y no se puede comparar de un
   vistazo, que es justo para lo que está.
*/
ul.reparto{list-style:none;margin:0 0 .8rem;padding:0}
/*
  ⚠ `flex-wrap` y `min-width:0`, y los dos hacen falta.

  Sin envolver, una fila con nombre largo y una cola larga a la derecha —«faltan
  Régimen Jurídico del Sector Público (Ley 40/2015)», en el panel de
  administración— empujaba la página a 459 px de ancho en un móvil de 360. La
  página entera se arrastraba de lado por una sola fila.

  `min-width: 0` en el elemento flexible es lo que de verdad lo arregla: un hijo
  de flex no encoge por debajo del ancho de su contenido salvo que se le diga, y
  `white-space: nowrap` en la cifra remataba el asunto. Es el mismo detalle que
  hizo falta en la barra del menú.
*/
ul.reparto li{display:flex;flex-wrap:wrap;align-items:baseline;gap:.2rem .8rem;padding:.45rem 0;
  border-bottom:1px solid var(--borde);font-size:.94rem}
ul.reparto li > *{min-width:0}
ul.reparto .cuantas small{white-space:normal}
ul.reparto li:last-child{border-bottom:0}
ul.reparto li a{flex:1 1 auto;min-width:0}
/*
  `0 1 auto`, no `0 0 auto`: el segundo prohíbe encoger, y por eso ni
  `flex-wrap` ni `min-width: 0` arreglaban nada. Medido en /admin a 360 px: la
  cola «55 % · 42 temarios · faltan Urbanismo y ordenación del territorio» medía
  361 px dentro de un hueco de 305 y empujaba la página entera a 388.
*/
ul.reparto .cuantas{flex:0 1 auto;min-width:0;font-variant-numeric:tabular-nums;font-weight:700}
ul.reparto .cuantas small{font-weight:400;color:var(--tinta-suave)}
/*
  ⚠ EL SELLO IBA A 12,5 px. «texto consolidado a diciembre de 2015» es la frase que
  distingue a este sitio de todo lo que se vende por ahí —casi nadie enseña de cuándo es el
  texto que estudias—, y estaba escrita en la letra más pequeña de la pantalla. Si es el
  argumento, se tiene que poder leer: 0,85rem = 13,6 px.
*/
.cuantas small { font-size: .85rem; }

/* ═══════════════════════════════════════════════ ÁREA DE ESTUDIO ══ */
/*
   Tres decisiones, y las tres se tomaron MIRANDO la página, que es lo que no
   hice la primera vez:

   1. UNA PREGUNTA SE LEE EN COLUMNA ESTRECHA. Un enunciado de dos líneas
      repartido en 1.180 píxeles obliga a barrer la cabeza de lado a lado. El
      test va a 640, que es donde cae el renglón cómodo.
   2. LAS FILAS DE MATERIA NO SON FILAS DE LISTADO. En el listado de
      convocatorias el número de la derecha es el dato principal; aquí el dato
      es el progreso, y «0 de 1» en tamaño gigante en la otra punta de la
      pantalla no dice nada. Va una barra pegada al título.
   3. EL BOTÓN ES UNA OPCIÓN, NO UN BOTÓN. Sin JavaScript cada respuesta es un
      <button>, que trae de serie fondo, borde y fuente propios. Hay que
      devolverle el aspecto de algo que se elige.
*/

/*
   La columna de lectura del test: ancha para respirar, estrecha para leer.

   Centrada, y no por gusto: cuando la pantalla tiene 1.180 y la columna 660,
   dejarla pegada a la izquierda deja medio metro de vacío a la derecha y la
   pregunta parece un resto de otra página. Y con aire arriba, porque esto es
   una pantalla de concentración: lo primero que se ve tiene que ser la
   pregunta, no la cabecera.
*/
.estudio-columna { max-width: 660px; margin-inline: auto; padding-top: 1.2rem; }

.sello-fecha {
  display: flex; flex-wrap: wrap; gap: .3rem .8rem; align-items: baseline;
  margin: 0 0 1.5rem; padding: .6rem .85rem;
  background: var(--lienzo); border: 1px solid var(--borde);
  border-left: 3px solid var(--abierto); border-radius: var(--radio-sm);
  font-size: .84rem;
}
.sello-marca { font-weight: 700; }
.sello-detalle { color: var(--tinta-suave); }
.sello-aviso { color: var(--urgente); font-weight: 700; }

/* ── Panel del alumno ─────────────────────────────────────────────────── */

.estudio-resumen { display: flex; flex-wrap: wrap; gap: 1.6rem; margin: 0 0 1.1rem; }
.estudio-dato { display: flex; flex-direction: column; }
.estudio-dato b { font-size: 1.7rem; line-height: 1.1; font-variant-numeric: tabular-nums; }
.estudio-dato span { font-size: .8rem; color: var(--tinta-suave); }

/* ── Lista de materias ────────────────────────────────────────────────── */

.materias-estudio { display: grid; gap: .6rem; margin: 0; padding: 0; list-style: none; }
/* Dos columnas en escritorio: con una, 28 oficios y 51 materias hacían una
   página kilométrica de filas a todo lo ancho junto a párrafos con tope de
   lectura —el contraste era lo que se sentía como «texto cortado a media
   pantalla»—. A dos columnas cada tarjeta mide como un párrafo y la página
   pesa la mitad de alto. En móvil, una columna, que es donde se estudia. */
@media (min-width: 900px) { .materias-estudio { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/*
   ⚠ `flex` y no `block`, y por un motivo concreto: los saltos de línea de la
   plantilla entre un <span> y el siguiente crean cajas de texto anónimas que
   arrastran la altura de renglón del padre. Con `block` cada tarjeta se comía
   27 px de aire por debajo del último renglón. Un contenedor flex ignora los
   nodos de texto en blanco entre sus hijos, así que el problema desaparece de
   raíz en vez de taparse con un margen negativo.
*/
.materias-estudio a {
  display: flex; flex-direction: column; gap: .1rem;
  padding: .8rem 1rem; background: var(--lienzo);
  border: 1px solid var(--borde); border-radius: var(--radio-sm);
  text-decoration: none; color: inherit;
}
.materias-estudio a:hover { border-color: var(--borde-fuerte); }
.materias-estudio .mat-cabeza { display: flex; width: 100%; justify-content: space-between; align-items: baseline; gap: 1rem; }
.materias-estudio .mat-nombre { font-weight: 700; font-size: .98rem; }
.materias-estudio .mat-cuenta { font-size: .82rem; color: var(--tinta-suave); font-variant-numeric: tabular-nums; white-space: nowrap; }
/*
  ⚠ Estos 128 elementos llevan DATOS que el alumno lee —«90 temarios reales leídos · 48
  materias»—, no adorno. Medidos a 12,8 px eran la talla más usada de la página, y en un
  producto que se lee una hora seguida eso es demasiado pequeño para lo que dice. Suben a
  0,85rem = 13,6 px, comprobado a 360 px sin desbordar.
*/
.materias-estudio .mat-pie { display: flex; width: 100%; justify-content: space-between; gap: 1rem; margin-top: .3rem; font-size: .85rem; color: var(--tinta-suave); }
/*
   La barra de progreso: es lo que el alumno viene a ver.

   ⚠ El `display: block` no es opcional. Es un <span>, y a un elemento en línea
   no se le aplica la altura: la barra se quedaba en nada y el hueco lo marcaba
   la altura de renglón del padre —27 px de aire en cada tarjeta—. Se veía
   perfectamente en la página y no lo veía ninguna prueba.
*/
.barra-progreso {
  display: block; height: 5px; margin-top: .5rem;
  background: var(--lienzo-2); border-radius: 999px; overflow: hidden;
}
.barra-progreso i { display: block; height: 100%; background: var(--marca); border-radius: 999px; }

/* ── La pregunta ──────────────────────────────────────────────────────── */

.test-cabecera { display: flex; flex-wrap: wrap; gap: .5rem .85rem; align-items: center; margin-bottom: 1.1rem; font-size: .8rem; }
.test-paso { font-variant-numeric: tabular-nums; color: var(--tinta-suave); font-weight: 600; }
.test-materia { font-weight: 600; }
.test-razon { color: var(--tinta-tenue); }
.test-resultado {
  font-weight: 700; text-transform: uppercase; letter-spacing: .06em; font-size: .74rem;
  padding: .2rem .7rem; border-radius: 999px;
}
.test-resultado.ok { background: var(--abierto-tenue); color: var(--abierto); }
.test-resultado.ko { background: var(--urgente-tenue); color: var(--urgente); }

/*
   Acotado a h1: «enunciado» también es la clase del texto de un tema dentro de
   las listas de temario, y sin el h1 delante aquellas líneas pasaban a 1,28rem
   en negrita. Es el mismo choque de nombres que el de .pie, y por eso conviene
   mirar quién más usa una clase antes de darle estilo propio.
*/
h1.enunciado {
  font-size: 1.28rem; line-height: 1.45; margin: .2rem 0 1.5rem;
  font-weight: 600; letter-spacing: -.015em;
}

ul.opciones { list-style: none; margin: 0 0 1.2rem; padding: 0; display: grid; gap: .5rem; }
ul.opciones li { margin: 0; }
ul.opciones .opcion,
ul.opciones.resuelto li {
  display: flex; width: 100%; gap: .8rem; align-items: flex-start; text-align: left;
  padding: .8rem .95rem; background: var(--lienzo);
  border: 1px solid var(--borde); border-radius: var(--radio-sm);
  font: inherit; font-size: .97rem; line-height: 1.45; color: inherit;
}
ul.opciones .opcion { cursor: pointer; }
ul.opciones .opcion:hover { border-color: var(--marca); background: var(--marca-tenue); }
ul.opciones .letra {
  flex: 0 0 1.55rem; height: 1.55rem; display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--borde-fuerte); border-radius: 50%;
  font-size: .76rem; font-weight: 700; color: var(--tinta-suave);
}
/* El color NUNCA es la única señal: el borde y el símbolo también lo dicen. */
ul.opciones.resuelto li.buena { border: 2px solid var(--abierto); background: var(--abierto-tenue); }
ul.opciones.resuelto li.buena .letra { border-color: var(--abierto); color: var(--abierto); }
ul.opciones.resuelto li.buena .letra::after { content: "✓"; margin-left: .12rem; }
ul.opciones.resuelto li.mala { border: 2px solid var(--urgente); background: var(--urgente-tenue); }
ul.opciones.resuelto li.mala .letra { border-color: var(--urgente); color: var(--urgente); }
ul.opciones.resuelto li.mala .letra::after { content: "✗"; margin-left: .12rem; }

.test-repaso { font-size: .88rem; color: var(--tinta-suave); margin: 1rem 0 1.3rem; }
.matiz-linea { color: var(--tinta-suave); font-size: .86rem; }

/* ── El reparto del simulacro ─────────────────────────────────────────── */

.simulacro-cobertura { font-variant-numeric: tabular-nums; }

/* ── Oficio: la cobertura, la etiqueta de libre y las dos columnas ────── */
/*
   La cifra de cobertura es el dato de la página, así que va en grande y con la
   barra debajo. No lleva color propio: en una pantalla al sol el verde y el
   gris se parecen, y además el número ya dice lo que hay que saber.
*/
.cobertura-grande { display: flex; flex-direction: column; gap: .5rem; margin: .2rem 0 .9rem; }
.cobertura-cifra { font-size: 2.4rem; font-weight: 800; line-height: 1; font-variant-numeric: tabular-nums; }
.cobertura-grande .barra-progreso { height: 8px; }
/*
  El pie de la cifra grande. Va debajo y no dentro del `<details>` a propósito: dice
  cuántas preguntas hay y qué mide el otro número, y eso no se pliega. Lo que se
  pliega es CÓMO se calculan, no cuánto hay.
*/
/* ⚠ 62ch daban 83 caracteres por renglón: la unidad engaña, el carácter medido no. */
.cobertura-pie { font-size: .93rem; color: var(--tinta-suave); margin: -.4rem 0 .9rem; max-width: 52ch; line-height: 1.5; }
.cobertura-pie strong { color: var(--tinta); }

/*
  ═══ «DÓNDE SE EXPLICA ESTO», EN LA PANTALLA DE UNA PREGUNTA FALLADA ═══

  Se distingue del panel de la explicación con un borde de color en el canto: es una
  ACCIÓN, no más texto que leer, y el alumno tiene que verlo como una salida y no como
  otro párrafo. El botón es «suave» a propósito: el botón fuerte de esta pantalla es
  «Siguiente pregunta», y dos botones con el mismo peso obligan a elegir entre dos
  cosas que no compiten —seguir el test o ir a estudiar el punto que has fallado—.
*/
.donde-explica { border-left: 3px solid var(--marca); }
/* «¿Ves un error en esta pregunta?» (fallo 110): plegado y discreto, debajo de todo. */
.aviso-error { margin-top: 1.6rem; font-size: .9rem; color: var(--tinta-suave); }
.aviso-error summary { cursor: pointer; }
.aviso-error form { margin-top: .6rem; }
.boton-suave {
  display: inline-block; padding: .55rem .95rem; border-radius: var(--radio-sm);
  border: 1px solid var(--marca); color: var(--marca); background: transparent;
  font-weight: 650; text-decoration: none; line-height: 1.3;
}
.boton-suave:hover, .boton-suave:focus-visible { background: var(--lienzo-2); }

/*
   «libre» junto al nombre de una materia. Es la única marca de precio que hay
   en el área y va en positivo —se marca lo que se regala, no lo que se cobra—:
   una web sembrada de candados enseña el muro antes que el producto.
*/
.etiqueta-libre {
  display: inline-block; vertical-align: .06em; margin-left: .35rem;
  padding: .05rem .38rem; border-radius: 999px;
  background: var(--abierto-tenue); color: var(--abierto);
  border: 1px solid var(--abierto);
  /* 0,68rem eran 10,9 px, la talla más pequeña del sitio. En versal y con espaciado se
     lee, pero 10,9 es poco incluso para una etiqueta: 0,73rem = 11,7 px. */
  font-size: .73rem; font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
}

/* Una materia del reparto que todavía no tiene preguntas: se lista igual, sin
   enlace y en tono apagado. Ocultarla dejaría el reparto mintiendo. */
.sin-banco { flex: 1 1 auto; min-width: 0; color: var(--tinta-tenue); }

/*
   Dos paneles a la par —lo libre y lo de pago—. `auto-fit` con un mínimo real
   en `ch` para que caiga a una columna cuando el texto empiece a apretarse, y
   no a un ancho de pantalla elegido a ojo.
*/
.dos-columnas { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 30ch), 1fr)); gap: 1rem; align-items: start; }
.dos-columnas .panel { margin: 0; height: 100%; }

@media (max-width: 560px) {
  /* ⚠ `h1.enunciado`, no `.enunciado`: esta media query estaba sin acotar y le
     subía el cuerpo al texto de cada tema de un temario, que usa la misma
     clase. Es la colisión que está explicada cuarenta líneas más arriba, vuelta
     a colar en la regla de móvil. */
  h1.enunciado { font-size: 1.06rem; }
  .cobertura-cifra { font-size: 2rem; }
  ul.opciones .opcion, ul.opciones.resuelto li { padding: .7rem .8rem; gap: .65rem; }
  .estudio-resumen { gap: 1.1rem; }
  .estudio-dato b { font-size: 1.45rem; }

  /*
    ── LAS TABLAS DE COMPARACIÓN SE APILAN ──────────────────────────────

    Una tabla de datos con celdas cortas se desplaza de lado y se lee bien.
    Una tabla de COMPARACIÓN con prosa dentro, no: medido en el módulo de
    haciendas locales a 360 px, sus tres columnas ocupaban 528 px, el texto
    salía **a una palabra por renglón** —una celda de trescientos píxeles de
    alto— y la tercera columna quedaba fuera de la pantalla. Comparar tres
    cosas es justo para lo que existía esa tabla.

    Aquí cada fila pasa a ser un bloque: la primera celda lo encabeza y las
    demás dicen de qué columna vienen (`data-th`). Sin JavaScript y sin
    duplicar contenido. La cabecera se esconde para la vista pero sigue ahí
    para un lector de pantalla, que no necesita el apaño.

    ⚠ Solo `.comparativa`. Las tablas de /radiografia y /fuentes son de datos
    y con el desplazamiento lateral se leen mejor que apiladas.
  */
  table.comparativa thead {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip-path: inset(50%); white-space: nowrap;
  }
  table.comparativa, table.comparativa tbody, table.comparativa tr,
  table.comparativa th, table.comparativa td { display: block; width: auto; }
  table.comparativa tr {
    padding: .75rem 0; border-bottom: 1px solid var(--borde);
  }
  table.comparativa tr:last-child { border-bottom: 0; }
  table.comparativa th[scope="row"],
  table.comparativa tbody td:first-child {
    padding: 0 0 .35rem; border-bottom: 0;
    font-weight: 700; font-size: 1rem; line-height: 1.35;
  }
  table.comparativa td[data-th] {
    padding: .18rem 0 .18rem .9rem; border-bottom: 0;
    border-left: 2px solid var(--borde);
  }
  table.comparativa td[data-th]::before {
    content: attr(data-th); display: block;
    font-size: .74rem; text-transform: uppercase; letter-spacing: .05em;
    color: var(--tinta-suave); font-weight: 700;
  }
  /* Apilada ya no hay caja que desplazar: el marco sobra y el `overflow-x`
     dejaría una barra fantasma de un píxel. */
  .tabla-envoltorio:has(> table.comparativa) {
    overflow-x: visible; border: 0; box-shadow: none; background: none;
  }
}

/* ── Tronco común / de familia / específico ───────────────────────────── */
/*
   Tres bloques con su porcentaje al lado del título. El porcentaje va en el
   encabezado y no en una barra: aquí el dato no es un progreso —no hay nada
   que completar—, es el reparto de un temario, y una barra invitaría a leerlo
   como «llevas el 41 %».
*/
/*
   El bloque necesita peso propio: tres listas seguidas con un encabezado fino
   se leen como una sola lista larga y el agrupamiento —que es TODO el mensaje
   de esta sección— se pierde. Una línea vertical a la izquierda basta y no
   compite con la barra de cobertura de arriba.
*/
.nivel { margin: 1.4rem 0; padding-left: .9rem; border-left: 3px solid var(--borde); }
.nivel:first-of-type { border-left-color: var(--marca); }
.nivel-titulo {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  gap: .3rem 1rem; margin: 0 0 .2rem; font-size: 1.08rem;
}
.nivel-parte { font-size: .84rem; font-weight: 600; color: var(--tinta-suave); font-variant-numeric: tabular-nums; white-space: nowrap; }
.nivel-pie { font-size: .88rem; color: var(--tinta-suave); max-width: 68ch; margin: 0 0 .6rem; }

/* ═══════════════════════════════════════════ ACCESO Y PANELES ══ */
/*
   El enlace de acceso del menú. Va el último y con un borde suave para que se
   distinga de la navegación sin gritar: no es una sección de la web, es el
   estado de quien mira.
*/
.nav-acceso {
  border: 1px solid var(--borde-fuerte); border-radius: var(--radio-sm);
  margin-left: .35rem; white-space: nowrap;
}

/*
   La caja de acceso. Campos anchos y etiquetas encima: en un móvil, una
   etiqueta al lado deja al campo la mitad del renglón.
*/
.formulario-acceso { display: flex; flex-direction: column; gap: .3rem; max-width: 26rem; }
.formulario-acceso label { font-size: .88rem; font-weight: 650; margin-top: .5rem; }
.formulario-acceso input {
  font: inherit; padding: .6rem .7rem;
  border: 1px solid var(--borde-fuerte); border-radius: var(--radio-sm);
  background: var(--lienzo); color: var(--tinta);
}
.formulario-acceso .boton { margin-top: 1rem; align-self: flex-start; }

/*
   Las alertas del panel de administración.

   ⚠ El color NO es la única señal: cada línea lleva su símbolo delante. Quien
   no distingue el rojo del verde tiene que poder leer el estado igual, y este
   panel es justo donde alguien decide si hay que actuar.
*/
ul.alertas { list-style: none; margin: 0 0 .8rem; padding: 0; display: grid; gap: .45rem; }
ul.alertas li {
  padding: .6rem .8rem .6rem 2.1rem; border-radius: var(--radio-sm);
  font-size: .95rem; position: relative;
}
ul.alertas li::before { position: absolute; left: .75rem; font-weight: 700; }
.alerta-roja { background: var(--urgente-tenue); border: 1px solid var(--urgente); }
.alerta-roja::before { content: "✗"; color: var(--urgente); }
.alerta-verde { background: var(--abierto-tenue); border: 1px solid var(--abierto); }
.alerta-verde::before { content: "✓"; color: var(--abierto); }

/*
   Las cifras del panel. `auto-fit` con mínimo en `ch` para que caigan solas de
   cuatro a dos a una, sin elegir a ojo ningún ancho de pantalla.
*/
.cifras-admin {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 11ch), 1fr));
  gap: .7rem; margin: 1rem 0 1.4rem;
}
.cifras-admin .cifra {
  background: var(--lienzo); border: 1px solid var(--borde);
  border-radius: var(--radio-sm); padding: .7rem .8rem;
  display: flex; flex-direction: column; gap: .1rem;
}
.cifras-admin .cifra b { font-size: 1.5rem; line-height: 1.1; font-variant-numeric: tabular-nums; }
.cifras-admin .cifra span { font-size: .8rem; color: var(--tinta-suave); }

/*
   LA TIRA DE SECCIONES DEL PANEL.

   ⚠ No se desliza de lado. El menú público sí lo hace, y allí costó que a 360 px
   se viera el 32 % de la barra con ocho destinos fuera de la pantalla (fallo 32).
   Aquí son seis destinos cortos: con `flex-wrap` caen a dos líneas y **no se
   pierde ninguno**, que es lo único que importa en una navegación de la que
   depende llegar a los datos fiscales.

   La sección de dentro se marca con `aria-current="page"`, así que el estilo
   cuelga del atributo y no de una clase que haya que acordarse de poner.
*/
.nav-admin {
  display: flex; flex-wrap: wrap; gap: .4rem;
  margin: 0 0 1.5rem; padding-bottom: .9rem;
  border-bottom: 1px solid var(--borde);
}
.nav-admin a {
  text-decoration: none; font-size: .93rem; font-weight: 650;
  color: var(--tinta-suave); background: var(--lienzo);
  border: 1px solid var(--borde); border-radius: 999px;
  padding: .38rem .85rem; line-height: 1.35;
}
.nav-admin a:hover { color: var(--tinta); border-color: var(--marca-borde); }
.nav-admin a[aria-current="page"] {
  color: var(--lienzo); background: var(--tinta); border-color: var(--tinta);
}

/* El estado de cada sección en la rejilla del resumen: verde si no hay nada que
   hacer, rojo si sí. `.mal` ya existía más abajo; `.ok` no, y sin ella el «se
   puede cobrar» salía del mismo color que el «cerrado». */
.ok { color: var(--abierto); }

/*
   Órdenes para copiar y pegar, en el panel. Se desliza de lado dentro de su caja
   y NO empuja la página: una orden de shell no se puede partir por la mitad —una
   línea cortada pegada en un terminal hace otra cosa— así que aquí el scroll
   horizontal es lo correcto, al revés que en las tablas de los módulos.
*/
.bloque-codigo {
  background: var(--lienzo-2); border: 1px solid var(--borde);
  border-radius: var(--radio-sm); padding: .8rem .9rem;
  overflow-x: auto; margin: .6rem 0;
}
.bloque-codigo code {
  font-family: var(--mono); font-size: .82rem; line-height: 1.55;
  white-space: pre; color: var(--tinta);
}

/*
   Una página de lectura: columna estrecha para el renglón, pero alineada con
   el resto del sitio. La diferencia con `.estudio-columna` es el centrado, y
   no es un detalle: con `margin-inline:auto` el título salta 233 px al pasar
   de una página a otra, que es lo que se vio en /guia y luego en los módulos.
*/
.leyendo { max-width: 680px; margin-inline: 0; padding-top: 1.2rem; }

/* ═══════════════════════════════════════════ LA FRANJA DE VENTA ══ */
/*
   Va después de las convocatorias urgentes: es el momento en que alguien acaba
   de ver una plaza que le encaja. Fondo propio para que se lea como una parada
   y no como una sección más del archivo, pero sin colores de oferta: lo que
   convence aquí son las cifras, y una franja chillona las desmiente.
*/
/* El fondo y los dos bordes van en la capa a sangre: si se quedan aquí, se
   cortan a 1.140 px como se cortaba el del héroe. Ver `.a-sangre`. */
.franja-venta::before { background: var(--marca-tenue); border-block: 1px solid var(--marca-borde); }
.venta-cab { max-width: 62ch; margin-bottom: 1.4rem; }
.venta-cab h2 { margin-bottom: .4rem; }
.venta-cab .entradilla { font-size: 1.06rem; line-height: 1.6; color: var(--tinta-suave); margin: 0; }

.venta-pruebas {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 26ch), 1fr));
  gap: .9rem; margin-bottom: 1.4rem;
}
.venta-prueba {
  background: var(--lienzo); border: 1px solid var(--marca-borde);
  border-radius: var(--radio); padding: .9rem 1rem;
  display: flex; flex-direction: column; gap: .3rem;
}
.venta-prueba b { font-size: 1.35rem; line-height: 1.15; font-variant-numeric: tabular-nums; }
.venta-prueba span { font-size: .92rem; color: var(--tinta-suave); line-height: 1.5; }

.venta-accion { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem 1.1rem; }
/*
   El precio va JUNTO al botón y en el mismo tamaño que el texto normal. Ni
   escondido en letra pequeña ni gritado: quien está decidiendo necesita verlo
   sin buscarlo, y esconderlo es lo que hace que la gente desconfíe.
*/
/*
  ⚠ 101 CARACTERES EN UN SOLO RENGLÓN, Y ES LA LÍNEA DE LAS CONDICIONES.

  Medida en la portada a 1.440 px: «Sin permanencia, se cancela desde tu cuenta y
  el mes ya pagado no se pierde» salía en **una sola línea de 101 caracteres**,
  cuando el techo medido del sitio son 80 y la banda cómoda acaba en 75.

  Y es justo la línea que no puede costar leer: dice qué pasa si te das de baja.
  Se le pone su propio tope, como lo tienen `.prosa`, `.matiz` y `.panel > p`.

  Se coló porque la franja de venta se escribió después de la pasada de
  tipografía —el fallo 22: una decisión bien medida caduca cuando cambia lo que
  medía— y porque la prueba que vigila los anchos lleva una lista de clases
  escrita a mano, que es el fallo 18.
*/
.venta-precio { margin: 0; font-size: .98rem; color: var(--tinta-suave); max-width: 60ch; }
.venta-precio strong { color: var(--tinta); }
.boton.grande { font-size: 1.02rem; padding: .8rem 1.4rem; }

/* ═══════════════════════════════════════ EL CANAL DE WHATSAPP ══ */
/*
   Una tira, no una sección: va entre el héroe y las urgentes y no puede
   competir con ninguna de las dos. Paleta de la marca —no el verde de
   WhatsApp—, por lo mismo que la franja de venta no lleva colores de oferta.
   La sección que la envuelve recorta su padding: el de `.seccion` está pensado
   para bloques con cabecera, y aquí dejaría un vacío de dos dedos por lado.
*/
.canal-wa { padding-block: 0 .4rem; }
.canal-wa-tira {
  display: flex; align-items: center; gap: .9rem 1.1rem; flex-wrap: wrap;
  background: var(--marca-tenue); border: 1px solid var(--marca-borde);
  border-radius: var(--radio); padding: .9rem 1.2rem;
}
.canal-wa-tira .icono-venta { flex-shrink: 0; }
.canal-wa-texto { margin: 0; flex: 1 1 30ch; max-width: 66ch; font-size: .95rem; line-height: 1.5; color: var(--tinta-suave); }
.canal-wa-texto strong { color: var(--tinta); }

/* ══════════════════════════════════════════════ EL MURO ══ */
/*
   La etiqueta que dice de qué zona es esta página. Va ANTES del título: quien
   llega tiene que saber en un vistazo que está mirando algo de pago, sin leer
   un párrafo para descubrirlo.
*/
.etiqueta-pago {
  display: inline-block; margin-bottom: .5rem;
  padding: .18rem .55rem; border-radius: 999px;
  background: var(--marca-tenue); color: var(--marca); border: 1px solid var(--marca-borde);
  font-size: .74rem; font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
}

/*
   Las cifras de lo que se está perdiendo AQUÍ. Grandes, porque son el
   argumento: «41 temas tiene el temario que publicaron» convence más que
   cualquier frase que podamos escribir.
*/
.muro-cifras {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 14ch), 1fr));
  gap: .7rem; margin: 1.2rem 0;
}
.muro-cifra {
  background: var(--lienzo); border: 1px solid var(--borde);
  border-radius: var(--radio); padding: .8rem .9rem;
  display: flex; flex-direction: column; gap: .2rem;
}
.muro-cifra b { font-size: 1.7rem; line-height: 1.05; font-variant-numeric: tabular-nums; }
.muro-cifra span { font-size: .85rem; color: var(--tinta-suave); line-height: 1.45; }

/* El panel del precio: el único con borde de marca, para que sea el que se mira. */
.panel-venta { border-color: var(--marca-borde); background: var(--marca-tenue); }
.precio-grande { display: flex; flex-wrap: wrap; align-items: baseline; gap: .2rem .7rem; margin-bottom: .8rem; }
.precio-grande b { font-size: 2.1rem; line-height: 1; letter-spacing: -.02em; }
.precio-grande span { font-size: .9rem; color: var(--tinta-suave); }

/* ═════════════════════════════════════════════ LA RACHA ══ */
/*
   Discreta a propósito. Una racha que parpadea o que ocupa media pantalla se
   convierte en la razón de entrar, y aquí la razón de entrar es aprobar. Esto
   es un dato más, cierto y comprobable, no un juego.

   ⚠ Cuando está en peligro cambia el color Y el texto. El color solo no vale:
   quien no distingue el ámbar del gris se quedaría sin el aviso, que es
   justamente la única vez que la racha dice algo útil.
*/
.racha {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .2rem .8rem;
  padding: .6rem .9rem; margin: 0 0 1rem;
  background: var(--lienzo); border: 1px solid var(--borde);
  border-left: 4px solid var(--abierto); border-radius: var(--radio-sm);
}
.racha-dias { font-size: .95rem; }
.racha-dias b { font-size: 1.3rem; font-variant-numeric: tabular-nums; }
.racha-pie { font-size: .86rem; color: var(--tinta-suave); }
.racha.en-peligro { border-left-color: var(--pronto); background: var(--pronto-tenue); }

/* ═════════════════════════════════════ LA TABLA COMPARATIVA ══ */
/*
   Va en tabla y no en dos columnas de viñetas porque es una comparación: con
   dos listas hay que ir y venir para saber qué cambia de una a otra, que es
   justo lo que la persona ha venido a averiguar.

   `<th scope="row">` no es un capricho: con lector de pantalla, una celda que
   dice «Sí» sin saber de qué fila es no significa nada.
*/
table.comparativa { width: 100%; border-collapse: collapse; font-size: .95rem; }
table.comparativa th, table.comparativa td { padding: .6rem .7rem; text-align: left; border-bottom: 1px solid var(--borde); }
table.comparativa thead th { font-size: .8rem; text-transform: uppercase; letter-spacing: .04em; color: var(--tinta-suave); }
table.comparativa thead th:last-child { color: var(--marca); }
table.comparativa th[scope="row"] { font-weight: 600; }
table.comparativa tbody tr:last-child th, table.comparativa tbody tr:last-child td { border-bottom: 0; }
/* Ni el sí ni el no dependen del color: llevan su símbolo delante. */
table.comparativa .si { color: var(--abierto); font-weight: 700; }
table.comparativa .si::before { content: "✓ "; }
table.comparativa .no { color: var(--tinta-tenue); }
table.comparativa .no::before { content: "— "; }

/* Las casillas de consentimiento. El texto va al lado y hace de zona pulsable:
   una casilla de 13 px sin etiqueta asociada es imposible de marcar con el
   pulgar, y es justo la que decide si podemos escribirle a alguien. */
.formulario-acceso .casilla {
  display: flex; align-items: flex-start; gap: .55rem;
  margin-top: .7rem; font-weight: 400; font-size: .92rem; line-height: 1.45;
  cursor: pointer;
}
.formulario-acceso .casilla input { width: 1.1rem; height: 1.1rem; margin-top: .12rem; flex: none; }

/* ─────────────── LA TIRA DE DÍAS DEL ESTADO DE BOLETINES ───────────────
   Celdas de 10 px, una por día CON tanda. Los días sin tanda no se pintan:
   una ausencia no es un cero, y pintarla igual sería el verde falso que este
   panel viene a evitar. El color va con `title` para que se pueda leer sin
   depender del color, que es lo que exige el contraste y el lector de pantalla. */
.tira { display: inline-flex; gap: 2px; align-items: center; }
.tira i {
  width: 10px; height: 18px; border-radius: 2px; display: inline-block;
  background: var(--borde);
}
.tira i.dia-bien { background: #1a7f37; }
.tira i.dia-vacio { background: #bf8700; }
.tira i.dia-fallo { background: #b42318; }
/* El ámbar sigue la MISMA forma que las otras dos alertas —fondo, borde y un
   símbolo delante— porque si no, el tercer estado parecería de otra familia. Y el
   símbolo importa: distinguir tres estados solo por el color deja fuera a quien no
   los distingue. */
.alerta-ambar { background: #fff8e6; border: 1px solid #bf8700; }
.alerta-ambar::before { content: "!"; color: #bf8700; }
@media (prefers-color-scheme: dark) {
  .alerta-ambar { background: #2b2110; }
}
.mal { color: #b42318; }

/* ─────────────── MODO FOCO: LA PANTALLA DE ESTUDIO ───────────────
   La cabecera se queda en la marca y una salida; el pie, en el aviso legal.
   Está explicado en `pagina()` de vistas.js: debajo de la pregunta había 25
   líneas de menú, y esta es la única pantalla del sitio donde los destinos
   estorban en vez de ayudar. */
.cabecera-foco .cabecera-fila { justify-content: space-between; }
.salir-foco {
  font-size: .92rem; color: var(--tinta-suave); text-decoration: none;
  padding: .35rem .7rem; border: 1px solid var(--borde); border-radius: var(--radio-sm);
}
.salir-foco:hover, .salir-foco:focus-visible { color: var(--tinta); border-color: var(--tinta-suave); }
/* El pie en foco: sin rejilla de enlaces, solo la línea legal, y discreto. */
.pie-foco { margin-top: 2.5rem; }
.pie-foco .pie-legal { border-top: none; padding-top: .8rem; font-size: .82rem; opacity: .75; }

/* ─────────────── EL CIERRE DE LA PRUEBA: LA PANTALLA QUE VENDE ───────────────
   Es la única pantalla a la que alguien llega con las ganas puestas —acaba de
   contestar seis y quiere la séptima—, así que el precio y el botón van dentro
   de la primera pantalla, sin desplazar. Medido a 360 px. */
.cierre-prueba { text-align: left; }
.cierre-marca {
  font-size: .78rem; letter-spacing: .08em; text-transform: uppercase;
  color: var(--tinta-suave); margin: 0 0 .3rem;
}
.cierre-prueba h1 { font-size: clamp(1.4rem, 5vw, 1.9rem); margin: 0 0 .6rem; line-height: 1.2; }
.cierre-prueba .entradilla { font-size: 1rem; margin-bottom: 1.2rem; }

/*
  Las materias falladas. Sin rojo y sin icono de error: es el índice de lo que
  hay detrás, no una corrección. El borde lateral basta para separarlo del
  titular sin convertirlo en una alarma.
*/
.cierre-fallos {
  border-left: 3px solid var(--marca); padding: .1rem 0 .1rem .8rem;
  margin: 0 0 1.2rem;
}
.cierre-fallos-rotulo {
  font-size: .78rem; letter-spacing: .06em; text-transform: uppercase;
  color: var(--tinta-suave); margin: 0 0 .35rem;
}
.cierre-fallos ul { list-style: none; margin: 0; padding: 0; }
.cierre-fallos li { margin: 0 0 .2rem; line-height: 1.4; }
.cierre-fallos li a { font-weight: 600; }
.cierre-fallos li span { color: var(--tinta-suave); font-size: .92rem; }

.oferta {
  border: 2px solid var(--tinta); border-radius: var(--radio);
  padding: 1.1rem 1.1rem 1.3rem; background: var(--lienzo-2);
}
.oferta-precio { display: flex; flex-direction: column; margin-bottom: .9rem; }
.oferta-precio b { font-size: 2.1rem; line-height: 1; }
.oferta-precio span { font-size: .88rem; color: var(--tinta-suave); margin-top: .25rem; }
/*
  «Qué se compra», en la última pantalla antes de pagar. El icono va más pequeño
  que en la portada —28 px en vez de 40—: aquí son cinco seguidos y a tamaño de
  portada la lista se convierte en una fila de cuadrados con texto al lado.
*/
.compra-lista { list-style: none; padding: 0; margin: 0; }
.compra-lista li {
  display: flex; gap: .7rem; align-items: flex-start;
  margin-bottom: .75rem; line-height: 1.5;
}
.compra-lista li:last-child { margin-bottom: 0; }
.compra-lista .icono-venta { width: 28px; height: 28px; border-radius: 8px; margin: .1rem 0 0; }
.compra-lista .icono-venta svg { width: 16px; height: 16px; }

.oferta-lista { list-style: none; padding: 0; margin: 0 0 1.1rem; }
.oferta-lista li {
  position: relative; padding-left: 1.5rem; margin-bottom: .6rem;
  font-size: .96rem; line-height: 1.45;
}
/* La marca de verificación va en `::before` y no como carácter en el HTML: así no
   la lee el lector de pantalla cuatro veces seguidas sin aportar nada. */
.oferta-lista li::before {
  content: "✓"; position: absolute; left: 0; top: 0;
  color: var(--abierto); font-weight: 700;
}
.oferta .boton.grande { width: 100%; text-align: center; box-sizing: border-box; }
.oferta-pie { font-size: .86rem; color: var(--tinta-suave); margin: .8rem 0 0; }
.oferta-aviso {
  font-size: .95rem; margin: 0 0 .8rem; padding: .7rem .85rem;
  background: var(--fondo); border: 1px solid var(--borde); border-radius: var(--radio-sm);
}

/* ─────────────── EL CURSO: UNA SOLA COSA QUE HACER ───────────────
   Va arriba de la ficha de oficio, antes de la cobertura y del reparto del
   temario. El orden ES la decisión: quien ha pagado no viene a informarse,
   viene a estudiar. Está explicado en `camino.js`. */
.curso { margin: 1.4rem 0 2rem; }
.curso-ahora {
  border: 2px solid var(--tinta); border-radius: var(--radio);
  padding: 1.1rem 1.1rem 1.2rem; background: var(--lienzo-2);
}
.curso-rotulo {
  font-size: .76rem; letter-spacing: .08em; text-transform: uppercase;
  color: var(--tinta-suave); margin: 0 0 .35rem;
}
.curso-ahora h2 { font-size: clamp(1.25rem, 4.5vw, 1.6rem); margin: 0 0 .5rem; line-height: 1.25; }
.curso-porque { font-size: .95rem; margin: 0 0 1rem; color: var(--tinta-suave); max-width: 68ch; }
.curso-ahora .boton.grande { width: 100%; text-align: center; box-sizing: border-box; }
/* Los cuatro estados llevan color EN EL BORDE y no solo en el texto, y cada uno
   tiene además su rótulo escrito: distinguir «ha cambiado el BOE» de «toca
   repasar» solo por el color dejaría fuera a quien no los distingue. */
.curso-cambio { border-color: var(--urgente); }
.curso-repaso { border-color: var(--abierto); }
.curso-aldia { border-color: var(--borde); background: var(--fondo); }

.curso-avance { margin-top: 1rem; }
.curso-avance .barra-progreso { margin-bottom: .5rem; }
.curso-avance .matiz { margin: 0; }
.curso-detalle { margin-top: 1rem; }
.curso-detalle > summary { font-size: .95rem; cursor: pointer; }

ol.pasos { list-style: none; padding: 0; margin: .8rem 0 0; counter-reset: none; }
.paso {
  display: grid; grid-template-columns: 2rem 1fr auto; gap: .7rem;
  align-items: center; padding: .6rem 0; border-top: 1px solid var(--borde);
}
.paso-n {
  width: 1.9rem; height: 1.9rem; border-radius: 50%; display: grid; place-items: center;
  font-size: .82rem; font-weight: 700; background: var(--lienzo-2); color: var(--tinta-suave);
  border: 1px solid var(--borde);
}
.paso-ok .paso-n { background: var(--abierto); color: #fff; border-color: var(--abierto); }
.paso-marcha .paso-n { border-color: var(--tinta); color: var(--tinta); }
.paso-cuerpo { display: flex; flex-direction: column; min-width: 0; }
.paso-titulo { font-weight: 600; text-decoration: none; }
.paso-titulo:hover { text-decoration: underline; }
.paso-detalle { font-size: .84rem; color: var(--tinta-suave); }
.paso-estado {
  display: flex; flex-direction: column; align-items: flex-end; text-align: right;
  font-size: .82rem; color: var(--tinta-suave); white-space: nowrap;
}
/* 11,8 px para «87 % de tu temario», que es una cifra del progreso: sube a 12,8. */
.paso-estado small { font-size: .8rem; opacity: .9; }
.paso-ok .paso-estado { color: var(--abierto); font-weight: 600; }
/* A 360 px la columna del estado se lleva media fila: se baja debajo del título. */
@media (max-width: 30rem) {
  .paso { grid-template-columns: 1.9rem 1fr; }
  .paso-estado { grid-column: 2; align-items: flex-start; text-align: left; margin-top: .15rem; }
}

/* El cierre de una lección: el paso siguiente del curso, no un panel más.
   Se marca con el borde para que se distinga del panel de fuentes que va justo
   encima —los dos son cajas y sin esto se leen como una sola—. */
.panel-siguiente { border: 2px solid var(--tinta); background: var(--lienzo-2); }
.panel-siguiente h3 { margin-top: .1rem; }
.panel-siguiente .boton.grande { width: 100%; text-align: center; box-sizing: border-box; }

/*
  ═══════════════════════════════════════════════════════════════════════════
  LAS CASILLAS DE ACEPTACIÓN Y EL MODELO DE DESISTIMIENTO
  ═══════════════════════════════════════════════════════════════════════════

  Dos clases para la parte de contratar, y las dos existen por un motivo medido.

  `.casilla` alinea el cuadradito con la PRIMERA LÍNEA del texto, no con su
  centro: los textos de aceptación ocupan tres o cuatro renglones y con
  `align-items:center` el cuadrado acaba flotando en medio del párrafo, donde
  nadie lo asocia con lo que hay que marcar. Y el peso normal es deliberado: un
  `label` en negrita de cuatro líneas se lee como un titular y no como algo que
  hay que leer.

  `.modelo` es el formulario de desistimiento del anexo A del texto refundido.
  Va en `<pre>` porque son líneas con guiones para rellenar y su disposición es
  parte del documento, pero **con `white-space: pre-wrap`**: un `<pre>` normal no
  parte líneas y en un móvil de 360 px se sale de la pantalla. Es el fallo 36 —una
  tabla que se desplaza de lado no está arreglada, está escondida— aplicado aquí.
*/
.casilla {
  display: flex; gap: .6rem; align-items: flex-start;
  font-weight: 400; margin-bottom: 1rem; line-height: 1.5;
}
.casilla input[type="checkbox"] { margin-top: .3rem; flex: 0 0 auto; width: 1.05rem; height: 1.05rem; }

.modelo {
  white-space: pre-wrap; word-break: break-word;
  background: var(--lienzo-2); border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
  padding: .9rem 1rem; margin: .8rem 0;
  font-size: .92rem; line-height: 1.6;
  font-family: var(--tipo-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
}

/*
  ─── EL CASO PRÁCTICO ────────────────────────────────────────────────────────

  Un supuesto práctico no se lee como un test. En el examen el enunciado de
  hechos está delante TODO el rato y se vuelve a él en cada pregunta, así que
  aquí van los hechos arriba, destacados, y las preguntas debajo en una lista
  que se recorre sin salir de la página.

  Las respuestas van dentro de un `<details>` cerrado: la gracia del ejercicio
  es contestar con los hechos delante antes de mirar. Abierto por defecto, el
  caso se convertiría en una lectura y dejaría de ser un ejercicio.

  ⚠ `.caso-opciones` numera con letras porque la solución se cita como «a)»,
  «b)»… igual que en un examen real, y porque un número al lado del número de
  pregunta se confunde.
*/
.caso-hechos { background: var(--lienzo-2); border-left: 4px solid var(--acento); }
.caso-hechos h2 { margin-top: 0; font-size: 1.05rem; }
.caso-hechos p { margin: .6rem 0; line-height: 1.65; max-width: 66ch; }

.lista-casos { list-style: none; padding: 0; margin: 1rem 0 0; }
.caso-pregunta {
  border: 1px solid var(--borde); border-radius: var(--radio-sm);
  padding: 1rem 1.1rem; margin-bottom: 1rem;
}
.caso-enunciado { margin: 0 0 .7rem; line-height: 1.6; max-width: 66ch; }
.caso-opciones { list-style: lower-alpha; margin: 0 0 .6rem; padding-left: 1.6rem; }
.caso-opciones li { margin-bottom: .35rem; line-height: 1.55; max-width: 64ch; }
.caso-solucion summary { cursor: pointer; font-weight: 600; font-size: .94rem; }
.caso-solucion p { margin: .6rem 0 0; line-height: 1.6; max-width: 66ch; }

/*
  ─── EL CASO PRÁCTICO, RESUELTO Y CORREGIDO ─────────────────────────────────

  Sin corregir, cada opción es una etiqueta con su radio: el área de pulsación
  es la línea entera y no el círculo de 16 px, porque esto se contesta en el
  móvil del autobús. Corregido, las opciones dejan de ser pulsables —volver a
  cambiarlas y reenviar haría que el marcador no significara nada— y se marcan
  la buena y, si se falló, la elegida.

  El marcador va ARRIBA, antes de los hechos: al corregir, lo primero que se
  busca es cuántas van.
*/
.caso-marcador { border-left: 4px solid var(--acento); }
.caso-nota { font-size: 1.6rem; margin: 0 0 .3rem; }

.caso-opcion { display: flex; gap: .6rem; align-items: flex-start; cursor: pointer; line-height: 1.55; }
.caso-opcion input[type="radio"] { margin-top: .32rem; flex: 0 0 auto; width: 1.05rem; height: 1.05rem; }
.caso-opciones li { margin-bottom: .5rem; max-width: 64ch; }

.caso-opciones.corregidas { list-style: none; padding-left: 0; }
.caso-opciones.corregidas li { padding: .35rem .55rem; border-radius: var(--radio-sm); }
.caso-opciones.corregidas li.buena { background: var(--abierto-tenue, #e8f5ec); font-weight: 600; }
.caso-opciones.corregidas li.mala { background: var(--urgente-tenue, #fdecec); text-decoration: line-through; }

.caso-pregunta.acertada { border-left: 4px solid var(--abierto, #2e7d4f); }
.caso-pregunta.fallada { border-left: 4px solid var(--urgente, #c0392b); }
.caso-porque { margin-top: .8rem; padding-top: .8rem; border-top: 1px solid var(--borde); }
.caso-porque p { line-height: 1.6; max-width: 66ch; margin: .4rem 0; }
.caso-veredicto { font-weight: 600; margin-top: 0; }

/*
  ─── LA MUESTRA DE UN CASO PRÁCTICO ─────────────────────────────────────────

  `.de-pago` son los enunciados de las preguntas que NO se resuelven sin pagar.
  Se enseñan enteros a propósito —es el texto por el que alguien busca— y se
  marcan con un candado y un tono apagado para que se vea de un golpe qué hay
  dentro y qué no. Esconderlos dejaría la página sin nada que indexar; pintarlos
  como los demás haría creer que están resueltos.

  `.caso-venta` va al final y no flotando en medio: quien llega de una búsqueda
  primero tiene que encontrar lo que buscaba. Vender antes de dar es lo que hace
  que se cierre la pestaña.
*/
.caso-venta { border-left: 4px solid var(--acento); margin-top: 2rem; }
.caso-venta h2 { margin-top: 0; }
.caso-venta p { max-width: 66ch; line-height: 1.6; }

/*
  ─── LO QUE QUEDA DENTRO, SIN PARECER UN ERROR ──────────────────────────────

  Estaba resuelto con seis cajas de línea DISCONTINUA, grises y con un candado
  flotando en cada una: **1.100 px de scroll a 360 px** que se leen como
  «contenido roto», no como «hay más aquí». Y empujaban el panel que vende
  hasta los 3.104 px, casi cinco pantallas de móvil.

  Ahora es UN panel con la lista numerada dentro —los números importan: son la
  2, la 3, la 4… del mismo caso—. Ocupa la cuarta parte y se entiende de un
  vistazo.
*/
.cerradas { border-left: 4px solid var(--borde); }
.cerradas h2 { margin-top: 0; font-size: 1.05rem; }
.cerradas-lista { margin: .8rem 0 0; padding-left: 1.5rem; }
.cerradas-lista li {
  margin-bottom: .5rem; line-height: 1.5;
  color: var(--tinta-suave); max-width: 64ch;
}

/*
  La etiqueta que convierte un color en información. Un bloque verde sin decir
  por qué obliga a deducir que esa es la correcta, y quien no distinga bien el
  color no lo deduce nunca.
*/
.marca-buena, .marca-mala {
  display: inline-block; margin-left: .5rem;
  font-size: .72rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  padding: .1rem .4rem; border-radius: var(--radio-sm); vertical-align: middle;
}
.marca-buena { background: var(--abierto, #2e7d4f); color: #fff; }
.marca-mala { background: var(--urgente, #c0392b); color: #fff; }
.caso-opciones.corregidas li.mala .marca-mala { text-decoration: none; }

/*
  El título del panel de venta NO va en versalita pequeña como los demás. El
  estilo de `.panel h2` convierte los encabezados en etiquetas gris de 0,8rem, y
  eso está bien para «LOS HECHOS» —que orienta— y mal para el único bloque de la
  página que tiene que pesar: quien llega de una búsqueda decide aquí.
*/
.caso-venta h2 {
  font-size: 1.25rem; text-transform: none; letter-spacing: 0;
  color: var(--tinta); margin-bottom: .6rem;
}

/*
  ─── EL CASO A DOS COLUMNAS, PORQUE MEDIA PANTALLA ESTABA VACÍA ─────────────

  Medido a 1.440 px: la columna de texto ocupaba **587 px de un contenedor de
  1.180 —el 50 %— con 593 px vacíos a la derecha**. Ensanchar el texto no era la
  solución: un renglón de mil píxeles no se lee, y por eso está el tope de 66ch.
  Lo que faltaba era **poner algo en la mitad vacía**.

  Y lo que tiene que ir ahí no es decoración: son LOS HECHOS. En un examen el
  supuesto está delante todo el rato y se vuelve a él en cada pregunta; en una
  sola columna, a 1.400 px de scroll, ya no lo ves. `position: sticky` lo
  resuelve y de paso llena el hueco.

  ⚠ Las dos columnas son 1fr y 1fr a propósito: el texto se topa en 66ch (587 px)
  y cada columna mide ~574, así que **las dos se llenan enteras** y no queda
  hueco muerto en ninguna.

  ⚠ `top: 7.5rem` es la altura de la cabecera pegajosa, la misma que usa
  `scroll-margin-top` para las anclas de los módulos. Con menos, el panel se
  mete debajo del menú.

  En móvil no hay dos columnas: se apila, y los hechos van primero.
*/
.caso-tablero { display: block; }
.titulo-columna { margin-top: 2rem; }

@media (min-width: 62rem) {
  .caso-tablero {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 2rem;
    align-items: start;
    margin-top: 1.5rem;
  }
  .caso-lado {
    position: sticky; top: 7.5rem;
    max-height: calc(100vh - 9rem); overflow-y: auto;
  }
  .caso-lado .caso-hechos { margin-top: 0; }
  .titulo-columna { margin-top: 0; }
}

/*
  `min-width: 0` no es cosmético: en una rejilla, una columna con contenido
  largo —una URL, una palabra sin espacios— se niega a encogerse por debajo de
  su contenido mínimo y desborda la rejilla entera hacia la derecha. Es el fallo
  clásico de CSS Grid y no se ve hasta que aparece el primer texto largo.
*/
.caso-principal { min-width: 0; }

/*
  ─── LA PÁGINA DE UN CASO ES UNA LANDING, NO UNA FICHA ──────────────────────

  Quien llega aquí desde una búsqueda no sabe quiénes somos y tiene delante
  veinte webs iguales. Así que la página demuestra primero —resuelve una
  pregunta de examen con su artículo delante— y argumenta después.

  `.prueba-tira` va arriba con tres cifras. Son cifras y no adjetivos porque un
  adjetivo lo escribe cualquiera.

  `.empujon` es la oferta puesta en el momento de más ganas: justo después de
  ver que la primera pregunta funciona. Es el fallo 49 al derecho.
*/
.prueba-tira {
  list-style: none; display: flex; flex-wrap: wrap; gap: 1rem;
  padding: 0; margin: 1.2rem 0 0;
}
.prueba-tira li {
  flex: 1 1 12rem; background: var(--lienzo-2);
  border-radius: var(--radio-sm); padding: .8rem 1rem;
}
.prueba-tira strong { display: block; font-size: 1.5rem; line-height: 1.1; color: var(--acento); }
.prueba-tira span { display: block; font-size: .86rem; color: var(--tinta-suave); margin-top: .25rem; line-height: 1.4; }

.empujon {
  display: flex; flex-wrap: wrap; align-items: center; gap: 1rem;
  border: 1px solid var(--acento); border-radius: var(--radio-sm);
  padding: 1rem 1.1rem; margin: 1.5rem 0;
}
.empujon p { margin: 0; flex: 1 1 16rem; line-height: 1.55; max-width: 60ch; }



/*
  ─── LA BARRA DE COMPRA DEL MÓVIL ───────────────────────────────────────────

  Medido a 360 px en la página de un caso: el primer botón de compra caía a
  **2.369 px, 3,7 pantallas de scroll**. Subirlo en el flujo no arreglaba nada
  —detrás va contenido que también hace falta— así que lo que se hace es que no
  haya que buscarlo: barra fija abajo con el precio dentro, a 0 px en todo
  momento.

  Sin una línea de JavaScript: `position: fixed` y una media query.

  ⚠ El hueco va en el BODY (`body.con-barra`) y no dentro del contenido. La
  primera versión lo puso en `main`, y como el pie va después, sus últimos 71 px
  quedaban debajo de la barra. Medido bajando del todo a 360 px.

  ⚠ En escritorio NO se pinta. Allí el primer CTA ya está a 1.026 px y una barra
  fija sería ruido comiéndose pantalla.
*/
body.con-barra { padding-bottom: 5.2rem; }
.barra-compra {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
  display: flex; align-items: center; gap: .9rem;
  padding: .7rem 1rem calc(.7rem + env(safe-area-inset-bottom, 0px));
  background: var(--fondo); border-top: 1px solid var(--borde);
  box-shadow: 0 -6px 18px rgba(0, 0, 0, .07);
}
.barra-texto { flex: 1 1 auto; min-width: 0; line-height: 1.2; }
.barra-texto strong { display: block; font-size: 1.05rem; }
.barra-texto span {
  display: block; font-size: .74rem; color: var(--tinta-suave); margin-top: .15rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.barra-compra .boton { flex: 0 0 auto; }

@media (min-width: 62rem) {
  .barra-compra { display: none; }
  body.con-barra { padding-bottom: 0; }
}

/*
  ─── EL PIE, PLEGADO EN MÓVIL ───────────────────────────────────────────────

  Medido a 360 px: el pie ocupaba **1.618 px, dos pantallas y media**, y era el
  bloque más alto de la página —más que el supuesto de un caso, más que las
  preguntas y más que la franja de argumentos—. En TODAS las páginas.

  En escritorio la rejilla va a cinco columnas y cuesta poco, así que allí se
  abre sola y el resumen desaparece. En móvil se pliega.

  Los enlaces siguen en el HTML dentro del `<details>`, así que Google los
  rastrea igual: esto no es esconder, es no obligar a recorrerlos.
*/
.pie-mapa > summary {
  cursor: pointer; font-weight: 600; font-size: .92rem;
  padding: .6rem 0; list-style: none;
}
.pie-mapa > summary::-webkit-details-marker { display: none; }
.pie-mapa > summary::after { content: " ▾"; opacity: .6; }
.pie-mapa[open] > summary::after { content: " ▴"; }

@media (min-width: 62rem) {
  /* En escritorio no hay nada que plegar: el mapa va abierto y sin resumen. */
  .pie-mapa > summary { display: none; }
  .pie-mapa > .pie-rejilla { display: grid !important; }
}

/*
  ─── LO QUE EL MÓVIL NO NECESITA TAN GRANDE ─────────────────────────────────

  Desglose a 360 px de la página de un caso (6.613 px, 10,3 pantallas):

      pie del sitio      1.618   ← ya plegado arriba
      argumentos         1.130
      hechos               763
      pregunta resuelta    683
      cerradas             663
      venta                405
      tira de cifras       316   ← tres bloques apilados para tres números
      cabecera             273

  No se quita ni una palabra: se compacta lo que solo estaba suelto porque en
  escritorio sobra sitio. La tira de cifras pasa a una fila de tres, y las
  tarjetas de argumentos pierden relleno y ganan densidad.
*/
@media (max-width: 61.99rem) {
  /* Tres cifras en una fila: en columna eran 316 px para tres números. */
  .prueba-tira { gap: .5rem; margin-top: .9rem; }
  .prueba-tira li { flex: 1 1 0; min-width: 0; padding: .55rem .5rem; text-align: center; }
  .prueba-tira strong { font-size: 1.15rem; }
  .prueba-tira span { font-size: .72rem; margin-top: .15rem; }

  .por-que { padding: 1.8rem 0 1.6rem; margin-top: 1.8rem; }
  

  /* El titular: a 31,2 px ocupaba TRES renglones y se comía media pantalla. */
  .cabecera-seccion h1 { font-size: 1.65rem; line-height: 1.2; }

  .empujon { padding: .8rem .9rem; gap: .7rem; margin: 1.1rem 0; }
  .caso-venta { margin-top: 1.5rem; }
  .caso-hechos p { margin: .45rem 0; }
}

/*
  ─── LA LANDING DE UN MÓDULO, Y LO QUE DEMUESTRA ────────────────────────────

  Toda la zona de pago se convierte en landing cuando quien mira no ha pagado.
  El módulo enseña el sello, el índice entero, los artículos con su fecha y la
  PRIMERA SECCIÓN COMPLETA; el resto se corta sobre el HTML —no se esconde con
  CSS, que eso no es un muro sino un cartel encima del contenido—.

  `.comparalo` no proclama nada: da las cuatro preguntas que separan un temario
  serio de un PDF y las contesta aquí. Demostrar en vez de decir «somos los
  mejores», que es lo que no está medido y lo más fácil de desmontar.

  Reutiliza `.comparativa`, que ya se apila en móvil con `data-th` (fallo 36: una
  tabla que se desplaza de lado no está arreglada, está escondida).
*/
.modulo-texto > :first-child { margin-top: 0; }
.lista-fuentes { list-style: none; padding: 0; margin: .6rem 0 0; }
.lista-fuentes li { margin-bottom: .55rem; line-height: 1.4; }
.lista-fuentes .cuantas { display: block; color: var(--tinta-suave); }

.comparalo { margin-top: 2.5rem; }
.comparalo h2 { font-size: 1.25rem; }

.precio-contexto {
  margin-top: 2rem; padding: 1.2rem 1.3rem;
  background: var(--lienzo-2); border-radius: var(--radio-sm);
  border-left: 4px solid var(--acento);
}
.precio-contexto h2 { margin-top: 0; font-size: 1.25rem; }
.precio-lista { margin: .8rem 0 0; padding-left: 1.3rem; }
.precio-lista li { margin-bottom: .45rem; line-height: 1.55; max-width: 66ch; }

/*
  ─── «POR QUÉ ESTUDIAR AQUÍ», QUE ES EL ARGUMENTO MÁS FUERTE ────────────────

  Estaba en cuatro cajas grises iguales con título y párrafo, y Sergio lo dijo
  en una frase: «toda la página parece un Excel». Tenía razón: en una pantalla
  que ya es texto, listas y un índice, cuatro cajas más no se leen.

  Tres cosas cambian eso, y ninguna es decorativa:

    · La sección va A SANGRE con fondo propio, para que se vea que empieza otra
      cosa. Es el mismo recurso del héroe de la portada.
    · Cada motivo entra por una frase CORTA Y GRANDE. Lo que se retiene de un
      argumento es una frase, no un párrafo.
    · Y cierra con un dato al pie, en versal pequeña: el argumento se sostiene
      en una cifra, no en un adjetivo.
*/
.por-que { padding: 2.5rem 0 2.2rem; margin-top: 2.5rem; }
.por-que::before { background: var(--lienzo-2); }
.por-que-antetitulo {
  text-transform: uppercase; letter-spacing: .08em; font-size: .74rem;
  font-weight: 700; color: var(--acento); margin: 0 0 .3rem;
}
.por-que > .contenedor > h2 { margin-top: 0; font-size: 1.6rem; max-width: 24ch; }
.por-que-rejilla {
  display: grid; gap: 1.4rem 2rem; margin-top: 1.6rem;
  grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
}
.por-que-rejilla article { border-top: 3px solid var(--acento); padding-top: .8rem; }
.por-que-titular {
  font-size: 1.12rem; font-weight: 700; line-height: 1.3;
  margin: 0 0 .45rem; max-width: 28ch;
}
.por-que-rejilla p { line-height: 1.6; margin: 0 0 .5rem; max-width: 46ch; }
.por-que-dato {
  text-transform: uppercase; letter-spacing: .05em; font-size: .72rem;
  font-weight: 700; color: var(--tinta-suave); margin: 0;
}

/*
  ─── LAS CUATRO PREGUNTAS ───────────────────────────────────────────────────

  Estaban en una tabla de dos columnas. Una tabla se audita; un argumento se
  lee. Ahora cada par es la pregunta en grande y la respuesta debajo, con la
  numeración fuera del texto para que la vista salte de pregunta a pregunta.
*/
.comparalo { margin-top: 2.5rem; }
.comparalo h2 { font-size: 1.35rem; max-width: 28ch; }
.comparalo-lista { list-style: none; counter-reset: preg; padding: 0; margin: 1.4rem 0 0; }
.comparalo-lista li {
  counter-increment: preg; position: relative;
  padding: 0 0 1.1rem 2.6rem; margin-bottom: 1.1rem;
  border-bottom: 1px solid var(--borde);
}
.comparalo-lista li:last-child { border-bottom: 0; }
.comparalo-lista li::before {
  content: counter(preg); position: absolute; left: 0; top: .05rem;
  width: 1.8rem; height: 1.8rem; border-radius: 50%;
  background: var(--acento); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: .85rem; font-weight: 700;
}
.comparalo-pregunta { font-size: 1.08rem; font-weight: 700; margin: 0 0 .35rem; line-height: 1.35; max-width: 40ch; }
.comparalo-respuesta { margin: 0; line-height: 1.6; max-width: 62ch; color: var(--tinta-suave); }

/*
  ─── DONDE SE CORTA LA LECTURA ──────────────────────────────────────────────

  Antes este bloque repetía los títulos de las secciones cerradas, que ya están
  en el índice de la izquierda: la misma lista dos veces en la misma pantalla.
  Ahora es lo que tiene que ser —una marca de dónde se acaba lo abierto— y los
  títulos viven en un solo sitio.
*/
.corte {
  margin: 1.8rem 0; padding: 1.1rem 1.2rem;
  border: 1px dashed var(--borde); border-radius: var(--radio-sm);
  background: var(--lienzo-2);
}
.corte p { margin: 0; line-height: 1.6; max-width: 60ch; }
.corte-que {
  text-transform: uppercase; letter-spacing: .06em; font-size: .74rem;
  font-weight: 700; color: var(--tinta-suave); margin-bottom: .35rem !important;
}

/*
  ─── DE DÓNDE SALE EL MÓDULO ────────────────────────────────────────────────

  La lista de artículos uno a uno medía **2.567 px a 360 px en el módulo más
  grande: cuatro pantallas de móvil, el 24 % de la página** para 33 enlaces.
  Y la lista no es lo que demuestra nada: lo demuestra el recuento y la fecha.
  Fuera va el resumen por norma —que además dice más— y la lista entera queda
  plegada para quien quiera comprobarla.
*/
.resumen-fuentes { list-style: none; padding: 0; margin: .6rem 0 .8rem; }
.resumen-fuentes li { margin-bottom: .5rem; line-height: 1.4; }
.resumen-fuentes .cuantas { display: block; font-size: .84rem; color: var(--tinta-suave); }
.mas-fuentes > summary { cursor: pointer; font-size: .88rem; font-weight: 600; padding: .3rem 0; }

/*
  ─── QUÉ SE COMPRA, QUE NO ES ESTA PÁGINA ───────────────────────────────────

  La entradilla del módulo decía «15 secciones · 15 min de lectura», y ese es el
  precio de la unidad equivocada: nadie paga 9,90 € por quince minutos de
  lectura. Lo que se compra es el acceso a TODO, y eso tiene que verse.

  Las tres cifras van grandes y la lista de abajo dice lo que el sistema HACE
  —repaso espaciado, curso, simulacros—, que es lo que lo separa de un PDF.
*/
.incluye { margin-top: 2.5rem; }
.incluye h2 { font-size: 1.35rem; max-width: 26ch; }
.incluye-entrada { line-height: 1.6; max-width: 62ch; }
.incluye-rejilla {
  display: grid; gap: 1rem; margin: 1.2rem 0;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
}
.incluye-rejilla div {
  background: var(--lienzo-2); border-radius: var(--radio-sm); padding: .9rem 1rem;
}
.incluye-rejilla strong { display: block; font-size: 1.6rem; line-height: 1.1; color: var(--acento); }
.incluye-rejilla span { display: block; font-size: .84rem; color: var(--tinta-suave); margin-top: .3rem; line-height: 1.45; }
.incluye-lista { margin: 0; padding-left: 1.3rem; }
.incluye-lista li { margin-bottom: .5rem; line-height: 1.6; max-width: 64ch; }

/*
  ─── POR QUÉ ESTÁ HECHO ASÍ ─────────────────────────────────────────────────

  ⛔ Sin promesas de aprobado y sin «tasas de aprobados»: las que circulan las
  publican academias que venden cursos, sin fuente primaria. Lo que se cita es la
  evidencia del MÉTODO, con autor y año, para que se pueda comprobar.

  La fuente va en pequeño y en cursiva debajo de cada motivo: es una cita, no un
  argumento de venta, y tiene que leerse como lo que es.
*/
.metodo { margin-top: 2.5rem; }
.metodo h2 { font-size: 1.35rem; }
.metodo-rejilla {
  display: grid; gap: 1.4rem 2rem; margin: 1.2rem 0 1rem;
  grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
}
.metodo-rejilla article { border-left: 3px solid var(--borde); padding-left: 1rem; }
.metodo-titular { font-size: 1.05rem; font-weight: 700; margin: 0 0 .4rem; line-height: 1.35; max-width: 30ch; }
.metodo-rejilla p { line-height: 1.6; margin: 0 0 .5rem; max-width: 52ch; }
.metodo-fuente { font-size: .78rem; color: var(--tinta-suave); margin: 0 !important; }

/*
  ─── UNA COLUMNA LATERAL ALTA NO PUEDE SER PEGAJOSA ─────────────────────────

  `.caso-lado` se diseñó para el supuesto de hecho de un caso práctico: un panel
  corto que cabe en pantalla, y por eso lleva `position: sticky` con tope de alto
  y scroll propio —así el supuesto sigue delante mientras se contesta—.

  Al reutilizarlo en el módulo se rompió: ahí la columna lleva el índice de 22
  secciones MÁS la lista de normas. Medido a 1.440 px: **454 px de contenido
  cortados dentro de su propia caja**, con una barra de scroll interna que nadie
  espera. Eso es lo que Sergio vio como «sale cortada, sin sentido», y tenía
  razón.

  Cuando la columna es alta no se pega: fluye. Se pierde que acompañe al scroll
  y se gana que se vea entera, que es lo que hace falta en un índice.
*/
@media (min-width: 62rem) {
  .caso-lado.lado-alto {
    position: static;
    max-height: none;
    overflow: visible;
  }
}

/*
  El tablero del módulo se marca aparte para poder darle el reparto que le toca:
  el índice y las normas ocupan menos que el texto, así que la columna de leer se
  lleva más ancho. En el caso práctico son 1fr y 1fr porque los hechos hay que
  poder leerlos igual de cómodos que las preguntas.
*/
@media (min-width: 62rem) {
  .caso-tablero.tablero-alto { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }

  /*
    ⚠ Y LA COLUMNA SE COLOCA A MANO, NO POR EL ORDEN DEL HTML.

    El documento dice ahora TEXTO y luego ÍNDICE, porque ese es el orden en que
    hay que leerlo —en móvil, con un lector de pantalla y para Google—. Si la
    rejilla se dejara a su aire, el texto caería en la columna estrecha de 5fr y
    el índice en la ancha de 7fr, que es justo al revés de lo que se quiere.

    `grid-column` no depende del orden del HTML, así que las dos cosas pueden
    ser distintas a propósito: el orden de lectura lo manda el documento y la
    colocación la manda la rejilla. Es la única forma de tener las dos bien.
  */
  .caso-tablero.tablero-alto > .caso-lado { grid-column: 1; grid-row: 1; }
  .caso-tablero.tablero-alto > .caso-principal { grid-column: 2; grid-row: 1; }
}

/*
  ─── EL REPARTO DEL TEMARIO, QUE ES LO QUE NADIE MÁS PUEDE DAR ──────────────

  «De los 315 temas de este temario, 18 son de medio ambiente y 8 de
  transparencia» exige haber leído el boletín provincial de ese ayuntamiento
  tema a tema. Es el argumento más fuerte del proyecto y estaba detrás de un
  muro con tres cifras.

  Va con barra, no con porcentaje, y por un motivo: el porcentaje obligaría a
  explicar el denominador en cada línea —solo se reconoce parte de los temas— y
  la barra compara sin afirmar nada. El número que se da es el de temas, que es
  comprobable abriendo el boletín.
*/
.reparto { margin-top: 2rem; }
.reparto h2 { font-size: 1.35rem; }
.reparto-pie { line-height: 1.6; max-width: 62ch; }
.reparto-lista { list-style: none; padding: 0; margin: 1.1rem 0 .8rem; }
.reparto-lista li {
  display: grid; grid-template-columns: minmax(0, 15rem) 1fr auto;
  gap: .8rem; align-items: center; margin-bottom: .5rem;
}
.rep-materia { font-size: .94rem; overflow: hidden; text-overflow: ellipsis; }
.rep-barra { height: .55rem; background: var(--lienzo-2); border-radius: 999px; overflow: hidden; }
.rep-barra i { display: block; height: 100%; background: var(--marca); border-radius: 999px; }
.rep-temas { font-size: .84rem; color: var(--tinta-suave); white-space: nowrap; }

@media (max-width: 45rem) {
  /* A 360 px tres columnas no caben: el nombre arriba y la barra debajo. */
  .reparto-lista li { grid-template-columns: 1fr auto; }
  .rep-materia { grid-column: 1 / -1; }
}

.muestra-pregunta { margin-top: 2rem; }
.muestra-pregunta h2 { font-size: 1.35rem; }

/*
  ─── LA LANDING EN MÓVIL: EL TEXTO PRIMERO ──────────────────────────────────

  Medido a 360 px en el módulo más grande: **9.251 px, 14,5 pantallas**, con el
  índice y la lista de normas ocupando 1.818 px ANTES de la primera línea del
  módulo. Quien llega de una búsqueda se come dos pantallas y media de mapa
  antes de ver el contenido que le trajo.

  ⚠ SE ARREGLÓ DOS VECES, Y LA PRIMERA ESTABA A MEDIAS. La primera versión dejó
  el índice delante en el HTML y lo mandó detrás con `order`, así que en la
  pantalla iba bien y en el documento seguía igual de mal: un lector de pantalla
  y Google se comían el mapa entero antes de la primera línea. `order` mueve
  píxeles, no el orden de lectura. Ahora el HTML lleva el texto primero —que es
  como se lee— y el índice se coloca a la izquierda en escritorio con
  `grid-column`, así que en móvil no hace falta reordenar nada.

  ⚠ Y las reglas de compactación apuntaban a `.argumentos-rejilla`, que dejó de
  existir al renombrar la sección a `.por-que`. Una regla CSS que no casa con
  nada no da ningún error: simplemente no compacta. Es el mismo agujero que las
  variables inexistentes, y la prueba de clases no lo ve porque comprueba que
  toda clase USADA tenga regla, no que toda regla tenga clase.
*/
@media (max-width: 61.99rem) {
  /* La cola de argumentos: 4.084 px, 6,4 pantallas. Se aprieta. */
  .por-que-rejilla { gap: 1rem; margin-top: 1.1rem; }
  .por-que-rejilla article { padding-top: .6rem; }
  .por-que-titular { font-size: 1.02rem; }
  .por-que-rejilla p { font-size: .9rem; line-height: 1.5; margin-bottom: .4rem; }
  .por-que > .contenedor > h2 { font-size: 1.35rem; }

  .incluye-rejilla { gap: .6rem; margin: .9rem 0; }
  .incluye-rejilla div { padding: .7rem .8rem; }
  .incluye-rejilla strong { font-size: 1.3rem; }
  .incluye-lista li { font-size: .9rem; line-height: 1.5; margin-bottom: .4rem; }

  .comparalo-lista li { padding-bottom: .8rem; margin-bottom: .8rem; }
  .comparalo-pregunta { font-size: 1rem; }
  .comparalo-respuesta { font-size: .9rem; line-height: 1.5; }

  .metodo-rejilla { gap: 1rem; }
  .metodo-rejilla p { font-size: .9rem; line-height: 1.5; }
  .precio-lista li { font-size: .92rem; margin-bottom: .35rem; }
}

/*
  ═══════════════════════════════════════════════════════════════════════════
  EL MENÚ DE CUENTA: SABER QUE ESTÁS DENTRO, Y PODER SALIR
  ═══════════════════════════════════════════════════════════════════════════

  Al entrar, la cabecera cambiaba una sola palabra —«Entrar» pasaba a «Admin»—
  y `/salir` no estaba enlazada en ninguna parte. Ahora hay un desplegable
  nativo: quién eres, con qué rol, a dónde ir y cómo salir.

  ⚠ Es un `<details>` y no un menú con JavaScript porque aquí no hay JavaScript
  de cliente: un opositor estudia en el autobús con el móvil que tiene. El
  navegador lo abre solo, con el teclado y con lector de pantalla.

  ⚠ Y CABE POR POCO. El ancho útil de la cabecera a 360 px son 305, y la marca
  más las acciones ya sumaban 315 con «Tu panel». Por eso en móvil se enseña
  solo el disco de la inicial y el correo entero se lee dentro, al desplegar.

  ⚠ POR QUÉ NO VA EN VERDE, QUE FUE LA PRIMERA VERSIÓN Y ESTABA MAL.
  `--abierto` ya significa algo en esta web: **el plazo está abierto**. Sale en
  las fichas, en el buscador y en /abiertas. Gastarlo además en «has iniciado
  sesión» es decir dos cosas con el mismo color, y la menos importante gritaba
  más que la otra. La identidad de quien mira no es un estado del producto: va
  en tinta normal, y lo único que la distingue es el disco con la inicial, que
  es la convención de todo el sector.
*/
.cuenta { position: relative; }
.cuenta > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .25rem .5rem .25rem .25rem;
  margin-left: .35rem;
  border-radius: 999px;
  color: var(--tinta);
  user-select: none;
  transition: background-color .12s ease;
}
.cuenta > summary::-webkit-details-marker { display: none; }
.cuenta > summary:hover { background: var(--lienzo-2); }
/*
  El anillo del teclado se pone a mano porque el `outline` por defecto abraza la
  caja rectangular y aquí el control es una píldora: quedaba una esquina fuera.
*/
.cuenta > summary:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--lienzo), 0 0 0 4px var(--marca);
}

/*
  El disco con la inicial. Sustituye al punto de color: dice lo mismo —hay
  alguien dentro— y además dice QUIÉN, sin gastar ni una palabra de ancho.
*/
.cuenta-disco {
  flex: 0 0 auto;
  width: 24px; height: 24px;
  border-radius: 50%;
  background: var(--marca);
  color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: .74rem; font-weight: 700; line-height: 1;
  letter-spacing: 0;
}
.cuenta-disco.grande { width: 34px; height: 34px; font-size: 1rem; margin-top: 1px; }
/*
  ⚠ En oscuro `--marca` es un lavanda claro (#a5b0ff), así que la inicial en
  blanco daría 1,4 de contraste: ilegible. Es la misma corrección que ya llevan
  `.boton` y `.paginacion .actual`, y por eso se escribe igual que ellas.
*/
@media (prefers-color-scheme: dark) { .cuenta-disco { color: #10131c; } }

.cuenta-nombre {
  max-width: 13ch;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: .92rem; font-weight: 600;
}
/*
  Un SVG y no el carácter «▾»: un glifo de texto cae donde quiera la fuente de
  cada sistema, no se alinea con la línea base y no puede girar. Girar al abrir
  es lo que le dice al que mira que ese control tiene dos estados.
*/
.cuenta-flecha {
  width: 10px; height: 6px;
  flex: 0 0 auto;
  color: var(--tinta-tenue);
  transition: transform .15s ease;
}
.cuenta[open] > summary { background: var(--lienzo-2); }
.cuenta[open] .cuenta-flecha { transform: rotate(180deg); }

.cuenta-menu {
  position: absolute;
  right: 0;
  top: calc(100% + .45rem);
  z-index: 50;
  min-width: 16rem;
  background: var(--lienzo);
  border: 1px solid var(--borde);
  border-radius: .7rem;
  box-shadow: var(--sombra-lg);
  padding: .3rem;
}
/*
  ⚠ `align-items: center` sobre un bloque de TRES líneas —nombre, correo y
  rol— centraba el disco a la altura del correo, así que quedaba bajo respecto
  al nombre, que es lo que identifica. Se alinea arriba, con el ajuste óptico
  justo para que su centro caiga en la línea del nombre.
*/
.cuenta-quien {
  display: flex; align-items: flex-start; gap: .6rem;
  padding: .65rem .6rem .7rem;
  margin-bottom: .3rem;
  border-bottom: 1px solid var(--borde);
}
.cuenta-datos { min-width: 0; display: block; }
.cuenta-datos b { display: block; font-size: .95rem; font-weight: 650; line-height: 1.25; }
.cuenta-correo {
  display: block;
  font-size: .78rem; color: var(--tinta-tenue);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/*
  El rol va en una etiqueta y no en texto corrido: es una propiedad de la cuenta,
  no una frase, y así se distingue del correo de un vistazo.
*/
.cuenta-rol {
  display: inline-block;
  margin-top: .3rem;
  padding: .1rem .38rem;
  border-radius: .3rem;
  background: var(--marca-tenue);
  color: var(--marca);
  /* 0,72rem es el suelo del sitio, medido: por debajo son menos de 11,5 px. */
  font-size: .72rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .05em;
}
/* Los destinos, agrupados: es lo único del menú que lleva a algún sitio. */
.cuenta-ir { display: block; }
.cuenta-menu a {
  display: block;
  padding: .5rem .6rem;
  border-radius: .4rem;
  font-size: .9rem;
  color: var(--tinta);
  text-decoration: none;
}
.cuenta-menu a:hover, .cuenta-menu a:focus-visible { background: var(--lienzo-2); }
/*
  Cerrar sesión va separada. No es adorno: es la única acción del menú que
  deshace algo, y pegada a «Tu cuenta» invita a pulsarla sin querer.

  ⚠ Y ya NO va en rojo. El rojo de esta paleta es `--urgente`, que marca los
  plazos a punto de cerrarse; cerrar sesión no es un peligro ni un error, es lo
  normal al terminar. Un rojo gastado en lo cotidiano deja de avisar de lo que
  importa. Se distingue por su sitio —debajo de la línea— y no por el color.
*/
.cuenta-salir {
  margin-top: .3rem;
  padding-top: .5rem !important;
  border-top: 1px solid var(--borde);
  border-radius: 0 0 .4rem .4rem !important;
  color: var(--tinta-suave) !important;
  font-weight: 600;
}

/*
  ⚠ EN MÓVIL, SOLO EL DISCO. El ancho útil de la cabecera a 360 px son 305, y el
  disco ocupa 24 donde el punto ocupaba 7: con el nombre al lado, las acciones
  se caían a una tercera fila. El nombre entero, el correo y el rol se leen
  dentro al desplegar, que es donde sobra sitio —y es lo que hace cualquier
  aplicación con cuentas—.

  El menú, además, se ancla al borde de la pantalla y no al del desplegable: con
  305 px útiles, uno de 16rem colgando de un elemento pegado a la derecha se
  salía por el lado. Medido a 360.
*/
@media (max-width: 30rem) {
  .cuenta > summary { padding: .2rem; gap: 0; }
  .cuenta-nombre, .cuenta-flecha { display: none; }
  .cuenta-menu { right: -.4rem; min-width: min(15rem, calc(100vw - 2.4rem)); }
}

/* ── La oferta de /contratar ───────────────────────────────────────────────
   El precio era una línea de texto corrido; es una oferta y se ve como tal.
   La cifra sale de los mismos datos que antes: aquí solo se pinta. */
.oferta-precio {
  display: flex; align-items: center; gap: 1.3rem; flex-wrap: wrap;
  background: var(--lienzo); border: 1px solid var(--marca-borde); border-radius: var(--radio);
  border-top: 3px solid var(--marca);
  padding: 1.3rem 1.5rem; margin-bottom: 1.4rem; box-shadow: var(--sombra);
}
.oferta-cifra b { font-size: 2.3rem; font-weight: 800; letter-spacing: -.035em; line-height: 1; color: var(--marca); white-space: nowrap; }
.oferta-detalle { display: flex; flex-direction: column; gap: .3rem; min-width: 0; max-width: 46ch; }
.oferta-detalle span:first-child { font-weight: 700; color: var(--tinta); font-size: .95rem; }
.oferta-detalle span:last-child { color: var(--tinta-suave); font-size: .92rem; line-height: 1.5; }

/* ── La venta en la ficha ──────────────────────────────────────────────────
   El módulo que faltaba en la página donde aterriza el tráfico. Borde con el
   acento de la marca para distinguirse de los paneles informativos sin gritar. */
.venta-ficha { border-color: var(--marca-borde); border-top: 3px solid var(--marca); }

/* ── El menú «Explorar» ────────────────────────────────────────────────────
   El catálogo hondo en la cabecera. `<details>` sin JavaScript, como el menú
   de cuenta. En móvil este desplegable NO existe —la tira recorta con
   overflow y enmascara el borde, y un panel colgando saldría cortado— y en su
   lugar se enseñan los mismos destinos como entradas de la tira (.nav-extra). */
.nav-explorar { position: relative; }
.nav-explorar summary {
  list-style: none; cursor: pointer; user-select: none;
  display: inline-flex; align-items: center; gap: .32rem;
  padding: .42rem .7rem; border-radius: 8px;
  font-size: .92rem; font-weight: 600; color: var(--tinta-suave); white-space: nowrap;
}
.nav-explorar summary::-webkit-details-marker { display: none; }
.nav-explorar summary:hover { background: var(--lienzo-2); color: var(--tinta); }
.nav-explorar summary.activo { color: var(--marca); background: var(--marca-tenue); }
.nav-explorar summary svg { width: 10px; height: 7px; transition: transform .15s ease; }
.nav-explorar[open] summary svg { transform: rotate(180deg); }
.nav-explorar[open] summary { background: var(--lienzo-2); color: var(--tinta); }
.nav-panel {
  position: absolute; top: calc(100% + 10px); right: 0; z-index: 50;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .15rem;
  width: 460px; padding: .6rem;
  background: var(--lienzo); border: 1px solid var(--borde); border-radius: 14px;
  box-shadow: 0 18px 50px -12px rgb(18 22 31 / .22), var(--sombra-md);
}
.nav-panel a {
  display: flex; flex-direction: column; gap: .1rem;
  padding: .6rem .7rem; border-radius: 9px; text-decoration: none;
}
.nav-panel a:hover { background: var(--lienzo-2); }
.nav-panel a[aria-current="page"] { background: var(--marca-tenue); }
.nav-panel a b { font-size: .93rem; font-weight: 700; color: var(--tinta); letter-spacing: -.01em; }
.nav-panel a small { font-size: .8rem; color: var(--tinta-tenue); line-height: 1.35; }
/* Los mismos destinos, como entradas de la tira: solo en móvil. */
.nav .nav-extra { display: none; }
@media (max-width: 860px) {
  .nav-explorar { display: none; }
  .nav .nav-extra { display: inline-block; }
}

/* ── Los iconos de venta ───────────────────────────────────────────────────
   Chip índigo tenue con trazo de la marca. El tamaño y el color viven aquí:
   los dibujos van en currentColor a propósito. */
.icono-venta {
  display: grid; place-items: center; flex: none;
  width: 40px; height: 40px; border-radius: 11px;
  background: var(--marca-tenue); color: var(--marca);
  margin-bottom: .25rem;
}
.icono-venta svg { width: 22px; height: 22px; }
/* Dentro de un título de panel, el chip se hace compacto y conviven en línea. */
.panel h3 .icono-venta { width: 30px; height: 30px; border-radius: 8px; display: inline-grid; vertical-align: -9px; margin: 0 .45rem 0 0; }
.panel h3 .icono-venta svg { width: 17px; height: 17px; }

/* ── Secciones más cómodas de leer ─────────────────────────────────────────
   Tres toques suaves, no una reforma: más aire entre secciones, la entradilla
   de cada tarjeta de venta con un punto más de cuerpo e interlineado, y los
   encabezados de sección con hueco claro respecto a lo anterior. */
.seccion { padding: clamp(2.6rem, 6vw, 4rem) 0; }
.venta-prueba span { font-size: .95rem; line-height: 1.55; }
.seccion h2 { margin-bottom: .35em; }
