/* web/static/estilo.css
 *
 * Hoja de estilo unica de Radar Aferioja (F1.6, hallazgo "el sitio tiene
 * CSS cero"). Sin frameworks, sin build step, sin fuentes web (pila de
 * fuentes de sistema): un solo fichero, servido tal cual desde
 * `/static/estilo.css` (ver `web/app/main.py::static_file`).
 *
 * Guia de diseno: sitio de interes publico sobre fiabilidad ferroviaria,
 * NO una landing de startup ni el sitio de una operadora. Sobrio,
 * legible, denso-pero-respirable. Paleta azul/gris pizarra elegida a
 * proposito lejos de los colores corporativos de Renfe (rojo), Ouigo
 * (magenta) e Iryo (frambuesa) -- CLAUDE.md §7, obligacion 4: nunca debe
 * sugerir patrocinio o afiliacion con ninguna operadora.
 *
 * WCAG AA (requisito de entrada, no un extra -- estandar del propietario):
 * ratios de contraste calculados a mano con la formula de luminancia
 * relativa de WCAG 2.x (no asumidos), reproducibles con cualquier
 * calculadora de contraste:
 *
 *   texto normal, minimo exigido 4.5:1
 *     --color-text        sobre --color-bg        = 15.62:1
 *     --color-text        sobre --color-bg-muted   = 13.79:1
 *     --color-text-muted  sobre --color-bg        =  7.56:1
 *     --color-text-muted  sobre --color-bg-muted   =  6.67:1
 *     --color-link        sobre --color-bg        =  8.00:1
 *     --color-link        sobre --color-bg-muted   =  7.06:1
 *     --color-link-visited sobre --color-bg       = 10.18:1
 *     blanco (texto de boton) sobre --color-link   =  8.00:1
 *
 *   componentes UI / texto grande, minimo exigido 3:1
 *     --color-border      sobre --color-bg        =  5.93:1
 *     --color-border      sobre --color-bg-muted   =  5.24:1
 *     --color-focus       sobre --color-bg        =  5.76:1
 *     --color-focus       sobre --color-bg-muted   =  5.08:1
 *
 * --color-border-subtle NO se usa nunca como unico portador de
 * informacion (siempre acompaña a --color-border en la fila de
 * cabecera, o al padding/zebra de una tabla) -- decorativo a proposito,
 * exento del 3:1 por la misma razon que exime WCAG 1.4.11 a los
 * elementos puramente decorativos.
 */

:root {
  --color-bg: #ffffff;
  --color-bg-muted: #eef1f5;
  --color-text: #1c2430;
  --color-text-muted: #4b5563;
  --color-link: #0b4ea2;
  --color-link-visited: #0a3f85;
  --color-border: #5a6572;
  --color-border-subtle: #d7dce2;
  --color-focus: #a34e00;

  /* D-042 (rediseño F1.6): escala de magnitud del indicador de
     puntualidad (generator/indicator.py) -- CUATRO pasos fijos, NUNCA
     reutilizados como "serie" en ningun otro contexto (paleta reservada,
     skill dataviz). Se usan EXCLUSIVAMENTE como relleno de un objeto
     grafico no textual (WCAG 1.4.11, contraste >=3:1 frente a fondo) --
     el texto (cifra + etiqueta) nunca lleva estos colores, ver
     ".indicador-puntualidad__cifra/__etiqueta" mas abajo. Deliberadamente
     alejados del rojo/magenta corporativos de Renfe/Ouigo/Iryo (CLAUDE.md
     §7 obligacion 4): tonos oscuros/desaturados, no el rojo vivo tipico
     de una marca de operadora. Ratios de contraste verificados a mano
     (formula de luminancia relativa WCAG 2.x, igual criterio que el
     resto de esta cabecera):

       objeto grafico, minimo exigido 3:1
         --sev-alta     (#146c2e) sobre --color-bg        = 6.53:1
         --sev-alta     (#146c2e) sobre --color-bg-muted   = 5.77:1
         --sev-media    (#8a5a00) sobre --color-bg        = 5.93:1
         --sev-media    (#8a5a00) sobre --color-bg-muted   = 5.23:1
         --sev-baja     (#a3491c) sobre --color-bg        = 5.95:1
         --sev-baja     (#a3491c) sobre --color-bg-muted   = 5.26:1
         --sev-muy-baja (#9c2b2b) sobre --color-bg        = 7.52:1
         --sev-muy-baja (#9c2b2b) sobre --color-bg-muted   = 6.63:1

     Los cuatro superan tambien el 4,5:1 de texto normal (margen para el
     futuro), aunque este proyecto nunca los usa como color de texto. */
  --sev-alta: #146c2e;
  --sev-media: #8a5a00;
  --sev-baja: #a3491c;
  --sev-muy-baja: #9c2b2b;

  --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;

  /* Medida comoda de lectura (prosa), independiente del ancho del
     contenedor -- las tablas/pre NO se acotan a esta medida, necesitan
     su propio ancho para seguir siendo legibles. */
  --measure: 68ch;
  --container-width: 60rem;

  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2.5rem;

  --radius: 0.25rem;
}

