/*
 * Capa base y componentes del sistema visual de EPA 360.
 *
 * NO HAY UN SOLO VALOR LITERAL DE COLOR, TAMAÑO DE LETRA NI RADIO EN ESTE
 * ARCHIVO: todo sale de `tokens.css` con `var(--…)`, y
 * `test/integration/sistema_visual_test.rb` lo verifica. Un color nuevo se
 * agrega en `DESIGN.md`, se espeja en `tokens.css` y recién entonces se usa acá.
 *
 * Propshaft sirve el CSS tal cual: no hay compilador, no hay `@import` (no los
 * reescribe con digest) y no hay framework de terceros. `tokens.css` se enlaza
 * por separado desde el layout, ANTES que esta hoja.
 *
 * Solo están implantadas las piezas que hoy tienen una pantalla detrás:
 * `tarjeta`, `campo`, `campo-error`, `boton-primario`, `boton-fantasma`, `aviso`
 * y `navegacion-operacion`. El resto del catálogo de `DESIGN.md` —`pill-estado`,
 * `tabla`, `hoja-modal`, `stepper`, `tilde`, `casillero-codigo`,
 * `cabecera-modulo`— queda en tokens disponibles y sin clase propia hasta que
 * exista la pantalla que lo use.
 */

/* ==========================================================================
   Tipografía servida desde el propio origen
   ========================================================================== */

/*
 * Quicksand es la familia exclusiva del manual de marca (§1.3), en los dos pesos
 * que la rampa usa. Se sirve desde `app/assets/fonts/` y no desde un tercero:
 * el disco del servidor es descartable y una fuente pedida a otro origen es una
 * dependencia de terceros en tiempo de ejecución, en el camino crítico de cada
 * pantalla. Son los subconjuntos `latin` de la versión SIL OFL, que cubren las
 * acentuadas y los signos de apertura del español.
 *
 * `font-display: swap` porque el texto tiene que ser legible antes de que la
 * fuente llegue: la pila de reserva de `body` es la que se ve mientras tanto.
 */
@font-face {
  font-family: "Quicksand";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/assets/quicksand-500-ae3df5cd.woff2") format("woff2");
}

@font-face {
  font-family: "Quicksand";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/assets/quicksand-700-853cb26c.woff2") format("woff2");
}

/* ==========================================================================
   Capa base
   ========================================================================== */

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

