/* Vistas: estilos específicos de cada página (portada, listado de retos,
   panel del profesor, gestión de usuarios...). Extraído de app.css
   (Tarea 2) sin cambiar ningún valor. */

/* --- Portada: cifras (tiles) y tabla de retos -----------------------------
   Reemplaza a la agrupación por dificultad en tarjetas (Tarea 8). `.tile` es
   el componente de componentes.css; aquí solo va la rejilla que los coloca. */

.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1rem;
  margin-bottom: 1.5rem;
}
.valor-total { font-size: 0.62em; color: var(--texto-tenue); font-weight: 400; }
/* Barra de progreso dentro de un .tile: más fina que la suelta de abajo. */
.tile .progreso { height: 4px; min-width: 0; }

/* <progress>: sin ancho en línea (la CSP prohíbe estilos embebidos). */
.progreso {
  flex: 1;
  min-width: 180px;
  height: 9px;
  border: 1px solid var(--borde);
  border-radius: 999px;
  background: var(--fondo);
  overflow: hidden;
  -webkit-appearance: none;
  appearance: none;
}
.progreso::-webkit-progress-bar { background: transparent; }
.progreso::-webkit-progress-value { background: linear-gradient(90deg, var(--verde), var(--ambar)); border-radius: 999px; }
.progreso::-moz-progress-bar { background: linear-gradient(90deg, var(--verde), var(--ambar)); border-radius: 999px; }

/* --- Filtros y buscador de la portada (Tarea 9) ---------------------------
   `.chip` es de componentes.css; aquí solo van los envoltorios (fila
   completa, cada grupo de chips, la caja de búsqueda), que no existían. */

.filtros-fila {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  flex-wrap: wrap;
  margin-bottom: 1.25rem;
}
.filtros-grupo { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }

.buscador {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  border: 1px solid var(--borde);
  background: var(--fondo-alt);
  border-radius: var(--radio-sm);
  padding: 0.5rem 0.75rem;
  flex: 1 1 220px;
  max-width: 320px;
}
.buscador svg { flex: none; color: var(--texto-tenue); }
.buscador input[type="text"] {
  width: 100%;
  min-width: 0;
  padding: 0;
  border: none;
  background: none;
}
.buscador input[type="text"]:focus { outline: none; box-shadow: none; }

/* --- Celdas de la tabla de retos ------------------------------------------- */

.reto-celda { display: flex; flex-direction: column; gap: 0.2rem; }
.reto-celda a { color: var(--texto); font-weight: 500; }
.reto-celda a:hover { color: var(--verde); text-decoration: none; }
.reto-slug { font-family: var(--mono); font-size: 0.72rem; color: var(--texto-tenue); }

.dificultad-celda { display: flex; align-items: center; gap: 0.55rem; }

.login-marca {
  font-weight: 700;
  font-size: 1.25rem;
  letter-spacing: 0.04em;
  color: var(--texto);
  margin: 0 0 1.25rem;
}

/* --- Metadatos de reto (detalle y clase) ----------------------------------
   La agrupación por dificultad en tarjetas de la portada desapareció en la
   Tarea 8 (ahora es la tabla de arriba); esto sigue en pie de reto.html y
   admin_clase_detalle.html. */

/* Cabecera a dos columnas del detalle de reto: título/pills a la izquierda,
   `.sello` (componentes.css) a la derecha (Reto.dc.html «header»). */
.reto-cabecera {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 2rem;
  margin-bottom: 1.5rem;
  flex-wrap: wrap;
}
.reto-cabecera-info { flex: 1 1 320px; min-width: 0; }
.reto-cabecera-info .prompt { margin-bottom: 0.7rem; }

/* A 400px el `flex-wrap` de arriba ya manda el sello a su propia línea (su
   base de 120px no cabe junto a los 320px de `.reto-cabecera-info`); aquí
   además lo encogemos para que no quede desproporcionado en una pantalla tan
   estrecha (repaso a 400px, Tarea 17). */
@media (max-width: 480px) {
  .reto-cabecera { flex-direction: column; }
  .sello { width: 84px; height: 84px; align-self: flex-start; }
  .sello-titulo { font-size: 11px; }
  .sello-puesto { font-size: 18px; }
}

.reto-meta { display: flex; gap: 0.4rem; align-items: center; flex-wrap: wrap; margin: -0.25rem 0 0.6rem; }

.dif-básica    { color: var(--verde); border-color: rgba(var(--verde-rgb), 0.5); background: rgba(var(--verde-rgb), 0.08); }
.dif-media     { color: var(--ambar); border-color: rgba(var(--ambar-rgb), 0.5); background: rgba(var(--ambar-rgb), 0.08); }
.dif-avanzada  { color: var(--rojo);  border-color: rgba(var(--rojo-rgb), 0.5);  background: rgba(var(--rojo-rgb), 0.08); }

.ayuda-inline { color: var(--texto-tenue); font-size: 0.75rem; }

.cuenta-atras { font-variant-numeric: tabular-nums; }
.cuenta-atras-urgente { color: var(--ambar); }
.cuenta-atras-cerrada { color: var(--rojo); }

.migas { font-size: 0.78rem; color: var(--texto-tenue); margin: 0 0 0.85rem; }
.migas a:hover { color: var(--verde); }

.subtitulo { font-size: 0.95rem; margin: 0 0 1rem; color: var(--texto); }

/* --- Enunciado y guía en Markdown ------------------------------------------
   `.rejilla-lab-guia` (la guía del laboratorio, Tarea 10) comparte toda esta
   tipografía con `.enunciado`: ambas son el mismo `markdown_seguro()` y deben
   leerse igual. */