/* ---------------------------------------------------------------------
 * Reset minimo + base
 * --------------------------------------------------------------------- */

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

html {
  font-size: 100%; /* respeta el tamaño de fuente del navegador (WCAG 1.4.4) */
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-sans);
  font-size: 1rem;
  line-height: 1.6;
}

/* Ningun elemento (tabla ancha, imagen, bloque pre) debe poder forzar
   scroll horizontal de la PAGINA -- cada uno gestiona su propio overflow
   mas abajo. Mobile-first: valido desde 320px. */
img {
  max-width: 100%;
  height: auto;
}

/* ---------------------------------------------------------------------
 * Buscador cliente (D-042, rediseño F1.6): landmark propio, ANTES del
 * <nav> en el marcado (base.html) -- "search-first". Mismo fondo que el
 * nav (--color-bg-muted) para que ambos se lean como una franja superior
 * coherente, con un borde propio que los separa visualmente sin repetir
 * el mismo tono de borde que ya usa el nav debajo.
 * --------------------------------------------------------------------- */

.buscador {
  width: 100%;
  background: var(--color-bg-muted);
  border-bottom: 1px solid var(--color-border);
  padding: var(--space-3) var(--space-4);
}

/* Cada hijo directo se centra y se acota a --container-width por
   separado (mismo criterio que ya usa "nav ul" mas abajo) -- mas simple
   que envolver el contenido en un <div> nuevo que la plantilla no tiene. */
.buscador > * {
  max-width: var(--container-width);
  margin-inline: auto;
}

.buscador > label {
  display: block;
  font-weight: 600;
  font-size: 0.9375rem;
  margin-bottom: var(--space-1);
}

.buscador > input[type="search"] {
  display: block;
  width: 100%;
}

.buscador__estado {
  margin-top: var(--space-2);
  min-height: 1.5em;
  color: var(--color-text-muted);
  font-size: 0.875rem;
}

.buscador__resultados {
  list-style: none;
  margin-top: var(--space-1);
  padding: 0;
}

.buscador__resultados li {
  margin: 0;
  padding: var(--space-1) 0;
  border-bottom: 1px solid var(--color-border-subtle);
}

.buscador__resultados li:last-child {
  border-bottom: none;
}

.buscador__tipo {
  color: var(--color-text-muted);
  font-size: 0.8125rem;
}

/* ---------------------------------------------------------------------
 * Landmarks: nav/main/footer.
 *
 * D-041: nav real del modulo, presente en TODA pagina (ver base.html).
 * Mobile-first sin menu JS -- un <ul> que hace wrap con flex-wrap ya es
 * usable a 320px sin ninguna hamburguesa ni <script> (evita ademas tener
 * que anadir un hash nuevo a script-src en la CSP, web/app/
 * security_headers.py). El foco visible ya lo cubre la regla generica
 * `a:focus` de mas abajo -- no hace falta ninguna regla de foco propia
 * para los enlaces del nav.
 * --------------------------------------------------------------------- */

nav[aria-label="Navegación principal"] {
  width: 100%;
  background: var(--color-bg-muted);
  border-bottom: 1px solid var(--color-border-subtle);
}

nav[aria-label="Navegación principal"] ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-4);
  list-style: none;
  max-width: var(--container-width);
  margin: 0 auto;
  padding: var(--space-3) var(--space-4);
}

nav[aria-label="Navegación principal"] li {
  margin: 0;
}

nav[aria-label="Navegación principal"] a {
  display: inline-block;
  padding: var(--space-1) 0;
  font-size: 0.9375rem;
  font-weight: 600;
  text-decoration: none;
}

nav[aria-label="Navegación principal"] a:hover {
  text-decoration: underline;
  text-decoration-thickness: 2px;
}

main {
  flex: 1 0 auto;
  width: 100%;
  max-width: var(--container-width);
  margin-inline: auto;
  padding: var(--space-5) var(--space-4) var(--space-6);
}

footer {
  flex-shrink: 0;
  width: 100%;
  max-width: var(--container-width);
  margin-inline: auto;
  padding: var(--space-4);
  border-top: 1px solid var(--color-border-subtle);
  color: var(--color-text-muted);
  font-size: 0.875rem;
  line-height: 1.5;
}

