/* ==========================================================================
   OsakiTest — design system (adapted from Claude Design "Modernist" mockup,
   opotest-blue palette). Tokens + components, plain CSS, no build step.
   ========================================================================== */

:root{

--color-bg:#eef3f8;
--color-surface:#ffffff;
--color-text:#1f2937;
--color-divider:color-mix(in srgb, #1f2937 12%, transparent);

--color-accent:#0d6efd;
--color-accent-100:#eaf2ff;
--color-accent-200:#cfe2ff;
--color-accent-300:#9ec5fe;
--color-accent-400:#6ea8fe;
--color-accent-500:#0d6efd;
--color-accent-600:#0a58ca;
--color-accent-700:#084298;
--color-accent-800:#052c65;
--color-accent-900:#03163a;

--color-neutral-100:#ffffff;
--color-neutral-200:#f3f6fb;
--color-neutral-300:#e3e9f2;
--color-neutral-400:#c7d1e0;
--color-neutral-500:#9aa7bd;
--color-neutral-600:#71809a;
--color-neutral-700:#505d75;
--color-neutral-800:#33405a;
--color-neutral-900:#1c2436;

--color-success:#198754;
--color-success-100:#e9f7ef;
--color-success-800:#0f5132;

--color-danger:#dc3545;
--color-danger-100:#fdecee;
--color-danger-800:#842029;

--color-warn:#f59e0b;
--color-warn-100:#fff7e6;
--color-warn-800:#92610a;

/* Entre el rojo de danger y el ámbar de warn: para lo que suspende de verdad,
   no solo se enfría —eso ya lo dice warn— sino que pide que se le haga caso. */
--color-alerta:#e8590c;
--color-alerta-100:#fdece2;
--color-alerta-800:#8a3308;

--series-1:#2a78d6;
--series-2:#008300;
--series-3:#e87ba4;
--series-4:#eda100;
--series-5:#1baf7a;
--series-6:#eb6834;

--font-heading:'Segoe UI', system-ui, sans-serif;
--font-body:'Segoe UI', system-ui, sans-serif;

--space-1:4px;
--space-2:8px;
--space-3:12px;
--space-4:16px;
--space-6:24px;
--space-8:32px;

--radius-sm:8px;
--radius-md:10px;
--radius-lg:18px;

--shadow-sm:0 1px 2px color-mix(in srgb, #1c2436 10%, transparent);
--shadow-md:0 3px 10px color-mix(in srgb, #1c2436 12%, transparent);
--shadow-lg:0 12px 32px color-mix(in srgb, #1c2436 20%, transparent);

}

:root[data-theme="dark"]{

--color-bg:#10141b;
--color-surface:#1a2029;
--color-text:#e8ecf3;
--color-divider:color-mix(in srgb, #e8ecf3 14%, transparent);

--color-accent:#3d8bfd;
--color-accent-100:#132840;
--color-accent-200:#1c3654;
--color-accent-300:#2f4f78;
--color-accent-400:#4f7fc4;
--color-accent-500:#3d8bfd;
--color-accent-600:#5b9dfe;
--color-accent-700:#8cbdfe;
--color-accent-800:#a9cbff;
--color-accent-900:#d6e6ff;

--color-neutral-100:#1a2029;
--color-neutral-200:#212934;
--color-neutral-300:#2b3542;
--color-neutral-400:#3d4a5c;
--color-neutral-500:#5a687d;
--color-neutral-600:#8b96a8;
--color-neutral-700:#aab4c4;
--color-neutral-800:#d7dee8;
--color-neutral-900:#05070a;

--color-success:#2fb673;
--color-success-100:#132a1e;
--color-success-800:#8fe0b4;

--color-danger:#f2626f;
--color-danger-100:#3a181b;
--color-danger-800:#ffb3ba;

--color-warn:#ffb84d;
--color-warn-100:#3a2a0d;
--color-warn-800:#ffd699;

--series-1:#3987e5;
--series-2:#008300;
--series-3:#d55181;
--series-4:#c98500;
--series-5:#199e70;
--series-6:#d95926;

--shadow-sm:0 1px 2px rgba(0,0,0,.35);
--shadow-md:0 3px 10px rgba(0,0,0,.4);
--shadow-lg:0 12px 32px rgba(0,0,0,.5);

}

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

body{
margin:0;
background:var(--color-bg);
color:var(--color-text);
font-family:var(--font-body);
font-size:15px;
line-height:1.55;
}

h1,h2,h3,h4,h5,h6{
font-family:var(--font-heading);
font-weight:700;
line-height:1.2;
margin:0 0 var(--space-2);
}
h1{font-size:34px}
h2{font-size:28px}
h3{font-size:22px}
h4{font-size:19px}
h5{font-size:16px}
h6{font-size:12px;letter-spacing:.08em;text-transform:uppercase}

p{margin:0 0 var(--space-3)}
a{color:var(--color-accent);text-decoration:none}
a:hover{text-decoration:underline}

.text-muted{color:color-mix(in srgb, var(--color-text) 55%, transparent)}
.d-none{display:none !important}
/* Párrafo largo en escritorio, resumen de una frase en móvil: para las
   explicaciones de Estadísticas, que en un móvil de verdad se comen media
   pantalla antes de llegar al dato. Los dos van en la plantilla, no uno
   armado desde JS, que es donde vive todo lo traducible. */
.texto-corto{display:none}
@media (max-width:640px){
.texto-largo{display:none}
.texto-corto{display:block}
}
/* Título de sección con una línea que lo une con la cifra de la derecha, en vez
   de dejarlas sueltas a los dos lados. La línea va como span propio en vez de
   `::after` porque tiene que quedar EN MEDIO, antes de la cifra. */
.titulo-con-linea{display:flex;align-items:center;gap:var(--space-6);margin:calc(var(--space-8) + var(--space-6)) 0 var(--space-3)}
.titulo-con-linea h2{margin:0;flex-shrink:0}
.titulo-linea{flex:1;height:1px;background:var(--color-divider)}
.titulo-con-linea-cifra{flex-shrink:0}

::-webkit-scrollbar{width:10px}
::-webkit-scrollbar-thumb{background:var(--color-neutral-400)}

/* — buttons — */
.btn{
display:inline-flex;align-items:center;justify-content:center;gap:8px;
cursor:pointer;text-decoration:none;
font-family:var(--font-heading);font-weight:700;font-size:14px;line-height:1.2;
color:var(--color-text);
background:transparent;border:1.5px solid transparent;
padding:10px 18px;border-radius:999px;
}
.btn:hover{text-decoration:none}
.btn svg{display:block;flex-shrink:0}
.btn:disabled{opacity:.45;cursor:not-allowed}
.btn-primary{background:var(--color-accent);color:#fff}
.btn-primary:hover{background:var(--color-accent-600)}
.btn-secondary{border-color:var(--color-divider);background:var(--color-surface)}
.btn-secondary:hover{background:var(--color-neutral-200)}
.btn-ghost{color:var(--color-accent)}
.btn-ghost:hover{background:var(--color-accent-100)}
.btn-icon{width:38px;height:38px;padding:0;border-radius:50%}
.btn-block{width:100%;margin-top:0}
.btn-sm{padding:6px 14px;font-size:13px}
.btn-google{border-color:var(--color-divider);background:var(--color-surface);color:var(--color-text)}
.btn-google:hover{background:var(--color-neutral-200)}
.btn-danger{border-color:var(--color-danger);color:var(--color-danger);background:transparent}
.btn-danger:hover{background:var(--color-danger);color:#fff}
.btn-warn{background:var(--color-warn);color:#fff}
.btn-warn:hover{background:color-mix(in srgb, var(--color-warn) 88%, black)}

/* Rueda dentro del propio botón: el que espera es siempre el que se acaba de
   pulsar, y así no hace falta tapar el diálogo con una capa de carga.
   Va después de :disabled a propósito, porque los dos flujos que la usan
   desactivan el botón y con opacidad .45 la rueda casi no se veía. */
.btn.is-cargando{opacity:.8;cursor:progress}
.btn.is-cargando::before{
content:"";width:14px;height:14px;flex-shrink:0;
border-radius:50%;border:2px solid currentColor;border-top-color:transparent;
animation:btn-giro .6s linear infinite;
}
@keyframes btn-giro{to{transform:rotate(360deg)}}
/* Quien prefiere no ver animaciones se queda con el aro quieto, que sigue
   diciendo que el botón está ocupado. */
@media (prefers-reduced-motion:reduce){
.btn.is-cargando::before{animation:none}
}

.auth-divider{display:flex;align-items:center;gap:12px;margin:var(--space-4) 0;font-size:12.5px;color:color-mix(in srgb, var(--color-text) 55%, transparent)}
.auth-divider::before,.auth-divider::after{content:"";flex:1;height:1px;background:var(--color-divider)}

/* — alta por pasos — */
.wizard-progress{font-size:12px;margin:0 0 var(--space-4);color:color-mix(in srgb, var(--color-text) 55%, transparent)}
.wizard-actions{display:flex;justify-content:flex-end;gap:var(--space-2);margin-top:var(--space-4)}
.wizard-actions .btn{min-width:130px}
/* Con dos botones, el de volver a la izquierda y el que avanza a la derecha */
.wizard-actions.is-doble{justify-content:space-between}
@media (max-width:480px){
.wizard-actions .btn{min-width:0;flex:1}
}

/* — documentos legales — */
.legal-nav{display:flex;flex-wrap:wrap;gap:6px;margin:var(--space-4) 0}
.legal-nav .tag{text-decoration:none;color:inherit}
.legal-nav .tag.is-active{background:var(--color-accent);color:#fff;border-color:transparent}

.legal-doc{padding:var(--space-6);margin-bottom:var(--space-8);line-height:1.65}
.legal-doc h1{font-size:28px;margin-bottom:2px}
.legal-doc h2{font-size:18px;margin:var(--space-6) 0 var(--space-2);padding-top:var(--space-3);border-top:1px solid var(--color-divider)}
.legal-doc h3{font-size:15px;margin:var(--space-4) 0 var(--space-2)}
.legal-doc p{margin:0 0 var(--space-3);font-size:14.5px}
.legal-doc ul{margin:0 0 var(--space-3);padding-left:20px;font-size:14.5px}
.legal-doc li{margin-bottom:6px}
.legal-doc code{font-size:13px;padding:1px 5px;border-radius:5px;background:var(--color-neutral-200)}
.legal-meta{font-size:12.5px;margin-bottom:var(--space-4)}
.legal-rule{border:none;border-top:1px solid var(--color-divider);margin:var(--space-6) 0}

.legal-callout{padding:var(--space-3) var(--space-4);margin:0 0 var(--space-3);border-left:3px solid var(--color-accent);border-radius:var(--radius-sm);background:var(--color-accent-100);font-size:14.5px}
.legal-form-model{padding:var(--space-4);border:1px dashed var(--color-divider);border-radius:var(--radius-sm);font-size:14px}

.legal-table{width:100%;border-collapse:collapse;margin:0 0 var(--space-4);font-size:13.5px}
.legal-table th,.legal-table td{padding:8px 10px;text-align:left;vertical-align:top;border-bottom:1px solid var(--color-divider)}
.legal-table th{font-weight:700;white-space:nowrap}
.legal-table td:first-child{white-space:normal}

.legal-links{display:flex;flex-wrap:wrap;gap:2px 10px;padding:var(--space-3) 0 0;margin-top:var(--space-2);border-top:1px solid var(--color-divider)}
.legal-links a{font-size:11.5px;color:color-mix(in srgb, var(--color-text) 55%, transparent);text-decoration:none}
.legal-links a:hover{color:var(--color-accent);text-decoration:underline}

@media (max-width:640px){
.legal-doc{padding:var(--space-4)}
.legal-table{display:block;overflow-x:auto}
}

/* — forms — */
.field{margin-bottom:var(--space-3)}
.field>label{display:block;font-size:12.5px;margin-bottom:5px;color:color-mix(in srgb, var(--color-text) 70%, transparent)}
.field-hint{font-size:12px;line-height:1.4;margin:6px 0 0;color:color-mix(in srgb, var(--color-text) 55%, transparent)}
.input{
width:100%;min-height:40px;padding:8px 14px;font:inherit;font-size:14px;
color:var(--color-text);background:var(--color-neutral-200);
border:1.5px solid var(--color-divider);border-radius:999px;
}
.input:hover{border-color:var(--color-accent-300)}
.input:focus-visible{outline:none;border-color:var(--color-accent)}
/* Una textarea con las puntas de .input redondeadas del todo (999px) se ve como
   una pastilla estirada; con varias líneas hace falta una esquina normal. Se
   puede estirar a mano, pero no sin límite: max-height la para. */
textarea.input{border-radius:var(--radius-sm);resize:vertical;max-height:320px}
/* .select-flecha (ver más abajo) es inline-flex y se encoge a su contenido: le
   vale en una fila de filtros con ancho propio, pero dentro de un .field tiene
   que ocupar todo el hueco como cualquier otro campo del formulario. */
.field .select-flecha{display:flex;width:100%}
/* Un <select> dentro de flex no se encoge por sí solo a la anchura del hueco:
   el min-width automático es el de su opción más larga, así que sin esto un
   test con un título largo lo dejaba más ancho que los demás campos. */
.field .select-flecha .input{min-width:0;flex:1}

.checkbox-list{display:flex;flex-direction:column;gap:8px}
.checkbox-item{display:flex;align-items:center;gap:8px;font-size:14px;cursor:pointer}
.checkbox-item input{width:16px;height:16px;accent-color:var(--color-accent);cursor:pointer}

/* El de «Resolver», en Fijadas y A revisar: una pastilla con un círculo en vez
   del checkbox nativo. Sin color: ni el círculo ni el rótulo llevan acento, a
   diferencia de otras pruebas de este mismo control. Solo este —el resto de
   checkboxes de la aplicación se quedan con el nativo de siempre—. */
.resolver-toggle{
display:inline-flex;align-items:center;gap:10px;
padding:6px 18px 6px 6px;border:1.5px solid var(--color-divider);border-radius:999px;
background:var(--color-surface);
}
.resolver-toggle span{color:var(--color-text);font-weight:700}
.resolver-toggle input{
appearance:none;-webkit-appearance:none;margin:0;flex-shrink:0;
width:24px;height:24px;border-radius:50%;
border:1.5px solid var(--color-divider);background:var(--color-neutral-300);
cursor:pointer;transition:background .15s ease, border-color .15s ease;
}
.resolver-toggle input:hover{border-color:var(--color-neutral-500)}
.resolver-toggle input:checked{
border-color:var(--color-neutral-900);
background:var(--color-neutral-900) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='5 13 10 18 19 7'/%3E%3C/svg%3E") center/14px no-repeat;
}

.seg{display:inline-flex;overflow:hidden;border:1.5px solid var(--color-divider);border-radius:999px}
.seg-opt{display:inline-flex;align-items:center;gap:6px;padding:8px 16px;font-size:13.5px;cursor:pointer}
.seg-opt+.seg-opt{border-left:1.5px solid var(--color-divider)}
.seg-opt input{position:absolute;opacity:0;width:0;height:0;pointer-events:none}
.seg-opt:has(input:checked){background:var(--color-accent);color:#fff}
.seg-opt:not(:has(input:checked)):hover{background:var(--color-neutral-200)}
.seg-opt:has(input:disabled){cursor:default;color:color-mix(in srgb, var(--color-text) 40%, transparent)}
/* Los cuatro tiempos del simulacro se reparten el ancho del diálogo: son cuatro
   y en un móvil se salían de la pastilla, que no parte líneas. */
#simulacro-presets{display:flex;width:100%}
#simulacro-presets .seg-opt{flex:1;justify-content:center;padding:8px 6px}

/* — cards — */
.card{
display:flex;flex-direction:column;gap:var(--space-2);
padding:var(--space-4);border-radius:var(--radius-lg);
background:var(--color-surface);border:none;
}
.card-kicker{font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--color-accent)}
.card-title{font-family:var(--font-heading);font-weight:700;font-size:17px;line-height:1.25}
.card-body{margin:0;font-size:13.5px;opacity:.8;flex:1}
.elev-sm{box-shadow:var(--shadow-sm)}
.elev-md{box-shadow:var(--shadow-md)}
.elev-lg{box-shadow:var(--shadow-lg)}

.category-icon{margin-bottom:6px;color:var(--color-accent)}
.category-icon-inline{margin-bottom:0;display:inline-flex;align-items:center}
.category-icon.is-success{color:var(--color-success)}
/* Es el color que ya tiene por defecto, pero la ficha de test pide el suyo por
   el nombre del tono: sin esta regla, «accent» sería la única clase que no
   existe y el día que cambie el color por defecto se separarían. */
.category-icon.is-accent{color:var(--color-accent)}
.category-icon.is-warn{color:var(--color-warn)}
.category-card{
position:relative;
color:inherit;text-decoration:none;cursor:pointer;
max-width:300px;width:100%;
transition:transform .15s ease, box-shadow .15s ease;
}
.category-card:hover{color:inherit;text-decoration:none;transform:translateY(-3px);box-shadow:var(--shadow-md)}
/* Cabecera de cada categoría en Aprendizaje recomendado, encima de su Repaso y
   sus marcas: lleva a la categoría entera, ya que las dos fichas de debajo
   solo cubren repaso y marcas, no temario ni estudio. */
.smart-review-cat-titulo{display:inline-flex;align-items:center;gap:var(--space-2);color:inherit;text-decoration:none}
.smart-review-cat-titulo:hover{color:var(--color-accent)}
/* Cuatro fichas por fila, en la batería de preguntas. La rejilla y no el
   flex-wrap porque con fichas sueltas cortaría por donde le tocase.
   minmax(0,250px) es el ancho de ficha de siempre como tope: sin él una
   ventana ancha las estira más de la cuenta. */
.categories-grid{
display:grid;grid-template-columns:repeat(4,minmax(0,250px));
gap:var(--space-2);margin-bottom:var(--space-6);
}
@media (max-width:1180px){
.categories-grid{grid-template-columns:repeat(3,minmax(0,250px))}
}
@media (max-width:860px){
.categories-grid{grid-template-columns:repeat(2,minmax(0,250px))}
}
@media (max-width:520px){
/* A todo el ancho y no una ficha de hasta 250px: con una sola columna esa
   ficha se quedaba estrecha, pegada a la izquierda del contenedor por
   defecto (`justify-content:start`) o, centrada, con el mismo hueco repartido
   a los dos lados. En una columna no hace falta ese tope de ancho de cuando
   competía con otras tres. El `max-width:300px` de `.category-card` es el
   mismo tope pensado para cuando hay varias por fila: sin quitarlo aquí, la
   ficha se sigue quedando corta y pegada a la izquierda en un móvil de más de
   300px de ancho útil. */
.categories-grid{grid-template-columns:1fr}
.categories-grid .category-card{max-width:none}
}

/* — lista de categorías sin sesión, solo móvil —
   Por debajo de 760px la rejilla de fichas de siempre (Inicio, Temario,
   Batería de preguntas para quien no ha iniciado sesión) se sustituye por una
   rejilla fija de dos columnas, mismo diseño de ficha que ya lleva
   `#grid-categoria` en el asistente de reto: icono en insignia arriba,
   título y «N preguntas» debajo. En escritorio la rejilla de siempre se queda
   como estaba; las dos se pintan siempre y este `display` decide cuál se ve,
   para no repintar nada al cambiar de ancho. */
.categorias-lista{display:none;grid-template-columns:repeat(2,1fr);gap:var(--space-3);margin-bottom:var(--space-6)}
/* `.tiene-lista-movil` marca la rejilla que tiene una `.categorias-lista`
   hermana al lado —Inicio, Temario y la Batería de preguntas para quien no ha
   iniciado sesión—: sin esta marca habría que apagar `.categories-grid` entera
   por debajo de 760px, y esa misma clase la usa también la rejilla de tests
   de la Batería (`#qb-tests`), que no tiene ninguna lista con la que
   sustituirse y se queda como rejilla también en móvil. */
@media (max-width:760px){
.categorias-lista{display:grid}
.categories-grid.tiene-lista-movil{display:none}
}
.categoria-fila{
display:flex;flex-direction:column;gap:6px;text-align:left;
padding:var(--space-4);border:1.5px solid var(--color-divider);
border-radius:var(--radius-lg);background:var(--color-surface);
color:inherit;text-decoration:none;cursor:pointer;
transition:border-color .15s ease, transform .15s ease;
}
.categoria-fila:hover{color:inherit;text-decoration:none;border-color:var(--color-accent);transform:translateY(-1px)}

/* — inicio: fichas de categoría —
   Dos por fila y no cuatro: llevan barra de progreso y botón a todo lo ancho,
   así que necesitan más aire que la ficha estrecha de siempre. */
.inicio-cards-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-3);margin-bottom:var(--space-6)}
@media (max-width:640px){
.inicio-cards-grid{grid-template-columns:1fr}
}
.inicio-card{
position:relative;
display:flex;flex-direction:column;gap:var(--space-3);
padding:var(--space-4);border-radius:var(--radius-lg);
background:var(--color-surface);box-shadow:var(--shadow-sm);
color:inherit;text-decoration:none;cursor:pointer;
transition:box-shadow .15s ease;
}
.inicio-card:hover{color:inherit;text-decoration:none;box-shadow:var(--shadow-md)}
/* Con una categoría de dos niveles al lado de una de cuatro, la fila del grid
   ya estira las dos fichas a la misma altura; lo que falta es que «Abrir»
   ocupe ese hueco de sobra en vez de quedarse pegado al último nivel. */
.inicio-card>.btn{margin-top:auto}
.inicio-card-cabecera{display:flex;align-items:center;gap:var(--space-3)}
.inicio-card-cabecera-texto{min-width:0}
/* Más pequeño que el resto de `.card-title` —17px— porque aquí compite con el
   icono en una ficha más baja que las de Temario. */
.inicio-card-titulo{font-size:15px}
.inicio-card-estado{margin:0;font-size:12px;opacity:.7}
.inicio-card-nivel-titulo{font-size:15px;font-weight:700;line-height:1.4;margin:0;color:var(--color-text)}
/* Mismas pastillas neutras que el resto de la aplicación (`.tag.tag-neutral`),
   no un color por dato: los tres dicen lo mismo —esto es cortito y sin
   sorpresas—, así que compiten en jerarquía con el titular si llevan acento. */
.inicio-card-nivel-chips{display:flex;flex-wrap:wrap;gap:6px}
/* Pie separado con una línea porque dejó de ser la última frase del texto:
   es la acción, y necesita leerse aparte. `margin-top:auto` para que baje al
   fondo de la ficha aunque el titular ocupe una o dos líneas. */
.inicio-card-nivel-acciones{display:flex;align-items:center;justify-content:space-between;gap:var(--space-2);margin-top:auto;padding-top:var(--space-3);border-top:1px solid var(--color-divider)}
.inicio-card-nivel-meta{font-size:12.5px;color:var(--color-neutral-600)}
/* Desglose de la categoría por bucket en vez de un dominio a secas: dos por
   fila, sin estirarse a lo ancho de su celda como haría un `.tag` en un grid
   por defecto. */
.inicio-card-chips{display:grid;grid-template-columns:repeat(2,max-content);gap:6px 10px;justify-content:start}
/* Inicio en móvil: título a tamaño completo —como en el mockup que trajo el
   usuario, sin el recorte a 15px que hace falta en escritorio para dejar
   sitio a dos fichas por fila— y «Abrir» con más aire. Solo la rejilla de
   Inicio con sesión (`#categories-grid.inicio-cards-grid`): Temario reutiliza
   la misma ficha pero no es el menú que se pidió cambiar. */
@media (max-width:760px){
#categories-grid.inicio-cards-grid .inicio-card-titulo{font-size:17px}
#categories-grid.inicio-cards-grid .inicio-card>.btn,
#categories-grid.inicio-cards-grid .inicio-card-nivel-acciones .btn{padding:13px 18px;font-size:15px}
}
/* Aprendizaje recomendado: la ficha lleva además el repaso espaciado de esa
   categoría, aparte y a la derecha, con el mismo patrón que `.marcas-card`
   —envoltura con `container-type` para que la ficha entera se estire a la
   altura de la fila de la rejilla, y `.marcas-card-divisor`/`.marcas-espaciado`
   reutilizados tal cual, con sus propios `@container` ya listos para cuando
   la ficha se estreche—. `.inicio-card-split-top` es esa fila (texto e icono a
   la izquierda, repaso espaciado a la derecha); el botón de abrir va fuera de
   ella y a todo el ancho de `.inicio-card`, porque abre la ficha entera y no
   solo su mitad izquierda. */
.inicio-card-shell{container-type:inline-size;display:flex}
/* `display:flex` en la envoltura estira la ficha a la altura de la fila de la
   rejilla (el comentario de arriba), pero el eje principal de una fila es el
   ancho: sin `flex:1` aquí, `.inicio-card` —su único hijo— se queda con el
   ancho de su contenido en vez de con el de la celda, y dos fichas de la
   rejilla con distinto texto (una con repaso espaciado, otra sin él) salían
   con anchos distintos en vez de ocupar toda la columna por igual. */
.inicio-card-shell>.inicio-card{flex:1;min-width:0}
.inicio-card.is-split{position:relative;flex-direction:column;gap:var(--space-3);padding:var(--space-4)}
.inicio-card-split-top{display:flex;gap:0;margin:calc(-1 * var(--space-4));margin-bottom:0}
.inicio-card-izquierda{flex:1;min-width:0;display:flex;flex-direction:column;gap:var(--space-3);padding:var(--space-4)}
@container (max-width:400px){
.inicio-card-split-top{flex-direction:column}
}
/* Tamaño de sobra de `.marcas-espaciado-cifra` recortado para esta ficha —el
   repaso espaciado compite aquí con «Abrir», que es la acción de verdad—; en
   móvil se recorta un poco más, ver más abajo. */
.sr-espaciado-cifra{font-size:22px}
/* Aprendizaje recomendado en móvil: ficha más visual que el reparto de
   escritorio, calcada del mockup que trajo el usuario — icono y título
   arriba, y el repaso espaciado como caja plana con la cifra a la izquierda y
   un único renglón de texto a la derecha, «Repaso espaciado · solo las que…»,
   en vez de la columna aparte con divisor y dos líneas sueltas de escritorio.
   Ese renglón único es la parte con trampa: `.marcas-espaciado` pasa a
   `display:flex` de una fila con la cifra y `.sr-espaciado-texto` como sus dos
   únicos hijos —el título y la frase, sueltos, se convertirían cada uno en su
   propia columna en vez de fluir como un mismo párrafo—, y dentro de
   `.sr-espaciado-texto` título y frase pasan a `inline` para que compongan esa
   única línea, con el punto separador puesto por CSS (`::after` en el
   título) y la mayúscula de «Solo» bajada con `::first-letter` en vez de
   duplicar la frase traducida en minúscula. Por `max-width` del viewport y no
   del `@container` de arriba: con la ficha a todo el ancho de la columna,
   entre 400 y 760px —una tablet— el contenedor todavía mide de sobra para el
   reparto de escritorio, que ahí no cabe igual de bien. */
@media (max-width:760px){
.inicio-card.is-split .inicio-card-split-top{flex-direction:column}
.inicio-card.is-split .marcas-card-divisor{display:none}
/* Sin ninguna pregunta de repaso espaciado, la caja solo repetía «0» —dato ya
   sin nada útil que decir— y encima ocupaba sitio de sobra en una ficha ya
   apretada: en escritorio la fila entera queda vacía a su lado y no estorba,
   pero en columna sí. Aquí desaparece del todo; en escritorio se sigue viendo
   deshabilitada, como el resto de estados «sin nada todavía» de la ficha. */
.inicio-card.is-split .marcas-espaciado.is-disabled{display:none}
/* `.inicio-card-split-top` sale a los bordes de la ficha con un margen
   negativo —para que `.inicio-card-izquierda` reponga su propio relleno y la
   línea divisoria de escritorio llegue de punta a punta—, pero esta caja no
   tiene ese relleno propio: sin el margen de aquí se queda pegada a los
   bordes en vez de dentro de la ficha, como el resto del contenido. */
.inicio-card.is-split .marcas-espaciado{
flex:none;display:flex;flex-direction:row;align-items:center;text-align:left;justify-content:flex-start;
gap:var(--space-3);margin:0 var(--space-4);padding:10px 12px;
border-radius:var(--radius-md);background:var(--color-neutral-200);
}
.inicio-card.is-split .sr-espaciado-cifra{flex-shrink:0;min-width:22px;font-size:18px;font-weight:800;text-align:center}
.inicio-card.is-split .sr-espaciado-texto{flex:1;min-width:0}
.inicio-card.is-split .marcas-row-titulo.is-suave{display:inline;font-weight:400;font-size:12px;color:color-mix(in srgb, var(--color-text) 55%, transparent)}
.inicio-card.is-split .marcas-row-titulo.is-suave::after{content:" · "}
.inicio-card.is-split .marcas-row-desc{display:inline;font-size:12px}
.inicio-card.is-split .marcas-row-desc::first-letter{text-transform:lowercase}
.inicio-card.is-split>.btn{padding:13px 18px;font-size:15px}
}
/* — temario: fila horizontal —
   Aquí cada categoría va sola en vez de competir por hueco en una rejilla:
   icono, título, actividad, progreso y el botón de abrir en una sola línea,
   como .fallado-card, la ficha vecina con el mismo formato. Más estrecha que
   el resto del contenido —`max-width`, no todo `.app-main-inner`— porque una
   fila de esta altura estirada a 900px deja mucho hueco vacío en el centro. */
.temario-list{display:flex;flex-direction:column;gap:var(--space-2);margin-bottom:var(--space-6);max-width:560px}
.temario-card{
display:flex;align-items:center;gap:var(--space-4);
padding:var(--space-4);border-radius:var(--radius-lg);
background:var(--color-surface);box-shadow:var(--shadow-sm);
color:inherit;text-decoration:none;cursor:pointer;
transition:box-shadow .15s ease;
}
.temario-card:hover{color:inherit;text-decoration:none;box-shadow:var(--shadow-md)}
.temario-card-icono{
flex-shrink:0;width:40px;height:40px;border-radius:var(--radius-md);
background:var(--color-accent-100);color:var(--color-accent);
display:flex;align-items:center;justify-content:center;
}
.temario-card-info{flex:1;min-width:0}
.temario-card-subtitulo{font-size:13px;opacity:.65;margin-top:2px}
/* «N temas · Sin estudiar hace N días»: la pastilla va fuera del texto
   atenuado, que si fuera su hijo heredaría la opacidad y se vería descolorida
   en vez de con el naranja de aviso de verdad. */
.temario-card-actividad{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:2px}
.temario-card-actividad .temario-card-subtitulo{margin-top:0}
/* Mismo icono y color que la ficha de Repaso, pero solo cifra y sin frase: la
   fila de Aprendizaje recomendado no tiene alto para el desglose entero, así
   que cada motivo se lee al pasar por encima (`title`). */
.temario-card-chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}
.temario-card-chip{
display:inline-flex;align-items:center;gap:5px;
padding:2px 9px 2px 2px;border-radius:999px;
background:var(--color-neutral-200);font-size:12px;
font-family:var(--font-heading);font-weight:700;
}
.temario-card-chip .sr-bucket-icono{width:18px;height:18px}
.temario-card-chip .sr-bucket-icono svg{width:11px;height:11px}
/* En la ficha de Inicio, `.category-card-link` cubre toda la tarjeta con
   `z-index:1` para que se pueda pinchar entera: sin subir el chip por encima,
   el ratón nunca llega a tocarlo y `.pista:hover` no se dispara nunca. */
.temario-card-chip.pista{position:relative;z-index:2}

/* Tema destacado de la ficha de Temario: caja de color entero en vez de la
   Composición de Inicio —aquí no hace falta el desglose de las cuatro
   cifras, con el nombre de un tema real sobra—. Fija del todo, sin JS: la
   plantilla ya manda la clase `is-<tipo>` que pone el color de la caja, del
   punto y de la etiqueta. El botón para seguir con el tema no va dentro:
   vive en `.temario-card-acciones`, junto a «Abrir». */
.temario-card-destacado{padding:var(--space-3) var(--space-4);border-radius:var(--radius-lg)}
.temario-destacado-cabecera{display:flex;align-items:center;gap:6px;margin-bottom:2px}
.temario-destacado-tipo{font-size:10.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase}
.temario-destacado-tema{font-family:var(--font-heading);font-weight:700;font-size:14.5px;line-height:1.3}
.temario-destacado-frase{font-size:12.5px;opacity:.85;margin-top:1px}

/* «Abrir» y «Seguir con el tema», uno junto al otro: el primero se estira
   —de ahí anular `.btn-block` a `width:auto` y darle `flex:1`, que si no
   ocupaba el 100% de la fila y tiraba «Seguir» fuera—, el segundo se queda
   con el ancho de su texto. */
.temario-card-acciones{display:flex;gap:10px}
.temario-card-acciones .btn-block{width:auto;flex:1}
/* Encima del enlace invisible que cubre toda la ficha (`.category-card-link`,
   `z-index:1`): sin esto el clic en «Seguir» abriría el temario de la
   categoría en vez del tema. Mismo truco que ya usa la estrella de fijar. */
.temario-destacado-boton{position:relative;z-index:2;flex-shrink:0}

.temario-card-destacado.is-aprendiendo{background:var(--color-warn-100)}
.temario-card-destacado.is-aprendiendo .temario-destacado-tipo{color:var(--color-warn-800)}
.temario-card-destacado.is-aprendiendo .temario-destacado-punto{background:var(--color-warn)}
.temario-card-destacado.is-consolidando{background:var(--color-accent-100)}
.temario-card-destacado.is-consolidando .temario-destacado-tipo{color:var(--color-accent-800)}
.temario-card-destacado.is-consolidando .temario-destacado-punto{background:var(--color-accent)}
.temario-card-destacado.is-dominado{background:var(--color-success-100)}
.temario-card-destacado.is-dominado .temario-destacado-tipo{color:var(--color-success-800)}
.temario-card-destacado.is-dominado .temario-destacado-punto{background:var(--color-success)}
.temario-card-destacado.is-empezar{background:var(--color-neutral-200)}
.temario-card-destacado.is-empezar .temario-destacado-tipo{color:var(--color-neutral-700)}
.temario-card-destacado.is-empezar .temario-destacado-punto{background:var(--color-neutral-500)}

.temario-card-progreso{flex-shrink:0;width:120px}
.temario-card-progreso .progress-track{margin-bottom:4px}
.temario-card-progreso-cifra{display:block;text-align:right;font-size:12px;opacity:.7;white-space:nowrap}
@media (max-width:700px){
.temario-card{flex-wrap:wrap}
.temario-card-progreso{width:100%;order:3}
}
@media (max-width:480px){
.temario-card{gap:var(--space-3);padding:var(--space-3)}
}
/* — test fallado: ficha horizontal —
   Es la única ficha de la página que no compite por hueco en una rejilla: va
   sola y ancha, con el icono, el texto y la acción en una sola fila para que se
   lea de un vistazo en vez de recortarse en una tarjeta vertical. */
.fallado-card{
display:flex;align-items:center;gap:var(--space-4);
padding:var(--space-4);border-radius:var(--radius-lg);
background:var(--color-surface);box-shadow:var(--shadow-sm);
}
.fallado-icono{
flex-shrink:0;width:52px;height:52px;border-radius:50%;
background:var(--color-warn-100);color:var(--color-warn);
display:flex;align-items:center;justify-content:center;
}
.fallado-info{flex:1;min-width:0}
.fallado-accion{flex-shrink:0;display:flex;align-items:center;gap:var(--space-3)}
.fallado-card.is-disabled{opacity:.6}
@media (max-width:640px){
.fallado-card{flex-wrap:wrap}
.fallado-accion{width:100%;justify-content:space-between}
}
/* — tus marcas: tarjeta con filas —
   En Aprendizaje recomendado con más de una categoría no hay una ficha propia
   donde colgar «Tus marcas» —a diferencia de smart_review_category.html, que
   la trae junto a la suya—, así que va en su propia tarjeta con una fila por
   marca: menos sitio que las tres fichas sueltas de Revisión y ya enseña las
   cifras sin tener que entrar. */
/* La ficha se parte en dos: la lista de Fijadas/A revisar a la izquierda, y
   Repaso espaciado aparte a la derecha, como una acción propia y no una fila
   más —es la única de las tres que se puede hacer ahora mismo, así que pide
   más peso que una línea igual a las otras dos. El padding baja al hijo de cada
   lado porque la ficha ya no tiene uno solo que valga para los dos. */
/* `flex-direction` y `gap` se reponen a mano: `.card` los deja en columna con
   hueco entre hijos, y aquí las dos mitades van una al lado de la otra y
   pegadas a la línea que las separa. */
/* `container-type` y no `@media`: ver el comentario de `.sr-ficha`, la ficha
   vecina con el mismo problema — la barra lateral fija le roba ancho real que
   el viewport no refleja.

   Va en `.marcas-card-shell`, la envoltura que la plantilla pone alrededor de
   `.marcas-card`, y no en `.marcas-card` mismo: `.marcas-card` es justo lo que
   cambia de `flex-direction` más abajo, y un elemento no puede reestilarse a
   sí mismo con su propio `@container` (ver el mismo comentario en `.sr-card`).
   `display:flex` en la envoltura para que `.marcas-card` —su único hijo—
   herede el estirado a la altura de la fila de la rejilla; sin él se quedaba
   con la altura de su contenido y la ficha de al lado, más alta, dejaba un
   hueco debajo. */
.marcas-card-shell{container-type:inline-size;display:flex}
.marcas-card{display:flex;flex-direction:row;gap:0;padding:0;flex:1}
.marcas-card-lista{flex:1;min-width:0;padding:var(--space-4) var(--space-4) calc(var(--space-4) - 4px)}
.marcas-card-divisor{width:1px;flex-shrink:0;background:var(--color-divider)}
.marcas-card-header{display:flex;justify-content:space-between;align-items:baseline;gap:var(--space-3);flex-wrap:wrap}
.marcas-row{
display:flex;align-items:center;gap:var(--space-3);
padding:var(--space-3) var(--space-2);margin:0 calc(-1 * var(--space-2));
border-radius:var(--radius-sm);color:inherit;text-decoration:none;cursor:pointer;
}
.marcas-row+.marcas-row{border-top:1px solid var(--color-divider)}
.marcas-row:hover{color:inherit;text-decoration:none;background:color-mix(in srgb, var(--color-text) 4%, transparent)}
.marcas-row.is-disabled{cursor:not-allowed;opacity:.55}
.marcas-row.is-disabled:hover{background:none}
/* Marca la fila cuyo panel está desplegado —un nivel de dominio en el
   carrusel de category.html, `alternarNivelCategoria`— con el mismo tinte
   que ya deja el `:hover`, para que no se pierda al levantar el dedo. */
.marcas-row.is-active{background:color-mix(in srgb, var(--color-text) 4%, transparent)}
.marcas-row-icono{
flex-shrink:0;width:34px;height:34px;border-radius:var(--radius-md);
display:flex;align-items:center;justify-content:center;
}
.marcas-row-icono.is-fijar{background:var(--color-accent-100);color:var(--color-accent)}
.marcas-row-icono.is-advertencia{background:var(--color-warn-100);color:var(--color-warn)}
.marcas-row-icono.is-repaso{background:var(--color-success-100);color:var(--color-success)}
.marcas-row-texto{flex:1;min-width:0}
.marcas-row-titulo{display:block;font-family:var(--font-heading);font-weight:700;font-size:14.5px}
/* Sin icono, la cifra grande ya es lo que llama la atención de este bloque: el
   rótulo solo la explica, así que pesa menos que en una fila de la lista. */
.marcas-row-titulo.is-suave{font-weight:600;color:color-mix(in srgb, var(--color-text) 65%, transparent)}
.marcas-row-titulo-corta{display:none}
.marcas-row-desc{display:block;font-size:12.5px;color:color-mix(in srgb, var(--color-text) 55%, transparent)}
.marcas-row-cifra{font-size:15px;font-weight:700;font-variant-numeric:tabular-nums;flex-shrink:0}
@container (max-width:400px){
.marcas-row-desc{display:none}
}
/* Repaso espaciado, aparte de la lista: icono, cifra grande y texto centrados
   en columna, no una fila más con las mismas proporciones que Fijadas y A
   revisar. Es la única acción real de las tres —a las otras dos se entra a
   mirar, a esta se entra a hacer algo—, así que pesa distinto. */
.marcas-espaciado{
display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;
gap:4px;padding:var(--space-4) var(--space-3);flex:0 0 160px;
color:inherit;text-decoration:none;cursor:pointer;
}
.marcas-espaciado:hover{color:inherit;text-decoration:none;background:color-mix(in srgb, var(--color-text) 4%, transparent)}
.marcas-espaciado.is-disabled{cursor:not-allowed;opacity:.55}
.marcas-espaciado.is-disabled:hover{background:none}
.marcas-espaciado-icono{
width:40px;height:40px;border-radius:50%;margin-bottom:2px;
background:var(--color-success-100);color:var(--color-success);
display:flex;align-items:center;justify-content:center;
}
.marcas-espaciado-cifra{font-family:var(--font-heading);font-weight:700;font-size:32px;line-height:1.1}
@container (max-width:400px){
.marcas-card{flex-direction:column}
.marcas-card-divisor{width:auto;height:1px}
.marcas-espaciado{flex:none}
}
/* Por debajo de esto «Tus marcas» deja de ser una ficha con cabecera y lista
   —no hay sitio para el título, el recuento ni las descripciones— y pasa a
   tres fichas cortas en fila, icono + etiqueta + cifra, del mismo tamaño que
   el resto de accesos rápidos del móvil. `display:contents` en
   `.marcas-card-lista` saca sus filas al nivel de `.marcas-card` para que las
   tres —las dos de la lista y «Repaso espaciado»— formen una sola fila flex;
   la cabecera y el divisor, que ya no pintan nada, se ocultan. */
@container (max-width:300px){
.marcas-card-header,.marcas-card-divisor{display:none}
.marcas-card-lista{display:contents}
/* `min-width:0` en los dos niveles: sin él, cada ficha se negaba a encogerse
   por debajo del ancho que pide su contenido —icono, etiqueta y cifra en una
   sola línea— y en vez de encogerse se salía de `.marcas-card`, que a su vez
   se salía de la rejilla y de la propia ventana. Encogidas, el texto envuelve
   a dos líneas en vez de desbordar. */
.marcas-card{flex-direction:row;gap:var(--space-2);min-width:0}
.marcas-row,.marcas-espaciado{
flex:1;min-width:0;flex-direction:row;align-items:center;justify-content:space-between;text-align:left;
gap:6px;margin:0;padding:var(--space-2);
border:1px solid var(--color-divider);border-radius:var(--radius-md);
}
.marcas-row-icono,.marcas-espaciado-icono{
width:auto;height:auto;background:none !important;border-radius:0;margin-bottom:0;
}
.marcas-row-icono svg,.marcas-espaciado-icono svg{width:18px;height:18px}
.marcas-row-texto{flex:none}
.marcas-espaciado-cifra{order:2;font-size:15px}
.marcas-espaciado .marcas-row-titulo{order:1}
.marcas-row-titulo-larga{display:none}
.marcas-row-titulo-corta{display:inline}
}

/* — Para ti — */
/* Una categoría a la vez en escritorio, con la misma fila de pestañas que
   Inicio/Temario/Aprendizaje recomendado (`.para-ti-tabs`); en móvil, un
   carrusel deslizable con el dedo, una página por categoría —mismo patrón
   que el de Temario (`.temario-movil-*`), Categoría (`.cat-movil-*`) y
   Aprendizaje recomendado (`.sr-movil-*`): scroll-snap nativo, sin JS de por
   medio para el gesto en sí (el JS de `para_ti.html` solo mantiene los
   puntos al día y ajusta el alto de la fila a la página que se ve, igual que
   en Temario). */
.para-ti-movil{display:none}
@media (max-width:760px){
.para-ti-tabs{display:none}
.para-ti-escritorio{display:none}
.para-ti-movil{display:block}
}

.para-ti-movil-puntos{display:flex;justify-content:center;gap:6px;margin-bottom:var(--space-3)}
.para-ti-movil-punto{
width:7px;height:7px;border-radius:999px;padding:0;border:0;
background:var(--color-neutral-400);cursor:pointer;
transition:width .2s ease, background .2s ease;
}
.para-ti-movil-punto.is-active{width:20px;background:var(--color-accent)}

.para-ti-movil-pistas{
display:flex;align-items:flex-start;overflow-x:auto;scroll-snap-type:x mandatory;
scrollbar-width:none;-ms-overflow-style:none;
transition:height .2s ease;
}
.para-ti-movil-pistas::-webkit-scrollbar{display:none}
.para-ti-movil-pagina{position:relative;flex:0 0 100%;min-width:0;scroll-snap-align:start;padding:0 var(--space-2)}
/* Misma cinta que Categoría/Aprendizaje recomendado/Temario —`.pin-ribbon.
   card-pin`, quiz.js ya la reconoce sola—, pegada casi al borde de la página
   y no a los 10px de la ficha de una rejilla: aquí no comparte esquina con
   ningún otro icono. */
.para-ti-movil-pagina .pin-ribbon.card-pin{top:0}

/* Sin fondo propio: va directo sobre la tarjeta blanca de la categoría, y solo
   la cifra de acierto se recorta aparte en su propia caja. */
.panel-punto-debil{
display:flex;align-items:center;justify-content:space-between;gap:var(--space-6);flex-wrap:wrap;
}
.panel-punto-debil-cuerpo{flex:2;min-width:240px}
.panel-punto-debil-kicker{
display:flex;align-items:center;gap:6px;margin-bottom:var(--space-2);
font-family:var(--font-heading);font-weight:700;font-size:11.5px;
letter-spacing:.05em;text-transform:uppercase;
color:var(--color-alerta);
}
.panel-punto-debil-titulo{font-size:21px;margin:0 0 8px}
.panel-punto-debil-desc{margin:0 0 var(--space-3);font-size:13.5px;opacity:.75;max-width:46ch}
.panel-punto-debil-acciones{display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap}
/* Botón oscuro a propósito, no `.btn-primary`: es la acción de todo el panel,
   y el azul de siempre se perdía al lado del acento de los botones de abajo. */
.panel-punto-debil-boton{background:var(--color-neutral-900);color:#fff;border-color:transparent}
.panel-punto-debil-boton:hover{background:color-mix(in srgb, var(--color-neutral-900) 85%, transparent)}
/* La caja de la cifra lleva el mismo tono de aviso que el rótulo de arriba,
   no el fondo neutro de la página: es la cifra que explica por qué esta
   categoría es «tu punto más débil», así que pesa como tal. */
.panel-punto-debil-caja{
flex-shrink:0;min-width:130px;padding:var(--space-4) var(--space-6);
border-radius:var(--radius-md);background:var(--color-alerta-100);text-align:center;
}
.panel-punto-debil-cifra{font-family:var(--font-heading);font-weight:800;font-size:34px;line-height:1;color:var(--color-alerta)}
.panel-punto-debil-caja .text-muted{color:var(--color-alerta-800);opacity:.75}
/* Solo la usa el carrusel móvil (`compacto=True` en el macro de
   `_para_ti_panel.html`): junto al título en vez de aparte en su propia
   columna —ahí no hay sitio para las dos—, y con menos aire, como en el
   mockup. */
.panel-punto-debil-fila-titulo{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}
.panel-punto-debil-caja-chip{width:auto;min-width:0;padding:8px 12px}
.panel-punto-debil-caja-chip .panel-punto-debil-cifra{font-size:26px}
.panel-punto-debil-caja-chip .text-muted{font-size:11px}
/* El botón de «Repasar N preguntas» a todo el ancho de la tarjeta, como en el
   mockup: sin la chapa con el recuento al lado —sobra, el botón ya dice
   cuántas son—, eso solo lo lleva la versión de escritorio del macro. */
.panel-punto-debil-boton-ancho{flex:1 0 100%;justify-content:center}
/* El acento de aviso pasa del rótulo a todo el borde de la tarjeta en el
   carrusel móvil, como en el mockup —en escritorio se queda solo en el
   texto—. `:has()`, que ya se usa en el resto del proyecto para esto mismo. */
.para-ti-movil-pagina .card:has(.panel-punto-debil){border-top:3px solid var(--color-alerta)}

/* El rótulo va fuera de la tarjeta de las filas, no dentro: son dos cajas
   separadas, como el punto débil y el dominio de más abajo. */
.panel-despues{margin:var(--space-6) 0 var(--space-3)}
/* Toda la fila lleva a empezar el test, no solo el botón: mismo truco que
   `.category-card-link` (enlace invisible a tamaño completo, por debajo del
   botón visible gracias al z-index), pero sobre una fila en vez de una ficha.
   Sin relleno ni margen negativo propios: la tarjeta que las envuelve no
   lleva relleno —así las filas llegan de borde a borde— y recorta las
   esquinas con `overflow:hidden`, así que la fila no necesita redondearlas. */
.panel-fila{
position:relative;
display:flex;align-items:center;justify-content:space-between;gap:var(--space-4);flex-wrap:wrap;
padding:var(--space-4);cursor:pointer;transition:transform .15s ease;
}
.panel-fila+.panel-fila{border-top:1px solid var(--color-divider)}
.panel-fila:hover{transform:translateY(-2px)}
.panel-fila-icono{
flex-shrink:0;width:34px;height:34px;border-radius:var(--radius-sm);
display:flex;align-items:center;justify-content:center;
}
.panel-fila-icono.is-warn{background:var(--color-warn-100);color:var(--color-warn)}
.panel-fila-icono.is-accent{background:var(--color-accent-100);color:var(--color-accent)}
.panel-fila-icono.is-success{background:var(--color-success-100);color:var(--color-success)}
.panel-fila-icono.is-neutral{background:var(--color-neutral-200);color:var(--color-neutral-700)}
.panel-fila-cuerpo{flex:1;min-width:220px}
.panel-fila-titulo{display:flex;align-items:center;gap:10px;flex-wrap:wrap;font-family:var(--font-heading);font-weight:700;font-size:15px}
.panel-fila-desc{margin:4px 0 0;font-size:13.5px;opacity:.75}
.panel-fila .btn{position:relative;z-index:2}

.panel-dominio{margin-top:var(--space-6)}
.panel-dominio-header{
display:flex;align-items:baseline;justify-content:space-between;gap:var(--space-3);flex-wrap:wrap;
padding-bottom:var(--space-3);border-bottom:1px solid var(--color-divider);margin-bottom:var(--space-3);
}
.panel-dominio-fila{
display:grid;grid-template-columns:220px 1fr 130px;align-items:center;gap:var(--space-3);
padding:6px var(--space-4);margin:0 calc(-1 * var(--space-4)) 4px;
color:inherit;text-decoration:none;border-radius:var(--radius-sm);transition:background .15s ease;
}
.panel-dominio-fila:hover{background:color-mix(in srgb, var(--color-text) 6%, transparent);color:inherit;text-decoration:none}
.panel-dominio-nombre{font-size:13.5px}
.panel-dominio-cifra{font-size:12.5px;font-weight:700;text-align:right;white-space:nowrap}
@media (max-width:640px){
/* La columna del porcentaje era fija (90px) y a la derecha: sin la etiqueta
   de nivel el número quedaba pegado al borde del todo, lejos de la barra a la
   que pertenece. `auto` la encoge a lo que ocupa el número y `text-align:left`
   lo deja justo después de la barra, no al otro extremo de la fila. */
.panel-dominio-fila{grid-template-columns:100px 1fr auto;gap:8px}
.panel-dominio-nombre,.panel-dominio-cifra{font-size:11.5px}
.panel-dominio-cifra{text-align:left}
/* Sin sitio para «Sólido»/«Prioritario» junto al porcentaje aquí: se salía de
   su hueco y se comía la fila de al lado. El color del nivel ya lo lleva la
   barra de progreso, así que el número solo no pierde información. */
.panel-dominio-nivel{display:none}
}

/* La cifra + flecha que sustituyen al botón de cada aviso, y el texto de
   cierre del carrusel: los pinta el macro solo con `compacto=True`, así que
   no hace falta ningún `@media` que los esconda en escritorio —ahí ni se
   pintan—. */
.panel-fila-extra{display:inline-flex;align-items:center;gap:6px;flex-shrink:0}
.panel-fila-cifra{font-family:var(--font-heading);font-weight:800;font-size:19px}
.panel-fila-cifra.is-warn{color:var(--color-warn-800)}
.panel-fila-cifra.is-accent{color:var(--color-accent-800)}
.panel-fila-cifra.is-success{color:var(--color-success-800)}
.panel-fila-cifra.is-neutral{color:var(--color-neutral-700)}
.panel-fila-flecha{color:var(--color-neutral-400)}
/* Sin el suelo de 220px de escritorio, que en una página del carrusel es casi
   todo su ancho: con un título largo dejaba a la cifra y la flecha sin sitio
   y las mandaba a su propia línea, partidas del resto por `flex-wrap`. */
.para-ti-movil-pagina .panel-fila-cuerpo{min-width:0}

/* El texto que en escritorio va una vez arriba del todo (ver `para_ti.html`)
   se repite al final de cada página del carrusel móvil, debajo de «Tu
   dominio por tema»: cada página es autónoma, no hay cabecera común bajo la
   que ponerlo una sola vez. Con su propio fondo en vez de texto suelto, para
   que no se confunda con la descripción de la categoría de más arriba. */
.para-ti-pie{
margin:var(--space-6) 0 0;padding:var(--space-3) var(--space-4);
border-radius:var(--radius-md);background:var(--color-accent-100);color:var(--color-accent-800);
font-size:13px;text-align:center;
}
/* Mismo texto en escritorio, pero suelto y sin la caja de color de arriba —ahí
   ya cierra la tarjeta de «Tu dominio por tema», que le pone su propio fondo
   detrás—; solo le hacía falta el hueco de encima, que sin esto quedaba
   pegado al borde de esa tarjeta. */
.para-ti-pie-escritorio{margin-top:var(--space-6)}

.category-card.is-disabled{opacity:.55;cursor:default;pointer-events:none}
.category-card-link{position:absolute;inset:0;z-index:1}
.card-answers-btn{position:absolute;top:10px;right:10px;z-index:2;padding:5px 14px;font-size:12px;min-height:0}
.card-warn{border:1.5px solid var(--color-warn)}
/* El simulacro se marca solo por arriba: con el borde entero de `.card-warn` se
   leía como un aviso, y no lo es —es el test a reloj—, solo el distinto de la
   fila. */
.card-cima-warn{border-top:3px solid var(--color-warn)}
.dominio-ring-wrap{position:absolute;top:10px;right:10px}
.dominio-ring circle:nth-child(2){transition:stroke-dashoffset .5s ease}

/* — tags — */
/* El gap sustituye al espacio de la palabra: al ser flex, el texto suelto que
   acompaña a un <span> o a un icono pierde sus espacios de los extremos y se
   pegaría al número ("4preguntas"). */
.tag{display:inline-flex;align-items:center;gap:4px;font-size:11.5px;letter-spacing:.02em;padding:4px 12px;border-radius:999px;font-weight:600}
.tag-btn{position:relative;z-index:2;cursor:pointer;text-decoration:none;transition:transform .15s ease, box-shadow .15s ease}
.tag-btn:hover{color:inherit;text-decoration:none;transform:translateY(-1px);box-shadow:var(--shadow-sm)}
.tag-accent{background:var(--color-accent-100);color:var(--color-accent-800)}
.tag-success{background:var(--color-success-100);color:var(--color-success-800)}
.tag-danger{background:var(--color-danger-100);color:var(--color-danger-800)}
.tag-warn{background:var(--color-warn-100);color:var(--color-warn-800)}
.tag-alerta{background:var(--color-alerta-100);color:var(--color-alerta-800)}
.tag-neutral{background:var(--color-neutral-200);color:var(--color-neutral-800)}

/* Las pastillas de "N preguntas" no se mueven ni cambian de color con el hover:
   quien se levanta es la tarjeta entera, y ellas suben con ella sin vida propia. */

@media (prefers-reduced-motion:reduce){
.select-flecha-icono{transition:none}
.category-card,.tag-btn{transition:box-shadow .15s ease, background .15s ease}
.category-card:hover,.tag-btn:hover{transform:none}
.reto-card-envoltura:hover .reto-card,.reto-card-envoltura:hover .reto-quitar{transform:none}
}

/* El tema de la pregunta que se está modificando, debajo de las opciones: el
   rótulo, la pastilla con el tema y su área en gris. El área va sin pastilla para
   que no compitan las dos y se lea «tema (de tal área)». */
.qp-tema{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin:var(--space-4) 0 0}
.qp-tema-rotulo{
font-family:var(--font-heading);font-size:11px;font-weight:700;
letter-spacing:.06em;text-transform:uppercase;color:var(--color-neutral-600);
}
.qp-tema-area{font-size:12px;color:var(--color-neutral-600)}

/* La letra de la respuesta y su texto, cada una en su columna. Iban seguidas con
   un espacio de por medio, así que la segunda línea de una respuesta larga se
   colocaba debajo de la pastilla en vez de alinearse con la primera. */
.qb-respuesta{display:flex;align-items:flex-start;gap:8px}
.qb-respuesta>.tag{flex-shrink:0}
/* El `vertical-align:middle` de toda celda es el problema, no la solución: la
   respuesta larga es la que manda el alto de la fila, así que su letra —ya
   pegada a la primera línea— cae arriba del todo, y el Nº, centrado en esa
   misma fila, se queda más abajo que ella. Arriba las dos y coinciden. */
.qb-tabla td{vertical-align:top}
/* En móvil no hay sitio para una cuarta columna, así que se quita la de «Tu
   respuesta» y la fila entera se tiñe de naranja claro para seguir diciendo
   lo mismo —esta pregunta ya no se corrige con la respuesta de la
   plataforma— sin gastar ese hueco. En escritorio la columna de siempre ya lo
   dice y la fila se queda sin teñir. */
@media (max-width:520px){
.qb-tabla .qb-col-personal{display:none}
.qb-tabla tbody tr.qb-fila-personal,
.qb-tabla tbody tr.qb-fila-personal:nth-child(even){background:var(--color-warn-100)}
}

.qb-grid-cell{display:block;color:inherit;text-decoration:none;cursor:pointer;transition:background .15s ease,color .15s ease}
.qb-grid-cell:hover{background:var(--color-accent-100) !important;color:var(--color-accent-800)}

/* — rótulo al pasar por encima — */
/* El texto sale de `data-pista` y se pinta debajo, centrado. Sustituye al
   `title` del navegador en los botones que son solo un icono: el del navegador
   tarda un segundo largo en salir, no se puede peinar y en táctil no sale nunca.

   Va en `::after` y no en un elemento aparte para que un icono suelto no
   necesite envoltura. `pointer-events:none` porque el rótulo cae justo debajo
   del botón: sin eso se come el segundo clic. `pista-dcha` es para el último
   icono de una fila, que centrado se saldría por el borde de la tarjeta. */
.pista{position:relative}
.pista::after{
content:attr(data-pista);position:absolute;top:calc(100% + 6px);left:50%;
transform:translateX(-50%) translateY(-2px);
padding:5px var(--space-2);border-radius:var(--radius-sm);
background:var(--color-neutral-900);color:#fff;
font-size:11.5px;font-weight:600;line-height:1;white-space:nowrap;
box-shadow:var(--shadow-md);
opacity:0;pointer-events:none;
transition:opacity .12s ease, transform .12s ease;
}
.pista:hover::after,
.pista:focus-visible::after{opacity:1;transform:translateX(-50%) translateY(0)}
.pista-dcha::after{left:auto;right:0;transform:translateY(-2px)}
.pista-dcha:hover::after,
.pista-dcha:focus-visible::after{transform:translateY(0)}
/* En táctil no hay ratón que pasar por encima: el `:hover` se queda pegado tras
   pulsar y el rótulo se planta encima de la respuesta hasta el siguiente toque. */
@media (hover:none){
.pista::after{content:none}
}

/* — dialog — */
.dialog-backdrop{
position:fixed;inset:0;display:flex;align-items:center;justify-content:center;
padding:var(--space-4);background:color-mix(in srgb, var(--color-neutral-900) 45%, transparent);
backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
z-index:1100;
}
/* En el navegador móvil, `backdrop-filter` sobre lo que hay detrás —la barra
   lateral entre ellos— lo repinta duplicado y como reflejado en vez de
   desenfocado: un artefacto del propio renderizador, no de este CSS. Se
   quita el `blur` y sube la capa oscura a cambio —mismo cambio y mismo
   motivo que ya usa `.sin-desenfoque` para la ayuda, solo que aquí entra
   por ancho de pantalla y no por clase, porque el fallo es de todos los
   diálogos en móvil, no solo del más largo—. */
@media (max-width:860px){
.dialog-backdrop{
background:color-mix(in srgb, var(--color-neutral-900) 58%, transparent);
backdrop-filter:none;-webkit-backdrop-filter:none;
}
}
.dialog{
position:relative;
width:min(440px,100%);display:flex;flex-direction:column;gap:var(--space-3);
padding:var(--space-6);border-radius:var(--radius-lg);
background:var(--color-surface);box-shadow:var(--shadow-lg);
max-height:86vh;overflow-y:auto;
/* Capa propia. El fondo de detrás lleva `backdrop-filter`, que es de pantalla
   completa: sin esto, cambiar el color de una fila al pasar el ratón obligaba a
   rehacer el desenfoque de toda la ventana en cada fotograma, y el encendido de
   las opciones del diálogo de retos llegaba con retraso y se arrastraba. Con el
   diálogo en su capa, lo que se repinta es solo él.

   No gasta memoria de más: mientras están cerrados, los diálogos son
   `display:none` y no tienen capa. */
will-change:transform;
}
/* La ayuda es la única ventana lo bastante larga para desplazarse, y el
   desenfoque del fondo es de pantalla completa: mientras la caja se mueve por
   encima, el navegador rehace el filtro entero en cada fotograma y el scroll se
   arrastra. Sin él, ese scroll va por el camino rápido. La capa oscura sube a
   cambio, porque sin difuminar el fondo se cuela más. */
.dialog-backdrop.sin-desenfoque{
background:color-mix(in srgb, var(--color-neutral-900) 58%, transparent);
backdrop-filter:none;-webkit-backdrop-filter:none;
}
.dialog-wide{width:min(590px,100%)}
/* La ayuda es la única con párrafos largos: 590px la deja demasiado estrecha. */
.dialog-help{width:min(650px,100%)}
.dialog-title{font-family:var(--font-heading);font-weight:700;font-size:20px;padding-right:30px}
.dialog-body{font-size:14px;opacity:.85}
.dialog-actions{display:flex;justify-content:flex-end;gap:var(--space-2);margin-top:var(--space-2)}
/* Cuando las dos opciones pesan lo mismo, repartir el ancho entero evita que la
   de confirmar quede a un lado con el texto largo desbordando la fila. */
.dialog-actions-full .btn{flex:1;justify-content:center}

/* Aviso de borrado —«Eliminar test», «Eliminar reto», y el mismo diálogo de la
   lista de retos que también sirve para «Salir del reto»—: un icono con su aro
   pulsando y el botón de confirmar relleno en vez del contorno de .btn-danger
   normal. Solo estos diálogos, no todos los que usan .dialog: ajustes o ayuda
   no borran nada. */
.dialog-alerta-cabecera{display:flex;gap:var(--space-3);align-items:flex-start}
.dialog-alerta-icono{
flex:none;width:46px;height:46px;border-radius:var(--radius-md);
background:var(--color-danger-100);color:var(--color-danger);
display:flex;align-items:center;justify-content:center;
animation:dialog-alerta-pulso 2.2s ease-out infinite;
}
@keyframes dialog-alerta-pulso{
0%{box-shadow:0 0 0 0 color-mix(in srgb, var(--color-danger) 35%, transparent)}
70%{box-shadow:0 0 0 14px color-mix(in srgb, var(--color-danger) 0%, transparent)}
100%{box-shadow:0 0 0 0 color-mix(in srgb, var(--color-danger) 0%, transparent)}
}
@media (prefers-reduced-motion:reduce){
.dialog-alerta-icono{animation:none}
}
.dialog-alerta-titulos{flex:1;min-width:0;display:flex;flex-direction:column;gap:6px}
/* En una columna flex, align-items:stretch (el valor por defecto) estira a lo
   ancho también a los hijos inline-flex como .tag: sin esto la pastilla del
   nombre ocupaba todo el hueco en vez de ceñirse a su propio texto. */
.dialog-alerta-titulos .tag{align-self:flex-start}
/* Relleno y no el contorno de .btn-danger de siempre: aquí es la única acción
   posible aparte de cancelar, y tiene que pesar como tal. */
.dialog-alerta .btn-danger{background:var(--color-danger);color:#fff;border-color:transparent}
.dialog-alerta .btn-danger:hover{background:var(--color-danger-800)}

.resumen-mejor{color:var(--color-success);font-weight:700}
.resumen-peor{color:var(--color-danger);font-weight:700}
.resumen-igual{color:var(--color-neutral-500);font-weight:700}
.resumen-nota{margin:8px 0 0;font-size:12.5px;line-height:1.45;color:color-mix(in srgb, var(--color-text) 55%, transparent)}
.resumen-eyebrow{
font-size:12px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;margin-bottom:10px;
color:color-mix(in srgb, var(--color-text) 60%, transparent);
}

/* «Progreso por dominio» y «Evolución», debajo de la cuadrícula de la
   evaluación: la sombra de `.elev-sm` apenas se nota por arriba contra el
   fondo claro de la página, así que llevan también un borde propio para que
   el filo superior se distinga sin depender de la sombra. */
#dominio-progreso,
#evolucion-test{border:1px solid var(--color-divider)}
.comparativa-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:var(--space-3);margin-bottom:var(--space-4)}
/* Cada dato en su propia tarjeta, no en un bloque gris dentro de la grande: así
   se distingue de un vistazo del texto suelto de alrededor. */
.comparativa-tile{
padding:var(--space-3);border-radius:var(--radius-md);
background:var(--color-surface);border:1px solid var(--color-divider);
}
.comparativa-tile-fila{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin:2px 0 6px}
.comparativa-tile-valor{font-family:var(--font-heading);font-weight:700;font-size:34px}
/* Fila de un nivel de dominio: el punto de color es el mismo `.legend-dot` de
   las tarjetas de categoría, así que un color cambiado ahí no se desincroniza. */
.comparativa-dominio-fila{display:flex;align-items:center;gap:8px;padding:6px 0;font-size:13px}
.comparativa-dominio-fila-etiqueta{flex:1}
/* Los mismos cuatro niveles que las filas de debajo, pero a escala y en una
   sola barra: de un vistazo se ve qué peso tiene cada uno sobre el total. Los
   tramos son hijos con su propio ancho en `style`; aquí solo el molde. */
.dominio-stack-bar{display:flex;height:8px;border-radius:999px;overflow:hidden;background:var(--color-neutral-200);margin-bottom:4px}

/* — clasificación — */
.rank-eyebrow{
font-size:12px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
color:var(--color-accent);margin-bottom:6px;
}
.rank-titulo{font-size:34px;line-height:1.1;margin:0 0 4px}
.rank-subtitulo{font-size:14px;color:var(--color-neutral-600);margin:0 0 var(--space-6)}

.rank-barra{
display:flex;justify-content:space-between;align-items:center;
gap:var(--space-3);margin-bottom:var(--space-4);flex-wrap:wrap;
}
.rank-barra-dcha{display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap}

/* Filtro de periodo: cuatro pastillas dentro de una sola pista, para que se lea
   como un interruptor y no como cuatro botones sueltos. */
.rank-periodos{
display:inline-flex;gap:6px;padding:5px;
border-radius:14px;background:var(--color-neutral-200);
}
.rank-periodo{
padding:6px 14px;border-radius:9px;
border:1px solid var(--color-divider);background:var(--color-surface);
font-size:13px;font-weight:600;color:var(--color-text);
transition:background .15s ease, color .15s ease, border-color .15s ease;
}
.rank-periodo:hover{background:var(--color-neutral-300);text-decoration:none}
.rank-periodo.is-active,
.rank-periodo.is-active:hover{
background:var(--color-accent);border-color:var(--color-accent);color:#fff;
}

.rank-buscador{position:relative;display:inline-flex;align-items:center}
.rank-buscador svg{position:absolute;left:12px;color:var(--color-neutral-500);pointer-events:none}
.rank-buscador .input{padding-left:34px;width:210px;max-width:100%}
/* La cruz nativa de type=search cambia de sitio entre navegadores y aquí no hace
   falta: el campo se vacía y la tabla se repinta sola. */
.rank-buscador .input::-webkit-search-cancel-button{display:none}

/* La tarjeta recorta: es lo que redondea las esquinas de la cabecera, y en
   pantalla estrecha lo que deja desplazar la tabla en horizontal sin sacarla
   de su marco. La cabecera no es pegajosa: se va con el scroll como el resto. */
.rank-card{overflow-x:auto;border:1px solid var(--color-divider)}
/* Hace falta border-collapse:separate para que el radio de las esquinas se
   respete; con collapse los navegadores lo ignoran. Lleva el selector de
   elemento a propósito: .table{border-collapse:collapse} se declara más abajo
   en el fichero y, a igualdad de especificidad, ganaría la última.
   Con table-layout:fixed los anchos de abajo mandan de verdad: en automático el
   navegador se los reparte por contenido y el alias se comía el sobrante. */
table.rank-table{border-collapse:separate;border-spacing:0;table-layout:fixed;min-width:720px}
/* Sin padding ni tamaño propios: hereda los de .table para que se lea igual que
   la tabla del historial. */
.rank-table thead th{
background:var(--color-surface);
border-bottom:1px solid var(--color-divider);
}
.rank-table thead th:first-child{border-top-left-radius:var(--radius-lg)}
.rank-table thead th:last-child{border-top-right-radius:var(--radius-lg)}

.rank-table tbody tr:last-child td{border-bottom:none}
/* Sin cebra: las filas se separan con la divisoria, como en el resto de fichas.
   Va con tbody para ganarle a .table sin depender del orden del fichero. */
.rank-table tbody tr:nth-child(even){background:none}
.rank-table tbody tr.rank-row:hover{background:var(--color-neutral-200)}
.rank-table tbody tr.is-me{background:var(--color-accent-100)}
.rank-table tbody tr.is-me:hover{background:var(--color-accent-200)}
.rank-table tbody tr.is-me td{font-weight:700}

/* En porcentajes y no en píxeles porque la tabla es fluida. El alias se queda
   justo: si se le deja crecer, el hueco hasta la primera cifra es un desierto. */
.rank-col-pos{width:8%}
.rank-col-alias{width:20%}
.rank-col-acc{width:16%}
.rank-col-num{width:14%;font-variant-numeric:tabular-nums}
.rank-table thead th.rank-col-pos,
.rank-table thead th.rank-col-acc,
.rank-table thead th.rank-col-num,
.rank-table tbody td.rank-col-pos,
.rank-table tbody td.rank-col-acc,
.rank-table tbody td.rank-col-num{text-align:center}
.rank-table tbody td.rank-col-num{color:var(--color-neutral-700)}
.rank-table td.rank-col-alias{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

.rank-pos{font-family:var(--font-heading);font-weight:600;color:var(--color-neutral-600)}
/* Las tres primeras llevan chapa y una banda del mismo color pegada al borde de
   la tarjeta: el podio se distingue sin llegar a leer el número. */
.rank-medalla{
display:inline-flex;align-items:center;justify-content:center;
width:24px;height:24px;border-radius:8px;
font-family:var(--font-heading);font-weight:700;font-size:12.5px;color:#fff;
}
.medalla-1{background:#e3a008}
.medalla-2{background:var(--color-neutral-500)}
.medalla-3{background:#d1743a}
.rank-row.is-podio td:first-child{box-shadow:inset 3px 0 0 var(--color-neutral-500)}
.rank-row.podio-1 td:first-child{box-shadow:inset 3px 0 0 #e3a008}
.rank-row.podio-3 td:first-child{box-shadow:inset 3px 0 0 #d1743a}

.rank-alias{display:inline-flex;align-items:center;gap:8px;font-weight:600}
.rank-you{font-size:11px;padding:1px 8px;border-radius:999px;background:var(--color-accent);color:#fff;font-weight:700}

/* Acierto: porcentaje y, apagado al lado, el número bruto del que sale. */
.rank-acc{display:inline-flex;align-items:baseline;gap:8px}
.rank-acc-pct{font-weight:700;font-variant-numeric:tabular-nums}
.rank-acc-raw{font-size:12.5px;color:var(--color-neutral-500);font-variant-numeric:tabular-nums}

.rank-corte td{text-align:center;color:var(--color-neutral-500);padding:6px}

.rank-vacio{color:var(--color-neutral-600);padding:var(--space-8);text-align:center}
/* El aviso de que sin cuenta no hay puesto: va debajo de la tabla, en fila, con
   la misma forma que las tarjetas de aviso del resto de la aplicación. */
.rank-invitado{flex-direction:row;align-items:center;gap:var(--space-4);margin-top:var(--space-4)}
.rank-invitado .gate-icon{flex-shrink:0;margin-bottom:0}
.rank-invitado-texto{flex:1;min-width:200px}
.rank-invitado .btn{flex-shrink:0}
@media (max-width:700px){
.rank-invitado{flex-wrap:wrap}
.rank-invitado .btn{width:100%}
}

.rank-pie{
display:flex;justify-content:space-between;align-items:center;
gap:var(--space-3);margin-top:var(--space-4);flex-wrap:wrap;
}
.rank-pie-texto{font-size:13px;color:var(--color-neutral-600)}
.rank-pie-enlace{
padding:0;border:0;background:none;cursor:pointer;
font-size:13px;font-weight:600;color:var(--color-accent);
}
/* Es <a> o <button> según la página que se mire: el subrayado se declara aquí
   para que las dos variantes se comporten igual al pasar por encima. */
.rank-pie-enlace:hover{text-decoration:underline}
.rank-pager{display:flex;align-items:center;gap:6px}
.rank-pager-btn{
display:inline-flex;align-items:center;justify-content:center;
min-width:36px;height:36px;padding:0 10px;
border:1px solid var(--color-divider);border-radius:var(--radius-md);
background:var(--color-surface);
font-size:14px;font-weight:600;color:var(--color-text);
transition:background .15s ease, border-color .15s ease;
}
.rank-pager-btn:hover{background:var(--color-neutral-200);text-decoration:none}
.rank-pager-btn.is-active{border-color:var(--color-text);border-width:1.5px}
.rank-pager-btn.is-disabled{opacity:.35;pointer-events:none}

/* Mientras llega el trozo nuevo la tabla se apaga en vez de vaciarse: sin salto
   de altura no hay parpadeo al filtrar. Si la espera se alarga, encima de esto
   entra el esqueleto (ver .sk), que sí sustituye a la tabla vieja. */
#rank-zona{transition:opacity .15s ease}
#rank-zona.is-cargando{opacity:.45}

.rank-th-info{display:inline-flex;align-items:center;gap:5px}
.rank-info-btn{
display:inline-flex;align-items:center;justify-content:center;
padding:0;border:0;background:none;cursor:pointer;line-height:0;
color:var(--color-accent);opacity:.7;transition:opacity .15s ease;
}
.rank-info-btn:hover{opacity:1}
.rank-info-cols{display:flex;flex-direction:column;gap:var(--space-2);margin:0}
.rank-info-cols dt{font-family:var(--font-heading);font-weight:700;font-size:13.5px}
.rank-info-cols dd{margin:1px 0 0;font-size:13px;line-height:1.45;opacity:.85}
.rank-table tr.is-flash{animation:rank-flash 1.6s ease}
@keyframes rank-flash{
0%{background:var(--color-accent-300)}
40%{background:var(--color-accent-300)}
100%{background:var(--color-accent-100)}
}

/* Lista de tarjetas para el corte móvil: por debajo de 760px la tabla no cabe
   legible y desplazarla en horizontal no lo arregla, así que aquí se sustituye
   entera por esto (oculto en escritorio; el media query de abajo cambia cuál se
   ve). Vive en esta sección y no en una propia porque son las mismas filas. */
.rank-lista{display:none;flex-direction:column;gap:8px;margin-bottom:var(--space-3)}
.rank-tarjeta{
display:flex;align-items:center;gap:12px;
padding:12px 14px;border-radius:var(--radius-lg);
border:1px solid var(--color-divider);background:var(--color-surface);
}
.rank-tarjeta.is-yo{border-color:var(--color-accent);background:var(--color-accent-100)}

/* Redonda y más grande que la chapa de la tabla: en una lista vertical el
   número de posición hace de avatar. El color del podio es el mismo que
   `.medalla-1/2/3` de la tabla de escritorio, para que sea el mismo podio. */
.rank-avatar{
display:flex;align-items:center;justify-content:center;flex-shrink:0;
width:36px;height:36px;border-radius:50%;
font-family:var(--font-heading);font-weight:700;font-size:14px;color:#fff;
}
.rank-avatar.medalla-otra{background:var(--color-neutral-300);color:var(--color-neutral-700)}
.rank-avatar.medalla-yo{background:var(--color-accent)}

.rank-tarjeta-datos{flex:1;min-width:0}
.rank-tarjeta-nombre{font-family:var(--font-heading);font-weight:700;font-size:15px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rank-tarjeta-meta{font-size:12.5px;color:var(--color-neutral-600);margin-top:1px}

.rank-tarjeta-pct{flex-shrink:0;text-align:right}
.rank-tarjeta-pct-num{display:block;font-family:var(--font-heading);font-weight:700;font-size:15px;font-variant-numeric:tabular-nums;margin-bottom:5px}
/* Sin margin-left:auto: el bloque mide lo que ocupa "81% 3856" y el número de
   aciertos lo ensancha por la derecha, así que centrada esa barra quedaba por
   debajo del número de aciertos y no del porcentaje. Empieza donde empieza el
   porcentaje porque es lo primero del bloque, no porque esté puesta a la
   izquierda a propósito. */
.rank-tarjeta-barra{display:block;width:48px;height:5px;border-radius:999px;background:var(--color-neutral-300);overflow:hidden}
.rank-tarjeta-barra-fill{display:block;height:100%;border-radius:999px;background:var(--color-accent)}
/* Sin más semántica que distinguir de un vistazo un acierto alto de uno bajo
   dentro de la propia lista. */
.rank-tarjeta-barra-fill.is-alta{background:var(--color-success)}
.rank-tarjeta-barra-fill.is-baja{background:var(--color-warn)}

/* "Ver más" alarga la lista en vez de sustituirla (ver rankVerMas en
   ranking.html): por eso no tiene ninguno de los números de página del pager
   de escritorio, solo un botón. */
.rank-vermas{
display:none;width:100%;margin-top:var(--space-2);
padding:13px;border-radius:var(--radius-lg);
border:1px solid var(--color-divider);background:var(--color-surface);
font-size:14px;font-weight:600;color:var(--color-accent);cursor:pointer;
}
.rank-vermas:hover{background:var(--color-neutral-200)}
.rank-vermas:disabled{opacity:.6;cursor:progress}

@media (max-width:760px){
.rank-titulo{font-size:30px}
.rank-barra{align-items:stretch}
.rank-barra-dcha{width:100%}
.rank-buscador{flex:1}
.rank-buscador .input{width:100%}
.rank-periodos{width:100%;justify-content:space-between}
.rank-periodo{flex:1;text-align:center;padding:7px 8px}
.rank-card{display:none}
.rank-pie{display:none}
.rank-lista{display:flex}
.rank-vermas{display:block}
}

/* — retos — */
/* 20px entre el título «Retos» y las fichas. No se suma a los 8px del margen
   inferior del título: entre hermanos en flujo normal los márgenes verticales
   colapsan y manda el mayor, así que este 20 es el que se ve. */
.retos-grid{
display:flex;flex-wrap:wrap;gap:var(--space-2);
margin-top:20px;margin-bottom:var(--space-6);
}
.reto-card-envoltura{position:relative;display:flex}
/* El hover va en la envoltura y no en la ficha: la X está encima de ella pero
   fuera de su enlace, así que posarse en el aspa no le llegaba a la tarjeta y
   esta se dejaba caer justo cuando se apunta al botón. Suben las dos juntas. */
.reto-card-envoltura:hover .reto-card{transform:translateY(-3px);box-shadow:var(--shadow-md)}
.reto-card-envoltura:hover .reto-quitar{transform:translateY(-3px)}
/* La X de quitar el reto: siempre a la vista, en gris apagado, y se pinta de
   rojo al posarse encima de ella. Va sobre el enlace de la ficha (z-index)
   porque este ocupa la tarjeta entera y si no se llevaría el clic. */
.reto-quitar{
position:absolute;top:10px;right:10px;z-index:2;
appearance:none;-webkit-appearance:none;border:none;padding:0;cursor:pointer;
width:26px;height:26px;border-radius:50%;
display:flex;align-items:center;justify-content:center;
background:transparent;color:var(--color-neutral-500);
transition:transform .15s ease, background .15s ease, color .15s ease;
}
.reto-quitar:hover{background:var(--color-danger-100);color:var(--color-danger)}
.reto-quitar:focus-visible{outline:2px solid var(--color-accent);outline-offset:2px}
.reto-opciones{display:flex;flex-direction:column;gap:var(--space-2);margin-top:var(--space-3)}
.reto-opcion{
display:flex;align-items:center;gap:10px;width:100%;text-align:left;
padding:12px 14px;border:1px solid var(--color-divider);border-radius:var(--radius-md);
background:none;cursor:pointer;color:inherit;text-decoration:none;
/* Corto a propósito: el resto de botones cambian de fondo al instante, y con
   .15s estas dos opciones se encendían más tarde que todo lo demás. */
transition:border-color .08s ease, background .08s ease;
}
/* Solo las que llevan a algún sitio: en «Eliminar test» cada fila es un div con
   su propio botón dentro, y encenderla entera la haría parecer pulsable. */
a.reto-opcion:hover,button.reto-opcion:hover{border-color:var(--color-accent);background:var(--color-neutral-200);color:inherit;text-decoration:none}
.reto-opcion>span:last-child{display:flex;flex-direction:column;flex:1}
.reto-opcion.is-danger:hover{border-color:var(--color-danger);background:color-mix(in srgb, var(--color-danger) 8%, transparent)}
/* Crear reto sin cuenta: no lleva a ningún sitio —es un div, no un enlace—, así
   que ya no se enciende solo; esto es lo que dice que además está apagada. */
.reto-opcion.is-disabled{opacity:.55;cursor:default}
/* Su rótulo (`.pista::after`) cuelga por debajo de la fila, y esa fila es la
   última: sin hueco de sobra ahí abajo, el rótulo se salía del cuadro y
   `.dialog` —que recorta y desplaza lo que no le cabe— sacaba una barra de
   scroll para enseñar cuatro píxeles de nada. Más padding que barra. */
#dialog-reto .dialog{padding-bottom:64px}
.reto-codigo{font-family:var(--font-heading);font-size:22px;letter-spacing:.28em;text-align:center}

/* El asistente ocupa la pantalla: un paso cada vez, sin nada que distraiga.
   Se apoya en el margen izquierdo, como el resto de páginas, y crece con su
   contenido en vez de estirarse: así los botones quedan justo debajo del paso y
   no clavados al fondo. */
.reto-wizard-inner{margin:0}
.reto-wizard{display:flex;flex-direction:column}
.reto-paso{flex:none}
.reto-centro{
display:flex;flex-direction:column;align-items:center;justify-content:center;
text-align:center;gap:var(--space-3);
}
.reto-paso-num{
font-family:var(--font-heading);font-weight:700;font-size:12px;
letter-spacing:.06em;text-transform:uppercase;color:var(--color-accent);
margin-bottom:var(--space-2);
}
/* El paso del nombre arranca donde arrancan los demás: centrado quedaba metido
   hacia la derecha y el asistente parecía moverse de un paso al siguiente. */
.reto-centro.is-izquierda{align-items:flex-start;text-align:left}
.reto-centro.is-izquierda .reto-titulo-input{text-align:left}
.reto-pregunta{font-size:26px;margin:0 0 4px}
.reto-titulo-input{font-size:20px;text-align:center;max-width:420px;padding:14px 18px}
.reto-aviso{margin:0;font-size:13px;color:var(--color-danger)}
/* La consecuencia de una elección, no un error: en ámbar y con el icono al lado
   del texto, no encima. `align-items:flex-start` para que en dos líneas el icono
   se quede a la altura de la primera. */
.reto-nota{
display:flex;align-items:flex-start;gap:8px;
margin:var(--space-3) 0 0;max-width:640px;
font-size:13px;line-height:1.45;color:var(--color-warn-800);
}
.reto-nota svg{flex:none;margin-top:2px;color:var(--color-warn)}
.reto-opciones-grid{
display:flex;flex-wrap:wrap;gap:var(--space-2);margin-top:var(--space-4);
}
.reto-tarjeta{
display:flex;flex-direction:column;gap:6px;width:230px;text-align:left;
padding:var(--space-4);border:1.5px solid var(--color-divider);
border-radius:var(--radius-lg);background:var(--color-surface);
cursor:pointer;color:inherit;transition:border-color .15s ease, transform .15s ease;
}
.reto-tarjeta:hover{border-color:var(--color-accent);transform:translateY(-1px)}
.reto-tarjeta.is-selected{border-color:var(--color-accent);background:var(--color-accent-100)}
.reto-tarjeta-titulo{font-family:var(--font-heading);font-weight:700;font-size:15px}
/* En móvil, tanto la lista de categorías como la de tests del asistente de
   reto pasan de fichas anchas en fila (`.reto-tarjeta` a 230px, una o dos por
   línea según cupieran) a una rejilla fija de dos columnas, con el icono en
   su misma insignia redondeada que ya usan Inicio y Temario
   (`.temario-card-icono`): caben más fichas sin desplazarse tanto y se leen
   de un vistazo. Un test suelto de alguna categoría no lleva icono
   (`iconoDeTest` en challenge_new.html) y la ficha se queda con el hueco de
   arriba vacío en vez de coja. */
@media (max-width:520px){
#grid-categoria,#lista-tests{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--space-3)}
#grid-categoria .reto-tarjeta,#lista-tests .reto-tarjeta{width:auto;gap:6px}
}
/* El nombre de ejemplo se lee como parte de la frase que lo anuncia si queda a
   6px de ella: 20px entre el texto y la pastilla (14 propios + el gap). */
.reto-tarjeta .tag{margin-top:14px}
/* Los treinta dibujos del reto. Rejilla de celdas fijas y no tarjetas como el
   resto del asistente: aquí lo que se compara es el dibujo, y con un rótulo al
   lado la elección se convertía en una lista de nombres que nadie lee. El ancho
   se limita para que no se estire hasta el borde en pantallas anchas y deje una
   sola fila larguísima. */
.reto-iconos-grid{
display:grid;grid-template-columns:repeat(auto-fill,minmax(56px,1fr));gap:var(--space-2);
width:min(560px,100%);margin-top:var(--space-4);
}
.reto-icono-opcion{
display:flex;align-items:center;justify-content:center;aspect-ratio:1;
border:1.5px solid var(--color-divider);border-radius:var(--radius-lg);
background:var(--color-surface);color:var(--color-text);
cursor:pointer;transition:border-color .15s ease, transform .15s ease;
}
.reto-icono-opcion:hover{border-color:var(--color-accent);transform:translateY(-1px)}
.reto-icono-opcion.is-selected{border-color:var(--color-accent);background:var(--color-accent-100);color:var(--color-accent-800)}
.reto-check{
display:flex;align-items:flex-start;gap:10px;cursor:pointer;
margin-top:var(--space-3);
}
.reto-check>span{display:flex;flex-direction:column}
/* La barra del tiempo por pregunta. Ancha como el campo del título para que el
   paso no se ensanche de golpe respecto al anterior. */
.reto-tiempo-ajuste{
display:flex;flex-direction:column;gap:6px;
width:min(420px,100%);margin-top:var(--space-4);
}
.reto-tiempo-valor{
font-family:var(--font-heading);font-weight:700;font-size:25px;line-height:1;
color:var(--color-accent);
}
.reto-tiempo-barra{
width:100%;height:7px;margin:0;cursor:pointer;
accent-color:var(--color-accent);background:none;
}
.reto-tiempo-extremos{
display:flex;justify-content:space-between;
font-size:12px;color:var(--color-neutral-500);
}
#tiempo-nota{margin:var(--space-2) 0 0}
.reto-config{padding:var(--space-4);margin-bottom:var(--space-3);display:flex;flex-direction:column;gap:2px}
.reto-cantidad{display:flex;align-items:center;gap:10px;margin:6px 0 0 26px}
.reto-abrir-picker{align-self:flex-start;margin:8px 0 0 26px}
.reto-barra{
display:flex;justify-content:space-between;gap:var(--space-2);
margin-top:var(--space-4);
}
/* Sin «Atrás», «Siguiente» se queda pegado al borde derecho de lo que tiene
   encima en vez de irse al lado contrario. El ancho de la barra lo fija
   ajustarBarra() en challenge_new.html, midiendo dónde acaba ese contenido. */
.reto-barra.is-solo{justify-content:flex-end}
.reto-codigo-grande{
font-family:var(--font-heading);font-weight:700;font-size:34px;letter-spacing:.18em;
color:var(--color-accent);
}
/* Las preguntas se eligen en la misma tabla que se lee en Batería de preguntas,
   con dos columnas más para meterlas y sacarlas. Las que ya están dentro se
   tiñen: la fila lo dice antes de llegar a los botones. La regla lleva el
   nth-child a cuestas porque el rayado de .table lo pinta después. */
.reto-picker-fila.is-dentro,
.table tbody tr.reto-picker-fila.is-dentro:nth-child(even){
background:var(--color-success-100);color:var(--color-success-800);
}
.reto-picker-fila td{white-space:nowrap}
.reto-picker-fila td:nth-child(2){white-space:normal;width:100%}
/* La lista de móvil, oculta por defecto: por debajo de 520px se ve ella y se
   apaga la tabla (`.reto-picker-tabla`) en vez de forzar sus filas a partirse
   en dos líneas, que dejaba rayas de borde por duplicado —la de la fila y la
   que ya pone `.table` entre filas— y una columna de respuesta mal medida,
   porque para el resto de la tabla seguía siendo una columna de verdad. Las
   dos se pintan siempre (`tablaPicker()` en challenge_new.html) y comparten
   botones a través de `par`, así que da igual cuál se vea. Una sola caja para
   todas las preguntas —no una ficha suelta por pregunta— y el número en una
   columna de ancho fijo (`grid`, no `flex`): así se lee como la tabla de
   escritorio, con el número siempre en la misma posición fila tras fila, en
   vez de una fila de tarjetas separadas. */
.reto-picker-movil{display:none}
@media (max-width:520px){
.reto-picker-tabla{display:none}
.reto-picker-movil{display:block;padding:0}
}
.reto-picker-ficha{padding:16px 14px;display:flex;flex-direction:column;gap:14px;border-top:1px solid var(--color-divider)}
.reto-picker-ficha:first-child{border-top:none}
.reto-picker-ficha.is-dentro{background:var(--color-success-100);color:var(--color-success-800)}
.reto-picker-ficha-cabecera{display:grid;grid-template-columns:22px 1fr;align-items:start;gap:10px}
.reto-picker-ficha-numero{font-weight:700}
.reto-picker-ficha-respuesta{min-width:0}
/* Los tres botones a partes iguales en todo el ancho de la ficha —no
   apretados a la izquierda—: cada uno crece lo mismo y se estira a la
   anchura que le toca. */
.reto-picker-ficha-botones{display:flex;gap:8px}
.reto-picker-ficha-botones .btn{flex:1 1 0}
.reto-picker-detalle{display:flex;flex-direction:column;gap:var(--space-3);margin-top:var(--space-3)}

.reto-codigo-banda{
display:flex;align-items:center;gap:12px;flex-wrap:wrap;
width:fit-content;max-width:100%;
margin-top:20px;padding:12px 16px;
border-radius:var(--radius-md);background:var(--color-neutral-200);
}
.reto-codigo-valor{font-family:var(--font-heading);font-weight:700;font-size:19px;letter-spacing:.05em;color:var(--color-text)}
.reto-mini-tabla{display:flex;flex-direction:column;gap:2px;width:100%;margin-top:8px}
.reto-mini-fila{display:flex;justify-content:space-between;gap:8px;font-size:12.5px;opacity:.8}
.reto-mini-fila.is-me{opacity:1;font-weight:700;color:var(--color-accent)}
.reto-mini-puntos{font-family:var(--font-heading);font-weight:700}
.reto-mini-curso{font-style:italic;font-weight:400;opacity:.75}

/* — retos: paleta propia —
   Fija y no ligada a `--color-*`: a diferencia del resto de la aplicación,
   esta pantalla no se atempera a claro/oscuro —la cabecera ya era siempre
   oscura de antes— y ahora sus tarjetas van siempre en el mismo blanco con el
   mismo acento, tal como se diseñaron. Vive aquí, junto a lo primero que la
   usa, para no dejar un bloque de variables sin dueño al principio del
   fichero. */
:root{
--reto-accent:#1d74f5;
--reto-accent-dark:#1558c4;
--reto-ink:#0f172a;
--reto-muted:#64748b;
/* Mismo color de texto que el resto de la aplicación (`--color-text`), pero
   fijo a su valor en claro y no a la variable: las tarjetas de retos van
   siempre en blanco, claro u oscuro, así que con la variable el texto se
   volvería casi blanco sobre blanco en modo oscuro. Variable aparte y no un
   alias de `--color-text`, para poder tocar solo esto si algún día la sección
   sí seguía el tema. */
--reto-title:#1f2937;
--reto-muted-soft:#475569;
--reto-line:#e6ecf3;
--reto-line-soft:#eef2f6;
--reto-surface-soft:#f8fafc;
--reto-neutral-bg:#f1f5f9;
--reto-neutral-fg:#64748b;
--reto-success-bg:#e6f4ec;
--reto-success-fg:#15734a;
--reto-warn-bg:#fdf2d4;
--reto-warn-fg:#8a6410;
--reto-warn-line:#f3e2b4;
--reto-gold-bg:#fdf2d4;--reto-gold-fg:#9a6f12;
--reto-silver-bg:#eef1f5;--reto-silver-fg:#607086;
--reto-bronze-bg:#f8e8db;--reto-bronze-fg:#9a5f2c;
}
/* Pastilla de estado —«En juego» / «Terminado»— y las tres pastillas de una
   fila de test: mismas seis combinaciones bg/fg del diseño, con un solo
   molde de pastilla para las cuatro. */
.reto-pill{
display:inline-flex;align-items:center;
font-size:11px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;
padding:5px 11px;border-radius:999px;white-space:nowrap;
}
.reto-pill.is-lg{font-size:11.5px;padding:5px 12px}
.reto-pill-success{background:var(--reto-success-bg);color:var(--reto-success-fg)}
.reto-pill-warn{background:var(--reto-warn-bg);color:var(--reto-warn-fg)}
.reto-pill-neutral{background:var(--reto-neutral-bg);color:var(--reto-neutral-fg)}
/* Pastilla informativa (preguntas, fecha…), sin color de estado. */
.reto-tag{
font-size:12.5px;font-weight:600;color:var(--reto-muted-soft);
background:var(--reto-neutral-bg);border-radius:999px;padding:6px 12px;white-space:nowrap;
}
/* Interruptor de filtro (Todos/Pendientes/Jugados): activo en tinta, no en
   acento, porque aquí compite con las pastillas de color de cada ficha y un
   azul más se perdía entre ellas. */
.reto-chip-switch{display:inline-flex;gap:6px;background:#fff;border:1px solid var(--reto-line);border-radius:999px;padding:4px}
.reto-chip{
border:none;border-radius:999px;padding:8px 15px;
font-size:13px;font-weight:700;cursor:pointer;background:transparent;color:var(--reto-muted);
transition:background .15s ease,color .15s ease;
}
.reto-chip.is-active{background:var(--reto-ink);color:#fff}
/* Interruptor de periodo (Día/Semana/Mes/Global): activo en blanco con
   sombra, la pastilla «hundida» de un segmented control, no en tinta ni en
   acento —los usa ya el de arriba y el resto de la aplicación—. */
/* `grid-template-columns` se quedó sin poner: sin ella, `display:grid` cae a
   una sola columna implícita y cada botón se apilaba en su propia fila en vez
   de formar la rejilla de 2×2 del diseño. */
.reto-period-switch{display:grid;grid-template-columns:repeat(2,1fr);gap:4px;background:var(--reto-neutral-bg);border-radius:18px;padding:4px}
.reto-period-switch.is-fila{display:inline-flex;flex-wrap:wrap}
.reto-period-btn{
display:block;border:none;border-radius:999px;padding:9px 10px;
font-size:13px;font-weight:700;text-align:center;text-decoration:none;
cursor:pointer;background:transparent;color:var(--reto-muted);
transition:background .15s ease,color .15s ease,box-shadow .15s ease;
}
.reto-period-btn:hover{text-decoration:none;color:var(--reto-title)}
.reto-period-switch.is-fila .reto-period-btn{padding:9px 18px}
.reto-period-btn.is-active{background:#fff;color:var(--reto-title);box-shadow:0 1px 3px rgba(15,23,42,.12)}

/* La cabecera de la caja de clasificación: el título y, solo en móvil, la
   píldora desplegable del periodo a su lado. En escritorio esa píldora no se
   pinta —la rejilla de cuatro botones de siempre va debajo, sin tocar—. */
.reto-clasificacion-cabecera{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:14px}
.reto-periodo-dropdown{display:none;position:relative}
.reto-periodo-actual{
display:inline-flex;align-items:center;gap:6px;
border:none;border-radius:999px;padding:8px 14px;
font-size:13px;font-weight:700;cursor:pointer;
background:var(--reto-ink);color:#fff;
}
.reto-periodo-menu{
position:absolute;top:calc(100% + 6px);right:0;z-index:5;
background:#fff;border:1px solid var(--reto-line);border-radius:14px;
box-shadow:0 8px 24px rgba(15,23,42,.14);padding:6px;min-width:140px;
}
.reto-periodo-opcion{display:block;padding:9px 12px;border-radius:10px;font-size:13.5px;font-weight:600;color:var(--reto-title);text-decoration:none}
.reto-periodo-opcion:hover{background:var(--reto-neutral-bg);color:var(--reto-title);text-decoration:none}
.reto-periodo-opcion.is-active{background:var(--reto-ink);color:#fff}
@media (max-width:520px){
.reto-periodo-dropdown{display:block}
#reto-period-switch-completo{display:none}
}
/* Chapa de posición —podio y tabla completa—: mismos tres colores en las dos
   pantallas donde aparece un ganador. */
.reto-medalla{
display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;
width:24px;height:24px;border-radius:999px;
font-family:var(--font-heading);font-weight:800;font-size:11.5px;
}
.reto-medalla.is-chica{width:20px;height:20px;font-size:11px}
.reto-medalla.is-grande{width:30px;height:30px;font-size:13px}
.reto-medalla-1{background:var(--reto-gold-bg);color:var(--reto-gold-fg)}
.reto-medalla-2{background:var(--reto-silver-bg);color:var(--reto-silver-fg)}
.reto-medalla-3{background:var(--reto-bronze-bg);color:var(--reto-bronze-fg)}
.reto-medalla-otra{background:var(--reto-neutral-bg);color:var(--reto-neutral-fg)}
/* Aro con la inicial, solo en la tabla completa: seis pares ya usados en el
   diseño, uno por posición y no por persona, para que la lista no cambie de
   color al filtrar o cambiar de periodo. */
.reto-avatar{
display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;
width:34px;height:34px;border-radius:999px;
font-family:var(--font-heading);font-weight:800;font-size:13.5px;
}
.reto-avatar-0{background:#dbeafe;color:#1d4ed8}
.reto-avatar-1{background:#fde8e8;color:#b4322f}
.reto-avatar-2{background:#e0f2ea;color:#1a7a52}
.reto-avatar-3{background:#f3e8fd;color:#7031c0}
.reto-avatar-4{background:#fdf0d9;color:#976215}
.reto-avatar-5{background:#e2f0f9;color:#1a6284}

/* — retos: lista — */
.reto-eyebrow{font-size:12px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--reto-muted);margin-bottom:6px}
/* Es un <h1>: hereda `--font-heading` y el peso 700 de la regla general
   (arriba del todo del fichero), como el resto de títulos de página
   («Clasificación», «Historial»…). El 800 y el letter-spacing negativo que
   llevaba antes eran solo de aquí y por eso se veía más «gordo» que ellos. */
.reto-lista-titulo{margin:0;color:var(--reto-title)}
/* La versión corta se pinta siempre y se oculta hasta el corte móvil, no al
   revés, para que quien tenga JS desactivado o CSS a medio cargar vea la
   frase completa por defecto. */
.reto-intro-corta{display:none}
@media (max-width:760px){
.reto-intro-larga{display:none}
.reto-intro-corta{display:block}
}
.reto-lista-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(290px,1fr));gap:16px;margin-top:20px}
.reto-lista-card{
position:relative;text-align:left;background:#fff;border:1px solid var(--reto-line);border-radius:20px;
padding:20px;display:flex;flex-direction:column;gap:14px;width:100%;
box-shadow:0 1px 2px rgba(15,23,42,.04);
transition:transform .15s ease,box-shadow .15s ease;
color:var(--reto-title);
}
.reto-lista-top{display:flex;align-items:center;gap:12px}
.reto-lista-icono{width:38px;height:38px;border-radius:12px;background:#e8f1fe;color:var(--reto-accent);display:flex;align-items:center;justify-content:center;flex-shrink:0}
/* Misma tipografía que `.card-title` en el resto de la aplicación —
   `--font-heading`, 700— y no un peso 800 sin familia propia. El color ya le
   llega de `.reto-lista-card` (`--reto-title`, ver «retos: paleta propia»). */
.reto-lista-nombre{font-family:var(--font-heading);font-size:22px;font-weight:700;letter-spacing:-.02em;overflow-wrap:anywhere}
/* Participantes/tests y la pastilla de estado en la misma fila: antes el
   estado iba junto al icono, arriba, donde competía con la X de quitar el
   reto por el mismo rincón de la tarjeta. */
.reto-lista-meta-fila{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:5px}
.reto-lista-meta{font-size:13.5px;color:var(--reto-muted)}
.reto-lista-pie{display:flex;align-items:center;justify-content:space-between;gap:8px;border-top:1px solid var(--reto-line-soft);padding-top:12px}
.reto-lista-pie-label{font-size:13px;color:var(--reto-muted);white-space:nowrap}
.reto-lista-pie-valor{font-family:var(--font-heading);font-size:15px;font-weight:700;color:var(--reto-title);white-space:nowrap}
/* La X de quitar el reto sobre la tarjeta nueva: mismo truco de siempre
   —fuera del enlace, encima con z-index—, pero en tinta clara sobre blanco,
   que es el fondo que lleva ahora la tarjeta. */
.reto-lista-envoltura{position:relative}
.reto-lista-envoltura .reto-quitar{background:var(--reto-surface-soft);color:var(--reto-muted)}
.reto-lista-envoltura .reto-quitar:hover{background:var(--reto-warn-bg);color:var(--reto-warn-fg)}
/* La X está fuera de `.reto-lista-card` (ver comentario en el HTML), así que un
   `:hover` puesto en la propia tarjeta no la alcanza: en cuanto el puntero pasa
   de la ficha al aspa, la tarjeta pierde el hover y cae de golpe. El hover va
   en la envoltura —cubre tarjeta y aspa— para que suban las dos juntas al
   posarse en cualquiera de ellas, como ya hace `.reto-card-envoltura`. */
.reto-lista-envoltura:hover .reto-lista-card{color:var(--reto-title);text-decoration:none;transform:translateY(-2px);box-shadow:0 10px 24px rgba(15,23,42,.09)}
.reto-lista-envoltura:hover .reto-quitar{transform:translateY(-2px)}

/* — retos: cabecera del reto y clasificación global —
   La cabecera va siempre sobre fondo oscuro, sea cual sea el tema: misma idea
   que `.pista::after` y `.panel-punto-debil-boton`, un bloque que corta con la
   tarjeta de alrededor en vez de mimetizarse con ella.

   `.reto-hero-bleed` la saca a todo el ancho de `.app-main`, no solo del
   contenido centrado: márgenes negativos iguales al padding de `.app-main`,
   repetidos en el único corte en el que ese padding cambia (860px). Sin esto
   la cabecera se quedaría con el mismo margen que el resto de la página y no
   llegaría a los bordes. */
.reto-hero-bleed{margin:calc(-1 * var(--space-8)) calc(-1 * var(--space-8)) 0}
@media (max-width:860px){
.reto-hero-bleed{margin:calc(-1 * var(--space-4)) calc(-1 * var(--space-3)) 0}
}
.reto-hero{
display:flex;flex-direction:column;align-items:center;gap:6px;text-align:center;
/* El padding de abajo no es un espaciado cualquiera: tiene que quedar por
   encima de lo que sube la banda del código (-40px) con margen de sobra, o la
   banda se monta encima del texto en vez de sobre el hueco vacío de debajo. */
padding:var(--space-6) var(--space-4) 72px;
background:var(--color-neutral-900);color:#fff;
}
.reto-hero-top{
display:flex;align-items:center;justify-content:space-between;gap:12px;
width:100%;max-width:900px;margin:0 auto 28px;
}
.reto-hero-volver{
display:inline-flex;align-items:center;gap:6px;
font-size:13.5px;font-weight:700;color:color-mix(in srgb, #fff 85%, transparent);
}
.reto-hero-volver:hover{color:#fff;text-decoration:none}
/* Botón de acción de la cabecera (Configuración / Salir): una pastilla apenas
   más clara que el propio fondo, no `.btn-secondary` —blanco sobre negro
   desentonaba con el resto del bloque—. */
.reto-hero-top .btn{
background:color-mix(in srgb, #fff 10%, transparent);
border-color:color-mix(in srgb, #fff 18%, transparent);color:#fff;
}
.reto-hero-top .btn:hover{background:color-mix(in srgb, #fff 16%, transparent)}
.reto-hero-icono{
width:52px;height:52px;margin-bottom:6px;border-radius:var(--radius-md);
background:color-mix(in srgb, #fff 8%, transparent);
border:1px solid color-mix(in srgb, #fff 16%, transparent);
color:var(--color-warn);
display:flex;align-items:center;justify-content:center;
}
.reto-hero-titulo{font-family:var(--font-heading);font-weight:800;font-size:clamp(28px,4.5vw,44px);line-height:1.1;margin:4px 0 0;letter-spacing:-.02em}
.reto-hero-meta{font-size:13.5px;color:color-mix(in srgb, #fff 72%, transparent);margin:4px 0 0}
.reto-hero-meta strong{color:#fff}
/* Los dos botones se quedan uno en cada margen incluso aquí: antes
   `justify-content:center` los juntaba en el medio de la cabecera, lejos de
   los bordes que marca el resto de la aplicación en móvil. */
@media (max-width:520px){
.reto-hero-top{margin-bottom:20px}
}
/* La banda del código se sube sobre el filo del fondo oscuro: mitad dentro de
   la cabecera, mitad fuera. El -40px es a propósito y no un espaciado: es la
   mitad larga de la altura de la propia banda, para que quede centrada sobre
   el borde en vez de colgando de un lado. Un único valor a cualquier ancho:
   el padding de `.reto-hero` ya deja hueco de sobra, así que no hace falta un
   segundo ajuste para el móvil. */
.reto-codigo-banda.is-flotante{
width:100%;max-width:900px;justify-content:space-between;
margin:-40px auto 0;padding:12px 22px;
border-radius:20px;background:#fff;color:var(--reto-title);
box-shadow:0 10px 30px rgba(16,24,40,.16);position:relative;z-index:2;
cursor:pointer;user-select:none;
}
/* La etiqueta y el código van juntos, pegados a la izquierda; «Copiar» es lo
   único que se separa, al otro extremo por el `justify-content` de la banda. */
.reto-codigo-grupo{display:flex;align-items:center;gap:14px}
.reto-codigo-banda.is-flotante .help-section-title{margin:0;color:var(--reto-muted)}
.reto-codigo-banda.is-flotante .reto-codigo-valor{color:var(--reto-title)}
/* Es un `span` con pinta de botón, no un botón real: el que recibe el clic (y
   el foco de teclado) es toda la banda, así que un botón anidado dentro
   duplicaría el área interactiva y el foco. */
.reto-codigo-copiar-btn{display:inline-flex;align-items:center;gap:6px;pointer-events:none}
.reto-codigo-icono{display:inline-flex}

/* Todo lo de aquí abajo va en la paleta fija de retos (`--reto-*`), no en los
   tokens de tema de la aplicación: es la misma idea que la cabecera oscura,
   una pantalla que no se atempera a claro/oscuro.

   Los tests a la izquierda y la clasificación aparte, a la derecha: es la
   misma idea que `.marcas-card`, una acción principal y algo que se consulta
   de reojo sin competir por el mismo ancho. Se apila en una columna por debajo
   de 760px, el mismo corte que ya usan Temario y la ficha de categoría. */
.reto-detalle-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(240px,300px);gap:var(--space-4);align-items:start;color:var(--reto-title)}
@media (max-width:760px){
.reto-detalle-grid{grid-template-columns:minmax(0,1fr)}
}
/* Molde de tarjeta blanca fija, para los tests y para la clasificación: el
   `.card` normal del resto de la aplicación sigue el tema, y aquí no toca. */
.reto-card{background:#fff;border:1px solid var(--reto-line);border-radius:20px;padding:18px;box-shadow:0 1px 2px rgba(15,23,42,.04)}
.reto-card.is-panel{border-radius:24px;padding:20px}
.reto-tests-lista{display:flex;flex-direction:column;gap:var(--space-2)}
/* La pestaña «Clasificación» y el escondite por pestaña (`reto-tab-oculta`)
   son solo cosa de móvil: ahí compiten por el mismo hueco tests y
   clasificación, y una decide cuál se ve. En escritorio las dos van siempre a
   la vista, cada una en su columna del grid de arriba —el botón sobra y
   `reto-tab-oculta` no debe esconder nada—, así que ninguna de las dos reglas
   existe fuera de este `@media`. */
.reto-chip-clasificacion{display:none}
@media (max-width:760px){
.reto-chip-clasificacion{display:inline-block}
.reto-tab-oculta{display:none}
/* Solo hace falta el hueco cuando las dos se apilan de verdad —clasificación
   sin pestaña que la esconda, por no haber ningún test—; con la pestaña
   activa nunca se ven las dos a la vez y el hueco de encima sobraría. */
#reto-clasificacion:not(.reto-tab-oculta){margin-top:12px}
}
/* La X de quitar vive fuera de este enlace, en `.reto-card-envoltura` (ver
   comentario en la plantilla), así que ya no es hijo directo de la lista: por
   clase y no por `>a`, que dejó de alcanzarlo. El propio hover —levantar la
   ficha— lo pone `.reto-card-envoltura:hover .reto-card` más abajo, para que
   suba a la vez que la X; aquí solo la transición, que tiene que vivir en el
   elemento que cambia. */
.reto-test-card{width:100%;color:inherit;text-decoration:none;cursor:pointer;transition:transform .15s ease,box-shadow .15s ease}
.reto-test-card:hover{color:inherit;text-decoration:none}
.reto-tests-cabecera{display:flex;justify-content:space-between;align-items:flex-end;flex-wrap:wrap;gap:10px;margin-bottom:12px}
.reto-tests-cabecera .reto-eyebrow{margin-bottom:2px}
.reto-tests-cabecera .card-title{color:var(--reto-title)}
/* El botón de «Clasificación» va pegado a los chips de filtro, no suelto al
   otro extremo de la cabecera: los dos deciden qué se ve en la misma zona de
   la pantalla, así que viajan juntos si la cabecera envuelve en una ventana
   estrecha. */
.reto-tests-filtros{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
/* Aviso de que se está en modo de quitar tests: a todo lo ancho, así que con
   `flex-wrap` de la cabecera cae en su propia línea en vez de apretarse junto
   al título o a los chips de filtro. */
.reto-borrando-aviso{
display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;
width:100%;padding:9px 14px;border-radius:var(--radius-md);
background:var(--reto-warn-bg);color:var(--reto-warn-fg);font-size:13.5px;font-weight:600;
}
/* La info del test y su caja de ganadores van lado a lado y no apilados: es la
   misma pregunta de siempre —qué es y quién va ganando— resuelta de un
   vistazo en vez de haber que desplegar la ficha para verlo. */
.reto-test-fila{display:flex;flex-wrap:wrap;gap:var(--space-4)}
.reto-test-info{flex:1 1 220px;min-width:0}
.reto-test-info .card-title{color:var(--reto-title)}
.reto-test-categoria{font-size:13.5px;color:var(--reto-muted);margin:2px 0 8px}
.reto-test-tags{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.reto-test-pie{
display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;
margin-top:12px;padding-top:12px;border-top:1px solid var(--reto-line-soft);
}
.reto-test-resultado-label{display:block;font-size:11.5px;font-weight:600;color:var(--reto-muted)}
/* Misma tipografía que `.reto-lista-pie-valor` y que `.card-title` en el resto
   de la aplicación — `--font-heading`, 700— y no un peso 800 sin familia
   propia, que es letra del sistema y se nota distinta al lado del resto. */
.reto-test-resultado-valor{font-family:var(--font-heading);font-size:15px;font-weight:700;color:var(--reto-title)}
.reto-test-ganadores{
flex:0 1 200px;min-width:160px;
background:var(--reto-surface-soft);border-radius:14px;
padding:12px 14px;align-self:stretch;
}
.reto-test-ganadores-vacio{display:flex;flex-direction:column;justify-content:center;text-align:center;background:none;border:1px dashed var(--reto-line)}
.reto-test-ganadores-vacio p{color:var(--reto-muted-soft)}
/* Borde propio en vez de `border:none` de `.card`: es lo único que distingue
   «esto te queda por jugar» de un vistazo, antes de leer la pastilla de
   estado. Ámbar clarito y no el color de aviso a secas, que a todo el borde
   de una tarjeta grande se ve más a gusto que en un texto suelto. */
.reto-test-card.is-pendiente{border-color:var(--reto-warn-line)}
/* Móvil: título/etiquetas arriba a todo el ancho, «Tu resultado» y ganadores
   en dos columnas, y el botón (Ver resultado/Empezar/…) debajo a todo el
   ancho — antes el botón quedaba pegado a «Tu resultado» y los ganadores caían
   como una franja suelta al final, sin relación visual con la puntuación.
   `.reto-test-info` y `.reto-test-pie` pasan a `display:contents`: sus hijos
   pasan a ser celdas directas de esta rejilla sin tocar el DOM, y `order` fija
   el sitio de cada uno aunque la ganadora esté fuera de `.reto-test-pie` en el
   marcado. */
@media (max-width:760px){
.reto-test-fila{display:grid;grid-template-columns:1fr 1fr;column-gap:var(--space-3)}
.reto-test-info,.reto-test-pie{display:contents}
.reto-test-fila>.reto-test-info>.card-title{grid-column:1/-1;order:1}
.reto-test-fila>.reto-test-info>.reto-test-categoria{grid-column:1/-1;order:2}
.reto-test-tags{grid-column:1/-1;order:3}
.reto-test-resultado{order:4;margin-top:12px;padding-top:12px;border-top:1px solid var(--reto-line-soft)}
.reto-test-ganadores{order:5;margin-top:12px}
.reto-test-cta{order:6;grid-column:1/-1;width:100%;text-align:center;margin-top:10px}
}
/* Fila de ganador dentro de la caja del test: chapa + nombre y puntos en dos
   líneas, igual que el podio de la clasificación de al lado —misma forma en
   los dos sitios donde aparece un ganador—. */
.reto-ganador-fila{display:flex;align-items:flex-start;gap:9px;padding:5px 0}
.reto-ganador-fila.is-me .reto-ganador-nombre{color:var(--reto-accent-dark)}
.reto-ganador-datos{display:flex;flex-direction:column;gap:0;min-width:0}
.reto-ganador-nombre{font-size:13.5px;font-weight:600;color:var(--reto-title);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.reto-ganador-fila.is-me .reto-ganador-nombre{font-weight:800}
.reto-ganador-puntos{font-family:var(--font-heading);font-size:13px;font-weight:700;color:var(--reto-title)}

.reto-pos{font-family:var(--font-heading);font-weight:600;color:var(--reto-muted);flex-shrink:0}

.reto-rank-nombre{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}
.reto-rank-alias{font-size:14px;font-weight:600;color:var(--reto-title);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.reto-rank-fila.is-me .reto-rank-alias{color:var(--reto-accent-dark);font-weight:800}
.reto-rank-fila{display:flex;align-items:center;gap:11px;padding:10px 0;border-top:1px solid var(--reto-line-soft)}
.reto-rank-fila:first-child{border-top:none;padding-top:0}
.reto-rank-puntos{font-family:var(--font-heading);font-weight:700;font-size:15px;color:var(--reto-title);font-variant-numeric:tabular-nums;flex-shrink:0}
.reto-rank-victorias{font-size:12px;color:var(--reto-muted)}

/* — retos: tabla completa — */
.reto-board-cabecera{display:flex;align-items:center;gap:8px;background:#fff;border:1px solid var(--reto-line);border-radius:999px;padding:9px 16px 9px 12px;font-size:13.5px;font-weight:700;color:var(--reto-title)}
.reto-board-cabecera:hover{background:var(--reto-surface-soft);color:var(--reto-title);text-decoration:none}
/* Mismo tamaño, peso y margen que cualquier `<h1>` de la aplicación —los de
   `h1,h2,h3...` al principio del fichero—: llevaba un tamaño, un peso y un
   `letter-spacing` propios que lo desentonaban del resto. Solo el color sigue
   siendo el de esta pantalla (`--reto-title`), igual que el resto del texto
   de aquí. */
.reto-board-titulo{color:var(--reto-title);margin-top:4px}
.reto-board-sub{font-size:14px;color:var(--reto-muted);margin-top:6px}
.reto-board-tabla{background:#fff;border:1px solid var(--reto-line);border-radius:24px;overflow:hidden;box-shadow:0 1px 2px rgba(15,23,42,.04)}
.reto-board-fila{
display:grid;grid-template-columns:56px minmax(0,1fr) 92px 96px;gap:12px;align-items:center;
padding:14px 22px;border-bottom:1px solid var(--reto-line-soft);
}
.reto-board-fila:last-child{border-bottom:none}
.reto-board-fila.is-cabecera{
background:var(--reto-surface-soft);
font-size:11.5px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:var(--reto-muted);
}
.reto-board-fila.is-me{background:#f6faff}
.reto-board-quien{display:flex;align-items:center;gap:12px;min-width:0}
.reto-board-nombre{display:block;font-size:15px;font-weight:600;color:var(--reto-title);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.reto-board-fila.is-me .reto-board-nombre{font-weight:800;color:var(--reto-accent-dark)}
.reto-board-hechos{display:block;font-size:12.5px;color:var(--reto-muted)}
.reto-board-num{text-align:right;font-size:14.5px;font-weight:700;color:var(--reto-muted-soft)}
.reto-board-puntos{font-family:var(--font-heading);text-align:right;font-size:17px;font-weight:700;letter-spacing:-.01em;color:var(--reto-title)}
@media (max-width:600px){
.reto-board-fila{grid-template-columns:40px minmax(0,1fr) 70px;padding:12px 14px}
.reto-board-fila>:nth-child(3){display:none}
}
@media (max-width:700px){
.reto-tarjeta{width:100%}
.reto-pregunta{font-size:21px}
.reto-codigo-grande{font-size:26px;letter-spacing:.1em}
}

/* — el reto jugándose — */
/* Anclado arriba y no centrado a lo alto: centrado, el panel bailaba de sitio
   según lo larga que fuera la pregunta o la tabla, y la cuenta atrás quedaba
   demasiado abajo para verla sin bajar la vista. */
.reto-juego{
display:flex;align-items:flex-start;justify-content:center;
min-height:calc(100vh - var(--space-8));padding:var(--space-3) 0 var(--space-6);
}
.reto-juego-inner{width:100%}
.reto-panel{padding:var(--space-6);gap:0}
.reto-panel .reto-centro{gap:var(--space-3);min-height:0;padding:var(--space-4) 0}
.reto-cuenta{
font-family:var(--font-heading);font-weight:700;font-size:82px;line-height:1;
color:var(--color-accent);
}
.reto-cuenta.is-tick{animation:reto-latido .6s ease}
@keyframes reto-latido{
0%{transform:scale(1.35);opacity:.35}
100%{transform:scale(1);opacity:1}
}
.reto-juego-barra{
display:flex;align-items:center;justify-content:space-between;gap:10px;
margin-bottom:var(--space-3);
}
/* Barra fina bajo la del test: se vacía en los 30 s que tarda la puntuación en
   tocar su suelo, así que lo que se ve menguar es lo que se está perdiendo.
   En los últimos 10 s se pone en rojo. */
/* El hueco va en píxeles: --space-5 no existe entre las variables, así que la
   barra se quedaba pegada al enunciado sin margen ninguno. */
.reto-tiempo-pista{
height:4px;border-radius:999px;background:var(--color-neutral-200);
overflow:hidden;margin-bottom:20px;
}
.reto-tiempo-relleno{
height:100%;width:100%;border-radius:999px;
background:var(--color-accent);transition:background .3s ease;
}
.reto-tiempo-relleno.is-agotando{background:var(--color-danger)}
.reto-enunciado{font-size:19px;line-height:1.4;margin:0 0 var(--space-4)}
/* La pastilla de la pantalla intermedia: de qué test es y por qué pregunta se
   va, en pequeño y arriba del todo, para que lo grande sea la puntuación. */
.reto-marca{
display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap;
justify-content:center;padding:7px 16px;border-radius:999px;
background:var(--color-neutral-200);
font-family:var(--font-heading);font-weight:700;font-size:12px;
letter-spacing:.06em;text-transform:uppercase;
color:color-mix(in srgb, var(--color-text) 60%, transparent);
}
.reto-ganancia{font-family:var(--font-heading);font-weight:700;font-size:60px;line-height:1;margin-top:var(--space-2)}
.reto-ganancia.is-acierto{color:var(--color-success)}
.reto-ganancia.is-fallo{color:var(--color-neutral-500)}
.reto-tabla-viva{
width:min(430px,100%);padding:2px var(--space-4);gap:0;
margin-top:var(--space-2);
display:flex;flex-direction:column;
border-radius:var(--radius-md);background:var(--color-neutral-200);
}
.reto-tabla-fila{
display:flex;align-items:center;gap:14px;padding:13px 0;font-size:14.5px;
border-bottom:1px solid var(--color-divider);
}
.reto-tabla-fila:last-child{border-bottom:none}
.reto-tabla-fila.is-me{font-weight:700;color:var(--color-accent)}
/* El número de puesto va apagado salvo en la fila propia, que se colorea
   entera: así el ojo cae en el nombre y no en la columna de cifras. */
.reto-tabla-pos{
font-family:var(--font-heading);font-weight:700;width:16px;text-align:left;
color:color-mix(in srgb, var(--color-text) 45%, transparent);
}
.reto-tabla-fila.is-me .reto-tabla-pos{color:inherit}
.reto-tabla-nombre{flex:1;text-align:left;font-weight:700}
.reto-tabla-detalle{font-size:12.5px;opacity:.7}
.reto-tabla-puntos{font-family:var(--font-heading);font-weight:700}
@media (max-width:700px){
.reto-juego{min-height:0;padding:0}
.reto-panel{padding:var(--space-4)}
.reto-cuenta{font-size:62px}
.reto-enunciado{font-size:17px}
}

/* — perfil — */
.profile-tile{
display:flex;align-items:center;gap:12px;
padding:12px 14px;margin-bottom:var(--space-3);
border-radius:var(--radius-md);background:var(--color-neutral-200);
}
.profile-avatar{
width:38px;height:38px;border-radius:50%;flex-shrink:0;
background:var(--color-accent-100);color:var(--color-accent);
display:flex;align-items:center;justify-content:center;
}
.profile-avatar.is-plain{background:var(--color-surface);border:1px solid var(--color-divider)}
.profile-avatar svg{display:block}
.profile-tile-name{font-family:var(--font-heading);font-weight:700;font-size:15px}
.profile-tile-sub{font-size:13.5px;line-height:1.4}

.profile-section{margin-top:var(--space-4)}
.profile-section-title{font-family:var(--font-heading);font-weight:700;font-size:14.5px;margin-bottom:2px}
.profile-section-hint{margin:0 0 var(--space-2);font-size:12.5px;line-height:1.45;color:color-mix(in srgb, var(--color-text) 55%, transparent)}
.profile-rule{border:none;border-top:1px solid var(--color-divider);margin:var(--space-6) 0 0}

.profile-buscador{display:flex;gap:10px;margin-bottom:var(--space-3)}
.temario-buscador{display:flex;gap:10px;max-width:420px;margin-bottom:var(--space-6)}
.profile-check-list{gap:0}
.profile-check-list .checkbox-item{padding:9px 2px;font-size:14.5px;gap:12px}
.profile-check-list .checkbox-item input{width:18px;height:18px;border-radius:var(--radius-sm)}

.btn-lg{padding:13px 18px;font-size:15px;margin-top:var(--space-6)}

/* — escaparate: datos de ejemplo animados en estadísticas — */
/* Desenfoque suave: destaca la tarjeta sin ocultar los datos ni impedir que se
   desplieguen las secciones para ver sus animaciones. */
/* Los datos son inventados: no se puede pulsar nada del fondo, solo la tarjeta
   de iniciar sesión, que va fuera de este contenedor. */
.app-main-inner.is-demo{
filter:blur(2px);
pointer-events:none;user-select:none;
}
.app-main-inner.is-demo a,
.app-main-inner.is-demo button,
.app-main-inner.is-demo select,
.app-main-inner.is-demo .attempt-row{cursor:default}


.demo-banner{
flex-direction:row;align-items:center;gap:var(--space-4);
margin-bottom:var(--space-6);
border:1.5px solid var(--color-accent-200);
}
.demo-banner .gate-icon{flex-shrink:0;margin-bottom:0}
.demo-banner-text{flex:1;min-width:200px}
.demo-banner .btn{flex-shrink:0}
@media (max-width:700px){
.demo-banner{flex-wrap:wrap}
.demo-banner .btn{width:100%}
}

.preview-gate{
position:fixed;inset:0;z-index:900;
display:flex;align-items:center;justify-content:center;
padding:var(--space-4);pointer-events:none;
}
.preview-gate-card{
pointer-events:auto;
width:min(430px,100%);gap:var(--space-3);
padding:var(--space-6);text-align:left;
}
/* Sin botón de cerrar: el hueco que .dialog-title reserva para la aspa sobra. */
.preview-gate-card .dialog-title{padding-right:0}
@media (max-width:860px){
.preview-gate{align-items:flex-start;padding-top:88px}
}

/* — ayuda: apartados del menú lateral — */
.help-section-title{
font-family:var(--font-heading);font-weight:700;font-size:12px;
letter-spacing:.06em;text-transform:uppercase;
color:color-mix(in srgb, var(--color-text) 55%, transparent);
}
.help-list{display:flex;flex-direction:column;gap:var(--space-3);margin-top:15px}
.help-item{display:flex;align-items:flex-start;gap:10px}
.help-icon{
flex-shrink:0;width:30px;height:30px;border-radius:50%;margin-top:1px;
background:var(--color-accent-100);color:var(--color-accent);
display:flex;align-items:center;justify-content:center;
}
.help-item-title{font-family:var(--font-heading);font-weight:700;font-size:14px;line-height:1.3}
.help-item-body{margin:2px 0 0;font-size:13px;line-height:1.45;opacity:.85}
/* Los 2px de arriba separan el cuerpo de su título; entre dos cuerpos del mismo
   apartado se quedan cortos y las dos ideas se leen como un bloque. */
.help-item-body+.help-item-body{margin-top:7px}
/* Las listas dentro de un apartado —lo que incluye Aprendizaje recomendado, los
   tres factores de Clasificación—: sin viñeta, que ya lo dice el espaciado, y
   con el mismo cuerpo que el resto del apartado. */
.help-item-list{list-style:none;margin:7px 0 0;padding:0;display:flex;flex-direction:column;gap:6px}
.help-item-list li{font-size:13px;line-height:1.45;opacity:.85}
.help-item-list b{opacity:1}

.dialog-close{
position:absolute;top:14px;right:14px;
appearance:none;-webkit-appearance:none;border:none;background:transparent;
width:28px;height:28px;border-radius:50%;padding:0;cursor:pointer;
display:flex;align-items:center;justify-content:center;
color:var(--color-accent);
}
.dialog-close:hover{background:var(--color-accent-100)}

/* — modal de función solo para registrados — */
.gate-icon{
width:48px;height:48px;border-radius:50%;margin-bottom:var(--space-1);
background:var(--color-accent-100);color:var(--color-accent);
display:flex;align-items:center;justify-content:center;
}
/* El aviso de que se acabó el tiempo no es una invitación a nada: en rojo, como
   el reloj justo antes de llegar a cero. */
.gate-icon.is-danger{background:var(--color-danger-100);color:var(--color-danger)}
.gate-icon.is-warn{background:var(--color-warn-100);color:var(--color-warn)}
.gate-note{margin:0;font-size:14px;font-weight:700}
.gate-points{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:10px}
.gate-point{display:flex;align-items:flex-start;gap:10px;font-size:13.5px;line-height:1.45}
.gate-check{
width:19px;height:19px;border-radius:50%;flex-shrink:0;margin-top:1px;
background:var(--color-success-100);color:var(--color-success);
display:flex;align-items:center;justify-content:center;
}

/* — table — */
.table{width:100%;border-collapse:collapse;font-size:14px}
.table th{
text-align:left;font-size:11px;letter-spacing:.06em;text-transform:uppercase;
color:color-mix(in srgb, var(--color-text) 60%, transparent);
padding:var(--space-2) var(--space-3);border-bottom:2px solid var(--color-divider);
}
.table td{padding:var(--space-3);border-bottom:1px solid var(--color-divider)}
.table tbody tr:nth-child(even){background:color-mix(in srgb, var(--color-text) 4%, transparent)}

/* — actividad por categoría —
   La fila de categoría lleva flecha y la de sus tests no, así que no comparten
   plantilla de columnas. Da igual: las cuatro cifras son de ancho fijo y el
   padding derecho es el mismo en las dos, así que el grid las ancla por la
   derecha igual de bien que si compartieran plantilla. */
.cat-activity-header,
.cat-activity-cat{
display:grid;grid-template-columns:20px minmax(0,1fr) repeat(4,84px);
column-gap:var(--space-2);align-items:center;width:100%;
padding-left:var(--space-3);padding-right:var(--space-3);
}
.cat-activity-header{
padding-top:var(--space-2);padding-bottom:var(--space-2);border-bottom:2px solid var(--color-divider);
font-size:11px;letter-spacing:.06em;text-transform:uppercase;
color:color-mix(in srgb, var(--color-text) 60%, transparent);
}
.cat-activity-cat{
background:none;border:0;border-bottom:1px solid var(--color-divider);
padding-top:var(--space-3);padding-bottom:var(--space-3);margin:0;cursor:pointer;
font:inherit;color:inherit;text-align:left;
}
.cat-activity-name{font-weight:600}
.cat-activity-num{text-align:center;font-variant-numeric:tabular-nums}
.cat-activity-pct{font-weight:700}
.cat-activity-caret{transition:transform .15s ease}
.cat-activity-cat.is-open .cat-activity-caret{transform:rotate(90deg)}
/* Resaltada mientras está abierta, con el filo que ya usa la fila señalada de
   Temario: así se ve de un vistazo qué categoría se está mirando. */
.cat-activity-cat.is-open{
background:color-mix(in srgb, var(--color-text) 4%, transparent);
box-shadow:inset 3px 0 0 var(--color-neutral-900);
}
.cat-activity-tests{padding:var(--space-2) var(--space-3) var(--space-3) 40px;border-bottom:1px solid var(--color-divider)}
.cat-activity-tests-label{font-size:10.5px;letter-spacing:.06em;text-transform:uppercase;color:var(--color-neutral-600);margin:0 0 6px}
.cat-activity-test-row{
display:grid;grid-template-columns:minmax(0,1fr) repeat(4,84px);
column-gap:var(--space-2);align-items:center;width:100%;padding:6px var(--space-2);
margin:0 calc(-1 * var(--space-2));border-radius:var(--radius-sm);
}
/* En escritorio, `width:100%` calculaba el ancho de la fila sobre el hueco de
   `.cat-activity-tests` (con su indentado de 40px a la izquierda), y el
   margen negativo simétrico no compensa ese hueco asimétrico —12px de
   `--space-3` a la derecha, no los 8px de `--space-2` que sí cancela a la
   izquierda—: las cuatro cifras del test acababan 16px a la izquierda de las
   de su categoría, en vez de en la misma columna. Con `width:auto`, el ancho
   ya no está fijado de antemano: lo calcula el margen negativo de cada lado
   contra el hueco real que le queda, así que la fila crece lo que hace falta
   para que sus columnas terminen donde terminan las de la cabecera. Solo
   aquí: en móvil el ancho tenía que seguir siendo el 100% de siempre. */
@media (min-width:641px){
.cat-activity-test-row{width:auto}
}
.cat-activity-test-row:hover{background:color-mix(in srgb, var(--color-text) 6%, transparent)}
.cat-activity-test-row .cat-activity-name{font-weight:400}
/* Aciertos y fallos aparte, más el ratio de cada test y el rótulo corto de
   cabecera: piezas que solo existen para el móvil de aquí abajo, calcado del
   mockup que trajo el usuario. Ocultas por defecto para no duplicar nada en
   escritorio, donde ya hay columna propia para cada cifra. */
.cat-activity-col-corta,
.cat-activity-resumen,
.cat-activity-ratio{display:none}
@media (max-width:640px){
/* Con caret+nombre+4 columnas de cifras no cabía nada legible en un móvil de
   verdad —de ahí el `overflow-x:auto` de la ficha entera—; aquí se enseñan
   solo dos cifras (respondidas y % de acierto) en la fila, y aciertos/fallos
   se leen en `.cat-activity-resumen` al desplegar la categoría, como en el
   mockup. Mismo truco en cada test: sin sitio para tres columnas más, el
   ratio «aciertos/respondidas» las sustituye por una sola. */
.cat-activity-header,
.cat-activity-cat{grid-template-columns:20px minmax(0,1fr) repeat(2,58px);font-size:12.5px}
.cat-activity-col-aciertos,
.cat-activity-col-fallos{display:none}
.cat-activity-col-larga{display:none}
.cat-activity-col-corta{display:inline}
.cat-activity-resumen{
display:flex;gap:14px;padding:0 0 var(--space-2);font-size:12.5px;
}
.cat-activity-resumen-ok{color:var(--color-success-800)}
.cat-activity-resumen-ko{color:var(--color-danger-800)}
.cat-activity-test-row{grid-template-columns:minmax(0,1fr) auto 58px}
.cat-activity-test-row .cat-activity-col-respondidas{display:none}
.cat-activity-ratio{display:block;font-size:11.5px;color:var(--color-neutral-600);font-variant-numeric:tabular-nums}
.cat-activity-tests{padding-left:26px}
}

/* — esqueletos de carga —
   Barras grises con la forma de lo que se está esperando. Se usan cuando la
   tabla tarda en llegar: en la clasificación, mientras se pide el trozo nuevo;
   en el historial, mientras el navegador espera a la página siguiente. La
   plantilla del esqueleto vive junto a la tabla que imita, para que las dos
   cambien a la vez. */
.sk{
display:block;border-radius:var(--radius-sm);
background-color:var(--color-neutral-300);
background-image:linear-gradient(
90deg,
transparent 0%,
color-mix(in srgb, var(--color-neutral-100) 65%, transparent) 50%,
transparent 100%);
background-size:220% 100%;background-repeat:no-repeat;
animation:sk-brillo 1.3s ease-in-out infinite;
}
/* El alto y los márgenes salen del alto real de una celda (14px de texto más
   12px de relleno arriba y abajo): así el esqueleto no cambia la altura de la
   tarjeta cuando entran los datos de verdad. */
.sk-linea{height:12px;margin:4px 0;width:var(--sk-ancho,100%)}
.sk-chapa{width:24px;height:24px;border-radius:8px;margin:4px auto}
.sk-centro{margin-left:auto;margin-right:auto}
@keyframes sk-brillo{
from{background-position:120% 0}
to{background-position:-120% 0}
}
/* Quien prefiere no ver animaciones se queda con las barras quietas: siguen
   diciendo que ahí va a haber contenido. */
@media (prefers-reduced-motion:reduce){
.sk{animation:none;background-image:none}
}
/* La cabecera del esqueleto se apaga: los rótulos son de verdad y, a pleno
   color, parecerían una tabla ya cargada. */
.sk-tabla thead th{opacity:.55}
.sk-tabla tbody tr:nth-child(even){background:none}
.sk-tabla tbody tr:last-child td{border-bottom:none}

/* — pestañas de categoría — */
/* La de dentro es una ficha blanca pegada a la línea, como las lengüetas de una
   carpeta —redondeada solo por arriba—; las otras, texto suelto sobre el fondo.
   No se envuelven en varias filas: con muchas categorías se arrastra la fila de
   lado, que deja la pantalla donde estaba en vez de empujar el título abajo. */
.pestanas{
display:flex;gap:2px;margin-bottom:var(--space-6);
border-bottom:1px solid var(--color-divider);
overflow-x:auto;scrollbar-width:none;
}
.pestanas::-webkit-scrollbar{display:none}
/* `.pestana` es ahora el envoltorio —solo forma y borde, `position:relative`
   para la cinta— y `.pestana-link` lleva el texto y el hueco de siempre: dos
   acciones en la misma lengüeta (abrir, fijar) no caben en un único enlace.
   `border-radius:inherit` en el enlace: si no, su propio fondo cuadrado
   sobresaldría por la esquina redondeada del envoltorio. */
.pestana{
position:relative;flex:none;
border-radius:var(--radius-md) var(--radius-md) 0 0;
border:1.5px solid transparent;border-bottom:none;
}
.pestana-link{
display:block;padding:10px 18px;white-space:nowrap;
font-family:var(--font-heading);font-weight:600;font-size:14px;
color:var(--color-neutral-600);border-radius:inherit;
}
.pestana-link:hover{color:var(--color-text);text-decoration:none;background:color-mix(in srgb, var(--color-text) 5%, transparent)}
/* El borde inferior de la fila se tapa con uno propio del color del fondo: sin
   esto la lengüeta activa queda cruzada por la línea en vez de abrirse a ella. */
.pestana.is-active{
border-color:var(--color-divider);
box-shadow:0 -1px 0 var(--color-surface) inset;
margin-bottom:-1px;
}
/* El hueco de la cinta (solo la activa la lleva) va aquí y no en `.pestana-link`
   a secas: las demás pestañas no necesitan sitio para nada. */
.pestana.is-active .pestana-link{background:var(--color-surface);color:var(--color-text);font-weight:700;padding:10px 30px 11px 18px}
/* — cinta de categoría fijada —
   Fijar la pestaña activa la guarda en `sessionStorage` (quiz.js) y hace que
   Inicio, Temario y Aprendizaje recomendado salten directos a ella la próxima
   vez, sin pasar por su menú de elegir categoría. Icono de marcador —hueco sin
   fijar, relleno del color de acento al fijarlo—, no una caja: es la única
   pestaña que lo lleva, así que no hace falta que destaque como una pieza más
   de la fila.

   No lleva `.pista`: `.pestanas` necesita `overflow-x:auto` para las
   categorías que no caben en una fila, y con un eje en `auto` el navegador
   pone el otro en `auto` también aunque no se le pida —de sobra comprobado, no
   es un despiste—, así que el rótulo de `.pista` (absoluto, colgado del propio
   botón) se recortaría contra esa caja. Su rótulo es `.pin-tooltip`: un único
   elemento compartido que quiz.js coloca con `position:fixed` según la
   posición del botón (`mostrarPinTooltip`), así queda fuera de esa caja. */
.pin-ribbon{
position:absolute;top:6px;right:7px;z-index:1;
width:15px;height:15px;padding:0;border:none;cursor:pointer;
background:none;display:flex;
color:var(--color-neutral-400);
transition:color .15s ease;
}
.pin-ribbon svg{width:100%;height:100%}
.pin-ribbon:hover{color:var(--color-accent)}
/* Mismo aspecto que `.pista::after` pero como elemento propio y no `::after`:
   necesita `position:fixed`, y las coordenadas fijas las pone JS (no hay forma
   de expresar en CSS puro "debajo de este botón" fuera del flujo normal). */
.pin-tooltip{
position:fixed;padding:5px var(--space-2);border-radius:var(--radius-sm);
background:var(--color-neutral-900);color:#fff;
font-size:11.5px;font-weight:600;line-height:1;white-space:nowrap;
box-shadow:var(--shadow-md);
opacity:0;pointer-events:none;z-index:1200;
transform:translate(-50%,-2px);
transition:opacity .12s ease, transform .12s ease;
}
.pin-tooltip.is-visible{opacity:1;transform:translate(-50%,0)}
/* En táctil no hay ratón que pasar por encima: el toque deja el tooltip
   plantado hasta el siguiente, como le pasaría a `.pista` (ver arriba). */
@media (hover:none){
.pin-tooltip{display:none}
}
.pin-ribbon.is-fijada{color:var(--color-accent)}
.pin-ribbon.is-fijada svg path{fill:currentColor}
/* — fijar categoría desde la ficha, en móvil —
   En escritorio, fijar una categoría se hace desde su pestaña (arriba), ya
   dentro de la ficha de esa categoría. En móvil no hay pestañas —no caben, y
   para eso está esta estrella— así que hace falta fijar sin entrar primero:
   la misma cinta (`.pin-ribbon`, quiz.js ya la reconoce por la clase, sin
   tocar JS) pero como botón propio en la esquina de la ficha de Inicio,
   Aprendizaje recomendado y Temario, más grande porque aquí es el dedo el que
   apunta, no el ratón. Oculta en escritorio: ahí ya está la vía de siempre, y
   dos formas de fijar lo mismo en la misma pantalla solo confunden.
   `.inicio-card`/`.inicio-card.is-split` ya son `position:relative`, así que
   la estrella se coloca contra la ficha entera sin envoltorio nuevo. */
.pin-ribbon.card-pin{
display:none;top:10px;right:10px;z-index:2;
width:30px;height:30px;padding:7px;border-radius:50%;
background:var(--color-accent-100);color:var(--color-neutral-500);
}
.pin-ribbon.card-pin.is-fijada{background:var(--color-accent);color:#fff}
@media (max-width:760px){
.pin-ribbon.card-pin{display:flex}
}
/* En los carruseles de una sola categoría (Categoría, Aprendizaje recomendado,
   Temario) la cinta se sube más que en la ficha de la rejilla de arriba: aquí
   no comparte esquina con ningún icono, así que se pega casi al borde de la
   página en vez de quedarse a 10px. */
.cat-movil-pagina .pin-ribbon.card-pin,
.sr-movil-pagina .pin-ribbon.card-pin,
.temario-movil-pagina .pin-ribbon.card-pin{top:0}

/* — aviso de categoría fijada, en móvil —
   Sube desde abajo al fijar con la estrella grande (`.card-pin`) y se retira
   solo (`mostrarPinAviso` en quiz.js); quitar una categoría no enseña nada.
   Oculto por defecto y solo por debajo de 760px, el mismo corte que ya usa
   `.card-pin`: la estrella de la pestaña de escritorio no dispara este aviso
   —fijar ahí ya pasa dentro de la ficha de la categoría—, pero por si acaso
   se redimensiona la ventana con el aviso a medio salir, se corta por CSS y
   no solo dejando de llamar a la función. */
.pin-aviso{
display:none;position:fixed;left:50%;bottom:var(--space-4);z-index:1200;
align-items:flex-start;gap:10px;
width:min(320px,calc(100% - 2 * var(--space-4)));
padding:var(--space-3) var(--space-4);border-radius:var(--radius-md);
background:var(--color-surface);box-shadow:var(--shadow-lg);border:1px solid var(--color-divider);
transform:translate(-50%,calc(100% + var(--space-4)));opacity:0;pointer-events:none;
transition:transform .25s ease, opacity .25s ease;
}
@media (max-width:760px){
.pin-aviso{display:flex}
}
.pin-aviso.is-visible{transform:translate(-50%,0);opacity:1}
.pin-aviso-icono{flex-shrink:0;margin-top:1px;color:var(--color-warn)}
.pin-aviso-icono svg{width:18px;height:18px}
.pin-aviso-titulo{font-weight:700;font-size:13.5px;color:var(--color-text)}
.pin-aviso-desc{margin-top:2px;font-size:12.5px;color:var(--color-neutral-600)}

/* — sidebar shell — */
.app-shell{display:flex;height:100vh;width:100%;overflow:hidden}
.sidebar{
width:268px;transition:width .22s ease;
background:var(--color-neutral-200);border-right:1px solid var(--color-divider);
display:flex;flex-direction:column;padding:var(--space-4) var(--space-3);gap:var(--space-4);
flex-shrink:0;overflow-x:hidden;overflow-y:auto;
}
.sidebar.is-collapsed{width:76px}
.sidebar.is-collapsed.is-hovering{width:268px}
.sidebar-header{display:flex;align-items:center;justify-content:space-between;gap:8px}
.sidebar.is-collapsed:not(.is-hovering) .sidebar-header{justify-content:center}
.sidebar.is-collapsed:not(.is-hovering) [data-sidebar-label]{display:none}
.sidebar.is-collapsed .sidebar-header .btn-icon{display:none}
.sidebar.is-collapsed.is-hovering .sidebar-header .btn-icon{display:inline-flex}
[data-sidebar-collapsed-only]{display:none}
.sidebar.is-collapsed:not(.is-hovering) [data-sidebar-collapsed-only]{display:inline-flex}
.sidebar-brand{display:flex;align-items:center;gap:10px;min-width:0}
/* Con la barra colapsada, el logo es el botón de expandir (quiz.js,
   `expandirSidebarDesdeLogo`): el propio botón de colapsar se esconde hasta que
   el hover ensancha la barra, así que sin esto no había pista de que se
   pudiera pulsar nada aquí. Expandida no hace nada al pulsarlo, así que se
   queda con el cursor normal. */
.sidebar.is-collapsed .sidebar-brand{cursor:pointer}
.sidebar-logo{
width:26px;height:26px;flex-shrink:0;
display:block;object-fit:contain;
margin-left:8px;
}
/* Con la barra plegada solo queda la anilla: sin el desplazamiento queda centrada. */
.sidebar.is-collapsed:not(.is-hovering) .sidebar-logo{margin-left:0}
.sidebar-brand-name{font-family:var(--font-heading);font-weight:700;font-size:18px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.brand-accent{color:var(--color-accent)}
.sidebar nav{display:flex;flex-direction:column;gap:2px}
.op-row{
cursor:pointer;display:flex;align-items:center;gap:10px;
padding:9px 10px;border-radius:var(--radius-md);color:var(--color-text);
}
.op-row svg{flex-shrink:0}
.op-row span{font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* El botón «Para ti» lleva el nombre de quien ha iniciado sesión: uno largo no
   debe romper la pastilla ni empujarla a dos líneas. */
.sidebar-cta{overflow:hidden}
/* En su propia página, «Para ti» se queda con el mismo fondo que al pasar el
   ratón: sin `.op-row`, no tiene el `.is-active` de las demás filas del menú y
   no había forma de ver que es donde ya se está. */
.sidebar-cta.is-active{background:var(--color-accent-600)}
.sidebar-cta span{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.op-row:hover{background:color-mix(in srgb, var(--color-text) 6%, transparent)}
.op-row.is-active{background:var(--color-accent-100);color:var(--color-accent-800)}
/* Plegada, la fila se queda solo con el icono: sin centrarlo, el relleno
   lateral de la fila lo deja descolgado hacia la izquierda. */
.sidebar.is-collapsed:not(.is-hovering) .op-row{justify-content:center}
.sidebar-spacer{flex:1}
.sidebar-foot{display:flex;flex-direction:column;gap:2px;border-top:1px solid var(--color-divider);padding-top:var(--space-3)}
.sidebar-login-card{background:var(--color-accent-100);gap:8px}
.sidebar-login-card p{margin:0;font-size:12.5px;color:var(--color-accent-800)}
.sidebar-user{display:flex;align-items:center;gap:8px;font-size:13.5px;padding:6px 10px}
/* No es un enlace de texto, es la fila de una cuenta: se marca con el fondo de
   `.op-row`, como las demás filas del menú, y no con el subrayado que la regla
   general le pone a cualquier <a>. */
.sidebar-user:hover{text-decoration:none}
.sidebar-avatar{
display:flex;align-items:center;justify-content:center;flex-shrink:0;
width:26px;height:26px;border-radius:50%;
background:var(--color-accent-100);color:var(--color-accent-800);
}
/* Con el nombre a secas, `.op-row span` mandaba: hace falta la clase de la fila
   delante para ganarle. */
.sidebar-user .sidebar-user-nombre{font-size:13.5px;font-weight:600}

/* Scrollbar propia de la barra lateral: solo la pastilla, sin carril propio —
   se ve el fondo de la barra detrás, no una franja oscura pegada al borde.

   Invisible hasta que se pasa el ratón por encima —mismo patrón que
   `.app-main` más abajo—, y con `.is-hovering` en vez de `:hover`: es la
   misma clase que ya pone/quita quiz.js con `mouseenter`/`mouseleave` para
   expandir la barra colapsada, así que la pastilla aparece exactamente
   cuando la barra está ancha (desplegada del todo, o colapsada pero
   agrandada por el ratón) y no antes.

   Sin `scrollbar-color`, a propósito: es la única forma de animar la
   pastilla. Chrome 121+ ignora `::-webkit-scrollbar-thumb` en cuanto hay un
   `scrollbar-color` en la regla —se probó con los dos a la vez y el
   `transition` de abajo no se veía, ganaba siempre `scrollbar-color`, que
   ningún navegador anima—. El coste es Firefox, que sin `scrollbar-color` no
   tiene forma de pintar esta pastilla a su manera y cae en su scrollbar de
   sistema, siempre visible y sin el gris propio del tema. */
.sidebar::-webkit-scrollbar{width:10px}
.sidebar::-webkit-scrollbar-track{background:transparent}
.sidebar::-webkit-scrollbar-thumb{
background:transparent;border-radius:999px;
border:2px solid transparent;background-clip:padding-box;
transition:background-color 6s ease;
}
.sidebar.is-hovering::-webkit-scrollbar-thumb{background:var(--color-neutral-400)}
.sidebar::-webkit-scrollbar-thumb:hover{background:var(--color-neutral-500)}
.sidebar::-webkit-scrollbar-button{display:none}

.app-main{flex:1;overflow-y:auto;padding:var(--space-8)}
.app-main-inner{max-width:90%}

/* Pastilla invisible hasta que se pasa el ratón por encima: en un touchpad o
   una pantalla táctil no hace falta —ahí el sistema ya la esconde solo—, pero
   en un ratón de escritorio se queda una franja gris fija todo el rato si no
   se hace así. Mismo truco que la de la barra lateral, pero empezando en
   transparente en vez de en gris. */
.app-main{scrollbar-color:transparent transparent}
.app-main:hover{scrollbar-color:var(--color-neutral-400) transparent}
.app-main::-webkit-scrollbar{width:10px}
.app-main::-webkit-scrollbar-track{background:transparent}
.app-main::-webkit-scrollbar-thumb{background:transparent;border-radius:999px;border:2px solid transparent;background-clip:padding-box}
.app-main:hover::-webkit-scrollbar-thumb{background:var(--color-neutral-400)}
.app-main::-webkit-scrollbar-thumb:hover{background:var(--color-neutral-500)}
.app-main::-webkit-scrollbar-button{display:none}

@media (min-width:861px){
/* El reto comparte la regla con el test normal en vez de repetir el valor: así
   no pueden separarse, y ambas ganan a .app-main-inner por ir después. */
.quiz-main-inner,
.reto-juego-inner{max-width:880px;margin:0 auto}
}

/* — quiz — */
/* En el simulacro el reloj va hacia atrás y se enciende cuando queda poco: ámbar
   en el último quinto y rojo en el último veinteavo, que es donde hay que
   decidir si repartir el tiempo que queda. El latido del rojo es lo único que se
   ve sin mirar el reloj, que es de lo que se trata. */
#temporizador{font-variant-numeric:tabular-nums;transition:background .3s ease, color .3s ease}
#temporizador.is-warn{background:var(--color-warn-100);color:var(--color-warn-800)}
#temporizador.is-danger{background:var(--color-danger-100);color:var(--color-danger-800);animation:temporizador-late 1s ease-in-out infinite}
@keyframes temporizador-late{
0%,100%{opacity:1}
50%{opacity:.55}
}
@media (prefers-reduced-motion:reduce){
#temporizador.is-danger{animation:none}
}

.progress-track{height:10px;border-radius:999px;background:var(--color-neutral-300);overflow:hidden;margin-bottom:var(--space-6)}
.progress-fill{height:100%;border-radius:999px;background:var(--color-accent);transition:width .35s ease}
/* Piezas del mockup de móvil que trajo el usuario para la pantalla de
   pregunta —barra en tramos, número grande, «Finalizar test» plegado—:
   ocultas aquí y solo a la vista en el `@media` de móvil más abajo, donde
   también se esconde lo que sustituyen (`.progress-track`, `#contador` no
   hace falta esconderlo porque ya dice lo mismo con palabras). `.quiz-
   cabecera` no va en esta lista: envuelve contenido que también hace falta
   en escritorio, así que se queda visible y sin estilo propio hasta que el
   `@media` la convierte en tarjeta. */
.quiz-barra-segmentada,.quiz-pregunta-numero-grupo{display:none}
.quiz-finalizar-toggle{display:none}

.op-opt{
appearance:none;-webkit-appearance:none;
transition:background .15s ease, border-color .15s ease, transform .15s ease;
display:flex;align-items:center;gap:12px;text-align:left;width:100%;
padding:14px 16px;margin-bottom:12px;border-radius:var(--radius-md);
border:1.5px solid var(--color-divider);background:var(--color-surface);color:var(--color-text);
cursor:pointer;font:inherit;font-size:15px;
}
.op-opt:hover{transform:translateX(2px)}
.op-opt.is-locked:hover{transform:none}
.op-opt:disabled{cursor:default}
/* Ya respondida: ni se puede cambiar ni debe parecer que se puede. */
.op-opt.is-locked{cursor:default}
.op-opt.is-static{cursor:default}
/* En estudio la correcta se marca con el borde y la letra, sin rellenar de
   verde: se lee mucho rato seguido. */
.op-opt-study-correct{border-color:var(--color-success)}
.op-opt-study-correct .op-badge{background:var(--color-success);color:#fff}

mark.hl{background:color-mix(in srgb, var(--color-warn) 38%, transparent);color:inherit;border-radius:3px;padding:0 1px}
.is-highlighting #pregunta,.is-highlighting .op-text{cursor:text}
.is-highlighting mark.hl{cursor:pointer}
.op-opt.op-opt-neutral:not(.is-locked):hover{border-color:var(--color-accent)}
.op-opt.op-opt-neutral:not(.is-locked):hover .op-badge{background:var(--color-accent);color:#fff}
.op-badge{
width:26px;height:26px;border-radius:50%;background:var(--color-neutral-300);color:var(--color-text);
display:flex;align-items:center;justify-content:center;font-family:var(--font-heading);font-size:12px;flex-shrink:0;
}
.op-opt-selected{border-color:var(--color-accent-400);background:var(--color-accent-100);color:var(--color-accent-800)}
.op-opt-selected .op-badge{background:var(--color-accent-400);color:#fff}
.op-opt-correct{border-color:var(--color-success);background:var(--color-success-100);color:var(--color-success-800)}
.op-opt-correct .op-badge{background:var(--color-success);color:#fff}
.op-opt-wrong{border-color:var(--color-danger);background:var(--color-danger-100);color:var(--color-danger-800)}
.op-opt-wrong .op-badge{background:var(--color-danger);color:#fff}
.op-opt-blank{border-color:var(--color-divider)}
.op-opt-platform-secondary{border-color:var(--color-divider);background:rgba(148,163,184,.12)}
.op-opt-platform-secondary .op-badge{background:var(--color-neutral-300);color:var(--color-neutral-700)}

/* El fondo tintado se queda, pero con filo del color y el icono delante: sin
   borde, sobre la tarjeta blanca, el aviso se leía como un párrafo más. El icono
   va de línea y del color del texto, no un emoji: cada sistema pintaba los suyos
   con otra forma y otro color, y el rojo del ❌ no era el rojo de la aplicación. */
.feedback-banner{
display:flex;align-items:flex-start;gap:10px;
padding:14px 16px;border-radius:var(--radius-md);margin-top:6px;
border:1px solid transparent;
}
.feedback-banner.is-success{background:var(--color-success-100);color:var(--color-success-800);border-color:color-mix(in srgb, var(--color-success) 35%, transparent)}
.feedback-banner.is-fail{background:var(--color-danger-100);color:var(--color-danger-800);border-color:color-mix(in srgb, var(--color-danger) 35%, transparent)}
/* El icono no se encoge ni se estira con el texto, y se alinea con la primera
   línea: en el aviso de fallo hay dos y centrado quedaba a media altura. */
.feedback-icono{flex-shrink:0;margin-top:1px}
.feedback-banner.is-success .feedback-icono{color:var(--color-success)}
.feedback-banner.is-fail .feedback-icono{color:var(--color-danger)}
.feedback-headline{font-family:var(--font-heading);font-weight:700;font-size:15px}
.feedback-detalle{font-size:13px;line-height:1.5;margin-top:3px}

/* — modo estudio: explicación, fuente y avisos de revisión — */
.study-info{display:flex;flex-direction:column;gap:var(--space-3);margin-top:var(--space-4)}
.study-block h4{font-family:var(--font-heading);font-size:13px;text-transform:uppercase;letter-spacing:.04em;color:var(--color-neutral-600);margin:0 0 4px}
.study-block p{margin:0;font-size:14px;line-height:1.55}
.study-revision{background:var(--color-warn-100);color:var(--color-warn-800);border-left:3px solid var(--color-warn);border-radius:var(--radius-md);padding:12px 14px}
.study-revision-title{font-family:var(--font-heading);font-size:14px;line-height:1.4}
.study-revision-note{margin:6px 0 0;font-size:13px;line-height:1.5;opacity:.9}
.study-source{display:inline-flex;align-items:flex-start;gap:6px;font-size:13px;line-height:1.45;color:var(--color-accent-600);align-self:flex-start}
.study-source:hover{text-decoration:underline}

/* La cabecera del resultado: el anillo con la nota y, al lado, el título y el
   recuento. En su propio fondo, como una franja aparte de la tarjeta blanca
   que la contiene: es lo primero que hay que ver al terminar, y así se
   distingue de un vistazo del resto. En estrecho el anillo se pone encima en
   vez de encoger, que a menos de 64px la cifra de dentro deja de leerse. */
.evaluacion-cabecera{
display:flex;align-items:center;gap:var(--space-4);margin-bottom:var(--space-4);
padding:var(--space-4);border-radius:var(--radius-lg);background:var(--color-neutral-200);
}
.evaluacion-cabecera-texto{min-width:0;flex:1}
/* Sin tope se estira hasta las pastillas de la derecha, que con una frase
   larga quedaban apretadas contra la segunda línea del mensaje. */
#evaluacion-mensaje{margin:0 0 2px;font-weight:600;max-width:38ch}
/* Las mismas tres cifras del resumen de texto, en pastilla y de un color cada
   una: se leen sin tener que pararse a leer la frase de al lado. */
.evaluacion-cifras{display:flex;gap:6px;flex-shrink:0}
/* El anillo es un `conic-gradient` con un disco encima que le abre el hueco: un
   número y dos reglas, sin SVG ni biblioteca. El tramo se pinta con --anillo-pct
   y --anillo-color, que pone el JS con el mismo corte que la barra de «Por área
   del temario» en Estadísticas: rojo, naranja o verde según la nota, no un color
   fijo. El hueco lleva el color de la tarjeta y no blanco, para que valga igual
   en oscuro.

   El disco va en `::before` y no en una máscara porque una máscara se lleva por
   delante también la cifra de dentro. */
.anillo-nota{
position:relative;flex-shrink:0;width:78px;height:78px;border-radius:50%;
display:flex;align-items:center;justify-content:center;
background:conic-gradient(var(--anillo-color, var(--color-success)) calc(var(--anillo-pct) * 1%), var(--color-neutral-300) 0);
}
.anillo-nota::before{content:"";position:absolute;inset:9px;border-radius:50%;background:var(--color-surface)}
.anillo-cifra{position:relative;font-family:var(--font-heading);font-weight:700;font-size:19px;color:var(--color-text)}

#evaluacion-leyenda{font-weight:600}

/* Los dos botones se reparten el ancho de la tarjeta: son el final de la
   pantalla y las dos únicas salidas, así que no se quedan encogidos en una
   esquina. Con uno solo visible —en estudio se ocultan— el que quede lo ocupa
   todo, que es lo que hace `flex:1` sin más reglas. */
.evaluacion-acciones{display:flex;gap:10px}
.evaluacion-acciones .btn{flex:1}

.evaluation-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(52px,1fr));gap:10px}
.evaluation-question{
appearance:none;-webkit-appearance:none;
aspect-ratio:1;font:inherit;font-family:var(--font-heading);font-weight:700;
border-radius:var(--radius-md);border:1.5px solid var(--color-divider);padding:0;
background:var(--color-surface);color:var(--color-text);cursor:pointer;
display:flex;align-items:center;justify-content:center;text-decoration:none;
position:relative;
}
.evaluation-question.has-revision::after{
content:"";position:absolute;top:4px;right:4px;
width:8px;height:8px;border-radius:50%;
background:var(--color-warn);border:1px solid var(--color-surface);
}
.evaluation-question:hover{text-decoration:none}
/* Colores planos y no tintados: la cuadrícula se lee de un golpe, de lejos y sin
   contar, que es para lo único que está. Las tres son las de la leyenda.

   `is-skipped` —vista y saltada— se pinta como `is-blank`: para el que estudia
   las dos son lo mismo, una pregunta sin responder. */
.evaluation-question.is-success{background:var(--color-success);color:#fff;border-color:var(--color-success)}
.evaluation-question.is-fail{background:var(--color-danger);color:#fff;border-color:var(--color-danger)}
.evaluation-question.is-blank,
.evaluation-question.is-skipped{background:var(--color-neutral-200);color:var(--color-neutral-600);border-color:var(--color-neutral-300)}

/* En el estudio no se responde nada, así que la cuadrícula no dice acierto ni
   fallo: dice por dónde se ha pasado. `is-visto` no puede ser el gris de
   `is-skipped` porque ahí significa lo contrario —vista y saltada—, y las dos
   convivirían en la misma parrilla sin distinguirse.

   `is-actual` va encima de la que toque: la pregunta en la que se estaba también
   está vista, así que el aro se suma al color en vez de sustituirlo. */
.evaluation-question.is-visto{background:var(--color-accent-600);color:#fff;border-color:var(--color-accent-600)}
/* La del final de la racha se queda en blanco con el borde azul fuerte: entre
   casillas ya azules, un azul más azul no se encuentra de un vistazo. El color
   de texto se repone aquí a propósito: `is-visto` lo deja en blanco para su
   fondo azul, y esta casilla también lleva esa clase —es la última vista de la
   racha—, así que sin esto el número se quedaba blanco sobre blanco. */
.evaluation-question.is-actual{background:var(--color-surface);color:var(--color-text);border-color:var(--color-accent-600);box-shadow:0 0 0 2px var(--color-accent-200)}
/* Elegida para el test que se está montando. Va la última de las tres porque
   manda sobre las otras dos: mientras se elige, lo que importa es si entra. */
.evaluation-question.is-elegida{background:var(--color-accent-600);color:#fff;border-color:var(--color-accent-600)}
.evaluation-question.is-elegida::before{background:var(--color-surface)}
/* El «más» y el «menos» van en una esquina y el aviso de revisión en la otra:
   una pregunta puede llevar los dos a la vez. */
.eq-marca{
position:absolute;top:-7px;left:-7px;
width:18px;height:18px;border-radius:50%;
display:flex;align-items:center;justify-content:center;
font-size:13px;line-height:1;font-weight:700;
background:var(--color-neutral-500);color:#fff;border:2px solid var(--color-surface);
}
.evaluation-question.is-elegida .eq-marca{background:var(--color-accent-600)}

/* Leyenda de los estados, la del examen y la del estudio. Los cuadros repiten
   los colores de las casillas en pequeño, que es lo que hay que reconocer. */
.eval-leyenda{
display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-4);
margin-bottom:var(--space-3);font-size:13px;
}
.eval-leyenda>span{display:flex;align-items:center;gap:6px}
.eval-muestra{
width:14px;height:14px;flex-shrink:0;
border-radius:4px;border:1.5px solid var(--color-neutral-300);
background:var(--color-neutral-200);
}
.eval-muestra.is-success{background:var(--color-success);border-color:var(--color-success)}
.eval-muestra.is-fail{background:var(--color-danger);border-color:var(--color-danger)}
.eval-muestra.is-visto{background:var(--color-accent-600);border-color:var(--color-accent-600)}
.eval-muestra.is-actual{background:var(--color-surface);border-color:var(--color-accent-500)}
/* El aviso no es un estado de la casilla —cualquiera puede llevarlo encima,
   vista o no— así que no comparte cuadrado con los demás: un punto suelto,
   igual que el que se ve en la esquina de la propia casilla. */
.eval-muestra.is-aviso{width:8px;height:8px;border-radius:50%;border:none;background:var(--color-warn)}

/* — generar test desde el estudio — */
.estudio-generar{
display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--space-3);
margin-bottom:var(--space-3);padding:10px 14px;
border-radius:var(--radius-md);border:1.5px solid var(--color-divider);background:var(--color-neutral-200);
}
.estudio-generar-texto{margin:0;font-size:13px}
.estudio-generar-acciones{display:flex;flex-wrap:wrap;gap:8px}

/* — statistics — */
.stat-card{align-items:flex-start}
.stat-value{font-family:var(--font-heading);font-size:34px}
.split-bar{height:16px;border-radius:999px;overflow:hidden;display:flex;background:var(--color-neutral-300)}
.split-bar-success{height:100%;background:var(--color-success)}
.split-bar-fail{height:100%;background:var(--color-danger)}
.legend-dot{width:10px;height:10px;border-radius:50%;display:inline-block;flex-shrink:0}
/* El punto de cada nivel de dominio, con el color de su pastilla. Era un emoji
   (🔴🟡🟢🏆): cada sistema lo pintaba de un tono distinto —y el trofeo ni
   siquiera era un punto—, así que no casaba con el color de la ficha ni con el
   de la barra de estadísticas, que salen los dos de la misma variable. */
.dominio-titulo{display:flex;align-items:center;gap:7px}

/* — páginas de error — */
.error-card{
margin:var(--space-8) auto;padding:var(--space-6);
align-items:center;text-align:center;gap:var(--space-3);
}
/* El número, grande y flojo de color: identifica el error de un vistazo para
   quien sepa leerlo, y no le roba el sitio a la explicación, que es lo que
   necesita todo el mundo. */
.error-code{
font-family:var(--font-heading);font-weight:700;font-size:15px;letter-spacing:.16em;
color:color-mix(in srgb, var(--color-text) 38%, transparent);
}
.error-titulo{font-size:24px;margin:0}
.error-acciones{display:flex;flex-wrap:wrap;justify-content:center;gap:var(--space-2);margin-top:var(--space-3)}
@media (max-width:520px){
.error-acciones .btn{width:100%}
}

.attempt-row{cursor:pointer}
.attempt-row:hover{background:var(--color-neutral-200)}

/* — historial: móvil —
   Por debajo de 640px la tabla de 5 columnas se sustituye por esta lista de
   tarjetas de 3 —fecha+hora, test+categoría, aciertos—, con la misma
   cuadrícula de preguntas al desplegar y «Ver más» en vez de Anterior/
   Siguiente, calcado del mockup que trajo el usuario. Oculta por defecto
   porque `.hist-escritorio` es quien manda hasta el media query de abajo,
   igual que `.sr-movil`/`.sr-escritorio` en Aprendizaje recomendado. */
.hist-movil{display:none}
.hist-cabecera,
.hist-fila-boton{
display:grid;grid-template-columns:52px minmax(0,1fr) 56px;
column-gap:var(--space-2);align-items:center;width:100%;
}
.hist-cabecera{
padding:var(--space-2) var(--space-3);border-bottom:2px solid var(--color-divider);
font-size:11px;letter-spacing:.06em;text-transform:uppercase;
color:color-mix(in srgb, var(--color-text) 60%, transparent);
}
.hist-fila{border-bottom:1px solid var(--color-divider)}
.hist-fila:last-child{border-bottom:none}
.hist-fila-boton{
padding:var(--space-3);border:0;background:none;font:inherit;color:inherit;
text-align:left;cursor:pointer;
}
.hist-fila-boton:hover{background:var(--color-neutral-200)}
.hist-fecha{font-size:13px;line-height:1.3}
.hist-hora{display:block;font-size:11px;color:color-mix(in srgb, var(--color-text) 55%, transparent)}
.hist-test-titulo{display:block;font-weight:600;font-size:14px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hist-test-cat{display:block;font-size:12px;color:color-mix(in srgb, var(--color-text) 55%, transparent);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hist-aciertos{text-align:right;font-weight:700;font-size:14px;font-variant-numeric:tabular-nums}
.hist-aciertos.is-success{color:var(--color-success-800)}
.hist-aciertos.is-warn{color:var(--color-warn-800)}
.hist-aciertos.is-danger{color:var(--color-danger-800)}
.hist-detalle{padding:0 var(--space-3) var(--space-3)}
.hist-ver-mas{width:100%;margin-top:var(--space-3)}
.hist-contador{text-align:center;font-size:13px;margin-top:var(--space-2)}
@media (max-width:640px){
.hist-escritorio{display:none}
.hist-movil{display:block}
}

/* — historial: filtros — */
.hist-filtros{display:flex;gap:var(--space-2);margin-bottom:var(--space-4);flex-wrap:wrap}
.hist-filtros .input{width:auto;min-width:170px}
/* La flecha nativa del desplegable va clavada al borde derecho y no hay forma de
   moverla: se quita y se pinta una propia, 20px más adentro que aquella. Va en
   SVG con currentColor para que siga al tema, como la lupa del buscador. */
/* El desplegable lo pinta la aplicación: el <select> se queda debajo, oculto,
   como fuente de las opciones y de la elección. Mientras el JavaScript no lo
   monta —o si no llega a ejecutarse— lo que se ve es el del navegador con su
   flecha escondida y la nuestra encima, que es un sitio razonable donde quedarse. */
.select-flecha{position:relative;display:inline-flex;align-items:center}
.select-flecha .input{appearance:none;-webkit-appearance:none;padding-right:52px}
.select-flecha[data-propio] select{display:none}
.select-flecha-icono{
position:absolute;right:30px;color:var(--color-neutral-500);pointer-events:none;
transition:transform .18s ease;
}
/* Dentro del botón la flecha deja de ir colocada a mano: es el último hijo de una
   fila, y el hueco lo abre el `gap`. */
.select-boton .select-flecha-icono{position:static}
.select-flecha.is-abierto .select-flecha-icono{transform:rotate(180deg)}
.select-flecha .select-boton{
display:inline-flex;align-items:center;justify-content:space-between;gap:var(--space-3);
width:auto;padding-right:var(--space-4);cursor:pointer;text-align:left;
font:inherit;color:inherit;
}
.select-boton:hover{border-color:var(--color-accent-300)}
.select-boton-texto{white-space:nowrap}
/* La lista cuelga del botón y se sale de la caja: por encima de la tabla que
   tiene debajo, y con su propio desplazamiento cuando hay más categorías de las
   que caben sin tapar media pantalla. */
.select-lista{
position:absolute;top:calc(100% + 6px);left:0;z-index:40;
min-width:100%;max-height:320px;overflow-y:auto;
/* El hueco de la derecha es más ancho que los otros tres a propósito: es el
   carril de `.scroll-pista`, y con el mismo `--space-1` de los demás lados la
   pastilla se metía tres píxeles por encima del fondo de la fila señalada. */
padding:var(--space-1) 12px var(--space-1) var(--space-1);border:1px solid var(--color-divider);border-radius:var(--radius-md);
background:var(--color-surface);box-shadow:var(--shadow-lg);
display:flex;flex-direction:column;
/* La barra nativa se esconde y la dibuja el JS encima (`.scroll-pista`,
   compartida con los diálogos largos —ayuda, cómo se calcula la
   clasificación—): así es igual en todos los navegadores, que con
   `::-webkit-scrollbar` no lo es —Firefox no la reconoce. */
scrollbar-width:none;-ms-overflow-style:none;
}
.select-lista::-webkit-scrollbar{display:none}
/* — barra de scroll flotante propia — */
/* Marca el contenedor que la lleva: sin ella, el resto de diálogos —cortos,
   sin nada que desplazar— no necesitan esconder su barra ni pintar nada
   encima. `crearPistaScroll()` en quiz.js pinta y mueve la pista y la
   pastilla; aquí solo su aspecto. */
.con-pista{scrollbar-width:none;-ms-overflow-style:none}
.con-pista::-webkit-scrollbar{display:none}
/* La pista es hija de lo que se desplaza y por eso se movería con el
   contenido: el `translateY` que le pone el JS cancela justo ese
   desplazamiento, para que se quede fija en la ventana visible como una barra
   de verdad. Empieza y acaba 10px antes del borde —ni en top:0 ni en
   bottom:0— porque a ras de la esquina el radio del contenedor le recorta la
   punta redondeada a la pastilla; parándose antes, esa punta se ve entera. */
.scroll-pista{
position:absolute;top:10px;right:2px;bottom:10px;width:5px;pointer-events:none;
}
.scroll-hilo{
position:absolute;left:0;width:100%;min-height:24px;border-radius:999px;
background:var(--color-neutral-500);opacity:0;
transition:opacity .15s ease;
}
.con-pista:hover .scroll-hilo{opacity:.55}
.select-opcion{
appearance:none;-webkit-appearance:none;border:none;background:none;
padding:9px var(--space-3);border-radius:var(--radius-sm);
font:inherit;font-size:14px;color:inherit;text-align:left;white-space:nowrap;cursor:pointer;
transition:background .12s ease, color .12s ease;
}
.select-opcion:hover{background:var(--color-accent-100);color:var(--color-accent-800)}
.select-opcion.is-elegida{background:var(--color-accent);color:#fff}
.select-opcion:focus-visible{outline:2px solid var(--color-accent);outline-offset:-2px}

/* — progress chart — */
.progress-chart{width:100%;height:auto;display:block}
.progress-chart .chart-grid{stroke:var(--color-divider);stroke-width:1}
.progress-chart .chart-axis-label{fill:var(--color-neutral-600);font-size:10px}
.progress-chart polyline{fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.progress-chart circle{cursor:pointer}
.progress-chart text{font-family:var(--font-body);font-weight:600}
.trend-up{color:var(--color-success)}
.trend-down{color:var(--color-danger)}

/* — dominio bar chart — */
.dominio-bar-chart{display:flex;align-items:stretch;gap:16px;height:200px;padding:4px}
.dominio-bar-col{flex:1;display:flex;flex-direction:column;align-items:center;min-width:0}
.dominio-bar-track{flex:1;width:100%;display:flex;align-items:flex-end;justify-content:center}
.dominio-bar-fill{width:100%;max-width:64px;min-height:4px;border-radius:8px 8px 0 0;transition:height .3s ease}
.dominio-bar-count{font-weight:700;font-size:15px;margin-top:8px}
.dominio-bar-label{font-size:11.5px;color:var(--color-text);opacity:.7;text-align:center;margin-top:2px;line-height:1.3}

.section-toggle svg{transition:transform .2s ease}
.section-toggle.is-collapsed svg{transform:rotate(180deg)}
/* La fila entera del título despliega la sección, así que se marca como pulsable
   y no deja seleccionar el texto: al pulsar dos veces seguidas se quedaba el
   título en azul de selección. */
.seccion-titulo{display:flex;align-items:center;gap:8px;margin:var(--space-6) 0 2px;cursor:pointer;user-select:none}
/* La misma sección plegable, pero con su resumen dentro: título y cifras a la
   izquierda, cuánto se domina y la flecha a la derecha. Es una ficha y no un
   rótulo suelto porque lo que hay debajo también lo es, y así plegada la sección
   sigue siendo un bloque de la pantalla en vez de una línea de texto. */
/* Ocupa el ancho del contenedor, como el resto de bloques de la pantalla: es una
   sección, no una ficha suelta, y encogida a su contenido rompía la columna que
   forman las fichas de arriba y la tabla de dentro.

   `padding:0` y `gap:0` porque el relleno lo ponen la cabecera y el cuerpo, cada
   uno el suyo, y la línea que los separa tiene que llegar a los bordes. */
.seccion-bloque{margin:var(--space-6) 0;padding:0;gap:0}
/* `flex-direction` va explícito: `.card` apila en columna, y sin decir nada aquí
   el resumen se ponía debajo del título en vez de al otro lado de la fila. */
.seccion-panel{
display:flex;flex-direction:row;align-items:center;justify-content:space-between;
gap:var(--space-6);flex-wrap:wrap;
padding:var(--space-4) var(--space-6);
cursor:pointer;user-select:none;
}
.seccion-cuerpo{padding:var(--space-4) var(--space-6);border-top:1px solid var(--color-divider)}
.seccion-panel-titulo{font-family:var(--font-heading);font-weight:700;font-size:18px;margin:0}
.seccion-panel-nota{margin:2px 0 0;font-size:12.5px;color:var(--color-neutral-600)}
.seccion-panel-medida{display:flex;align-items:center;gap:var(--space-3)}
.seccion-panel-barra{width:110px;flex:none}
.temario-barra-dominio{background:var(--color-accent)}
.seccion-panel-dato{font-size:13px;font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap}
/* Con el título ocupando su propia línea, `.seccion-panel-medida` es el único
   hijo que queda en la suya: `space-between` del padre no reparte nada con un
   solo elemento y se queda pegado a la izquierda, corto, con toda la fila
   vacía al lado. A todo lo ancho y repartido él mismo, la barra crece en vez
   de quedarse en sus 110px fijos. */
@media (max-width:640px){
.seccion-panel-medida{width:100%;justify-content:space-between}
.seccion-panel-barra{flex:1}
}

/* — aprendizaje recomendado: móvil —
   Por debajo de 760px `.sr-escritorio` desaparece entero y `.sr-movil` ocupa
   su sitio: la fila de pestañas no cabe deslizable ahí abajo, así que el
   cambio de categoría pasa a ser el propio carrusel (ver el script de
   smart_review_category.html). Oculto por defecto porque el corte de
   escritorio es el que manda hasta el media query de más abajo. */
.sr-movil{display:none}
@media (max-width:760px){
.sr-escritorio{display:none}
.sr-movil{display:block}
}

.sr-movil-puntos{display:flex;justify-content:center;gap:6px;margin-bottom:var(--space-3)}
.sr-movil-punto{
width:7px;height:7px;border-radius:999px;padding:0;border:0;
background:var(--color-neutral-400);cursor:pointer;
transition:width .2s ease, background .2s ease;
}
.sr-movil-punto.is-active{width:20px;background:var(--color-accent)}

/* `scroll-snap` nativo hace de motor del gesto —sin él haría falta reproducir
   a mano lo que el navegador ya sabe hacer con el dedo—; el JS solo mantiene
   los puntos al día y lleva hasta la página al pulsar uno. Sin scrollbar
   porque los puntos ya son la referencia de en qué página se está.

   `align-items:flex-start` y no el `stretch` de siempre: una fila flex estira
   cada hijo a la altura del más alto, y una categoría con menos que enseñar
   se quedaba con el hueco entero de la más cargada debajo. El script
   (`ajustarAlturaSrMovilActiva()`) fija la altura de la fila a la de la
   página que se ve en cada momento; `flex-start` es solo para que, antes de
   que corra ese script, ninguna página se estire de más. */
.sr-movil-pistas{
display:flex;align-items:flex-start;overflow-x:auto;scroll-snap-type:x mandatory;
scrollbar-width:none;-ms-overflow-style:none;
transition:height .2s ease;
}
.sr-movil-pistas::-webkit-scrollbar{display:none}
/* El hueco a los lados no es solo estético: a mitad de gesto se ven dos
   páginas a la vez —la que se deja y la que llega—, y sin este padding sus
   fichas quedaban pegadas por el borde como si fueran la misma categoría.
   Mismo criterio que `.temario-movil-pagina`.
   `overflow-anchor:none` porque plegar una sección la deja en `display:none`,
   y sin esto el navegador —que ancla el scroll a lo que hay a la vista— se
   queda sin nada a lo que anclarse ahí y salta solo a la parte de arriba de
   la página. Mismo criterio que `.temario-arbol`. */
/* `position:relative` para la cinta de fijar (`.pin-ribbon.card-pin`), que se
   coloca contra la página entera sin envoltorio nuevo. */
.sr-movil-pagina{position:relative;flex:0 0 100%;min-width:0;scroll-snap-align:start;padding:0 var(--space-2);overflow-anchor:none}

.sr-movil-titulo{margin:0 0 2px;font-size:26px}
.sr-movil-subtitulo{margin:0 0 var(--space-4)}

/* Ficha de hoy: la única con paleta propia de toda la pantalla —el resto es
   consulta, esta es la acción que de verdad importa—, con el mismo fondo
   oscuro que ya usa la cabecera de un reto jugándose. La decoración es un
   círculo suelto sin ningún significado, solo para que el bloque no sea un
   rectángulo liso. */
.sr-movil-hoy{
position:relative;overflow:hidden;
padding:var(--space-4);border-radius:var(--radius-lg);
background:var(--color-neutral-900);color:#fff;margin-bottom:var(--space-3);
}
.sr-movil-hoy-decoracion{
position:absolute;top:-30px;right:-30px;width:110px;height:110px;border-radius:50%;
background:color-mix(in srgb, #fff 8%, transparent);
}
.sr-movil-hoy-eyebrow{
position:relative;font-size:11.5px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
color:color-mix(in srgb, #fff 65%, transparent);margin-bottom:6px;
}
.sr-movil-hoy-cifra{position:relative;font-family:var(--font-heading);font-weight:700;font-size:26px;line-height:1.15}
.sr-movil-hoy-cifra-corta{font-size:20px}
.sr-movil-hoy-detalle{position:relative;font-size:13px;color:color-mix(in srgb, #fff 75%, transparent);margin-top:2px}
.sr-movil-hoy-boton{
position:relative;display:block;margin-top:var(--space-3);
padding:11px;border-radius:var(--radius-md);text-align:center;
background:var(--color-accent-400);color:var(--color-neutral-900);font-weight:700;font-size:14px;
}
.sr-movil-hoy-boton:hover{text-decoration:none;background:var(--color-accent-300)}

/* Una fila por tema y no la tabla de escritorio —Tema/Preguntas/Aciertos/
   Completado no cabe legible aquí—: el nombre, una barra de dominio del mismo
   color que usa `_para_ti_panel.html` para lo mismo, y cuántas preguntas
   aporta a la recomendación, que es la cifra que suma el subtítulo de la
   ficha. */
/* En dos líneas y no una: los temas del temario real llevan nombres largos
   —no el «Tema 1» de un ejemplo—, y con la barra al lado en la misma línea
   casi todos se veían cortados por unas pocas letras. */
.sr-tema-fila{
display:flex;flex-direction:column;gap:6px;padding:10px 0;
border-top:1px solid var(--color-divider);color:inherit;
}
.sr-tema-fila:first-child{border-top:none;padding-top:2px}
.sr-tema-fila:hover{text-decoration:none;color:inherit}
.sr-tema-nombre{font-size:13.5px;font-weight:600}
.sr-tema-medida{display:flex;align-items:center;gap:var(--space-2)}
.sr-tema-barra{display:block;flex:1;height:5px;border-radius:999px;background:var(--color-neutral-300);overflow:hidden}
.sr-tema-barra-fill{display:block;height:100%;border-radius:999px}
.sr-tema-cifra{flex-shrink:0;width:24px;text-align:right;font-size:13px;font-weight:700;color:var(--color-neutral-600);font-variant-numeric:tabular-nums}

/* Fijadas, a revisar y repaso espaciado en tres fichas iguales y no en las
   filas horizontales de `.marcas-row` de escritorio: apiladas, esas tres
   filas eran la sección más larga de la pantalla y aquí lo urgente es no
   crecer más de la cuenta. Mismos colores que ya distinguen cada marca en
   escritorio (`.marcas-row-icono`), para que sigan significando lo mismo. */
.sr-marcas-tiles{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--space-2)}
.sr-marca-tile{
display:flex;flex-direction:column;align-items:center;text-align:center;gap:4px;
padding:var(--space-3) var(--space-2);border-radius:var(--radius-lg);
border:1px solid var(--color-divider);background:var(--color-surface);color:inherit;
}
.sr-marca-tile:hover{text-decoration:none;color:inherit;background:var(--color-neutral-200)}
.sr-marca-tile.is-disabled{cursor:not-allowed;opacity:.55}
.sr-marca-tile.is-disabled:hover{background:var(--color-surface)}
.sr-marca-tile-icono{
width:34px;height:34px;border-radius:50%;display:flex;align-items:center;justify-content:center;
}
.sr-marca-tile-icono.is-fijar{background:var(--color-accent-100);color:var(--color-accent)}
.sr-marca-tile-icono.is-advertencia{background:var(--color-warn-100);color:var(--color-warn)}
.sr-marca-tile-icono.is-repaso{background:var(--color-success-100);color:var(--color-success)}
.sr-marca-tile-cifra{font-family:var(--font-heading);font-weight:700;font-size:19px;line-height:1.1}
.sr-marca-tile-etiqueta{font-size:11.5px;color:var(--color-neutral-600)}

/* — categoría: móvil —
   Mismo reparto que Aprendizaje recomendado: por debajo de 760px
   `.cat-escritorio` desaparece entero y `.cat-movil` ocupa su sitio con el
   carrusel deslizable de category.html (ver el script ahí). Nombre propio y
   no `.sr-movil` reutilizada: son pantallas distintas y cada una busca su
   bloque por su prefijo. */
.cat-movil{display:none}
@media (max-width:760px){
.cat-escritorio{display:none}
.cat-movil{display:block}
}

.cat-movil-puntos{display:flex;justify-content:center;gap:6px;margin-bottom:var(--space-3)}
.cat-movil-punto{
width:7px;height:7px;border-radius:999px;padding:0;border:0;
background:var(--color-neutral-400);cursor:pointer;
transition:width .2s ease, background .2s ease;
}
.cat-movil-punto.is-active{width:20px;background:var(--color-accent)}

/* `align-items:flex-start` y no el `stretch` de siempre: una fila flex estira
   cada hijo a la altura del más alto, y una categoría con menos que enseñar
   se quedaba con el hueco entero de la más cargada debajo. El script
   (`ajustarAlturaCatMovilActiva()`) fija la altura de la fila a la de la
   página que se ve en cada momento; `flex-start` es solo para que, antes de
   que corra ese script, ninguna página se estire de más. */
.cat-movil-pistas{
display:flex;align-items:flex-start;overflow-x:auto;scroll-snap-type:x mandatory;
scrollbar-width:none;-ms-overflow-style:none;
transition:height .2s ease;
}
.cat-movil-pistas::-webkit-scrollbar{display:none}
/* El hueco a los lados no es solo estético: a mitad de gesto se ven dos
   páginas a la vez —la que se deja y la que llega—, y sin este padding sus
   fichas quedaban pegadas por el borde como si fueran la misma categoría.
   Mismo criterio que `.temario-movil-pagina`.
   `overflow-anchor:none` porque plegar una sección o abrir un desglose la
   deja en `display:none`, y sin esto el navegador —que ancla el scroll a lo
   que hay a la vista— se queda sin nada a lo que anclarse ahí y salta solo a
   la parte de arriba de la página. Mismo criterio que `.temario-arbol`. */
/* `position:relative` para la cinta de fijar (`.pin-ribbon.card-pin`), que se
   coloca contra la página entera sin envoltorio nuevo. */
.cat-movil-pagina{position:relative;flex:0 0 100%;min-width:0;scroll-snap-align:start;padding:0 var(--space-2);overflow-anchor:none}

.cat-movil-titulo{margin:0 0 2px;font-size:26px}
.cat-movil-subtitulo{margin:0 0 var(--space-4)}

.cat-movil-card{margin-bottom:var(--space-4);padding:0}
.cat-movil-card-cabecera{display:flex;align-items:baseline;justify-content:space-between;gap:var(--space-3);padding:var(--space-4) var(--space-4) 0}
.cat-movil-card-cuerpo{padding:var(--space-2) var(--space-4) var(--space-2)}

.cat-movil-fila-chevron{flex-shrink:0;color:var(--color-neutral-500)}

/* Barra de dominio de la categoría, en miniatura: los mismos cuatro colores
   que las fichas de escritorio, uno por nivel y ancho proporcional a cuántas
   preguntas lleva cada uno. */
.cat-movil-barra-segmentada{display:flex;height:12px;border-radius:999px;overflow:hidden;background:var(--color-neutral-300);margin-bottom:var(--space-3)}
.cat-movil-barra-segmentada span{display:block;height:100%}

/* Panel de «practicar este nivel», plegado hasta que se toca su fila
   (`alternarNivelCategoria` en category.html). Uno abierto a la vez, como en
   la maqueta: abrir otro cierra este. */
.cat-nivel-panel{padding:var(--space-3);margin:2px 0 6px;background:var(--color-neutral-100);border-radius:var(--radius-md)}

/* Una respuesta personalizada por bloque, sin la rejilla de escritorio: aquí
   se leen en una sola columna, la etiqueta del test encima y no al lado,
   porque un enunciado largo ya ocupa el ancho entero. */
.cat-movil-pa-item{padding:var(--space-3) 0;border-top:1px solid var(--color-divider)}
.cat-movil-pa-item:first-child{border-top:none;padding-top:0}
.cat-movil-pa-item .tag{display:inline-flex}
.cat-movil-pa-stem{font-size:13.5px;font-weight:600;line-height:1.35;margin:4px 0 2px}
.cat-movil-pa-resp{font-size:12.5px;opacity:.75}

/* Barra fija de «Repasar falladas»: la única acción de esta pantalla que
   conviene tener siempre a mano, así que flota sobre el contenido en vez de
   esperar al final del scroll como la ficha de escritorio. Una sola para todo
   el carrusel (ver el comentario de category.html sobre por qué no vive
   dentro de cada página), con espacio reservado abajo para que no tape la
   última ficha. */
.cat-movil-con-fallada{padding-bottom:88px}
.cat-movil-fallada-fija{
position:fixed;left:var(--space-3);right:var(--space-3);
bottom:calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
z-index:850;
display:flex;align-items:center;gap:var(--space-3);
padding:var(--space-3) var(--space-4);border-radius:var(--radius-lg);
background:var(--color-warn);color:#fff;
box-shadow:0 8px 24px color-mix(in srgb, var(--color-warn) 45%, transparent);
text-decoration:none;
}
.cat-movil-fallada-fija:hover{color:#fff;text-decoration:none}
.cat-movil-fallada-texto{flex:1;min-width:0}
.cat-movil-fallada-titulo{display:block;font-family:var(--font-heading);font-weight:700;font-size:15.5px}
.cat-movil-fallada-detalle{display:block;font-size:12.5px;color:color-mix(in srgb, #fff 88%, transparent);margin-top:1px}
.cat-movil-fallada-flecha{flex-shrink:0;font-size:19px;font-weight:700}

/* — por área del temario — */
.concept-legend{display:flex;flex-wrap:wrap;gap:var(--space-4);font-size:12.5px;color:var(--color-neutral-600);margin-bottom:var(--space-4)}
.concept-legend span{display:flex;align-items:center;gap:6px}
/* El velo es una capa blanca única sobre toda la lista, no un difuminado por
   área: así el área abierta puede quedar por encima, entera y nítida, en vez
   de solo "menos oscurecida" que las demás. */
.concept-areas{position:relative}
.concept-area+.concept-area{margin-top:14px}
.concept-area{position:relative}
.concept-veil{
position:absolute;inset:calc(-1 * var(--space-2));z-index:1;
background:var(--color-surface);border-radius:var(--radius-md);
opacity:0;pointer-events:none;transition:opacity .2s ease;
}
/* El área abierta sube por encima del velo con su propio fondo opaco: por eso
   se ve recortada y nítida en vez de teñida como las demás. */
.concept-area.is-active{
position:relative;z-index:2;background:var(--color-surface);
border-radius:var(--radius-md);box-shadow:var(--shadow-md);
padding:var(--space-4);margin:0 calc(-1 * var(--space-4));
}
/* Toda la fila es el botón que despliega, no solo la flecha: es la zona grande
   y evidente, y en el móvil la flecha sola sería un blanco imposible. */
.concept-area-head{
display:flex;align-items:center;gap:8px;width:100%;
background:none;border:0;padding:0 0 4px;margin:0;cursor:pointer;
font:inherit;font-size:13px;color:inherit;text-align:left;
}
.concept-area-label{font-weight:600;flex:1;min-width:0}
.concept-figure{white-space:nowrap;font-variant-numeric:tabular-nums}
.concept-caret{flex-shrink:0;transition:transform .2s ease}
.concept-area-head.is-open .concept-caret{transform:rotate(90deg)}
.concept-list{margin:12px 0 4px;padding-left:14px;border-left:2px solid var(--color-divider);display:flex;flex-direction:column;gap:12px}
.concept-row-head{display:flex;justify-content:space-between;gap:8px;font-size:12.5px;margin-bottom:4px}
.concept-practice{margin-top:6px}
@media (max-width:520px){
.concept-list{padding-left:10px}
.concept-practice{width:100%}
}

/* — entrada escalonada de arriba abajo — */
/* Cada cosa baja a su sitio al cargar la pantalla, de arriba abajo. La usan
   Aprendizaje recomendado y el historial. El turno lo pone la plantilla en
   --orden, como en Temario: dejarlo en manos de `nth-child` ataba el CSS al
   número exacto de elementos, que aquí depende de cuántos tests tenga la
   categoría o de cuántos intentos entren en la página.

   `backwards` para que el elemento esté ya invisible antes de su turno; sin él
   aparece pintado y luego pega el salto. El tope de diez turnos es para que una
   categoría con veinte tests no tenga la última ficha esperando dos segundos.

   El movimiento es el mismo `temario-brota` de Temario a propósito: las dos
   pantallas se abren igual y no hay dos caídas distintas en la aplicación. */
.entra-en-orden{
animation:temario-brota .35s ease backwards;
animation-delay:calc(min(var(--orden,0),10) * 70ms);
}
@media (prefers-reduced-motion:reduce){
.entra-en-orden{animation:none}
}

/* — temario: los bloques y sus temas — */
/* Centrado y estrecho a propósito: es un índice que se lee de arriba abajo, no
   una pantalla de trabajo. Cada ficha lleva su color en --temario-color, que le
   pone la plantilla por posición: la pastilla y el enlace salen los dos de ahí,
   así que cambiar el color de una ficha es cambiar esa sola variable.
   Lo que no lleva es filo de color arriba: al seguir el redondeo de la esquina
   se curvaba hacia abajo por los lados y parecía un borde a medio pintar. */
.temario-page{max-width:1180px;text-align:center;position:relative}
.temario-volver{text-align:left;margin-bottom:var(--space-1)}
/* `width:fit-content` + `margin:auto` en vez de `inline-flex` suelto: un
   elemento inline no responde a `margin:auto`, así que se centraba solo donde
   el contenedor tenía `text-align:center` —la página de escritorio de
   Temario— y se quedaba pegado a la izquierda en los carruseles de móvil
   (Temario, «Para ti»), que no lo llevan puesto porque el resto de la página
   sí va alineado a la izquierda. Así se centra él solo en los dos sitios. */
.temario-kicker{
display:flex;width:fit-content;margin:0 auto;padding:6px var(--space-4);border-radius:999px;
background:var(--color-accent);color:var(--color-neutral-100);
font-size:11px;letter-spacing:.08em;text-transform:uppercase;font-weight:700;
}
/* En em y no en píxeles para que el ancho siga al tamaño del título, que es
   variable: 10em parte «Banco de preguntas / por temario» en dos líneas y las
   deja en dos a cualquier tamaño de pantalla. `balance` las iguala. */
.temario-titulo{margin:var(--space-4) auto var(--space-2);max-width:10em;text-wrap:balance;font-size:clamp(28px,4vw,42px);line-height:1.1;letter-spacing:-.02em}
.temario-resumen{margin:0 0 var(--space-8);font-size:14px;color:var(--color-neutral-600)}
.temario-resalte{color:var(--color-accent);font-weight:700}

.temario-raiz{display:flex;justify-content:center;margin-bottom:var(--space-8);animation:temario-brota .35s ease backwards;animation-delay:calc(var(--temario-orden) * var(--temario-paso))}
.temario-nodo{
display:flex;align-items:center;gap:var(--space-3);
/* 15px por lado sobre el espaciado normal: son los 30px de ancho de más que se
   le pidieron a la ficha, y no hay token que valga esa mitad. */
padding:var(--space-3) calc(var(--space-6) + 15px);border-radius:var(--radius-lg);
background:linear-gradient(135deg, var(--color-accent-500), var(--color-accent-600));
color:var(--color-neutral-100);text-decoration:none;text-align:left;
box-shadow:0 12px 28px color-mix(in srgb, var(--color-accent) 32%, transparent);
transition:transform .15s ease, box-shadow .15s ease;
}
.temario-nodo:hover{color:var(--color-neutral-100);text-decoration:none;transform:translateY(-3px);box-shadow:0 16px 34px color-mix(in srgb, var(--color-accent) 42%, transparent)}
.temario-nodo-icono{
display:flex;align-items:center;justify-content:center;flex-shrink:0;
width:38px;height:38px;border-radius:var(--radius-md);
background:color-mix(in srgb, var(--color-neutral-100) 22%, transparent);
}
.temario-nodo-texto{display:flex;flex-direction:column;gap:2px}
.temario-nodo-titulo{font-family:var(--font-heading);font-weight:700;font-size:16px}
.temario-nodo-cifra{font-size:12px;opacity:.85}

/* `dense` es lo que deja el panel pegado a su ficha en vez de al final de la
   fila: al ocupar toda la anchura salta de fila él solo, y `dense` rellena con
   las fichas siguientes el hueco que deja en la suya en vez de dejarlo vacío
   y empujarlas todas una fila más abajo. */
/* Sin esto, en el carrusel móvil cerrar el bloque abierto para abrir otro deja
   su panel en `display:none` justo encima de donde estabas mirando, y el
   navegador —que ancla el scroll a lo que hay a la vista para no dar saltos al
   cargar contenido— se queda sin nada a lo que anclarse y lo manda a él solo a
   la parte de arriba de la página. `overflow-anchor:none` le dice que no
   intente anclarse dentro de este árbol. */
.temario-arbol{overflow-anchor:none}
.temario-fila{display:grid;grid-template-columns:repeat(4,1fr);grid-auto-flow:dense;gap:var(--space-4)}
.temario-fila.is-siguiente{margin-top:var(--space-4)}
/* La ficha va dentro de una envoltura porque las marcas de la esquina son
   botones y la ficha es otro. La envoltura es la que se levanta y la que se
   apaga, para que las marcas la acompañen; la ficha solo pone su sombra. */
/* El levantarse cuelga de la envoltura y no del botón: la estrella está encima
   del botón pero fuera de él, así que con el `:hover` en el botón la ficha se
   descolgaba justo al llegar a la estrella y volvía a subir al salir. La
   envoltura cubre las dos cosas, y la ficha se queda quieta y arriba mientras el
   ratón esté en cualquier parte de ella. */
.temario-bloque-caja{
position:relative;display:flex;
transition:transform .15s ease, opacity .2s ease;
animation:temario-brota .35s ease backwards;
animation-delay:calc((var(--temario-orden) + var(--temario-indice) * .25) * var(--temario-paso));
}
.temario-bloque-caja:hover{transform:translateY(-3px)}
/* El rótulo de la marca se sale de la ficha por la derecha, y la ficha de al
   lado va después en el HTML: sin subir la caja mientras se apunta a la marca,
   la vecina se pinta encima y el texto se lee a medias. */
.temario-bloque-caja:has(.temario-marca:hover),
.temario-bloque-caja:has(.temario-marca:focus-visible){z-index:3}
.temario-bloque{
appearance:none;-webkit-appearance:none;
position:relative;flex:1;gap:var(--space-2);align-items:flex-start;
padding:var(--space-4);
border:none;background:var(--color-surface);
font:inherit;color:inherit;text-align:left;cursor:pointer;
transition:box-shadow .15s ease;
}
.temario-bloque-caja:hover .temario-bloque{box-shadow:var(--shadow-md)}
.temario-bloque.is-open{box-shadow:var(--shadow-md)}
.temario-bloque-cifras{display:flex;flex-wrap:wrap;gap:var(--space-2);margin-top:var(--space-1)}
.temario-tag-color{background:color-mix(in srgb, var(--temario-color) 14%, transparent);color:var(--temario-color)}
/* Con un bloque abierto, los demás se apagan: la lista de temas de abajo es
   larga y sin esto no se ve de cuál de los ocho está colgando. */
.temario-arbol.is-desplegado .temario-bloque-caja:not(.is-open){opacity:.4}
.temario-arbol.is-desplegado .temario-bloque-caja:not(.is-open):hover{opacity:1}
.temario-bloque-titulo{font-family:var(--font-heading);font-weight:700;font-size:14.5px;line-height:1.3;flex:1}
/* El título es lo primero de la ficha desde que no lleva icono, así que le caían
   encima la estrella y el visto: se les reserva el ancho, y solo donde están —sin
   sesión no hay marcas y el título ocupa la ficha entera—. */
.temario-bloque-caja:has(.temario-marcas) .temario-bloque-titulo{padding-right:50px}
/* «Ver temas» y su flecha se quedan quietos: avanzaban hacia la derecha con el
   ratón sobre la ficha, y al ir a por la estrella —que está encima del botón, con
   huecos entre medias— el rótulo se movía a tirones sin que se estuviera señalando
   nada. La ficha ya se levanta al pasar por encima, que dice lo mismo sin bailar. */
.temario-toggle{display:flex;align-items:center;gap:6px;padding-top:var(--space-2);font-size:12.5px;font-weight:600;color:var(--temario-color)}

/* — temario: la estrella y el visto de cada bloque — */
/* Las dos marcas van en la esquina de arriba a la derecha, encima de la ficha y
   del panel. `z-index` porque la ficha es un botón que ocupa la caja entera: sin
   él, el clic en la estrella se lo queda la ficha y el bloque se abre. */
.temario-marcas{position:absolute;top:var(--space-3);right:var(--space-3);z-index:1;display:flex;gap:2px}
.temario-panel .temario-marcas{top:var(--space-4);right:var(--space-4)}
.temario-marca{
position:relative;display:flex;align-items:center;justify-content:center;
width:26px;height:26px;padding:0;border:none;border-radius:var(--radius-sm);
background:none;color:var(--color-neutral-400);
transition:color .15s ease, background .15s ease;
}
/* Apagadas se quedan en gris claro; encendidas, cada una con su color. El visto
   no se pulsa —lo enciende haber acertado todo el bloque—, así que no cambia el
   cursor ni responde al ratón más que con su rótulo. */
.temario-marca-estrella{cursor:pointer}
.temario-marca-estrella:hover{background:color-mix(in srgb, var(--color-warn) 16%, transparent);color:var(--color-warn)}
.temario-marca-estrella.is-on{color:var(--color-warn)}
.temario-marca-estrella.is-on svg{fill:currentColor}
/* El aro: lo lleno va en `--aro-vuelta` (0-100) y el color en la clase. Se pinta
   con un cono y se le abre el agujero con una máscara redonda; así es un solo
   elemento vacío, sin SVG por bloque ni dos capas superpuestas.

   El surco se queda siempre visible por detrás: sin él, un bloque sin responder
   sería un hueco en la esquina y no se leería como «esto está a cero». */
/* El aro: el surco entero por detrás y encima el arco de lo respondido, que
   viene ya recortado del SVG. Aquí solo van los colores. El surco se ve siempre,
   también a cero: sin él, un bloque sin empezar sería un hueco en la esquina en
   vez de un aro vacío. */
.temario-aro{--aro-color:var(--color-neutral-300)}
.temario-aro-surco{stroke:var(--color-neutral-200)}
.temario-aro-arco{stroke:var(--aro-color)}
.temario-aro.is-bien{--aro-color:var(--color-success)}
.temario-aro.is-medio{--aro-color:var(--color-warn)}
.temario-aro.is-mal{--aro-color:var(--color-danger)}
/* Las de la última columna sacarían el rótulo fuera de la pantalla: ahí se
   alinea por la derecha en vez de centrarse. */
.temario-bloque-caja.is-ultimo .temario-marca:last-child::after,
.temario-panel .temario-marca:last-child::after{left:auto;right:0;transform:translateY(-2px)}
.temario-bloque-caja.is-ultimo .temario-marca:last-child:hover::after,
.temario-bloque-caja.is-ultimo .temario-marca:last-child:focus-visible::after,
.temario-panel .temario-marca:last-child:hover::after,
.temario-panel .temario-marca:last-child:focus-visible::after{transform:translateY(0)}

/* El panel ahora es un item más de la rejilla de `.temario-fila`: el `gap` de
   la rejilla ya pone la separación con la fila de fichas de encima, así que
   no lleva `margin-top` propio o la duplicaría. */
.temario-panel{grid-column:1/-1;position:relative;text-align:left;padding:var(--space-6);animation:temario-brota .3s ease}
.temario-panel-titulo{margin:0 0 var(--space-1);font-size:17px;display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-2)}
/* La parte del temario va pegada al título, no en la línea de las cifras: ahí
   quedaría como una cifra más y no lo es. Fuera de la altura de línea del
   titular, que es de 17px, para que no lo estire. */
.temario-panel-parte{font-family:var(--font-body);font-size:12px;line-height:1.3}
.temario-panel-cifras{margin:0 0 var(--space-4);font-size:13px;color:var(--color-neutral-600)}

/* — repaso inteligente: el desglose de la ficha — */
/* Descripción y motivos van en dos columnas mientras hay sitio para las dos:
   ver el comentario de la plantilla. Por debajo de 640px la ficha ya comparte
   fila con «Tus marcas» —su mismo corte, más abajo—, y esas dos columnas se
   quedaban tan estrechas que cada palabra de los motivos rompía en su propia
   línea. Apiladas, la línea divisoria pasa de vertical a horizontal. */
/* `container-type` y no `@media`: esta ficha se aprieta cuando la barra
   lateral se queda fija y ancha —sidebar expandida, ventana estrecha—, y ahí
   el hueco real es mucho menor que el ancho de la ventana. Un corte por
   viewport no ve eso: por eso el aviso de la barra lateral seguía roto justo
   antes de que la barra colapsara, con la ventana todavía "ancha". Con
   `container-type` la ficha responde a su propio ancho, tenga la barra al
   lado el tamaño que tenga.

   Va en `.sr-card` —la ficha entera, ver la plantilla— y no en `.sr-ficha`:
   un elemento no puede reestilarse a sí mismo por su propio `@container`, solo
   a sus descendientes. Puesto en `.sr-ficha` la consulta se evaluaba pero
   nunca cambiaba nada de `.sr-ficha`, que es justo la que necesita cambiar de
   columnas a fila. */
.sr-card{container-type:inline-size}
.sr-ficha{display:flex;gap:var(--space-4);align-items:stretch;max-width:760px;margin:0 auto}
.sr-ficha-motivos{flex:1;min-width:0;border-left:1px solid var(--color-divider);padding-left:var(--space-4)}
@container (max-width:380px){
.sr-ficha{flex-direction:column}
.sr-ficha-motivos{border-left:none;padding-left:0;border-top:1px solid var(--color-divider);padding-top:var(--space-4)}
}
/* Por debajo de esto la ficha ya no tiene sitio ni para los motivos apilados:
   el desglose completo se hace en la propia pantalla del repaso, así que se
   queda solo con lo que hace falta para decidir si empezarlo —qué es y
   cuántas preguntas trae. */
@container (max-width:280px){
.sr-ficha-motivos{display:none}
}
/* Cuatro motivos en columna, cada uno icono + cifra + texto en la misma línea:
   la lista queda al lado del bloque de texto, no debajo, así que va en su
   propia columna vertical y no apilada bajo la descripción. */
.sr-buckets{display:flex;flex-direction:column;gap:12px}
.sr-bucket{display:flex;align-items:center;gap:10px;font-size:13.5px}
/* Ancho fijo y alineada a la izquierda: centrada, un número de dos cifras
   («55») arranca más a la izquierda que uno de una («3»), y las cuatro cifras
   dejan de alinearse entre ellas de una fila a la siguiente. A la izquierda
   dentro del mismo hueco fijo, todas arrancan en el mismo punto —pegadas al
   icono— y de paso el texto de al lado sigue arrancando siempre igual. */
.sr-bucket-numero{
font-family:var(--font-heading);font-weight:700;font-size:14px;
flex-shrink:0;min-width:20px;text-align:left;
}
/* El color va solo en el icono de cada motivo: con el texto también coloreado,
   los cuatro juntos se leían como un arcoíris en vez de una lista. */
.sr-bucket-etiqueta{color:var(--color-text)}
/* Círculo de color detrás, como `.help-icon`: son emoji de toda la vida
   sustituidos por iconos de línea, y sin el fondo se quedaban demasiado
   discretos al lado del texto en negrita de al lado. */
.sr-bucket-icono{
flex:none;width:32px;height:32px;border-radius:var(--radius-md);
display:flex;align-items:center;justify-content:center;
}
.sr-bucket-icono svg{width:16px;height:16px}
/* Un color por bucket, para distinguirlos de un vistazo igual que hacían los
   emoji que sustituyen. `nuevas` usa un color de serie —de los reservados a
   distinguir categorías en las gráficas— porque no hay ningún tono semántico
   (éxito/aviso/peligro) que le pegue: no es ni bueno ni malo, es solo nuevo. */
.sr-bucket-icono.is-repaso{background:var(--color-alerta-100);color:var(--color-alerta)}
.sr-bucket-icono.is-dudas{background:var(--color-warn-100);color:var(--color-warn)}
.sr-bucket-icono.is-stale{background:var(--color-accent-100);color:var(--color-accent)}
.sr-bucket-icono.is-nuevas{background:color-mix(in srgb, var(--series-3) 18%, transparent);color:var(--series-3)}
.sr-bucket-icono.is-consolidar{background:var(--color-success-100);color:var(--color-success)}

/* El desglose de aciertos, solo con sesión. La tabla se desborda a lo ancho en
   su propia caja: la página no debe moverse de lado por una columna de más. */
.temario-tabla-envoltorio{overflow-x:auto}
.temario-tabla td{vertical-align:middle}
/* `.table th` alinea a la izquierda, así que el centrado va en las dos: si no,
   el rótulo y su cifra quedan cada uno en un sitio. */
.temario-tabla th.temario-cifra,
.temario-tabla td.temario-cifra{text-align:center;font-variant-numeric:tabular-nums}
.temario-tabla-tema{color:inherit;text-decoration:none;font-weight:600}
/* La fila entera abre el test del tema, así que se anuncia como pulsable: sin el
   cursor, el único sitio que parecía tener enlace seguía siendo el nombre. */
.temario-tabla-fila{cursor:pointer}
.temario-tabla-tema:hover{color:inherit;text-decoration:none}
/* De qué área es el tema, debajo de su nombre. Solo hace falta en la
   recomendación del aprendizaje: en Temario la tabla ya cuelga de su área y
   repetirla en cada fila sería decir cuatro veces lo mismo. */
.temario-tabla-area{display:block;font-size:11.5px;color:var(--color-neutral-600);margin-top:1px}
/* Se marca la fila entera, no el texto: son cuatro columnas que se leen juntas y
   subrayar solo el título dejaba fuera las cifras que lo acompañan. El filo va en
   `box-shadow` y no en `border-left` para que no empuje el contenido al entrar.

   Las bandas alternas de `.table` se quedan mientras el ratón está fuera, que
   ayudan a seguir una fila de punta a punta; en cuanto entra se apagan todas y
   solo queda encendida la señalada, que con las demás grises no se distinguía.

   El apagado va por `tbody:hover`, así que pesa más que el resalte de la fila:
   por eso este también cuelga de `tbody:hover`, o la fila par señalada se
   quedaría en blanco. */
.temario-tabla tbody tr{transition:background .15s ease}
.temario-tabla tbody:hover tr:nth-child(even){background:transparent}
.temario-tabla tbody:hover tr:hover{background:color-mix(in srgb, var(--color-text) 5%, transparent)}
.temario-tabla tbody tr:hover td:first-child{box-shadow:inset 3px 0 0 var(--color-accent)}
.temario-progreso{display:flex;align-items:center;gap:var(--space-2);min-width:150px}
.temario-barra{flex:1;display:flex;height:10px;border-radius:999px;overflow:hidden;background:var(--color-neutral-300)}
.temario-barra-ok{background:var(--color-success)}
.temario-barra-mal{background:var(--color-danger)}
.temario-progreso-pct{font-size:12.5px;font-variant-numeric:tabular-nums;white-space:nowrap;color:var(--color-neutral-600)}
.temario-temas{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:var(--space-3)}
.temario-tema{
display:flex;align-items:center;gap:var(--space-3);
padding:var(--space-3);border-radius:var(--radius-md);
border:1px solid var(--color-divider);background:var(--color-surface);
color:inherit;text-decoration:none;
transition:transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
.temario-tema:hover{color:inherit;text-decoration:none;transform:translateY(-2px);box-shadow:var(--shadow-sm);border-color:var(--color-accent);background:var(--color-accent-100)}
.temario-tema-titulo{flex:1;font-size:13.5px;line-height:1.3}
.temario-tema-cifra{font-size:12px;color:var(--color-neutral-600);white-space:nowrap}
.temario-tema-flecha{flex-shrink:0;color:var(--color-accent);transition:transform .15s ease}
.temario-tema:hover .temario-tema-flecha{transform:translateX(3px)}

/* Mismo desglose que `.temario-tabla`, en fila y no en columnas: por debajo de
   520px —donde `.temario-fila` ya deja un bloque por línea— cuatro columnas
   con barra de progreso no caben legibles y la tabla solo se leía deslizando
   de lado. Las dos se pintan siempre (`filasMovil()` en temario_category.html)
   y esta media query decide cuál se ve, así que un cambio de ancho de ventana
   no obliga a repintar nada. */
.temario-temas-movil{display:none;flex-direction:column}
@media (max-width:520px){
/* Acotado a `.temario-panel`: `.temario-tabla-envoltorio` es la misma clase
   que usa la tabla de «Recomendación por temario» en Aprendizaje recomendado,
   que no lleva `.temario-temas-movil` al lado y no debe apagarse aquí. */
.temario-panel .temario-tabla-envoltorio{display:none}
.temario-temas-movil{display:flex}
}
.temario-tema-movil{
display:flex;flex-direction:column;gap:6px;padding:12px 0;
border-top:1px solid var(--color-divider);color:inherit;text-decoration:none;
}
.temario-tema-movil:first-child{border-top:none;padding-top:2px}
.temario-tema-movil:hover{color:inherit;text-decoration:none}
.temario-tema-movil-fila1{display:flex;align-items:flex-start;gap:8px}
.temario-tema-movil-titulo{flex:1;font-size:13.5px;font-weight:600;line-height:1.3}
.temario-tema-movil-fila2{display:flex;align-items:center;gap:var(--space-2)}
.temario-tema-movil-fila2 .temario-barra{flex:1}

/* La página se arma de arriba abajo al cargar: primero la raíz y luego cada fila
   de bloques, con un pequeño desfase de izquierda a derecha dentro de la fila.
   El retraso sale de --temario-orden y --temario-indice, que reparte la
   plantilla, así que añadir una fila no obliga a tocar nada aquí. */
.temario-page{--temario-paso:90ms}
@keyframes temario-brota{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:none}}

@media (prefers-reduced-motion:reduce){
.temario-nodo,.temario-tema,.temario-bloque-caja{transition:box-shadow .15s ease, border-color .15s ease, opacity .2s ease}
.temario-nodo:hover,.temario-tema:hover,.temario-bloque-caja:hover{transform:none}
.temario-tema:hover .temario-tema-flecha{transform:none}
.temario-raiz,.temario-bloque-caja,.temario-panel{animation:none}
}

/* Los mismos cortes que .categories-grid: son fichas del mismo tamaño y en la
   misma pantalla, y con otros la página se reorganizaría dos veces seguidas. */
@media (max-width:1180px){
.temario-fila{grid-template-columns:repeat(3,1fr)}
}
@media (max-width:860px){
.temario-fila{grid-template-columns:repeat(2,1fr)}
}
@media (max-width:520px){
.temario-fila{grid-template-columns:1fr}
}

/* — temario: carrusel móvil —
   Mismo reparto que Categoría y Aprendizaje recomendado: por debajo de 760px
   `.temario-escritorio` desaparece entero —la fila de pestañas no cabe
   deslizable ahí abajo— y `.temario-movil` ocupa su sitio con un panel por
   categoría, deslizable con el dedo (ver el script de temario_category.html).
   Los bloques del panel activo ya se leían bien en una columna gracias a
   `.temario-fila` en 520px; el carrusel no cambia eso, solo cómo se llega a
   la categoría. */
.temario-movil{display:none}
@media (max-width:760px){
.temario-escritorio{display:none}
.temario-movil{display:block}
}

/* Aquí no hay `.temario-fila` de por medio —cada página del carrusel mete sus
   bloques sueltos, uno bajo otro, directamente en `.temario-arbol`—, así que
   sin este `gap` las fichas quedaban pegadas: el `gap` de `.temario-fila` no
   llega hasta aquí porque esa clase ni se pinta en el carrusel. */
.temario-movil .temario-arbol{display:flex;flex-direction:column;gap:var(--space-4)}

.temario-movil-puntos{display:flex;justify-content:center;gap:6px;margin-bottom:var(--space-3)}
.temario-movil-punto{
width:7px;height:7px;border-radius:999px;padding:0;border:0;
background:var(--color-neutral-400);cursor:pointer;
transition:width .2s ease, background .2s ease;
}
.temario-movil-punto.is-active{width:20px;background:var(--color-accent)}

/* `align-items:flex-start` y no el `stretch` de siempre: una fila flex estira
   cada hijo a la altura del más alto, y con una categoría de ocho bloques al
   lado de una de tres, la de tres se quedaba con el hueco entero de la de
   ocho debajo. El script (`ajustarAlturaMovilActiva()`) fija la altura de la
   fila a la de la página que se ve en cada momento; `flex-start` es solo para
   que, antes de que corra ese script, ninguna página se estire de más. La
   `transition` es lo que suaviza el cambio de alto al deslizar entre
   categorías de tamaños distintos. */
.temario-movil-pistas{
display:flex;align-items:flex-start;overflow-x:auto;scroll-snap-type:x mandatory;
scrollbar-width:none;-ms-overflow-style:none;
transition:height .2s ease;
}
.temario-movil-pistas::-webkit-scrollbar{display:none}
/* El hueco a los lados no es solo estético: a mitad de gesto se ven dos
   páginas a la vez —la que se deja y la que llega—, y sin este padding sus
   fichas quedaban pegadas por el borde como si fueran la misma categoría. */
/* `position:relative` para la cinta de fijar (`.pin-ribbon.card-pin`), que se
   coloca contra la página entera sin envoltorio nuevo —mismo truco que ya usa
   `.inicio-card`—. */
.temario-movil-pagina{position:relative;flex:0 0 100%;min-width:0;scroll-snap-align:start;padding:0 var(--space-2)}

/* — pin / flag marks — */
/* Iconos de línea sin caja: apagados son un gris que no compite con la pregunta,
   y encendidos se tiñen del color de lo que significan —fijada en azul, marcada
   en ámbar—. Antes eran un botón redondo con borde para cada emoji: cuatro
   círculos al lado del enunciado pesaban más que el enunciado.

   El rótulo al pasar por encima lo pone `.pista`, no `title`. */
.quiz-pregunta-iconos{display:flex;gap:4px;flex-shrink:0}
.quiz-actions-spacer{flex:1}
.mark-btn-wrap{position:relative}
.mark-btn{
appearance:none;-webkit-appearance:none;
width:32px;height:32px;padding:0;border-radius:var(--radius-sm);
border:none;background:none;
color:var(--color-neutral-500);
display:flex;align-items:center;justify-content:center;line-height:1;cursor:pointer;
transition:background .15s ease, color .15s ease;
user-select:none;-webkit-user-select:none;-webkit-tap-highlight-color:transparent;
}
.mark-btn svg{display:block}
/* Solo con ratón: en táctil el :hover se queda pegado tras pulsar y el botón
   parece seleccionado. */
@media (hover:hover){
.mark-btn:hover{background:var(--color-neutral-200);color:var(--color-text)}
}
.mark-btn.is-active{color:var(--color-accent)}
.mark-advertencia.is-active{color:var(--color-warn)}
.mark-btn.mark-pop{animation:mark-pop .4s ease}
@keyframes mark-pop{
0%{transform:scale(1)}
35%{transform:scale(1.35)}
60%{transform:scale(.92)}
100%{transform:scale(1)}
}
/* El aviso de «Fijada» y el rótulo del hover caen en el mismo sitio: mientras el
   aviso está puesto —lo quita el JS a los dos segundos— el rótulo se calla, o se
   pintan uno encima del otro justo después de pulsar. */
.mark-btn-wrap:has(.mark-msg:not(.d-none)) .pista::after{opacity:0}
.mark-msg{
position:absolute;top:100%;right:0;margin-top:4px;z-index:1;
font-size:11px;white-space:nowrap;color:var(--color-accent-800);
background:var(--color-accent-100);padding:2px 8px;border-radius:999px;
}

/* — review lists — */
.review-list{display:flex;flex-direction:column;gap:var(--space-4)}
.review-card{padding:var(--space-4)}
.review-list.is-resolved .op-opt[data-correct="true"]:not(.is-locked){
background:var(--color-success-100);border-color:var(--color-success);color:var(--color-success-800);
}
.review-list.is-resolved .op-opt[data-correct="true"]:not(.is-locked) .op-badge{
background:var(--color-success);color:#fff;
}
/* Con la respuesta ya a la vista, responder no evalúa nada: se quita el clic
   además de en JS, para que el cursor ya avise de que ahí no hay nada que
   pulsar en vez de que solo se note al intentarlo. */
.review-list.is-resolved .op-opt:not(.is-locked){cursor:default;pointer-events:none}

/* — panel de administración — */
/* El panel no vive dentro de .app-shell: no tiene barra lateral, así que se
   centra él solo en vez de heredar el hueco que la barra deja. */
.admin-shell{max-width:1040px;margin:0 auto;padding:var(--space-8) var(--space-6)}
.admin-header{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--space-4);margin-bottom:var(--space-8)}
.admin-meta{display:flex;align-items:center;gap:var(--space-3);flex-shrink:0}
.admin-kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:var(--space-4);margin-bottom:var(--space-6)}
.admin-block{margin-bottom:var(--space-6)}
/* Catorce columnas no caben con el gap de 16px del gráfico de dominio, que solo
   pinta cuatro barras. */
.admin-chart{gap:var(--space-1);height:180px}
.admin-chart .dominio-bar-label{font-size:10.5px}
.admin-chart .dominio-bar-count{font-size:13px}
/* Cuatro columnas de tabla no encogen por debajo de su contenido: sin esto, en
   el móvil la tabla ensancha la página entera en vez de desplazarse ella. */
.admin-scroll{overflow-x:auto}
.admin-nota{font-size:13px;max-width:640px;margin:var(--space-8) 0 0}

/* — misc — */
.category-search{max-width:520px}

/* — responsive / mobile — */
.mobile-topbar{
display:none;
align-items:center;gap:12px;
position:sticky;top:0;z-index:900;
padding:10px var(--space-4);
background:var(--color-surface);border-bottom:1px solid var(--color-divider);
}
.sidebar-backdrop{
display:none;
position:fixed;inset:0;
background:color-mix(in srgb, var(--color-neutral-900) 50%, transparent);
z-index:1000;
}
.sidebar-backdrop.is-open{display:block}

@media (max-width:860px){

.mobile-topbar{display:flex}

.app-shell{height:auto;min-height:100vh}

.sidebar{
position:fixed;top:0;left:0;height:100vh;width:268px;max-width:82%;
transform:translateX(-100%);transition:transform .25s ease;
z-index:1001;
}
.sidebar.is-open{transform:translateX(0)}
.sidebar .btn-icon[aria-label="Colapsar menú"]{display:none}

.app-main{padding:var(--space-4) var(--space-3)}
.app-main-inner{max-width:100%}
/* Menos margen lateral solo en el test: es la pantalla con menos alrededor —una
   pregunta y sus respuestas— y con más margen sobraba más que en cualquier otra. */
.app-main:has(.quiz-main-inner){padding-left:var(--space-2);padding-right:var(--space-2)}

/* La pantalla de pregunta, a tarjetas sueltas sobre el fondo azulado de
   `body` (`--color-bg`) en vez de una única tarjeta grande —cabecera,
   pregunta, cada respuesta y la barra de abajo, cada una la suya, como en
   el mockup que trajo el usuario—. `#quiz-panel` pasa a ser un contenedor
   transparente que solo separa a sus hijos directos; cada pieza pone su
   propia tarjeta. */
/* !important en padding y gap porque el `style="padding:var(--space-6);gap:0"`
   del HTML —pensado para la tarjeta única de escritorio— pesa más que esta
   regla sin ellos: quedaban 24px de más a cada lado en todos sus hijos
   directos (cabecera, pregunta, respuestas, acciones), y sobre todo el hueco
   entre tarjetas se quedaba en 0 en vez de en var(--space-3) —de ahí que la
   separación antes de la primera pregunta no fuera la misma que entre el
   resto de tarjetas: no había ninguna, en ningún sitio—. */
#quiz-panel{
background:transparent;box-shadow:none;padding:0 !important;
display:flex;flex-direction:column;gap:var(--space-3) !important;
}
/* Título y contador en la misma fila, la barra debajo a todo lo ancho, como
   en el mockup: rejilla sobre los hijos directos de la cabecera en vez de
   las dos filas de escritorio (título arriba, «Pregunta X» + chapas debajo).
   `.progress-track` no entra en la plantilla de áreas: sigue con
   `display:none` más abajo, así que deja de ser hijo de rejilla y no le
   hace falta hueco propio. */
/* A todo lo ancho, pegada a la barra superior salvo un margen pequeño: los
   márgenes negativos cancelan el padding lateral y parte del superior de
   `.app-main` —sin tocarlo para el resto de la página, solo para esta
   tarjeta—, así que no hace falta sacarla de `.app-main` en la plantilla. */
.quiz-cabecera{
background:var(--color-surface);border-radius:0;
box-shadow:var(--shadow-sm);padding:var(--space-4);
margin:calc(-1 * var(--space-2)) calc(-1 * var(--space-2)) 0;
display:grid;grid-template-columns:1fr auto;
grid-template-areas:"titulo contador" "tramos tramos";
column-gap:var(--space-3);row-gap:var(--space-2);align-items:center;
}
.quiz-cabecera h1{grid-area:titulo;margin:0 !important;font-size:17px;font-weight:800;line-height:1.25}
/* «Pregunta X» sobra aquí: el número grande de la tarjeta de la pregunta, más
   abajo, ya dice lo mismo. Solo se esconde el rótulo, no la fila entera —las
   chapas de respondidas/temporizador se quedan—, así que `justify-content`
   pasa de repartir dos huecos a alinear el que queda contra la derecha;
   ambos con `!important` porque pisan un `style` en el HTML pensado para la
   fila de escritorio. */
.quiz-cabecera h5#contador{display:none}
.quiz-cabecera h1 + div{grid-area:contador;margin:0 !important;justify-content:flex-end !important}
/* La fila de la pregunta pasa de fila a rejilla: número+«Pregunta» e iconos
   en la fila de arriba —como en el mockup—, y el enunciado debajo a todo lo
   ancho, no al lado de los iconos como en escritorio, donde no cabría.
   `margin:0` con `!important` porque el margen inferior es un `style` en el
   HTML pensado para la fila de escritorio: aquí ese hueco ya lo pone el
   `gap` de `#quiz-panel`. */
.quiz-pregunta-fila{
background:var(--color-surface);border-radius:var(--radius-lg);
box-shadow:var(--shadow-sm);padding:var(--space-4);margin:0 !important;
/* `display:grid` con !important porque el `style="display:flex"` del HTML
   —el de escritorio, donde número+pregunta+iconos van en una sola fila— tiene
   más especificidad que cualquier regla de este fichero y si no se fuerza
   gana igual dentro de este `@media`, dejando la pregunta metida como hijo
   flex más en la fila de arriba: se ve como una columna de una palabra de
   ancho, no como el enunciado a todo lo ancho debajo. */
display:grid !important;grid-template-columns:auto 1fr auto;
grid-template-areas:"numero . iconos" "texto texto texto";
column-gap:10px;row-gap:12px;align-items:start;
}
.quiz-pregunta-numero-grupo{display:inline-flex;align-items:center;gap:8px;grid-area:numero}
.quiz-pregunta-numero{font-family:var(--font-heading);font-weight:800;font-size:22px;line-height:1;color:var(--color-accent)}
.quiz-pregunta-etiqueta{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--color-neutral-500)}
.quiz-pregunta-iconos{grid-area:iconos;gap:14px}
#pregunta{grid-area:texto;font-size:18px}
/* Piezas del mockup de móvil, ahora a la vista —ver por qué empiezan ocultas
   junto a `.progress-fill` más arriba—. Acotado a la cabecera del quiz: un
   `.progress-track` suelto aquí escondía también la barra de «Tu dominio por
   tema» en Para ti, que reutiliza la misma clase para su propia barra. */
.quiz-cabecera .progress-track{display:none}
.quiz-barra-segmentada{display:flex;gap:3px;margin-bottom:0;grid-area:tramos}
.quiz-barra-segmentada-tramo{flex:1;height:5px;border-radius:999px;background:var(--color-neutral-300)}
.quiz-barra-segmentada-tramo.is-lleno{background:var(--color-accent)}
#respuestas{display:flex;flex-direction:column;gap:var(--space-3)}
/* Ya no se fuerza el borde a transparente sustituyéndolo por sombra: el de
   1.5px con --color-divider de escritorio es el mismo del mockup, y sin
   pisarlo aquí las clases de estado (seleccionada/correcta/incorrecta)
   vuelven a pintar el suyo en vez de quedarse tapadas por esta regla con id,
   de más especificidad que ellas. */
#respuestas .op-opt{border-radius:var(--radius-lg);margin-bottom:0}
/* Anterior/Siguiente clavados abajo del todo, como una tarjeta flotante y no
   una franja pegada a los tres bordes: `left`/`right`/`bottom` a 0 miden
   contra el viewport, y el margen de después la separa de los tres,
   esquinas redondeadas en vez de vivas. `position:fixed` la saca del flujo
   de `#quiz-panel`, así que ya no cuenta para su `gap` —de ahí el padding de
   más en `.quiz-main-inner`, para que la última respuesta no quede tapada
   debajo—. */
#quiz-actions{
position:fixed;left:0;right:0;bottom:0;z-index:900;
margin:0 var(--space-3) var(--space-3) !important;
background:var(--color-surface);border-radius:var(--radius-lg);
box-shadow:0 8px 24px color-mix(in srgb, var(--color-neutral-900) 18%, transparent);
padding:var(--space-3) var(--space-3) calc(var(--space-3) + env(safe-area-inset-bottom));
}
/* Alto de #quiz-actions en móvil: los botones miden 52px (ver
   .quiz-btn-anterior/.quiz-btn-siguiente) más var(--space-3) de padding
   arriba y abajo, más el margen que ahora la separa del borde. Sin este
   hueco, el fijado de encima taparía la última respuesta o el aviso de
   resultado. */
.quiz-main-inner{padding-bottom:calc(52px + var(--space-3) * 3 + env(safe-area-inset-bottom))}
/* La flecha solo se enseña si hay algo que desplegar: `#finalizar-btn` o
   `#volver-evaluacion-btn` a la vista (nunca los dos a la vez). En estudio
   ninguno lo está, así que tampoco ella. Mide lo mismo de alto que Anterior/
   Siguiente para quedar alineada con ellos; más ancha que alta y no cuadrada,
   que con solo 52px se quedaba en una tira fina apretada contra el icono. */
.quiz-actions:has(#finalizar-btn:not(.d-none)) .quiz-finalizar-toggle,
.quiz-actions:has(#volver-evaluacion-btn:not(.d-none)) .quiz-finalizar-toggle{display:inline-flex}
.quiz-finalizar-toggle{order:3;width:68px;height:52px;border-radius:var(--radius-lg)}
.quiz-finalizar-toggle svg{transition:transform .2s ease}
.quiz-actions.is-open .quiz-finalizar-toggle svg{transform:rotate(180deg)}
/* Plegados hasta que se abre la flecha: a todo lo ancho y antes que
   Anterior/Siguiente, como en el mockup, no metidos en la misma fila. */
#finalizar-btn,#volver-evaluacion-btn{display:none}
.quiz-actions.is-open #finalizar-btn:not(.d-none),
.quiz-actions.is-open #volver-evaluacion-btn:not(.d-none){
display:flex;order:0;flex:1 0 100%;width:100%;margin-bottom:2px;
justify-content:center;padding:14px;font-size:15px;
}
/* Aviso en el mismo tono suave de peligro del resto de la aplicación
   —derivado de --color-danger— en vez del botón secundario neutro de
   escritorio con solo el texto en rojo. */
.quiz-actions.is-open #finalizar-btn:not(.d-none){
background:var(--color-danger-100);
border-color:color-mix(in srgb, var(--color-danger) 35%, transparent);
}

/* Anterior y Siguiente se reparten casi todo el ancho a partes iguales,
   grandes y fáciles de tocar, como en el mockup, en vez de angostos con
   hueco de sobra entre medias. `order` los coloca aunque en el marcado el
   del medio (Finalizar test / Evaluación del examen / Ver todas) vaya entre
   los otros dos. */
.quiz-actions{flex-direction:row;flex-wrap:wrap;gap:var(--space-2);align-items:stretch}
.quiz-actions .btn{width:auto}
.quiz-btn-anterior,.quiz-btn-siguiente{flex:1 1 0;justify-content:center;padding:14px;font-size:15px;min-height:52px}
.quiz-btn-anterior{order:1}
.quiz-btn-siguiente{order:2;box-shadow:0 8px 18px color-mix(in srgb, var(--color-accent) 30%, transparent)}
.quiz-actions-spacer{display:none}
#finalizar-btn,#volver-evaluacion-btn,#study-grid-btn{order:3;flex:0 0 auto;width:auto}

.admin-shell{padding:var(--space-6) var(--space-3)}
.admin-header{flex-direction:column}

/* Dos columnas y no apilado: el título, la descripción y el recuento a la
   izquierda; el anillo del porcentaje a la derecha, pegado arriba en vez de
   centrado en el alto de las dos filas, que es lo primero que se quiere ver.
   En vez de encoger el anillo por debajo de 78px —donde la cifra de dentro
   deja de leerse— se le da su propia columna. */
.evaluacion-cabecera{display:grid;grid-template-columns:1fr auto;align-items:center;gap:var(--space-3)}
.evaluacion-cabecera-texto{grid-column:1;grid-row:1}
.evaluacion-cifras{grid-column:1;grid-row:2}
#evaluacion-anillo{grid-column:2;grid-row:1 / span 2;align-self:start}

/* Dos rótulos largos en paralelo no caben en un móvil: se apilan, cada uno con
   el ancho entero. */
.evaluacion-acciones{flex-direction:column}

}

@media (max-width:480px){

.dialog{padding:var(--space-4)}
.card{padding:var(--space-3)}
.op-opt{padding:12px}

}
