/* =========================================================================
   STA Reemplazos — hoja de estilos de la aplicación (Fase 1)
   Nace del CSS de los mockups aprobados (mockups/assets/estilo-sta.css):
   misma paleta institucional, mismo semáforo de estados, mismo aire.
   No se duplica variable por variable "porque sí": si la skill sta-stack
   §7 cambia la paleta, se cambia acá y se propaga sola a toda la app.
   ========================================================================= */

:root {
  /* Institucional */
  --sta-azul:        #1B4965;
  --sta-azul-claro:  #5FA8D3;
  --sta-arena:       #F7F5F2;
  --sta-tinta:       #1F2933;
  --sta-gris:        #6B7280;
  --sta-borde:       #E1DDD4;
  --sta-blanco:      #FFFFFF;

  /* Semáforo de estados del reemplazo — mismo color en calendario, tablero e impresos */
  --estado-sin-cubrir:        #C62828;  --estado-sin-cubrir-fondo:  #FDECEA;
  --estado-asignado:          #B26A00;  --estado-asignado-fondo:    #FFF4E0;
  --estado-confirmado:        #1565C0;  --estado-confirmado-fondo:  #E7F0FB;
  --estado-realizado:         #2E7D32;  --estado-realizado-fondo:   #E8F5E9;
  --estado-anulado:           #616161;  --estado-anulado-fondo:     #F0F0F0;

  --sombra-tarjeta: 0 1px 3px rgba(31,41,51,.08), 0 1px 2px rgba(31,41,51,.06);
  --sombra-flotante: 0 8px 28px rgba(31,41,51,.18);
  --radio: 10px;
  --radio-chico: 6px;
  --transicion: 240ms ease;

  /* Bootstrap adopta la paleta institucional en vez de la suya */
  --bs-font-sans-serif: 'Inter', system-ui, -apple-system, sans-serif;
  --bs-body-font-family: 'Inter', system-ui, -apple-system, sans-serif;
  --bs-body-color: var(--sta-tinta);
  --bs-body-bg: var(--sta-arena);
  --bs-primary: var(--sta-azul);
  --bs-primary-rgb: 27, 73, 101;
  --bs-link-color: var(--sta-azul);
  --bs-link-hover-color: var(--sta-azul-claro);
  --bs-border-radius: var(--radio-chico);
  --bs-border-color: var(--sta-borde);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

html { scroll-behavior: smooth; }

body {
  background: var(--sta-arena);
  color: var(--sta-tinta);
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden; /* nunca scroll horizontal de la página completa (celular) */
}

/* El atributo `hidden` nativo pierde contra cualquier regla de autor que
   fije `display` (p. ej. `.alerta-global{display:flex}`), porque el origen
   "autor" siempre gana sobre el del navegador aunque la especificidad sea
   igual. app.js alterna vistas y avisos con `.hidden`, así que esta regla
   es la que de verdad los oculta. */
[hidden] { display: none !important; }

a { color: var(--sta-azul); text-decoration: none; }
a:hover { color: var(--sta-azul-claro); text-decoration: underline; }

h1, h2, h3, h4, h5 { color: var(--sta-tinta); font-weight: 700; letter-spacing: -.01em; }

.text-institucional { color: var(--sta-azul); }
.text-gris-sta { color: var(--sta-gris); }

/* Accesibilidad: salta directo al contenido sin pasar por el menú */
.enlace-saltar {
  position: absolute;
  left: -999px;
  top: 0;
  background: var(--sta-tinta);
  color: #fff;
  padding: .6rem 1rem;
  z-index: 2000;
  border-radius: 0 0 var(--radio-chico) 0;
}
.enlace-saltar:focus { left: 0; }

/* -------------------------------------------------------------------------
   Encabezado institucional
   ------------------------------------------------------------------------- */
.app-header {
  background: var(--sta-azul);
  color: #fff;
  padding: .7rem 1rem;
  position: sticky;
  top: 0;
  z-index: 1030;
}
.app-header .liceo {
  font-size: .68rem;
  text-transform: uppercase;
  letter-spacing: .06em;
  opacity: .8;
}
.app-header h1 {
  color: #fff;
  font-size: 1.05rem;
  margin: 0;
}
.app-header .fecha-hoy { font-size: .78rem; opacity: .85; }

.avatar-usuario {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: #fff;
  color: var(--sta-azul);
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.rol-tag {
  display: inline-flex; align-items: center; gap: .3rem; font-size: .64rem; font-weight: 800;
  text-transform: uppercase; letter-spacing: .04em; border-radius: 999px; padding: .16rem .5rem;
  background: rgba(255,255,255,.18); color: #fff;
}

/* -------------------------------------------------------------------------
   Menú principal — barra bajo el encabezado, colapsa en celular
   ------------------------------------------------------------------------- */
.app-menu {
  background: #143a51;
  border-bottom: 1px solid rgba(255,255,255,.08);
}
.app-menu .navbar-nav .nav-link {
  color: rgba(255,255,255,.8);
  font-weight: 600;
  font-size: .88rem;
  padding: .7rem .9rem;
  border-left: 3px solid transparent;
  transition: background var(--transicion), color var(--transicion);
}
.app-menu .navbar-nav .nav-link i { width: 1.1em; text-align: center; margin-right: .4rem; }
.app-menu .navbar-nav .nav-link:hover { color: #fff; background: rgba(255,255,255,.06); }
.app-menu .navbar-nav .nav-link.activo {
  color: #fff;
  background: rgba(255,255,255,.1);
  border-left-color: var(--sta-azul-claro);
}
.app-menu .navbar-nav .nav-link.bloqueado {
  opacity: .4;
  pointer-events: none;
}
/* Insignias de avisos del menú (docs/API.md §12). Llevan el NÚMERO escrito, no
   un punto de color: un punto dice "pasa algo", un `3` dice qué hacer. Y el
   borde blanco las deja legibles en blanco y negro, igual que el resto de la
   aplicación (sta-stack §7). En cero no se dibuja nada.

   Son dos, y a propósito se distinguen a simple vista, porque no son la misma
   urgencia:
     · Postulaciones → ámbar `asignado`: alguien tiene que DECIDIR algo.
     · Reemplazos    → rojo `sin_cubrir`: un bloque de HOY va a pasar en unas
       horas y no hay nadie. Es el mismo #C62828 de `estados_reemplazo.color`
       que esa persona ya ve en el calendario y en las tablas — no una paleta
       nueva, porque un rojo que significa dos cosas distintas en dos
       pantallas deja de significar nada. */
.app-menu .navbar-nav .nav-link .badge-aviso-menu {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 1.35rem; height: 1.35rem; padding: 0 .35rem; margin-left: .45rem;
  font-size: .7rem; font-weight: 800; line-height: 1; font-variant-numeric: tabular-nums;
  color: #fff; border: 1.5px solid #fff; border-radius: 999px;
}
.app-menu .navbar-nav .nav-link .badge-aviso-menu--postulaciones { background: var(--estado-asignado); }
.app-menu .navbar-nav .nav-link .badge-aviso-menu--sin-cubrir    { background: var(--estado-sin-cubrir); }
@media (min-width: 768px) {
  .app-menu .navbar-nav .nav-link.activo { border-left: none; border-bottom: 3px solid var(--sta-azul-claro); }

  /* El menú NUNCA esconde una entrada.
   *
   * `navbar-expand-md` de Bootstrap pone la lista en fila con `nowrap`. Con
   * cuenta de administrador son 17 entradas que miden 1599 px, así que en una
   * pantalla de 1366 al 100 % de zoom se salían cuatro por el borde derecho:
   * Importar, Usuarios, Imprimir y **Mi clave** — la de cambiar la contraseña.
   * No quedaban recortadas a medias, que se nota: quedaban FUERA, y el menú
   * terminaba limpio en "Pantalla de sala" como si ahí se acabara. A 75 % de
   * zoom sí cabían, y por eso el problema solo aparecía en un tamaño.
   *
   * `wrap` es el seguro: lo que no cabe baja a una segunda fila. Vale para
   * cualquier ancho y para cualquier rol, aunque mañana se agregue otra
   * entrada. */
  .app-menu .navbar-nav { flex-wrap: wrap; }
}

/* Se probó también apretar el espaciado y la letra en ese rango para que las
 * 17 entradas cupieran en UNA fila. No sirve, y conviene dejar escrito por
 * qué para que nadie lo reintente: con la letra más chica los rótulos largos
 * ("Registrar ausencia") dejan de partirse en dos líneas y el botón se vuelve
 * MÁS ANCHO. Medido en el navegador: la suma bajaba de 2151 a 1865 px, seguían
 * sin caber en los 1351 disponibles, y el menú quedaba igual en dos filas
 * —105 px de alto contra 107—. Dos píxeles a cambio de cambiarle la letra a
 * toda la aplicación. */
.btn-cerrar-sesion {
  background: transparent;
  border: 1.5px solid rgba(255,255,255,.5);
  color: #fff;
  border-radius: var(--radio-chico);
  font-weight: 600;
  font-size: .82rem;
  padding: .4rem .8rem;
  transition: background var(--transicion);
}
.btn-cerrar-sesion:hover { background: rgba(255,255,255,.14); color: #fff; }
.navbar-toggler { border-color: rgba(255,255,255,.5); }
.navbar-toggler:focus { box-shadow: 0 0 0 .2rem rgba(255,255,255,.25); }
.navbar-toggler-icon-sta { color: #fff; font-size: 1.2rem; }

/* -------------------------------------------------------------------------
   Barra de progreso superior — mientras hay una petición en curso
   ------------------------------------------------------------------------- */
.barra-progreso {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: var(--sta-azul-claro);
  z-index: 2100;
  transform: scaleX(0);
  transform-origin: left;
  opacity: 0;
  transition: transform 280ms ease, opacity 280ms ease;
}
.barra-progreso.activa { transform: scaleX(1); opacity: 1; }

/* -------------------------------------------------------------------------
   Avisos globales (éxito / error / info) — refuerzo con ícono y texto,
   nunca solo color, porque también aparece en pantallas que se imprimen.
   ------------------------------------------------------------------------- */
.alerta-global {
  display: flex;
  align-items: flex-start;
  gap: .6rem;
  border-radius: var(--radio);
  padding: .75rem .9rem;
  font-size: .9rem;
  border: 1.5px solid transparent;
  box-shadow: var(--sombra-flotante);
  animation: aparecer var(--transicion);
}
/* Flota sobre el contenido, no dentro de <main>: así sigue visible aunque
   la vista cambie de la app al login (p. ej. "tu sesión expiró"). */
.alerta-global--flotante {
  position: fixed;
  top: 12px;
  left: 50%;
  transform: translateX(-50%);
  width: min(560px, 92vw);
  z-index: 2050;
}
@keyframes aparecer { from { opacity: 0; transform: translate(-50%, -8px); } to { opacity: 1; transform: translate(-50%, 0); } }
.alerta-global span:nth-child(2) { flex: 1; }
.alerta-global .btn-cerrar-aviso {
  background: transparent;
  border: none;
  font-size: 1.2rem;
  line-height: 1;
  color: inherit;
  opacity: .6;
  cursor: pointer;
}
.alerta-global .btn-cerrar-aviso:hover { opacity: 1; }
.alerta-error   { background: var(--estado-sin-cubrir-fondo); color: var(--estado-sin-cubrir); border-color: var(--estado-sin-cubrir); }
.alerta-info    { background: var(--estado-confirmado-fondo); color: var(--estado-confirmado); border-color: var(--estado-confirmado); }
.alerta-exito   { background: var(--estado-realizado-fondo); color: var(--estado-realizado); border-color: var(--estado-realizado); }

/* variantes usadas dentro de formularios (mismo lenguaje visual, sin botón de cerrar) */
p.alerta-error, p.alerta-info, p.alerta-exito,
div.alerta-error, div.alerta-info, div.alerta-exito {
  border-radius: var(--radio-chico);
  padding: .55rem .75rem;
  font-size: .85rem;
  margin-bottom: 1rem;
}

/* -------------------------------------------------------------------------
   Semáforo de estados — el componente que se repite en todo el sistema
   ------------------------------------------------------------------------- */
.badge-estado {
  display: inline-flex; align-items: center; gap: .35rem; font-weight: 700; font-size: .78rem;
  padding: .28rem .6rem; border-radius: 999px; border: 1.5px solid transparent; line-height: 1.1; white-space: nowrap;
}
.badge-estado .icono { font-size: .95em; }
.badge-estado--sin-cubrir  { color: var(--estado-sin-cubrir);  background: var(--estado-sin-cubrir-fondo);  border-color: var(--estado-sin-cubrir); }
.badge-estado--asignado    { color: var(--estado-asignado);    background: var(--estado-asignado-fondo);    border-color: var(--estado-asignado); }
.badge-estado--confirmado  { color: var(--estado-confirmado);  background: var(--estado-confirmado-fondo);  border-color: var(--estado-confirmado); }
.badge-estado--realizado   { color: var(--estado-realizado);   background: var(--estado-realizado-fondo);   border-color: var(--estado-realizado); }
.badge-estado--anulado     { color: var(--estado-anulado);     background: var(--estado-anulado-fondo);     border-color: var(--estado-anulado); text-decoration: line-through; }
.leyenda-semaforo { display: flex; flex-wrap: wrap; gap: .5rem .9rem; align-items: center; }

/* Insignias de rol y de activo/inactivo, reutilizadas en Usuarios y Docentes */
.badge-rol { font-size: .68rem; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; padding: .2rem .55rem; border-radius: 999px; }
.badge-rol--admin      { background: #EDE7F6; color: #5E35B1; }
.badge-rol--directivo  { background: #eaf3f9; color: var(--sta-azul); }
.badge-rol--docente    { background: var(--estado-confirmado-fondo); color: var(--estado-confirmado); }

.badge-estado-simple { font-size: .72rem; font-weight: 700; padding: .2rem .55rem; border-radius: 999px; display: inline-flex; align-items: center; gap: .3rem; }
.badge-estado-simple--activo   { background: var(--estado-realizado-fondo); color: var(--estado-realizado); }
.badge-estado-simple--inactivo { background: var(--estado-anulado-fondo); color: var(--estado-anulado); }

.badge-pendiente {
  display: inline-flex; align-items: center; gap: .35rem; font-size: .72rem; font-weight: 700;
  background: var(--estado-asignado-fondo); color: var(--estado-asignado); border: 1px solid var(--estado-asignado);
  border-radius: 999px; padding: .25rem .6rem;
}

/* -------------------------------------------------------------------------
   Tarjetas y botones genéricos
   ------------------------------------------------------------------------- */
.tarjeta-sta { background: #fff; border: 1px solid var(--sta-borde); border-radius: var(--radio); box-shadow: var(--sombra-tarjeta); }

.btn-sta-primario {
  background: var(--sta-azul); color: #fff; border: none; border-radius: var(--radio-chico);
  font-weight: 600; padding: .55rem 1.1rem; transition: background var(--transicion), transform var(--transicion);
}
.btn-sta-primario:hover { background: #143a51; color: #fff; }
.btn-sta-primario:active { transform: scale(.98); }
.btn-sta-primario:disabled { opacity: .6; }

.btn-sta-fantasma {
  background: transparent; color: var(--sta-azul); border: 1.5px solid var(--sta-azul); border-radius: var(--radio-chico);
  font-weight: 600; padding: .5rem 1rem; transition: background var(--transicion);
}
.btn-sta-fantasma:hover { background: #eef4f8; color: var(--sta-azul); }

.btn-sta-peligro { background: var(--estado-sin-cubrir); color: #fff; border: none; border-radius: var(--radio-chico); font-weight: 700; }
.btn-sta-peligro:hover { background: #a41f1f; color: #fff; }

.btn-icono-sta {
  width: 34px; height: 34px; border-radius: var(--radio-chico); border: 1px solid var(--sta-borde);
  background: #fff; color: var(--sta-tinta); display: inline-flex; align-items: center; justify-content: center;
  transition: background var(--transicion), border-color var(--transicion);
}
.btn-icono-sta:hover { background: var(--sta-arena); border-color: var(--sta-azul-claro); }

/* -------------------------------------------------------------------------
   Cascarón de carga — el tercer estado inicial de index.html, entre "no se
   sabe si hay sesión" y "ya se sabe". Visible desde el primer instante (sin
   `hidden` en el HTML) para que nadie vea el login ni la app equivocados
   mientras se resuelve sesion.estado(); app.js lo oculta apenas responde.
   ------------------------------------------------------------------------- */
#cascaron-carga {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
}
.estado-carga { text-align: center; padding: 2.2rem 1rem; color: var(--sta-gris); }
.estado-carga i { font-size: 1.8rem; margin-bottom: .5rem; display: block; }

/* -------------------------------------------------------------------------
   Pantalla de invitado (login / recuperación) — tarjeta centrada
   ------------------------------------------------------------------------- */
.vista-pantalla-completa {
  /* 100vh se queda corto en celular: los navegadores móviles lo calculan con la
     barra de direcciones oculta, así que al aparecer ésta el degradado deja una
     franja clara abajo. 100dvh sigue la altura real; el 100vh queda como respaldo
     para navegadores viejos, que lo aplican y luego lo pisan si entienden dvh. */
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.25rem;
  background: linear-gradient(135deg, var(--sta-azul) 0%, #123549 100%);
}
.tarjeta-login {
  width: 100%;
  max-width: 400px;
  padding: 1.75rem 1.5rem;
}
.login-marca { text-align: center; margin-bottom: 1.4rem; }
.login-marca .liceo { font-size: .68rem; text-transform: uppercase; letter-spacing: .07em; color: var(--sta-gris); }
.login-marca h1 { font-size: 1.3rem; margin: .2rem 0 0; }

/* -------------------------------------------------------------------------
   Contenido de la app: filtros, tablas responsivas, tarjetas de listado
   ------------------------------------------------------------------------- */
main#contenido { max-width: 1240px; }

.barra-filtros { display: flex; flex-wrap: wrap; gap: .6rem; align-items: end; }
.barra-filtros .campo { display: flex; flex-direction: column; gap: .25rem; }
.barra-filtros label { font-size: .74rem; font-weight: 700; color: var(--sta-gris); }

/* Tabla que se convierte en tarjetas apiladas en celular: sin ella la
   tabla del horario / listado no funciona con una mano en el pasillo. */
.tabla-sta { width: 100%; border-collapse: collapse; }
.tabla-sta th {
  text-align: left; font-size: .72rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--sta-gris); border-bottom: 2px solid var(--sta-borde); padding: .55rem .6rem;
}
.tabla-sta td { padding: .65rem .6rem; border-bottom: 1px solid var(--sta-borde); vertical-align: middle; font-size: .9rem; }
.tabla-sta tbody tr:hover { background: #fbfaf8; }
.tabla-sta .celda-acciones { display: flex; gap: .4rem; justify-content: flex-end; }

@media (max-width: 767.98px) {
  .tabla-sta thead { display: none; }
  .tabla-sta, .tabla-sta tbody, .tabla-sta tr, .tabla-sta td { display: block; width: 100%; }
  .tabla-sta tr {
    background: #fff; border: 1px solid var(--sta-borde); border-radius: var(--radio);
    margin-bottom: .7rem; padding: .3rem .8rem; box-shadow: var(--sombra-tarjeta);
  }
  .tabla-sta td { border-bottom: 1px dashed var(--sta-borde); padding: .5rem 0; display: flex; justify-content: space-between; gap: .8rem; align-items: center; }
  .tabla-sta td:last-child { border-bottom: none; }
  .tabla-sta td::before { content: attr(data-etiqueta); font-weight: 700; color: var(--sta-gris); font-size: .74rem; flex-shrink: 0; }
  .tabla-sta .celda-acciones { justify-content: flex-end; width: 100%; }
}

.paginacion-sta { display: flex; align-items: center; justify-content: space-between; gap: .8rem; margin-top: .9rem; flex-wrap: wrap; }
.paginacion-sta .info { font-size: .84rem; color: var(--sta-gris); }

.estado-vacio { text-align: center; padding: 2.2rem 1rem; color: var(--sta-gris); }
.estado-vacio i { font-size: 1.8rem; margin-bottom: .5rem; display: block; opacity: .5; }

/* -------------------------------------------------------------------------
   Tablero — indicadores grandes (Fase 6, skill fase-6-panel-visual §1)
   ------------------------------------------------------------------------- */
.indicador { padding: 1.1rem 1.2rem; display: flex; flex-direction: column; gap: .15rem; min-height: 118px; justify-content: center; }
.indicador .etiqueta { font-size: .72rem; text-transform: uppercase; letter-spacing: .06em; font-weight: 700; color: var(--sta-gris); }
.indicador .valor { font-size: 2.3rem; font-weight: 800; line-height: 1; color: var(--sta-tinta); }
.indicador .detalle { font-size: .78rem; color: var(--sta-gris); }

/* -------------------------------------------------------------------------
   Nota de diseño / avisos suaves reutilizados dentro de formularios
   ------------------------------------------------------------------------- */
.nota-diseno {
  border: 1.5px dashed #b9c3cc; background: #fbfcfd; border-radius: var(--radio);
  padding: .85rem 1rem; font-size: .82rem; color: var(--sta-gris);
}
.nota-diseno strong { color: var(--sta-tinta); }

/* -------------------------------------------------------------------------
   Clave temporal (reseteo de contraseña) — se muestra una única vez
   ------------------------------------------------------------------------- */
.clave-temporal {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 1.3rem;
  letter-spacing: .04em;
  background: var(--sta-arena);
  border: 1.5px dashed var(--sta-azul-claro);
  border-radius: var(--radio-chico);
  padding: .6rem .8rem;
  text-align: center;
  user-select: all;
}

/* utilidades */
.solo-movil { display: none; }
@media (max-width: 767.98px) { .solo-movil { display: block; } .solo-escritorio { display: none !important; } }

/* -------------------------------------------------------------------------
   Impresión: por ahora esta fase no genera documentos imprimibles (eso
   llega en la Fase 5), pero de cortesía nunca se imprime el menú ni el
   encabezado de navegación si alguien presiona Ctrl+P desde cualquier vista.
   ------------------------------------------------------------------------- */
@media print {
  .app-header, .app-menu, .barra-progreso, .alerta-global, .no-imprimir { display: none !important; }
  body { background: #fff !important; }
}


/* Marca discreta en la fila del usuario conectado, donde antes iban los botones
   de resetear clave y desactivar. No es decorativa: explica por qué esa fila
   tiene menos acciones que las demás. */
.marca-tu-cuenta {
  font-size: .75rem;
  color: var(--sta-gris);
  font-style: italic;
  white-space: nowrap;
  align-self: center;
}

/* Cuenta maestra: se distingue de "tu cuenta" porque es una regla del sistema,
   no una relativa a quién está mirando. Va con escudo y en azul institucional
   para que se lea como protección y no como advertencia. */
.marca-cuenta-maestra {
  font-size: .75rem;
  color: var(--sta-azul);
  font-weight: 600;
  white-space: nowrap;
  align-self: center;
  display: inline-flex;
  gap: .3rem;
  align-items: center;
}

/* =========================================================================
   FASE 2 — Datos maestros y carga del horario
   ========================================================================= */

/* -------------------------------------------------------------------------
   Texto de dato faltante — nunca solo un guión mudo: siempre con ícono y
   texto (skill sta-stack §7 aplica también fuera del semáforo de estados),
   porque "sin sala" y "sin profesor jefe" son justo los datos que esta
   fase existe para completar.
   ------------------------------------------------------------------------- */
.texto-pendiente {
  color: var(--estado-asignado);
  font-style: italic;
  font-size: .85rem;
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  white-space: nowrap;
}

/* -------------------------------------------------------------------------
   Badge de ciclo — "1 CICLO" / "2 CICLO", el vocabulario literal del liceo
   (nunca "jornada"). Colores neutros a propósito: no es un estado del
   semáforo de reemplazos, es solo una etiqueta de agrupación.
   ------------------------------------------------------------------------- */
.badge-ciclo {
  display: inline-flex; align-items: center; font-size: .68rem; font-weight: 800;
  text-transform: uppercase; letter-spacing: .04em; padding: .2rem .55rem; border-radius: 999px;
  border: 1.5px solid var(--sta-borde);
}
.badge-ciclo--1 { background: #eef4f8; color: var(--sta-azul); border-color: var(--sta-azul-claro); }
.badge-ciclo--2 { background: #f3eefc; color: #5E35B1; border-color: #c9b7ee; }

.badge-tipo-sala {
  display: inline-flex; align-items: center; gap: .35rem; font-size: .78rem; font-weight: 600; color: var(--sta-tinta);
}
.badge-tipo-sala--especial { color: #5E35B1; }
.badge-tipo-sala i { width: 1.1em; text-align: center; }

/* Tipo de día no lectivo, en la pantalla de Feriados. Mismo lenguaje que
   `badge-tipo-sala`. Los tres llevan el nombre escrito y no solo el color,
   porque esta tabla se imprime y se pega en la sala. */
.badge-tipo-dia {
  display: inline-flex; align-items: center; gap: .35rem;
  font-size: .74rem; font-weight: 700; letter-spacing: .02em;
  padding: .15rem .55rem; border-radius: 999px; border: 1.5px solid;
}
.badge-tipo-dia--feriado    { color: var(--estado-confirmado); background: var(--estado-confirmado-fondo); border-color: var(--estado-confirmado); }
.badge-tipo-dia--vacaciones { color: var(--estado-realizado);  background: var(--estado-realizado-fondo);  border-color: var(--estado-realizado); }
.badge-tipo-dia--otro       { color: var(--sta-gris);          background: var(--sta-arena);               border-color: var(--sta-borde); }

/* Lápiz para editar una clase del horario. Va dentro de una celda apretada, así
   que aparece al pasar el mouse por encima y no compite con el contenido. En
   una pantalla táctil no hay hover: ahí queda siempre visible. */
.grilla-clase { position: relative; }
.btn-editar-clase {
  position: absolute; top: 2px; right: 2px;
  border: 0; background: transparent; color: var(--sta-gris);
  font-size: .72rem; line-height: 1; padding: .15rem .25rem; border-radius: 4px;
  opacity: 0; transition: opacity var(--transicion), background var(--transicion);
}
.grilla-clase:hover .btn-editar-clase, .btn-editar-clase:focus-visible { opacity: 1; }
.btn-editar-clase:hover { background: var(--sta-arena); color: var(--sta-azul); }
@media (hover: none) { .btn-editar-clase { opacity: .55; } }

.badge-carga-semanal {
  display: inline-flex; align-items: center; font-size: .78rem; font-weight: 700;
  background: var(--sta-arena); border: 1px solid var(--sta-borde); border-radius: 999px; padding: .2rem .6rem;
}

.btn-link-sta {
  background: none; border: none; padding: 0; color: var(--sta-azul); font-size: .78rem; font-weight: 600;
  text-decoration: underline; cursor: pointer;
}
.btn-link-sta:hover { color: var(--sta-azul-claro); }

/* Botones "toggle" (por curso / por docente) — mismo lenguaje visual que
   btn-sta-fantasma, pero con un estado activo claro sin depender solo del
   color (queda además con fondo sólido, no solo un borde más oscuro). */
.btn-toggle-sta.activo { background: var(--sta-azul); color: #fff; border-color: var(--sta-azul); }

/* -------------------------------------------------------------------------
   Grilla horaria — la tabla que comparten horario.js (por curso / por
   docente) y el modal de "carga semanal" de docentes.js. Scroll horizontal
   propio en celular en vez de convertirse en tarjetas: es un calendario,
   no un listado, y perder la cuadrícula le quitaría el sentido.
   ------------------------------------------------------------------------- */
.tabla-horario { width: 100%; border-collapse: collapse; font-size: .84rem; }
.tabla-horario th, .tabla-horario td { border: 1px solid var(--sta-borde); padding: .45rem .5rem; vertical-align: top; }
.tabla-horario thead th {
  background: var(--sta-azul); color: #fff; font-size: .72rem; text-transform: uppercase; letter-spacing: .04em;
  text-align: center; position: sticky; top: 0; z-index: 2;
}
.tabla-horario .col-periodo {
  background: var(--sta-arena); white-space: nowrap; font-weight: 700; font-size: .78rem;
  position: sticky; left: 0; z-index: 1;
}
.tabla-horario thead .col-periodo { z-index: 3; }
.tabla-horario .col-dia--hoy { background: #123549; }
.grilla-periodo-num { display: block; }
.grilla-periodo-hora { display: block; font-weight: 400; color: var(--sta-gris); font-size: .68rem; }

.tabla-horario .fila-pausa td {
  background: repeating-linear-gradient(45deg, #f3f1ec, #f3f1ec 6px, #ece8e0 6px, #ece8e0 12px);
  color: var(--sta-gris); font-size: .72rem; font-weight: 700; text-align: center; letter-spacing: .03em;
  padding: .3rem .5rem;
}

.celda-horario { min-width: 130px; }
.celda-horario--vacia { color: var(--sta-borde); text-align: center; }
.celda-horario--nodia {
  background: repeating-linear-gradient(135deg, #fafaf8, #fafaf8 6px, #f0efe9 6px, #f0efe9 12px);
  text-align: center;
}
.grilla-clase { display: flex; flex-direction: column; gap: .1rem; margin-bottom: .35rem; }
.grilla-clase:last-child { margin-bottom: 0; }
.grilla-asignatura { font-weight: 700; color: var(--sta-tinta); }
.grilla-detalle { color: var(--sta-gris); font-size: .78rem; }
.grilla-sala { font-size: .76rem; color: var(--sta-gris); }
.grilla-sala--pendiente { color: var(--estado-asignado); font-style: italic; }
.grilla-anomalia { font-size: .68rem; color: var(--estado-asignado); }

.tabla-horario--compacta { font-size: .78rem; }
.tabla-horario--compacta .celda-horario { min-width: 100px; }

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

/* -------------------------------------------------------------------------
   Importación en dos pasos
   ------------------------------------------------------------------------- */
.resumen-importacion {
  padding: .9rem 1rem; display: flex; flex-direction: column; gap: .15rem;
}
.resumen-importacion .etiqueta { font-size: .72rem; text-transform: uppercase; letter-spacing: .05em; font-weight: 700; color: var(--sta-gris); }
.resumen-importacion .valor { font-size: 1.9rem; font-weight: 800; line-height: 1; }
.resumen-importacion.resumen-ok .valor { color: var(--estado-realizado); }
.resumen-importacion.resumen-neutro .valor { color: var(--estado-confirmado); }
.resumen-importacion.resumen-problema .valor { color: var(--estado-asignado); }

.badge-motivo-problema {
  display: inline-block; background: var(--estado-sin-cubrir-fondo); color: var(--estado-sin-cubrir);
  border: 1px solid var(--estado-sin-cubrir); border-radius: 999px; padding: .15rem .55rem; font-size: .74rem; font-weight: 700;
}

/* -------------------------------------------------------------------------
   Bandeja de datos pendientes — mismo componente que el mockup ya
   aprobado (mockups/tablero.html).
   ------------------------------------------------------------------------- */
.panel-pendientes { border-top: 4px solid var(--estado-asignado); }
.fila-pendiente {
  display: flex; align-items: center; gap: .75rem; padding: .65rem .2rem; border-bottom: 1px solid var(--sta-borde); flex-wrap: wrap;
}
.fila-pendiente:last-child { border-bottom: none; }
.fila-pendiente .icono-pend {
  width: 34px; height: 34px; border-radius: 8px; background: var(--estado-asignado-fondo); color: var(--estado-asignado);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.fila-pendiente .texto { flex: 1; font-size: .87rem; min-width: 160px; }
.fila-pendiente .conteo {
  font-weight: 800; background: var(--sta-arena); border: 1px solid var(--sta-borde); border-radius: 999px;
  padding: .1rem .6rem; font-size: .8rem; color: var(--sta-tinta);
}
.btn-icono-sta--chico { width: 28px; height: 28px; font-size: .78rem; }

/* -------------------------------------------------------------------------
   Impresión: la grilla horaria y los paneles de esta fase tampoco arrastran
   fondos oscuros ni controles al imprimir.
   ------------------------------------------------------------------------- */
@media print {
  .tabla-horario thead th, .tabla-horario .col-periodo { background: #fff !important; color: #000 !important; }
  .btn-toggle-sta, #horario-fecha, .celda-acciones, .btn-icono-sta { display: none !important; }
}

/* =========================================================================
   FASE 3 — Motor de reemplazos
   Las clases de esta sección nacen de los dos mockups ya aprobados
   (mockups/registro-ausencia.html y mockups/asignar-reemplazante.html):
   se portan tal cual, sin reinterpretarlas. Se ajustan solo los tamaños de
   marco porque acá viven dentro de <main id="contenido"> (con menú y
   encabezado arriba), no en una pantalla propia como en el mockup.
   ========================================================================= */

/* Contenedor angosto reusado por Registrar ausencia y Asignar reemplazante:
   mismo criterio que .tarjeta-login (mx-auto): en celular ocupa todo el
   ancho, en escritorio se ve como un panel centrado, no un formulario
   estirado de punta a punta. */
.contenedor-angosto { max-width: 560px; margin: 0 auto; }
.contenedor-angosto--ancho { max-width: 720px; margin: 0 auto; }

/* -------------------------------------------------------------------------
   Registrar ausencia — mockups/registro-ausencia.html
   ------------------------------------------------------------------------- */
.paso { padding: 1rem 0 .3rem; }
.paso h2 {
  font-size: .78rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--sta-gris); display: flex; align-items: center; gap: .4rem; margin-bottom: .6rem;
}
.paso h2 .num {
  width: 20px; height: 20px; border-radius: 50%; background: var(--sta-azul); color: #fff;
  font-size: .7rem; display: inline-flex; align-items: center; justify-content: center; font-weight: 800; flex-shrink: 0;
}

.buscador-docente { position: relative; }
.buscador-docente input {
  width: 100%; font-size: 1.05rem; padding: .8rem 1rem .8rem 2.6rem;
  border: 1.5px solid var(--sta-borde); border-radius: 12px; background: var(--sta-arena);
}
.buscador-docente input:focus { outline: none; border-color: var(--sta-azul-claro); background: #fff; box-shadow: 0 0 0 3px rgba(95,168,211,.25); }
.buscador-docente i.fa-magnifying-glass { position: absolute; left: 1rem; top: 50%; transform: translateY(-50%); color: var(--sta-gris); }

.resultado-docente {
  display: flex; align-items: center; gap: .7rem; width: 100%;
  padding: .65rem .5rem; border: none; background: none; text-align: left;
  border-radius: 10px; transition: background var(--transicion);
}
.resultado-docente:hover, .resultado-docente:focus-visible { background: var(--sta-arena); }
.resultado-docente .avatar {
  width: 38px; height: 38px; border-radius: 50%; background: var(--sta-azul-claro); color: #08202f;
  display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: .82rem; flex-shrink: 0;
}
.resultado-docente .nombre { font-weight: 600; font-size: .95rem; }
.resultado-docente .dicta { color: var(--sta-gris); font-size: .78rem; }

.docente-elegido {
  display: flex; align-items: center; gap: .7rem; background: var(--estado-confirmado-fondo);
  border: 1.5px solid var(--estado-confirmado); border-radius: 12px; padding: .7rem .9rem;
}
.docente-elegido .avatar {
  width: 40px; height: 40px; border-radius: 50%; background: var(--estado-confirmado); color: #fff;
  display: flex; align-items: center; justify-content: center; font-weight: 800; flex-shrink: 0;
}
.docente-elegido button { margin-left: auto; background: none; border: none; color: var(--sta-gris); font-size: 1rem; }

.grid-motivos { display: grid; grid-template-columns: 1fr 1fr; gap: .6rem; }
@media (min-width: 480px) { .grid-motivos { grid-template-columns: 1fr 1fr 1fr; } }
.btn-motivo {
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: .35rem;
  border: 1.5px solid var(--sta-borde); border-radius: 12px; background: #fff;
  padding: .8rem .5rem; font-size: .82rem; font-weight: 600; color: var(--sta-tinta);
  transition: border-color var(--transicion), background var(--transicion), transform var(--transicion);
}
.btn-motivo i { font-size: 1.25rem; color: var(--sta-azul); }
.btn-motivo:active { transform: scale(.97); }
.btn-motivo.activo { border-color: var(--sta-azul); background: #eef4f8; }
.btn-motivo.activo i { color: var(--sta-azul); }
.btn-motivo.activo::after { content: '\2713'; position: absolute; top: .3rem; right: .4rem; font-weight: 800; color: var(--sta-azul); font-size: .8rem; }

.grid-rango { display: flex; flex-wrap: wrap; gap: .5rem; }
.pill-rango {
  border: 1.5px solid var(--sta-borde); border-radius: 999px; background: #fff;
  padding: .5rem 1rem; font-weight: 600; font-size: .85rem; color: var(--sta-tinta);
  transition: all var(--transicion);
}
.pill-rango.activo { background: var(--sta-azul); border-color: var(--sta-azul); color: #fff; }
.rango-personalizado { display: none; gap: .5rem; margin-top: .6rem; flex-wrap: wrap; }
.rango-personalizado.mostrar { display: flex; }
.rango-personalizado input { border: 1.5px solid var(--sta-borde); border-radius: 8px; padding: .45rem .6rem; flex: 1; min-width: 140px; font-size: .85rem; }

.aviso-hora { display: flex; align-items: center; gap: .5rem; background: var(--sta-arena); border-radius: 10px; padding: .55rem .8rem; font-size: .8rem; color: var(--sta-gris); flex-wrap: wrap; }
.aviso-hora strong { color: var(--sta-tinta); }
.aviso-hora input[type=datetime-local] { border: 1.5px solid var(--sta-borde); border-radius: 8px; padding: .3rem .5rem; font-size: .8rem; }

.resumen-preview { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: .5rem; gap: .5rem; flex-wrap: wrap; }
.resumen-preview .cuenta { font-weight: 800; color: var(--sta-azul); white-space: nowrap; }
.fila-clase {
  display: flex; align-items: center; gap: .7rem; padding: .6rem .3rem;
  border-bottom: 1px solid var(--sta-borde);
}
.fila-clase:last-child { border-bottom: none; }
.fila-clase input[type=checkbox] { width: 20px; height: 20px; flex-shrink: 0; accent-color: var(--sta-azul); }
.fila-clase .datos { flex: 1; font-size: .85rem; }
.fila-clase .datos b { font-size: .88rem; }
.fila-clase .datos .sub { color: var(--sta-gris); font-size: .78rem; }
.fila-clase.desmarcada { opacity: .45; }
.fila-clase.desmarcada .datos { text-decoration: line-through; }
.fila-clase .alerta-sala { color: var(--estado-asignado); font-size: .74rem; font-style: italic; text-decoration: none !important; display: inline-flex; align-items: center; gap: .25rem; }
.fila-clase .nota-electivo { color: var(--sta-gris); font-size: .74rem; font-style: italic; display: block; }
.bloque-chip {
  background: var(--sta-tinta); color: #fff; font-size: .7rem; font-weight: 700;
  border-radius: 6px; padding: .15rem .4rem; flex-shrink: 0; min-width: 30px; text-align: center;
}

/* Barra inferior fija dentro del panel (no de toda la pantalla): pegada al
   fondo del contenedor angosto, visible sin perder el contexto del resto
   del formulario mientras se hace scroll. */
.barra-confirmar {
  position: sticky; bottom: 0; background: #fff; border-top: 1px solid var(--sta-borde);
  padding: .8rem 0 calc(.8rem + env(safe-area-inset-bottom));
  display: flex; flex-direction: column; gap: .4rem; margin-top: .5rem;
}
.barra-confirmar .btn-confirmar { width: 100%; padding: .9rem; font-size: 1rem; border-radius: 12px; }
.barra-confirmar .btn-confirmar:disabled { background: var(--sta-borde); color: var(--sta-gris); }
.contador-toques { text-align: center; font-size: .72rem; color: var(--sta-gris); }

/* -------------------------------------------------------------------------
   Asignar reemplazante — mockups/asignar-reemplazante.html
   ------------------------------------------------------------------------- */
.ficha-bloque {
  background: var(--sta-arena);
  border: 1px solid var(--sta-borde);
  border-radius: var(--radio);
  padding: .9rem 1.1rem;
  margin-bottom: 1rem;
}
.ficha-bloque .curso { font-size: 1.05rem; font-weight: 800; }
.ficha-bloque .meta { font-size: .82rem; color: var(--sta-gris); }
.ficha-bloque .meta .sep { margin: 0 .3rem; opacity: .5; }

h2.titulo-seccion {
  font-size: .8rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--sta-gris); margin-bottom: .7rem; display: flex; align-items: center; gap: .4rem;
}

.candidato {
  border: 1.5px solid var(--sta-borde);
  border-radius: 12px;
  padding: .85rem .95rem;
  margin-bottom: .65rem;
  transition: border-color var(--transicion), box-shadow var(--transicion);
}
.candidato.sugerido {
  border-color: var(--estado-realizado);
  background: var(--estado-realizado-fondo);
  box-shadow: 0 2px 10px rgba(46,125,50,.12);
}
.candidato .cabecera { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.candidato .avatar {
  width: 40px; height: 40px; border-radius: 50%; background: var(--sta-azul-claro); color: #08202f;
  display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: .85rem; flex-shrink: 0;
}
.candidato.sugerido .avatar { background: var(--estado-realizado); color: #fff; }
.candidato .nombre { font-weight: 700; font-size: .98rem; }
.candidato .etiqueta-sugerido {
  display: inline-flex; align-items: center; gap: .25rem; background: var(--estado-realizado);
  color: #fff; font-size: .65rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase;
  border-radius: 999px; padding: .12rem .5rem; margin-left: .4rem;
}
.candidato .puntaje {
  margin-left: auto; font-weight: 800; font-size: 1.05rem; color: var(--sta-tinta); white-space: nowrap;
}
.candidato.sugerido .puntaje { color: var(--estado-realizado); }
.candidato .puntaje small { font-weight: 600; font-size: .68rem; color: var(--sta-gris); display: block; text-align: right; }

.razones { list-style: none; margin: .6rem 0 0; padding: 0; font-size: .83rem; }
.razones li { display: flex; gap: .45rem; padding: .18rem 0; align-items: baseline; }
.razones li .signo { width: 26px; flex-shrink: 0; font-weight: 800; text-align: right; font-variant-numeric: tabular-nums; }
.razones li.positiva .signo { color: var(--estado-realizado); }
.razones li.negativa .signo { color: var(--estado-sin-cubrir); }
.razones li .texto { color: var(--sta-tinta); }

.candidato .acciones { display: flex; gap: .5rem; margin-top: .75rem; flex-wrap: wrap; }
.candidato .acciones .btn { flex: 1; font-size: .85rem; min-width: 160px; }

.separador-otros {
  display: flex; align-items: center; gap: .6rem; margin: 1rem 0 .5rem; color: var(--sta-gris); font-size: .78rem;
}
.separador-otros::before, .separador-otros::after { content: ''; flex: 1; border-top: 1px dashed var(--sta-borde); }

.buscar-otro { border: 1.5px dashed var(--sta-borde); border-radius: 12px; padding: .8rem .9rem; text-align: center; }
.buscar-otro input {
  width: 100%; margin-top: .5rem; border: 1.5px solid var(--sta-borde); border-radius: 8px;
  padding: .5rem .7rem; font-size: .85rem;
}

.tarjeta-choque {
  background: var(--estado-sin-cubrir-fondo);
  border: 1.5px solid var(--estado-sin-cubrir);
  border-radius: 12px;
  padding: .95rem 1rem;
  display: flex;
  gap: .7rem;
  margin-bottom: 1rem;
}
.tarjeta-choque .icono { font-size: 1.4rem; color: var(--estado-sin-cubrir); flex-shrink: 0; margin-top: .1rem; }
.tarjeta-choque .titulo { font-weight: 800; color: var(--estado-sin-cubrir); font-size: .95rem; margin-bottom: .2rem; }
.tarjeta-choque .detalle { font-size: .86rem; color: var(--sta-tinta); }
.tarjeta-choque .detalle b { font-weight: 700; }

.btn-volver-elegir {
  display: inline-flex; align-items: center; gap: .35rem; font-size: .8rem; font-weight: 600;
  color: var(--sta-azul); margin-top: .6rem; background: none; border: none; padding: 0;
}

.bloque-libre-alt {
  display: flex; align-items: center; justify-content: space-between; gap: .6rem;
  border: 1.5px solid var(--sta-borde); border-radius: 10px; padding: .55rem .8rem; margin-bottom: .5rem;
  font-size: .85rem; flex-wrap: wrap;
}
.bloque-libre-alt .info b { display: block; }
.bloque-libre-alt .info .gris { color: var(--sta-gris); font-size: .78rem; }

.grid-no-persona { display: grid; grid-template-columns: 1fr 1fr; gap: .6rem; }
.opcion-no-persona {
  border: 1.5px solid var(--sta-borde); border-radius: 12px; padding: .8rem .7rem; text-align: left;
  background: #fff; transition: all var(--transicion);
}
.opcion-no-persona:hover { border-color: var(--sta-azul-claro); background: #f7fbfd; }
.opcion-no-persona i { font-size: 1.15rem; color: var(--sta-azul); margin-bottom: .35rem; display: block; }
.opcion-no-persona .nombre { font-weight: 700; font-size: .85rem; display: block; }
.opcion-no-persona .desc { font-size: .74rem; color: var(--sta-gris); display: block; margin-top: .15rem; }
.opcion-no-persona.peligro { border-color: var(--estado-sin-cubrir); }
.opcion-no-persona.peligro i { color: var(--estado-sin-cubrir); }
.opcion-no-persona.peligro:hover { background: var(--estado-sin-cubrir-fondo); }

/* -------------------------------------------------------------------------
   Tarjeta "urgente" — de mockups/tablero.html. La reutilizan el selector
   de bloque de Asignar reemplazante (cuando se entra sin id) y el listado
   de Reemplazos como variante compacta de fila sin cubrir.
   ------------------------------------------------------------------------- */
.tarjeta-urgente {
  background: #fff;
  border: 1.5px solid var(--estado-sin-cubrir);
  border-left: 6px solid var(--estado-sin-cubrir);
  border-radius: var(--radio);
  padding: .9rem 1.1rem;
  display: flex;
  flex-wrap: wrap;
  gap: .6rem 1.2rem;
  align-items: center;
  justify-content: space-between;
  margin-bottom: .6rem;
  transition: transform var(--transicion), box-shadow var(--transicion);
}
button.tarjeta-urgente { width: 100%; text-align: left; cursor: pointer; }
button.tarjeta-urgente:hover { box-shadow: var(--sombra-tarjeta); transform: translateY(-1px); }
.tarjeta-urgente .info b { display: block; font-size: 1rem; }
.tarjeta-urgente .info .meta { color: var(--sta-gris); font-size: .84rem; }
.tarjeta-urgente .info .meta .sep { margin: 0 .3rem; opacity: .5; }

/* -------------------------------------------------------------------------
   Reemplazos — listado con filtros y ficha lateral (offcanvas de
   Bootstrap: ya viene con el comportamiento responsive correcto —
   se desliza en celular, panel fijo en escritorio — sin reinventarlo).
   ------------------------------------------------------------------------- */
.btn-solo-sin-cubrir {
  display: inline-flex; align-items: center; gap: .4rem; font-weight: 700; font-size: .85rem;
  border: 1.5px solid var(--estado-sin-cubrir); color: var(--estado-sin-cubrir); background: #fff;
  border-radius: 999px; padding: .5rem 1rem; transition: all var(--transicion); white-space: nowrap;
}
.btn-solo-sin-cubrir:hover { background: var(--estado-sin-cubrir-fondo); }
.btn-solo-sin-cubrir.activo { background: var(--estado-sin-cubrir); color: #fff; }

.fila-reemplazo-clic { cursor: pointer; }
.fila-reemplazo-clic:hover { background: var(--sta-arena) !important; }

#offcanvas-ficha-reemplazo .offcanvas-body { display: flex; flex-direction: column; gap: 1rem; }
.ficha-linea { display: flex; justify-content: space-between; gap: .8rem; font-size: .88rem; padding: .35rem 0; border-bottom: 1px dashed var(--sta-borde); }
.ficha-linea:last-child { border-bottom: none; }
.ficha-linea .etiqueta { color: var(--sta-gris); font-weight: 600; }
.ficha-linea .valor { text-align: right; }

.historial-evento { display: flex; gap: .6rem; padding: .5rem 0; border-bottom: 1px solid var(--sta-borde); font-size: .82rem; }
.historial-evento:last-child { border-bottom: none; }
.historial-evento .icono { color: var(--sta-azul); flex-shrink: 0; margin-top: .15rem; }
.historial-evento .cuando { color: var(--sta-gris); font-size: .74rem; display: block; }

/* -------------------------------------------------------------------------
   Mis reemplazos — vista del docente (solo lo suyo, sin listados generales)
   ------------------------------------------------------------------------- */
.tarjeta-mi-reemplazo { padding: 1rem 1.1rem; margin-bottom: .8rem; }
.tarjeta-mi-reemplazo .cabecera-mr { display: flex; justify-content: space-between; align-items: flex-start; gap: .6rem; flex-wrap: wrap; margin-bottom: .4rem; }
.tarjeta-mi-reemplazo .curso-mr { font-weight: 800; font-size: 1.02rem; }
.tarjeta-mi-reemplazo .meta-mr { color: var(--sta-gris); font-size: .85rem; }
.tarjeta-mi-reemplazo .meta-mr .sep { margin: 0 .3rem; opacity: .5; }
.tarjeta-mi-reemplazo .actividad-mr {
  background: var(--sta-arena); border-radius: var(--radio-chico); padding: .6rem .8rem; font-size: .85rem; margin-top: .5rem;
}
.tarjeta-mi-reemplazo .actividad-mr .etiqueta { display: block; font-size: .68rem; text-transform: uppercase; letter-spacing: .05em; color: var(--sta-gris); font-weight: 700; margin-bottom: .2rem; }
.tarjeta-mi-reemplazo .acciones-mr { display: flex; gap: .5rem; margin-top: .7rem; flex-wrap: wrap; }
.tarjeta-mi-reemplazo textarea { width: 100%; border: 1.5px solid var(--sta-borde); border-radius: 8px; padding: .5rem .6rem; font-size: .85rem; margin-top: .5rem; }

/* -------------------------------------------------------------------------
   Ausencias
   ------------------------------------------------------------------------- */
.badge-ausencia-vigencia { font-size: .78rem; color: var(--sta-tinta); }
.badge-ausencia-vigencia .sep { margin: 0 .3rem; color: var(--sta-gris); }

/* Impresión: ninguna de las pantallas interactivas de esta fase se
   imprime tal cual (eso lo resuelve la Fase 5 con plantillas propias en
   public/impresion/); de cortesía se ocultan los controles que no
   tendrían sentido en papel si alguien igual presiona Ctrl+P. */
@media print {
  .barra-confirmar, .btn-solo-sin-cubrir, .candidato .acciones, .tarjeta-mi-reemplazo .acciones-mr,
  .paginacion-sta, .barra-filtros { display: none !important; }
}

/* =========================================================================
   FASE 4 — Calendario (mes/semana/día con FullCalendar 6 + grilla del día
   hecha a mano). Mismo semáforo, misma regla: el color nunca va solo.
   ========================================================================= */

/* FullCalendar 6 se pinta con sus propias variables CSS: se adopta acá la
   paleta institucional en vez de dejar el azul/gris por defecto de la
   librería (skill sta-stack §7: "un solo lugar que tocar"). */
#cal-fullcalendar {
  --fc-border-color: var(--sta-borde);
  --fc-button-bg-color: #fff;
  --fc-button-border-color: var(--sta-azul);
  --fc-button-text-color: var(--sta-azul);
  --fc-button-hover-bg-color: #eef4f8;
  --fc-button-hover-border-color: var(--sta-azul);
  --fc-button-active-bg-color: var(--sta-azul);
  --fc-button-active-border-color: var(--sta-azul);
  --fc-today-bg-color: #eef4f8;
  --fc-neutral-bg-color: var(--sta-arena);
  --fc-page-bg-color: #fff;
  font-size: .85rem;
}
#cal-fullcalendar .fc-toolbar-title { font-size: 1.05rem; color: var(--sta-tinta); font-weight: 800; }
#cal-fullcalendar .fc-button { font-weight: 600; text-transform: none; box-shadow: none !important; }
#cal-fullcalendar .fc-daygrid-day.fc-day-today, #cal-fullcalendar .fc-timegrid-col.fc-day-today { background: var(--fc-today-bg-color); }

/* La tarjeta de cada reemplazo dentro del calendario: sin relleno sólido
   (mes tiene poco espacio), con un borde de color a la izquierda + ícono +
   texto — nunca solo el color, porque esto también se imprime en B/N. */
.fc-evt-sta {
  border-left: 4px solid var(--sta-borde);
  border-radius: 4px;
  padding: .15rem .4rem;
  font-size: .74rem;
  line-height: 1.25;
  overflow: hidden;
  cursor: pointer;
}
.fc-evt-cabecera { font-weight: 700; color: var(--sta-tinta); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fc-evt-linea { color: var(--sta-gris); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fc-evt-estado { font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fc-evt-anulado .fc-evt-cabecera, .fc-evt-anulado .fc-evt-estado { text-decoration: line-through; }
.fc-timegrid-event .fc-evt-sta { height: 100%; }

/* Botones Mes/Semana/Día/Grilla del día — mismo lenguaje que el toggle
   "por curso/por docente" de Horario (btn-toggle-sta ya existe). */
#cal-selector-vista .btn-toggle-sta { font-size: .85rem; }

/* -------------------------------------------------------------------------
   Grilla del día — filas = bloques, columnas = grupos (docs/API.md §9,
   `calendario.dia`). Reutiliza la tabla-horario ya aprobada (scroll
   horizontal propio + columna de bloque fija) en vez de reinventar el
   patrón responsive.
   ------------------------------------------------------------------------- */
.tabla-grilla-dia .celda-grilla-dia { min-width: 150px; vertical-align: top; padding: .35rem; transition: background var(--transicion); }
.tabla-grilla-dia .celda-grilla-dia--sobre { background: #eef4f8; }
.tabla-grilla-dia .celda-grilla-dia--fuera { opacity: .3; }

.chip-grilla-dia {
  border-left: 4px solid var(--sta-borde);
  border-radius: 6px;
  padding: .4rem .5rem;
  font-size: .78rem;
  cursor: grab;
  position: relative;
  transition: box-shadow var(--transicion), opacity var(--transicion);
}
.chip-grilla-dia:active { cursor: grabbing; }
.chip-grilla-dia.arrastrando { opacity: .35; }
.chip-grilla-dia .linea1 { font-weight: 700; padding-right: 1.4rem; }
.chip-grilla-dia .linea1 .icono-texto { display: inline-block; width: 1em; text-align: center; }
.chip-grilla-dia .linea2 { color: var(--sta-gris); font-size: .72rem; margin-top: .1rem; }
.chip-grilla-dia-mover {
  position: absolute; top: .3rem; right: .3rem; background: none; border: none;
  color: var(--sta-gris); padding: .1rem .3rem; line-height: 1; border-radius: 4px;
}
.chip-grilla-dia-mover:hover { background: rgba(0,0,0,.06); color: var(--sta-tinta); }

/* -------------------------------------------------------------------------
   Modal "Mover a…" (vistas/calendario.js) — reutiliza .ficha-bloque,
   .titulo-seccion y .resultado-docente ya definidos para Asignar
   reemplazante, así el vocabulario visual es el mismo en toda la app.
   ------------------------------------------------------------------------- */
#modal-mover-reemplazo .titulo-seccion { margin-top: 0; }

@media print {
  #cal-fullcalendar .fc-toolbar, #cal-selector-vista, .chip-grilla-dia-mover,
  #cal-btn-deshacer, #cal-btn-solo-sin-cubrir { display: none !important; }
  .tabla-grilla-dia thead th { background: #fff !important; color: #000 !important; }
}

/* =========================================================================
   FASE 7 — Ficha del curso + Postulaciones
   ========================================================================= */

/* -------------------------------------------------------------------------
   Ficha del curso (vistas/cursos.js, '#/cursos?id='): tarjetas de dato
   (sala / profesor jefe / matrícula) en fila, que se apilan en celular
   como el resto de la app (skill sta-stack §6).
   ------------------------------------------------------------------------- */
.grid-ficha-curso { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: .8rem; }
.tarjeta-dato { padding: .9rem 1.1rem; display: flex; flex-direction: column; gap: .35rem; }
.tarjeta-dato-etiqueta { font-size: .72rem; text-transform: uppercase; letter-spacing: .05em; font-weight: 700; color: var(--sta-gris); }
.tarjeta-dato-valor { font-size: 1rem; font-weight: 600; color: var(--sta-tinta); display: flex; align-items: center; flex-wrap: wrap; gap: .2rem; }

.badge-electivo {
  display: inline-flex; align-items: center; gap: .3rem; font-size: .74rem; font-weight: 700;
  color: #5E35B1; background: #f3eefc; border: 1px solid #c9b7ee; border-radius: 999px; padding: .15rem .55rem;
}

/* -------------------------------------------------------------------------
   Postulaciones — vista del docente (docs/API.md §11)
   ------------------------------------------------------------------------- */
.tarjeta-postulable .puntaje-postulable {
  font-weight: 800; font-size: 1.3rem; color: var(--sta-azul); text-align: right; white-space: nowrap; flex-shrink: 0;
}
.tarjeta-postulable .puntaje-postulable small { display: block; font-weight: 600; font-size: .66rem; color: var(--sta-gris); text-transform: uppercase; letter-spacing: .04em; }
.tarjeta-postulable .ficha-bloque { flex: 1; min-width: 220px; margin-bottom: 0; }
.pie-postulable {
  display: flex; align-items: center; justify-content: space-between; gap: .8rem; flex-wrap: wrap;
  margin-top: .9rem; padding-top: .8rem; border-top: 1px dashed var(--sta-borde);
}
.acciones-postulable { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }

/* Pill de estado de la POSTULACIÓN — deliberadamente distinta del semáforo
   de --estado-* de los reemplazos (docs/API.md §11: "este no tiene color
   ni ícono propios en la paleta institucional"), para que nadie confunda
   "tu postulación fue aprobada" con el semáforo de cobertura del bloque. */
.pill-postulacion {
  display: inline-flex; align-items: center; gap: .35rem; font-weight: 700; font-size: .78rem;
  padding: .28rem .6rem; border-radius: 999px; border: 1.5px solid var(--sta-borde); background: var(--sta-arena); color: var(--sta-tinta);
  white-space: nowrap;
}
.pill-postulacion--pendiente { color: var(--sta-azul); border-color: var(--sta-azul-claro); background: #eef4f8; }
.pill-postulacion--aprobada  { color: var(--estado-realizado); border-color: var(--estado-realizado); background: var(--estado-realizado-fondo); }
.pill-postulacion--rechazada { color: var(--sta-gris); border-color: var(--sta-borde); background: var(--sta-arena); text-decoration: line-through; }
.pill-postulacion--retirada  { color: var(--sta-gris); border-color: var(--sta-borde); background: var(--sta-arena); }

/* Pestañas "Disponibles" / "Mis postulaciones" con el lenguaje institucional
   en vez del azul por defecto de Bootstrap. */
#post-doc-tabs .nav-link { color: var(--sta-gris); font-weight: 600; border: none; border-bottom: 2.5px solid transparent; }
#post-doc-tabs .nav-link.active { color: var(--sta-azul); background: none; border-bottom-color: var(--sta-azul); }

@media print {
  .tarjeta-postulable .acciones-postulable, .candidato .acciones,
  #post-doc-tabs, #post-doc-form-rango, #post-bandeja-btn-actualizar { display: none !important; }
}

/* =========================================================================
   FASE 6 — Tablero, estadísticas y pantalla de sala de profesores
   (skill fase-6-panel-visual). El semáforo sigue viviendo en las variables
   --estado-* de arriba: nada acá define un color de estado nuevo.
   ========================================================================= */

/* -------------------------------------------------------------------------
   Indicadores grandes del tablero — "del tamaño de un pulgar en el celular"
   (skill §1). El crítico (sin cubrir > 0) se distingue con borde e ícono,
   nunca solo con el color.
   ------------------------------------------------------------------------- */
.indicador--critico { background: var(--estado-sin-cubrir-fondo); border: 2px solid var(--estado-sin-cubrir); }
.indicador--critico .etiqueta { color: var(--estado-sin-cubrir); }
.indicador--critico .valor { color: var(--estado-sin-cubrir); font-size: 2.9rem; }

.muestra-color { width: 12px; height: 12px; border-radius: 3px; display: inline-block; flex-shrink: 0; }

/* -------------------------------------------------------------------------
   Línea de tiempo del día — igual lenguaje visual que el mockup aprobado
   (mockups/tablero.html). Solo dos estados agregados por bloque, porque
   `informes.tablero` no entrega el desglose por reemplazo (docs/API.md
   §14): "todo cubierto" (verde) o "algo sin cubrir" (rojo), nunca un color
   inventado para un estado que la API no mandó.
   ------------------------------------------------------------------------- */
/* Rejilla, no fila con scroll.
 *
 * Antes era `display:flex` + `overflow-x:auto`, y los chips llevaban
 * `flex: 1 0 58px` — ese 0 es flex-shrink: nunca se achicaban. Los 12 bloques
 * miden 751px fijos, así que en cualquier ventana más angosta que eso los
 * últimos se iban fuera del borde. Con el navegador a media pantalla (683px)
 * desaparecían B10, B11 y B12: toda la tarde, de 13:40 a 15:55. Y no se veía
 * que faltaran — la barra de scroll horizontal es casi invisible en Windows,
 * así que el Tablero se veía completo mostrando dos tercios del día. Un curso
 * sin cubrir a las 14:25 no aparecía por ninguna parte.
 *
 * `auto-fit` + `minmax` acomoda las columnas que quepan y baja el resto a una
 * segunda fila, alineadas con las de arriba. Nada queda escondido y no hay
 * nada que desplazar — que es la condición para que sirva también proyectado
 * en una pantalla sin mouse. */
.linea-tiempo {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(58px, 1fr));
  gap: 5px;
  align-items: stretch;
  padding-bottom: .3rem;
}
.bloque-tiempo {
  flex: 1 0 58px; position: relative; border-radius: 8px; padding: .55rem .3rem .4rem; text-align: center;
  color: #fff; font-weight: 700; font-size: .78rem; min-height: 62px;
  display: flex; flex-direction: column; justify-content: center; transition: transform var(--transicion);
}
.bloque-tiempo:hover { transform: translateY(-2px); }
.bloque-tiempo .num { font-size: .92rem; }
.bloque-tiempo .hora { font-size: .62rem; font-weight: 500; opacity: .92; display: block; }
.bloque-tiempo.st-sin-cubrir { background: var(--estado-sin-cubrir); }
.bloque-tiempo.st-realizado  { background: var(--estado-realizado); }
.bloque-tiempo.st-neutral    { background: #fff; color: var(--sta-gris); border: 1.5px dashed var(--sta-borde); font-weight: 600; }
.bloque-tiempo.en-curso { outline: 3px solid var(--sta-tinta); outline-offset: 2px; }
.bloque-tiempo.en-curso::after {
  content: 'AHORA'; position: absolute; top: -10px; left: 50%; transform: translateX(-50%);
  background: var(--sta-tinta); color: #fff; font-size: .58rem; padding: 1px 7px; border-radius: 999px; letter-spacing: .04em;
}

/* -------------------------------------------------------------------------
   Tarjetas "sin cubrir" — actúa aquí primero.
   ------------------------------------------------------------------------- */
.tarjeta-urgente {
  background: #fff; border: 1.5px solid var(--estado-sin-cubrir); border-left: 6px solid var(--estado-sin-cubrir);
  border-radius: var(--radio); padding: 1rem 1.1rem; display: flex; flex-wrap: wrap; gap: .6rem 1.2rem;
  align-items: center; justify-content: space-between;
}
.tarjeta-urgente .info b { display: block; font-size: 1rem; }
.tarjeta-urgente .info .meta { color: var(--sta-gris); font-size: .84rem; }
.tarjeta-urgente .info .meta .sep { margin: 0 .3rem; opacity: .5; }

/* -------------------------------------------------------------------------
   Próximas ausencias
   ------------------------------------------------------------------------- */
.fila-proxima { display: flex; align-items: center; gap: .8rem; padding: .6rem .2rem; border-bottom: 1px solid var(--sta-borde); }
.fila-proxima:last-child { border-bottom: none; }
.fecha-chip { background: var(--sta-arena); border: 1px solid var(--sta-borde); border-radius: 8px; text-align: center; width: 52px; flex-shrink: 0; padding: .2rem 0; }
.fecha-chip .dia { font-size: 1.05rem; font-weight: 800; line-height: 1; }
.fecha-chip .mes { font-size: .62rem; text-transform: uppercase; color: var(--sta-gris); }

/* -------------------------------------------------------------------------
   Mapa de calor del mes — cuadrícula de 7 columnas (L a D), scroll dentro
   de su propio contenedor si hace falta: la página nunca hace scroll
   horizontal (skill §7). La intensidad de fondo codifica volumen; el
   ícono ⚠ (no solo un borde de color) marca un día con algo sin cubrir.
   ------------------------------------------------------------------------- */
.mapa-calor-contenedor { overflow-x: auto; }
.mapa-calor-grid { display: grid; grid-template-columns: repeat(7, minmax(38px, 1fr)); gap: 4px; min-width: 280px; }
.mapa-calor-cabecera { margin-bottom: 4px; }
.mapa-calor-col-titulo { text-align: center; font-size: .68rem; font-weight: 800; color: var(--sta-gris); text-transform: uppercase; }
.mapa-calor-celda {
  position: relative; aspect-ratio: 1 / 1; border-radius: 6px; border: 1px solid var(--sta-borde);
  display: flex; flex-direction: column; align-items: center; justify-content: center; font-size: .74rem; font-weight: 700;
  color: var(--sta-tinta);
}
.mapa-calor-celda--vacia { border: none; background: transparent; }
.mapa-calor-celda--no-lectivo { background: repeating-linear-gradient(45deg, #fff, #fff 4px, var(--sta-arena) 4px, var(--sta-arena) 8px); color: var(--sta-borde); }
.mapa-calor-celda--sin-cubrir { border: 2px solid var(--estado-sin-cubrir); }
.mapa-calor-num { font-size: .68rem; opacity: .75; }
.mapa-calor-total { font-size: .84rem; }
.mapa-calor-alerta { position: absolute; top: -6px; right: -6px; color: var(--estado-sin-cubrir); background: #fff; border-radius: 50%; font-size: .7rem; line-height: 1; padding: 2px; }
@media (max-width: 420px) { .mapa-calor-grid { grid-template-columns: repeat(7, minmax(30px, 1fr)); } }

/* -------------------------------------------------------------------------
   Estadísticas (vistas/estadisticas.js) — Chart.js dentro de su propio
   contenedor con scroll vertical si el lienzo es alto; nunca scroll
   horizontal de la página (skill §7).
   ------------------------------------------------------------------------- */
.grafico-sta-lienzo { position: relative; height: 260px; }
.grafico-sta-lienzo--alto { height: 340px; max-height: 46vh; overflow-y: auto; }
.detalle-tabla-grafico { margin-top: .75rem; }
.detalle-tabla-grafico summary { cursor: pointer; color: var(--sta-azul); font-weight: 600; font-size: .84rem; }
.detalle-tabla-grafico[open] summary { margin-bottom: .5rem; }
.th-orden { background: none; border: none; padding: 0; font: inherit; color: inherit; display: inline-flex; align-items: center; gap: .3rem; cursor: pointer; }
.th-orden:hover { color: var(--sta-azul); }

@media print {
  #vista-estadisticas .btn-toggle-sta, #vista-estadisticas #est-form-periodo,
  #vista-estadisticas .btn-link-sta { display: none !important; }
}

/* -------------------------------------------------------------------------
   Pantallas (admin, vistas/pantallas.js) — reutiliza .tabla-sta y los
   modales existentes; sin reglas nuevas de tabla.
   ------------------------------------------------------------------------- */