.enunciado, .rejilla-lab-guia { margin-bottom: 1.25rem; }
.enunciado h1, .enunciado h2, .rejilla-lab-guia h1, .rejilla-lab-guia h2 { font-size: 1.02rem; margin: 1.6rem 0 0.6rem; }
.enunciado h1:first-child, .enunciado h2:first-child,
.rejilla-lab-guia h1:first-child, .rejilla-lab-guia h2:first-child { margin-top: 0; }
.enunciado h3, .rejilla-lab-guia h3 { font-size: 0.9rem; margin: 1.2rem 0 0.5rem; }
.enunciado p, .enunciado li, .rejilla-lab-guia p, .rejilla-lab-guia li { font-size: 0.9rem; }
.enunciado a, .rejilla-lab-guia a { text-decoration: underline; text-underline-offset: 2px; }
.enunciado code, .rejilla-lab-guia code {
  background: var(--fondo);
  border: 1px solid var(--borde);
  border-radius: var(--radio-xs);
  padding: 0.06rem 0.34rem;
  font-size: 0.85em;
  color: var(--ambar);
}
.enunciado pre, .rejilla-lab-guia pre {
  background: #0c1213;
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
  padding: 0.9rem 1.05rem;
  overflow-x: auto;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2);
}
.enunciado pre code, .rejilla-lab-guia pre code { background: none; border: none; padding: 0; color: var(--texto); }
.enunciado hr, .rejilla-lab-guia hr { border: none; border-top: 1px solid var(--borde); margin: 1.5rem 0; }
.enunciado table, .rejilla-lab-guia table { border-collapse: collapse; width: 100%; font-size: 0.85rem; }
.enunciado th, .enunciado td, .rejilla-lab-guia th, .rejilla-lab-guia td { border: 1px solid var(--borde); padding: 0.45rem 0.65rem; text-align: left; }
.enunciado th, .rejilla-lab-guia th { background: rgba(255, 255, 255, 0.02); }

/* --- Tarjeta de laboratorio: guía a la izquierda, ficha a la derecha ------- */

.rejilla-lab {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: 2rem;
  align-items: start;
}

.ficha { display: flex; flex-direction: column; gap: 0.65rem; }
.ficha .boton { width: 100%; margin-top: 0.15rem; }
.ficha-fila {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  font-family: var(--mono);
  font-size: 0.82rem;
}
.ficha-clave { color: var(--texto-tenue); }
.ficha-valor { color: var(--texto); }

@media (max-width: 760px) {
  .rejilla-lab { grid-template-columns: 1fr; }
}

/* --- Estado de resolución -------------------------------------------------- */

.estado-resuelto { color: var(--verde); border-color: rgba(var(--verde-rgb), 0.4); background: rgba(var(--verde-rgb), 0.07); padding: 0.12rem 0.5rem; border-radius: 999px; }

.puntos { color: var(--ambar); font-weight: 700; font-size: 1.05rem; }

/* --- Panel del profesor --------------------------------------------------- */

.admin-nav {
  display: flex;
  gap: 0.5rem;
  padding: 0 0 0.85rem;
  margin-bottom: 1.5rem;
  border-bottom: 1px solid var(--borde);
  flex-wrap: wrap;
}
/* Las pestañas del panel son `.chip` (componentes.css); aquí solo el
   envoltorio y el color del activo, que en el realm de admin es ámbar
   (como `.nav-admin` en la barra superior), no verde. */
.admin-nav .chip.activo {
  color: var(--ambar);
  border-color: var(--ambar);
  background: rgba(var(--ambar-rgb), 0.08);
}

.alertas { margin-bottom: 1.75rem; }
.subtitulo-alerta { color: var(--rojo); }

.metricas {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 0.85rem;
  margin-bottom: 1.75rem;
}

.metrica {
  background: linear-gradient(180deg, var(--fondo-elev), var(--fondo-alt));
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  padding: 1rem 1.1rem;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  box-shadow: var(--sombra);
  transition: transform var(--trans), border-color var(--trans);
}
.metrica:hover { transform: translateY(-2px); border-color: var(--borde-fuerte); }
.metrica-alerta { border-color: rgba(var(--rojo-rgb), 0.5); }
.metrica-alerta .metrica-valor { color: var(--rojo); }
.metrica-valor { font-size: 1.7rem; font-weight: 700; color: var(--verde); line-height: 1.1; }
.metrica-etiqueta { font-size: 0.73rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--texto); }
.metrica-extra { font-size: 0.7rem; color: var(--texto-tenue); }

/* --- Filtros y formularios anchos ----------------------------------------- */

.filtros {
  display: flex;
  gap: 1rem;
  align-items: flex-end;
  flex-wrap: wrap;
  padding: 1.1rem 1.25rem;
  background: var(--fondo-alt);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  margin-bottom: 1.25rem;
}
.filtro { display: flex; flex-direction: column; min-width: 11rem; max-width: 22rem; flex: 1 1 11rem; }
.filtro label { margin-top: 0; }
.filtro-acciones { flex-direction: row; align-items: center; gap: 0.9rem; min-width: 0; }

.boton-compacto { margin-top: 0; padding: 0.48rem 1rem; font-size: 0.82rem; }

.rejilla-form {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 0 1rem;
}

/* Un campo que necesita la fila entera (una lista de selección múltiple, un
   textarea): en una columna de 220px no se lee ni la mitad de cada opción. */
.rejilla-form .campo-ancho { grid-column: 1 / -1; }
.rejilla-form .campo-ancho select[multiple] { max-width: 34rem; }
.rejilla-form .campo-ancho .ayuda { margin-top: 0.4rem; }

textarea { font-size: 0.85rem; line-height: 1.5; resize: vertical; }

.checkbox {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  text-transform: none;
  letter-spacing: 0;
  font-size: 0.85rem;
  color: var(--texto);
  margin-top: 1.25rem;
}
.checkbox input { margin: 0; }

.paginacion { display: flex; gap: 1.5rem; font-size: 0.85rem; }

/* --- Gestión de usuarios --------------------------------------------------- */

.tarjeta-password { border-color: rgba(var(--ambar-rgb), 0.5); margin-bottom: 1.5rem; }

.password-unica {
  font-size: 1.35rem;
  letter-spacing: 0.04em;
  color: var(--ambar);
  background: var(--fondo);
  border: 1px dashed var(--ambar);
  border-radius: var(--radio-sm);
  padding: 0.85rem 1rem;
  margin: 0 0 1rem;
  overflow-wrap: anywhere;
  user-select: all;
}

.fila-inactiva { opacity: 0.55; }

.password-inicial {
  color: var(--ambar);
  background: rgba(var(--ambar-rgb), 0.1);
  border: 1px solid rgba(var(--ambar-rgb), 0.35);
  border-radius: var(--radio-xs);
  padding: 0.1rem 0.4rem;
  user-select: all;
  white-space: nowrap;
}

/* --- Flags manuales (formulario de admin y página de reto) --------------- */

.subtitulo-sep { margin-top: 1.75rem; }

.flags-form { display: flex; flex-direction: column; gap: 0.5rem; margin-bottom: 0.5rem; }
.flag-slot { display: grid; grid-template-columns: 9rem 1fr 5.5rem; gap: 0.6rem; align-items: center; }
.flag-slot input { margin: 0; }
.flag-slot-cab { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--texto-tenue); }