footer p {
  max-width: var(--measure);
  margin: 0;
}

/* ---------------------------------------------------------------------
 * Tipografia: jerarquia clara de titulares, medida comoda en prosa
 * --------------------------------------------------------------------- */

h1, h2, h3 {
  color: var(--color-text);
  font-weight: 700;
  line-height: 1.25;
  max-width: var(--measure);
}

h1 {
  font-size: clamp(1.5rem, 1.2rem + 1.2vw, 2.25rem);
  margin: 0 0 var(--space-4);
}

h2 {
  font-size: 1.375rem;
  margin: var(--space-6) 0 var(--space-3);
}

h3 {
  font-size: 1.125rem;
  margin: var(--space-5) 0 var(--space-2);
}

p, li {
  max-width: var(--measure);
}

p {
  margin: 0 0 var(--space-4);
}

ul, ol {
  margin: 0 0 var(--space-4);
  padding-left: 1.25em;
}

li {
  margin-bottom: var(--space-2);
}

/* bloque de cita/nota (usado por el <noscript> de /estado/, ver mas
   abajo) -- separado aqui por si algun dia se reutiliza. */
strong {
  font-weight: 700;
}

/* ---------------------------------------------------------------------
 * Enlaces y foco visible en TODO elemento interactivo (requisito de
 * entrada, no un extra). Un solo anillo de foco, sin :focus-visible:
 * se prefiere el selector simple y universalmente soportado antes que
 * arriesgar que un navegador antiguo descarte la regla entera por una
 * pseudo-clase que no entiende.
 * --------------------------------------------------------------------- */

a {
  color: var(--color-link);
  text-underline-offset: 0.15em;
}

a:visited {
  color: var(--color-link-visited);
}

a:hover {
  text-decoration-thickness: 2px;
}

a:focus,
button:focus,
input:focus,
select:focus,
[tabindex]:focus {
  outline: 3px solid var(--color-focus);
  outline-offset: 2px;
}

/* ---------------------------------------------------------------------
 * Tablas: los hubs de familia, la de frescura de feeds y el podio de
 * /estado/, las de /ranking/ y /corredores/av/, y las de umbrales
 * verificados de /reclamar/.
 *
 * El scroll horizontal vive en un ENVOLTORIO, no en el <table> (hallazgo
 * I1 de la auditoria pre-produccion). La version anterior ponia
 * `display: block; overflow-x: auto` en la propia tabla para no tocar
 * las plantillas: resolvia el layout por debajo de 320px y creaba un
 * fallo WCAG 2.1.1 (Teclado, nivel A) -- un contenedor scrollable sin
 * `tabindex` no esta en el orden de tabulacion, asi que a 375px sobre
 * /linea/ habia 698px (67% del ancho) inalcanzables sin raton: todas las
 * columnas de dato. La correccion exige el marcado que aquel comentario
 * habia descartado: `<div class="tabla-scroll" role="region"
 * tabindex="0" aria-label="...">`.
 *
 * `tabindex="0"` es incondicional, tambien cuando la tabla cabe entera y
 * no hay nada que desplazar. Aplicarlo solo al desbordar exigiria JS
 * (medir `scrollWidth` vs `clientWidth` en cada resize) y, con
 * `script-src 'self'` sin 'unsafe-inline', un fichero mas y su
 * mantenimiento -- a cambio de ahorrar una parada de tabulacion
 * anunciada con su nombre. Se prefiere la parada de mas: el coste es un
 * tab, el del fallo es dato inalcanzable.
 * --------------------------------------------------------------------- */

.tabla-scroll {
  overflow-x: auto;
  /* Sin esto, el anillo de foco de `[tabindex]:focus` se recortaria
     contra el borde del propio contenedor que desborda. */
  padding: 1px;
  margin: 0 0 var(--space-5);
}

table {
  width: 100%;
  /* El margen inferior lo lleva ahora `.tabla-scroll` (el elemento que
     de verdad ocupa el flujo); dejarlo tambien aqui lo duplicaria. */
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius);
  /* Al recuperar `display: table` (antes era `block`), las celdas
     vuelven a separarse por defecto: `collapse` conserva el aspecto de
     rejilla continua que ya tenia el diseno D-042. */
  border-collapse: collapse;
  font-size: 0.9375rem;
  /* Digitos de ancho fijo: ayuda a comparar cifras en una misma columna
     de un vistazo, sin necesitar saber que columnas son numericas. */
  font-variant-numeric: tabular-nums;
}

