/* ==========================================================
   CCE — Hoja de estilos principal
   Sin dependencias externas: ninguna fuente ni CSS remoto, para
   cumplir el objetivo de carga < 2 s en 3G (Frontend, Rendimiento).
   ========================================================== */

/* ----------------------------------------------------------
   Variables de tema
   Los nombres --primary-color / --background-color /
   --text-color / --card-color son los definidos por la
   especificación de Frontend.
   ---------------------------------------------------------- */
:root {
  /* Acento por defecto: azul */
  --acento-fuerte: #1d4ed8;
  --acento-medio:  #2563eb;
  --acento-suave:  #60a5fa;

  /* El tono fuerte y no el medio: con el medio, tres de los seis acentos
     no llegaban a 4,5:1 sobre blanco —verde 3,3, naranja 3,6, cian 3,7—
     y eran ilegibles en enlaces y en el texto blanco de los botones
     (informe de UX consolidado, octubre de 2026). */
  --primary-color:    var(--acento-fuerte);
  --background-color: #f4f6f9;
  --text-color:       #16202e;
  --card-color:       #ffffff;

  --texto-tenue:  #5b6675;
  --borde:        #dde3ea;
  --superficie-2: #eef1f5;

  --exito:   #15803d;
  --exito-fondo: #f0fdf4;
  --peligro: #b91c1c;
  --peligro-fondo: #fef2f2;
  /* Situación que todavía se puede revertir: el alumno se acerca al
     límite de faltas pero no lo alcanzó. Distinto de --peligro, que
     marca lo que ya ocurrió. */
  --atencion: #a16207;
  --atencion-fondo: #fefce8;

  /* El texto que va sobre un relleno de acento o de peligro. En oscuro
     esos rellenos son tonos claros, y el blanco encima daba 2,5:1: las
     iniciales de la cuenta, el contador del menú y «Saltar al
     contenido» no se leían. Una variable y no una excepción por clase,
     que es como se habían ido escapando. */
  --sobre-acento: #fff;

  --radio: 8px;
  --sombra: 0 1px 2px rgba(16, 24, 40, .06), 0 1px 3px rgba(16, 24, 40, .1);
  --ancho-sidebar: 232px;
  --alto-header: 60px;
}

[data-tema="oscuro"] {
  --primary-color:    var(--acento-suave);
  --background-color: #0f151d;
  --text-color:       #e8edf3;
  --card-color:       #18202b;

  --texto-tenue:  #97a3b3;
  --borde:        #2a3543;
  --superficie-2: #212b38;

  --exito:   #4ade80;
  --exito-fondo: #12251a;
  --peligro: #f87171;
  --peligro-fondo: #2a1517;
  --atencion: #fbbf24;
  --atencion-fondo: #2a2312;

  --sobre-acento: #0f151d;

  --sombra: 0 1px 2px rgba(0, 0, 0, .3), 0 1px 3px rgba(0, 0, 0, .4);
}

/* Colores de acento. Cada uno define un tono fuerte para modo claro y
   uno suave para modo oscuro: el mismo azul que contrasta sobre blanco
   no alcanza el contraste mínimo sobre fondo oscuro. */