.flags-lista { display: flex; flex-direction: column; gap: 0.5rem; margin: 0 0 1.1rem; }
.flag-fila {
  display: flex; align-items: center; gap: 0.7rem;
  padding: 0.55rem 0.85rem;
  background: var(--fondo);
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
}
.flag-fila-ok { border-color: rgba(var(--verde-rgb), 0.4); background: rgba(var(--verde-rgb), 0.05); }
.flag-etq { font-weight: 600; }
.flag-pts { color: var(--ambar); font-size: 0.85rem; }
.flag-estado { margin-left: auto; font-size: 0.75rem; color: var(--texto-tenue); }
.flag-estado-ok { color: var(--verde); font-weight: 700; }

/* Override de .flag-slot en pantallas estrechas: vivía junto a 'Tabla
   responsive' en app.css, pero sobreescribe reglas de 'Flags manuales' de
   más arriba en esta misma hoja, así que se mueve aquí para conservar el
   orden de cascada exacto (si viviera en componentes.css, que carga antes
   que vistas.css, dejaría de ganar el pulso de especificidad). */
@media (max-width: 560px) {
  .flag-slot { grid-template-columns: 1fr; }
  .flag-slot-cab { display: none; }
}

/* --- Responsive & accesibilidad ------------------------------------------ */

/* Barra superior en pantallas medianas: marca, secciones y cuenta arriba; la
   clase activa y la vista (profesor/alumno) bajan a una segunda fila que ocupa
   todo el ancho, en vez de partirse por donde caiga. */
@media (max-width: 900px) {
  .topbar { row-gap: 0.5rem; padding-block: 0.6rem; }
  .barra-centro {
    order: 3;
    flex: 1 1 100%;
    margin-inline: 0;
    flex-wrap: nowrap;
    justify-content: space-between;
    gap: 0.8rem;
  }
  .selector-clase-superior { flex: 1 1 auto; min-width: 0; flex-wrap: nowrap; }
  .selector-clase-superior select { flex: 1 1 auto; min-width: 0; max-width: none; }
}

/* Cuatro cifras en dos filas de dos, nunca tres y una suelta. */
@media (max-width: 860px) {
  .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 560px) {
  .topbar { gap: 0.8rem; padding: 0.7rem 1rem; }
  .nav { gap: 1.1rem; }
  .contenido { padding: 1.5rem 1rem 2.5rem; }
  .sesion { width: 100%; margin-left: 0; }
  .tiles { gap: 0.6rem; }
  .buscador { max-width: none; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; scroll-behavior: auto; }
  .metrica:hover, .boton:hover { transform: none; }
}

/* --- Perfil del alumno (Tarea 12, Perfil.dc.html) -------------------------
   `.tarjeta`, `.tiles`/`.tile` y `.progreso` son de componentes.css; aquí solo
   van la cabecera, las filas de categoría y la píldora de resultado de envío,
   que no existían todavía. */

.perfil-cabecera {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  flex-wrap: wrap;
  margin-bottom: 1.5rem;
}
.perfil-nombre { font-family: var(--mono); font-weight: 700; font-size: 1.15rem; }
.perfil-correo { font-size: 0.78rem; color: var(--texto-tenue); margin-top: 0.2rem; }
.perfil-meta { font-size: 0.78rem; color: var(--texto-tenue); text-align: right; }

.panel-progreso { margin-bottom: 1.5rem; }

.categoria-fila { display: flex; align-items: center; gap: 0.75rem; padding: 0.4rem 0; }
.categoria-nombre { width: 6.5rem; flex: none; font-size: 0.8rem; }
.categoria-fraccion { width: 3rem; flex: none; text-align: right; font-size: 0.78rem; color: var(--texto-tenue); }
.categoria-fila .progreso { flex: 1; min-width: 0; }

.rejilla-perfil { display: grid; grid-template-columns: 1fr 1fr; gap: 1.25rem; }
@media (max-width: 760px) {
  .rejilla-perfil { grid-template-columns: 1fr; }
}

.envios-lista { display: flex; flex-direction: column; }
.envio-fila {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--borde);
  flex-wrap: wrap;
}
.envios-lista .envio-fila:last-child { border-bottom: none; }
.envio-cuando { width: 9.5rem; flex: none; font-size: 0.76rem; color: var(--texto-tenue); }
.envio-slug { flex: 1; font-size: 0.82rem; min-width: 8rem; }
.envio-nota { font-size: 0.72rem; color: var(--texto-tenue); margin: -0.3rem 0 0.5rem 9.5rem; }

/* Píldora del resultado de un envío: correcta / incorrecta / caducada / alerta
   (nunca el valor de la flag). Distinta de `.pildora-estado` (componentes.css),
   que es el estado del reto, no el de un envío concreto. */
.pildora-resultado {
  display: inline-flex;
  align-items: center;
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 500;
  border-radius: var(--radio-pill);
  padding: 0.25rem 0.75rem;
  white-space: nowrap;
  flex: none;
}
.pildora-resultado-ok { background: rgba(var(--verde-rgb), 0.1); color: var(--verde); border: 1px solid rgba(var(--verde-rgb), 0.3); }
.pildora-resultado-mal { background: transparent; color: var(--texto-tenue); border: 1px solid var(--borde); }
.pildora-resultado-caducada { background: rgba(var(--ambar-rgb), 0.1); color: var(--ambar); border: 1px solid rgba(var(--ambar-rgb), 0.3); }
.pildora-resultado-alerta { background: rgba(var(--rojo-rgb), 0.1); color: var(--rojo); border: 1px solid rgba(var(--rojo-rgb), 0.3); }

/* --- Ranking (Tarea 13, Ranking.dc.html) -----------------------------------
   Colores del podio deliberadamente fuera de la paleta de estado (ni verde
   "resuelto" ni ámbar "pendiente"): el primer puesto no debe leerse como un
   estado del reto. `.fila-propia` y `.etiqueta` (baja) son de componentes.css
   y se conservan tal cual. */