html {
  /* El zoom al 200% es condición de trabajo, no caso de laboratorio: el ajuste
     automático de tamaño de iOS al rotar pelea con eso. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100vh;
  background-color: var(--color-fondo);
  color: var(--color-tinta);
  font-family: var(--tipo-cuerpo-familia), "Trebuchet MS", "Segoe UI", system-ui, sans-serif;
  font-size: var(--tipo-cuerpo-tamano);
  font-weight: var(--tipo-cuerpo-peso);
  line-height: var(--tipo-cuerpo-interlinea);
}

/* La rampa de encabezados es la del nivel semántico, no la del tamaño que
   quede bien: `h1` es el título de la pantalla y hay uno solo. */
h1 {
  margin: 0 0 var(--espacio-4);
  font-size: var(--tipo-titulo-tamano);
  font-weight: var(--tipo-titulo-peso);
  line-height: var(--tipo-titulo-interlinea);
  letter-spacing: var(--tipo-titulo-espaciado);
}

h2 {
  margin: 0 0 var(--espacio-3);
  font-size: var(--tipo-titulo-sm-tamano);
  font-weight: var(--tipo-titulo-sm-peso);
  line-height: var(--tipo-titulo-sm-interlinea);
}

h3 {
  margin: 0 0 var(--espacio-2);
  font-size: var(--tipo-seccion-tamano);
  font-weight: var(--tipo-seccion-peso);
  line-height: var(--tipo-seccion-interlinea);
}

p {
  margin: 0 0 var(--espacio-3);
}

p:last-child {
  margin-bottom: 0;
}

a {
  color: var(--color-naranja-oscuro);
}

/* Los controles no heredan la tipografía del documento por su cuenta. */
input,
button,
select,
textarea {
  font: inherit;
  color: inherit;
}

/* ==========================================================================
   Foco — pieza heredada, nunca suprimida
   ========================================================================== */

/*
 * `foco` no es un atributo de `campo`: TODO elemento interactivo lo hereda, y
 * por eso la regla es universal y no una lista de selectores que alguien tenga
 * que acordarse de ampliar. 2px de trazo en `naranja-oscuro` con 2px de
 * separación, que mide 4.97 / 4.45 / 3.89 sobre las tres superficies del
 * sistema.
 *
 * En esta hoja no hay —ni puede haber— una supresión del anillo: la suite busca
 * `outline` puesto en nada y falla si aparece.
 */
:focus-visible {
  outline: 2px solid var(--color-naranja-oscuro);
  outline-offset: 2px;
}

/*
 * Sobre relleno oscuro el anillo se invierte a blanco: un anillo naranja sobre
 * relleno naranja mediría 1.62:1. La separación se vuelve negativa para que el
 * trazo caiga adentro del relleno, que es la única superficie contra la que el
 * blanco contrasta acá.
 */
.boton-primario:focus-visible {
  outline-color: var(--color-blanco);
  outline-offset: calc(-1 * var(--espacio-0-5));
}

/* ==========================================================================
   Piso táctil
   ========================================================================== */

/*
 * 44px de alto mínimo en todo lo que se toca, sin excepción por rango de botón.
 * Va como regla de la capa base y no componente por componente para que un
 * control nuevo nazca cumpliéndolo.
 */
a[href],
button,
summary,
select,
textarea,
input:not([type="hidden"]) {
  min-height: var(--espacio-toque-minimo);
}

/* ==========================================================================
   Movimiento reducido
   ========================================================================== */

/*
 * La superficie es casi nula —la espina prohíbe parpadeos— pero la regla se
 * declara igual, así que la primera animación que alguien agregue ya nace
 * respetándola. `none` y no una duración diminuta: lo que se pide es que no
 * quede ninguna animación ni transición corriendo, no que corran rápido.
 */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }
}

/* ==========================================================================
   Disposición
   ========================================================================== */

.contenedor {
  width: 100%;
  /* El tope de medida de lectura. No es un token del sistema visual: es una
     decisión de disposición de esta cáscara. */
  max-width: 960px;
  margin-inline: auto;
  padding-inline: var(--espacio-margen-telefono);
}

@media (min-width: 48em) {
  .contenedor {
    padding-inline: var(--espacio-margen-escritorio);
  }
}

/* El salto al contenido es el primer elemento enfocable del documento. Se
   esconde fuera de la pantalla en vez de encogerse a 1px: un control de 1px de
   alto no cumpliría el piso táctil cuando aparece. Un desplazamiento negativo
   no agranda el ancho del documento, así que no rompe el reflow a 320px. */
.salto-al-contenido {
  position: absolute;
  left: -9999px;
  top: var(--espacio-2);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  padding-inline: var(--espacio-4);
  background-color: var(--color-superficie);
  border: 1px solid var(--color-linea-fuerte);
  border-radius: var(--radio-md);
  color: var(--color-tinta);
  font-size: var(--tipo-boton-tamano);
  font-weight: var(--tipo-boton-peso);
  text-decoration: none;
}

.salto-al-contenido:focus {
  left: var(--espacio-4);
}

.cabecera-operacion {
  background-color: var(--color-superficie);
  border-bottom: 1px solid var(--color-linea);
}

.cabecera-operacion__interior {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--espacio-2);
  padding-block: var(--espacio-2);
}

/* El nombre en texto y no el isologotipo: el manual prohíbe alterar el signo
   (§1.6) y en el repositorio no hay un vectorial de la marca. Inventarlo sería
   peor que nombrarla. */
