/* =========================================================================
   Portal de Gestión — Plan B Strategic Solutions
   Dark corporativo, coherente con los dashboards de clientes.
   ========================================================================= */

/* Las superficies que se apoyan directamente sobre el fondo animado son
   opacas a propósito: los circuitos deben verse ALREDEDOR del contenido, no
   a través de él. Tres niveles, del más hundido al más elevado:
     --bg     fondo de la página (es lo único que deja ver la animación)
     --card   tarjetas del panel (resumen, laboratorios, actividad)
     --panel  superficies elevadas y aisladas (login y modales)
   Los rgba() que quedan en la hoja son tintes SOBRE un padre ya opaco
   (badges, filas, botones), no transparencia contra el fondo. */
:root {
  /* El desplegable de un <select> lo dibuja el sistema operativo, no la
     página: estilar `option` no alcanza y en Windows salía blanco sobre el
     tema oscuro. color-scheme es lo único que el navegador escucha para eso,
     y de paso deja oscuros los scrollbars y el resto de controles nativos. */
  color-scheme: dark;

  --bg:            #0c1021;
  --card:          #131829;
  --panel:         #1a2035;
  --borde:         rgba(255, 255, 255, .06);
  --borde-fuerte:  rgba(255, 255, 255, .12);
  /* Tres niveles de texto, los mismos que usan los dashboards de los clientes
     (Quifatex y Dimabru comparten este fondo y declaran --text2: #94a3b8).
     Contraste medido sobre el fondo más oscuro de cada superficie:
       --texto    15.3  primario
       --texto-2   6.3  secundario: etiquetas, subtítulos, notas, datos de
                        tarjeta, encabezados. Todo esto hay que LEERLO, así
                        que pasa el 4.5 de WCAG AA con margen.
       --texto-3   3.4  atenuado de verdad. Solo para lo decorativo o lo que
                        todavía no aplica: la flecha de una fila, el
                        marcador de un paso pendiente, un placeholder. */
  --texto:         #e2e8f0;
  --texto-2:       #94a3b8;
  --texto-3:       #64748b;

  --azul:          #2563eb;
  --azul-claro:    #60a5fa;
  --teal:          #2dd4bf;
  --violeta:       #818cf8;
  --ambar:         #fbbf24;
  --verde:         #34d399;
  --rojo:          #f87171;

  --radio:         14px;
  --radio-sm:      9px;
  --sombra:        0 18px 50px rgba(0, 0, 0, .38);

  --fuente: 'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html, body { height: 100%; }

body {
  font-family: var(--fuente);
  background: var(--bg);
  color: var(--texto);
  min-height: 100vh;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

button, input, select, textarea { font-family: inherit; font-size: inherit; }
button { cursor: pointer; }
a { color: var(--azul-claro); }

/* =========================================================================
   FONDO ANIMADO — ondas de datos (login) y cuadrícula (portal)
   ========================================================================= */

.fondo {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}

.fondo__ondas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* Dentro del portal el movimiento distrae: cambiamos las ondas animadas
   por una cuadricula tecnica estatica. Los glows se mantienen en ambos casos. */
body.app-activa .fondo__ondas { display: none; }

.fondo__grid {
  position: absolute;
  inset: 0;
  display: none;
  background-image:
    linear-gradient(rgba(96, 165, 250, .055) 1px, transparent 1px),
    linear-gradient(90deg, rgba(96, 165, 250, .055) 1px, transparent 1px);
  background-size: 34px 34px;
}

body.app-activa .fondo__grid { display: block; }

/* Manchas de resplandor sobre el SVG */
.fondo__glow {
  position: absolute;
  border-radius: 50%;
  filter: blur(85px);
  opacity: .5;
}

.fondo__glow--azul {
  top: -12%;
  left: -8%;
  width: 520px;
  height: 520px;
  background: radial-gradient(circle, rgba(37, 99, 235, .38) 0%, transparent 70%);
}

.fondo__glow--teal {
  bottom: -15%;
  right: -6%;
  width: 460px;
  height: 460px;
  background: radial-gradient(circle, rgba(45, 212, 191, .22) 0%, transparent 70%);
}

/* =========================================================================
   LAYOUT GENERAL
   ========================================================================= */

.pantalla { position: relative; z-index: 1; }
[hidden] { display: none !important; }

.contenedor {
  max-width: 1340px;
  margin: 0 auto;
  padding: 0 28px;
}

/* =========================================================================
   LOGIN
   ========================================================================= */

.login {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px 20px;
}

.login__card {
  width: 100%;
  max-width: 410px;
  background: var(--panel);
  border: 1px solid var(--borde-fuerte);
  border-radius: 20px;
  padding: 40px 36px 32px;
  box-shadow: var(--sombra);
  animation: aparecer .5s cubic-bezier(.2, .7, .3, 1) both;
}

.login__logo {
  display: block;
  height: 52px;
  margin: 0 auto 26px;
  object-fit: contain;
}

.login__titulo {
  font-size: 1.22rem;
  font-weight: 700;
  text-align: center;
  letter-spacing: -.2px;
}

.login__sub {
  font-size: .8rem;
  color: var(--texto-2);
  text-align: center;
  margin-top: 5px;
  margin-bottom: 28px;
}

.campo { margin-bottom: 16px; }

.campo__label {
  display: block;
  font-size: .73rem;
  font-weight: 600;
  color: var(--texto-2);
  text-transform: uppercase;
  letter-spacing: .5px;
  margin-bottom: 7px;
}

.campo__input {
  width: 100%;
  background: rgba(255, 255, 255, .03);
  border: 1px solid var(--borde-fuerte);
  border-radius: var(--radio-sm);
  padding: 11px 13px;
  color: var(--texto);
  font-size: .9rem;
  transition: border-color .18s, background .18s;
}

.campo__input:focus {
  outline: none;
  border-color: var(--azul);
  background: rgba(37, 99, 235, .06);
}

.campo__input::placeholder { color: var(--texto-3); }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  border: 1px solid transparent;
  border-radius: var(--radio-sm);
  padding: 10px 16px;
  font-size: .86rem;
  font-weight: 600;
  transition: all .18s;
  white-space: nowrap;
  /* Varios botones son <a> (abrir el dashboard, abrir el portal del cliente).
     Sin esto heredan el subrayado del navegador y se ven como enlaces sueltos
     dentro de una fila de botones. */
  text-decoration: none;
}

.btn:disabled { opacity: .5; cursor: not-allowed; }

/* El `gap` de arriba ya prevé un icono, pero faltaba acotarlo: un SVG sin
   dimensiones se estira hasta llenar el botón. `flex:none` evita además que se
   comprima cuando la etiqueta es larga. */
.btn svg { width: 15px; height: 15px; flex: none; }

.btn--primario {
  background: var(--azul);
  color: #fff;
}
.btn--primario:hover:not(:disabled) { background: #1d4ed8; }

.btn--secundario {
  background: rgba(255, 255, 255, .05);
  border-color: var(--borde-fuerte);
  color: var(--texto);
}
.btn--secundario:hover:not(:disabled) { background: rgba(255, 255, 255, .09); }

.btn--fantasma {
  background: transparent;
  border-color: var(--borde-fuerte);
  color: var(--texto-2);
}
.btn--fantasma:hover:not(:disabled) { color: var(--texto); border-color: var(--borde); }

.btn--bloque { width: 100%; }
.btn--chico { padding: 6px 11px; font-size: .74rem; }

.login__acciones { margin-top: 22px; }

.login__link {
  display: block;
  text-align: center;
  margin-top: 15px;
  font-size: .79rem;
  color: var(--texto-2);
  text-decoration: none;
}
.login__link:hover { color: var(--azul-claro); }

.alerta {
  border-radius: var(--radio-sm);
  padding: 11px 13px;
  font-size: .82rem;
  line-height: 1.45;
  margin-bottom: 16px;
}

.alerta--error {
  background: rgba(248, 113, 113, .1);
  border: 1px solid rgba(248, 113, 113, .28);
  color: #fca5a5;
}

.alerta--aviso {
  background: rgba(251, 191, 36, .09);
  border: 1px solid rgba(251, 191, 36, .25);
  color: #fcd34d;
}

.alerta--ok {
  background: rgba(52, 211, 153, .09);
  border: 1px solid rgba(52, 211, 153, .25);
  color: #6ee7b7;
}

.alerta--info {
  background: rgba(96, 165, 250, .08);
  border: 1px solid rgba(96, 165, 250, .22);
  color: #bfdbfe;
}

/* =========================================================================
   HEADER DE LA APP
   ========================================================================= */

.header {
  position: sticky;
  top: 0;
  z-index: 40;
  /* Opaco, no translúcido: el contenido se desplaza POR DEBAJO de esta barra
     y con alfa las tarjetas se transparentaban a través del encabezado. */
  background: var(--bg);
  border-bottom: 1px solid var(--borde);
}

.header__fila {
  max-width: 1340px;
  margin: 0 auto;
  padding: 14px 28px;
  display: flex;
  align-items: center;
  gap: 20px;
}

.header__marca { display: flex; align-items: center; gap: 13px; min-width: 0; }
.header__logo { height: 34px; object-fit: contain; flex-shrink: 0; }

.header__titulo { font-size: 1rem; font-weight: 700; line-height: 1.2; }
.header__sub { font-size: .7rem; color: var(--texto-2); margin-top: 1px; }

.header__spacer { flex: 1; }

.usuario {
  display: flex;
  align-items: center;
  gap: 11px;
  flex-shrink: 0;
}

.usuario__avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--azul), var(--violeta));
  display: grid;
  place-items: center;
  font-size: .85rem;
  font-weight: 700;
  color: #fff;
  flex-shrink: 0;
}