[data-acento="azul"]    { --acento-fuerte: #1d4ed8; --acento-medio: #2563eb; --acento-suave: #60a5fa; }
/* El verde fuerte es un tono más oscuro que el resto de su familia: con
   #15803d, el texto de acento sobre el gris de las insignias daba 4,43:1. */
[data-acento="verde"]   { --acento-fuerte: #166534; --acento-medio: #16a34a; --acento-suave: #4ade80; }
[data-acento="morado"]  { --acento-fuerte: #6d28d9; --acento-medio: #7c3aed; --acento-suave: #a78bfa; }
[data-acento="naranja"] { --acento-fuerte: #c2410c; --acento-medio: #ea580c; --acento-suave: #fb923c; }
[data-acento="rojo"]    { --acento-fuerte: #b91c1c; --acento-medio: #dc2626; --acento-suave: #f87171; }
[data-acento="cian"]    { --acento-fuerte: #0e7490; --acento-medio: #0891b2; --acento-suave: #22d3ee; }

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

/* El atributo `hidden` tiene que ganar.
   `[hidden] { display: none }` es una regla del NAVEGADOR, y cualquier
   regla del autor le gana sin importar la especificidad. Sin esta línea,
   `.campo { display: flex }` deja visibles los campos que el script
   oculta: en «Nueva notificación» aparecían a la vez los selectores de
   curso, usuario y rol; en el legajo el campo de cantidad no se iba
   nunca; y en la planilla, «Quitar» se ofrecía sin nada que quitar. No
   es un problema de navegadores viejos: falla en todos.

   Va una sola vez y con `!important`: escrita clase por clase, la
   siguiente clase con `display` vuelve a romperla en silencio. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  /* Fuentes del sistema: cero descargas. */
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 15px;              /* mínimo 14 px según la especificación */
  line-height: 1.55;
  color: var(--text-color);
  background-color: var(--background-color);
}

h1, h2, h3 { margin: 0; line-height: 1.3; }
p { margin: 0; }
ul { margin: 0; padding: 0; list-style: none; }
a { color: var(--primary-color); }

/* Foco visible en todo elemento interactivo: requisito de navegación
   por teclado (Frontend, Accesibilidad). */
:focus-visible {
  outline: 2px solid var(--primary-color);
  outline-offset: 2px;
  border-radius: 4px;
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ----------------------------------------------------------
   Botones
   ---------------------------------------------------------- */
/* Los enlaces con forma de botón (Volver, Nuevo alumno, Editar) llegaban
   con el subrayado del navegador: en la misma fila convivían un <a>
   subrayado y un <button> que no, y la diferencia no significaba nada.
   El recuadro ya los distingue de un enlace de texto. */
.boton {
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  min-height: 40px;
  padding: .5rem 1rem;
  font: inherit;
  font-weight: 500;
  border: 1px solid transparent;
  border-radius: var(--radio);
  background: var(--superficie-2);
  color: var(--text-color);
  cursor: pointer;
}

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

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

.boton--sutil {
  background: transparent;
  border-color: var(--borde);
  color: var(--texto-tenue);
}

.boton--ancho { width: 100%; }

.boton-icono {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  font-size: 1.05rem;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: transparent;
  color: var(--text-color);
  cursor: pointer;
}

.boton-icono:hover { background: var(--superficie-2); }

/* ----------------------------------------------------------
   Alertas
   ---------------------------------------------------------- */
.alerta {
  padding: .65rem .85rem;
  border-radius: var(--radio);
  border: 1px solid transparent;
  font-size: .92rem;
}

.alerta--error {
  color: var(--peligro);
  background: var(--peligro-fondo);
  border-color: var(--peligro);
}

/* Cuando fallan varias reglas de validación el aviso deja de ser una
   línea y pasa a ser una lista: hay que sacarle los márgenes que el
   navegador le pone al <p> y al <ul> sueltos. */
.alerta__titulo { margin: 0 0 .3rem; font-weight: 600; }

.alerta__lista { margin: 0; padding-left: 1.15rem; }
.alerta__lista li + li { margin-top: .15rem; }

/* ----------------------------------------------------------
   Formularios
   ---------------------------------------------------------- */
.campo { display: flex; flex-direction: column; gap: .35rem; }

/* Ver la regla general de `[hidden]` en «Base»: acá había una copia para
   `.campo`, y después otra para la paleta, y el día que un botón se ocultó
   desde el script hizo falta una tercera. */

.campo label {
  font-size: .88rem;
  font-weight: 500;
  color: var(--texto-tenue);
}

/* El select también: sin esto quedaba con el alto de fábrica, 19 px, en
   Configuración y en todo formulario que no fuera `.formulario`. */
.campo input,
.campo select {
  min-height: 42px;
  padding: .5rem .7rem;
  font: inherit;
  font-size: 16px;             /* evita el zoom automático de iOS al enfocar */
  color: var(--text-color);
  background: var(--card-color);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}

.campo input:focus,
.campo select:focus { border-color: var(--primary-color); }

/* El campo que la lista de errores menciona, marcado donde se lo va a
   corregir. `aria-invalid` no es decoración: es lo que oye un lector de
   pantalla al llegar al campo, y el borde es lo mismo para quien ve.

   Va DESPUÉS de `.campo input` y no junto a `.alerta`, que sería su
   lugar temático: las dos reglas tienen la misma especificidad y
   `.campo input` usa el atajo `border`, que reescribe el color. Puesto
   antes, esto no pintaba nada. */
.campo--con-error label { color: var(--peligro); }

.campo--con-error input,
.campo--con-error select,
.campo--con-error textarea,
[aria-invalid="true"] { border-color: var(--peligro); }

/* ----------------------------------------------------------
   Login
   ---------------------------------------------------------- */
.pagina-login { background: var(--background-color); }

.login {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 1.25rem;
}

.login__caja {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  width: 100%;
  max-width: 380px;
  padding: 1.75rem;
  background: var(--card-color);
  border: 1px solid var(--borde);
  border-radius: 12px;
  box-shadow: var(--sombra);
}

.login__marca { text-align: center; }

/* El escudo se muestra tal cual: sin fondo de color ni recorte. Tiene
   transparencia propia y funciona igual en tema claro y oscuro, así que
   no necesita variante. */
.login__logo {
  display: block;
  width: 88px;
  height: 88px;
  margin: 0 auto .6rem;
  object-fit: contain;
}

.login__titulo { font-size: 1.06rem; }

.login__institucion {
  margin-top: .2rem;
  font-size: .85rem;
  color: var(--texto-tenue);
}

.login__ayuda {
  font-size: .8rem;
  text-align: center;
  color: var(--texto-tenue);
}

/* ----------------------------------------------------------
   Estructura de la aplicación
   ---------------------------------------------------------- */
.app { display: flex; min-height: 100vh; }

.app__principal {
  flex: 1;
  min-width: 0;               /* permite que las tablas anchas hagan scroll */
  display: flex;
  flex-direction: column;
}

/* ----------------------------------------------------------
   Sidebar
   ---------------------------------------------------------- */
.sidebar {
  flex-shrink: 0;
  width: var(--ancho-sidebar);
  padding: 1rem .7rem;
  background: var(--card-color);
  border-right: 1px solid var(--borde);
}

.sidebar__marca {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .3rem .5rem 1rem;
}

.sidebar__logo {
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  object-fit: contain;
}

/* El nombre completo son cuatro palabras y la barra mide 232 px: tiene
   que poder cortarse en varias líneas sin empujar el logo. */
.sidebar__institucion {
  font-size: .8rem;
  font-weight: 600;
  line-height: 1.25;
  color: var(--texto-tenue);
  min-width: 0;
}

/* ----------------------------------------------------------
   Secciones y grupos del menú
   ----------------------------------------------------------
   Diecinueve renglones iguales obligaban a leerlos todos para
   encontrar uno. Agrupados son cinco bloques, y los dos grupos
   que se abren guardan diez destinos que no se usan a diario. */
.sidebar__seccion {
  margin: .9rem .6rem .25rem;
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .6px;
  text-transform: uppercase;
  color: var(--texto-tenue);
}

.sidebar__lista:first-of-type { margin-top: 0; }

/* El triángulo que el navegador le pone al <summary> no se puede
   alinear con los iconos; se usa una flecha propia. */
.sidebar__grupo__titulo {
  cursor: pointer;
  list-style: none;
  user-select: none;
}

.sidebar__grupo__titulo::-webkit-details-marker { display: none; }

.sidebar__flecha {
  margin-left: auto;
  font-size: .7rem;
  color: var(--texto-tenue);
  transition: transform .15s ease;
}

.sidebar__flecha::before { content: "›"; font-size: 1.1rem; line-height: 1; }

.sidebar__grupo[open] > .sidebar__grupo__titulo .sidebar__flecha {
  transform: rotate(90deg);
}

/* La sangría alinea los iconos de adentro con el texto de afuera: se ve
   que cuelgan del grupo sin necesidad de una línea o un recuadro. */
.sidebar__sublista { padding-left: 1.3rem; }

.sidebar__sublista .sidebar__link { font-size: .9rem; }

.sidebar__link {
  display: flex;
  align-items: center;
  gap: .7rem;
  padding: .55rem .6rem;
  margin-bottom: .15rem;
  font-size: .93rem;
  color: var(--text-color);
  text-decoration: none;
  border-radius: var(--radio);
}

.sidebar__link:hover { background: var(--superficie-2); }

.sidebar__link--activo {
  color: var(--sobre-acento);
  background: var(--primary-color);
  font-weight: 500;
}

.sidebar__icono {
  width: 20px;
  text-align: center;
  font-size: 1rem;
}

.sidebar__overlay {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: rgba(0, 0, 0, .45);
}

/* El ✕ del menú en el teléfono. 44 px: es lo primero que se busca con el
   pulgar al abrir el menú por error. */
.sidebar__cerrar {
  display: none;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin-left: auto;
  font-size: 1.15rem;
  color: var(--text-color);
  background: transparent;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  cursor: pointer;
}

.sidebar__cerrar:hover { background: var(--superficie-2); }

/* ----------------------------------------------------------
   Header
   ---------------------------------------------------------- */
.header {
  display: flex;
  align-items: center;
  gap: .75rem;
  min-height: var(--alto-header);
  padding: .55rem 1rem;
  background: var(--card-color);
  border-bottom: 1px solid var(--borde);
}

.header__hamburguesa {
  display: none;              /* sólo en móvil */
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  font-size: 1.2rem;
  color: var(--text-color);
  background: transparent;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  cursor: pointer;
}

.header__titulo { flex: 1; min-width: 0; }

.header__titulo h1 {
  font-size: .98rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.header__sigla { display: none; }

.header__subtitulo {
  font-size: .78rem;
  color: var(--texto-tenue);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.header__acciones {
  display: flex;
  align-items: center;
  gap: .5rem;
}

.header__usuario {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.25;
}

.header__nombre { font-size: .88rem; font-weight: 600; }

.etiqueta-rol {
  font-size: .66rem;
  font-weight: 600;
  letter-spacing: .4px;
  padding: .1rem .4rem;
  color: var(--primary-color);
  background: var(--superficie-2);
  border-radius: 4px;
}

.header__logout { margin: 0; }

/* ----------------------------------------------------------
   Selector de tema y paleta de acento
   ---------------------------------------------------------- */
.selector-tema { position: relative; display: flex; gap: .4rem; }

.paleta {
  position: absolute;
  top: calc(100% + .4rem);
  right: 0;
  z-index: 50;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: .4rem;
  padding: .55rem;
  background: var(--card-color);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  box-shadow: var(--sombra);
}


.paleta__color {
  width: 26px;
  height: 26px;
  border: 2px solid transparent;
  border-radius: 50%;
  cursor: pointer;
}

.paleta__color--activo { border-color: var(--text-color); }

.paleta__color--azul    { background: #2563eb; }
.paleta__color--verde   { background: #16a34a; }
.paleta__color--morado  { background: #7c3aed; }
.paleta__color--naranja { background: #ea580c; }
.paleta__color--rojo    { background: #dc2626; }
.paleta__color--cian    { background: #0891b2; }

/* ----------------------------------------------------------
   Contenido
   ---------------------------------------------------------- */
.contenido { flex: 1; padding: 1.25rem 1rem; }

.contenido__titulo { font-size: 1.25rem; }

.contenido__bajada {
  margin-top: .2rem;
  margin-bottom: 1.25rem;
  font-size: .9rem;
  color: var(--texto-tenue);
}

.grilla {
  display: grid;
  gap: .85rem;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}

.tarjeta {
  padding: 1rem;
  background: var(--card-color);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  box-shadow: var(--sombra);
}

.tarjeta--enlace {
  display: block;
  color: inherit;
  text-decoration: none;
}

.tarjeta--enlace:hover { border-color: var(--primary-color); }

.tarjeta__icono {
  display: inline-block;
  margin-bottom: .4rem;
  font-size: 1.3rem;
  color: var(--primary-color);
}

.tarjeta__titulo { font-size: .98rem; }

/* Un título que lleva a algún lado: el relleno lo deja por encima de los
   24 px para tocar con el dedo (medía 21 en «Mesas de examen»). */
.tarjeta__titulo a { display: inline-block; padding-block: .2rem; }

.tarjeta__estado {
  margin-top: .15rem;
  font-size: .8rem;
  color: var(--texto-tenue);
}

/* La acción secundaria de una tarjeta, debajo de la principal. Era un
   enlace de 17 px de alto. */
.tarjeta__secundaria { margin-top: .5rem; font-size: .9rem; }

/* Panel de inicio: una tarjeta por cosa pendiente o por saber hoy. El
   borde izquierdo dice de un vistazo si hay algo que hacer. */
.inicio {
  display: grid;
  gap: .85rem;
  grid-template-columns: repeat(auto-fill, minmax(min(18rem, 100%), 1fr));
  align-items: start;
}

.inicio__tarjeta { border-left-width: 4px; }
.inicio__tarjeta--pendiente { border-left-color: var(--atencion); }
.inicio__tarjeta--listo     { border-left-color: var(--exito); }

/* El borde dice el estado de un vistazo, pero sólo a quien distingue el
   ámbar del verde. La marca del título dice lo mismo sin depender del
   color (WCAG 1.4.1). Después de la barra va lo que lee un lector de
   pantalla: nada, porque el texto de la tarjeta ya lo dice. */
.inicio__tarjeta--pendiente .tarjeta__titulo::before,
.inicio__tarjeta--listo .tarjeta__titulo::before {
  display: inline-grid;
  place-items: center;
  width: 1.25rem;
  height: 1.25rem;
  margin-right: .45rem;
  vertical-align: -.15rem;
  border-radius: 50%;
  font-size: .78rem;
  font-weight: 700;
  color: var(--card-color);
}
.inicio__tarjeta--pendiente .tarjeta__titulo::before { content: "!"; content: "!" / ""; background: var(--atencion); }
.inicio__tarjeta--listo .tarjeta__titulo::before     { content: "✓"; content: "✓" / ""; background: var(--exito); }

.inicio__dato { margin: .35rem 0 0; font-size: .92rem; }

/* Los cursos sin lista, como botones: en el teléfono uno por renglón y
   de ancho completo, con aire entre uno y otro. */
.inicio__accesos {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
  gap: .5rem;
  margin: .65rem 0 0;
}

.inicio__acceso {
  display: flex;
  align-items: center;
  gap: .45rem;
  min-height: 44px;
  padding: .4rem .85rem;
  font-size: .9rem;
  font-weight: 500;
  color: var(--text-color);
  text-decoration: none;
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}

.inicio__acceso:hover { border-color: var(--primary-color); }

/* Una cosa por renglón —clases, encuestas, certificados—: el renglón
   entero es el enlace, y la flecha dice que lleva a algún lado. */
.inicio__filas { margin: .5rem 0 0; }
.inicio__filas li + li { border-top: 1px solid var(--borde); }

.inicio__fila {
  display: flex;
  align-items: center;
  gap: .6rem;
  min-height: 44px;
  padding: .35rem .5rem;
  margin: 0 -.5rem;
  font-size: .9rem;
  color: var(--text-color);
  text-decoration: none;
  border-radius: var(--radio);
}

.inicio__fila:hover { background: var(--superficie-2); }

.inicio__fila::after {
  content: "›";
  content: "›" / "";
  font-size: 1.2rem;
  line-height: 1;
  color: var(--texto-tenue);
}

.inicio__fila-texto { flex: 1; min-width: 0; }

.inicio__fila-dato {
  color: var(--texto-tenue);
  font-variant-numeric: tabular-nums;
}

.inicio__lista {
  margin: .5rem 0 0;
  padding-left: 1.1rem;
  font-size: .9rem;
}
.inicio__lista li + li { margin-top: .2rem; }

.inicio__hora {
  display: inline-block;
  min-width: 3rem;
  font-variant-numeric: tabular-nums;
  color: var(--texto-tenue);
}

.inicio__cifras {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: .5rem;
  margin: .6rem 0 0;
}
.inicio__cifras dt { font-size: .75rem; color: var(--texto-tenue); }
.inicio__cifras dd { margin: 0; font-size: 1.15rem; font-weight: 600; }

/* Lo que resuelve la tarjeta, como botón y no como enlace de 18 px. */
.inicio__pie {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin: .8rem 0 0;
}

.inicio__pie .boton {
  min-height: 44px;
  font-size: .88rem;
  color: var(--primary-color);
}

/* ----------------------------------------------------------
   Utilidades
   ---------------------------------------------------------- */

/* Visible para lectores de pantalla, oculto visualmente. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.vacio {
  padding: 2rem 1rem;
  text-align: center;
  color: var(--texto-tenue);
  background: var(--card-color);
  border: 1px dashed var(--borde);
  border-radius: var(--radio);
}

.insignia {
  padding: .05rem .35rem;
  font-size: .68rem;
  font-weight: 600;
  color: var(--texto-tenue);
  background: var(--superficie-2);
  border-radius: 4px;
}

/* ----------------------------------------------------------
   Encabezado de sección
   ---------------------------------------------------------- */
.contenido__encabezado {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}

.contenido__encabezado .contenido__bajada { margin-bottom: 0; }

/* ----------------------------------------------------------
   Filtros y búsqueda
   ---------------------------------------------------------- */
.filtros {
  display: flex;
  gap: .5rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}

.filtros__busqueda { flex: 1 1 220px; }

.filtros input,
.filtros select,
.formulario select,
.formulario--linea select {
  min-height: 40px;
  padding: .45rem .6rem;
  font: inherit;
  font-size: 15px;
  color: var(--text-color);
  background: var(--card-color);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}

.filtros input:focus,
.filtros select:focus { border-color: var(--primary-color); }

/* ----------------------------------------------------------
   Tablas
   ---------------------------------------------------------- */
.tabla-scroll {
  overflow-x: auto;               /* la tabla scrollea, no la página */
  /* Sin esto, lo que va con position:absolute adentro —el «Acciones»
     oculto del encabezado, que es .sr-only— no queda recortado por el
     scroll: se ubicaba donde caía la última columna, fuera de la
     pantalla, y estiraba la página entera. En Profesores, a 768 px, la
     página medía 790 y se podía correr de costado. */
  position: relative;
  background: var(--card-color);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}

.tabla {
  width: 100%;
  border-collapse: collapse;
  font-size: .9rem;
}

.tabla th,
.tabla td {
  padding: .6rem .75rem;
  text-align: left;
  border-bottom: 1px solid var(--borde);
}

/* Las dos reglas siguientes se enganchan a `data-etiqueta`, que ya es
   parte de la estructura de las tablas —de ahí saca el modo tarjeta del
   celular el rótulo de cada celda—. Así valen para las once tablas que
   tienen una columna Fecha sin ir a tocarlas una por una, y para la
   próxima también. */

/* Una fecha no se parte. «2026-09-» arriba y «04» abajo se lee como dos
   datos distintos, y pasa apenas otra columna de la fila se estira. */
.tabla td[data-etiqueta="Fecha"] { white-space: nowrap; }

/* Una observación es texto que escribió una persona, y puede venir sin
   un solo espacio donde cortar. Sin esto la celda crece hasta donde haga
   falta, la tabla se desarma y el resto de las columnas se apretujan
   —doscientos caracteres seguidos dejaban la fecha en dos renglones—. */
.tabla td[data-etiqueta="Observación"] {
  overflow-wrap: anywhere;
  max-width: 38rem;
}

/* ----------------------------------------------------------
   Encabezados que ordenan
   ----------------------------------------------------------
   El botón lo agrega interfaz.js: sin JavaScript el encabezado queda
   como estaba y la tabla se lee igual. */
.tabla__ordenar {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  /* 24 px de alto como mínimo para el clic (WCAG 2.5.8): con el alto del
     texto medía 19. */
  min-height: 24px;
  padding: 0;
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}

.tabla__ordenar:hover { color: var(--primary-color); }

/* La flecha ocupa su lugar desde el principio, aunque no esté ordenada:
   si apareciera recién al primer clic, todos los encabezados se
   correrían un poco y la tabla daría un salto. */
.tabla__flecha::before {
  content: "↕";
  font-size: .85em;
  opacity: .45;
}

[aria-sort="ascending"] .tabla__flecha::before { content: "↑"; opacity: 1; }
[aria-sort="descending"] .tabla__flecha::before { content: "↓"; opacity: 1; }

[aria-sort="ascending"] .tabla__ordenar,
[aria-sort="descending"] .tabla__ordenar { color: var(--primary-color); }

/* ----------------------------------------------------------
   Períodos rápidos
   ----------------------------------------------------------
   «Cómo viene este chico» es la pregunta de todos los días, y con dos
   campos de fecha obligaba a calcular a mano qué día fue hace un mes. */
.rangos {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem;
  margin-bottom: .75rem;
}

.rangos__rotulo {
  align-self: center;
  margin-right: .2rem;
  font-size: .8rem;
  font-weight: 600;
  color: var(--texto-tenue);
}

.tabla thead th {
  font-size: .78rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .3px;
  color: var(--texto-tenue);
  background: var(--superficie-2);
  white-space: nowrap;
}

.tabla tbody tr:last-child td { border-bottom: 0; }
.tabla tbody tr:hover { background: var(--superficie-2); }

.tabla__acciones {
  display: flex;
  gap: .35rem;
  justify-content: flex-end;
  align-items: center;
  flex-wrap: wrap;
}

.tabla__acciones form { margin: 0; }

/* Motivo + botón dentro de una celda: en una fila si entra, apilado si
   no. Lo usa la lista de alumnos sin nota del cierre de período, donde
   marcar «no cursó» exige escribir por qué. */
.formulario-en-linea {
  display: flex;
  gap: .35rem;
  align-items: center;
  flex-wrap: wrap;
  margin: 0;
}

.formulario-en-linea input[type="text"] { flex: 1 1 180px; min-width: 0; }

/* ----------------------------------------------------------
   Indicadores de estado
   ---------------------------------------------------------- */
.estado {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  font-size: .8rem;
  font-weight: 500;
  white-space: nowrap;
}

.estado::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
}

.estado--activo   { color: var(--exito); }
.estado--inactivo { color: var(--texto-tenue); }

/* ----------------------------------------------------------
   Paginación
   ---------------------------------------------------------- */
.paginacion {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .75rem;
  margin-top: 1rem;
}

.paginacion__estado {
  font-size: .85rem;
  color: var(--texto-tenue);
}

/* ----------------------------------------------------------
   Formularios de alta y edición
   ---------------------------------------------------------- */
.formulario {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  max-width: 520px;
  padding: 1.25rem;
  background: var(--card-color);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  box-shadow: var(--sombra);
}

.campo__ayuda {
  font-size: .78rem;
  color: var(--texto-tenue);
}

.formulario__acciones {
  display: flex;
  gap: .5rem;
  flex-wrap: wrap;
  padding-top: .25rem;
}

/* Formularios con varios bloques temáticos (alta de alumno). */
.formulario--ancho { max-width: 780px; }

.grupo {
  min-width: 0;      /* sin esto un fieldset no se deja encoger en grid */
  margin: 0;
  padding: 0;
  border: 0;
}

.grupo + .grupo {
  padding-top: 1rem;
  border-top: 1px solid var(--borde);
}

.grupo__titulo {
  padding: 0;
  margin-bottom: .75rem;
  font-size: .8rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .4px;
  color: var(--texto-tenue);
}

.grupo__campos {
  display: grid;
  gap: .85rem;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}

.campo--ancho { grid-column: 1 / -1; }

/* Bloque de datos vinculados debajo de un formulario (alumnos a cargo). */
.seccion-relacionada { margin-top: 1.25rem; }

/* Casilla de verificación con su etiqueta al costado. */
.campo--casilla {
  flex-direction: row;
  align-items: center;
  gap: .5rem;
}

.campo--casilla input {
  width: 18px;
  height: 18px;
  min-height: 0;
  margin: 0;
  accent-color: var(--primary-color);
}

.campo--casilla label {
  margin: 0;
  font-weight: 400;
  color: var(--text-color);
}

/* ----------------------------------------------------------
   Fichas de contacto (tutores de un alumno)
   ---------------------------------------------------------- */
.fichas-contacto {
  display: grid;
  gap: .7rem;
  margin-bottom: 1rem;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}

.ficha-contacto {
  padding: .85rem;
  background: var(--card-color);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}

.ficha-contacto__encabezado {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: .5rem;
  margin-bottom: .6rem;
}

.ficha-contacto__encabezado form { margin: 0; }

.ficha-contacto__nombre {
  display: block;
  margin-bottom: .2rem;
  font-size: .95rem;
}

/* Etiqueta arriba, dato abajo: a 360 px una grilla de dos columnas
   deja los domicilios largos ilegibles. */
.ficha-contacto__datos {
  display: grid;
  gap: .4rem;
  margin: 0;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
}

.ficha-contacto__datos dt {
  font-size: .7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .3px;
  color: var(--texto-tenue);
}

.ficha-contacto__datos dd {
  margin: 0;
  font-size: .88rem;
  overflow-wrap: anywhere;   /* correos y domicilios largos no desbordan */
}

.insignia--destacada {
  color: var(--primary-color);
  background: var(--superficie-2);
}

/* Alumno libre por inasistencias. Se sigue pudiendo tomar asistencia:
   la insignia advierte, no bloquea. */
.insignia--alerta {
  color: var(--peligro);
  background: var(--peligro-fondo);
  border: 1px solid var(--peligro);
}

/* Cerca del límite de faltas: todavía se puede evitar. */
.insignia--aviso {
  color: var(--atencion);
  background: var(--atencion-fondo);
  border: 1px solid var(--atencion);
}

/* Formulario de vinculación: en una fila si entra, apilado si no. */
.vincular-tutor {
  display: flex;
  align-items: flex-end;
  gap: .6rem;
  flex-wrap: wrap;
  padding: .85rem;
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}

.vincular-tutor .campo { flex: 1 1 180px; }
.vincular-tutor .campo--casilla { flex: 0 0 auto; align-self: center; }

.vincular-tutor select {
  min-height: 40px;
  padding: .45rem .6rem;
  font: inherit;
  font-size: 15px;
  color: var(--text-color);
  background: var(--card-color);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}

/* ----------------------------------------------------------
   Credencial recién generada
   Se muestra una sola vez, así que tiene que saltar a la vista.
   ---------------------------------------------------------- */
.credencial {
  margin-bottom: 1rem;
  padding: 1rem;
  background: var(--exito-fondo);
  border: 2px solid var(--exito);
  border-radius: var(--radio);
}

.credencial__titulo {
  margin-bottom: .7rem;
  font-size: .95rem;
  color: var(--exito);
}

.credencial__datos {
  display: flex;
  gap: 2rem;
  flex-wrap: wrap;
  margin: 0 0 .7rem;
}

.credencial__datos dt {
  font-size: .72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .3px;
  color: var(--texto-tenue);
}

.credencial__datos dd { margin: .15rem 0 0; }

.credencial__datos code {
  display: inline-block;
  padding: .3rem .6rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 1.05rem;
  letter-spacing: .5px;
  color: var(--text-color);
  background: var(--card-color);
  border: 1px solid var(--borde);
  border-radius: 6px;
  user-select: all;            /* un clic selecciona toda la credencial */
}

.credencial__aviso {
  font-size: .82rem;
  color: var(--texto-tenue);
}

code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .92em;
}

/* ----------------------------------------------------------
   Calificaciones
   ---------------------------------------------------------- */

/* Selector de trimestre y tipo dentro de cada tarjeta de materia. */
.planilla-selector {
  display: grid;
  gap: .5rem;
  margin-top: .8rem;
  grid-template-columns: 1fr 1fr;
}

.planilla-selector .boton { grid-column: 1 / -1; }

.planilla-selector select {
  min-height: 38px;
  padding: .4rem .5rem;
  font: inherit;
  font-size: 15px;
  color: var(--text-color);
  background: var(--card-color);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}

/* Campo de nota: angosto y centrado, para recorrer la columna de un vistazo. */
.entrada-nota {
  width: 5rem;
  min-height: 40px;
  padding: .4rem .5rem;
  font: inherit;
  font-size: 16px;         /* evita el zoom de iOS al enfocar */
  font-weight: 600;
  text-align: center;
  color: var(--text-color);
  background: var(--card-color);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}

.entrada-nota:focus { border-color: var(--primary-color); }

/* La nota final calculada por el sistema se distingue de la que escribió
   una persona. El borde punteado no es el único indicador: el título del
   campo lo dice, y el historial muestra la insignia "calculada". */
.entrada-nota--calculada {
  border-style: dashed;
  color: var(--texto-tenue);
  background: var(--superficie-2);
}

/* Período cerrado: la nota se ve pero no se edita. El fondo no es el
   único indicador — el campo es readonly, el encabezado de la columna
   lleva el símbolo y su title lo dice. */
.entrada-nota--cerrada {
  background: var(--superficie-2);
  color: var(--texto-tenue);
  cursor: not-allowed;
}

.columna--cerrada { color: var(--texto-tenue); }

.columna__candado {
  font-size: .8em;
  opacity: .8;
}

/* Planilla de cinco períodos: las columnas de nota se aprietan para que
   la grilla completa entre sin scroll horizontal en una netbook. */
.tabla--planilla .entrada-nota {
  width: 4.25rem;
}

.tabla--planilla th:not(:first-child),
.tabla--planilla td:not(:first-child) {
  text-align: center;
  white-space: nowrap;
}

/* El DNI bajo el nombre del alumno: presente, sin competir con él. */
.tabla__secundario {
  display: block;
  font-size: .8125rem;
  color: var(--texto-tenue);
}

.entrada-observacion {
  width: 100%;
  min-width: 10rem;
  min-height: 40px;
  padding: .4rem .6rem;
  font: inherit;
  font-size: 16px;
  color: var(--text-color);
  background: var(--card-color);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}

/* Nota mostrada: el color distingue aprobado de desaprobado sin depender
   sólo del número, pero el valor sigue visible para quien no percibe el
   color. */
.nota {
  display: inline-block;
  min-width: 2.4rem;
  padding: .15rem .45rem;
  font-weight: 700;
  text-align: center;
  border-radius: 6px;
}

.nota--aprobada    { color: var(--exito);   background: var(--exito-fondo); }
.nota--desaprobada { color: var(--peligro); background: var(--peligro-fondo); }

/* Y una marca además del color. El número solo no alcanzaba: 5,13 y 6,63
   se distinguían por el verde y el rojo, y para leerlos hay que saber que
   el umbral es 6 (informe de UX del 29/9/2026, WCAG 1.4.1). En el boletín
   impreso en blanco y negro, el color ni siquiera llega. Lo que va después
   de la barra es lo que lee un lector de pantalla. */
.nota--aprobada::after,
.nota--desaprobada::after {
  margin-left: .25rem;
  font-weight: 400;
  font-size: .85em;
}
.nota--aprobada::after    { content: "✓"; content: "✓" / "aprobada"; }
.nota--desaprobada::after { content: "✗"; content: "✗" / "desaprobada"; }

/* Notas sueltas de un alumno, en fila. */
.notas-sueltas {
  display: inline-flex;
  gap: .25rem;
  flex-wrap: wrap;
}

.nota--chica {
  min-width: 1.9rem;
  padding: .05rem .3rem;
  font-size: .8rem;
}

.nota--anulada {
  color: var(--texto-tenue);
  background: var(--superficie-2);
  text-decoration: line-through;
}

/* Una nota anulada se conserva en el historial pero se atenúa. */
/* Apagadas con color y fondo, no con transparencia: al 60 % el texto
   secundario quedaba en 2,5:1, por debajo del mínimo (informe de UX del
   29/9/2026). Con el tono tenue sigue viéndose apagada y se lee. */
.fila--anulada,
.fila--baja { color: var(--texto-tenue); background: var(--superficie-2); }

.editar-nota {
  display: flex;
  align-items: center;
  gap: .3rem;
  margin: 0;
}

.editar-nota .entrada-nota {
  width: 4.2rem;
  min-height: 32px;
  padding: .2rem .3rem;
  font-size: 15px;
}

/* ----------------------------------------------------------
   Variantes de botón y alerta añadidas por el módulo de usuarios
   ---------------------------------------------------------- */
.boton--chico {
  min-height: 32px;
  padding: .25rem .6rem;
  font-size: .82rem;
}

/* Peligro con borde y sin relleno: una baja no puede pesar lo mismo que
   «Guardar». Relleno se veía igual que el botón principal, y con el
   acento rojo eran idénticos (informe de UX del 29/9/2026, hallazgo 01).
   Se llena recién al pasar por encima, y en el diálogo que la confirma. */
.boton--peligro {
  color: var(--peligro);
  background: transparent;
  border-color: var(--peligro);
}

.boton--peligro:hover,
.boton--peligro:focus-visible,
.boton--peligro-lleno {
  color: var(--sobre-acento);
  background: var(--peligro);
  border-color: var(--peligro);
  filter: none;
}

.alerta--exito {
  color: var(--exito);
  background: var(--exito-fondo);
  border-color: var(--exito);
}

/* Ni error ni éxito: algo que todavía no pasó y que el usuario no puede
   hacer que pase. Usa la misma escala que --atencion en las insignias. */
.alerta--aviso {
  color: var(--atencion);
  background: var(--atencion-fondo);
  border-color: var(--atencion);
}

/* ----------------------------------------------------------
   Página de error
   ---------------------------------------------------------- */
.error {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .75rem;
  min-height: 100vh;
  padding: 1.5rem;
  text-align: center;
}

.error__codigo {
  font-size: 3.2rem;
  font-weight: 700;
  line-height: 1;
  color: var(--primary-color);
}

.error__mensaje { font-size: 1.1rem; font-weight: 500; max-width: 46ch; }

.error__detalles {
  font-size: .87rem;
  color: var(--texto-tenue);
}

/* ----------------------------------------------------------
   Notificaciones
   ---------------------------------------------------------- */

/* Contador de no leídas en el menú lateral. */
.sidebar__contador {
  margin-left: auto;
  min-width: 20px;
  padding: .05rem .35rem;
  font-size: .7rem;
  font-weight: 700;
  text-align: center;
  color: var(--sobre-acento);
  background: var(--peligro);
  border-radius: 999px;
}

/* En tablet el sidebar muestra sólo iconos: el contador se superpone. */
@media (max-width: 1024px) and (min-width: 721px) {
  .sidebar__link { position: relative; }
  .sidebar__contador {
    position: absolute;
    top: 2px;
    right: 2px;
    margin: 0;
    min-width: 16px;
    font-size: .62rem;
    padding: 0 .2rem;
  }
}

/* ----------------------------------------------------------
   Pestañas de filtro
   ---------------------------------------------------------- */
.pestanias {
  display: flex;
  align-items: center;
  gap: .25rem;
  flex-wrap: wrap;
  margin-bottom: .9rem;
  border-bottom: 1px solid var(--borde);
}

.pestania {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .5rem .8rem;
  font-size: .88rem;
  color: var(--texto-tenue);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;   /* se apoya sobre el borde del contenedor */
}

.pestania:hover { color: var(--text-color); }

.pestania--activa {
  color: var(--primary-color);
  border-bottom-color: var(--primary-color);
  font-weight: 600;
}

/* Los descartados no son un estado más de la bandeja: se separan. */
.pestania--aparte { margin-left: auto; }

.pestania__cuenta {
  font-size: .72rem;
  font-weight: 600;
  padding: .05rem .4rem;
  border-radius: 999px;
  background: var(--superficie-2);
  border: 1px solid var(--borde);
}

.pestania--activa .pestania__cuenta {
  background: var(--primary-color);
  border-color: var(--primary-color);
  color: var(--card-color);
}

/* ----------------------------------------------------------
   Bandeja agrupada por día
   ---------------------------------------------------------- */
.dia + .dia { margin-top: 1.5rem; }

.dia__titulo {
  display: flex;
  align-items: baseline;
  gap: .6rem;
  margin: 0 0 .55rem;
  padding-bottom: .3rem;
  border-bottom: 1px solid var(--borde);
}

.dia__nombre {
  font-size: .78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: var(--texto-tenue);
}

.dia__cuenta {
  font-size: .75rem;
  font-weight: 400;
  color: var(--texto-tenue);
}

.lista-notificaciones {
  display: flex;
  flex-direction: column;
  gap: .5rem;
}

.notificacion {
  display: flex;
  align-items: flex-start;
  gap: .75rem;
  padding: .85rem;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}

/* Sin leer: fondo de tarjeta plena, borde de acento a la izquierda y la
   etiqueta textual. El color solo no alcanza para señalar el estado. */
.notificacion--sin-leer {
  background: var(--card-color);
  border-left: 3px solid var(--primary-color);
  box-shadow: var(--sombra);
}

/* Leída: se hunde contra el fondo. Sigue legible —no se baja el
   contraste del texto— pero deja de competir con lo que falta leer. */
.notificacion--leida {
  background: transparent;
  border-style: dashed;
}

.notificacion--leida .notificacion__asunto { font-weight: 500; }

.notificacion__enlace {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: .25rem;
  color: inherit;
  text-decoration: none;
}

.notificacion__cabecera {
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: wrap;
}

.notificacion__asunto {
  font-weight: 600;
  font-size: .95rem;
}

.notificacion--sin-leer .notificacion__asunto { font-weight: 700; }

.notificacion__meta {
  font-size: .78rem;
  color: var(--texto-tenue);
}

/* Extracto de dos líneas: alcanza para reconocer el mensaje sin abrirlo. */
.notificacion__extracto {
  font-size: .85rem;
  color: var(--texto-tenue);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  /* Respaldo por si `-webkit-line-clamp` no se aplica: sin esto, un
     aviso de dos mil caracteres se despliega entero y una bandeja de
     treinta avisos se vuelve ilegible. Dos renglones a 1.4 de interlínea
     son 2.8em; se redondea a 2.9em para que no corte las tildes. */
  max-height: 2.9em;
}

.notificacion__hora {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

/* En columna y no en fila: dos botones cortos uno al lado del otro se
   confunden entre sí cuando la fila es angosta. */
.notificacion__acciones {
  display: flex;
  flex-direction: column;
  gap: .3rem;
  flex-shrink: 0;
}

.notificacion__acciones form { margin: 0; }
.notificacion__acciones .boton { width: 100%; justify-content: center; }

.acciones-bandeja {
  display: flex;
  gap: .4rem;
  flex-wrap: wrap;
  margin-bottom: .9rem;
}

.acciones-bandeja form { margin: 0; }

@media (max-width: 620px) {
  /* En pantalla angosta los botones pasan abajo, a lo ancho: al costado
     dejarían el asunto en dos caracteres por línea. */
  .notificacion { flex-direction: column; }
  .notificacion__acciones { flex-direction: row; width: 100%; }
  .notificacion__acciones form { flex: 1; }
  .pestania--aparte { margin-left: 0; }
}

.filtros__separador { flex: 1 1 auto; }

.mensaje-completo {
  max-width: 720px;
  padding: 1.25rem;
  background: var(--card-color);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  box-shadow: var(--sombra);
}

/* Respeta los saltos de línea que escribió el emisor sin permitir marcado. */
.mensaje-completo__texto {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  line-height: 1.6;
}

.formulario textarea {
  min-height: 9rem;
  padding: .6rem .7rem;
  font: inherit;
  font-size: 16px;
  line-height: 1.5;
  color: var(--text-color);
  background: var(--card-color);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  resize: vertical;
}

.formulario textarea:focus { border-color: var(--primary-color); }

/* ----------------------------------------------------------
   Auditoría
   ---------------------------------------------------------- */

/* Tipo de acción. El color acompaña, pero el texto siempre está. */
.accion {
  display: inline-block;
  padding: .1rem .45rem;
  font-size: .78rem;
  font-weight: 600;
  border-radius: 4px;
  background: var(--superficie-2);
  white-space: nowrap;
}

/* Con su fondo y no el gris común: el verde sobre gris daba 4,43:1. */
.accion--insert, .accion--exitoso   { color: var(--exito); background: var(--exito-fondo); }
.accion--delete, .accion--fallido   { color: var(--peligro); background: var(--peligro-fondo); }
.accion--update                     { color: var(--primary-color); }
.accion--login                      { color: var(--texto-tenue); }
.accion--error, .accion--bloqueado  { color: var(--peligro); font-weight: 700; }

/* Valor anterior y posterior de un campo modificado. El tachado y la
   etiqueta «modificado» hacen legible el cambio sin depender del color. */
.cambio__antes {
  color: var(--texto-tenue);
  text-decoration: line-through;
}

.cambio__despues {
  font-weight: 600;
  color: var(--text-color);
}

.fila--cambiada td:first-child { border-left: 3px solid var(--primary-color); }

.cambios-resumen {
  display: flex;
  flex-direction: column;
  gap: .2rem;
  font-size: .82rem;
}

.cambios-resumen code { font-size: .78rem; color: var(--texto-tenue); }

/* Conteos por acción y módulo que encabezan el listado. */
.etiquetas-resumen {
  display: flex;
  gap: .4rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}

.etiqueta-resumen {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  padding: .25rem .6rem;
  font-size: .8rem;
  color: var(--texto-tenue);
  background: var(--card-color);
  border: 1px solid var(--borde);
  border-radius: 999px;
}

.etiqueta-resumen__cantidad {
  font-weight: 700;
  color: var(--text-color);
}

/* ----------------------------------------------------------
   Medidas (barras de las estadísticas)

   Se usa <meter>, no un div con ancho calculado: una barra con ancho
   dinámico exigiría un style="" en línea, que la CSP bloquea. Además
   <meter> ya es accesible —los lectores de pantalla anuncian valor y
   rango— y no necesita JavaScript.

   El pseudo-elemento del relleno difiere entre motores, así que hay que
   escribirlo dos veces. Si el navegador no aplica ninguno, la barra se
   ve con el estilo nativo y el número al lado sigue siendo legible.
   ---------------------------------------------------------- */
.medida {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  white-space: nowrap;
}

.medida__barra {
  width: 90px;
  height: 10px;
  border: 1px solid var(--borde);
  border-radius: 5px;
  background: var(--superficie-2);
  /* Chrome no aplica background al elemento sin esto. */
  -webkit-appearance: none;
  appearance: none;
}

.medida__barra::-webkit-meter-bar {
  background: var(--superficie-2);
  border: 0;
  border-radius: 5px;
}

.medida__barra::-webkit-meter-optimum-value    { background: var(--exito);   border-radius: 5px; }
.medida__barra::-webkit-meter-suboptimum-value { background: #d97706;        border-radius: 5px; }
.medida__barra::-webkit-meter-even-less-good-value { background: var(--peligro); border-radius: 5px; }

.medida__barra:-moz-meter-optimum::-moz-meter-bar     { background: var(--exito); }
.medida__barra:-moz-meter-sub-optimum::-moz-meter-bar { background: #d97706; }
.medida__barra:-moz-meter-sub-sub-optimum::-moz-meter-bar { background: var(--peligro); }

/* Barra sin lectura de bueno/malo: sólo proporción. */
.medida__barra--neutra::-webkit-meter-optimum-value { background: var(--primary-color); }
.medida__barra--neutra:-moz-meter-optimum::-moz-meter-bar { background: var(--primary-color); }

/* ----------------------------------------------------------
   Asistencias
   ---------------------------------------------------------- */

/* Selector de estado: botones grandes, pensados para marcar rápido
   con el dedo en un teléfono mientras se pasa lista. */
.estados {
  display: flex;
  gap: .3rem;
  flex-wrap: wrap;
  margin: 0;
  padding: 0;
  border: 0;
}

.estados__opcion {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 38px;
  padding: .3rem .55rem;
  font-size: .82rem;
  font-weight: 500;
  color: var(--texto-tenue);
  background: var(--card-color);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  cursor: pointer;
  user-select: none;
}

/* El radio real queda invisible pero sigue siendo el que recibe el foco
   y el que leen los lectores de pantalla. */
.estados__opcion input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.estados__opcion:hover { background: var(--superficie-2); }

.estados__opcion:has(input:focus-visible) {
  outline: 2px solid var(--primary-color);
  outline-offset: 2px;
}

/*
  El estado elegido, marcado DOS veces.
  ------------------------------------------------------------------
  La primera con `input:checked + span`, que pinta el texto adentro de
  la etiqueta. La segunda con `:has()`, que además pinta el recuadro
  entero. Se ve mejor con `:has()`, pero sin él la primera alcanza para
  saber qué está marcado.

  Hace falta el par porque el radio real es invisible —1 píxel y
  opacidad cero, para que el foco y los lectores de pantalla lo sigan
  encontrando—, así que si el estilo del seleccionado no aparece, la
  planilla queda con los cuatro botones idénticos y el preceptor pasa
  lista a ciegas. `:has()` recién llegó a Firefox en la 121, de diciembre
  de 2023, y las escuelas suelen quedarse en la versión ESR.

  El color no es el único indicador en ninguno de los dos caminos: el
  estado elegido va además en negrita.
*/
.estados__opcion input:checked + span {
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.estados__opcion--presente input:checked + span     { color: var(--exito); }
.estados__opcion--ausente input:checked + span      { color: var(--peligro); }
.estados__opcion--tarde input:checked + span,
.estados__opcion--justificada input:checked + span  { color: var(--text-color); }

/* El color por sí solo no alcanza: el estado seleccionado además se
   marca en negrita y con borde grueso. */
.estados__opcion:has(input:checked) {
  font-weight: 700;
  border-width: 2px;
}

.estados__opcion--presente:has(input:checked) {
  color: var(--exito);
  background: var(--exito-fondo);
  border-color: var(--exito);
}

.estados__opcion--ausente:has(input:checked) {
  color: var(--peligro);
  background: var(--peligro-fondo);
  border-color: var(--peligro);
}

.estados__opcion--tarde:has(input:checked),
.estados__opcion--justificada:has(input:checked) {
  color: var(--text-color);
  background: var(--superficie-2);
  border-color: var(--text-color);
}

/* Con `:has()` el recuadro ya lleva el color y el subrayado sobra. */
.estados__opcion:has(input:checked) input:checked + span {
  text-decoration: none;
}

/* Estados en los listados de consulta. */
.estado--presente    { color: var(--exito); }
.estado--ausente     { color: var(--peligro); }
.estado--tarde       { color: var(--texto-tenue); }
.estado--justificada { color: var(--primary-color); }

/* Indicador numérico grande de las tarjetas de resumen. */
.indicador {
  margin: .3rem 0 .2rem;
  font-size: 2rem;
  font-weight: 700;
  line-height: 1.1;
  color: var(--primary-color);
}

.indicador--chico { font-size: 1.5rem; color: var(--text-color); }

/* ----------------------------------------------------------
   Boletín
   ---------------------------------------------------------- */
.boletin {
  max-width: 800px;
  padding: 1.75rem;
  background: var(--card-color);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  box-shadow: var(--sombra);
}

/* Escudo a la izquierda y el nombre pegado a él, como el membrete de una
   nota en papel. Antes el sello iba al otro extremo y por eso separaba. */
.boletin__encabezado {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding-bottom: 1rem;
  margin-bottom: 1.25rem;
  border-bottom: 2px solid var(--borde);
}

.boletin__institucion { font-size: 1.05rem; }

.boletin__subtitulo {
  margin-top: .15rem;
  font-size: .82rem;
  color: var(--texto-tenue);
}

.boletin__escudo {
  width: 64px;
  height: 64px;
  flex-shrink: 0;
  object-fit: contain;
}

.boletin__titulo {
  margin-bottom: 1rem;
  font-size: .98rem;
  font-weight: 600;
}

.boletin__datos {
  display: grid;
  gap: .7rem;
  margin: 0 0 1.25rem;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}

.boletin__datos dt {
  font-size: .7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .3px;
  color: var(--texto-tenue);
}

.boletin__datos dd {
  margin: .15rem 0 0;
  font-size: .92rem;
  font-weight: 500;
}

.tabla--boletin tfoot th,
.tabla--boletin tfoot td {
  padding: .7rem .75rem;
  font-weight: 700;
  background: var(--superficie-2);
  border-top: 2px solid var(--borde);
}

.boletin__pie {
  margin-top: 1.25rem;
  font-size: .8rem;
  color: var(--texto-tenue);
}

.boletin__firmas {
  display: flex;
  gap: 2rem;
  flex-wrap: wrap;
  margin-top: 2.5rem;
}

.boletin__firma {
  flex: 1 1 180px;
  padding-top: .4rem;
  font-size: .78rem;
  text-align: center;
  border-top: 1px solid var(--text-color);
}

/* ----------------------------------------------------------
   Impresión
   El boletín se imprime desde el navegador: la exportación a PDF
   está prevista para una versión futura de la especificación.
   ---------------------------------------------------------- */
@media print {
  /* Todo lo que es navegación o acción no va al papel. */
  .sidebar,
  .sidebar__overlay,
  .header,
  .sin-imprimir,
  .alerta {
    display: none !important;
  }

  body { background: #fff; color: #000; }

  .app { display: block; }
  .contenido { padding: 0; }

  .boletin {
    max-width: none;
    padding: 0;
    background: #fff;
    border: 0;
    box-shadow: none;
  }

  /* La tabla no debe partirse entre páginas si puede evitarse. */
  .tabla-scroll { overflow: visible; border: 0; }
  .tabla { font-size: 11pt; }
  .tabla thead { display: table-header-group; }
  .tabla tr { break-inside: avoid; }

  /* Los colores de fondo suelen no imprimirse: la condición se lee
     igual en la columna de texto, y el número siempre está visible. */
  .nota {
    padding: 0;
    color: #000 !important;
    background: transparent !important;
  }

  /* El escudo sí se imprime con sus colores. El resto de la hoja va en
     negro para ahorrar tinta, pero el boletín es un documento que sale
     firmado de la escuela: el escudo es lo que lo identifica. */
  .boletin__escudo {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  .boletin__encabezado { border-bottom-color: #000; }
  .boletin__firma { border-top-color: #000; }

  /* Impresión por lote: cada boletín en su propia hoja.
     `break-before` sobre el segundo en adelante y no `break-after` sobre
     todos, porque `break-after` en el último deja una hoja en blanco al
     final — treinta boletines, treinta hojas desperdiciadas. */
  .boletines-lote .boletin + .boletin { break-before: page; }

  @page { margin: 1.5cm; }
}

/* En pantalla, los boletines del lote se separan para que se vea dónde
   termina uno y empieza el siguiente. */
.boletines-lote .boletin + .boletin { margin-top: 2rem; }

/* ----------------------------------------------------------
   Responsive
   Escritorio: sidebar fijo. Tablet: sidebar angosto, sólo iconos.
   Móvil: sidebar oculto, se abre con el botón hamburguesa.
   ---------------------------------------------------------- */
@media (max-width: 1024px) {
  :root { --ancho-sidebar: 62px; }

  .sidebar__texto,
  .sidebar__institucion,
  .sidebar__flecha { display: none; }

  .sidebar__link { justify-content: center; padding: .6rem; }
  .sidebar__marca { justify-content: center; padding: .3rem 0 1rem; }

  /* En la barra de iconos el título de sección no entra, pero se lo
     saca de la vista y no del árbol de accesibilidad: es lo que nombra
     la lista por `aria-labelledby`, y con `display:none` ese nombre
     quedaría vacío. La separación pasa a hacerla una línea. */
  .sidebar__seccion {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
  }

  .sidebar__seccion + .sidebar__lista {
    margin-top: .5rem;
    padding-top: .5rem;
    border-top: 1px solid var(--borde);
  }

  /* Sin ancho para sangrar: los iconos de un grupo abierto se alinean
     con el resto y se distinguen por el fondo. */
  .sidebar__sublista {
    padding-left: 0;
    background: var(--superficie-2);
    border-radius: var(--radio);
  }
}

@media (max-width: 720px) {
  :root { --ancho-sidebar: 232px; }

  .sidebar {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 50;
    transform: translateX(-100%);
    transition: transform .2s ease;
  }

  .sidebar--abierto { transform: translateX(0); }

  .sidebar__texto,
  .sidebar__institucion { display: inline; }

  .sidebar__link { justify-content: flex-start; padding: .55rem .6rem; }
  .sidebar__marca { justify-content: flex-start; padding: .3rem 0 1rem .5rem; }
  .sidebar__cerrar { display: inline-flex; }

  /* Con el ✕ la barra necesita más que 232 px para que el nombre de la
     escuela no quede en cuatro renglones; sigue dejando a la vista una
     franja de la pantalla, que es lo que dice que esto se cierra. */
  .sidebar { width: min(300px, 86vw); overflow-y: auto; }

  /* En el teléfono la barra vuelve a medir 232 px, así que vuelve a
     entrar todo lo que la barra de iconos había tenido que esconder.
     Sin esto, el menú del celular —que es donde más apretado está—
     quedaba sin los títulos de sección: se veían las líneas
     separadoras y ningún nombre. */
  .sidebar__seccion {
    position: static;
    width: auto;
    height: auto;
    margin: .9rem .6rem .25rem;
    overflow: visible;
    clip: auto;
    white-space: normal;
  }

  .sidebar__seccion + .sidebar__lista {
    margin-top: 0;
    padding-top: 0;
    border-top: 0;
  }

  .sidebar__sublista {
    padding-left: 1.3rem;
    background: transparent;
  }

  .sidebar__flecha { display: block; }

  .header__hamburguesa { display: inline-flex; }
  .header__subtitulo,
  .header__usuario { display: none; }
  .header__titulo h1 { font-size: 1rem; letter-spacing: .04em; }

  /* La sigla en lugar del nombre cortado. El nombre completo sale de la
     vista y no del árbol de accesibilidad: es el título de la página. */
  .header__sigla { display: inline; }
  .header__nombre-completo {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
  }

  /* Una tabla de 6 columnas es ilegible a 360 px. Cada fila pasa a ser
     una tarjeta con la etiqueta de columna al costado del dato, tomada
     del atributo data-etiqueta de cada celda. */
  .tabla-scroll {
    background: transparent;
    border: 0;
    overflow-x: visible;
  }

  .tabla thead { display: none; }

  .tabla,
  .tabla tbody,
  .tabla tr,
  .tabla td { display: block; width: 100%; }

  .tabla tr {
    margin-bottom: .65rem;
    background: var(--card-color);
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    overflow: hidden;
  }

  .tabla tbody tr:hover { background: var(--card-color); }

  .tabla td {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: .5rem .75rem;
    text-align: right;
  }

  .tabla td::before {
    content: attr(data-etiqueta);
    flex-shrink: 0;
    font-size: .75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .3px;
    color: var(--texto-tenue);
    text-align: left;
  }

  /* La celda de acciones no lleva etiqueta ni alineación a la derecha. */
  .tabla td.tabla__acciones {
    justify-content: flex-start;
    background: var(--superficie-2);
  }

  .tabla td.tabla__acciones::before { content: none; }

  .filtros__busqueda { flex: 1 1 100%; }
  .filtros select { flex: 1 1 calc(50% - .25rem); }
}

@media (max-width: 380px) {
  .contenido { padding: 1rem .75rem; }
  .grilla { grid-template-columns: 1fr; }
}

/* Un comando para copiar y pegar. Se usa en la pantalla de respaldos,
   donde restaurar no tiene botón a propósito. */
.bloque-comando {
  margin: .5rem 0;
  padding: .7rem .85rem;
  overflow-x: auto;
  font-size: .85rem;
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}

/* Un dia sin lista tomada, en la planilla del profesor. Es informacion,
   no una alerta: todavia puede pasar preceptoria. */
.texto-sin-tomar {
  font-size: .85rem;
  font-style: italic;
  color: var(--texto-tenue);
}

/* ----------------------------------------------------------
   Horarios (RF10)
   ---------------------------------------------------------- */

.seccion__titulo {
  margin: 1.75rem 0 .75rem;
  font-size: 1rem;
  font-weight: 600;
  color: var(--texto-tenue);
  text-transform: uppercase;
  letter-spacing: .04em;
}

/* La grilla semanal. Cinco columnas de días más la de la hora: en un
   monitor entra entera, y en un teléfono la tabla ya scrollea sola
   dentro de .tabla-scroll. */
.tabla--horario { table-layout: fixed; }

.tabla--horario th[scope="col"]:first-child { width: 6.5rem; }

.horario__franja {
  display: flex;
  flex-direction: column;
  gap: .1rem;
  text-align: left;
  white-space: nowrap;
}

.horario__orden { font-weight: 600; }

.horario__hora {
  font-size: .8rem;
  font-weight: 400;
  color: var(--texto-tenue);
}

.horario__celda { vertical-align: top; padding: .3rem; }

.horario__clase {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: .1rem;
  min-height: 3.2rem;
  padding: .45rem .55rem;
  border-radius: var(--radio);
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  font-size: .88rem;
}

.horario__profesor {
  font-size: .8rem;
  color: var(--texto-tenue);
}

/* El botón de quitar vive dentro de la celda y no debe empujar el texto:
   por eso va posicionado y no en el flujo. */
.horario__quitar {
  position: absolute;
  top: .2rem;
  right: .2rem;
}

.boton-icono--chico {
  width: 24px;
  height: 24px;
  font-size: .9rem;
  line-height: 1;
  border-color: transparent;
  color: var(--texto-tenue);
}

.boton-icono--chico:hover {
  border-color: var(--peligro);
  color: var(--peligro);
}

/* La celda vacía es un destino, no un hueco: tiene que invitar a
   tocarla y ocupar lo mismo que una con clase, para que la grilla no
   salte al llenarse. */
.horario__vacia {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 3.2rem;
  border: 1px dashed var(--borde);
  border-radius: var(--radio);
  color: var(--texto-tenue);
  font-size: 1.2rem;
  text-decoration: none;
}

.horario__vacia:hover {
  border-color: var(--primary-color);
  border-style: solid;
  color: var(--primary-color);
}

.horario__libre {
  display: block;
  padding: .9rem 0;
  text-align: center;
  color: var(--texto-tenue);
}

/* Elegir qué materia va en una franja. */
.lista-opciones { display: flex; flex-direction: column; gap: .6rem; }

.lista-opciones__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: .8rem 1rem;
  background: var(--card-color);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}

.lista-opciones__item--ocupada { opacity: .65; }

@media (max-width: 640px) {
  .lista-opciones__item { flex-direction: column; align-items: stretch; }
}

/* ----------------------------------------------------------
   Ciclos lectivos
   ---------------------------------------------------------- */

.insignia--exito {
  color: var(--exito);
  background: var(--exito-fondo);
  border-color: var(--exito);
}

/* Un formulario de un solo campo: el campo y el botón en la misma línea,
   alineados por abajo porque el campo lleva etiqueta arriba. */
.formulario--linea {
  display: flex;
  align-items: flex-end;
  gap: .75rem;
  flex-wrap: wrap;
  margin-top: .5rem;
}

.formulario--linea .campo { max-width: 160px; }

/* Una fila que ya no está vigente: se lee, pero no compite con las que sí.
   La trayectoria del alumno la usa para las matrículas reemplazadas. */

/* ----------------------------------------------------------
   Formulario en curso
   ----------------------------------------------------------
   El botón deshabilitado ya se ve distinto, pero el cursor de
   espera sobre el formulario entero es lo que le dice a la
   persona que el clic llegó. Sin eso vuelve a hacer clic, que
   es justamente lo que se está evitando. */
.formulario--enviando {
  cursor: progress;
}

.formulario--enviando button[type="submit"] {
  opacity: 0.6;
}

/* ----------------------------------------------------------
   Saltar al contenido
   ----------------------------------------------------------
   Fuera de la vista hasta que se lo enfoca con el teclado. No
   se usa display:none ni visibility:hidden porque eso lo saca
   del orden de tabulación, que es justamente para lo que
   existe. */
.saltar-al-contenido {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 0.7rem 1.1rem;
  background: var(--primary-color, #1d4ed8);
  color: var(--sobre-acento, #fff);
  border-radius: 0 0 6px 0;
  text-decoration: none;
}

.saltar-al-contenido:focus {
  left: 0;
}

/* ----------------------------------------------------------
   Observación de la planilla: botón y diálogo
   ----------------------------------------------------------
   El campo de texto por fila pasó a ser un botón que abre un
   diálogo, como en la app: la observación es la excepción del
   día, no algo para completar en cada renglón. Ver
   interfaz.js; sin JavaScript se sigue viendo el campo. */
/* Tampoco más ancho que su celda: en la vista angosta la fila es una
   tarjeta de unos 343 px, y 22rem son 352 — un texto largo la desbordaba
   (informe de UX del 29/9/2026, hallazgo 06). */
.observacion {
  max-width: min(22rem, 100%);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: left;
  font-weight: normal;
  color: var(--texto-tenue);
}

/* Con algo escrito deja de ser una invitación y pasa a ser un dato. */
.observacion--escrita {
  color: var(--text-color);
  border-color: var(--borde);
}

.observacion::before {
  content: "✎";
  margin-right: .35rem;
}

.dialogo {
  width: min(32rem, calc(100vw - 2rem));
  padding: 0;
  color: var(--text-color);
  background: var(--card-color);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  box-shadow: var(--sombra);
}

.dialogo::backdrop {
  background: rgba(4, 9, 16, .55);
}

.dialogo__cuerpo {
  display: flex;
  flex-direction: column;
  gap: .75rem;
  padding: 1.25rem;
}

.dialogo__titulo {
  margin: 0;
  font-size: 1.05rem;
}

.dialogo__bajada {
  margin: 0;
  font-size: .9rem;
  color: var(--texto-tenue);
}

.dialogo textarea {
  width: 100%;
  /* 16px: con menos, iOS hace zoom al enfocar y descoloca la pantalla. */
  font: inherit;
  font-size: 16px;
  padding: .5rem .6rem;
  color: var(--text-color);
  background: var(--card-color);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  resize: vertical;
}

.dialogo__acciones {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .5rem;
}

/* Separa «Quitar» de «Cancelar» y «Aceptar»: borrar no se toca por
   error al ir a confirmar. */
.dialogo__espacio {
  flex: 1;
}

/* ------------------------------------------------------------------ */
/* Enlaces dentro de un aviso                                          */
/* ------------------------------------------------------------------ */

/* Van como botones aparte y no incrustados en el texto: el mensaje se
   sigue mostrando escapado, así que no puede inyectar marcado. Debajo
   del botón va la dirección entera, para poder leer a dónde lleva antes
   de tocarlo. */
.enlaces-del-aviso {
  margin-top: 1.5rem;
}

.enlaces-del-aviso__titulo {
  font-size: 1rem;
  margin-bottom: 0.5rem;
}

.enlaces-del-aviso__lista {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0.75rem;
}

.enlaces-del-aviso__url {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.8rem;
  color: var(--texto-tenue);
  /* Una dirección larga no puede empujar el ancho de la página. */
  overflow-wrap: anywhere;
}

/* ------------------------------------------------------------------ */
/* Nota final que se aparta del promedio                               */
/* ------------------------------------------------------------------ */

/* Informa, no reclama. Que la final puesta a mano no coincida con el
   promedio puede ser deliberado —el profesor tiene motivos que el sistema
   no conoce— así que esto va en letra chica, en el color de texto tenue y
   sin ningún adorno de alerta. Lo único que agrega es el dato que faltaba:
   cuánto daba el promedio, y un modo de ponerlo. */
.nota-difiere {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.72rem;
  line-height: 1.2;
  color: var(--texto-tenue);
  /* Sin nowrap: el texto va debajo de una celda angosta y forzarlo a una
     línea lo desbordaba sobre la columna vecina. */
  overflow-wrap: anywhere;
}

/* Un enlace, no un botón: apretarlo es una corrección menor, y un botón
   de verdad competiría visualmente con «Guardar planilla». */
.nota-difiere__usar {
  background: none;
  border: 0;
  padding: 0;
  margin-left: 0.2rem;
  font: inherit;
  color: var(--primary-color);
  text-decoration: underline;
  cursor: pointer;
}

.nota-difiere__usar:hover,
.nota-difiere__usar:focus-visible {
  text-decoration: none;
}

/* ------------------------------------------------------------------ */
/* La ficha de la cuenta, en la cabecera                               */
/* ------------------------------------------------------------------ */

/* Reemplaza al enlace suelto que mostraba el nombre de usuario —el DNI,
   para profesores y alumnos— con estilo de hipervínculo: azul, subrayado
   y flotando al lado de «Salir». Acá es un bloque con su propia forma,
   que es lo que uno espera de la cuenta en una barra superior. */
.cuenta {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .25rem .5rem .25rem .25rem;
  border-radius: 999px;
  color: inherit;
  text-decoration: none;
  transition: background-color .15s ease;
}

.cuenta:hover,
.cuenta:focus-visible {
  background: var(--superficie-2);
  text-decoration: none;
}

/* Las iniciales dan el ancla visual: se reconoce la cuenta de un vistazo,
   sin leer. */
.cuenta__inicial {
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  flex: none;
  border-radius: 50%;
  background: var(--primary-color);
  color: var(--sobre-acento);
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .02em;
}

.cuenta__texto {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
  /* Un nombre largo recorta en vez de empujar a «Salir» fuera de la barra. */
  min-width: 0;
}

.cuenta__nombre {
  font-size: .85rem;
  font-weight: 600;
  max-width: 12rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* El rol acompaña, no compite: sin mayúsculas ni recuadro. Antes decía
   PROFESOR en versalitas y parecía un grito. */
.cuenta__rol {
  font-size: .72rem;
  color: var(--texto-tenue);
}

/* En pantallas chicas queda el círculo: dice de quién es la sesión sin
   ocupar media barra. */
@media (max-width: 640px) {
  .cuenta__texto { display: none; }
  .cuenta { padding: .25rem; }
}

/* ----------------------------------------------------------
   Cambios sin guardar en las planillas
   ----------------------------------------------------------
   La celda cambiada lleva un borde de atención además del fondo:
   el color no es el único indicador. La barra queda pegada al pie
   de la ventana mientras haya algo pendiente. Ver interfaz.js. */
.celda--cambiada {
  background: var(--atencion-fondo);
  box-shadow: inset 3px 0 0 var(--atencion);
}

.barra-cambios {
  position: sticky;
  bottom: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  margin-top: 1rem;
  padding: .6rem .9rem;
  color: var(--text-color);
  background: var(--atencion-fondo);
  border: 1px solid var(--atencion);
  border-radius: var(--radio);
  box-shadow: var(--sombra);
}

.barra-cambios[hidden] { display: none; }

.barra-cambios__texto::before {
  content: "●";
  margin-right: .45rem;
  color: var(--atencion);
}

@media print { .barra-cambios { display: none; } }

/* Donde al lado ya está escrita la condición —la columna «Condición» del
   boletín—, la marca sobra: un lector de pantalla la leería dos veces. */
.nota--sin-marca::after { content: none; }

/* ----------------------------------------------------------
   Reglas de la planilla, arriba y a mano
   ---------------------------------------------------------- */
.planilla__reglas {
  margin: 0 0 .5rem;
  font-size: .9rem;
  color: var(--texto-tenue);
}

.planilla__ayuda {
  margin: 0 0 1rem;
  font-size: .9rem;
}

/* Con el color de texto y no el de acento: con algunos acentos —el naranja
   en modo claro— no llegaba al contraste mínimo. */
.planilla__ayuda summary {
  cursor: pointer;
  font-weight: 500;
  text-decoration: underline dotted;
  text-underline-offset: 3px;
}

.planilla__ayuda p {
  max-width: 70ch;
  margin: .4rem 0 0;
  color: var(--texto-tenue);
}

.formulario__nota {
  align-self: center;
  font-size: .85rem;
  color: var(--texto-tenue);
}

/* Cambiar de planilla desde su encabezado. */
.selector-planilla {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .4rem;
}

.selector-planilla select,
.selector-planilla input[type="date"] {
  min-height: 32px;
  max-width: 100%;
  padding: .25rem .5rem;
  font: inherit;
  font-size: .9rem;
  color: var(--text-color);
  background: var(--card-color);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}

/* ----------------------------------------------------------
   Menú de acciones por fila
   ---------------------------------------------------------- */
/* El nombre del alumno abre su ficha. Con el alto del texto medía 22 px,
   menos que el mínimo para tocar con el dedo (WCAG 2.5.8): el relleno lo
   lleva a 28 sin mover la fila. */
.enlace-fila {
  display: inline-block;
  padding-block: .2rem;
  color: inherit;
  text-decoration: none;
}
.enlace-fila:hover strong,
.enlace-fila:focus-visible strong { text-decoration: underline; }

.menu-acciones { position: relative; display: inline-block; }
.menu-acciones > summary { list-style: none; min-width: 2.5rem; letter-spacing: .1em; }
.menu-acciones > summary::-webkit-details-marker { display: none; }

.menu-acciones__lista {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  z-index: 20;
  display: flex;
  flex-direction: column;
  min-width: 11rem;
  padding: .3rem;
  background: var(--card-color);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  box-shadow: var(--sombra);
}

.menu-acciones__lista a,
.menu-acciones__lista button {
  display: block;
  width: 100%;
  padding: .45rem .6rem;
  font: inherit;
  font-size: .9rem;
  text-align: left;
  color: var(--text-color);
  text-decoration: none;
  background: none;
  border: 0;
  border-radius: calc(var(--radio) - 2px);
  cursor: pointer;
}

.menu-acciones__lista a:hover,
.menu-acciones__lista button:hover,
.menu-acciones__lista a:focus-visible,
.menu-acciones__lista button:focus-visible { background: var(--superficie-2); }

.menu-acciones__lista form { margin: 0; }

/* La baja, separada y en su color: la única acción que no es de consulta. */
.menu-acciones__peligro { color: var(--peligro) !important; border-top: 1px solid var(--borde) !important; border-radius: 0 !important; margin-top: .2rem; }

@media print { .menu-acciones { display: none; } }

/* ----------------------------------------------------------
   Mesas de examen
   ---------------------------------------------------------- */

/* Datos de una mesa: etiqueta a la izquierda, dato a la derecha; en un
   teléfono, uno debajo del otro. */
.ficha { display: grid; gap: .45rem; margin: 0; }
.ficha > div { display: grid; grid-template-columns: minmax(8rem, 12rem) 1fr; gap: .75rem; }
.ficha dt { color: var(--texto-tenue); font-size: .88rem; }
.ficha dd { margin: 0; }
@media (max-width: 600px) {
  .ficha > div { grid-template-columns: 1fr; gap: .1rem; }
}

.mesa-tarjeta__fecha { font-size: 1.05rem; font-weight: 600; }

/* ----------------------------------------------------------
   Encuestas
   ---------------------------------------------------------- */

.encuesta__preguntas > li { margin-bottom: .75rem; }
.encuesta__preguntas ul { margin: .25rem 0 .35rem; }

.encuesta__pregunta { border: 0; padding: 0; margin: 0 0 1.1rem; }
.encuesta__pregunta legend { font-weight: 600; margin-bottom: .35rem; }
/* Un radio o una casilla con su texto al lado, sin que el texto se parta
   debajo del control. */
.opcion { display: inline-flex; gap: .4rem; align-items: center; white-space: nowrap; }
.encuesta__pregunta .opcion { display: flex; padding: .2rem 0; white-space: normal; }

/* La casilla en sí: la de fábrica mide 13 px, chica para el dedo. Se toca
   toda la etiqueta, pero el cuadrito es lo que se busca con la vista. */
.opcion input[type="checkbox"],
.opcion input[type="radio"] {
  flex: none;
  width: 1.15rem;
  height: 1.15rem;
  margin: 0;
  accent-color: var(--primary-color);
}

/* Una opción con una frase entera, que en el teléfono no entra en un
   renglón: se parte en vez de cortarse en el borde. */
.opcion--frase { white-space: normal; min-height: 44px; }
.encuesta__escala { display: flex; flex-wrap: wrap; gap: .4rem .9rem; align-items: center; }

.encuesta__participacion { font-size: 1.05rem; margin: 0 0 .75rem; }

/* Una fila por opción: texto, barra y número. En un teléfono el texto va
   arriba y la barra ocupa el ancho. */
.barra-resultado {
  display: grid;
  grid-template-columns: minmax(8rem, 1fr) minmax(6rem, 2fr) 7rem;
  gap: .6rem;
  align-items: center;
  margin: .3rem 0;
}
.barra-resultado__medidor { width: 100%; }
.barra-resultado__numero { font-variant-numeric: tabular-nums; color: var(--texto-tenue); font-size: .88rem; }
@media (max-width: 600px) {
  .barra-resultado { grid-template-columns: 1fr 6.5rem; }
  .barra-resultado__texto { grid-column: 1 / -1; }
}

.encuesta__textos li, .encuesta__faltan li { margin: .3rem 0; }

/* Previas en el boletín: lo que adeuda a la fecha de consulta. */
.boletin__previas { margin-top: 1.25rem; }
.boletin__subtitulo-seccion { font-size: 1rem; margin: 0 0 .5rem; }
.boletin__aclaracion { margin: .35rem 0 0; font-size: .8rem; color: var(--texto-tenue); }

/* ----------------------------------------------------------
   Pestañas (riesgo pedagógico) y resumen
   ---------------------------------------------------------- */

/* Enlaces y no botones: cada vista tiene su dirección, se puede volver
   con «atrás» y abrir en otra pestaña. */
.pestanas {
  display: flex;
  gap: .25rem;
  border-bottom: 1px solid var(--borde);
  margin: 0 0 1rem;
  overflow-x: auto;
}
.pestanas__item {
  padding: .55rem .9rem;
  color: var(--texto-tenue);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  white-space: nowrap;
}
.pestanas__item:hover { color: var(--text-color); }
.pestanas__item--activa { color: var(--primary-color); border-bottom-color: var(--primary-color); font-weight: 600; }

.riesgo__resumen { margin: 0 0 .75rem; }

.riesgo__reglas p { margin: 0; }
.riesgo__reglas ul { margin: .3rem 0; padding-left: 1.1rem; list-style: disc; }

/* Los niveles de riesgo como filtro: cuántos hay en cada uno antes de
   elegir cuál mirar. El nombre del nivel va escrito; el punto de color
   acompaña. */
.niveles {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin: 0 0 .75rem;
}

.niveles__item {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  min-height: 44px;
  padding: .35rem .85rem;
  font-size: .9rem;
  color: var(--text-color);
  text-decoration: none;
  background: var(--card-color);
  border: 1px solid var(--borde);
  border-radius: 999px;
}

.niveles__item:hover { border-color: var(--primary-color); }

.niveles__item--activo {
  color: var(--primary-color);
  border-color: var(--primary-color);
  font-weight: 600;
}

.niveles__item--alto::before,
.niveles__item--medio::before,
.niveles__item--bajo::before {
  content: "";
  width: .6rem;
  height: .6rem;
  border-radius: 50%;
}
.niveles__item--alto::before  { background: var(--peligro); }
.niveles__item--medio::before { background: var(--atencion); }
.niveles__item--bajo::before  { background: var(--primary-color); }

.niveles__cuenta {
  min-width: 1.5rem;
  padding: 0 .35rem;
  font-size: .8rem;
  font-weight: 700;
  text-align: center;
  background: var(--superficie-2);
  border-radius: 999px;
  font-variant-numeric: tabular-nums;
}

/* El nivel en la tabla: más grande que las insignias de los motivos, que
   lo explican. */
.nivel-riesgo {
  display: inline-block;
  padding: .15rem .55rem;
  font-size: .8rem;
}