.cabecera-operacion__marca {
  margin: 0;
  color: var(--color-tinta);
  font-size: var(--tipo-titulo-sm-tamano);
  font-weight: var(--tipo-titulo-sm-peso);
  line-height: var(--tipo-titulo-sm-interlinea);
}

.disposicion-operacion {
  display: grid;
  gap: var(--espacio-6);
  padding-block: var(--espacio-6);
  align-items: start;
}

/* Lateral en escritorio, apilada en teléfono. */
@media (min-width: 48em) {
  .disposicion-operacion {
    grid-template-columns: minmax(0, 14rem) minmax(0, 1fr);
  }
}

.contenido-principal {
  min-width: 0;
}

/* Sin sesión no hay cáscara: la pantalla de ingreso se sirve con el mismo
   contenedor y nada más. */
.contenido-principal:only-child {
  padding-block: var(--espacio-6);
}

/* ==========================================================================
   Componentes
   ========================================================================== */

/* --- aviso ---------------------------------------------------------------
   El único mensaje no bloqueante del sistema. No se apila: el segundo
   reemplaza al primero, y por eso la región es una sola y vive en el layout. */
.aviso {
  margin: 0 0 var(--espacio-4);
  padding: var(--espacio-3) var(--espacio-4);
  background-color: var(--color-tinta);
  color: var(--color-blanco);
  border-radius: var(--radio-md);
  box-shadow: var(--sombra-flotante);
  font-size: var(--tipo-cuerpo-sm-tamano);
  font-weight: var(--tipo-cuerpo-sm-peso);
  line-height: var(--tipo-cuerpo-sm-interlinea);
}

/* --- tarjeta -------------------------------------------------------------
   Blanco sobre el fondo, borde de línea, sin sombra. */
.tarjeta {
  padding: var(--espacio-4);
  background-color: var(--color-superficie);
  border: 1px solid var(--color-linea);
  border-radius: var(--radio-lg);
}

/* --- campo ---------------------------------------------------------------
   Etiqueta visible siempre; el placeholder no es etiqueta. El error aparece
   junto al campo, nunca como resumen al principio de la pantalla. */
.campo {
  display: block;
  margin-bottom: var(--espacio-4);
}

/* En el rol `cuerpo` y no en `etiqueta`: §Typography asigna la etiqueta de campo
   a `cuerpo`, y 12px queda acotado a `banda-temporal` y a la cabecera de
   `tabla`. La lista de prohibiciones veta tipografía bajo 13px fuera de
   `pill-estado`, y una etiqueta de campo se lee tanto como el valor que rotula. */
.campo__etiqueta {
  display: block;
  margin-bottom: var(--espacio-1);
  color: var(--color-tinta-media);
  font-size: var(--tipo-cuerpo-tamano);
  font-weight: var(--tipo-cuerpo-peso);
  line-height: var(--tipo-cuerpo-interlinea);
}

.campo__control {
  display: block;
  width: 100%;
  padding: var(--espacio-3);
  background-color: var(--color-superficie);
  border: 1px solid var(--color-linea-fuerte);
  border-radius: var(--radio-md);
  color: var(--color-tinta);
  font-size: var(--tipo-cuerpo-tamano);
  font-weight: var(--tipo-cuerpo-peso);
  line-height: var(--tipo-cuerpo-interlinea);
}

.campo__control[aria-invalid="true"] {
  border-color: var(--color-vencido);
}

/* --- campo-error ---------------------------------------------------------
   El mensaje debajo de los campos que lo causaron, con su palabra y no solo
   con el borde rojo: el color acompaña, nunca informa solo. */
.campo-error {
  margin: 0 0 var(--espacio-4);
  color: var(--color-vencido);
  font-size: var(--tipo-cuerpo-sm-tamano);
  font-weight: var(--tipo-cuerpo-sm-peso);
  line-height: var(--tipo-cuerpo-sm-interlinea);
}

/* --- boton-primario ------------------------------------------------------
   Uno solo por pantalla: la acción que la pantalla existe para hacer. Relleno
   `naranja-oscuro` —no el institucional— porque es el que llega a 4.5:1 con
   texto blanco. */
