/* ===========================================================================
   public/css/base.css
   Reset, estilos globales del documento y clases utilitarias.

   Parte 2 de 12 de la hoja de estilos. El orden de carga IMPORTA:
   se enlazan en este mismo orden desde index.html y dashboard.html.
   =========================================================================== */
/* ===== 2. BASE RESET & GLOBAL ===== */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html { font-size: 16px; scroll-behavior: smooth; }

body {
  font-family: 'Segoe UI', system-ui, -apple-system, 'Helvetica Neue', Arial, sans-serif;
  background: var(--bg-deep);
  color: var(--text-primary);
  line-height: 1.6;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--clr-blue); text-decoration: none; }
a:hover { text-decoration: underline; }

ul, ol { list-style: none; }

img { max-width: 100%; display: block; }

:focus-visible {
  outline: 2px solid var(--clr-green);
  outline-offset: 2px;
}

/* Custom scrollbar */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: var(--bg-surface); }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }

/* ===== 3. UTILITY ===== */
.hidden   { display: none !important; }
.sr-only  { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0); }
.truncate { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.text-sm  { font-size: .875rem; }
.text-xs  { font-size: .75rem; }
.text-muted { color: var(--text-muted); }
.fw-600   { font-weight: 600; }
.mt-1     { margin-top: .5rem; }
.mt-2     { margin-top: 1rem; }
.gap-1    { gap: .5rem; }
.flex     { display: flex; }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }

/* ── Utilidades agregadas al sacar los estilos inline del JavaScript ──────────
   Habia 274 atributos style="" repartidos por los archivos .js. El problema no
   era la prolijidad: un estilo inline GANA sobre cualquier regla del CSS, asi
   que mientras estuvieran ahi no se podia cambiar el aspecto de la aplicacion
   desde la hoja de estilos — habia que ir archivo por archivo del JavaScript.

   Estas clases salen de contar cuales se repetian mas. Los valores son los
   mismos que tenian inline, para que el cambio sea invisible. */
.mb-1     { margin-bottom: .5rem; }
.mb-2     { margin-bottom: 1rem; }
.mt-3     { margin-top: 1.5rem; }
.gap-2    { gap: .75rem; }
.flex-wrap { flex-wrap: wrap; }
.justify-end { justify-content: flex-end; }

/* Colores de texto. Eran el grupo mas repetido de estilos inline: un
   style="color:var(--clr-green);" suelto, veintitantas veces. Ya usaban el
   token, asi que el color no cambia — lo que cambia es que ahora una regla del
   CSS puede alcanzarlos. */
.text-secondary { color: var(--text-secondary); }
.text-green     { color: var(--clr-green);  }
.text-amber     { color: var(--clr-amber);  }
.text-orange    { color: var(--clr-orange); }
.text-red       { color: var(--clr-red);    }
.text-blue      { color: var(--clr-blue);   }
.text-violet    { color: var(--clr-violet); }

.text-center { text-align: center; }
.m-0  { margin: 0; }
.ml-1 { margin-left: .5rem; }

/* El boton que se alinea con el pie de los campos en una barra de filtros.
   Los <label> empujan los <input> hacia abajo; sin esto el boton queda flotando
   a la altura de las etiquetas. */
.filter-action { align-self: flex-end; }

/* Anchos minimos de los <select> y <input> de las barras de filtro. Estaban
   como min-width sueltos con cinco valores distintos; se redujeron a tres. */
.fc-narrow { min-width: 140px; }
.fc-medium { min-width: 165px; }
.fc-wide   { min-width: 210px; }

/* ===== ACCESIBILIDAD: MOVIMIENTO REDUCIDO =====
   Quien configuró su sistema para reducir el movimiento (mareo, vértigo,
   trastornos vestibulares) recibe la interfaz sin animaciones. No se apagan del
   todo con `animation: none` porque hay spinners cuya ausencia se leería como
   "se colgó": se dejan casi instantáneas en su lugar. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Espaciados finos que no entran en la escala .mt-1/.mt-2/.mt-3 (medio, uno y
   uno y medio). Se usan donde el aire tiene que ser menor que medio renglón:
   el pie de un bloque de datos, un comentario debajo de su rótulo. */
.mt-025 { margin-top: .25rem; }
.fst-italic { font-style: italic; }

/* Utilidades que aparecieron al migrar los últimos paneles. */
.ml-025      { margin-left: .25rem; }
.mt-04       { margin-top: .4rem; }
.items-end   { align-items: flex-end; }
.gap-3       { gap: 1rem; }
.nowrap      { white-space: nowrap; }
.inline-flex-gap { display: inline-flex; align-items: center; gap: .35rem; }
/* Un campo que se queda con el espacio sobrante de su fila. El min-width:0 es
   lo que le permite ACHICARSE: sin él, un <select> con una opción larga se
   niega a bajar de su ancho natural y desborda la fila. */
.fg-crece     { flex: 1; min-width: 0; }
.fg-crece-min { flex: 1; min-width: 150px; }
.fg-doble-min160 { flex: 2; min-width: 160px; margin: 0; }
.fg-120 { width: 120px; }
.fg-130 { width: 130px; margin: 0; }

/* ── Saltar al contenido ─────────────────────────────────────────────────────
   El primer elemento enfocable del dashboard, oculto hasta que alguien navega
   con teclado. Ver el comentario en dashboard.html para el por que.

   La tecnica: se lo manda ARRIBA de la pantalla (top:-100%) en vez de usar
   display:none o visibility:hidden. Esos dos lo sacarian del recorrido de Tab
   por completo — quedaria escrito en el HTML y nunca alcanzable, que es justo
   lo unico que tenia que hacer.

   Al recibir foco baja a la vista. Sin esa regla el foco se iria a un elemento
   fuera de pantalla y la persona no sabria donde esta parada: peor que no
   tener el enlace.

   z-index alto porque la barra superior es fija y lo taparia. */
.skip-link {
  position: fixed;
  top: -100%;
  left: 1rem;
  z-index: 1000;
  padding: .6rem 1.1rem;
  border-radius: 0 0 var(--radius-md) var(--radius-md);
  background: var(--clr-orange);
  color: var(--clr-white);
  font-size: .9rem;
  font-weight: 600;
  text-decoration: none;
  box-shadow: var(--shadow-md);
  /* La transicion es solo del desplazamiento: aparece deslizandose desde
     arriba, que es de donde viene. */
  transition: top .15s ease;
}

.skip-link:focus {
  top: 0;
  /* El contorno propio del navegador sobre naranja pleno casi no se ve; este
     halo blanco lo hace inconfundible. */
  outline: 2px solid var(--clr-white);
  outline-offset: -4px;
}