/* display:block va aquí y no más abajo: los hijos pasaron a ser <span> (el
   disparador del menú es un <button> y no puede contener <div>), y si la
   regla estuviera después de la media query de 820px le ganaría por orden
   de fuente y el bloque no se ocultaría en pantallas chicas. */
.usuario__datos { display: block; line-height: 1.25; min-width: 0; }
.usuario__nombre { font-size: .83rem; font-weight: 600; }
.usuario__rol { font-size: .68rem; color: var(--texto-2); }

.btn-icono {
  background: transparent;
  border: 1px solid var(--borde-fuerte);
  border-radius: var(--radio-sm);
  padding: 7px 9px;
  color: var(--texto-2);
  display: grid;
  place-items: center;
  transition: all .18s;
}
.btn-icono:hover { color: var(--texto); border-color: var(--borde); background: rgba(255,255,255,.04); }
.btn-icono svg { width: 16px; height: 16px; display: block; }

/* --- Tabs --- */

.tabs {
  max-width: 1340px;
  margin: 0 auto;
  padding: 0 28px;
  display: flex;
  gap: 4px;
}

.tab {
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  padding: 11px 15px;
  font-size: .85rem;
  font-weight: 600;
  color: var(--texto-2);
  transition: color .18s, border-color .18s;
}

.tab:hover { color: var(--texto); }

.tab.is-activa {
  color: var(--azul-claro);
  border-bottom-color: var(--azul-claro);
}

/* =========================================================================
   CONTENIDO / PANELES
   ========================================================================= */

.contenido { padding: 28px 0 60px; }
.panel { animation: aparecer .35s ease-out both; }

.panel__vacio {
  text-align: center;
  padding: 70px 20px;
  color: var(--texto-2);
  font-size: .9rem;
}

.seccion-titulo {
  font-size: .74rem;
  font-weight: 700;
  color: var(--texto-2);
  text-transform: uppercase;
  letter-spacing: .8px;
  margin: 34px 0 14px;
}

/* =========================================================================
   TOASTS
   ========================================================================= */

.toasts {
  position: fixed;
  bottom: 22px;
  right: 22px;
  z-index: 300;
  display: flex;
  flex-direction: column;
  gap: 9px;
  max-width: 380px;
}

.toast {
  background: var(--card);
  border: 1px solid var(--borde-fuerte);
  border-left-width: 3px;
  border-radius: var(--radio-sm);
  padding: 12px 16px;
  font-size: .84rem;
  line-height: 1.45;
  box-shadow: var(--sombra);
  opacity: 0;
  transform: translateX(20px);
  transition: opacity .25s, transform .25s;
}

.toast.is-visible { opacity: 1; transform: translateX(0); }
.toast--ok { border-left-color: var(--verde); }
.toast--error { border-left-color: var(--rojo); }
.toast--aviso { border-left-color: var(--ambar); }
.toast--info { border-left-color: var(--azul-claro); }

/* =========================================================================
   SKELETONS
   ========================================================================= */

.skeleton {
  background: linear-gradient(90deg,
    rgba(255, 255, 255, .04) 25%,
    rgba(255, 255, 255, .08) 50%,
    rgba(255, 255, 255, .04) 75%);
  background-size: 200% 100%;
  border-radius: 6px;
  animation: brillo 1.4s ease-in-out infinite;
}