caption {
  text-align: left;
  font-weight: 600;
  color: var(--color-text-muted);
  padding: var(--space-2) var(--space-3) 0;
}

th, td {
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--color-border-subtle);
  text-align: left;
  white-space: nowrap;
}

thead th {
  background: var(--color-bg-muted);
  border-bottom: 2px solid var(--color-border);
  font-weight: 700;
}

tbody tr:last-child td {
  border-bottom: none;
}

tbody tr:nth-child(even) {
  background: var(--color-bg-muted);
}

/* ---------------------------------------------------------------------
 * Bloques de datos (<pre>{{ stats }}</pre> en linea/estacion/tren/
 * trayecto/nucleo): distincion obvia frente a la prosa que los rodea --
 * fondo propio, fuente monoespaciada de sistema, nunca confundible con
 * un parrafo.
 * --------------------------------------------------------------------- */

pre {
  background: var(--color-bg-muted);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius);
  padding: var(--space-4);
  margin: 0 0 var(--space-5);
  overflow-x: auto;
  white-space: pre-wrap;
  overflow-wrap: break-word;
  font-family: var(--font-mono);
  font-size: 0.9375rem;
  line-height: 1.7;
  font-variant-numeric: tabular-nums;
}

code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  background: var(--color-bg-muted);
  padding: 0.1em 0.35em;
  border-radius: 0.2em;
}

pre code {
  background: none;
  padding: 0;
}

/* ---------------------------------------------------------------------
 * Indicador de puntualidad (D-042, rediseño F1.6): barra + cifra +
 * etiqueta, generado por `generator/indicator.py::render_punctuality_
 * indicator` -- HTML identico byte a byte para el mismo dato (Regla 94),
 * el color viene SIEMPRE de la clase de nivel, nunca de un atributo
 * style/fill inline (bloqueado por la CSP del proyecto, ver el docstring
 * de ese modulo). Reutilizado tal cual en dos contextos: el bloque de
 * resumen de una ficha (tamano "grande", mas abajo) y una celda de la
 * tabla de un hub (tamano "compacto", generator/hubs.py).
 *
 * WCAG 1.4.1 ("nunca solo color"): el color vive UNICAMENTE en
 * ".indicador-puntualidad__relleno" (el SVG, marcado aria-hidden -- es
 * decorativo, la informacion real esta en el texto que lo acompaña). La
 * cifra (<strong>) y la etiqueta (<span>) usan los tokens de texto del
 * sitio (--color-text/--color-text-muted), NUNCA el color de nivel --
 * "el texto nunca lleva el color del dato" (skill dataviz,
 * marks-and-anatomy.md).
 * --------------------------------------------------------------------- */

.indicador-puntualidad {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  max-width: 100%;
}

.indicador-puntualidad--vacio {
  color: var(--color-text-muted);
  font-size: 0.9375rem;
  font-style: italic;
}

.indicador-puntualidad__barra {
  flex-shrink: 0;
  display: block;
  border-radius: var(--radius);
}

.indicador-puntualidad--grande .indicador-puntualidad__barra {
  width: 8rem;
  height: 0.875rem;
}

.indicador-puntualidad--compacto .indicador-puntualidad__barra {
  width: 4.5rem;
  height: 0.625rem;
}

/* La pista (fondo del carril) es decorativa -- igual que
   --color-border-subtle en el resto del fichero, nunca el unico
   portador de informacion (esa es la barra rellena). */
.indicador-puntualidad__pista {
  fill: var(--color-border-subtle);
}

.indicador-puntualidad--alta .indicador-puntualidad__relleno {
  fill: var(--sev-alta);
}

.indicador-puntualidad--media .indicador-puntualidad__relleno {
  fill: var(--sev-media);
}

.indicador-puntualidad--baja .indicador-puntualidad__relleno {
  fill: var(--sev-baja);
}

.indicador-puntualidad--muy-baja .indicador-puntualidad__relleno {
  fill: var(--sev-muy-baja);
}

.indicador-puntualidad__cifra {
  flex-shrink: 0;
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
}

.indicador-puntualidad--grande .indicador-puntualidad__cifra {
  font-size: 1.375rem;
}

.indicador-puntualidad--compacto .indicador-puntualidad__cifra {
  font-size: 1rem;
}

.indicador-puntualidad__etiqueta {
  color: var(--color-text-muted);
  font-size: 0.8125rem;
  line-height: 1.3;
}

/* ---------------------------------------------------------------------
 * Bloque de resumen de ficha (D-042, rediseño F1.6): indicador + cifras
 * clave arriba de la prosa -- "lead with the numbers, then the prose,
 * then the detail table" del encargo. Mismo fondo/borde que el resto de
 * bloques destacados del sitio (dl[data-estado-cobertura], noscript),
 * nunca un componente visual nuevo sin precedente en la hoja.
 * --------------------------------------------------------------------- */