.boton-primario {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding-inline: var(--espacio-5);
  background-color: var(--color-naranja-oscuro);
  border: 1px solid var(--color-naranja-oscuro);
  border-radius: var(--radio-md);
  color: var(--color-blanco);
  font-size: var(--tipo-boton-tamano);
  font-weight: var(--tipo-boton-peso);
  line-height: var(--tipo-boton-interlinea);
  cursor: pointer;
}

/* --- boton-fantasma ------------------------------------------------------
   Salidas y descartes. Nunca naranja: irse no es la acción que EPA promueve. */
.boton-fantasma {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding-inline: var(--espacio-3);
  background-color: transparent;
  border: none;
  border-radius: var(--radio-md);
  color: var(--color-tinta-media);
  font-size: var(--tipo-boton-tamano);
  font-weight: var(--tipo-boton-peso);
  line-height: var(--tipo-boton-interlinea);
  cursor: pointer;
  transition: background-color 120ms ease-in-out;
}

/* Un realce, no una afordancia: el control ya se ve y se lee sin pasar el
   puntero por encima. Con `prefers-reduced-motion` el cambio sigue estando y lo
   único que desaparece es el tiempo que tarda. */
.boton-fantasma:hover {
  background-color: var(--color-superficie-crema);
}

.boton-fantasma__forma {
  display: inline;
  margin: 0;
}

/* --- navegacion-operacion ------------------------------------------------
   Solo se muestra una sección cuando tiene contenido detrás: hoy es únicamente
   Inicio. La lista vive en `app/views/layouts/_navegacion.html.erb`. */
.navegacion-operacion {
  min-width: 0;
}

.navegacion-operacion__hoja {
  background-color: var(--color-superficie);
  border: 1px solid var(--color-linea);
  border-radius: var(--radio-md);
}

/* `list-item` y no `flex`: en `flex` el navegador se queda sin el triangulito
   de apertura, y la hoja pasaría a leerse como un rótulo en vez de como algo
   que se abre. La afordancia no puede depender de pasar el puntero. */
.navegacion-operacion__disparador {
  display: list-item;
  list-style-position: inside;
  padding-block: var(--espacio-3);
  padding-inline: var(--espacio-3);
  border-radius: var(--radio-md);
  color: var(--color-tinta-media);
  font-size: var(--tipo-cuerpo-sm-tamano);
  font-weight: var(--tipo-cuerpo-sm-peso);
  line-height: var(--tipo-cuerpo-sm-interlinea);
  cursor: pointer;
}

.navegacion-operacion__lista {
  margin: 0;
  padding: var(--espacio-2);
  list-style: none;
}

.navegacion-operacion__enlace {
  display: flex;
  align-items: center;
  padding-inline: var(--espacio-3);
  border-radius: var(--radio-sm);
  color: var(--color-tinta-media);
  font-size: var(--tipo-cuerpo-sm-tamano);
  font-weight: var(--tipo-cuerpo-sm-peso);
  line-height: var(--tipo-cuerpo-sm-interlinea);
  text-decoration: none;
  transition: background-color 120ms ease-in-out;
}

.navegacion-operacion__enlace:hover {
  background-color: var(--color-superficie-crema);
}

/* La sección activa se marca con fondo Y texto, no solo con color: el color
   acompaña y nunca identifica solo (NFR-16). */
.navegacion-operacion__enlace[aria-current="page"] {
  background-color: var(--color-naranja-tenue);
  color: var(--color-naranja-oscuro);
  font-weight: var(--tipo-seccion-peso);
}

/*
 * En escritorio la hoja queda abierta y su disparador desaparece: la navegación
 * es lateral y permanente. `::details-content` es lo que permite abrirla desde
 * CSS; donde el navegador todavía no lo entiende, la regla del disparador no se
 * aplica —está encerrada en el `@supports`— y la navegación sigue funcionando
 * como hoja desplegable, que es degradación y no rotura.
 */