.puesto { font-weight: 700; font-size: 0.92rem; }
.pos-oro { color: #e8c766; }
.pos-plata { color: #c7d4cd; }
.pos-bronce { color: #c98a5a; }
.pos-reg { color: var(--texto-tenue); font-weight: 500; }

.ranking-alumno { display: inline-flex; align-items: center; gap: 0.5rem; }

.pildora-tu {
  font-family: var(--mono);
  font-size: 0.66rem;
  color: var(--verde);
  border: 1px solid var(--verde);
  border-radius: var(--radio-pill);
  padding: 0.08rem 0.55rem;
}

/* --- Panel del profesor: clases y métricas (Tarea 14, Profesor.dc.html) ----
   `.chip` es de componentes.css; aquí solo el envoltorio de la fila de clases
   y el bloque de progreso/atascados. */

.clases-fila { margin-bottom: 1.5rem; }

/* Botón «Exportar notas (CSV)» (Tarea 15): a la derecha de la fila de
   píldoras de clase. `.boton` es de base.css. */
.clases-fila .boton {
  margin: 0 0 0 auto;
  min-height: 38px;
  padding: 0.4rem 1rem;
  gap: 0.4rem;
}
.clases-fila .boton svg { flex: none; }

.paneles-metricas {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: 1.25rem;
  margin-bottom: 1.75rem;
  align-items: start;
}
@media (max-width: 900px) {
  .paneles-metricas { grid-template-columns: 1fr; }
}

.progreso-reto-fila {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding: 0.45rem 0;
}
.progreso-reto-fila:not(:last-child) { border-bottom: 1px solid var(--borde); }
.progreso-reto-slug { width: 11rem; flex: none; font-size: 0.8rem; }
.progreso-reto-fila .progreso { flex: 1; min-width: 0; height: 10px; }
.progreso-reto-valor { width: 2.5rem; flex: none; text-align: right; }

.ayuda-chica { color: var(--texto-tenue); font-size: 0.72rem; margin: -0.5rem 0 0.85rem; }

/* Tarjeta con menos aire: un formulario de una línea (alta de alumno) no
   necesita el relleno de una ficha. */
.tarjeta-compacta { padding: 1.1rem 1.25rem; }
.tarjeta-compacta .subtitulo { margin-top: 0; margin-bottom: 0.75rem; }
.tarjeta-compacta .ayuda-chica { margin: 0.6rem 0 0; }

/* Alta rápida: correo, nombre y el botón «+» en la misma línea. El botón
   toma el alto de los campos (la rejilla estira) y es cuadrado. */
.alta-rapida {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(0, 2fr) auto;
  gap: 0.6rem;
  align-items: stretch;
}
.alta-rapida .boton-mas {
  margin: 0;
  min-height: 0;
  width: 2.75rem;
  padding: 0;
}
.alta-rapida .boton-mas .icono { margin: 0; width: 18px; height: 18px; stroke-width: 2.2; }

/* En un móvil el correo va solo en su línea; nombre y «+» debajo. */
@media (max-width: 560px) {
  .alta-rapida { grid-template-columns: minmax(0, 1fr) auto; }
  .alta-rapida #email { grid-column: 1 / -1; }
}

/* --- Panel del profesor a ancho completo (Fase 12) -------------------------
   El panel se lee en un proyector y en un portátil, y sus tablas tienen una
   columna por alumno: ocupan todo el ancho y recortan el texto largo, en vez
   de esconder columnas tras un scroll lateral. La vista del alumno conserva
   la columna centrada de `.contenido`. Única excepción: la matriz de
   calificaciones (`.tabla-scroll`, más abajo), que desborda a propósito
   porque con 30 alumnos en columnas no cabe de otra forma — decisión
   explícita del usuario, no un descuido. */
.contenido-admin {
  width: 100%;
  padding-inline: 8px;
}

/* `table-layout: auto`: el navegador reparte el ancho según el contenido de
   cada columna, en vez de darles a todas la misma porción. Con reparto fijo,
   una tabla de nueve columnas partía «brute-force-high» en tres líneas y
   dejaba «Estado» medio vacía. No desborda porque el texto envuelve (regla de
   abajo) y `width: 100%` obliga a la tabla a caber en el panel. */
.contenido-admin .tabla {
  table-layout: auto;
  width: 100%;
}

/* Lo que no cabe **envuelve**; no se recorta con puntos suspensivos. Recortar
   escondía justo lo que se va a leer (un correo, el slug de un reto) y en una
   tabla de `table-layout: fixed` el texto largo no puede desbordar la página:
   solo hace la fila más alta. */
.contenido-admin .tabla td {
  overflow-wrap: break-word;
  white-space: normal;
  /* Centrado con la fila: en una tabla con píldoras y botones de icono, el
     alineado arriba dejaba el texto y los adornos en dos alturas distintas. */
  vertical-align: middle;
}

/* `break-word` y no `anywhere`: `anywhere` deja que el navegador cuente el
   ancho mínimo de una columna como una sola letra, y con trece columnas el
   reparto automático estrujaba «publicar» en vertical, letra por letra. Con
   `break-word` el mínimo sigue siendo la palabra más larga y solo se parte lo
   que no cabe ni así. */
.contenido-admin .tabla .acciones-fila a,
.contenido-admin .tabla .acciones-fila button,
.contenido-admin .tabla .acciones-fila form { white-space: nowrap; }

/* La cabecera sí sigue en una línea: es la etiqueta de la columna, y partida
   («CATEGO / RÍA») cuesta más de leer que la columna que describe. Además
   marca un ancho mínimo sensato para el reparto automático. */
.contenido-admin .tabla th { white-space: nowrap; }

/* La primera columna suele ser el nombre de la fila (alumno, reto, correo) y
   es la que más se lee: sin un mínimo, el reparto automático se la da a las
   columnas de cifras y deja «Alumno de Prueba 1» en cuatro líneas. La matriz
   se queda fuera: su primera columna ya tiene un ancho propio. */
.contenido-admin .tabla-panel:not(.tabla-scroll) .tabla th:first-child:not(.col-marcar),
.contenido-admin .tabla-panel:not(.tabla-scroll) .tabla td:first-child:not(.col-marcar),
.contenido-admin .tabla-panel:not(.tabla-scroll) .tabla .col-marcar + th,
.contenido-admin .tabla-panel:not(.tabla-scroll) .tabla .col-marcar + td {
  min-width: 8rem;
}

/* Columna de contenido corto (una categoría, una cifra, un par de iconos): se
   queda con lo justo y le deja el sobrante a las que llevan texto de verdad
   —el slug y el título—, que son las que se leen. `width: 1%` es el truco de
   siempre para «tan estrecha como su contenido»; solo vale en una tabla que ya
   ocupa el ancho completo, así que la matriz, que se desborda a propósito,
   queda fuera. */
.contenido-admin .tabla-panel:not(.tabla-scroll) .tabla .col-corta {
  width: 1%;
  white-space: nowrap;
}

/* Una celda de acciones **no** puede ser `display: flex`: deja de ser
   `table-cell`, se sale del reparto de columnas (40 px para dos iconos) y sus
   bordes no siguen a la fila. Se queda como celda y son sus hijos los que se
   alinean. `.acciones-fila` fuera de una tabla (la tarjeta «Acciones» de una
   ficha) sigue siendo flex. */
.contenido-admin .tabla td.acciones-fila {
  display: table-cell;
  vertical-align: middle;
  white-space: nowrap;
}
.contenido-admin .tabla td.acciones-fila > * { vertical-align: middle; }
.contenido-admin .tabla td.acciones-fila > * + * { margin-left: 0.4rem; }

/* La columna de marcar es una casilla: ni ancho mínimo ni etiqueta. */
.contenido-admin .tabla .col-marcar {
  width: 2.2rem;
  min-width: 0;
  text-align: center;
  padding-inline: 0.35rem;
}

/* Lo que sí debe seguir en una línea: cifras, fechas y las píldoras de estado.
   Más específico que la regla de arriba (tres clases frente a dos). */
.contenido-admin .tabla .num,
.contenido-admin .tabla .pildora-estado,
.contenido-admin .tabla .etiqueta,
.contenido-admin .tabla .accion {
  white-space: nowrap;
}

/* Las acciones de una fila caben en dos líneas antes que desbordar; las que
   son solo iconos (`.acciones-iconos`) se quedan en una. */
.contenido-admin .acciones-fila:not(.acciones-iconos) {
  flex-wrap: wrap;
  white-space: normal;
  row-gap: 0.25rem;
}

/* La matriz de calificaciones anula lo de arriba: con `table-layout: fixed`
   el ancho de columna sale de la primera fila (la cabecera, que solo dice
   «Reto»), así que un slug largo se recortaría con «…» en vez de ensanchar
   la tabla — y el `min-width: max-content` de `.tabla-scroll`
   (componentes.css) no serviría de nada porque `table-layout: fixed` ya fijó
   el ancho antes de mirar el contenido. `table-layout: auto` + `width: auto`
   hacen que el ancho salga del contenido más ancho de cada columna (lo que
   activa el desbordamiento real); `overflow: visible` + `text-overflow: clip`
   deshacen el recorte con puntos suspensivos; `white-space: nowrap` evita que
   el slug envuelva en dos líneas en vez de ensanchar. Más específico que
   `.contenido-admin .tabla` (dos clases + elemento en ambos casos, pero aquí
   se añade `.tabla-scroll`) para ganar el empate de especificidad sin usar
   `!important`. */
/* `width: 100%` con el `min-width: max-content` de `.tabla-scroll`: la tabla
   llena la caja cuando cabe y la desborda (con su scroll) cuando no, en vez de
   quedarse encogida a la izquierda con medio panel vacío. */
.contenido-admin .tabla-scroll table {
  width: 100%;
}

.contenido-admin .tabla-scroll td,
.contenido-admin .tabla-scroll th {
  overflow: visible;
  text-overflow: clip;
  white-space: nowrap;
}

/* Envoltorio de tabla del panel: la misma caja que `.tabla-envoltorio` del
   alumno. Se desplaza **dentro de su caja** cuando la tabla no cabe: con trece
   columnas y los iconos de acción, a 1024 px ya no entra, y la alternativa era
   cortar contenido o empujar la página entera. `auto` no pinta barra si sobra
   sitio, así que en una pantalla ancha no se nota. */
.tabla-panel {
  overflow-x: auto;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: var(--fondo-alt);
  margin-bottom: 1.5rem;
  box-shadow: var(--sombra);
}

/* Matriz de la clase: retos en filas, una columna estrecha por alumno. */
.matriz-clase .col-alumno {
  min-width: 2.4rem;
  text-align: center;
  padding-inline: 0.2rem;
  border-left: 1px solid var(--borde);
}

/* Las tres primeras columnas se quedan con un ancho fijo para que el sobrante
   se reparta entre las de alumnos: si no, «Publicación» se llevaba media
   tabla y las iniciales quedaban amontonadas contra el borde derecho, que es
   lo que hacía parecer que faltaban datos. */
.contenido-admin .matriz-clase .col-publicacion { width: 11rem; }
.contenido-admin .matriz-clase .col-cierre { width: 9rem; }

/* Un hueco sin envíos también se dibuja: una rejilla con celdas en blanco
   parece media tabla sin cargar. */
.matriz-clase .marca-vacia { color: var(--borde-fuerte); }

/* El nombre del reto envuelve dentro de un ancho fijo: con `nowrap` un slug
   como `traversal-4-doble-codificacion` empujaba las columnas de alumnos
   fuera de la pantalla antes de que se viera ninguna. El resto de la matriz
   sí sigue en una línea (fechas, píldoras e iniciales). */
.contenido-admin .matriz-clase td.col-reto-nombre,
.contenido-admin .matriz-clase th.col-reto-nombre {
  width: 13rem;
  max-width: 13rem;
  white-space: normal;
  overflow-wrap: break-word;
}
.matriz-clase .celda-resuelto { color: var(--verde); }
.matriz-clase .marca-intento { color: var(--texto-tenue); }
.matriz-clase .fila-totales td { border-top: 2px solid var(--borde); }

/* Ficha de un usuario: pares etiqueta/valor en dos columnas. */
.ficha-datos {
  display: grid;
  grid-template-columns: minmax(8rem, 12rem) 1fr;
  gap: 0.45rem 1rem;
  margin: 0;
}

.ficha-datos dt { color: var(--texto-tenue); }
.ficha-datos dd { margin: 0; }

@media (max-width: 640px) {
  .ficha-datos { grid-template-columns: 1fr; gap: 0.15rem; }
  .ficha-datos dd { margin-bottom: 0.5rem; }
}

/* Detalle del historial: el texto largo envuelve en vez de desbordar. */
.celda-detalle {
  white-space: normal;
  overflow-wrap: anywhere;
}

/* Clases en rejilla: una tarjeta por clase, no una fila de tabla. */
.rejilla-clases {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
  gap: 1rem;
  margin-bottom: 1.25rem;
}

.tarjeta-clase .ficha-datos { grid-template-columns: 1fr auto; }

/* En una rejilla la separación la pone el `gap`: el margen de `.tarjeta`
   sumaría un hueco de más entre filas. */
.rejilla-clases > .tarjeta,
.paneles-metricas > .tarjeta { margin-bottom: 0; }

/* Tarjeta de clase: la tarjeta es una columna y las acciones van al fondo,
   así quedan alineadas entre tarjetas de distinta altura. */
.tarjeta-clase { display: flex; flex-direction: column; }
.acciones-clase {
  display: flex;
  gap: 0.6rem;
  margin-top: auto;
  padding-top: 0.9rem;
}
/* Los dos botones, a partes iguales y en la misma línea. */
.acciones-clase > .boton,
.acciones-clase > form { flex: 1 1 0; }
.acciones-clase form .boton { width: 100%; }

/* Listas de la portada del profesor: próximos cierres, atascados, alertas. */
.lista-simple,
.lista-alertas {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.lista-alertas li { color: var(--rojo); }

/* Retos en marcha de la clase, en tarjetas. */
.rejilla-retos-clase {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: 0.9rem;
}

.reto-clase {
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  padding: 0.9rem 1rem;
  background: var(--fondo-alt);
}

.reto-clase p { margin: 0.25rem 0 0; }
.reto-clase-nombre { font-weight: 700; }

/* Interruptor de visibilidad por clase (el ojo de la tabla del curso). */
.ojo {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 34px;
  min-height: 30px;
  padding: 0;
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
  background: transparent;
  color: var(--texto-tenue);
  cursor: pointer;
  transition: color var(--trans), border-color var(--trans), background var(--trans);
}

.ojo:hover { color: var(--texto); border-color: var(--borde-fuerte); }

.ojo-visible {
  color: var(--verde);
  border-color: rgba(var(--verde-rgb), 0.5);
  background: rgba(var(--verde-rgb), 0.1);
}

/* --- Tableta (Fase 12) -----------------------------------------------------
   El panel se usa en clase desde una tableta, no desde un móvil: el objetivo
   son ~768-1024 px en horizontal y vertical. Nada se apila en tarjetas (eso es
   de la portada del alumno, `.tabla-responsive`): las tablas se estrechan, el
   texto envuelve y los filtros pasan a ocupar la fila entera. */

@media (max-width: 1024px) {
  .contenido-admin { padding-inline: 4px; }

  .contenido-admin .tabla { font-size: 0.78rem; }
  .contenido-admin .tabla th,
  .contenido-admin .tabla td { padding: 9px 12px; }
  .contenido-admin .tabla-compacta th,
  .contenido-admin .tabla-compacta td { padding: 6px 6px; }

  /* La tabla del curso tiene trece columnas: en tableta el texto de la
     cabecera se queda sin mayúsculas ni tracking para ganar los últimos
     píxeles antes de que la tabla se salga de su caja. */
  .contenido-admin .tabla-compacta th {
    letter-spacing: 0;
    text-transform: none;
  }

  /* La matriz mantiene su scroll lateral, pero con la columna de reto más
     estrecha entran dos o tres alumnos más antes de tener que desplazarla. */
  .contenido-admin .matriz-clase td.col-reto-nombre,
  .contenido-admin .matriz-clase th.col-reto-nombre { width: 10rem; max-width: 10rem; }

  .rejilla-form { grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); }

  /* La cabecera sí puede partirse aquí: en vertical, «Dificultad» en dos
     líneas cuesta menos que perder la columna de al lado. */
  .contenido-admin .tabla th { white-space: normal; }
  .filtros { padding: 0.9rem 1rem; gap: 0.75rem; }
  .filtro { min-width: 0; flex: 1 1 10rem; }
  .filtro-acciones { flex: 1 1 100%; }
}

/* --- Listas de selección ---------------------------------------------------
   Las casillas se dibujan en `base.css`, con el resto de campos. */

select[multiple] {
  padding: 0.3rem;
  font-size: 0.82rem;
  min-height: 7.5rem;
  background: var(--fondo);
}
select[multiple] option {
  padding: 0.35rem 0.5rem;
  border-radius: var(--radio-xs);
  color: var(--texto);
}
/* El navegador pinta la opción marcada con el azul del sistema; aquí va con
   el verde de la consola, que es el color de «esto está elegido». */
select[multiple] option:checked {
  background: rgba(var(--verde-rgb), 0.16) linear-gradient(0deg, rgba(var(--verde-rgb), 0.16), rgba(var(--verde-rgb), 0.16));
  color: var(--verde);
}

/* Fila de campos que termina en un botón (elegir rol, asignar un reto): el
   botón se alinea con el campo en vez de caer debajo con su margen de arriba. */
.fila-accion {
  display: flex;
  align-items: flex-end;
  gap: 0.75rem;
  flex-wrap: wrap;
}
.fila-accion > div { flex: 1 1 12rem; min-width: 0; max-width: 22rem; }
.fila-accion .boton { margin-top: 0; }

/* El desplazamiento dentro de la caja lo tiene ya `.tabla-panel` a cualquier
   ancho (más arriba); aquí solo queda que la barra no se coma el borde. */
.contenido-admin .tabla-panel { overscroll-behavior-x: contain; }

/* --- Certificados y verificación pública (Fase 13) -------------------------
   El diploma se dibuja en SVG sobre papel claro (app/certificados.py): es lo
   único claro de toda la plataforma, y a propósito, porque se imprime. Aquí
   solo va su marco, los controles y la página pública de comprobación. */

.certificado-cabecera {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1.25rem;
  flex-wrap: wrap;
  margin-bottom: 1.25rem;
}
.certificado-cabecera .prompt { margin-bottom: 0.45rem; }
.certificado-acciones { display: flex; gap: 0.6rem; flex-wrap: wrap; }
.certificado-acciones .boton { margin-top: 0; }

/* La hoja: un papel apoyado sobre la consola. El borde verde tenue lo cose al
   resto de la interfaz sin meterse dentro del dibujo. */
.diploma-hoja {
  background: #fbfbf9;
  border: 1px solid var(--borde-fuerte);
  border-radius: var(--radio);
  box-shadow: var(--sombra-alta);
  padding: 0.5rem;
  margin-bottom: 1.5rem;
  overflow: hidden;
}
.diploma-lienzo {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radio-xs);
}

.diploma-codigo {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  flex-wrap: wrap;
}
.diploma-codigo > div { flex: 1 1 22rem; min-width: 0; }
.diploma-codigo .subtitulo { margin-bottom: 0.4rem; }
.diploma-codigo-valor {
  font-size: 1.45rem;
  letter-spacing: 0.08em;
  color: var(--verde);
  margin: 0 0 0.5rem;
}
.diploma-codigo .boton { margin-top: 0; }

/* Página pública: quien llega aquí no tiene sesión y solo quiere una
   respuesta, así que la columna es estrecha y el veredicto va primero. */
.verificacion { max-width: 52rem; }
.verificacion-entrada { display: block; margin-bottom: 1.5rem; max-width: 42rem; }

.buscador-codigo {
  display: flex;
  align-items: flex-end;
  gap: 0.75rem;
  flex-wrap: wrap;
  background: var(--fondo-alt);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  padding: 1rem 1.15rem;
  margin-bottom: 1.5rem;
}
.buscador-codigo label { flex: 1 1 100%; margin-bottom: 0; }
.buscador-codigo input {
  flex: 1 1 18rem;
  min-width: 0;
  font-family: var(--mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.buscador-codigo .boton { margin-top: 0; }

.veredicto {
  display: flex;
  align-items: flex-start;
  gap: 0.9rem;
  border: 1px solid var(--borde-fuerte);
  border-left-width: 3px;
  border-radius: var(--radio);
  padding: 1rem 1.15rem;
  margin-bottom: 1.5rem;
  background: var(--fondo-elev);
}
.veredicto-valido { border-left-color: var(--verde); }
.veredicto-invalido { border-left-color: var(--rojo); }
.veredicto-marca { flex: none; line-height: 0; margin-top: 0.1rem; }
.veredicto-valido .veredicto-marca { color: var(--verde); }
.veredicto-invalido .veredicto-marca { color: var(--rojo); }
.veredicto-titulo { margin: 0 0 0.3rem; font-size: 1.05rem; font-weight: 600; }
.veredicto-detalle { margin: 0; color: var(--texto-tenue); font-size: 0.85rem; }

.verificacion-datos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 0.15rem 1.5rem;
  margin: 0 0 1.5rem;
}
.verificacion-dato {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--borde);
}
.verificacion-dato dt { color: var(--texto-tenue); font-size: 0.78rem; }
.verificacion-dato dd { margin: 0; text-align: right; font-size: 0.85rem; }

/* Certificados ganados, en el perfil del alumno. */
.certificados-lista { display: flex; flex-direction: column; gap: 0.1rem; }
.certificado-fila {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--borde);
}
.certificado-fila:last-child { border-bottom: 0; }
.certificado-cuando { color: var(--texto-tenue); font-size: 0.78rem; }
.certificado-codigo { color: var(--verde); font-size: 0.78rem; }

/* Al imprimir queda la hoja y nada más: ni barra, ni botones, ni pie. */
@media print {
  .topbar,
  .pie,
  .migas,
  .banda-modo-alumno,
  .certificado-acciones,
  .certificado-cabecera,
  .diploma-codigo,
  .buscador-codigo,
  .veredicto,
  .verificacion-datos { display: none !important; }

  body { background: #fff; }
  .contenido { padding: 0; max-width: none; }
  .diploma-hoja {
    border: 0;
    box-shadow: none;
    padding: 0;
    margin: 0;
  }
}

/* Tarjeta que es en realidad una llamada a la acción: texto a la izquierda,
   botón a la derecha, y en móvil el botón debajo. */
.tarjeta-accion {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  flex-wrap: wrap;
}
.tarjeta-accion > div { flex: 1 1 22rem; min-width: 0; }
.tarjeta-accion .subtitulo { margin-bottom: 0.4rem; }
.tarjeta-accion .boton { margin-top: 0; }

/* --- Informe de comprobaciones de un ZIP (catálogo) ---------------------- */

.comprobaciones {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}

.comprobacion {
  display: grid;
  grid-template-columns: 1.6rem 1fr;
  gap: 0.6rem;
  align-items: start;
  padding: 0.5rem 0.7rem;
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
  background: var(--fondo-alt);
}

.comprobacion-icono {
  display: inline-grid;
  place-items: center;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 50%;
  font-family: var(--mono);
  font-weight: 700;
  color: var(--fondo);
}

.comprobacion[data-estado="ok"] .comprobacion-icono { background: var(--verde); }
.comprobacion[data-estado="aviso"] .comprobacion-icono { background: var(--ambar); }
.comprobacion[data-estado="error"] .comprobacion-icono { background: var(--rojo); }
.comprobacion[data-estado="ok"] { border-color: rgba(var(--verde-rgb), 0.35); }
.comprobacion[data-estado="aviso"] { border-color: rgba(var(--ambar-rgb), 0.45); }
.comprobacion[data-estado="error"] { border-color: rgba(var(--rojo-rgb), 0.45); }

.comprobacion-cuerpo {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  min-width: 0;
}

.comprobacion-titulo { font-weight: 600; }

.detalle {
  font-family: var(--mono);
  font-size: 0.82rem;
  color: var(--texto-tenue);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* --- La ventana de subida de un laboratorio ------------------------------ */

.dialogo-subida {
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: var(--fondo-alt);
  color: var(--texto);
  padding: 1.4rem;
  width: min(36rem, calc(100vw - 2rem));
  max-height: calc(100vh - 2rem);
  overflow-y: auto;
  box-shadow: var(--sombra-alta);
}

.dialogo-subida::backdrop { background: rgba(0, 0, 0, 0.6); }
.dialogo-subida .subtitulo { margin-top: 0; }

.anillo-progreso {
  position: relative;
  width: 8rem;
  height: 8rem;
  margin: 0.5rem auto 1rem;
}

.anillo-progreso svg {
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
}

.anillo-fondo,
.anillo-valor {
  fill: none;
  stroke-width: 10;
  stroke-linecap: round;
}

.anillo-fondo { stroke: var(--borde-fuerte); }

.anillo-valor {
  stroke: var(--azul);
  transition: stroke-dashoffset 220ms cubic-bezier(0.4, 0, 0.2, 1), stroke 300ms;
}

.dialogo-subida[data-estado="ok"] .anillo-valor { stroke: var(--verde); }
.dialogo-subida[data-estado="aviso"] .anillo-valor { stroke: var(--ambar); }
.dialogo-subida[data-estado="error"] .anillo-valor { stroke: var(--rojo); }

.anillo-numero {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-family: var(--mono);
  font-size: 1.6rem;
  font-weight: 700;
}

.subida-estado {
  min-height: 1.4em;
  margin: 0 0 0.8rem;
  text-align: center;
}

.dialogo-subida[data-estado="ok"] .subida-estado { color: var(--verde); }
.dialogo-subida[data-estado="aviso"] .subida-estado { color: var(--ambar); }
.dialogo-subida[data-estado="error"] .subida-estado { color: var(--rojo); }

.dialogo-subida .comprobaciones {
  max-height: 40vh;
  overflow-y: auto;
}

.dialogo-subida .comprobacion {
  animation: aparecer-comprobacion 260ms cubic-bezier(0.4, 0, 0.2, 1) both;
}

@keyframes aparecer-comprobacion {
  from { opacity: 0; transform: translateY(0.4rem); }
  to { opacity: 1; transform: none; }
}

.subida-botones {
  display: flex;
  gap: 0.8rem;
  justify-content: flex-end;
  align-items: center;
  margin: 1rem 0 0;
  padding: 0;
}

@media (prefers-reduced-motion: reduce) {
  .anillo-valor { transition: none; }
  .dialogo-subida .comprobacion { animation: none; }
}

/* --- Retos de la clase: transferencia y tabla editable (/panel/retos) ------
   Dos listas con casillas y dos flechas en medio, como un gestor de ficheros.
   Cada lista se desplaza dentro de su caja: con sesenta retos en el catálogo
   la página no crece, crece la lista. */
.transferencia {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  gap: 0.9rem;
  align-items: stretch;
}

.transferencia-lista {
  display: flex;
  flex-direction: column;
  min-width: 0;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: var(--fondo);
  overflow: hidden;
}

.transferencia-cabecera {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.6rem 0.75rem;
  border-bottom: 1px solid var(--borde);
  background: var(--fondo-elev);
}
.transferencia-titulo { font-family: var(--mono); font-size: 0.82rem; white-space: nowrap; }
.transferencia-cabecera .transferencia-filtro {
  margin-left: auto;
  max-width: 12rem;
  padding: 0.35rem 0.6rem;
  font-size: 0.8rem;
}

.transferencia-items {
  list-style: none;
  margin: 0;
  padding: 0.3rem 0;
  height: 20rem;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--borde-fuerte) transparent;
}
/* Cada reto: su casilla (el label, que ocupa la fila) y el ojo para
   visualizarlo, fuera del label para que pulsarlo no marque la casilla. */
.transferencia-items li { display: flex; align-items: center; }
.transferencia-items li > label { flex: 1; min-width: 0; }
.transferencia-ver { flex: none; margin-right: 0.4rem; }
.transferencia-items label {
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
  margin: 0;
  padding: 0.35rem 0.75rem;
  cursor: pointer;
  text-transform: none;
  letter-spacing: normal;
  color: var(--texto);
}
.transferencia-items label:hover { background: rgba(var(--verde-rgb), 0.06); }
/* La fila marcada se ilumina: se ve de un vistazo qué se va a mover. */
.transferencia-items label:has(input:checked) { background: rgba(var(--verde-rgb), 0.12); }
.transferencia-items input { flex: none; align-self: center; }
.transferencia-slug { font-size: 0.82rem; overflow-wrap: anywhere; }
.transferencia-meta { font-size: 0.72rem; margin-left: auto; white-space: nowrap; color: var(--texto-tenue); }
.transferencia-vacia { padding: 0.6rem 0.75rem; font-size: 0.82rem; }

.transferencia-botones {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.6rem;
}
.transferencia-botones .boton { margin: 0; min-height: 0; width: 2.75rem; height: 2.5rem; padding: 0; }
.transferencia-botones .icono { margin: 0; width: 18px; height: 18px; stroke-width: 2; }

/* Selector de módulo encima de las listas de /panel/retos. */
.selector-modulo { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.9rem; }
.selector-modulo label { margin: 0; }
.selector-modulo select { width: auto; min-width: 12rem; }

/* Módulo de un reto, como etiqueta pequeña (panel y portada del alumno). */
.etiqueta-modulo {
  display: inline-block;
  margin: 0 0.3rem 0.2rem 0;
  padding: 0.05rem 0.45rem;
  border: 1px solid var(--borde-fuerte);
  border-radius: 999px;
  font-size: 0.72rem;
  color: var(--texto-tenue);
  white-space: nowrap;
}

/* En un móvil las listas se apilan y las flechas giran: → pasa a ↓. */
@media (max-width: 720px) {
  .transferencia { grid-template-columns: minmax(0, 1fr); }
  .transferencia-botones { flex-direction: row; justify-content: center; }
  .transferencia-botones .icono { transform: rotate(90deg); }
  .transferencia-items { height: 14rem; }
}

/* Tabla de retos asignados: los campos de fecha no se estrechan hasta
   partirse, y las casillas van centradas en su columna. */
.tabla-retos-clase input[type="datetime-local"] {
  width: auto;
  min-width: 12.5rem;
  padding: 0.35rem 0.5rem;
  font-size: 0.8rem;
}
.tabla-retos-clase .col-casilla { text-align: center; }
.tabla-retos-clase td.col-fija { white-space: nowrap; }
.tabla-retos-clase th.col-casilla { white-space: normal; }
.ayuda-celda { display: block; margin-top: 0.2rem; font-size: 0.7rem; color: var(--texto-tenue); }

/* Portada del alumno: próximos a cerrar, pestañas de vista y carpetas. */
.proximos { margin: 1.2rem 0; }
.proximos-lista { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: 0.8rem; }
.proximo {
  display: flex; flex-direction: column; gap: 0.3rem;
  padding: 0.8rem 1rem;
  border: 1px solid var(--borde-fuerte); border-radius: 10px;
  color: var(--texto); text-decoration: none;
}
.proximo:hover { border-color: var(--verde); }
.proximo-titulo { font-weight: 600; }
.proximo-meta { font-size: 0.78rem; color: var(--texto-tenue); }
.vista-pestanas { margin: 0.8rem 0; }
.carpeta { margin: 0.8rem 0; border: 1px solid var(--borde); border-radius: 10px; }
.carpeta-cabecera {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 1rem;
  padding: 0.7rem 1rem; cursor: pointer;
}
.carpeta-titulo { font-weight: 600; }
.carpeta-meta { display: flex; align-items: center; gap: 0.5rem; font-size: 0.8rem; color: var(--texto-tenue); }
.carpeta-meta .progreso { width: 6rem; }
.carpeta > .tabla-envoltorio { padding: 0 0.6rem 0.6rem; }