.ficha-resumen {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-5);
  margin: 0 0 var(--space-5);
  padding: var(--space-4);
  background: var(--color-bg-muted);
  border-radius: var(--radius);
}

.ficha-resumen__cifras {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4) var(--space-5);
  margin: 0;
}

.ficha-resumen__cifras div {
  min-width: 8rem;
}

.ficha-resumen__cifras dt {
  color: var(--color-text-muted);
  font-size: 0.8125rem;
}

.ficha-resumen__cifras dd {
  margin: 0;
  font-weight: 700;
  font-size: 1.25rem;
  font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------
 * /estado/: cobertura en vivo (<dl data-estado-cobertura>) como par
 * etiqueta/cifra con jerarquia numerica clara -- cuadricula de 2
 * columnas (etiqueta | cifra) sin envoltorio nuevo, apoyada en el orden
 * dt/dd ya presente en la plantilla.
 * --------------------------------------------------------------------- */

section[aria-live] {
  margin-top: var(--space-5);
}

table[data-estado-feeds] {
  margin-top: var(--space-4);
}

dl[data-estado-cobertura] {
  display: grid;
  grid-template-columns: max-content 1fr;
  column-gap: var(--space-4);
  row-gap: var(--space-2);
  align-items: baseline;
  max-width: 24rem;
  margin: var(--space-4) 0 var(--space-5);
  padding: var(--space-4);
  background: var(--color-bg-muted);
  border-radius: var(--radius);
}

dl[data-estado-cobertura] dt {
  color: var(--color-text-muted);
  font-size: 0.875rem;
}

dl[data-estado-cobertura] dd {
  margin: 0;
  font-weight: 700;
  font-size: 1.25rem;
  font-variant-numeric: tabular-nums;
}

p[data-estado-atribucion] {
  color: var(--color-text-muted);
  font-size: 0.875rem;
  max-width: var(--measure);
}

/* ---------------------------------------------------------------------
 * Aviso <noscript> (/estado/): debe leerse como una nota, no como texto
 * de cuerpo corriente -- franja lateral + fondo propio.
 * --------------------------------------------------------------------- */

noscript {
  display: block;
  background: var(--color-bg-muted);
  border-left: 4px solid var(--color-border);
  padding: var(--space-3) var(--space-4);
  margin: 0 0 var(--space-4);
}

noscript p {
  margin: 0;
}

/* ---------------------------------------------------------------------
 * Formularios (calculadora de elegibilidad en /reclamar/): unico sitio
 * del modulo con <input>/<select>/<button>.
 * --------------------------------------------------------------------- */

label {
  display: block;
  font-weight: 600;
  margin-bottom: var(--space-1);
}

input, select, button {
  font: inherit;
  color: var(--color-text);
}

input[type="number"],
input[type="search"],
select {
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: var(--space-2) var(--space-3);
  max-width: 100%;
}

/* D-042 (rediseño F1.6): quitar el aspecto nativo de "x para borrar" +
   lupa que algunos motores (WebKit/Blink) dibujan sobre input[type=search]
   -- con el look ya unificado de arriba (fondo/borde/radio propios), el
   decorado nativo desentonaba y duplicaba la propia etiqueta del campo. */
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
  appearance: none;
}

button {
  display: inline-block;
  background: var(--color-link);
  color: #ffffff;
  border: none;
  border-radius: var(--radius);
  padding: var(--space-2) var(--space-4);
  margin-top: var(--space-2);
  font-weight: 600;
  cursor: pointer;
}

button:hover {
  background: var(--color-link-visited);
}

[role="status"] {
  margin-top: var(--space-3);
  font-weight: 600;
  max-width: var(--measure);
}

/* ---------------------------------------------------------------------
 * Breakpoints -- mobile-first desde 320px, un unico salto a pantallas
 * mas anchas (YAGNI: no se añaden mas niveles sin necesidad real).
 * --------------------------------------------------------------------- */

@media (min-width: 640px) {
  main {
    padding-inline: var(--space-6);
  }

  dl[data-estado-cobertura] {
    grid-template-columns: max-content 1fr max-content 1fr;
  }
}

/* ---------------------------------------------------------------------
 * prefers-reduced-motion: red de seguridad explicita -- este fichero no
 * define animaciones propias, pero cualquier transicion que el
 * navegador aplique por su cuenta (o que se añada aqui en el futuro)
 * queda anulada para quien lo pida.
 * --------------------------------------------------------------------- */

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