@keyframes brillo {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

.spinner {
  width: 17px;
  height: 17px;
  border: 2px solid rgba(255, 255, 255, .18);
  border-top-color: var(--azul-claro);
  border-radius: 50%;
  animation: girar .7s linear infinite;
  display: inline-block;
}

@keyframes girar { to { transform: rotate(360deg); } }

@keyframes aparecer {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* =========================================================================
   CARGA INICIAL
   ========================================================================= */

.cargando-inicial {
  position: fixed;
  inset: 0;
  z-index: 500;
  display: grid;
  place-items: center;
  background: var(--bg);
}

.cargando-inicial__contenido { text-align: center; }
.cargando-inicial img { height: 44px; margin-bottom: 20px; opacity: .85; }

/* =========================================================================
   RESPONSIVE
   ========================================================================= */

@media (max-width: 820px) {
  .contenedor, .header__fila, .tabs { padding-left: 16px; padding-right: 16px; }
  .header__sub { display: none; }
  .usuario__datos { display: none; }
  .tabs { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .tab { white-space: nowrap; }
  .toasts { left: 16px; right: 16px; max-width: none; }
}

@media (max-width: 520px) {
  .login__card { padding: 32px 24px 26px; }
  .header__titulo { font-size: .92rem; }
}

/* =========================================================================
   ACCESIBILIDAD — respetar preferencia de movimiento reducido
   ========================================================================= */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  /* Las ondas del login NO se detienen desde acá: son SMIL, que no obedece a
     esta media query, y `display:none` sobre el elemento de animación solo lo
     oculta mientras sigue corriendo (comprobado). Las pausa
     `initMovimientoReducido()` en js/app.js con pauseAnimations(). */

  /* El spinner es la señal de que algo está en curso, no un adorno: si se
     congela junto con el resto, una pantalla de espera parece colgada. Se
     mantiene girando, más lento. */
  .spinner {
    animation-duration: 1.6s !important;
    animation-iteration-count: infinite !important;
  }
}

/* =========================================================================
   PESTAÑA LABORATORIOS
   ========================================================================= */

/* --- Barra de resumen --- */

.resumen {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 10px;
  margin-bottom: 20px;
}

.resumen__item {
  background: var(--card);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  padding: 15px 17px;
}

.resumen__valor {
  font-size: 1.55rem;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -.5px;
}

.resumen__valor--chico { font-size: .95rem; padding-top: 9px; padding-bottom: 6px; }
.resumen__valor.es-ok { color: var(--verde); }
.resumen__valor.es-aviso { color: var(--ambar); }
.resumen__valor.es-error { color: var(--rojo); }

.resumen__etiqueta {
  font-size: .68rem;
  color: var(--texto-2);
  text-transform: uppercase;
  letter-spacing: .6px;
  font-weight: 600;
  margin-top: 5px;
}

/* --- Aviso de token --- */

.aviso-token { margin-bottom: 18px; }
.aviso-token a { margin-left: 6px; font-weight: 600; }

/* --- Tarjeta de laboratorio --- */

.labs { display: flex; flex-direction: column; gap: 16px; }

.lab-card {
  background: var(--card);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  overflow: hidden;
  transition: border-color .2s;
}

.lab-card:hover { border-color: var(--borde-fuerte); }
.lab-card.es-atrasado { border-color: rgba(251, 191, 36, .35); }
.lab-card.es-vencido { border-color: rgba(248, 113, 113, .4); }

.lab-card__banda {
  height: 46px;
  display: flex;
  align-items: center;
  padding: 0 18px;
  gap: 14px;
}

/* Respaldo oscuro: garantiza contraste sea cual sea el logo y el color de marca.
   Acá el alfa sí se justifica y no compromete la legibilidad: lo que hay detrás
   es la banda de marca dentro de una tarjeta opaca, no el fondo animado, así que
   compone siempre al mismo color; oscurece el color de marca sin abrir un hueco
   negro en la banda. */
.lab-card__logo-caja {
  display: inline-flex;
  align-items: center;
  background: rgba(8, 11, 22, .55);
  border: 1px solid rgba(255, 255, 255, .1);
  border-radius: 8px;
  padding: 5px 11px;
}

/* Valores de respaldo: utils.js sobrescribe la altura en linea para igualar
   el AREA de cada logo, no su altura. Igualar altura hace que un logo muy
   ancho (Dimabru) se vea al doble de grande que uno compacto (La Roche-Posay). */
.lab-card__logo {
  height: 30px;
  width: auto;
  max-width: 150px;
  object-fit: contain;
  display: block;
}

.lab-card__logo-txt { font-weight: 700; font-size: .85rem; color: #fff; }

.lab-card__banda-der {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 10px;
}

.estado-dash {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: .7rem;
  font-weight: 600;
  color: rgba(255, 255, 255, .78);
  white-space: nowrap;
}

.estado-dash__punto {
  width: 7px; height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
}

.estado-dash.es-vivo .estado-dash__punto {
  background: var(--verde);
  box-shadow: 0 0 0 3px rgba(52, 211, 153, .2);
}
.estado-dash.es-caido .estado-dash__punto {
  background: var(--rojo);
  box-shadow: 0 0 0 3px rgba(248, 113, 113, .2);
}

.badge {
  font-size: .67rem;
  font-weight: 700;
  padding: 4px 9px;
  border-radius: 20px;
  white-space: nowrap;
}

.badge--ok { background: rgba(52, 211, 153, .17); color: #6ee7b7; }
.badge--aviso { background: rgba(251, 191, 36, .17); color: #fcd34d; }

.lab-card__cuerpo { padding: 18px; }

.lab-card__encabezado {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 18px;
  margin-bottom: 16px;
}

.lab-card__nombre {
  font-size: 1.06rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  gap: 9px;
  flex-wrap: wrap;
}

.chip {
  font-size: .62rem;
  font-weight: 700;
  padding: 3px 8px;
  border-radius: 20px;
  text-transform: uppercase;
  letter-spacing: .4px;
}

.chip--fuente {
  background: rgba(96, 165, 250, .14);
  color: var(--azul-claro);
  border: 1px solid rgba(96, 165, 250, .22);
}

.lab-card__desc {
  font-size: .81rem;
  color: var(--texto-2);
  margin-top: 5px;
}

.lab-card__sep { margin: 0 5px; opacity: .5; }

.lab-card__meta { text-align: right; flex-shrink: 0; }

.lab-card__periodo {
  font-size: .83rem;
  font-weight: 600;
  color: var(--texto);
}

.lab-card__actualizado {
  font-size: .72rem;
  color: var(--texto-2);
  margin-top: 3px;
}

/* --- Miniaturas de dashboards --- */

/* La grilla se ajusta a cuantos dashboards publique el laboratorio: con menos
   de 4 se reparte el ancho completo en vez de dejar columnas vacias. Cuanto
   mas ancha la miniatura, mejor se lee su grafico. */
/* minmax(0,1fr) y no 1fr: `1fr` equivale a minmax(auto,1fr), asi que una
   palabra larga del contexto ensancha su columna y las miniaturas dejan de
   medir lo mismo. Con minimo 0 todas quedan exactamente iguales. */
.lab-card__mini {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
  margin-bottom: 16px;
}

.lab-card__mini[data-cols="1"] { grid-template-columns: minmax(0, 1fr); }
.lab-card__mini[data-cols="2"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.lab-card__mini[data-cols="3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }

.mini {
  background: rgba(255, 255, 255, .025);
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
  padding: 12px 13px;
  text-decoration: none;
  color: inherit;
  display: flex;
  flex-direction: column;
  gap: 7px;
  transition: background .18s, border-color .18s, transform .18s;
}

.mini:hover {
  background: rgba(255, 255, 255, .05);
  border-color: var(--borde-fuerte);
  transform: translateY(-2px);
}

.mini__nombre {
  font-size: .71rem;
  font-weight: 600;
  color: var(--texto-2);
  text-transform: uppercase;
  letter-spacing: .4px;
}

.mini__valor {
  font-size: 1.18rem;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -.4px;
}

.mini__unidad {
  font-size: .66rem;
  font-weight: 500;
  color: var(--texto-2);
  margin-left: 4px;
  letter-spacing: 0;
}

/* Mini-gráfico de ECharts: réplica del que ve el cliente en su propio portal.
   pointer-events:none para que el canvas no robe el click de la tarjeta. */
.mini__chart {
  height: 100px;
  width: 100%;
  pointer-events: none;
}

.mini__chart--vacio {
  display: grid;
  place-items: center;
  font-size: .66rem;
  color: var(--texto-2);
  border: 1px dashed var(--borde);
  border-radius: 5px;
}

.mini__contexto {
  font-size: .68rem;
  color: var(--texto-2);
  line-height: 1.35;
}

/* --- Acciones --- */

.lab-card__acciones {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  padding-top: 14px;
  border-top: 1px solid var(--borde);
}

.btn.es-copiado {
  color: var(--verde);
  border-color: rgba(52, 211, 153, .4);
}

/* --- Actividad reciente --- */

.actividad {
  background: var(--card);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  overflow: hidden;
}

.actividad__fila {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 17px;
  border-bottom: 1px solid var(--borde);
  font-size: .82rem;
}

.actividad__fila:last-child { border-bottom: none; }

.actividad__punto {
  width: 7px; height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
}

.actividad__punto.es-ok { background: var(--verde); }
.actividad__punto.es-aviso { background: var(--ambar); }
.actividad__punto.es-error { background: var(--rojo); }
.actividad__punto.es-info { background: var(--azul-claro); }
.actividad__punto.es-neutro { background: var(--texto-3); }

.actividad__lab { font-weight: 600; min-width: 130px; }
.actividad__texto { color: var(--texto-2); flex: 1; }
.actividad__usuario { color: var(--texto-2); font-size: .76rem; }

.actividad__fecha {
  color: var(--texto-2);
  font-size: .74rem;
  min-width: 92px;
  text-align: right;
}

.actividad__pie { margin-top: 12px; }

/* --- Responsive de la pestaña --- */

@media (max-width: 1100px) {
  .resumen { grid-template-columns: repeat(3, 1fr); }
  /* Solo baja el caso de 4: pasa a 2 columnas (2 filas llenas, sin huecos).
     Los de 1, 2 y 3 conservan su regla de arriba, que ya no deja huecos y
     tiene mas especificidad que este selector. Bajar el de 3 a 2 columnas
     seria justamente volver a dejar una celda vacia. */
  .lab-card__mini,
  .lab-card__mini[data-cols="4"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 820px) {
  .resumen { grid-template-columns: repeat(2, 1fr); }
  /* Con un número impar de items el último quedaría solo a media fila: se
     lo hace ocupar el ancho completo en vez de dejar el hueco. */
  .resumen__item:last-child:nth-child(odd) { grid-column: 1 / -1; }
  .lab-card__encabezado { flex-direction: column; gap: 10px; }
  .lab-card__meta { text-align: left; }
  .lab-card__acciones { flex-direction: column; }
  .lab-card__acciones .btn { width: 100%; }
  .actividad__fila { flex-wrap: wrap; gap: 6px 10px; }
  .actividad__lab { min-width: 0; }
  .actividad__texto { flex-basis: 100%; order: 3; }
  .actividad__fecha { margin-left: auto; }
}

@media (max-width: 520px) {
  /* A este ancho 3 columnas dejan las miniaturas ilegibles: pasa a 1 (unica
     alternativa sin huecos). Los de 1, 2 y 4 aguantan su reparto. */
  .lab-card__mini[data-cols="3"] { grid-template-columns: minmax(0, 1fr); }
  .resumen { grid-template-columns: 1fr 1fr; }
  .lab-card__banda { padding: 0 12px; gap: 8px; }
  .lab-card__logo { height: 22px; max-width: 108px; }
  .lab-card__logo-caja { padding: 4px 8px; }
  .estado-dash { display: none; }
  .lab-card__cuerpo { padding: 14px; }
}

/* =========================================================================
   MODAL DE CARGA
   ========================================================================= */

body.con-modal { overflow: hidden; }

.modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: 20px;
}

/* El velo sí conserva alfa y desenfoque: su trabajo es dejar entrever el panel
   apagado para dar contexto. No afecta la legibilidad del modal, que va encima
   y es opaco. */
.modal__fondo {
  position: absolute;
  inset: 0;
  background: rgba(6, 9, 20, .72);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  animation: aparecer .16s ease-out;
}

.modal__caja {
  position: relative;
  width: 100%;
  /* Sin min-width:0 el tamaño mínimo automático de un item de grid es su
     min-content, así que una fila con texto sin cortes ensancha la caja por
     encima del viewport y el contenido se sale por la derecha. */
  min-width: 0;
  max-width: 560px;
  max-height: calc(100vh - 40px);
  display: flex;
  flex-direction: column;
  /* El color literal no es redundante: --panel estuvo sin definir y una var()
     que no resuelve invalida la declaración entera, así que la caja se quedaba
     SIN fondo y los modales salían transparentes. Acá ese fallo no se nota a
     simple vista en el código pero deja el texto ilegible, así que va respaldo. */
  background: var(--panel, #1a2035);
  border: 1px solid var(--borde-fuerte);
  border-radius: var(--radio);
  box-shadow: 0 24px 70px rgba(0, 0, 0, .55);
  animation: subir .2s cubic-bezier(.2, .8, .3, 1);
}

@keyframes aparecer { from { opacity: 0 } to { opacity: 1 } }
@keyframes subir {
  from { opacity: 0; transform: translateY(12px) scale(.985) }
  to   { opacity: 1; transform: none }
}

.modal__cab {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 18px 20px 14px;
  border-bottom: 1px solid var(--borde);
}

.modal__titulo { font-size: 1.02rem; font-weight: 700; }
.modal__sub { font-size: .78rem; color: var(--texto-2); margin-top: 2px; }
.modal__cab .btn-icono { margin-left: auto; flex-shrink: 0; }

.modal__cuerpo {
  padding: 18px 20px;
  overflow-y: auto;
  flex: 1;
}

.modal__cuerpo--centrado { text-align: center; padding: 30px 24px; }

.modal__estado {
  font-size: .95rem;
  font-weight: 600;
  margin-top: 14px;
}

.modal__pie {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  padding: 14px 20px 18px;
  border-top: 1px solid var(--borde);
  flex-wrap: wrap;
}

.nota { font-size: .74rem; color: var(--texto-2); line-height: 1.5; margin-top: 8px; }
.nota--centrada { text-align: center; }
.nota--error { color: #fca5a5; }
.nota a { color: var(--azul-claro); }

.spinner--grande { width: 34px; height: 34px; border-width: 3px; }

/* --- Periodo publicado --- */

.dato-actual {
  display: flex;
  align-items: baseline;
  gap: 9px;
  flex-wrap: wrap;
  background: rgba(255, 255, 255, .025);
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
  padding: 10px 13px;
  margin-bottom: 16px;
}

.dato-actual__etq {
  font-size: .64rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: var(--texto-2);
}
.dato-actual__val { font-size: .87rem; font-weight: 600; }
.dato-actual__aux { font-size: .72rem; color: var(--texto-2); margin-left: auto; }

/* --- Zona de arrastre --- */

.dropzone {
  border: 1.5px dashed var(--borde-fuerte);
  border-radius: var(--radio);
  padding: 32px 20px;
  text-align: center;
  cursor: pointer;
  transition: border-color .18s, background .18s;
}

.dropzone:hover,
.dropzone:focus-visible {
  border-color: rgba(96, 165, 250, .5);
  background: rgba(96, 165, 250, .04);
  outline: none;
}

.dropzone.es-activa {
  border-color: var(--azul-claro);
  background: rgba(96, 165, 250, .09);
}

.dropzone__icono { width: 30px; height: 30px; color: var(--azul-claro); opacity: .75; }
.dropzone__txt { font-size: .9rem; font-weight: 600; margin-top: 10px; }
.dropzone__aux { font-size: .74rem; color: var(--texto-2); margin-top: 5px; }

.desplegable { margin-top: 16px; }
.desplegable summary {
  font-size: .78rem;
  color: var(--texto-2);
  cursor: pointer;
  padding: 6px 0;
}
.desplegable summary:hover { color: var(--texto); }

.lista-hojas { list-style: none; margin-top: 8px; display: grid; gap: 5px; }
.lista-hojas code,
.nota code {
  background: rgba(255, 255, 255, .05);
  border: 1px solid var(--borde);
  border-radius: 4px;
  padding: 2px 6px;
  font-size: .73rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* --- Archivo elegido --- */

.archivo {
  display: flex;
  align-items: center;
  gap: 12px;
  background: rgba(255, 255, 255, .025);
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
  padding: 11px 13px;
  margin-bottom: 16px;
}

.archivo__icono { width: 24px; height: 24px; color: var(--azul-claro); flex-shrink: 0; }
.archivo__datos { min-width: 0; flex: 1; }
.archivo__nombre {
  font-size: .82rem;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.archivo__meta { font-size: .72rem; color: var(--texto-2); margin-top: 2px; }

/* --- Lista de chequeos por hoja --- */

.chequeos { list-style: none; display: grid; gap: 6px; }

.chequeo {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: .8rem;
  padding: 8px 11px;
  border-radius: var(--radio-sm);
  border: 1px solid var(--borde);
  background: rgba(255, 255, 255, .02);
}

.chequeo::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
}
.chequeo--ok::before { background: var(--verde); box-shadow: 0 0 0 3px rgba(52, 211, 153, .16); }
.chequeo--error::before { background: var(--rojo); box-shadow: 0 0 0 3px rgba(248, 113, 113, .16); }

.chequeo--error { border-color: rgba(248, 113, 113, .26); background: rgba(248, 113, 113, .05); }

.chequeo__nombre {
  font-weight: 600;
  min-width: 0;          /* si no, el nombre largo no deja encoger la fila */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.chequeo__detalle {
  margin-left: auto;
  color: var(--texto-2);
  font-size: .75rem;
  white-space: nowrap;
  flex-shrink: 0;
}

.delta { font-weight: 600; margin-left: 5px; }
.delta.es-mas { color: #6ee7b7; }
.delta.es-menos { color: #fcd34d; }

.lista-motivos { margin: 7px 0 0 16px; display: grid; gap: 4px; }

/* --- Pasos de publicacion --- */

.pasos { list-style: none; display: grid; gap: 3px; }

.paso {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 4px;
  font-size: .85rem;
  transition: color .2s;
}

.paso__marca {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: .72rem;
  font-weight: 700;
  flex-shrink: 0;
  border: 1.5px solid var(--borde-fuerte);
  color: var(--texto-2);
  transition: all .2s;
}

.paso.es-hecho { color: var(--texto-2); }
.paso.es-hecho .paso__marca {
  background: rgba(52, 211, 153, .16);
  border-color: rgba(52, 211, 153, .4);
  color: #6ee7b7;
}

.paso.es-activo { color: var(--texto); font-weight: 600; }
.paso.es-activo .paso__marca {
  border-color: var(--azul-claro);
  color: var(--azul-claro);
  animation: latir 1.5s ease-in-out infinite;
}

.paso.es-pendiente { color: var(--texto-3); }

@keyframes latir {
  0%, 100% { box-shadow: 0 0 0 0 rgba(96, 165, 250, .35) }
  50%      { box-shadow: 0 0 0 6px rgba(96, 165, 250, 0) }
}

/* --- Marca de resultado --- */

.marca-resultado {
  width: 54px;
  height: 54px;
  margin: 0 auto;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 1.6rem;
  font-weight: 700;
  animation: subir .3s cubic-bezier(.2, .8, .3, 1);
}

.marca-resultado--ok { background: rgba(52, 211, 153, .15); color: #6ee7b7; }
.marca-resultado--aviso { background: rgba(251, 191, 36, .15); color: #fcd34d; }
.marca-resultado--error { background: rgba(248, 113, 113, .15); color: #fca5a5; }
/* Desenlace correcto pero sin cambios. Va en azul y no en verde para no
   confundirlo con "se publicó": son resultados distintos. */
.marca-resultado--info { background: rgba(96, 165, 250, .15); color: #93c5fd; }

.resultado__periodo { font-size: .88rem; margin-top: 10px; }
.es-tenue { color: var(--texto-2); }

/* Dentro de un cuerpo centrado, una lista de motivos centrada es ilegible:
   el ojo pierde el arranque de cada renglón. Estos dos bloques recuperan la
   alineación a la izquierda sin sacarlos del cuerpo centrado. */
.alerta--izq { text-align: left; margin-top: 14px; }
.alerta--izq .lista-motivos { margin-top: 6px; }

.chequeos--resultado { text-align: left; margin: 14px 0 4px; }

@media (max-width: 520px) {
  .modal { padding: 0; }
  .modal__caja { max-width: none; max-height: 100vh; height: 100vh; border-radius: 0; border: none; }
  .modal__pie { flex-direction: column-reverse; }
  .modal__pie .btn { width: 100%; }
  .dato-actual__aux { margin-left: 0; width: 100%; }
  /* A este ancho el nombre de hoja y su detalle no caben en la misma línea. */
  .chequeo { flex-wrap: wrap; row-gap: 2px; }
  .chequeo__nombre { flex: 1 1 auto; }
  .chequeo__detalle { flex-basis: 100%; margin-left: 17px; text-align: left; }
  .archivo .btn { flex-shrink: 0; }
}

/* Nota: las animaciones del modal ya las neutraliza la regla global de
   prefers-reduced-motion que está más arriba; no hace falta repetirlas. */

/* =========================================================================
   HISTORIAL
   ========================================================================= */

.seccion-titulo__cuenta {
  font-size: .74rem;
  font-weight: 600;
  color: var(--texto-2);
  margin-left: 8px;
}

.badge--error { background: rgba(248, 113, 113, .17); color: #fca5a5; }
.badge--info { background: rgba(96, 165, 250, .17); color: #bfdbfe; }
.badge--neutro { background: rgba(255, 255, 255, .07); color: var(--texto-2); }

.chip--ok {
  background: rgba(52, 211, 153, .14);
  color: #6ee7b7;
  border: 1px solid rgba(52, 211, 153, .22);
}

.btn--peligro {
  background: rgba(248, 113, 113, .16);
  border-color: rgba(248, 113, 113, .4);
  color: #fca5a5;
}
.btn--peligro:hover:not(:disabled) {
  background: rgba(248, 113, 113, .24);
  color: #fecaca;
}

/* --- Filtros --- */

.filtros {
  display: flex;
  gap: 9px;
  flex-wrap: wrap;
  margin-bottom: 16px;
  align-items: center;
}

.filtros__campo {
  width: auto;
  min-width: 0;
  font-size: .82rem;
  padding: 8px 11px;
}

.filtros__campo--busca { flex: 1; min-width: 200px; }

select.filtros__campo {
  appearance: none;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 9px center;
  background-size: 13px;
  padding-right: 28px;
}

select.filtros__campo option { background: var(--card); color: var(--texto); }

/* --- Lista de cargas --- */

.cargas { display: grid; gap: 7px; }

.carga {
  background: var(--card);
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
  overflow: hidden;
  transition: border-color .18s;
}

.carga:hover { border-color: var(--borde-fuerte); }
.carga.es-abierta { border-color: rgba(96, 165, 250, .28); }

.carga__cab {
  width: 100%;
  display: grid;
  grid-template-columns: 96px minmax(0, 1.1fr) minmax(0, 2fr) minmax(0, 1.2fr) minmax(0, 1fr) 82px 20px;
  align-items: center;
  gap: 12px;
  padding: 11px 14px;
  background: none;
  border: none;
  color: inherit;
  text-align: left;
  font-size: .81rem;
}

.carga__cab > span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.carga__cab .badge { justify-self: start; }
.carga__lab { font-weight: 600; }
/* El punto de aviso va fuera del texto: si estuviera dentro, al truncarse el
   nombre del archivo quedaría recortado justo cuando hace falta verlo. */
.carga__archivo { color: var(--texto-2); display: flex; align-items: center; gap: 6px; }
/* Truncado que conserva la extensión: solo la base se recorta con puntos
   suspensivos y el ".xlsx" se mantiene pegado al final, en vez del
   "…Enero a Agosto.x…" que dejaba el ellipsis corriente. */
.carga__archivo-txt {
  min-width: 0;
  display: flex;
}
.carga__archivo-base {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.carga__archivo-ext {
  flex-shrink: 0;
  white-space: nowrap;
}
.carga__periodo { color: var(--texto-2); font-size: .76rem; }
.carga__autor { color: var(--texto-2); font-size: .76rem; }
.carga__fecha { color: var(--texto-2); font-size: .74rem; text-align: right; }

.punto-aviso {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--ambar);
  flex-shrink: 0;
  box-shadow: 0 0 0 3px rgba(251, 191, 36, .16);
}

.carga__flecha {
  width: 15px;
  height: 15px;
  color: var(--texto-3);
  transition: transform .2s;
}
.carga.es-abierta .carga__flecha { transform: rotate(180deg); }

.carga__cuerpo {
  padding: 4px 14px 14px;
  border-top: 1px solid var(--borde);
  animation: desplegar .2s ease-out;
}

@keyframes desplegar {
  from { opacity: 0; transform: translateY(-4px) }
  to   { opacity: 1; transform: none }
}

.carga__pie {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--borde);
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 10px;
}

/* --- Detalle --- */

.detalle { padding-top: 14px; }

.detalle__datos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 8px 18px;
  font-size: .78rem;
  margin-bottom: 14px;
}

.detalle__datos > div {
  display: flex;
  gap: 7px;
  align-items: baseline;
  min-width: 0;
}

.detalle__etq {
  font-size: .64rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .4px;
  color: var(--texto-2);
  flex-shrink: 0;
}

.detalle__datos code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .74rem;
  background: rgba(255, 255, 255, .05);
  border-radius: 4px;
  padding: 1px 5px;
}

.detalle__bloque { margin-top: 16px; }

.detalle__subtitulo {
  font-size: .7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: var(--texto-2);
  margin-bottom: 9px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.detalle__acciones {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 16px;
}

/* --- Novedades --- */

.novedades { display: grid; gap: 11px; }

.novedades__titulo {
  font-size: .76rem;
  font-weight: 600;
  text-transform: capitalize;
  display: flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 5px;
}

.novedades__cuenta {
  font-size: .64rem;
  font-weight: 700;
  background: rgba(251, 191, 36, .16);
  color: #fcd34d;
  border-radius: 20px;
  padding: 1px 7px;
}

.novedades__items {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  align-items: center;
}

.novedades__items code {
  font-size: .71rem;
  font-family: inherit;
  background: rgba(255, 255, 255, .04);
  border: 1px solid var(--borde);
  border-radius: 4px;
  padding: 2px 7px;
  color: var(--texto-2);
}

.novedades__items .nota { margin-top: 0; }

.modal__parrafo { font-size: .85rem; line-height: 1.55; margin-bottom: 16px; }

/* --- Responsive --- */

@media (max-width: 1100px) {
  .carga__cab { grid-template-columns: 92px minmax(0, 1fr) minmax(0, 1.6fr) 76px 20px; }
  .carga__periodo, .carga__autor { display: none; }
}

@media (max-width: 640px) {
  .carga__cab {
    grid-template-columns: 1fr 20px;
    gap: 5px 10px;
    padding: 12px 14px;
  }
  .carga__cab .badge { grid-column: 1; }
  .carga__flecha { grid-row: 1; grid-column: 2; align-self: start; }
  .carga__lab, .carga__archivo { grid-column: 1; }
  .carga__fecha { grid-column: 1; text-align: left; }
  .filtros__campo, .filtros__campo--busca { width: 100%; flex-basis: 100%; }
}

/* =========================================================================
   ADMINISTRACION
   ========================================================================= */

.admin-bloque { margin-bottom: 34px; }

.admin-bloque__cab {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}

.admin-bloque__cab .seccion-titulo { margin: 0; }

.admin-lista { display: grid; gap: 7px; }

.admin-fila {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 1.5fr) auto;
  align-items: center;
  gap: 14px;
  background: var(--card);
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
  padding: 11px 14px;
  transition: border-color .18s;
}

.admin-fila:hover { border-color: var(--borde-fuerte); }
.admin-fila.es-inactiva { opacity: .55; }

.admin-fila__principal {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
  flex-wrap: wrap;
}

.admin-fila__nombre {
  font-weight: 600;
  font-size: .87rem;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.admin-fila__slug,
.admin-fila__meta code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .71rem;
  background: rgba(255, 255, 255, .05);
  border: 1px solid var(--borde);
  border-radius: 4px;
  padding: 1px 6px;
  color: var(--texto-2);
}

.admin-fila__avatar {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: rgba(96, 165, 250, .16);
  color: var(--azul-claro);
  font-size: .72rem;
  font-weight: 700;
  flex-shrink: 0;
}

.admin-fila__meta {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: .74rem;
  color: var(--texto-2);
  min-width: 0;
}

.admin-fila__meta > span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.admin-fila__acciones {
  display: flex;
  align-items: center;
  gap: 8px;
  justify-self: end;
  flex-shrink: 0;
}

.admin-fila__acciones select { min-width: 118px; }
.admin-fila__acciones select:disabled,
.admin-fila__acciones button:disabled { opacity: .4; cursor: not-allowed; }

.es-aviso { color: var(--ambar); }
.admin-fila__meta .es-error { color: var(--rojo); }

/* --- Formulario --- */

.campo__input--mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .84rem;
}

.campo__input.es-invalido {
  border-color: rgba(248, 113, 113, .55);
  background: rgba(248, 113, 113, .05);
}

.campo__error {
  font-size: .72rem;
  color: #fca5a5;
  margin-top: 5px;
}

.interruptor {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: 4px 10px;
  cursor: pointer;
  padding: 11px 0 3px;
}

.interruptor input {
  width: 16px;
  height: 16px;
  accent-color: var(--azul);
  cursor: pointer;
}

.interruptor > span:nth-of-type(1) { font-size: .86rem; font-weight: 600; }
.interruptor .nota { grid-column: 2; margin-top: 0; }

/* --- Responsive --- */

@media (max-width: 900px) {
  .admin-fila {
    grid-template-columns: 1fr;
    gap: 9px;
  }
  .admin-fila__acciones { justify-self: stretch; }
  .admin-fila__acciones select { flex: 1; }
  .admin-fila__acciones .btn { flex-shrink: 0; }
}

/* =========================================================================
   MENU DEL USUARIO
   ========================================================================= */

.usuario { position: relative; }

.usuario__disparador {
  display: flex;
  align-items: center;
  gap: 11px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radio-sm);
  padding: 5px 9px 5px 5px;
  color: inherit;
  text-align: left;
  transition: background .18s, border-color .18s;
}

.usuario__disparador:hover,
.usuario__disparador[aria-expanded="true"] {
  background: rgba(255, 255, 255, .04);
  border-color: var(--borde-fuerte);
}

.usuario__nombre,
.usuario__rol { display: block; }

.usuario__flecha {
  width: 14px;
  height: 14px;
  color: var(--texto-2);
  flex-shrink: 0;
  transition: transform .18s;
}
.usuario__disparador[aria-expanded="true"] .usuario__flecha { transform: rotate(180deg); }

.menu {
  position: absolute;
  top: calc(100% + 7px);
  right: 0;
  z-index: 60;
  min-width: 208px;
  background: var(--card);
  border: 1px solid var(--borde-fuerte);
  border-radius: var(--radio-sm);
  box-shadow: 0 14px 40px rgba(0, 0, 0, .45);
  padding: 5px;
  animation: subir .15s ease-out;
}

.menu__item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  background: transparent;
  border: none;
  border-radius: 6px;
  padding: 9px 11px;
  font-size: .83rem;
  font-weight: 500;
  color: var(--texto);
  text-align: left;
  transition: background .15s;
}

.menu__item:hover { background: rgba(255, 255, 255, .06); }
.menu__item svg { width: 15px; height: 15px; color: var(--texto-2); flex-shrink: 0; }
.menu__item:hover svg { color: var(--azul-claro); }

.menu__sep { height: 1px; background: var(--borde); margin: 5px 2px; }

/* =========================================================================
   DEFINIR CONTRASENA
   ========================================================================= */

/* Barra de fortaleza: cuatro tramos que se van encendiendo */
.fuerza { margin: -6px 0 14px; }

.fuerza__barra {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 4px;
}

.fuerza__barra span {
  height: 4px;
  border-radius: 2px;
  background: rgba(255, 255, 255, .08);
  transition: background .25s;
}

.fuerza__texto {
  font-size: .72rem;
  font-weight: 600;
  margin-top: 6px;
  text-align: right;
  color: var(--texto-2);
}

.fuerza[data-nivel="1"] .fuerza__barra span:nth-child(-n+1),
.fuerza[data-nivel="2"] .fuerza__barra span:nth-child(-n+2),
.fuerza[data-nivel="3"] .fuerza__barra span:nth-child(-n+3),
.fuerza[data-nivel="4"] .fuerza__barra span { background: currentColor; }

.fuerza[data-nivel="0"] { color: var(--rojo); }
.fuerza[data-nivel="1"] { color: var(--rojo); }
.fuerza[data-nivel="2"] { color: var(--ambar); }
.fuerza[data-nivel="3"] { color: #6ee7b7; }
.fuerza[data-nivel="4"] { color: var(--verde); }

.fuerza[data-nivel="0"] .fuerza__texto,
.fuerza[data-nivel="1"] .fuerza__texto { color: #fca5a5; }
.fuerza[data-nivel="2"] .fuerza__texto { color: #fcd34d; }
.fuerza[data-nivel="3"] .fuerza__texto,
.fuerza[data-nivel="4"] .fuerza__texto { color: #6ee7b7; }

/* Lista de requisitos */
.requisitos {
  list-style: none;
  display: grid;
  gap: 5px;
  margin: 0 0 16px;
}

.requisitos li {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: .75rem;
  color: var(--texto-2);
  transition: color .2s;
}

.requisitos__marca {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1.5px solid var(--borde-fuerte);
  flex-shrink: 0;
  position: relative;
  transition: all .2s;
}

.requisitos li.es-ok { color: #6ee7b7; }

.requisitos li.es-ok .requisitos__marca {
  background: rgba(52, 211, 153, .2);
  border-color: rgba(52, 211, 153, .5);
}

.requisitos li.es-ok .requisitos__marca::after {
  content: '';
  position: absolute;
  left: 3.5px;
  top: 1px;
  width: 3.5px;
  height: 7px;
  border: solid #6ee7b7;
  border-width: 0 1.8px 1.8px 0;
  transform: rotate(45deg);
}

.separador { height: 1px; background: var(--borde); margin: 4px 0 18px; }

@media (max-width: 520px) {
  /* .usuario__datos ya lo oculta la media query de 820px */
  .menu { right: -4px; min-width: 194px; }
}

/* =========================================================================
   MOSTRAR / OCULTAR CONTRASENA
   ========================================================================= */

/* La caja la crea activarOjos() envolviendo el input: hace de ancla para
   posicionar el boton dentro del campo. */
.campo__caja {
  position: relative;
  display: block;
}

/* Sitio reservado para el ojo. Sin esto el texto pasa por debajo del icono
   cuando la contrasena es larga, que es justo cuando hace falta leerla. */
.campo__caja .campo__input {
  padding-right: 44px;
}

.ojo {
  position: absolute;
  right: 5px;
  top: 50%;
  transform: translateY(-50%);
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  background: transparent;
  border: none;
  border-radius: 6px;
  color: var(--texto-2);
  transition: color .15s, background .15s;
}

/* El hover sube a --texto: al pasar el ojo de --texto-3 a --texto-2, quedaba
   del mismo color que su estado normal y el hover no se notaba. */
.ojo:hover { color: var(--texto); background: rgba(255, 255, 255, .05); }
.ojo.es-activo { color: var(--azul-claro); }

.ojo:focus-visible {
  outline: 2px solid var(--azul);
  outline-offset: -2px;
  color: var(--texto-2);
}

.ojo svg { width: 17px; height: 17px; display: block; }

/* Edge y algunos navegadores ponen su propio ojo: se quita para no tener dos. */
.campo__caja .campo__input::-ms-reveal,
.campo__caja .campo__input::-ms-clear { display: none; }

/* =========================================================================
   CONTACTOS AUTORIZADOS — panel «Enviar enlace»
   ========================================================================= */

/* Más ancha que el resto de modales: cada fila lleva nombre, correo, empresa
   y un botón, y a 560px el correo se parte en dos renglones. */
.modal--contactos .modal__caja { max-width: 660px; }

.contactos { display: grid; gap: 6px; margin: 14px 0 10px; }

.contacto {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  background: var(--card);
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
  padding: 11px 13px;
  transition: border-color .18s;
}

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

/* Sin acceso: se atenúa el bloque entero, no el texto suelto. Bajar solo el
   color dejaría el correo por debajo del contraste mínimo; la opacidad sobre
   el contenedor mantiene la relación interna y sigue leyéndose. */
.contacto.es-inactivo { opacity: .58; }
.contacto.es-inactivo:hover { opacity: .8; }

.contacto__check {
  width: 17px;
  height: 17px;
  margin-top: 2px;
  flex: none;
  accent-color: var(--azul);
  cursor: pointer;
}

/* Alinea las filas sin casilla con las que sí la tienen. */
.contacto__check-hueco { width: 17px; flex: none; }

.contacto__texto {
  flex: 1;
  min-width: 0;
  display: grid;
  gap: 2px;
  cursor: pointer;
}

.contacto.es-inactivo .contacto__texto { cursor: default; }

.contacto__nombre { font-size: .87rem; font-weight: 600; color: var(--texto); }

.contacto__correo {
  font-size: .79rem;
  color: var(--texto-2);
  word-break: break-all;
}

.contacto__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 7px;
  font-size: .74rem;
  color: var(--texto-2);
  margin-top: 3px;
}

.contacto__chip {
  font-size: .68rem;
  padding: 2px 7px;
  border-radius: 20px;
  background: rgba(96, 165, 250, .13);
  color: var(--azul-claro);
  border: 1px solid rgba(96, 165, 250, .2);
}

.contacto__chip--tenue {
  background: rgba(255, 255, 255, .05);
  color: var(--texto-2);
  border-color: var(--borde-fuerte);
}

.contactos__separador {
  font-size: .68rem;
  font-weight: 700;
  color: var(--texto-2);
  text-transform: uppercase;
  letter-spacing: .7px;
  margin: 10px 0 2px;
}

.contactos__pie {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  margin-bottom: 12px;
}

/* Enlace de texto sobrio: acción secundaria que no merece un botón. */
.enlace-sobrio {
  background: none;
  border: none;
  padding: 0;
  font-size: .78rem;
  color: var(--azul-claro);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.enlace-sobrio:hover { color: #93c5fd; }

/* --- Alta de contacto --- */

.alta {
  background: var(--panel, #1a2035);
  border: 1px solid var(--borde-fuerte);
  border-radius: var(--radio-sm);
  padding: 14px;
}

.alta__titulo {
  font-size: .78rem;
  font-weight: 700;
  color: var(--texto-2);
  text-transform: uppercase;
  letter-spacing: .6px;
  margin-bottom: 12px;
}

.alta__grilla {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 11px;
}

.alta__pie { display: flex; justify-content: flex-end; gap: 9px; margin-top: 13px; }

/* --- Enlace directo, al pie --- */

.enlace-directo {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--borde);
}

.enlace-directo__fila { display: flex; align-items: center; gap: 9px; }

.enlace-directo__url {
  flex: 1;
  min-width: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .73rem;
  color: var(--texto-2);
  background: rgba(255, 255, 255, .04);
  border: 1px solid var(--borde);
  border-radius: 6px;
  padding: 7px 10px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.enlace-directo__nota { font-size: .73rem; color: var(--texto-2); margin-top: 8px; }

.btn-icono.es-copiado { color: var(--verde); border-color: rgba(52, 211, 153, .4); }

@media (max-width: 560px) {
  .alta__grilla { grid-template-columns: 1fr; }

  /* El botón baja a su propia línea en vez de comprimir el texto: con los tres
     en fila, «Quitar acceso» se lleva 140px y el correo se parte a mitad de
     palabra. La base de 100%-28px es justo lo que deja libre la casilla más su
     separación, así que casilla y texto siguen compartiendo la primera línea. */
  .contacto { flex-wrap: wrap; }
  .contacto__texto { flex: 1 1 calc(100% - 28px); }
  .contacto .btn { margin-left: 28px; margin-top: 4px; }
}

/* =========================================================================
   ACCESOS — registro de ingresos a los tableros
   ========================================================================= */

.senales { display: grid; gap: 9px; margin-bottom: 18px; }

.senal {
  border: 1px solid var(--borde-fuerte);
  border-left-width: 3px;
  border-radius: var(--radio-sm);
  padding: 13px 15px;
  background: var(--card);
}

.senal--error { border-left-color: var(--rojo); }
.senal--aviso { border-left-color: var(--ambar); }

.senal__titulo { font-size: .87rem; font-weight: 600; color: var(--texto); }

.senal__lista {
  list-style: none;
  display: grid;
  gap: 4px;
  margin-top: 8px;
  font-size: .8rem;
  color: var(--texto-2);
}

.senal__lista strong { color: var(--texto); font-weight: 600; }

.senal__nota { font-size: .74rem; color: var(--texto-2); margin-top: 9px; }

/* La tabla no se comprime: a 6 columnas de ancho variable, encogerlas parte
   los correos en cuatro renglones. Se desplaza en horizontal dentro de su
   envoltura y el resto de la página no se mueve. */
.tabla-envoltura {
  overflow-x: auto;
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
  background: var(--card);
}

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

.tabla--accesos { min-width: 760px; }

.tabla thead th {
  text-align: left;
  font-size: .68rem;
  font-weight: 700;
  color: var(--texto-2);
  text-transform: uppercase;
  letter-spacing: .6px;
  padding: 11px 13px;
  border-bottom: 1px solid var(--borde-fuerte);
  white-space: nowrap;
}

.tabla tbody td {
  padding: 11px 13px;
  border-bottom: 1px solid var(--borde);
  color: var(--texto);
  vertical-align: top;
}

.tabla tbody tr:last-child td { border-bottom: none; }
.tabla tbody tr:hover { background: rgba(255, 255, 255, .02); }

/* Un rechazo no es un error del sistema: es información. Se marca con una
   banda al inicio de la fila, no tiñendo la fila entera de rojo. */
.tabla tbody tr.es-rechazado td:first-child { box-shadow: inset 3px 0 0 var(--rojo); }

.tabla__fecha { white-space: nowrap; color: var(--texto-2); }

.acceso__nombre { font-weight: 600; }
.acceso__correo { font-size: .76rem; color: var(--texto-2); margin-top: 2px; word-break: break-all; }
.acceso__detalle { font-size: .73rem; color: var(--texto-2); margin-top: 2px; }
.acceso__equipo { color: var(--texto-2); white-space: nowrap; }

.nota--pie {
  margin-top: 16px;
  padding: 13px 15px;
  background: rgba(255, 255, 255, .025);
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
}

.nota--pie strong { color: var(--texto); }

/* =========================================================================
   VERIFICACIÓN Y AVISO AL LABORATORIO
   ========================================================================= */

/* Ámbar: no es un error, es un alto. Publicar dejó el dashboard en línea, pero
   el cliente todavía no sabe nada y el correo no sale sin que alguien mire. */
.verificacion {
  background: rgba(251, 191, 36, .07);
  border: 1px solid rgba(251, 191, 36, .26);
  border-radius: var(--radio-sm);
  padding: 15px 16px;
  margin-top: 18px;
}

.verificacion__titulo {
  font-size: .87rem;
  font-weight: 600;
  color: #fcd34d;
  margin-bottom: 6px;
}

.verificacion__texto {
  font-size: .8rem;
  line-height: 1.6;
  color: var(--texto-2);
  margin-bottom: 13px;
}

.verificacion .btn { width: 100%; }

.verificacion__check {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-top: 14px;
  cursor: pointer;
  font-size: .83rem;
  line-height: 1.5;
  color: var(--texto);
  /* Las etiquetas de campo del portal van en mayúsculas; sin esto la frase
     de confirmación la hereda y queda gritada. */
  text-transform: none;
  font-weight: 400;
}

.verificacion__check input {
  width: 17px;
  height: 17px;
  margin-top: 1px;
  flex: none;
  accent-color: var(--ambar);
  cursor: pointer;
}

.verificacion__sello {
  font-size: .74rem;
  color: var(--texto-2);
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid rgba(251, 191, 36, .18);
}

/* Confirmada, el bloque baja el tono: ya cumplió su función de frenar. */
.verificacion.es-lista {
  background: rgba(52, 211, 153, .06);
  border-color: rgba(52, 211, 153, .24);
}
.verificacion.es-lista .verificacion__titulo { color: #6ee7b7; }
.verificacion.es-lista .verificacion__sello { border-top-color: rgba(52, 211, 153, .18); }
.verificacion.es-lista .verificacion__check input { accent-color: var(--verde); }

/* --- Destinatarios --- */

.destinatarios {
  background: rgba(96, 165, 250, .07);
  border: 1px solid rgba(96, 165, 250, .22);
  border-radius: var(--radio-sm);
  padding: 14px 16px;
  margin-top: 10px;
}

.destinatarios--vacio {
  background: rgba(255, 255, 255, .03);
  border-color: var(--borde-fuerte);
}

.destinatarios--hecho {
  background: rgba(52, 211, 153, .07);
  border-color: rgba(52, 211, 153, .22);
  margin-top: 18px;
}

.destinatarios__titulo {
  font-size: .7rem;
  font-weight: 700;
  color: var(--texto-2);
  text-transform: uppercase;
  letter-spacing: .7px;
  margin-bottom: 10px;
}

.destinatarios__texto { font-size: .81rem; color: var(--texto-2); line-height: 1.55; }
.destinatarios__texto + .enlace-sobrio { margin-top: 8px; display: inline-block; }

.destinatarios__lista { list-style: none; display: grid; gap: 7px; }

.destinatarios__lista li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 9px;
  font-size: .82rem;
}

.destinatarios__nombre { font-weight: 600; color: var(--texto); }
.destinatarios__correo { color: var(--texto-2); font-size: .78rem; word-break: break-all; }

.nota--correccion { margin-top: 12px; text-align: center; }
.nota--correccion .enlace-sobrio { font-size: .74rem; }

/* --- Cima de la pantalla de publicación --- */

/* El cuerpo dejó de ir centrado: abajo hay listas y casillas, que centradas
   son ilegibles. Solo la confirmación de arriba conserva el centrado. */
.publicado__cima { text-align: center; }
.publicado__cima .marca-resultado { margin-left: auto; margin-right: auto; }

/* --- Modal autónomo de aviso --- */

.modal--aviso .modal__caja { max-width: 560px; }

.aviso__contexto {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 12px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--borde);
}

.aviso__periodo { font-size: .95rem; font-weight: 600; color: var(--texto); }
.aviso__meta { font-size: .78rem; color: var(--texto-2); }

/* --- Pendiente en la fila del laboratorio --- */

.pendiente-aviso {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 9px;
  margin-top: 14px;
  padding: 10px 13px;
  background: rgba(251, 191, 36, .08);
  border: 1px solid rgba(251, 191, 36, .24);
  border-radius: var(--radio-sm);
}

.pendiente-aviso__punto {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--ambar);
  flex: none;
  box-shadow: 0 0 0 3px rgba(251, 191, 36, .16);
}

.pendiente-aviso__texto { flex: 1; min-width: 0; font-size: .82rem; color: #fcd34d; }

/* --- Pendiente en el historial --- */

/* Franja al costado, sin teñir la fila: la carga está bien publicada y pintar
   el renglón entero la haría parecer un problema. */
.carga.es-falta-avisar { box-shadow: inset 3px 0 0 var(--ambar); }

@media (max-width: 560px) {
  .pendiente-aviso__texto { flex-basis: 100%; }
  .pendiente-aviso .btn { margin-left: 16px; }
}

/* --- Aviso enviado con errores --- */

/* Rojo, no ámbar: ámbar es «falta hacerlo», y esto ya se hizo y salió mal.
   Distinguirlos importa porque la acción es distinta — uno se avisa, el otro
   se reintenta con los que faltan. */
.destinatarios--parcial {
  background: rgba(248, 113, 113, .06);
  border-color: rgba(248, 113, 113, .2);
  margin-top: 18px;
}

.destinatarios--fallo {
  background: rgba(248, 113, 113, .08);
  border-color: rgba(248, 113, 113, .26);
}

.destinatarios--fallo .destinatarios__titulo { color: #fca5a5; }

.destinatarios--fallo .destinatarios__lista li { display: grid; gap: 1px; }

.destinatarios__motivo { font-size: .74rem; color: #fca5a5; }

.destinatarios--fallo .destinatarios__texto { margin-top: 11px; }

.pendiente-aviso.es-con-errores {
  background: rgba(248, 113, 113, .08);
  border-color: rgba(248, 113, 113, .26);
}
.pendiente-aviso.es-con-errores .pendiente-aviso__punto {
  background: var(--rojo);
  box-shadow: 0 0 0 3px rgba(248, 113, 113, .16);
}
.pendiente-aviso.es-con-errores .pendiente-aviso__texto { color: #fca5a5; }

.carga.es-aviso-con-errores { box-shadow: inset 3px 0 0 var(--rojo); }

/* --- Rebotes en el detalle del historial --- */

.rebotes {
  margin-top: 13px;
  padding: 13px 15px;
  background: rgba(248, 113, 113, .07);
  border: 1px solid rgba(248, 113, 113, .22);
  border-radius: var(--radio-sm);
}

.rebotes__titulo { font-size: .83rem; font-weight: 600; color: #fca5a5; margin-bottom: 9px; }

.rebotes__lista { list-style: none; display: grid; gap: 8px; }
.rebotes__lista li { display: grid; gap: 1px; }

.rebotes__quien { font-size: .82rem; font-weight: 600; color: var(--texto); }
.rebotes__correo { font-size: .76rem; color: var(--texto-2); word-break: break-all; }
.rebotes__motivo { font-size: .74rem; color: #fca5a5; }

/* Enlace dentro de un aviso: solo aparece cuando el navegador bloqueó la
   ventana y hay que ofrecer el destino para abrirlo a mano. */
.toast__enlace {
  color: #bfdbfe;
  text-decoration: underline;
  text-underline-offset: 2px;
  font-weight: 600;
}
.toast__enlace:hover { color: #fff; }

/* Accesos del equipo: franja azul al costado. No es un estado excepcional,
   solo una población distinta de la del cliente, y conviene poder separarlas
   de un vistazo sin leer cada nombre. */
.tabla tbody tr.es-interno td:first-child { box-shadow: inset 3px 0 0 var(--azul-claro); }
