/* ============================================================
   S-Community · Sistema de Diseño (bundle drop-in)
   ------------------------------------------------------------
   Identidad visual: lila + turquesa sobre neutros con matiz ciruela.
   Tipografía Poppins (self-hosted, sin requests externos).
   Framework-agnóstico: solo CSS + custom properties.

   Uso: enlaza este archivo y mantén la carpeta assets/ como hermana
   (las @font-face apuntan a assets/fonts/).
     <link rel="stylesheet" href="s-community.css">

   Contenido: @font-face · tokens (:root) · reset/base · componentes
   (botón, campo, alerta, tabla, badge, chip, stat, pastillas,
   skeleton, estado vacío, primitivos de página) · utilidades · motion.
   ============================================================ */

/* ============================================================
   TIPOGRAFÍA — Poppins (self-hosted: .woff2 en assets/fonts/)
   ============================================================ */
@font-face {
  font-family: 'Poppins'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('assets/fonts/pxiEyp8kv8JHgFVrJJnecnFHGPezSQ.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Poppins'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('assets/fonts/pxiEyp8kv8JHgFVrJJfecnFHGPc.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Poppins'; font-style: normal; font-weight: 500; font-display: swap;
  src: url('assets/fonts/pxiByp8kv8JHgFVrLGT9Z1JlFd2JQEl8qw.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Poppins'; font-style: normal; font-weight: 500; font-display: swap;
  src: url('assets/fonts/pxiByp8kv8JHgFVrLGT9Z1xlFd2JQEk.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Poppins'; font-style: normal; font-weight: 600; font-display: swap;
  src: url('assets/fonts/pxiByp8kv8JHgFVrLEj6Z1JlFd2JQEl8qw.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Poppins'; font-style: normal; font-weight: 600; font-display: swap;
  src: url('assets/fonts/pxiByp8kv8JHgFVrLEj6Z1xlFd2JQEk.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Poppins'; font-style: normal; font-weight: 700; font-display: swap;
  src: url('assets/fonts/pxiByp8kv8JHgFVrLCz7Z1JlFd2JQEl8qw.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Poppins'; font-style: normal; font-weight: 700; font-display: swap;
  src: url('assets/fonts/pxiByp8kv8JHgFVrLCz7Z1xlFd2JQEk.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ============================================================
   TOKENS — variables globales de la identidad visual
   ============================================================ */
:root {
  /* Colores de marca */
  --color-primario: #ad89eb;
  --color-primario-oscuro: #8267b0;
  --color-lila: #bda1ef;
  --color-lila-suave: #e6dcf9;
  --color-acento: #48d1d3;

  /* Texto sobre colores de marca claros (accesibilidad: el blanco no pasa WCAG AA) */
  --color-sobre-marca: #241d33;

  /* Superficies y texto — neutros con matiz ciruela, no gris plano */
  --color-fondo: #ffffff;
  --color-superficie: #f7f6fb;
  --color-superficie-2: #f0edf8;   /* theads, zonas de agrupación */
  --color-texto: #241d33;
  --color-texto-suave: #6b657c;
  --color-borde: #e5e1ef;
  --color-borde-suave: #efecf7;    /* separadores de filas */

  /* Estados */
  --color-error: #d64550;
  --color-error-bg: #fdeaec;
  --color-exito: #24824c;
  --color-exito-bg: #e2f4e9;
  --color-aviso: #a26a08;
  --color-aviso-bg: #fdf3da;

  /* Tipografía */
  --fuente-base: 'Poppins', system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --peso-regular: 400;
  --peso-medio: 500;
  --peso-semi: 600;
  --peso-bold: 700;

  --texto-titulo: 1.65rem;
  --texto-grande: 1.2rem;
  --texto-base: 1rem;
  --texto-label: 0.9375rem;
  --texto-pequeno: 0.8125rem;

  /* Radios */
  --radio-input: 10px;
  --radio-boton: 10px;
  --radio-card: 14px;
  --radio-imagen: 12px;

  /* Sombras tintadas con la ciruela del texto */
  --sombra-suave: 0 1px 3px rgba(36, 29, 51, 0.05), 0 1px 2px rgba(36, 29, 51, 0.04);
  --sombra-card: 0 8px 24px rgba(36, 29, 51, 0.09);

  /* Espaciado */
  --esp-xs: 0.5rem;
  --esp-sm: 0.75rem;
  --esp-md: 1rem;
  --esp-lg: 1.5rem;
  --esp-xl: 2.5rem;

  /* ---- Movimiento ----
     REGLA DE USO. La distancia decide la DURACIÓN:
       cambia en el sitio (hover, color, borde)  -> --dur-rapida
       entra o recorre camino (modal, cajón)     -> --dur-media
       responde a lo que el dedo acaba de pulsar -> --dur-instante
       todo lo que SALE                          -> --dur-rapida
     La importancia decide la CURVA:
       estado -> estandar · llega -> entra · se va -> sale · confirma -> firme
     Nada en la ruta crítica pasa de --dur-media: esto lo usa personal
     administrativo muchas horas al día. */
  --dur-instante: 90ms;
  --dur-rapida: 140ms;
  --dur-media: 220ms;
  --curva-estandar: cubic-bezier(0.2, 0, 0.2, 1);
  --curva-entra: cubic-bezier(0, 0, 0.2, 1);
  --curva-sale: cubic-bezier(0.4, 0, 1, 1);
  /* Rebote corto, exclusivo de marcas de confirmación. Uno por pantalla. */
  --curva-firme: cubic-bezier(0.2, 1.35, 0.5, 1);
  --desp-entrada: 8px;
}

/* ============================================================
   RESET & BASE
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html { font-size: 100%; }
body {
  font-family: var(--fuente-base);
  font-size: var(--texto-base);
  font-weight: var(--peso-regular);
  color: var(--color-texto);
  background-color: var(--color-fondo);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img { max-width: 100%; display: block; }
input, button, select, textarea { font-family: inherit; font-size: inherit; color: inherit; }
/* El anillo va en ciruela lila: --color-primario da 2.78:1 sobre blanco y WCAG
   1.4.11 pide 3:1 para un indicador de foco. Con --color-primario-oscuro son
   4.65:1 sin salir de la paleta. El offset lo dibuja fuera de la caja, así que
   sobre un botón lila cae en el fondo de página y también contrasta. */
:focus-visible { outline: 2px solid var(--color-primario-oscuro); outline-offset: 2px; }
a { color: var(--color-primario-oscuro); text-decoration: none; }
a:hover { text-decoration: underline; }
::selection { background: var(--color-lila-suave); color: var(--color-sobre-marca); }

/* Scrollbars finos y tintados */
* { scrollbar-width: thin; scrollbar-color: #cfc6e6 transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-thumb { background: #cfc6e6; border-radius: 999px; border: 3px solid transparent; background-clip: content-box; }
*::-webkit-scrollbar-thumb:hover { background-color: var(--color-lila); }
*::-webkit-scrollbar-track { background: transparent; }

/* ============================================================
   TIPOGRAFÍA — primitivos de página
   ============================================================ */
.contenido__titulo {
  font-size: var(--texto-titulo);
  font-weight: var(--peso-bold);
  letter-spacing: -0.015em;
  line-height: 1.25;
  color: var(--color-texto);
  margin: 0 0 var(--esp-lg);
}
.pagina__cabecera {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--esp-md); flex-wrap: wrap; margin-bottom: var(--esp-lg);
}
.pagina__cabecera .contenido__titulo { margin: 0; }
.pagina__intro { color: var(--color-texto-suave); margin: 0 0 var(--esp-lg); max-width: 65ch; }
.pagina__estado { color: var(--color-texto-suave); font-size: var(--texto-label); padding: var(--esp-md) 0; }
.seccion-titulo { font-size: var(--texto-grande); font-weight: var(--peso-semi); margin: 0 0 var(--esp-md); }
.mono { font-variant-numeric: tabular-nums; letter-spacing: 0.01em; }

/* ============================================================
   BOTÓN
   ============================================================ */
.boton {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.45rem;
  width: 100%; padding: 0.8rem 1.25rem; border: none; border-radius: var(--radio-boton);
  font-size: var(--texto-base); font-weight: var(--peso-semi); cursor: pointer;
  transition: background-color var(--dur-rapida) var(--curva-estandar),
              border-color var(--dur-rapida) var(--curva-estandar),
              box-shadow var(--dur-rapida) var(--curva-estandar),
              filter var(--dur-rapida) var(--curva-estandar),
              transform var(--dur-instante) var(--curva-estandar);
}
.boton:disabled { opacity: 0.6; cursor: not-allowed; }
.boton:active:not(:disabled) { transform: translateY(1px) scale(0.99); }
.boton--primario:hover:not(:disabled),
.boton--acento:hover:not(:disabled),
.boton--peligro:hover:not(:disabled) { box-shadow: 0 4px 12px rgba(20, 20, 40, 0.16); }

.boton--primario { background: var(--color-primario); color: var(--color-sobre-marca); }
.boton--primario:hover:not(:disabled) { background: var(--color-primario-oscuro); }
.boton--acento { background: var(--color-acento); color: var(--color-sobre-marca); width: auto; }
.boton--acento:hover:not(:disabled) { filter: brightness(0.92); }
.boton--secundario { background: var(--color-fondo); color: var(--color-texto); border: 1px solid var(--color-borde); width: auto; }
.boton--secundario:hover:not(:disabled) { background: var(--color-superficie); }
.boton--peligro { background: var(--color-error); color: #ffffff; width: auto; }
.boton--peligro:hover:not(:disabled) { filter: brightness(0.92); }
.boton--chico { width: auto; padding: 0.4rem 0.85rem; font-size: var(--texto-pequeno); }
.boton__icono { width: 15px; height: 15px; flex-shrink: 0; }

/* ============================================================
   CAMPO DE FORMULARIO (label + input + error)
   ============================================================ */
.campo { display: flex; flex-direction: column; gap: var(--esp-xs); margin-bottom: var(--esp-md); }
.campo__label { font-size: var(--texto-label); font-weight: var(--peso-semi); color: var(--color-texto); }
.campo__input, .campo__select {
  width: 100%; padding: 0.75rem 1rem; border: 1px solid var(--color-borde);
  border-radius: var(--radio-input); background: var(--color-fondo);
  transition: border-color var(--dur-rapida) var(--curva-estandar),
              box-shadow var(--dur-rapida) var(--curva-estandar);
}
.campo__input::placeholder { color: var(--color-texto-suave); }
/* Campo deshabilitado DISTINGUIBLE del editable: el reset del kit (color:
   inherit sobre input/select) le gana al gris :disabled del navegador, así
   que sin esta regla un campo muerto parecía vivo — la misma trampa ya
   documentada en .cons-pill:disabled. Cubre los destinos fijos de «Creación
   alumno» y los centros bloqueados de carga masiva y matrícula presencial. */
.campo__input:disabled, .campo__select:disabled {
  background: var(--color-superficie-2); color: var(--color-texto-suave);
  cursor: not-allowed; opacity: 1;
}
/* El borde ES el indicador de foco del campo (la regla anula el outline), así
   que va en ciruela lila por contraste, igual que el anillo global. */
.campo__input:focus, .campo__select:focus {
  border-color: var(--color-primario-oscuro); box-shadow: 0 0 0 3px rgba(173, 137, 235, 0.35); outline: none;
}
.campo--error .campo__input, .campo--error .campo__select { border-color: var(--color-error); }
.campo--error .campo__input:focus { box-shadow: 0 0 0 3px rgba(214, 69, 80, 0.15); }
.campo__error { font-size: var(--texto-pequeno); color: var(--color-error); min-height: 1em; }
.campo__pista { font-size: var(--texto-pequeno); color: var(--color-texto-suave); line-height: 1.35; }
/* Aviso de Bloq Mayús bajo los campos de contraseña (js/caps-aviso.js):
   ámbar, no rojo — no es un error todavía, es un «ojo con lo que tecleas».
   El color NO es --color-aviso: ese par (#a26a08 / #fdf3da) da 4.13:1 y un
   texto de 13px exige 4.5:1 (WCAG AA); este ámbar oscurecido da 5.09:1. */
.campo__mayus {
  font-size: var(--texto-pequeno); color: #8f5d07;
  background: var(--color-aviso-bg); border-radius: var(--radio-input);
  padding: 4px 10px; width: fit-content; line-height: 1.35;
}
/* Vacía (sin aviso que dar) no pinta nada — la región queda en el DOM para
   que aria-live anuncie el texto cuando entre (caps-aviso.js). */
.campo__mayus:empty { padding: 0; background: none; }

/* ============================================================
   ALERTA
   ============================================================ */
.alerta { border-radius: var(--radio-input); padding: 0.75rem 1rem; font-size: var(--texto-label); margin-bottom: var(--esp-md); }
.alerta--error { background: var(--color-error-bg); color: var(--color-error); border: 1px solid rgba(214, 69, 80, 0.3); }
.alerta--aviso { background: var(--color-aviso-bg); color: var(--color-aviso); border: 1px solid rgba(176, 116, 12, 0.3); }
.alerta--exito { background: var(--color-exito-bg); color: var(--color-exito); border: 1px solid rgba(47, 143, 78, 0.3); }
.alerta--enfasis { display: flex; align-items: flex-start; gap: var(--esp-sm); border-left-width: 4px; line-height: 1.4; }
.alerta__icono { font-size: var(--texto-grande); line-height: 1; flex-shrink: 0; }

/* ============================================================
   TABLA
   ============================================================ */
.tabla-wrap { background: var(--color-fondo); border-radius: var(--radio-card); box-shadow: var(--sombra-suave); overflow-x: auto; border: 1px solid var(--color-borde); }
.tabla { width: 100%; border-collapse: collapse; }
.tabla thead { background: var(--color-superficie-2); }
.tabla th {
  text-align: left; padding: 0.75rem 1.1rem; font-size: 0.72rem; font-weight: var(--peso-semi);
  color: var(--color-texto-suave); text-transform: uppercase; letter-spacing: 0.06em;
  border-bottom: 1px solid var(--color-borde);
}
.tabla td { padding: 0.85rem 1.1rem; font-size: var(--texto-label); border-top: 1px solid var(--color-borde-suave); vertical-align: middle; }
.tabla tbody tr:first-child td { border-top: none; }
.tabla tbody tr { transition: background-color var(--dur-rapida) var(--curva-estandar); }
.tabla tbody tr:hover { background: var(--color-superficie); }

/* ============================================================
   BADGES (estado, riesgo, etiquetas)
   ============================================================ */
.badge {
  display: inline-flex; align-items: center; gap: 0.3rem; padding: 0.25rem 0.65rem;
  border-radius: 999px; font-size: var(--texto-pequeno); font-weight: var(--peso-semi); white-space: nowrap;
}
.badge--verde { background: var(--color-exito-bg); color: var(--color-exito); }
.badge--ambar { background: var(--color-aviso-bg); color: var(--color-aviso); }
.badge--rojo { background: var(--color-error-bg); color: var(--color-error); }
.badge--lila { background: var(--color-lila-suave); color: var(--color-primario-oscuro); }
.badge--gris { background: var(--color-superficie); color: var(--color-texto-suave); border: 1px solid var(--color-borde); }
.badge--turquesa { background: rgba(72, 209, 211, 0.18); color: #1c7274; }
/* Resaltado fuerte para "sensible / crítico" (con candado). */
.badge--sensible { background: var(--color-error-bg); color: var(--color-error); border: 1px solid var(--color-error); font-weight: 700; }
.badge--sensible::before { content: "🔒"; font-size: 0.85em; line-height: 1; }

/* ============================================================
   CHIP (uso libre: filtros, etiquetas)
   ============================================================ */
.chip {
  display: inline-flex; align-items: center; gap: 0.3rem; padding: 0.2rem 0.6rem;
  border-radius: 999px; font-size: var(--texto-pequeno); font-weight: var(--peso-medio);
  background: var(--color-lila-suave); color: var(--color-primario-oscuro);
}
.chip--aviso { background: var(--color-aviso-bg); color: var(--color-aviso); }
.chip--sensible { background: var(--color-error-bg); color: var(--color-error); border: 1px solid var(--color-error); font-weight: 700; }
.chip--sensible::before { content: "🔒"; margin-right: 0.15rem; font-size: 0.85em; }

/* ============================================================
   PASTILLAS DE FILTRO (por estado, por categoría…)
   ============================================================ */
.cons-pill {
  display: inline-flex; align-items: center; gap: 0.35rem; padding: 0.35rem 0.8rem;
  border: 1px solid var(--color-borde); border-radius: 999px; background: var(--color-fondo);
  color: var(--color-texto); font-size: var(--texto-label); font-weight: var(--peso-medio);
  cursor: pointer;
  /* color entra en la lista: la variante --activo lo cambia y sin esto saltaba
     mientras el fondo fundía. */
  transition: background-color var(--dur-rapida) var(--curva-estandar),
              border-color var(--dur-rapida) var(--curva-estandar),
              color var(--dur-rapida) var(--curva-estandar);
}
.cons-pill:hover { background: var(--color-superficie); }
.cons-pill__n {
  padding: 0.05rem 0.4rem; border-radius: 999px; background: var(--color-superficie);
  color: var(--color-texto-suave); font-size: var(--texto-pequeno); font-weight: var(--peso-semi);
  transition: background-color var(--dur-rapida) var(--curva-estandar),
              color var(--dur-rapida) var(--curva-estandar);
}
.cons-pill--activo { border-color: var(--color-primario); background: var(--color-lila-suave); color: var(--color-primario-oscuro); }
.cons-pill--activo.cons-pill--ambar { border-color: var(--color-aviso); background: var(--color-aviso-bg); color: var(--color-aviso); }
.cons-pill--activo.cons-pill--verde { border-color: var(--color-exito); background: var(--color-exito-bg); color: var(--color-exito); }
.cons-pill--activo.cons-pill--rojo { border-color: var(--color-error); background: var(--color-error-bg); color: var(--color-error); }
.cons-pill--activo .cons-pill__n { background: rgba(255, 255, 255, 0.6); color: inherit; }

/* ============================================================
   TARJETAS
   ============================================================ */
.tarjeta-stat {
  background: var(--color-fondo); border: 1px solid var(--color-borde); border-radius: var(--radio-card);
  box-shadow: var(--sombra-suave); padding: var(--esp-lg);
  transition: box-shadow var(--dur-rapida) var(--curva-estandar),
              transform var(--dur-rapida) var(--curva-estandar);
}
/* La elevación solo donde hay puntero de verdad: en táctil se quedaba pegada
   tras el toque, porque no hay «salir del elemento». */
@media (hover: hover) {
  .tarjeta-stat:hover { box-shadow: var(--sombra-card); transform: translateY(-2px); }
}
.tarjeta-stat__valor { font-size: var(--texto-titulo); font-weight: var(--peso-bold); color: var(--color-texto); }
.tarjeta-stat__etiqueta { font-size: var(--texto-label); color: var(--color-texto-suave); margin-top: var(--esp-xs); }

.tarjeta-crear {
  background: var(--color-fondo); border: 1px solid var(--color-borde); border-radius: var(--radio-card);
  box-shadow: var(--sombra-suave); padding: var(--esp-lg); margin-bottom: var(--esp-xl);
}
.tarjeta-crear__pie { display: flex; justify-content: flex-end; gap: var(--esp-sm); }

/* Banda de propósito / contexto (título + descripción con acento de marca). */
.proposito {
  display: flex; align-items: center; justify-content: space-between; gap: var(--esp-md); flex-wrap: wrap;
  margin-bottom: var(--esp-lg); padding: var(--esp-md) var(--esp-lg);
  background: var(--color-fondo); border: 1px solid var(--color-borde);
  border-left: 4px solid var(--color-primario); border-radius: var(--radio-card); box-shadow: var(--sombra-suave);
}
.proposito__desc { margin: 0; max-width: 72ch; line-height: 1.5; font-size: var(--texto-label); color: var(--color-texto-suave); }
.proposito__desc strong { color: var(--color-texto); font-weight: var(--peso-semi); }
.proposito__tag { flex-shrink: 0; padding: 0.35rem 0.75rem; border-radius: 999px; background: var(--color-lila-suave); color: var(--color-primario-oscuro); font-size: var(--texto-pequeno); font-weight: var(--peso-semi); white-space: nowrap; }

/* ============================================================
   ESTADO VACÍO
   ============================================================ */
.vacio {
  display: flex; flex-direction: column; align-items: center; gap: var(--esp-xs);
  padding: var(--esp-xl) var(--esp-lg); text-align: center;
  border: 1px dashed var(--color-borde); border-radius: var(--radio-card); background: var(--color-fondo);
}
.vacio__icono { font-size: 2rem; line-height: 1; opacity: 0.85; }
.vacio__titulo { font-weight: var(--peso-semi); color: var(--color-texto); }
.vacio__desc { margin: 0; max-width: 46ch; font-size: var(--texto-label); color: var(--color-texto-suave); line-height: 1.5; }
.vacio .boton { width: auto; margin-top: var(--esp-sm); }

/* ============================================================
   MOTION — micro-animaciones (sutiles, desactivables)
   ============================================================ */
@keyframes aparece { from { opacity: 0; transform: translateY(var(--desp-entrada)); } to { opacity: 1; transform: none; } }
/* Hermano de «aparece»: recorre lo mismo en sentido contrario. Lo comparten el
   modal, el desplegable y el asistente. Lo que aparece con gracia y desaparece
   de golpe se siente roto. */
@keyframes desaparece { to { opacity: 0; transform: translateY(var(--desp-entrada)); } }
@keyframes skel-brillo { from { background-position: 200% 0; } to { background-position: -200% 0; } }

/* Utilidad de entrada de contenido. */
.anim-aparece { animation: aparece var(--dur-media) var(--curva-entra); }

/* Stagger: hijos de .anim-lista entran escalonados (tope 8). */
.anim-lista > * { animation: aparece var(--dur-media) var(--curva-entra) backwards; }
.anim-lista > *:nth-child(1) { animation-delay: 0.02s; }
.anim-lista > *:nth-child(2) { animation-delay: 0.05s; }
.anim-lista > *:nth-child(3) { animation-delay: 0.08s; }
.anim-lista > *:nth-child(4) { animation-delay: 0.11s; }
.anim-lista > *:nth-child(5) { animation-delay: 0.14s; }
.anim-lista > *:nth-child(6) { animation-delay: 0.17s; }
.anim-lista > *:nth-child(7) { animation-delay: 0.2s; }
.anim-lista > *:nth-child(n + 8) { animation-delay: 0.22s; }

/* ============================================================
   SKELETON — placeholders de carga con brillo animado
   ============================================================ */
.skel { display: grid; gap: var(--esp-md); }
.skel--filas { gap: var(--esp-sm); }
.skel__linea, .skel__card {
  border-radius: var(--radio-input);
  background: linear-gradient(90deg, var(--color-superficie) 25%, var(--color-lila-suave) 50%, var(--color-superficie) 75%);
  background-size: 200% 100%; animation: skel-brillo 1.4s ease-in-out infinite;
}
.skel__linea { height: 16px; }
.skel__linea--corta { width: 55%; }
.skel__card { height: 92px; border-radius: var(--radio-card); }
.skel-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--esp-md); }

/* ============================================================
   ACCESIBILIDAD — respetar prefers-reduced-motion
   ============================================================ */
/* El comodín anterior solo neutralizaba TRANSICIONES, así que con la preferencia
   activa el modal, el desplegable y cada aviso seguían desplazándose. Ahora
   también las animaciones.

   Se dejan en 0.01ms y no en «none» a propósito: las salidas animadas esperan a
   animationend para retirar el nodo del DOM, y con «none» ese evento no llega.
   Los indicadores de carga se exceptúan aparte (css/styles.css): un spinner
   debe seguir indicando; se ralentiza, no se apaga. */
@media (prefers-reduced-motion: reduce) {
  .anim-aparece, .anim-lista > *, .skel__linea, .skel__card { animation: none; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