@media (min-width: 48em) {
  .navegacion-operacion__hoja::details-content {
    content-visibility: visible;
    block-size: auto;
  }

  @supports selector(::details-content) {
    .navegacion-operacion__disparador {
      display: none;
    }
  }
}

/* --- fila-lista ----------------------------------------------------------
   La fila de una lista de datos, del catálogo de `DESIGN.md`
   (`components.fila-lista`). Se implanta recién ahora porque recién ahora hay
   una pantalla detrás: la lista de trabajos programados de Inicio.

   `min-height` en el piso táctil y no en un valor de lectura: la fila es la
   unidad que se toca en teléfono.

   Rejilla y no `flex` con `space-between`: en `flex` cada celda mide lo que mide
   su contenido, así que los rótulos del encabezado no caen sobre las celdas de
   abajo —y la desviación es peor justo cuando una fila dice "Nunca" en vez de una
   fecha—. Con tres pistas proporcionales, todas las filas usan la misma
   definición y las columnas quedan alineadas.

   Las pistas son `minmax(0, …fr)` y no anchos fijos: a 320px se encogen y el
   texto envuelve, sin desbordar a lo ancho. */
.fila-lista {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
  /* Las celdas se encogen a su contenido dentro de su pista; sin esto el pill
     —que como ítem de rejilla se estira— pintaría su fondo de columna a
     columna. Las pistas no se mueven, así que las columnas siguen alineadas. */
  justify-items: start;
  gap: var(--espacio-3);
  min-height: var(--espacio-toque-minimo);
  padding: var(--espacio-3) var(--espacio-4);
  background-color: var(--color-superficie);
  border-bottom: 1px solid var(--color-linea);
}

/* Los rótulos de columna. Es la banda de encabezado de `components.lista-accion`
   —`{typography.etiqueta}`—, aplicada como modificador de la fila y no como un
   componente nuevo: son las mismas tres columnas y la misma caja. */
.fila-lista--encabezado {
  color: var(--color-tinta-media);
  font-size: var(--tipo-etiqueta-tamano);
  font-weight: var(--tipo-etiqueta-peso);
  line-height: var(--tipo-etiqueta-interlinea);
  letter-spacing: var(--tipo-etiqueta-espaciado);
}

/* --- pill-estado ---------------------------------------------------------
   La píldora de estado, del catálogo de `DESIGN.md` (`components.pill-estado`).
   El único lugar del sistema donde la tipografía baja de 12px: 11px es su rol
   `pill` y de nadie más. Los 12px de `etiqueta` sí se usan en otro lado —la banda
   de rótulos de `fila-lista`, acá arriba—, que es para lo que existe ese rol.

   Se implantan las dos variantes que hoy tienen caso —`ok` y `atencion`—; las
   otras cuatro de la paleta entran cuando exista la pantalla que las use, no
   antes.

   La píldora NUNCA va sola: adentro va la palabra del estado. El color
   acompaña y nunca identifica solo (NFR-16). */
.pill-estado {
  display: inline-block;
  padding: var(--espacio-0-5) var(--espacio-2);
  border-radius: var(--radio-sm);
  font-family: var(--tipo-pill-familia);
  font-size: var(--tipo-pill-tamano);
  font-weight: var(--tipo-pill-peso);
  line-height: var(--tipo-pill-interlinea);
}

.pill-estado--ok {
  background-color: var(--color-ok-fondo);
  color: var(--color-ok);
}

.pill-estado--atencion {
  background-color: var(--color-atencion-fondo);
  color: var(--color-atencion);
}

/* --- la lista de trabajos de Inicio --------------------------------------
   Disposición y nada más: ni un color, ni un tamaño, ni un radio. Es el
   contenedor que agrupa las `fila-lista` y despoja la lista de sus viñetas y su
   sangría de fábrica. */
.seccion-trabajos {
  margin-top: var(--espacio-6);
}

.lista-trabajos {
  margin: 0;
  padding: 0;
  list-style: none;
}
