﻿/* ============================================================
   Sistema de diseño PRESIDENCIA / ZEV Motors
   Ver docs/FRONTEND.md §3 (identidad) y §4 (las 8 reglas).

   "Precisión institucional con nervio de automotor": la interfaz
   se comporta como un instrumento de taller -- densa, angular,
   señalizada. El carácter lo ponen la franja diagonal de la
   marca, la numeración monoespaciada y los bordes duros; nunca
   gradientes, desenfoques ni sombras difusas de color.

   Se carga DESPUÉS de bootstrap.min.css. Regla 7: nunca se
   redefine .card ni .btn-primary directamente -- todo pasa por
   variables --bs-* o por clases propias con prefijo zev-.
   ============================================================ */

@import url('https://fonts.googleapis.com/css2?family=Archivo:ital,wght@0,500;0,600;0,700;0,900;1,700;1,900&family=Source+Sans+3:ital,wght@0,400;0,600;0,700;1,400&display=swap');

:root {
  /* --- Marca: tomados por muestreo de píxel de wwwroot/img/logoAutoZev.png --- */
  --zev-celeste: #2daae1;
  /* El celeste de la marca sobre fondo claro da 2.6:1 -- se ve, pero no se lee.
     Este es el mismo tono bajado hasta pasar 4.5:1 sobre blanco (5.0) y sobre la
     superficie cálida (4.6). Se usa cuando el celeste tiene que ser TEXTO: el
     enlace apuntado, sobre todo. La franja diagonal y los fondos siguen usando el
     celeste de la marca, donde el contraste no aplica. */
  --zev-celeste-texto: #1777a1;
  --zev-azul-profundo: #142850;
  --zev-rojo: #e20816;

  /* --- Neutros teñidos del celeste de la marca.
         Hasta la Sesión 9 esta escala era cálida --beige-- para huir del gris
         azulado #f8f9fa de Bootstrap. El resultado no se leyó como claro sino
         como apagado, y el celeste de la marca quedaba peleado con su propio
         fondo. Ahora los neutros salen del mismo tono que el logo (hue ~205):
         siguen sin ser el gris de librería, pero ahora pertenecen a la marca
         en vez de contradecirla. --- */
  --zev-gray-50: #f3f7fa;
  --zev-gray-100: #e6eef4;
  --zev-gray-200: #d9e4ec;
  --zev-gray-300: #bccdda;
  --zev-gray-400: #94a9ba;
  --zev-gray-500: #6c8395;
  --zev-gray-600: #4d6377;
  --zev-gray-700: #3a4d5e;
  --zev-gray-800: #24333f;
  --zev-gray-900: #16202a;

  /* Alto de la banda superior. La placa de la marca y la topbar lo
     comparten para que se lean como una sola franja blanca. */
  --zev-alto-banda: 3.5rem;

  --zev-ink: var(--zev-gray-900);

  /* Todo lo que en este sistema se pinta oscuro --la barra lateral, el botón
     primario, la página activa, la cabecera de una captura-- comparte este
     token. Era `--zev-ink`, y con la lateral ocupando una columna entera el
     casi-negro se volvió el color dominante de la pantalla. Ahora es el azul
     profundo de la marca: mismo peso visual, pero el que manda es un color
     del logo y no la tinta del texto. La tinta sigue siendo tinta: se lee, no
     se pinta con ella. */
  --zev-superficie-oscura: var(--zev-azul-profundo);

  --zev-surface: var(--zev-gray-50);
  --zev-surface-raised: #ffffff;
  --zev-border: var(--zev-gray-200);
  --zev-border-fuerte: var(--zev-gray-300);

  /* --- Estados semánticos: escala aparte, no compite con la marca --- */
  --zev-success: #1e7b34;
  --zev-success-bg: #e9f5ec;
  --zev-warning: #a6620b;
  --zev-warning-bg: #fcf1de;
  --zev-danger: #b3261e;
  --zev-danger-bg: #fbeae9;
  --zev-info: #0b5b8c;
  --zev-info-bg: #e7f1f8;

  /* --- Tipografía: dos voces, y una tercera entrada para el dato que se compara en columna --- */
  --zev-font-display: 'Archivo', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  --zev-font-body: 'Source Sans 3', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  /* La voz de los datos ya no es monoespaciada. Lo que hacía falta de la
     monoespaciada era una sola cosa --que los dígitos de una columna caigan
     unos sobre otros-- y eso lo da `font-variant-numeric: tabular-nums` en la
     misma sans del cuerpo. Lo demás que traía --el ancho fijo de las letras--
     no aportaba nada acá y hacía que el sistema se leyera como un editor de
     código. Sigue siendo un token aparte porque el dato lleva su propio peso
     y su propio interletrado, no porque lleve otra familia. */
  --zev-font-datos: var(--zev-font-body);

  --zev-text-2xs: 0.66rem;
  --zev-text-xs: 0.75rem;
  --zev-text-sm: 0.875rem;
  --zev-text-base: 1rem;
  --zev-text-lg: 1.125rem;
  --zev-text-xl: 1.5rem;
  --zev-text-2xl: 2rem;
  --zev-text-3xl: 2.75rem;

  /* --- Escala de espaciado (múltiplos de 4px) --- */
  --zev-space-1: 0.25rem;
  --zev-space-2: 0.5rem;
  --zev-space-3: 0.75rem;
  --zev-space-4: 1rem;
  --zev-space-6: 1.5rem;
  --zev-space-8: 2rem;
  --zev-space-12: 3rem;

  /* --- Bordes y elevación: contraste de escala, no de sombra.
         El radio es chico a propósito: lo redondo y uniforme es
         justo lo que hace genérica a una interfaz. --- */
  --zev-radius-sm: 2px;
  --zev-radius: 3px;
  --zev-border-width: 1px;
  --zev-shadow-sm: 0 1px 2px rgba(22, 32, 42, 0.07);
  --zev-shadow: 0 2px 6px rgba(22, 32, 42, 0.10);

  /* --- Movimiento: corto y seco. Esta gente entra todos los días
         al mismo formulario; una animación "cinematográfica" acá
         es tiempo perdido, no lujo. --- */
  --zev-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --zev-dur: 130ms;

  /* --- La franja tricolor de la marca, en un solo lugar: la usan la franja
         diagonal, el filo del boton apuntado y el avance del expediente. --- */
  --zev-tricolor: linear-gradient(
      135deg,
      var(--zev-celeste) 0%, var(--zev-celeste) 33%,
      var(--zev-azul-profundo) 33%, var(--zev-azul-profundo) 66%,
      var(--zev-rojo) 66%, var(--zev-rojo) 100%
    );

  /* --- Tramado diagonal: la marca aplicada como textura de fondo --- */
  --zev-hatch: repeating-linear-gradient(
    135deg,
    transparent 0 6px,
    rgba(22, 32, 42, 0.04) 6px 7px
  );

  /* --- Sobreescritura de variables de Bootstrap 5.3 (Regla 7) --- */
  --bs-primary: var(--zev-azul-profundo);
  --bs-primary-rgb: 20, 40, 80;
  --bs-primary-text-emphasis: var(--zev-azul-profundo);
  --bs-primary-bg-subtle: #e2e7ef;
  --bs-primary-border-subtle: #c3cddc;

  --bs-secondary: var(--zev-gray-600);
  --bs-secondary-rgb: 107, 98, 85;

  --bs-success: var(--zev-success);
  --bs-success-rgb: 30, 123, 52;
  --bs-success-bg-subtle: var(--zev-success-bg);

  --bs-warning: var(--zev-warning);
  --bs-warning-rgb: 166, 98, 11;
  --bs-warning-bg-subtle: var(--zev-warning-bg);

  --bs-danger: var(--zev-danger);
  --bs-danger-rgb: 179, 38, 30;
  --bs-danger-bg-subtle: var(--zev-danger-bg);

  --bs-info: var(--zev-info);
  --bs-info-rgb: 11, 91, 140;
  --bs-info-bg-subtle: var(--zev-info-bg);

  --bs-body-font-family: var(--zev-font-body);
  --bs-body-color: var(--zev-ink);
  --bs-body-bg: var(--zev-surface);
  --bs-border-color: var(--zev-border);
  --bs-border-radius: var(--zev-radius);
  --bs-border-radius-sm: var(--zev-radius-sm);
  --bs-border-radius-lg: var(--zev-radius);
  --bs-box-shadow: var(--zev-shadow);
  --bs-box-shadow-sm: var(--zev-shadow-sm);
  --bs-link-color: var(--zev-azul-profundo);
  --bs-link-hover-color: var(--zev-celeste-texto);
}

/* ============================================================
   Barras de scroll. La nativa de Windows es ancha, gris azulada y
   con flechas: en una interfaz densa como esta es lo primero que
   se ve, y no se parece a nada más del sistema. Acá es un filo
   delgado, del color de los neutros cálidos y sin flechas.

   scrollbar-width / scrollbar-color no se heredan, así que van en
   `*`: cada elemento con scroll propio (la lateral, las tablas
   anchas) tiene que declararlo por su cuenta.
   ============================================================ */

* {
  scrollbar-width: thin;
  scrollbar-color: var(--zev-gray-300) transparent;
}

::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

::-webkit-scrollbar-track,
::-webkit-scrollbar-corner {
  background: transparent;
}

/* El borde transparente con background-clip deja aire alrededor
   del pulgar sin necesidad de una pista pintada. Radio chico: lo
   redondo y blando es justo lo que no es este sistema. */
::-webkit-scrollbar-thumb {
  background: var(--zev-gray-300);
  background-clip: padding-box;
  border: 3px solid transparent;
  border-radius: var(--zev-radius-sm);
}

::-webkit-scrollbar-thumb:hover {
  background: var(--zev-gray-500);
  background-clip: padding-box;
}

/* El atributo `hidden` tiene que ganarle a cualquier display: casi todas las
   clases de acá declaran uno (flex, grid, inline-flex) y la regla del navegador,
   que viene de su hoja de usuario-agente, pierde contra cualquiera de ellas.
   Sin esto, `elemento.hidden = true` no oculta nada y hay que inventar una clase
   paralela para lo mismo que el atributo ya dice. */
[hidden] {
  display: none !important;
}

/* ============================================================
   Tipografía
   ============================================================ */

/* Cifras de ancho fijo en todo el sistema. Antes esto lo daba la familia
   monoespaciada allí donde se la usaba; ahora que el dato va en la misma sans
   que el cuerpo, la propiedad tiene que declararse. Es lo único que hacía
   falta de la mono: que la columna de montos caiga alineada. */
body {
  font-variant-numeric: tabular-nums;
}

h1, h2, h3, h4, h5, h6, .zev-display {
  font-family: var(--zev-font-display);
  font-weight: 900;
  letter-spacing: -0.015em;
}

/* Itálica reservada a lo que encabeza -- eco de la marca, no un
   estilo de énfasis genérico. */
.zev-headline-mark {
  font-style: italic;
}

/* El dato que se compara entre filas: placa, VIN, número de orden, monto.
   Lo que lo distingue del texto corriente es el peso y los dígitos de ancho
   fijo, no la familia. El interletrado abierto que tenía era compensación de
   la monoespaciada; sin ella, sobra. */
.zev-dato {
  font-family: var(--zev-font-datos);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* Micro-etiqueta de sección: la señalética que numera y nombra
   cada bloque, como el rotulado de un tablero. */
.zev-eyebrow {
  display: flex;
  align-items: center;
  gap: var(--zev-space-2);
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--zev-gray-600);
}

.zev-eyebrow::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--zev-border);
}

/* Foco visible y consistente en todo lo interactivo (Sesión 6
   audita accesibilidad, pero esto no se deja para después).
   El anillo es de tinta, no de marca: el celeste sobre fondo
   claro no llega al 3:1 que pide WCAG para un indicador de foco,
   y el foco es lo último que se puede permitir que sea sutil. */
.zev-btn:focus-visible,
.zev-input:focus-visible,
.zev-toast__close:focus-visible {
  outline: 2px solid var(--zev-ink);
  outline-offset: 2px;
}

/* ============================================================
   La franja diagonal -- gesto único de la casa. Se usa poco y
   siempre igual: acento del ítem activo en la navegación, remate
   de cabeceras, barra de progreso del flujo de la orden de
   trabajo. Un solo componente CSS, sin markup adicional.
   ============================================================ */

.zev-diagonal {
  background: var(--zev-tricolor);
}

/* Remate de cabecera: barra horizontal delgada bajo un título. */
.zev-diagonal--header {
  display: block;
  height: 4px;
  width: 3.5rem;
  border-radius: var(--zev-radius-sm);
}

/* Acento del ítem activo en la navegación: barra vertical al
   borde del link o de la tarjeta activa. */
.zev-diagonal--accent {
  display: inline-block;
  width: 4px;
  align-self: stretch;
  border-radius: var(--zev-radius-sm);
}

/* Mismo ancho que el acento, sin color: mantiene alineados los
   ítems de navegación que no están activos. */
.zev-diagonal--accent-spacer {
  display: inline-block;
  width: 4px;
  align-self: stretch;
}

/* Filo superior de un bloque (estado vacío, panel destacado). */
.zev-diagonal--edge {
  display: block;
  height: 3px;
  width: 100%;
}

/* Marca cuadrada de la franja (p.ej. junto al logo). */
.zev-mark {
  display: inline-block;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: var(--zev-radius);
}

.zev-logo-sm {
  height: 3rem;
  /* El tope de ancho es el del logo de Quito a esta altura: ahí no cambia nada, y los
     logos más apaisados (Guayaquil) entran achicados en vez de dominar la banda. */
  max-width: 15rem;
  object-fit: contain;
}

/* ============================================================
   Cabecera de página / de sección
   ============================================================ */

.zev-page-header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--zev-space-4);
  padding-bottom: var(--zev-space-3);
  border-bottom: 2px solid var(--zev-ink);
  margin-bottom: var(--zev-space-6);
}

.zev-page-header__title {
  margin: 0;
  font-size: var(--zev-text-2xl);
  line-height: 1.05;
}

.zev-page-header__meta {
  /* Cuando el título es largo la cabecera envuelve y el meta caía a la izquierda,
     pegado al título. El auto lo mantiene contra el borde derecho igual que sin envolver. */
  margin-left: auto;
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-xs);
  color: var(--zev-gray-600);
}

/* ============================================================
   Botones. Sólidos, angulares y con el gesto de la casa: al
   pasar el mouse aparece la franja diagonal por debajo, de
   izquierda a derecha. Un solo gesto, siempre el mismo.
   ============================================================ */

.zev-btn {
  position: relative;
  display: inline-flex;
  /* Dentro de un contenedor flex un botón se encoge como cualquier
     otro ítem, y como acá el texto no envuelve (white-space: nowrap)
     y lo que sobra se recorta (overflow: hidden), el resultado era
     un "Buscar" cortado a la mitad. Un botón mide lo que dice. */
  flex: none;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  padding: 0.55rem 1.1rem;
  font-family: var(--zev-font-display);
  font-size: var(--zev-text-sm);
  font-weight: 700;
  line-height: 1.2;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  border: var(--zev-border-width) solid transparent;
  border-radius: var(--zev-radius);
  background: var(--zev-gray-800);
  color: #fff;
  overflow: hidden;
  transition: background-color var(--zev-dur) var(--zev-ease),
              color var(--zev-dur) var(--zev-ease),
              border-color var(--zev-dur) var(--zev-ease),
              transform var(--zev-dur) var(--zev-ease);
}

.zev-btn::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 3px;
  background: var(--zev-tricolor);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 180ms var(--zev-ease);
}

.zev-btn:hover::after,
.zev-btn:focus-visible::after {
  transform: scaleX(1);
}

/* Se hunde al presionar: la única "física" que este sistema
   necesita, y confirma el clic con guante puesto. */
.zev-btn:active {
  transform: translateY(1px);
}

.zev-btn[disabled],
.zev-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  transform: none;
}

.zev-btn[disabled]::after,
.zev-btn:disabled::after {
  display: none;
}

.zev-btn--primary {
  background: var(--zev-azul-profundo);
  color: #fff;
}

.zev-btn--primary:hover {
  background: #0d1c38;
  color: #fff;
}

.zev-btn--ghost {
  background: transparent;
  color: var(--zev-ink);
  border-color: var(--zev-border-fuerte);
}

.zev-btn--ghost:hover {
  background: var(--zev-gray-100);
  color: var(--zev-ink);
  border-color: var(--zev-ink);
}

.zev-btn--danger {
  background: var(--zev-danger);
  color: #fff;
}

.zev-btn--danger:hover {
  background: #92201a;
  color: #fff;
}

/* Acción terciaria: sin caja, para lo que no compite por
   atención (cancelar, volver). */
.zev-btn--quiet {
  background: transparent;
  color: var(--zev-gray-600);
  padding-left: 0.5rem;
  padding-right: 0.5rem;
}

.zev-btn--quiet:hover {
  color: var(--zev-ink);
}

.zev-btn--sm {
  padding: 0.35rem 0.7rem;
  font-size: var(--zev-text-xs);
}

.zev-btn--lg {
  padding: 0.75rem 1.5rem;
  font-size: var(--zev-text-base);
}

/* Botón de solo ícono (acciones por fila). */
.zev-btn--icon {
  padding: 0.35rem 0.5rem;
}

/* ============================================================
   Etiquetas de estado -- señalética rectangular con LED sólido
   al frente, legible a un metro. Nunca píldoras pastel.
   ============================================================ */

.zev-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  padding: 0.3em 0.6em;
  font-family: var(--zev-font-display);
  font-size: var(--zev-text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  line-height: 1;
  border-radius: var(--zev-radius-sm);
  border: var(--zev-border-width) solid currentColor;
  background: transparent;
}

/* El "LED": cuadrado sólido del color del estado. Da lectura
   instantánea en una columna de tabla sin depender del texto. */
.zev-badge::before {
  content: '';
  width: 0.5em;
  height: 0.5em;
  background: currentColor;
  flex: none;
}

.zev-badge--neutral { color: var(--zev-gray-600); background: var(--zev-gray-100); }
.zev-badge--success { color: var(--zev-success); background: var(--zev-success-bg); }
.zev-badge--warning { color: var(--zev-warning); background: var(--zev-warning-bg); }
.zev-badge--danger  { color: var(--zev-danger);  background: var(--zev-danger-bg); }
.zev-badge--info    { color: var(--zev-info);    background: var(--zev-info-bg); }

/* El badge que además abre un menú: el estado se ve y se cambia en el
   mismo lugar, sin gastar una columna de acciones en la tabla. Como es
   un <button>, el navegador le impone su propia tipografía: se le
   devuelve la del badge. Lo demás (borde, LED, colores) lo hereda de
   .zev-badge, que es justo el punto de que sea el mismo objeto. */
.zev-badge--menu {
  font-family: var(--zev-font-display);
  font-size: var(--zev-text-xs);
  cursor: pointer;
}

.zev-badge--menu .bi {
  margin-left: 0.15rem;
  font-size: 0.9em;
  opacity: 0.7;
}

.zev-badge--menu[aria-expanded="true"] {
  box-shadow: inset 0 0 0 var(--zev-border-width) currentColor;
}

/* ============================================================
   Panel: el contenedor de contenido del sistema. Reemplaza a la
   .card de Bootstrap sin tocarla (Regla 7).
   ============================================================ */

.zev-panel {
  background: var(--zev-surface-raised);
  border: var(--zev-border-width) solid var(--zev-border);
  border-radius: var(--zev-radius);
}

.zev-panel__head {
  display: flex;
  align-items: center;
  gap: var(--zev-space-2);
  padding: var(--zev-space-3) var(--zev-space-4);
  border-bottom: var(--zev-border-width) solid var(--zev-border);
}

.zev-panel__title {
  margin: 0;
  font-size: var(--zev-text-sm);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* Panel plegable: un <details> con la cabecera de siempre como <summary>. Lo
   pliega el navegador — nada de JavaScript para algo que el HTML ya hace — y el
   estado se ve en el chevrón, no solo en que el cuerpo desaparezca. */
.zev-panel--plegable > summary {
  cursor: pointer;
  list-style: none;
  border-bottom-color: transparent;
}

.zev-panel--plegable[open] > summary {
  border-bottom-color: var(--zev-border);
}

.zev-panel--plegable > summary::-webkit-details-marker {
  display: none;
}

/* Resumen del panel plegado: los números que se miran de reojo, a la derecha
   del título y antes del chevrón. */
.zev-panel__resumen {
  display: flex;
  align-items: center;
  gap: var(--zev-space-2);
  color: var(--zev-gray-600);
  font-size: var(--zev-text-xs);
}

/* El título empuja: así el resumen y el chevrón quedan pegados a la derecha sin
   que ninguno de los dos tenga que reclamar el hueco por su cuenta. */
.zev-panel--plegable > summary > .zev-panel__title {
  margin-right: auto;
}

.zev-panel--plegable > summary::after {
  content: '';
  margin-left: var(--zev-space-3);
  width: 0.5rem;
  height: 0.5rem;
  border-right: 2px solid var(--zev-gray-600);
  border-bottom: 2px solid var(--zev-gray-600);
  transform: translateY(-2px) rotate(45deg);
  transition: transform var(--zev-dur) var(--zev-ease);
}

.zev-panel--plegable[open] > summary::after {
  transform: translateY(2px) rotate(225deg);
}

.zev-panel--plegable > summary:hover {
  background: var(--zev-gray-50);
}

.zev-panel__body {
  padding: var(--zev-space-4);
}

/* ============================================================
   Campos de formulario
   ============================================================ */

.zev-label {
  display: block;
  margin-bottom: 0.3rem;
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--zev-gray-600);
}

.zev-input {
  display: block;
  width: 100%;
  padding: 0.5rem 0.7rem;
  font-family: inherit;
  font-size: var(--zev-text-sm);
  color: var(--zev-ink);
  background: var(--zev-surface-raised);
  border: var(--zev-border-width) solid var(--zev-border-fuerte);
  border-radius: var(--zev-radius);
  transition: border-color var(--zev-dur) var(--zev-ease),
              box-shadow var(--zev-dur) var(--zev-ease);
}

.zev-input:focus {
  border-color: var(--zev-azul-profundo);
  box-shadow: 0 0 0 3px rgba(45, 170, 225, 0.28);
}

.zev-input::placeholder {
  color: var(--zev-gray-600);
}

/* Los datos que se comparan entre filas se escriben monoespaciados
   también dentro del campo, para que el dato se vea igual al
   escribirlo que al leerlo en la tabla. */
.zev-input--mono {
  font-family: var(--zev-font-datos);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
}

/* Las flechitas del campo numérico se sacan de TODOS los campos, no
   solo de los de precio: con el campo enfocado, la ruedita del mouse
   al desplazar la página le cambia el valor, y en una matriz de
   precios o en un kilometraje eso es un dato mal guardado que nadie
   ve. La ruedita se desactiva aparte, en modulos/shell.js: CSS puede
   esconder el control pero no el gesto. */
input[type="number"] {
  -moz-appearance: textfield;
  appearance: textfield;
}

input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* ------------------------------------------------------------
   Campo de contraseña con el ojo para verla. El markup lo pone
   VerClaveTagHelper (Regla 6) y el comportamiento vive en
   modulos/ver-clave.js (Regla 4).
   ------------------------------------------------------------ */

.zev-clave {
  position: relative;
  display: block;
}

/* Deja lugar al botón dentro del campo: el ojo no puede taparle
   los últimos caracteres a lo que se está escribiendo. */
.zev-input--clave {
  padding-right: 2.6rem;
}

.zev-clave__ojo {
  position: absolute;
  right: 0.3rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--zev-gray-600);
}

.zev-clave__ojo[aria-pressed="true"] {
  color: var(--zev-ink);
  box-shadow: inset 0 -3px 0 0 var(--zev-celeste);
}

/* Edge y IE agregan su propio ojo dentro del campo: con el
   nuestro al lado quedan dos, y el de ellos no se puede estilar. */
.zev-input--clave::-ms-reveal,
.zev-input--clave::-ms-clear {
  display: none;
}

.zev-input--invalid {
  border-color: var(--zev-danger);
}

.zev-input--invalid:focus {
  box-shadow: 0 0 0 3px rgba(179, 38, 30, 0.22);
}

.zev-field-error {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  margin-top: 0.3rem;
  font-size: var(--zev-text-xs);
  font-weight: 600;
  color: var(--zev-danger);
}

/* Sin esto, el <span> de validación vacío que el tag helper deja siempre en el
   markup sumaba su margen debajo de cada campo, error o no. */
.zev-field-error:empty {
  display: none;
}

.zev-hint {
  margin-top: 0.3rem;
  font-size: var(--zev-text-xs);
  color: var(--zev-gray-600);
}

/* ============================================================
   Tabla: instrumento de lectura. Cabecera oscura, filas densas,
   y al pasar el mouse la fila se marca con la franja diagonal.
   ============================================================ */

/* position: relative no es decorativo. Los .visually-hidden de las celdas son
   absolutos, y sin un ancestro posicionado su caja se calcula contra la página: se
   escapaban del scroll del .table-responsive y ensanchaban la página entera en un
   teléfono (la matriz de permisos la llevaba de 375 a 422px). */
.zev-table {
  position: relative;
  width: 100%;
  border-collapse: collapse;
  font-size: var(--zev-text-sm);
}

/* La cabecera era un bloque casi negro. Con veinticinco filas por pantalla
   esa banda es lo primero que se ve de cada listado, y sumada a la lateral
   dejaba la pantalla dominada por el oscuro. Ahora es clara y la jerarquía la
   da el filo de 2px en azul de marca: se sigue leyendo como cabecera, sin
   pesar como una viga. */
.zev-table thead th {
  padding: 0.55rem 0.6rem;
  font-size: var(--zev-text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  text-align: left;
  color: var(--zev-azul-profundo);
  background: var(--zev-gray-100);
  border-bottom: 2px solid var(--zev-azul-profundo);
  white-space: nowrap;
}

.zev-table tbody td {
  padding: 0.5rem 0.6rem;
  border-bottom: var(--zev-border-width) solid var(--zev-border);
  vertical-align: middle;
}

.zev-table tbody tr {
  background: var(--zev-surface-raised);
  transition: background-color var(--zev-dur) var(--zev-ease);
}

/* Banda alterna. En una tabla de diez columnas el ojo pierde la fila a mitad
   de camino; el tono es lo bastante bajo como para no leerse como estado. */
.zev-table tbody tr:nth-child(even) {
  background: var(--zev-gray-50);
}

.zev-table tbody tr:hover,
.zev-table tbody tr:nth-child(even):hover {
  background: var(--zev-gray-100);
}

/* La primera y la última columna llevan gutter propio: con el
   padding de celda a secas el dato quedaba tocando el borde del
   panel y la tabla se leía apretada contra el marco. La densidad
   está en el alto de fila, no en pegar el texto al filo. */
.zev-table thead th:first-child,
.zev-table tbody td:first-child {
  padding-left: var(--zev-space-4);
}

.zev-table thead th:last-child,
.zev-table tbody td:last-child {
  padding-right: var(--zev-space-4);
}

/* El acento diagonal entra desde arriba en la fila apuntada: la
   misma señal que marca el ítem activo en la navegación. */
.zev-table tbody td:first-child {
  position: relative;
}

.zev-table tbody td:first-child::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  background: var(--zev-tricolor);
  transform: scaleY(0);
  transform-origin: top center;
  transition: transform 160ms var(--zev-ease);
}

.zev-table tbody tr:hover td:first-child::before {
  transform: scaleY(1);
}

/* Cabecera ordenable. El TagHelper <sortable-th> y sortable-headers.js
   ya existían; acá solo se los viste para la cabecera oscura, donde el
   hover claro de site.css no se ve. */
.zev-table thead th.sortable-th {
  cursor: pointer;
  user-select: none;
  transition: color var(--zev-dur) var(--zev-ease);
}

.zev-table thead th.sortable-th:hover {
  color: var(--zev-celeste-texto);
}

.zev-table thead th .sort-icon {
  margin-left: 0.25rem;
  opacity: 0.35;
}

.zev-table thead th .sort-icon.active {
  color: var(--zev-celeste-texto);
  opacity: 1;
}

/* El identificador de la primera celda —número de orden, placa,
   código— es el enlace al expediente. Iba en --zev-azul-profundo,
   que a este tamaño y en negrita se lee casi negro: no parecía
   enlace y ensuciaba el mono. Ahora el color lo pone el subrayado,
   con el celeste de la marca, y el texto queda en tinta: se
   distingue del resto de la fila sin meter un azul de librería. */
.zev-table tbody td:first-child a {
  color: var(--zev-ink);
  text-decoration: underline;
  text-decoration-color: var(--zev-celeste);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
  transition: color var(--zev-dur) var(--zev-ease);
}

.zev-table tbody td:first-child a:hover,
.zev-table tbody td:first-child a:focus-visible {
  color: var(--zev-celeste-texto);
  text-decoration-color: var(--zev-celeste-texto);
}

.zev-table .zev-num {
  font-family: var(--zev-font-datos);
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

/* ============================================================
   Estado vacío. No es un ícono gris centrado con una frase
   triste: es una placa de taller sin rotular todavía -- tramado
   diagonal de fondo, filo tricolor arriba y el código del módulo
   en monoespaciada.
   ============================================================ */

.zev-empty {
  overflow: hidden;
  background: var(--zev-surface-raised);
  border: var(--zev-border-width) solid var(--zev-border);
  border-radius: var(--zev-radius);
}

.zev-empty__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--zev-space-3);
  padding: var(--zev-space-12) var(--zev-space-6);
  background-image: var(--zev-hatch);
}

.zev-empty__code {
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--zev-gray-600);
  padding: 0.3rem 0.6rem;
  border: var(--zev-border-width) solid var(--zev-border-fuerte);
  background: var(--zev-surface-raised);
}

.zev-empty__title {
  margin: 0;
  font-size: var(--zev-text-xl);
  line-height: 1.1;
  color: var(--zev-ink);
}

.zev-empty__msg {
  max-width: 34ch;
  margin: 0;
  font-size: var(--zev-text-sm);
  color: var(--zev-gray-600);
}

/* Solo para /DesignSystem: la placa de la marca sobre el fondo
   oscuro de la lateral, para poder mirarla fuera del shell. */
.zev-marca-demo {
  padding: var(--zev-space-4);
  background: var(--zev-superficie-oscura);
}

.zev-marca-demo__placa {
  display: flex;
  align-items: center;
  gap: var(--zev-space-2);
  width: 15.5rem;
  min-height: var(--zev-alto-banda);
  padding: var(--zev-space-2) var(--zev-space-3);
  background: var(--zev-surface-raised);
  border-bottom: var(--zev-border-width) solid var(--zev-border);
}

/* ------------------------------------------------------------
   La pantalla de error (Sesión 8). Es un estado vacío: lo que
   había para mostrar no está. Reusa .zev-empty entero y agrega
   una sola cosa, el número del código -- que es lo primero que se
   lee y lo que la gente copia al pedir ayuda.
   ------------------------------------------------------------ */

.zev-error__codigo {
  margin: 0;
  font-family: var(--zev-font-display);
  font-size: clamp(4rem, 14vw, 7rem);
  font-weight: 900;
  font-style: italic;
  line-height: 0.85;
  letter-spacing: -0.04em;
  color: var(--zev-ink);
}

.zev-error__ruta {
  max-width: 46ch;
  margin: 0;
  font-size: var(--zev-text-2xs);
  color: var(--zev-gray-600);
  overflow-wrap: anywhere;
}

.zev-error__acciones {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--zev-space-2);
  margin-top: var(--zev-space-2);
}

/* El identificador de la traza: sin él, "me salió error" no se
   puede buscar en el log del servidor. */
.zev-error__ref {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--zev-space-2);
  max-width: 100%;
  margin: var(--zev-space-2) 0 0;
  padding: 0.3rem 0.6rem;
  font-size: var(--zev-text-2xs);
  color: var(--zev-gray-600);
  background: var(--zev-surface-raised);
  border: var(--zev-border-width) solid var(--zev-border-fuerte);
  border-radius: var(--zev-radius-sm);
  overflow-wrap: anywhere;
}

.zev-error__ref-etiqueta {
  font-family: var(--zev-font-datos);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.14em;
}

/* ============================================================
   Toasts. Resultado de una acción tras POST-Redirect-GET
   (Regla 8): caja angular, columna de ícono sólida del color del
   estado, título en display y barra de vida abajo.
   ============================================================ */

.zev-toast-stack {
  display: flex;
  flex-direction: column;
  gap: var(--zev-space-2);
  width: min(26rem, 100%);
}

.zev-toast {
  position: relative;
  display: flex;
  align-items: stretch;
  gap: 0;
  overflow: hidden;
  background: var(--zev-surface-raised);
  border: var(--zev-border-width) solid var(--zev-border-fuerte);
  border-radius: var(--zev-radius);
  box-shadow: var(--zev-shadow-sm);
}

.zev-toast__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 2.75rem;
  font-size: var(--zev-text-lg);
  color: #fff;
  background: var(--zev-gray-600);
}

.zev-toast__body {
  flex: 1;
  padding: var(--zev-space-3) var(--zev-space-3) calc(var(--zev-space-3) + 2px);
}

.zev-toast__title {
  margin: 0 0 0.1rem;
  font-family: var(--zev-font-display);
  font-size: var(--zev-text-xs);
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.zev-toast__msg {
  margin: 0;
  font-size: var(--zev-text-sm);
  color: var(--zev-gray-700);
}

.zev-toast__close {
  flex: none;
  align-self: flex-start;
  padding: var(--zev-space-2) var(--zev-space-3);
  font-size: var(--zev-text-base);
  line-height: 1;
  color: var(--zev-gray-600);
  background: none;
  border: none;
  cursor: pointer;
  transition: color var(--zev-dur) var(--zev-ease);
}

.zev-toast__close:hover {
  color: var(--zev-ink);
}

/* Barra de vida: cuánto le queda al toast antes de cerrarse solo.
   La anima el módulo JS de toasts (Sesión 2); acá queda el
   estado inicial, lleno. */
.zev-toast__timer {
  position: absolute;
  left: 0;
  bottom: 0;
  height: 2px;
  width: 100%;
  background: currentColor;
  opacity: 0.35;
  transform-origin: left center;
}

.zev-toast--success { color: var(--zev-success); }
.zev-toast--success .zev-toast__icon { background: var(--zev-success); }
.zev-toast--success .zev-toast__title { color: var(--zev-success); }

.zev-toast--danger { color: var(--zev-danger); }
.zev-toast--danger .zev-toast__icon { background: var(--zev-danger); }
.zev-toast--danger .zev-toast__title { color: var(--zev-danger); }

.zev-toast--warning { color: var(--zev-warning); }
.zev-toast--warning .zev-toast__icon { background: var(--zev-warning); }
.zev-toast--warning .zev-toast__title { color: var(--zev-warning); }

.zev-toast--info { color: var(--zev-info); }
.zev-toast--info .zev-toast__icon { background: var(--zev-info); }
.zev-toast--info .zev-toast__title { color: var(--zev-info); }

/* ============================================================
   Tarjeta de contador del panel. No es una "stat card" con ícono
   pastel: es un tablero de instrumentos. El número manda -- en
   monoespaciada y grande, para comparar de un vistazo entre
   tarjetas -- y la tarjeta entera es el enlace que abre la lista
   ya filtrada (Regla 2: el filtro va en la URL).
   ============================================================ */

.zev-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: var(--zev-space-3);
}

.zev-stat {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--zev-space-1);
  padding: var(--zev-space-3) var(--zev-space-4) var(--zev-space-4);
  background: var(--zev-surface-raised);
  border: var(--zev-border-width) solid var(--zev-border);
  border-radius: var(--zev-radius);
  color: inherit;
  text-decoration: none;
  transition: border-color var(--zev-dur) var(--zev-ease),
              background-color var(--zev-dur) var(--zev-ease);
}

/* Mismo gesto que el botón: la franja diagonal aparece como filo
   inferior al apuntar. No se inventa una interacción nueva. */
.zev-stat::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 3px;
  transform: scaleX(0);
  transform-origin: left;
  background: var(--zev-tricolor);
  transition: transform var(--zev-dur) var(--zev-ease);
}

.zev-stat:hover,
.zev-stat:focus-visible {
  border-color: var(--zev-border-fuerte);
  color: inherit;
}

.zev-stat:hover::after,
.zev-stat:focus-visible::after,
.zev-stat--activa::after {
  transform: scaleX(1);
}

.zev-stat:focus-visible {
  outline: 2px solid var(--zev-ink);
  outline-offset: 2px;
}

/* La tarjeta del filtro vigente queda con la franja fija y el
   fondo invertido: se ve cuál lista se está mirando sin leer. */
.zev-stat--activa {
  background: var(--zev-superficie-oscura);
  border-color: var(--zev-superficie-oscura);
  color: var(--zev-gray-50);
}

.zev-stat--activa:hover,
.zev-stat--activa:focus-visible {
  color: var(--zev-gray-50);
  border-color: var(--zev-ink);
}

.zev-stat__label {
  font-size: var(--zev-text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--zev-gray-600);
}

.zev-stat--activa .zev-stat__label {
  color: var(--zev-gray-300);
}

.zev-stat__num {
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-3xl);
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.zev-stat__nota {
  font-size: var(--zev-text-xs);
  color: var(--zev-gray-600);
}

.zev-stat--activa .zev-stat__nota {
  color: var(--zev-gray-300);
}

/* ============================================================
   Avance del expediente -- QUINTO USO de la franja diagonal
   (docs/FRONTEND.md §3). La barra se llena con el tricolor en la
   proporción de etapas cumplidas; el resto queda en tramado, o
   sea "todavía sin rotular", el mismo lenguaje del estado vacío.
   ============================================================ */

/* Es un <progress> de verdad, no un div con el ancho puesto a mano:
   así el porcentaje viaja en el atributo value -- sin style= inline,
   que la Regla 7 prohíbe -- y el lector de pantalla lo anuncia solo. */
.zev-avance {
  -webkit-appearance: none;
  appearance: none;
  display: block;
  width: 100%;
  height: 6px;
  border: 0;
  border-radius: var(--zev-radius-sm);
  overflow: hidden;
  background-color: var(--zev-gray-100);
  background-image: var(--zev-hatch);
}

.zev-avance::-webkit-progress-bar {
  background-color: var(--zev-gray-100);
  background-image: var(--zev-hatch);
}

.zev-avance::-webkit-progress-value {
  background: var(--zev-tricolor);
}

.zev-avance::-moz-progress-bar {
  background: var(--zev-tricolor);
}

/* ============================================================
   El camino del expediente. Las cinco etapas de la orden de
   trabajo, en fila y clickeables: cada paso lleva al documento si
   existe y a crearlo si no.

   El camino ES la barra de avance -- el tramo que entra a cada
   paso cumplido va en tricolor y el resto en tramado, o sea la
   misma lectura que la barra pero sin repetirla al lado. Un solo
   gesto, el quinto uso de la franja (§3), y ningún componente
   nuevo que aprender.
   ============================================================ */

.zev-camino {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  margin: 0;
  padding: 0;
  list-style: none;
}

.zev-camino__paso {
  position: relative;
  min-width: 0;
  /* Deja lugar al nodo (2.2rem) más aire: sin esto el nodo pisa el nombre. */
  padding-top: 2.9rem;
}

/* El tramo que entra al paso. No hay tramo antes del primero. */
.zev-camino__paso:not(:first-child)::before {
  content: '';
  position: absolute;
  top: 1rem;
  left: -50%;
  width: 100%;
  height: 4px;
  border-radius: var(--zev-radius-sm);
  background-color: var(--zev-gray-100);
  background-image: var(--zev-hatch);
}

/* El :not(:first-child) de la regla de arriba suma una pseudo-clase
   y le gana a un selector de clase suelto: sin repetirlo acá, el
   tramo cumplido se quedaba con el tramado del pendiente. */
.zev-camino__paso--listo:not(:first-child)::before {
  background-color: transparent;
  background-image: var(--zev-tricolor);
}

.zev-camino__enlace {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2rem;
  padding: 0 var(--zev-space-2) var(--zev-space-2);
  color: inherit;
  text-align: center;
  text-decoration: none;
}

.zev-camino__enlace:focus-visible {
  outline: 2px solid var(--zev-ink);
  outline-offset: 2px;
  border-radius: var(--zev-radius-sm);
}

/* El nodo es cuadrado y sólido: señalética, no globito. */
.zev-camino__nodo {
  position: absolute;
  /* Por encima de los tramos. El tramo de un paso arranca en el centro del paso
     anterior, así que cruza la mitad derecha del nodo de ese paso; y como el
     ::before de un <li> se pinta después del contenido del <li> anterior, la
     línea quedaba encima del ícono. */
  z-index: 1;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.2rem;
  height: 2.2rem;
  font-size: var(--zev-text-base);
  color: var(--zev-gray-600);
  background: var(--zev-surface-raised);
  border: 2px solid var(--zev-border-fuerte);
  border-radius: var(--zev-radius);
  transition: border-color var(--zev-dur) var(--zev-ease),
              color var(--zev-dur) var(--zev-ease);
}

.zev-camino__paso--listo .zev-camino__nodo {
  color: var(--zev-gray-50);
  background: var(--zev-success);
  border-color: var(--zev-success);
}

.zev-camino__paso--encurso .zev-camino__nodo {
  color: var(--zev-gray-50);
  background: var(--zev-info);
  border-color: var(--zev-info);
}

/* Lo pendiente lleva el filo de la casa: es donde está el trabajo
   y es lo que el ojo tiene que encontrar primero. */
.zev-camino__paso--pendiente .zev-camino__nodo {
  color: var(--zev-ink);
  border-color: var(--zev-ink);
  box-shadow: inset 0 -4px 0 0 var(--zev-celeste);
}

/* Lo opcional y lo que no aplica se leen apagados, pero siguen
   siendo alcanzables: lo opcional se puede levantar cuando se
   quiera. */
.zev-camino__paso--opcional .zev-camino__nodo,
.zev-camino__paso--noaplica .zev-camino__nodo {
  color: var(--zev-gray-600);
  background: var(--zev-gray-50);
  border-color: var(--zev-border);
  border-style: dashed;
}

a.zev-camino__enlace:hover .zev-camino__nodo {
  border-color: var(--zev-ink);
  color: var(--zev-ink);
}

a.zev-camino__enlace:hover .zev-camino__paso--listo .zev-camino__nodo {
  color: var(--zev-gray-50);
}

.zev-camino__nombre {
  font-family: var(--zev-font-display);
  font-size: var(--zev-text-sm);
  font-weight: 700;
  line-height: 1.15;
}

.zev-camino__paso--opcional .zev-camino__nombre,
.zev-camino__paso--noaplica .zev-camino__nombre {
  color: var(--zev-gray-600);
}

.zev-camino__detalle {
  font-size: var(--zev-text-2xs);
  color: var(--zev-gray-600);
}

/* La marca de "acá está el trabajo", debajo del nombre. */
.zev-camino__marca {
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--zev-warning);
}

/* ------------------------------------------------------------
   El camino dentro de una celda de tabla (§3). Mismos cinco
   pasos, mismos estados, mismos destinos: solo los nodos, sin
   etiqueta debajo. Reemplazó a la barra de avance y al badge de
   "lo que sigue" -- los dos decían en qué estado está la orden,
   pero para abrir el documento que falta había que entrar antes
   al expediente.

   El nombre y el detalle no se borran: se ocultan a la vista y
   los sigue leyendo el lector de pantalla.
   ------------------------------------------------------------ */

.zev-camino--fila {
  /* No es un grid de 1fr: en una celda el ancho lo pone el
     contenido, no la columna. */
  display: inline-flex;
  gap: 0;
}

.zev-camino--fila .zev-camino__paso {
  padding-top: 0;
}

.zev-camino--fila .zev-camino__nodo {
  position: static;
  transform: none;
  width: 1.5rem;
  height: 1.5rem;
  font-size: var(--zev-text-2xs);
  border-width: 1px;
}

/* El tramo entre nodos, más corto y más fino: acá solo tiene que
   decir que los pasos están encadenados. */
.zev-camino--fila .zev-camino__paso:not(:first-child)::before {
  top: 50%;
  left: 0;
  width: 0.55rem;
  height: 2px;
  transform: translateY(-50%);
}

.zev-camino--fila .zev-camino__paso:not(:first-child) {
  padding-left: 0.55rem;
}

.zev-camino--fila .zev-camino__enlace {
  padding: 0;
}

.zev-camino--fila .zev-camino__nombre,
.zev-camino--fila .zev-camino__detalle,
.zev-camino--fila .zev-camino__marca {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Lo que sigue: el mismo gesto que el filo celeste del nodo
   pendiente, pero hacia afuera. En la fila no hay lugar para la
   palabra "Aquí estás", así que la dice el anillo. */
.zev-camino--fila .zev-camino__paso--sigue .zev-camino__nodo {
  box-shadow: 0 0 0 2px var(--zev-celeste);
}

/* Angosto: el camino se pone vertical y el tramo pasa a ser el
   filo izquierdo. Cinco pasos no entran en una pantalla de móvil
   sin quedar ilegibles. La variante de fila queda afuera: ahí son
   cinco nodos de 1.5rem y entran igual. */
@media (max-width: 767.98px) {
  .zev-camino:not(.zev-camino--fila) {
    grid-auto-flow: row;
    grid-auto-columns: auto;
  }

  .zev-camino:not(.zev-camino--fila) .zev-camino__paso {
    padding: 0 0 var(--zev-space-4) 3rem;
  }

  .zev-camino:not(.zev-camino--fila) .zev-camino__paso:not(:first-child)::before {
    top: -1.1rem;
    left: 1rem;
    width: 4px;
    height: 1.5rem;
  }

  .zev-camino:not(.zev-camino--fila) .zev-camino__nodo {
    top: 0;
    left: 0;
    transform: none;
  }

  .zev-camino:not(.zev-camino--fila) .zev-camino__enlace {
    align-items: flex-start;
    padding: 0;
    text-align: left;
  }
}

/* ============================================================
   Ficha de datos: pares etiqueta/valor de un expediente. Los
   valores que se comparan entre filas (placa, VIN, orden, montos)
   van en monoespaciada con .zev-dato, no acá.
   ============================================================ */

.zev-datos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: var(--zev-space-3) var(--zev-space-4);
  margin: 0;
}

.zev-datos__par {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
}

.zev-datos__label {
  font-size: var(--zev-text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--zev-gray-600);
}

.zev-datos__valor {
  font-size: var(--zev-text-sm);
  overflow-wrap: anywhere;
}

/* ============================================================
   Identificador de la orden de trabajo: la placa grande en
   monoespaciada, que es como la gente del taller nombra al
   vehículo. Va en la cabecera del expediente.
   ============================================================ */

.zev-placa {
  display: inline-block;
  padding: 0.15rem 0.55rem;
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-xl);
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--zev-ink);
  background: var(--zev-surface-raised);
  border: 2px solid var(--zev-ink);
  border-radius: var(--zev-radius-sm);
}

/* ============================================================
   Barra de filtros de un listado. No se esconde detrás de un
   botón "Filtros": en este sistema la primera cosa que hace todo
   el mundo al abrir una lista es buscar una placa, así que la
   caja de búsqueda está siempre a la vista (Regla 2: lo que se
   escriba acá queda en la URL).
   ============================================================ */

.zev-filtros {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--zev-space-3);
  padding: var(--zev-space-3) var(--zev-space-4);
  margin-bottom: var(--zev-space-4);
  background: var(--zev-surface-raised);
  border: var(--zev-border-width) solid var(--zev-border);
  border-radius: var(--zev-radius);
}

/* La búsqueda crece; los demás campos ocupan lo suyo.

   El min-width no es 0: con 0 el campo se encogía hasta cortar su
   propio placeholder ("Orden, código TC, placa, marca o modelo"
   quedaba en "...marca o mod"), que es justo el texto que dice por
   qué campos se puede buscar. Con el mínimo puesto, la barra
   envuelve antes de recortar.

   El mínimo va en rem y NO como min(26rem, 100%): ese 100% se
   resuelve contra el ancho del padre, que a su vez depende del
   contenido, y con la referencia circular el navegador deja de
   poder calcular el mínimo de contenido -- el contenedor se
   encoge por debajo de sus hijos y el botón de al lado se sale.
   En pantalla angosta el mínimo se suelta más abajo, con una
   media query. */
.zev-filtros__buscar {
  position: relative;
  flex: 1 1 26rem;
  min-width: 26rem;
}

/* En la cabecera de un panel el campo comparte renglón con el
   botón y el placeholder es más corto: el mismo mínimo de 22rem
   ahí empujaba el botón a una segunda línea. */
.zev-filtros__buscar--corto {
  flex: 0 1 18rem;
  min-width: 18rem;
}

.zev-filtros__buscar .bi-search {
  position: absolute;
  left: 0.6rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--zev-gray-600);
  pointer-events: none;
}

.zev-filtros__buscar .zev-input {
  padding-left: 2rem;
}

.zev-filtros__campo {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.zev-filtros__acciones {
  display: flex;
  gap: var(--zev-space-2);
  margin-left: auto;
}

/* La lista de la facturación es un campo de varios renglones: va en
   su propia línea de la barra, plegada mientras no se use para no
   robarle la vista a los filtros de todos los días. */
.zev-filtros__lista {
  flex: 1 1 100%;
}

.zev-filtros__lista > summary {
  cursor: pointer;
  width: fit-content;
  margin-bottom: var(--zev-space-2);
}

.zev-filtros__lista textarea {
  resize: vertical;
}

/* --- Selección múltiple (códigos TC, órdenes) ---
   Un <select multiple> obliga a Ctrl+clic, no dice cuántos hay
   elegidos y no se puede buscar. Esto es un desplegable con
   casillas de verdad adentro: van dentro del formulario GET y el
   navegador las manda como TC=…&TC=… (Regla 2). El módulo
   filtro-multiple solo agrega el filtrado y el resumen al día. */

.zev-multi__disparador {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--zev-space-2);
  width: 13rem;
  max-width: 100%;
  text-align: left;
  cursor: pointer;
}

.zev-multi__resumen {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.zev-multi__disparador .bi-chevron-down {
  flex-shrink: 0;
  font-size: 0.75em;
  color: var(--zev-gray-600);
  transition: transform var(--zev-dur) var(--zev-ease);
}

.zev-multi__disparador[aria-expanded="true"] {
  border-color: var(--zev-azul-profundo);
}

.zev-multi__disparador[aria-expanded="true"] .bi-chevron-down {
  transform: rotate(180deg);
}

.zev-multi__panel {
  width: 22rem;
  max-width: calc(100vw - 2rem);
  padding: 0;
}

.zev-multi__buscar {
  padding: var(--zev-space-2);
  border-bottom: var(--zev-border-width) solid var(--zev-border);
}

.zev-multi__lista {
  max-height: 16rem;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--zev-space-1) 0;
}

/* Casilla y texto son un solo blanco: el <label> envuelve a los dos. */
.zev-multi__opcion {
  display: flex;
  align-items: center;
  gap: var(--zev-space-2);
  margin: 0;
  padding: 0.35rem var(--zev-space-3);
  font-size: var(--zev-text-sm);
  cursor: pointer;
}

.zev-multi__opcion:hover,
.zev-multi__opcion:has(input:focus-visible) {
  background: var(--zev-gray-100);
  box-shadow: inset 3px 0 0 0 var(--zev-celeste);
}

.zev-multi__opcion input {
  flex-shrink: 0;
  margin: 0;
  accent-color: var(--zev-azul-profundo);
}

.zev-multi__opcion .zev-dato {
  min-width: 0;
  overflow-wrap: anywhere;
}

.zev-multi__detalle {
  flex-shrink: 0;
  margin-left: auto;
  font-size: var(--zev-text-2xs);
  color: var(--zev-gray-600);
}

.zev-multi__vacio {
  margin: 0;
  padding: var(--zev-space-3);
  font-size: var(--zev-text-xs);
  color: var(--zev-gray-600);
}

.zev-multi__pie {
  display: flex;
  justify-content: space-between;
  gap: var(--zev-space-2);
  padding: var(--zev-space-2);
  border-top: var(--zev-border-width) solid var(--zev-border);
}

.zev-multi__masivo {
  display: flex;
  gap: var(--zev-space-1);
}

/* --- Período: un día, un mes, un año o un rango ---
   El modo es la misma escala de radios de la inspección, y solo
   se ve el campo del modo elegido: por CSS con :has(), sin JS. Si
   el navegador no entiende :has() se ven todos los campos, que
   sigue funcionando. Los atajos son botones de envío: un clic y
   ya filtra, y el que coincide con lo vigente queda marcado. */

/* Sin línea divisoria: el período es un filtro más de la misma
   barra, y con el filo encima se leía como un bloque aparte. */
.zev-periodo {
  flex: 1 1 100%;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

.zev-periodo__fila {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--zev-space-2) var(--zev-space-3);
}

.zev-periodo__modos .zev-escala__opcion {
  min-width: 4.25rem;
}

.zev-periodo__modos .zev-escala__opcion:has(input:checked) {
  color: #ffffff;
  background: var(--zev-superficie-oscura);
}

.zev-periodo__valor {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--zev-space-2);
}

.zev-periodo__valor .zev-input {
  width: auto;
}

.zev-periodo__valor label {
  margin: 0;
  font-size: var(--zev-text-xs);
  color: var(--zev-gray-600);
}

.zev-periodo:has([data-periodo-modo]:checked) .zev-periodo__valor {
  display: none;
}

.zev-periodo:has([data-periodo-modo="dia"]:checked) [data-periodo="dia"],
.zev-periodo:has([data-periodo-modo="mes"]:checked) [data-periodo="mes"],
.zev-periodo:has([data-periodo-modo="anio"]:checked) [data-periodo="anio"],
.zev-periodo:has([data-periodo-modo="rango"]:checked) [data-periodo="rango"] {
  display: flex;
}

.zev-periodo__atajos {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--zev-space-1);
}

.zev-periodo__atajos-titulo {
  margin-right: var(--zev-space-1);
  font-size: var(--zev-text-xs);
  color: var(--zev-gray-600);
}

.zev-periodo__atajo {
  min-height: 34px;
  padding: 0 var(--zev-space-3);
  font-size: var(--zev-text-xs);
  font-weight: 600;
  color: var(--zev-ink);
  background: transparent;
  border: var(--zev-border-width) solid var(--zev-border-fuerte);
  border-radius: var(--zev-radius-sm);
  cursor: pointer;
  transition: background-color var(--zev-dur) var(--zev-ease),
              border-color var(--zev-dur) var(--zev-ease);
}

.zev-periodo__atajo:hover {
  background: var(--zev-gray-100);
  border-color: var(--zev-ink);
}

.zev-periodo__atajo:focus-visible {
  outline: 2px solid var(--zev-ink);
  outline-offset: 2px;
}

.zev-periodo__atajo[aria-current="true"] {
  color: #ffffff;
  background: var(--zev-superficie-oscura);
  border-color: var(--zev-superficie-oscura);
}

@media (max-width: 575.98px) {
  .zev-periodo__atajos {
    margin-left: 0;
  }

  .zev-multi__disparador {
    width: 100%;
  }
}

@media (pointer: coarse) {
  .zev-periodo__atajo,
  .zev-multi__opcion {
    min-height: 44px;
  }
}

/* Iniciales de una persona en una celda. Cuadrada, no un círculo:
   el redondeo uniforme es justo lo que hace genérica una interfaz
   (§3), y acá además alinea con el resto de la fila. */
/* Como disparador del menú de la cuenta la inicial es un botón:
   hereda el cuadrado y el mono, y agrega el foco y el estado
   abierto que el ícono genérico de persona no tenía. */
.zev-menu-btn--cuenta {
  width: auto;
  height: auto;
  padding: 0;
  border-color: transparent;
  background: none;
}

.zev-menu-btn--cuenta:hover,
.zev-menu-btn--cuenta[aria-expanded="true"] {
  background: none;
  border-color: transparent;
}

.zev-menu-btn--cuenta .zev-inicial {
  border: var(--zev-border-width) solid transparent;
  transition: box-shadow var(--zev-dur) var(--zev-ease);
}

.zev-menu-btn--cuenta:hover .zev-inicial,
.zev-menu-btn--cuenta[aria-expanded="true"] .zev-inicial {
  box-shadow: inset 0 -3px 0 0 var(--zev-celeste);
}

.zev-inicial {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-xs);
  font-weight: 700;
  color: var(--zev-gray-50);
  background: var(--zev-azul-profundo);
  border-radius: var(--zev-radius-sm);
}

/* ============================================================
   Menú de acciones de fila. Antes cada fila llevaba cuatro
   botones de colores distintos compitiendo entre sí; con veinte
   filas eso son ochenta manchas de color peleando con los datos,
   que es lo que la gente vino a leer. Ahora es un solo botón de
   tres puntos y el color queda para lo que significa algo.

   El comportamiento lo pone el dropdown de Bootstrap, que ya está
   cargado; acá va solo el aspecto, en clases propias (Regla 7).
   ============================================================ */

.zev-menu-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.9rem;
  height: 1.9rem;
  padding: 0;
  color: var(--zev-gray-600);
  background: transparent;
  border: var(--zev-border-width) solid transparent;
  border-radius: var(--zev-radius-sm);
  cursor: pointer;
  transition: background-color var(--zev-dur) var(--zev-ease),
              border-color var(--zev-dur) var(--zev-ease);
}

.zev-menu-btn:hover,
.zev-menu-btn[aria-expanded="true"] {
  color: var(--zev-ink);
  background: var(--zev-gray-100);
  border-color: var(--zev-border-fuerte);
}

.zev-menu-btn:focus-visible {
  outline: 2px solid var(--zev-ink);
  outline-offset: 2px;
}

.zev-menu {
  min-width: 12rem;
  padding: 0 0 var(--zev-space-1);
  background: var(--zev-surface-raised);
  border: var(--zev-border-width) solid var(--zev-border-fuerte);
  border-radius: var(--zev-radius);
  /* Desplazada y sin desenfoque. La sombra difusa de --zev-shadow
     está bien pegada a la página (paneles, toasts), pero un menú
     flota sobre el contenido y con ella se leía como el dropdown
     de cualquier librería. El filo duro es el gesto de la casa. */
  box-shadow: 3px 3px 0 0 rgba(22, 32, 42, 0.12);
}

/* De qué registro es este menú. Con veinticinco filas iguales y el
   menú flotando encima, sin esto hay que acordarse cuál se abrió.
   Es el mismo encabezado en monoespaciada de las secciones de la
   paleta: los dos son una lista de opciones. */
.zev-menu__titulo {
  max-width: 18rem;
  margin: 0;
  padding: var(--zev-space-2) var(--zev-space-3);
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--zev-gray-600);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  border-bottom: var(--zev-border-width) solid var(--zev-border);
}

/* Segunda línea del encabezado: el rol, el correo, lo que ubique
   sin ser el título. */
.zev-menu__nota {
  margin: 0;
  padding: 0 var(--zev-space-3) var(--zev-space-2);
  font-size: var(--zev-text-2xs);
  color: var(--zev-gray-600);
  border-bottom: var(--zev-border-width) solid var(--zev-border);
}

.zev-menu__titulo + .zev-menu__nota {
  margin-top: calc(-1 * var(--zev-border-width));
  padding-top: 0.2rem;
  border-top: 0;
}

.zev-menu__item {
  display: flex;
  align-items: center;
  gap: var(--zev-space-2);
  width: 100%;
  padding: 0.4rem var(--zev-space-3);
  font-size: var(--zev-text-sm);
  color: var(--zev-ink);
  text-align: left;
  text-decoration: none;
  background: none;
  border: 0;
  cursor: pointer;
}

.zev-menu__item i {
  width: 1rem;
  color: var(--zev-gray-600);
}

/* El filo celeste a la izquierda del ítem apuntado: el mismo
   gesto que marca la opción activa de la paleta. Un fondo gris a
   secas es lo que hace cualquier menú. */
.zev-menu__item:hover,
.zev-menu__item:focus-visible {
  color: var(--zev-ink);
  background: var(--zev-gray-100);
  box-shadow: inset 3px 0 0 0 var(--zev-celeste);
}

.zev-menu__item:hover i,
.zev-menu__item:focus-visible i {
  color: var(--zev-ink);
}

.zev-menu__item:focus-visible {
  outline: 2px solid var(--zev-ink);
  outline-offset: -2px;
}

/* Lo destructivo se lee como destructivo, y va último y separado
   para que no se elija por inercia. */
.zev-menu__item--peligro {
  color: var(--zev-danger);
}

.zev-menu__item--peligro i {
  color: var(--zev-danger);
}

.zev-menu__item--peligro:hover,
.zev-menu__item--peligro:focus-visible {
  color: var(--zev-danger);
  background: var(--zev-danger-bg);
  box-shadow: inset 3px 0 0 0 var(--zev-danger);
}

.zev-menu__item--peligro:hover i,
.zev-menu__item--peligro:focus-visible i {
  color: var(--zev-danger);
}

.zev-menu__sep {
  height: var(--zev-border-width);
  margin: var(--zev-space-1) 0;
  background: var(--zev-border);
}

/* Columnas que no pueden encogerse hasta romper su contenido (una
   celda con un campo editable adentro, una lista de vehículos). Van
   como clase y no como style= inline, que la Regla 7 prohíbe. */
.zev-table .zev-col-ancha { min-width: 16rem; }

/* Consolidado: el número de orden («CMP-B-4-4.5-2026-OM-00803») se partía
   en cinco renglones cuando la tabla apretaba. Con este mínimo queda en
   dos, y la composición va debajo en fila. El vehículo cede primero. */
.zev-table .zev-col-orden { min-width: 8.5rem; }
.zev-table .zev-col-vehiculo { min-width: 7rem; }

/* Tabla ancha de montos: el relleno lateral de celda baja de 0.6 a
   0.4rem. Con once columnas son ~40px, justo lo que faltaba para que
   entre a 1280px con la barra lateral abierta. Los bordes de la tabla
   conservan su gutter. */
.zev-table--compacta thead th:not(:first-child):not(:last-child),
.zev-table--compacta tbody td:not(:first-child):not(:last-child),
.zev-table--compacta tfoot td:not(:first-child):not(:last-child) {
  padding-left: 0.4rem;
  padding-right: 0.4rem;
}

/* El chevron del detalle ya tiene su propia caja: no necesita relleno a la izquierda. */
.zev-table--compacta > tbody > tr > td.zev-acciones,
.zev-table--compacta > thead > tr > th.zev-acciones {
  padding-left: 0;
}

.zev-composicion {
  display: flex;
  flex-wrap: wrap;
  gap: var(--zev-space-1);
  margin-top: var(--zev-space-1);
}

.zev-table thead abbr[title] {
  text-decoration: none;
  cursor: help;
}
.zev-table .zev-col-media { min-width: 8rem; }

/* Chevron de una fila desplegable. Gira con CSS a partir del
   aria-expanded que Bootstrap ya mantiene: no hace falta un
   <script> que escuche show/hide para eso. */
.zev-desplegar .bi {
  transition: transform var(--zev-dur) var(--zev-ease);
}

.zev-desplegar[aria-expanded="true"] .bi {
  transform: rotate(180deg);
}

/* La fila que solo contiene el detalle desplegable no se pinta ni
   se marca como una fila más: mientras está cerrada no existe. */
.zev-table tbody tr.zev-fila-detalle,
.zev-table tbody tr.zev-fila-detalle:hover {
  background: var(--zev-surface);
}

.zev-table tbody tr.zev-fila-detalle > td {
  padding: 0;
  border-bottom: 0;
}

.zev-table tbody tr.zev-fila-detalle > td:first-child::before {
  content: none;
}

.zev-table tbody tr.zev-fila-detalle .collapse.show,
.zev-table tbody tr.zev-fila-detalle .collapsing {
  padding: var(--zev-space-4);
  border-bottom: var(--zev-border-width) solid var(--zev-border);
}

/* La celda de acciones no crece: es una columna de ancho fijo al
   final de la fila. */
/* La fila entera abre el registro (ver modulos/fila-enlace.js). El cursor es lo
   que lo anuncia; el enlace de la primera celda sigue siendo el camino de teclado. */
.zev-table tbody tr[data-href] {
  cursor: pointer;
}

/* La celda de acciones no participa: ahí se apunta a un botón, no a la fila. */
.zev-table tbody tr[data-href] .zev-acciones {
  cursor: auto;
}

/* Botón destacado + menú, en la misma celda y sin separarse al final de la fila. */
.zev-acciones-fila {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--zev-space-1);
}

.zev-table .zev-acciones {
  width: 1%;
  text-align: right;
  white-space: nowrap;
}

/* ============================================================
   Modal de confirmación. Reemplaza a las siete páginas
   Delete.cshtml: preguntar "¿seguro?" no merece una navegación,
   una pantalla propia y un botón Volver.

   El comportamiento es el modal de Bootstrap; el aspecto se ajusta
   por sus variables --bs-modal-* (Regla 7: no se redefine
   .modal-content).
   ============================================================ */

.zev-modal {
  --bs-modal-bg: var(--zev-surface-raised);
  --bs-modal-border-color: var(--zev-border-fuerte);
  --bs-modal-border-radius: var(--zev-radius);
  --bs-modal-inner-border-radius: var(--zev-radius-sm);
  --bs-modal-header-border-color: var(--zev-border);
  --bs-modal-footer-border-color: var(--zev-border);
  --bs-modal-box-shadow: var(--zev-shadow);
}

.zev-modal__titulo {
  margin: 0;
  font-family: var(--zev-font-display);
  font-size: var(--zev-text-lg);
  font-weight: 900;
}

/* Lo que se va a borrar, textualmente: el nombre del registro en
   monoespaciada, para que se pueda contrastar con la fila de la
   que se salió antes de confirmar. */
.zev-modal__objeto {
  padding: var(--zev-space-3);
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-sm);
  background: var(--zev-gray-50);
  background-image: var(--zev-hatch);
  border: var(--zev-border-width) solid var(--zev-border);
  border-radius: var(--zev-radius-sm);
}

.zev-modal__aviso {
  margin: var(--zev-space-3) 0 0;
  font-size: var(--zev-text-sm);
  color: var(--zev-gray-600);
}

/* ============================================================
   Paginación. Números, no "‹ 1 2 3 ›" con globitos: es un
   instrumento, y el número de página es un dato.
   ============================================================ */

.zev-paginacion {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--zev-space-1);
  padding: var(--zev-space-3) var(--zev-space-4);
  border-top: var(--zev-border-width) solid var(--zev-border);
}

.zev-paginacion__info {
  margin-right: auto;
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-xs);
  color: var(--zev-gray-600);
}

.zev-paginacion__item {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.9rem;
  height: 1.9rem;
  padding: 0 0.4rem;
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-xs);
  font-weight: 500;
  color: var(--zev-gray-700);
  text-decoration: none;
  border: var(--zev-border-width) solid var(--zev-border);
  border-radius: var(--zev-radius-sm);
  transition: background-color var(--zev-dur) var(--zev-ease),
              border-color var(--zev-dur) var(--zev-ease);
}

.zev-paginacion__item:hover {
  color: var(--zev-ink);
  background: var(--zev-gray-100);
  border-color: var(--zev-border-fuerte);
}

.zev-paginacion__item:focus-visible {
  outline: 2px solid var(--zev-ink);
  outline-offset: 2px;
}

.zev-paginacion__item--activa {
  color: var(--zev-gray-50);
  background: var(--zev-superficie-oscura);
  border-color: var(--zev-superficie-oscura);
}

.zev-paginacion__item--activa:hover {
  color: var(--zev-gray-50);
  background: var(--zev-superficie-oscura);
}

.zev-paginacion__item--inerte {
  color: var(--zev-gray-600);
  pointer-events: none;
}

/* Salto entre bloques de páginas: no es un botón. */
.zev-paginacion__gap {
  padding: 0 0.2rem;
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-xs);
  color: var(--zev-gray-600);
}

/* En tablet, con guante y a la intemperie, el dedo no acierta un
   objetivo de 28px. Donde el puntero es grueso todo lo que se
   toca crece a 44px, sin engordar la densidad del escritorio. */
@media (pointer: coarse) {
  .zev-btn,
  .zev-input,
  .zev-toast__close {
    min-height: 44px;
  }

  /* El menú de la fila y su disparador: 30px de botón y 32px de ítem no se
     aciertan con guante, y son justo lo que se usa al recibir el vehículo. */
  .zev-menu-btn {
    width: 44px;
    height: 44px;
  }

  .zev-menu__item {
    min-height: 44px;
    padding-top: 0.6rem;
    padding-bottom: 0.6rem;
  }

  .zev-btn--sm {
    padding-left: 0.9rem;
    padding-right: 0.9rem;
  }

  .zev-table tbody td {
    padding-top: 0.7rem;
    padding-bottom: 0.7rem;
  }
}

/* Quien pidió menos movimiento, recibe menos movimiento. */
@media (prefers-reduced-motion: reduce) {
  .zev-btn,
  .zev-btn::after,
  .zev-input,
  .zev-table tbody tr,
  .zev-table tbody td:first-child::before,
  .zev-toast__close {
    transition: none;
  }
}

/* ============================================================
   EL SHELL: barra lateral por fase del flujo + barra superior.
   La lateral es oscura y el contenido claro: el marco de trabajo
   se distingue del trabajo mismo de un vistazo, y la navegación
   deja de competir con los datos.
   ============================================================ */

.zev-app {
  display: flex;
  min-height: 100vh;
  background: var(--zev-surface);
}

/* Salto al contenido: visible solo cuando se lo enfoca con el
   teclado, primero en el orden de tabulación. */
.zev-skip {
  position: absolute;
  left: -9999px;
  z-index: 1080;
  padding: var(--zev-space-2) var(--zev-space-4);
  background: var(--zev-superficie-oscura);
  color: #fff;
}

.zev-skip:focus {
  left: var(--zev-space-2);
  top: var(--zev-space-2);
}

/* --- Barra lateral --- */

.zev-sidebar {
  position: sticky;
  top: 0;
  z-index: 1030;
  display: flex;
  flex-direction: column;
  flex: none;
  width: 15.5rem;
  height: 100vh;
  background: var(--zev-superficie-oscura);
  color: rgba(255, 255, 255, 0.78);
  transition: width var(--zev-dur) var(--zev-ease);
}

/* La placa de la marca. Es clara y del mismo alto y borde que la
   topbar, así que las dos forman una sola banda blanca cruzando
   el tope de la aplicación, con el logo a la izquierda: un
   membrete, no un recuadro suelto.

   Antes era oscura como el resto de la lateral y el logo se leía
   con filter: invert(1). Invertir un logo no lo aclara: le da
   vuelta los colores, y el azul y el rojo de la franja salían
   naranja y celeste -- la marca al revés, justo en el único lugar
   donde aparece completa. */
.zev-sidebar__marca {
  display: flex;
  align-items: center;
  gap: var(--zev-space-2);
  /* El mismo alto que la topbar, fijado por el mismo valor en las
     dos: si dependiera del contenido, las dos mitades de la banda
     se desalinearían apenas cambie un botón. */
  min-height: var(--zev-alto-banda);
  padding: var(--zev-space-2) var(--zev-space-3);
  background: var(--zev-surface-raised);
  border-bottom: var(--zev-border-width) solid var(--zev-border);
}

.zev-sidebar__logo {
  height: 1.6rem;
  /* Tope para logos más apaisados que el de Quito (Guayaquil): sin él empujan la ciudad fuera. */
  max-width: 8rem;
  object-fit: contain;
}

/* Con la lateral colapsada el logo completo no entra: en su lugar
   queda la franja, que es la parte reconocible de la marca. */
.zev-sidebar__marca-compacta {
  display: none;
  width: 1.4rem;
  height: 1.4rem;
  border-radius: var(--zev-radius-sm);
}

/* Sobre la placa clara el celeste de la marca da 2.6:1 y no se
   lee: va el mismo tono bajado hasta pasar AA. */
.zev-sidebar__ciudad {
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-2xs);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--zev-celeste-texto);
}

.zev-sidebar__nav {
  flex: 1;
  overflow-y: auto;
  padding: var(--zev-space-3) 0;
  /* Sobre el fondo oscuro de la lateral, el pulgar claro del resto
     de la app sería un tajo blanco. */
  scrollbar-color: rgba(255, 255, 255, 0.18) transparent;
}

.zev-sidebar__nav::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.18);
  background-clip: padding-box;
}

.zev-sidebar__nav::-webkit-scrollbar-thumb:hover {
  background: rgba(255, 255, 255, 0.35);
  background-clip: padding-box;
}

.zev-sidebar__pie {
  padding: var(--zev-space-3);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.zev-nav-fase {
  padding: var(--zev-space-3) var(--zev-space-3) var(--zev-space-1);
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: rgba(255, 255, 255, 0.38);
  white-space: nowrap;
}

.zev-nav-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.45rem var(--zev-space-3);
  font-size: var(--zev-text-sm);
  color: rgba(255, 255, 255, 0.74);
  text-decoration: none;
  white-space: nowrap;
  transition: background-color var(--zev-dur) var(--zev-ease),
              color var(--zev-dur) var(--zev-ease);
}

.zev-nav-item i {
  flex: none;
  width: 1.1rem;
  font-size: 1rem;
  text-align: center;
}

.zev-nav-item:hover,
.zev-nav-item:focus-visible {
  background: rgba(255, 255, 255, 0.07);
  color: #fff;
}

.zev-nav-item:focus-visible {
  outline: 2px solid var(--zev-celeste);
  outline-offset: -2px;
}

.zev-nav-item--activo {
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
  font-weight: 600;
}

/* El acento diagonal marca dónde está uno parado: mismo gesto que
   en la fila apuntada de una tabla y en el filo del botón. */
.zev-nav-item--activo::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  background: var(--zev-tricolor);
}

/* Colapsada: solo íconos. El texto se oculta sin sacarlo del DOM,
   así el lector de pantalla lo sigue anunciando. */
.zev-app[data-sidebar="colapsada"] .zev-sidebar {
  width: 3.5rem;
}

.zev-app[data-sidebar="colapsada"] .zev-sidebar__texto,
.zev-app[data-sidebar="colapsada"] .zev-nav-fase {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.zev-app[data-sidebar="colapsada"] .zev-nav-item {
  justify-content: center;
  padding-left: 0;
  padding-right: 0;
}

.zev-app[data-sidebar="colapsada"] .zev-sidebar__marca {
  justify-content: center;
  padding-left: 0;
  padding-right: 0;
}

.zev-app[data-sidebar="colapsada"] .zev-sidebar__logo {
  display: none;
}

.zev-app[data-sidebar="colapsada"] .zev-sidebar__marca-compacta {
  display: block;
}

/* Separa los grupos cuando ya no hay título de fase que los
   separe. */
.zev-app[data-sidebar="colapsada"] .zev-nav-fase {
  margin-top: var(--zev-space-2);
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

/* --- Columna de contenido --- */

.zev-main {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
}

.zev-topbar {
  position: sticky;
  top: 0;
  z-index: 1020;
  display: flex;
  align-items: center;
  gap: var(--zev-space-2);
  min-height: var(--zev-alto-banda);
  padding: var(--zev-space-2) var(--zev-space-6);
  background: var(--zev-surface-raised);
  border-bottom: var(--zev-border-width) solid var(--zev-border);
}

.zev-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 2rem;
  height: 2rem;
  font-size: 1.05rem;
  color: var(--zev-gray-600);
  background: none;
  border: var(--zev-border-width) solid transparent;
  border-radius: var(--zev-radius);
  cursor: pointer;
  transition: background-color var(--zev-dur) var(--zev-ease),
              color var(--zev-dur) var(--zev-ease);
}

.zev-icon-btn:hover {
  background: var(--zev-gray-100);
  color: var(--zev-ink);
}

.zev-icon-btn:focus-visible {
  outline: 2px solid var(--zev-ink);
  outline-offset: 2px;
}

.zev-buscador {
  position: relative;
  flex: 1 1 22rem;
  max-width: 30rem;
  /* Sin esto el mínimo automático del botón es su texto completo y
     en un teléfono la topbar entera se sale de la pantalla. Acá el
     texto sí puede recortarse: el disparador dice a dónde lleva, no
     es un dato. */
  min-width: 0;
}

.zev-buscador i {
  position: absolute;
  left: 0.6rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--zev-gray-600);
  pointer-events: none;
}

.zev-buscador .zev-input {
  padding-left: 2rem;
}

/* El disparador de la paleta: se lee como el campo que había antes,
   pero es un botón. Un <input> en el header que abre un modal con
   otro <input> son dos campos para un solo estado (Regla 1). */
.zev-buscador__disparador {
  display: flex;
  align-items: center;
  gap: var(--zev-space-2);
  width: 100%;
  padding: 0.5rem 0.5rem 0.5rem 2rem;
  font-family: inherit;
  font-size: var(--zev-text-sm);
  color: var(--zev-gray-600);
  text-align: left;
  background: var(--zev-surface-raised);
  border: var(--zev-border-width) solid var(--zev-border-fuerte);
  border-radius: var(--zev-radius);
  cursor: pointer;
  transition: border-color var(--zev-dur) var(--zev-ease),
              color var(--zev-dur) var(--zev-ease);
}

.zev-buscador__texto {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.zev-buscador__disparador:hover {
  color: var(--zev-ink);
  border-color: var(--zev-ink);
}

.zev-buscador__disparador:focus-visible {
  outline: 2px solid var(--zev-ink);
  outline-offset: 2px;
}

/* Recordatorio del atajo, dentro del propio campo. */
.zev-atajo {
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-2xs);
  font-weight: 700;
  color: var(--zev-gray-600);
  padding: 0.1rem 0.35rem;
  border: var(--zev-border-width) solid var(--zev-border-fuerte);
  border-radius: var(--zev-radius-sm);
  white-space: nowrap;
}

.zev-migas {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  padding: var(--zev-space-3) var(--zev-space-6) 0;
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-2xs);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--zev-gray-600);
}

.zev-migas a {
  color: var(--zev-gray-600);
  text-decoration: none;
}

.zev-migas a:hover {
  color: var(--zev-ink);
  text-decoration: underline;
}

/* El aire de la página lo pone el shell, no cada vista. Antes esto
   era solo `flex: 1` y el contenido quedaba pegado a la barra
   lateral: las vistas viejas traían su propio `container-fluid py-4`
   y las nuevas, que ya no lo necesitan, no tenían margen ninguno.
   Va abajo más que arriba: la página termina en la última fila y el
   ojo necesita saber que ahí se acabó. */
.zev-contenido {
  flex: 1;
  padding: var(--zev-space-4) var(--zev-space-6) var(--zev-space-8);
  /* La barra de guardado vive pegada abajo: sin esto, tabular hasta el último campo
     del formulario lo dejaba justo debajo de la barra, con el foco invisible. */
  scroll-padding-bottom: 6rem;
}

/* Pantalla ancha: más aire lateral. La densidad es de la tabla, no
   del margen. */
@media (min-width: 1400px) {
  .zev-contenido {
    padding-left: var(--zev-space-8);
    padding-right: var(--zev-space-8);
  }

  .zev-migas,
  .zev-topbar {
    padding-left: var(--zev-space-8);
    padding-right: var(--zev-space-8);
  }
}

/* Los toasts flotan sobre el contenido, arriba a la derecha, sin
   empujar la página. */
.zev-toast-stack--flotante {
  position: fixed;
  top: var(--zev-space-4);
  right: var(--zev-space-4);
  z-index: 1060;
}

/* En móvil la lateral sale por encima del contenido. */
@media (max-width: 991.98px) {
  .zev-contenido {
    padding: var(--zev-space-3) var(--zev-space-4) var(--zev-space-6);
  }

  .zev-migas {
    padding-left: var(--zev-space-4);
    padding-right: var(--zev-space-4);
  }

  .zev-topbar {
    padding-left: var(--zev-space-3);
    padding-right: var(--zev-space-3);
  }

  .zev-sidebar {
    position: fixed;
    left: 0;
    top: 0;
    transform: translateX(-100%);
    transition: transform 180ms var(--zev-ease);
  }

  .zev-app[data-sidebar="abierta"] .zev-sidebar {
    transform: translateX(0);
  }

  /* Colapsada no aplica en móvil: o está fuera, o está encima. */
  .zev-app[data-sidebar="colapsada"] .zev-sidebar {
    width: 15.5rem;
  }

  .zev-app[data-sidebar="colapsada"] .zev-sidebar__texto,
  .zev-app[data-sidebar="colapsada"] .zev-nav-fase {
    position: static;
    width: auto;
    height: auto;
    clip-path: none;
  }

  .zev-app[data-sidebar="colapsada"] .zev-nav-item {
    justify-content: flex-start;
    padding-left: var(--zev-space-3);
    padding-right: var(--zev-space-3);
  }

  .zev-velo {
    position: fixed;
    inset: 0;
    z-index: 1025;
    background: rgba(22, 32, 42, 0.45);
  }
}

/* ============================================================
   Paleta de comandos (Ctrl+K)
   ============================================================ */

.zev-paleta {
  position: fixed;
  inset: 0;
  z-index: 1070;
  display: flex;
  justify-content: center;
  padding-top: 12vh;
  background: rgba(22, 32, 42, 0.4);
}

.zev-paleta[hidden] {
  display: none;
}

.zev-paleta__panel {
  display: flex;
  flex-direction: column;
  width: min(34rem, calc(100% - 2rem));
  max-height: 60vh;
  overflow: hidden;
  background: var(--zev-surface-raised);
  border: var(--zev-border-width) solid var(--zev-border-fuerte);
  border-radius: var(--zev-radius);
  box-shadow: 0 12px 32px rgba(22, 32, 42, 0.18);
}

/* El anillo va en el contenedor y no en el <input>, que no tiene borde propio:
   es el patrón de foco de un control compuesto (:focus-within). Antes el input
   llevaba outline:none y el foco no se veía en ninguna parte. */
.zev-paleta__campo:focus-within {
  outline: 2px solid var(--zev-ink);
  outline-offset: -2px;
}

.zev-paleta__campo {
  display: flex;
  align-items: center;
  gap: var(--zev-space-2);
  padding: var(--zev-space-3);
  border-bottom: var(--zev-border-width) solid var(--zev-border);
}

.zev-paleta__campo input {
  flex: 1;
  font-family: inherit;
  font-size: var(--zev-text-base);
  color: var(--zev-ink);
  background: none;
  border: none;
  outline: none;
}

.zev-paleta__lista {
  overflow-y: auto;
  margin: 0;
  padding: var(--zev-space-1) 0;
  list-style: none;
}

.zev-paleta__item {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  width: 100%;
  padding: 0.5rem var(--zev-space-3);
  font-size: var(--zev-text-sm);
  color: var(--zev-ink);
  text-align: left;
  background: none;
  border: none;
  cursor: pointer;
}

.zev-paleta__item i {
  flex: none;
  width: 1.1rem;
  color: var(--zev-gray-600);
  text-align: center;
}

.zev-paleta__item--activo,
.zev-paleta__item:hover {
  background: var(--zev-gray-100);
}

.zev-paleta__item--activo {
  box-shadow: inset 3px 0 0 0 var(--zev-celeste);
}

.zev-paleta__fase {
  margin-left: auto;
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-2xs);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--zev-gray-600);
}

.zev-paleta__vacio {
  padding: var(--zev-space-4);
  font-size: var(--zev-text-sm);
  color: var(--zev-gray-600);
  text-align: center;
}

/* Encabezado de sección de resultados: Órdenes de trabajo,
   Vehículos, Módulos. No es sticky a propósito -- taparía el ítem
   activo justo cuando scrollIntoView lo trae a la vista. */
.zev-paleta__seccion {
  padding: var(--zev-space-3) var(--zev-space-3) 0.3rem;
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--zev-gray-600);
}

/* Borde separador salvo en el primero: arriba del primero ya está
   el borde del campo de búsqueda. */
.zev-paleta__lista > .zev-paleta__seccion:not(:first-child) {
  margin-top: var(--zev-space-2);
  border-top: var(--zev-border-width) solid var(--zev-border);
}

/* Habilita la segunda línea sin romper el gap del ítem. */
.zev-paleta__texto {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* Placa, marca y fecha del resultado, debajo del título. */
.zev-paleta__detalle {
  font-size: var(--zev-text-2xs);
  color: var(--zev-gray-600);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ============================================================
   FORMULARIO LARGO: la hoja de recepción (Sesión 5).

   No es un asistente de pasos. El técnico llega con el vehículo
   delante y llena lo que puede en el orden que puede: la placa
   primero, las fotos cuando deja de llover, el kilometraje
   cuando abre la puerta. Un wizard obliga a un orden que el
   patio no respeta, así que son secciones en una sola página y
   un resumen al costado que dice qué falta.
   ============================================================ */

.zev-form {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 15rem;
  align-items: start;
  gap: var(--zev-space-6);
}

/* La pila de secciones. `zev-form__cuerpo` es la columna izquierda
   del formulario con resumen al costado; `zev-pila` es la misma
   pila cuando el formulario no lleva resumen, que son casi todos
   los de Crear/Editar. Un solo cuerpo de regla para las dos. */
.zev-form__cuerpo,
.zev-pila {
  display: flex;
  flex-direction: column;
  gap: var(--zev-space-4);
  min-width: 0;
}

.zev-form__lado {
  position: sticky;
  top: var(--zev-space-4);
}

/* Bajo 1200px el resumen no cabe al costado sin ahogar el
   formulario; pasa arriba, en horizontal. */
@media (max-width: 1199.98px) {
  .zev-form {
    grid-template-columns: minmax(0, 1fr);
  }

  .zev-form__lado {
    position: static;
    order: -1;
  }
}

/* --- Resumen: qué falta, sin tener que recorrer la página --- */

.zev-resumen {
  background: var(--zev-surface-raised);
  border: var(--zev-border-width) solid var(--zev-border);
  border-radius: var(--zev-radius);
  padding: var(--zev-space-3);
}

.zev-resumen__titulo {
  margin: 0 0 var(--zev-space-2);
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--zev-gray-600);
}

.zev-resumen__lista {
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin: 0 0 var(--zev-space-2);
  padding: 0;
  list-style: none;
}

@media (max-width: 1199.98px) {
  .zev-resumen__lista {
    flex-direction: row;
    flex-wrap: wrap;
    gap: var(--zev-space-1) var(--zev-space-3);
  }
}

.zev-resumen__item {
  display: flex;
  align-items: center;
  gap: var(--zev-space-2);
  padding: 0.3rem 0.4rem;
  font-size: var(--zev-text-sm);
  color: var(--zev-gray-600);
  text-decoration: none;
  border-radius: var(--zev-radius-sm);
  transition: background-color var(--zev-dur) var(--zev-ease);
}

.zev-resumen__item:hover {
  background: var(--zev-gray-100);
  color: var(--zev-ink);
}

.zev-resumen__item:focus-visible {
  outline: 2px solid var(--zev-ink);
  outline-offset: 2px;
}

/* El cuadrado se llena cuando la sección está resuelta. Cuadrado y
   no tilde: la misma señalética rectangular del resto (§3). */
.zev-resumen__marca {
  flex: 0 0 auto;
  width: 0.7rem;
  height: 0.7rem;
  border: 1px solid var(--zev-gray-400);
  border-radius: 1px;
  background: transparent;
}

.zev-resumen__item--listo {
  color: var(--zev-ink);
  font-weight: 600;
}

.zev-resumen__item--listo .zev-resumen__marca {
  background: var(--zev-success);
  border-color: var(--zev-success);
}

.zev-resumen__cuenta {
  margin-left: auto;
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-2xs);
  color: var(--zev-gray-600);
}

.zev-resumen__pie {
  margin: 0;
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-2xs);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--zev-gray-600);
}

/* --- Sección --- */

.zev-seccion {
  scroll-margin-top: var(--zev-space-4);
}

.zev-seccion__num {
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-2xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--zev-gray-600);
}

.zev-seccion__nota {
  margin: 0 0 var(--zev-space-3);
  font-size: var(--zev-text-sm);
  color: var(--zev-gray-600);
}

/* --- Rejilla de campos: sin .row/.col de Bootstrap. Las columnas
       se acomodan solas y no hay que elegir col-md-4 a mano. --- */

.zev-campos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: var(--zev-space-4);
}

.zev-campo {
  min-width: 0;
}

.zev-campo--ancho {
  grid-column: 1 / -1;
}

/* Interruptor: la casilla de Bootstrap es redonda y pastel; esta
   es un riel recto con el mismo filo del resto. */
.zev-switch {
  display: inline-flex;
  align-items: center;
  gap: var(--zev-space-2);
  cursor: pointer;
  font-size: var(--zev-text-sm);
  font-weight: 600;
}

.zev-switch input {
  appearance: none;
  flex: 0 0 auto;
  width: 2.4rem;
  height: 1.3rem;
  margin: 0;
  background: var(--zev-gray-200);
  border: var(--zev-border-width) solid var(--zev-border-fuerte);
  border-radius: var(--zev-radius-sm);
  position: relative;
  cursor: pointer;
  transition: background-color var(--zev-dur) var(--zev-ease);
}

.zev-switch input::after {
  content: "";
  position: absolute;
  top: 1px;
  left: 1px;
  width: calc(1.3rem - 6px);
  height: calc(1.3rem - 6px);
  background: var(--zev-surface-raised);
  border-radius: 1px;
  transition: transform var(--zev-dur) var(--zev-ease);
}

.zev-switch input:checked {
  background: var(--zev-azul-profundo);
  border-color: var(--zev-azul-profundo);
}

.zev-switch input:checked::after {
  transform: translateX(1.1rem);
}

.zev-switch input:focus-visible {
  outline: 2px solid var(--zev-ink);
  outline-offset: 2px;
}

/* --- Checklist de componentes: veintitrés casillas que se leen de
       un vistazo y, al marcarse, piden cuántos. --- */

/* Las líneas internas son bordes de cada casilla y no el fondo de la rejilla
   asomando por el gap: 23 casillas no llenan un número entero de filas y la
   celda sobrante quedaba pintada como un rectángulo gris suelto. Los bordes
   van arriba y a la izquierda con margen negativo, así no se duplican contra
   el marco. */
.zev-checklist {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
  background: var(--zev-surface-raised);
  border: var(--zev-border-width) solid var(--zev-border);
  border-radius: var(--zev-radius);
  overflow: hidden;
}

.zev-check {
  display: flex;
  align-items: center;
  gap: var(--zev-space-2);
  padding: 0.45rem var(--zev-space-3);
  margin: -1px 0 0 -1px;
  border-top: var(--zev-border-width) solid var(--zev-border);
  border-left: var(--zev-border-width) solid var(--zev-border);
  background: var(--zev-surface-raised);
  font-size: var(--zev-text-sm);
  transition: background-color var(--zev-dur) var(--zev-ease);
}

.zev-check:hover {
  background: var(--zev-gray-50);
}

.zev-check__input {
  appearance: none;
  flex: 0 0 auto;
  width: 1.05rem;
  height: 1.05rem;
  margin: 0;
  border: var(--zev-border-width) solid var(--zev-border-fuerte);
  border-radius: 1px;
  background: var(--zev-surface-raised);
  cursor: pointer;
}

.zev-check__input:checked {
  background-color: var(--zev-azul-profundo);
  border-color: var(--zev-azul-profundo);
  background-image: linear-gradient(45deg, transparent 45%, #fff 45%, #fff 55%, transparent 55%),
                    linear-gradient(-45deg, transparent 45%, #fff 45%, #fff 55%, transparent 55%);
}

.zev-check__input:focus-visible {
  outline: 2px solid var(--zev-ink);
  outline-offset: 2px;
}

.zev-check__nombre {
  flex: 1 1 auto;
  min-width: 0;
  cursor: pointer;
}

.zev-check__input:checked + .zev-check__nombre {
  font-weight: 600;
}

/* La cantidad aparece recién al marcar: veintitrés campos numéricos
   vacíos a la vez son ruido, y casi siempre la cantidad es 1. */
.zev-check__cant {
  flex: 0 0 3.2rem;
  width: 3.2rem;
  padding: 0.15rem 0.3rem;
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-xs);
  text-align: right;
  border: var(--zev-border-width) solid var(--zev-border-fuerte);
  border-radius: var(--zev-radius-sm);
  background: var(--zev-surface-raised);
  color: var(--zev-ink);
}

/* --- Trabajos a realizar --- */

.zev-trabajos {
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin: 0 0 var(--zev-space-3);
  padding: 0;
  list-style: none;
  background: var(--zev-border);
  border: var(--zev-border-width) solid var(--zev-border);
  border-radius: var(--zev-radius);
  overflow: hidden;
}

.zev-trabajos:empty {
  display: none;
}

.zev-trabajo {
  display: flex;
  align-items: center;
  gap: var(--zev-space-2);
  padding: 0.4rem var(--zev-space-3);
  background: var(--zev-surface-raised);
  font-size: var(--zev-text-sm);
}

.zev-trabajo__orden {
  flex: 0 0 1.6rem;
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-2xs);
  color: var(--zev-gray-600);
}

.zev-trabajo__texto {
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: anywhere;
}

.zev-trabajo__editor {
  flex: 1 1 auto;
  min-width: 0;
}

.zev-trabajo__acciones {
  display: flex;
  gap: var(--zev-space-1);
  margin-left: auto;
}

.zev-agregar {
  display: flex;
  gap: var(--zev-space-2);
}

.zev-agregar .zev-input {
  flex: 1 1 auto;
}

/* --- Lienzos: diagrama del vehículo y nivel de gasolina --- */

.zev-lienzos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
  gap: var(--zev-space-4);
}

.zev-lienzo__marco {
  background: var(--zev-surface-raised);
  background-image: var(--zev-hatch);
  border: var(--zev-border-width) solid var(--zev-border-fuerte);
  border-radius: var(--zev-radius);
  padding: var(--zev-space-2);
  text-align: center;
  overflow: auto;
}

/* touch-action: none es lo que hace que el dedo dibuje en vez de
   desplazar la página; sin esto, en tablet el trazo se corta a la
   primera y la hoja se va para abajo. */
.zev-lienzo__canvas {
  display: block;
  margin: 0 auto;
  max-width: 100%;
  height: auto;
  background: #fff;
  border: var(--zev-border-width) solid var(--zev-border);
  cursor: crosshair;
  touch-action: none;
}

.zev-lienzo__barra {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--zev-space-2);
  margin-top: var(--zev-space-2);
}

.zev-lienzo__barra .zev-input {
  width: auto;
}

/* Los colores de trazo se eligen como muestras, no en un <select>:
   con guante, apuntar a un color es un toque y no tres. */
.zev-tinta {
  display: flex;
  gap: var(--zev-space-1);
}

.zev-tinta__opcion {
  appearance: none;
  width: 1.6rem;
  height: 1.6rem;
  margin: 0;
  border: 2px solid var(--zev-border-fuerte);
  border-radius: var(--zev-radius-sm);
  cursor: pointer;
}

.zev-tinta__opcion--negro { background: #1c1915; }
.zev-tinta__opcion--rojo  { background: #e20816; }
.zev-tinta__opcion--azul  { background: #142850; }
.zev-tinta__opcion--verde { background: #1e7b34; }

.zev-tinta__opcion:checked {
  border-color: var(--zev-ink);
  box-shadow: inset 0 0 0 2px var(--zev-surface-raised);
}

.zev-tinta__opcion:focus-visible {
  outline: 2px solid var(--zev-ink);
  outline-offset: 2px;
}

/* --- Fotos y videos --- */

.zev-medios {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
  gap: var(--zev-space-3);
}

.zev-medios:empty {
  display: none;
}

.zev-medio {
  display: flex;
  flex-direction: column;
  border: var(--zev-border-width) solid var(--zev-border);
  border-radius: var(--zev-radius);
  overflow: hidden;
  background: var(--zev-surface-raised);
}

.zev-medio__vista {
  display: block;
  width: 100%;
  height: 9rem;
  object-fit: cover;
  background: var(--zev-gray-900);
}

/* La miniatura es el botón que abre el archivo entero. Es un <button> y no un
   div con onclick para que el teclado llegue igual que el dedo; pierde la caja
   del botón porque acá lo que se ve es la foto. */
.zev-medio__lupa {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
}

.zev-medio__lupa:focus-visible {
  outline: 2px solid var(--zev-ink);
  outline-offset: -2px;
}

/* ============================================================
   Visor: la foto, el video o el dibujo a tamaño completo. El
   <dialog> nativo pone el fondo, la tecla Esc y el foco atrapado;
   acá solo va la caja y la barra de abajo (modulos/visor.js).
   ============================================================ */

.zev-visor {
  width: min(92vw, 1100px);
  max-width: none;
  max-height: 92vh;
  padding: 0;
  border: var(--zev-border-width) solid var(--zev-border-fuerte);
  border-radius: var(--zev-radius);
  background: var(--zev-surface-raised);
  color: var(--zev-ink);
}

.zev-visor::backdrop {
  background: rgba(22, 32, 42, 0.82);
}

/* El fondo del marco es oscuro a propósito: una foto de taller recortada contra
   blanco se lee como parte de la página y no como la foto que se fue a mirar.
   Los dibujos son la excepción y la pone el visor: trazo oscuro sobre
   transparente contra fondo negro no se ve. */
.zev-visor__marco {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--zev-gray-900);
}

.zev-visor__marco--claro {
  background: var(--zev-surface-raised);
}

.zev-visor__vista {
  display: block;
  max-width: 100%;
  max-height: calc(92vh - 3.5rem);
  object-fit: contain;
}

.zev-visor__barra {
  display: flex;
  align-items: center;
  gap: var(--zev-space-3);
  padding: var(--zev-space-2) var(--zev-space-3);
  border-top: var(--zev-border-width) solid var(--zev-border);
}

.zev-visor__pie {
  flex: 1;
  min-width: 0;
  margin: 0;
  overflow: hidden;
  font-size: var(--zev-text-sm);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.zev-visor__acciones {
  display: flex;
  flex: none;
  align-items: center;
  gap: var(--zev-space-2);
}

.zev-visor__cuenta {
  font-size: var(--zev-text-xs);
  color: var(--zev-gray-600);
}

/* El diagrama de daños y el indicador de gasolina son dibujos sobre fondo
   claro, no fotos: recortarlos al centro pierde justo las marcas de los
   extremos, que es lo que se fue a mirar. Entran enteros y con más alto. */
.zev-medio__vista--dibujo {
  height: 14rem;
  object-fit: contain;
  background: var(--zev-surface-raised);
}

.zev-medio__pie {
  display: flex;
  flex-direction: column;
  gap: var(--zev-space-1);
  padding: var(--zev-space-2);
  border-top: var(--zev-border-width) solid var(--zev-border);
}

.zev-medio__nombre {
  display: flex;
  align-items: center;
  gap: var(--zev-space-2);
  margin: 0;
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-2xs);
  color: var(--zev-gray-600);
  overflow-wrap: anywhere;
}

.zev-medio__acciones {
  display: flex;
  justify-content: flex-end;
}

.zev-capturas {
  display: flex;
  flex-wrap: wrap;
  gap: var(--zev-space-2);
  margin-bottom: var(--zev-space-3);
}

/* --- Diálogo de captura. Es un <dialog> nativo: el fondo, la
       tecla Esc y el foco atrapado vienen de fábrica, sin una
       línea de JS ni z-index inventados. --- */

.zev-captura {
  width: min(46rem, calc(100vw - 2rem));
  padding: 0;
  border: var(--zev-border-width) solid var(--zev-gray-800);
  border-radius: var(--zev-radius);
  background: var(--zev-surface-raised);
  color: var(--zev-ink);
}

.zev-captura::backdrop {
  background: rgba(22, 32, 42, 0.72);
}

.zev-captura__head {
  display: flex;
  align-items: center;
  gap: var(--zev-space-2);
  padding: var(--zev-space-3) var(--zev-space-4);
  background: var(--zev-superficie-oscura);
  color: var(--zev-gray-50);
}

.zev-captura__titulo {
  margin: 0;
  font-size: var(--zev-text-sm);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.zev-captura__cuerpo {
  padding: var(--zev-space-4);
}

.zev-captura__video {
  display: block;
  width: 100%;
  max-height: 60vh;
  background: #000;
  border: var(--zev-border-width) solid var(--zev-border-fuerte);
  border-radius: var(--zev-radius-sm);
}

.zev-captura__pie {
  display: flex;
  flex-wrap: wrap;
  gap: var(--zev-space-2);
  padding: var(--zev-space-3) var(--zev-space-4);
  border-top: var(--zev-border-width) solid var(--zev-border);
  background: var(--zev-gray-50);
}

.zev-captura__reloj {
  display: inline-block;
  margin-top: var(--zev-space-3);
  padding: 0.1rem 0.5rem;
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-lg);
  font-weight: 700;
  color: var(--zev-surface-raised);
  background: var(--zev-danger);
  border-radius: var(--zev-radius-sm);
}

/* Últimos segundos antes del corte automático (ver el tope de
   duración en modulos/medios.js). */
.zev-captura__reloj--fin {
  animation: zev-parpadeo 1s ease-in-out infinite;
}

@keyframes zev-parpadeo {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

/* --- Aviso en línea: el vehículo encontrado, el borrador que
       quedó a medias, el error de una búsqueda. --- */

.zev-aviso {
  display: flex;
  align-items: flex-start;
  gap: var(--zev-space-3);
  padding: var(--zev-space-3);
  border: var(--zev-border-width) solid var(--zev-border-fuerte);
  border-left-width: 3px;
  border-radius: var(--zev-radius);
  background: var(--zev-surface-raised);
  font-size: var(--zev-text-sm);
}

/* El tag helper de validación alterna estas dos clases; la "valid" es el
   recuadro vacío que hay que esconder. */
.zev-aviso.validation-summary-valid {
  display: none;
}

.zev-aviso__cuerpo {
  flex: 1 1 auto;
  min-width: 0;
}

.zev-aviso__cuerpo > :last-child {
  margin-bottom: 0;
}

.zev-aviso__acciones {
  display: flex;
  gap: var(--zev-space-2);
  flex-wrap: wrap;
}

.zev-aviso--ok {
  border-left-color: var(--zev-success);
  background: var(--zev-success-bg);
}

.zev-aviso--error,
.zev-aviso.validation-summary-errors {
  border-left-color: var(--zev-danger);
  background: var(--zev-danger-bg);
  color: var(--zev-danger);
}

.zev-aviso.validation-summary-errors ul {
  margin: 0;
  padding-left: 1.1rem;
}

.zev-aviso--info {
  border-left-color: var(--zev-celeste);
  background: var(--zev-info-bg);
}

.zev-aviso--warning {
  border-left-color: var(--zev-warning);
  background: var(--zev-warning-bg);
}

/* --- Barra de guardado: se queda pegada abajo. El formulario mide
       dos pantallas y media; el botón de guardar no puede estar
       solo al final. --- */

.zev-guardar {
  position: sticky;
  bottom: 0;
  z-index: 5;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--zev-space-3);
  padding: var(--zev-space-3) var(--zev-space-4);
  background: var(--zev-surface-raised);
  border: var(--zev-border-width) solid var(--zev-border);
  border-radius: var(--zev-radius);
  box-shadow: var(--zev-shadow);
}

.zev-guardar__nota {
  margin: 0;
  font-size: var(--zev-text-xs);
  color: var(--zev-gray-600);
}

.zev-guardar__acciones {
  display: flex;
  flex-wrap: wrap;
  gap: var(--zev-space-2);
  margin-left: auto;
}

@media (pointer: coarse) {
  .zev-check,
  .zev-trabajo,
  .zev-check__cant,
  .zev-tinta__opcion {
    min-height: 44px;
  }

  .zev-check__input {
    width: 1.4rem;
    height: 1.4rem;
  }

  .zev-tinta__opcion {
    width: 2.6rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .zev-captura__reloj--fin {
    animation: none;
  }

  .zev-check,
  .zev-resumen__item,
  .zev-switch input,
  .zev-switch input::after {
    transition: none;
  }
}

/* ============================================================
   FICHAS Y CAMPO CHICO (Sesión 7).

   `zev-ficha` es una etiqueta de dos líneas para listar registros
   que no llevan tabla propia: los vehículos que usan un plan, los
   documentos de una orden. No es una tarjeta: no tiene sombra ni
   acción; es un dato con su nota debajo.

   `zev-input--sm` es el mismo campo dentro de una fila de tabla,
   donde el alto normal rompe la densidad.
   ============================================================ */

.zev-fichas {
  display: flex;
  flex-wrap: wrap;
  gap: var(--zev-space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.zev-ficha {
  padding: var(--zev-space-2) var(--zev-space-3);
  background: var(--zev-surface);
  border: var(--zev-border-width) solid var(--zev-border);
  border-left: 2px solid var(--zev-gray-300);
  border-radius: var(--zev-radius-sm);
}

.zev-ficha__clave {
  display: block;
  font-size: var(--zev-text-sm);
  font-weight: 700;
  color: var(--zev-ink);
}

.zev-ficha__nota {
  display: block;
  font-size: var(--zev-text-2xs);
  color: var(--zev-gray-600);
}

.zev-input--sm {
  padding: 0.2rem 0.4rem;
  font-size: var(--zev-text-sm);
  min-height: 0;
}

/* ============================================================
   BLOQUE DE TRABAJO (Sesión 7).

   Un ítem del informe técnico: el trabajo arriba y, adentro, sus
   repuestos y su conclusión. Es una tarjeta anidada de Bootstrap
   menos — el borde y el fondo del encabezado alcanzan para decir
   dónde empieza y dónde termina cada uno.
   ============================================================ */

.zev-trabajo-bloque {
  border: var(--zev-border-width) solid var(--zev-border);
  border-radius: var(--zev-radius-sm);
  background: var(--zev-surface-raised);
}

.zev-trabajo-bloque + .zev-trabajo-bloque,
.zev-trabajo-bloque + [data-repuestos="nuevos"]:not(:empty),
[data-repuestos="nuevos"] .zev-trabajo-bloque + .zev-trabajo-bloque {
  margin-top: var(--zev-space-3);
}

[data-repuestos="nuevos"]:not(:empty) {
  margin-top: var(--zev-space-3);
  display: flex;
  flex-direction: column;
  gap: var(--zev-space-3);
}

.zev-trabajo-bloque__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--zev-space-3);
  padding: var(--zev-space-2) var(--zev-space-3);
  background: var(--zev-gray-50);
  border-bottom: var(--zev-border-width) solid var(--zev-border);
}

.zev-trabajo-bloque__titulo {
  margin: 0;
  font-size: var(--zev-text-sm);
  font-weight: 700;
}

.zev-trabajo-bloque__head .zev-switch {
  margin-left: auto;
}

.zev-trabajo-bloque__cuerpo {
  padding: var(--zev-space-3);
}

/* ============================================================
   ÍTEMS Y TOTALES DE UN DOCUMENTO (Sesión 7).

   Las tres tablas de un documento —lubricantes, repuestos, mano de
   obra— y el bloque de totales, que estaban como tablas de
   Bootstrap dentro de tarjetas de colores distintos cada una. El
   total es el número que se compara contra el papel, así que va
   grande, en monoespaciada y alineado a la derecha con los otros.
   ============================================================ */

.zev-items__cant {
  width: 7rem;
}

.zev-items .input-cantidad {
  width: 100%;
  text-align: right;
}

/* Ítem del catálogo que ya está en este documento o en otro de la
   misma orden: se ve, pero no se puede elegir dos veces. */
.zev-items__fila--bloqueada {
  color: var(--zev-gray-600);
  background: var(--zev-gray-100);
}

.zev-items__subtotal {
  margin: var(--zev-space-3) 0 0;
  text-align: right;
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-2xs);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--zev-gray-600);
}

.zev-totales {
  margin-left: auto;
  width: min(24rem, 100%);
  background: var(--zev-surface-raised);
  border: var(--zev-border-width) solid var(--zev-border);
  border-radius: var(--zev-radius);
}

.zev-totales__fila {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--zev-space-4);
  padding: var(--zev-space-2) var(--zev-space-3);
}

.zev-totales__fila + .zev-totales__fila {
  border-top: var(--zev-border-width) solid var(--zev-border);
}

.zev-totales__label {
  font-size: var(--zev-text-sm);
  color: var(--zev-gray-600);
}

.zev-totales__monto {
  font-size: var(--zev-text-sm);
  font-weight: 700;
}

.zev-totales__fila--total {
  background: var(--zev-gray-50);
}

.zev-totales__fila--total .zev-totales__label {
  font-weight: 700;
  color: var(--zev-ink);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: var(--zev-text-2xs);
}

.zev-totales__fila--total .zev-totales__monto {
  font-size: var(--zev-text-xl);
}

/* Las insignias del plan por kilometraje, arriba de la tabla de
   mano de obra. */
.zev-plan-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--zev-space-2);
  margin-bottom: var(--zev-space-2);
}

/* Selector del mantenimiento, para elegirlo a mano. */
.zev-plan-elegir {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--zev-space-2);
  margin-bottom: var(--zev-space-2);
}

.zev-plan-elegir .zev-label {
  margin: 0;
}

.zev-plan-elegir .zev-input {
  width: auto;
  max-width: 100%;
}

/* Fuera de contrato: no es una advertencia del sistema sino una
   condición del ítem, así que tiene tono propio y no el ámbar de
   los estados. Antes venía como `style="background-color:#fd7e14"`
   inyectado por JavaScript, que la CSP estricta bloquea: la
   insignia salía sin color. */
.zev-badge--fuera {
  color: #8a3d00;
  background: #ffe6cc;
}

/* Las dos fechas de un documento de facturación. El rótulo va
   ENCIMA de cada fecha y no al lado: al lado la columna pedía el
   doble de ancho y la tabla de diez columnas se iba al scroll
   horizontal. Arriba ocupa lo mismo que una fecha sola, y estas
   filas ya miden varias líneas por el nombre del vehículo. */
.zev-fechas {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.zev-fechas__label {
  display: block;
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--zev-gray-600);
}

/* ============================================================
   LOS DOS PDF DE UN DOCUMENTO DE FACTURACIÓN.

   Un mismo documento se imprime de dos maneras y no son lo mismo:
   la PREFACTURA lleva lo que está dentro del contrato (preventivo
   y correctivo) y la PROFORMA lo que queda fuera. Eran dos
   botones grises idénticos con el nombre y un número, así que
   había que leerlos para saber cuál era cuál.

   Ahora cada uno lleva su filo de color a la izquierda -- el
   mismo naranja de la insignia "fuera de contrato" para la
   proforma -- y el número va encajonado en monoespaciada, que es
   lo que se compara entre filas. Un cero no se puede imprimir: el
   chip queda apagado y sin enlace, no como un botón deshabilitado
   que igual invita a apretarlo.
   ============================================================ */

/* Uno encima del otro y no en fila: en fila los dos chips pedían
   274px de una tabla de diez columnas y la empujaban al scroll
   horizontal. Apilados entran en la mitad, y las filas de este
   listado ya miden varias líneas por el nombre del vehículo. */
.zev-pdfs {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--zev-space-1);
}

.zev-pdf {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.25rem 0.5rem 0.25rem 0.4rem;
  font-size: var(--zev-text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--zev-ink);
  text-decoration: none;
  white-space: nowrap;
  background: var(--zev-surface-raised);
  border: var(--zev-border-width) solid var(--zev-border);
  border-left-width: 3px;
  border-radius: var(--zev-radius-sm);
  /* Los dos chips al mismo ancho: los números quedan en columna y
     se comparan de un vistazo entre filas. */
  min-width: 9.5rem;
  transition: border-color var(--zev-dur) var(--zev-ease),
              background-color var(--zev-dur) var(--zev-ease);
}

.zev-pdf i {
  font-size: var(--zev-text-sm);
  font-weight: 400;
}

/* Dentro del contrato: la tinta de la casa. */
.zev-pdf--prefactura {
  border-left-color: var(--zev-azul-profundo);
}

/* Fuera de contrato: el mismo naranja de .zev-badge--fuera. */
.zev-pdf--proforma {
  border-left-color: #8a3d00;
}

.zev-pdf--proforma i {
  color: #8a3d00;
}

a.zev-pdf:hover {
  background: var(--zev-gray-100);
  border-color: var(--zev-ink);
}

a.zev-pdf:hover.zev-pdf--prefactura {
  border-left-color: var(--zev-azul-profundo);
}

a.zev-pdf:hover.zev-pdf--proforma {
  border-left-color: #8a3d00;
}

a.zev-pdf:focus-visible {
  outline: 2px solid var(--zev-ink);
  outline-offset: 2px;
}

/* Sin ítems no hay PDF que generar: se muestra apagado y sin
   enlace, para que la fila siga diciendo cuántos hay de cada uno. */
.zev-pdf--vacio {
  color: var(--zev-gray-600);
  background: var(--zev-gray-50);
  border-color: var(--zev-border);
  border-left-color: var(--zev-border);
}

.zev-pdf__n {
  margin-left: auto;
  font-family: var(--zev-font-datos);
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  letter-spacing: 0;
  padding: 0 0.3rem;
  background: var(--zev-gray-100);
  border-radius: var(--zev-radius-sm);
}

.zev-pdf--vacio .zev-pdf__n {
  background: transparent;
}

/* ============================================================
   LOS 18 PUNTOS DE LA INSPECCIÓN (Sesión 7).

   Eran dieciocho tarjetas con un <select> de tres opciones cada
   una: dieciocho pantallas de scroll para decir tres palabras, y
   ningún modo de ver de un vistazo cuáles faltaban. Ahora cada
   punto es una fila con la escala a la vista — se marca de un
   toque, que es lo que hace falta con tablet en el patio — y el
   filo en ámbar dice cuáles siguen sin contestar. Eso último lo
   hace `:has()`, sin una línea de JavaScript, así que es correcto
   también después de marcar.
   ============================================================ */

.zev-puntos {
  display: flex;
  flex-direction: column;
  gap: var(--zev-space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.zev-punto {
  display: grid;
  grid-template-columns: 2rem minmax(0, 1fr) auto minmax(0, 14rem);
  align-items: center;
  gap: var(--zev-space-3);
  padding: var(--zev-space-2) var(--zev-space-3);
  background: var(--zev-surface-raised);
  border: var(--zev-border-width) solid var(--zev-border);
  border-left: 3px solid var(--zev-success);
  border-radius: var(--zev-radius-sm);
}

/* Sin condición elegida todavía. Es el estado en el que nace cada
   punto al crear la inspección. */
.zev-punto:not(:has(input[type="radio"]:checked)) {
  border-left-color: var(--zev-warning);
  background: var(--zev-warning-bg);
}

.zev-punto:has(.zev-escala__opcion--malo input:checked) {
  border-left-color: var(--zev-danger);
}

.zev-punto:has(.zev-escala__opcion--regular input:checked) {
  border-left-color: var(--zev-warning);
}

.zev-punto__num {
  font-size: var(--zev-text-sm);
  font-weight: 700;
  color: var(--zev-gray-600);
}

.zev-punto__nombre {
  font-size: var(--zev-text-sm);
  line-height: 1.35;
}

@media (max-width: 991.98px) {
  .zev-punto {
    grid-template-columns: 2rem minmax(0, 1fr);
  }

  .zev-punto .zev-escala,
  .zev-punto__obs {
    grid-column: 2 / -1;
  }
}

/* --- Escala de tres estados ---
   Un <select> esconde las opciones detrás de un clic y no dice el
   rango; acá los tres valores están a la vista y el elegido se
   pinta con el color de su significado. Son radios de verdad: el
   teclado y el lector de pantalla los recorren solos. */

.zev-escala {
  display: inline-flex;
  border: var(--zev-border-width) solid var(--zev-border-fuerte);
  border-radius: var(--zev-radius-sm);
  overflow: hidden;
}

.zev-escala__opcion {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 5.5rem;
  min-height: 34px;
  padding: 0 var(--zev-space-2);
  font-size: var(--zev-text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--zev-gray-600);
  cursor: pointer;
  transition: background-color var(--zev-dur) var(--zev-ease);
}

.zev-escala__opcion + .zev-escala__opcion {
  border-left: var(--zev-border-width) solid var(--zev-border-fuerte);
}

.zev-escala__opcion input {
  position: absolute;
  opacity: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  cursor: pointer;
}

.zev-escala__opcion:hover {
  background: var(--zev-gray-100);
}

.zev-escala__opcion:has(input:focus-visible) {
  outline: 2px solid var(--zev-ink);
  outline-offset: -2px;
}

.zev-escala__opcion--malo:has(input:checked) {
  color: #ffffff;
  background: var(--zev-danger);
}

.zev-escala__opcion--regular:has(input:checked) {
  color: #ffffff;
  background: var(--zev-warning);
}

.zev-escala__opcion--bien:has(input:checked) {
  color: #ffffff;
  background: var(--zev-success);
}

@media (pointer: coarse) {
  .zev-escala__opcion {
    min-height: 44px;
  }
}

/* En el teléfono la escala ocupa el ancho de la fila y se reparte
   en tres: con ancho mínimo por opción, "Excelente" se cortaba. */
/* Debajo de esto ni 26rem ni 18rem entran, así que el campo cede
   y el placeholder se recorta: es preferible a una barra más ancha
   que la pantalla. */
@media (max-width: 575.98px) {
  .zev-filtros__buscar,
  .zev-filtros__buscar--corto {
    min-width: 0;
  }

  /* Un atajo de teclado en un teléfono es ruido, y es lo primero
     que se puede sacar cuando la banda no da más de sí. */
  .zev-buscador__disparador .zev-atajo {
    display: none;
  }
}

@media (max-width: 575.98px) {
  .zev-punto .zev-escala {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
  }

  .zev-escala__opcion {
    min-width: 0;
  }
}

/* ============================================================
   MATRIZ DE PRECIOS POR MODELO (Sesión 7).

   Los dos catálogos —repuestos y mano de obra— no guardan un
   precio por ítem sino uno por modelo de vehículo, y vincular un
   ítem a media flota es ponerle el mismo número a varias filas.
   Eran treinta tarjetas de Bootstrap idénticas en una rejilla:
   había que recorrerlas con la rueda del mouse para encontrar un
   modelo, y nada decía cuántas estaban cargadas.

   Acá cada modelo es una fila de una línea —nombre a la
   izquierda, monto a la derecha, alineados en columna para poder
   compararlos— con buscador, filtro de "solo los cargados",
   contador y carga en lote sobre lo que está a la vista.
   Comportamiento en modulos/precios-modelo.js.
   ============================================================ */

.zev-precios__barra {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--zev-space-3) var(--zev-space-4);
  padding-bottom: var(--zev-space-3);
  border-bottom: var(--zev-border-width) solid var(--zev-border);
}

.zev-precios__barra .zev-filtros__buscar {
  flex: 1 1 16rem;
}

/* Marca y tipo: el ancho lo pone el contenido, no la barra. Solo
   se dibujan cuando hay más de un valor -- un filtro que no
   filtra nada es ruido. */
.zev-precios__filtro {
  width: auto;
  flex: 0 0 auto;
}

.zev-precios__lote {
  display: flex;
  align-items: center;
  gap: var(--zev-space-2);
  margin-left: auto;
}

.zev-precios__lote .zev-precios__monto {
  width: 7.5rem;
}

/* El signo pegado al campo y no dentro del placeholder: el monto
   se lee en columna con los de las otras filas y un "$" adentro
   correría los dígitos. */
.zev-precios__monto {
  display: flex;
  align-items: stretch;
}

.zev-precios__signo {
  display: flex;
  align-items: center;
  padding: 0 var(--zev-space-2);
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-sm);
  color: var(--zev-gray-600);
  background: var(--zev-gray-100);
  border: var(--zev-border-width) solid var(--zev-border-fuerte);
  border-right: 0;
  border-radius: var(--zev-radius) 0 0 var(--zev-radius);
}

.zev-precios__monto .zev-input {
  min-width: 0;
  border-radius: 0 var(--zev-radius) var(--zev-radius) 0;
  text-align: right;
}

.zev-precios__cuenta {
  margin: var(--zev-space-3) 0 var(--zev-space-2);
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-2xs);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--zev-gray-600);
}

.zev-precios__lista {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(21rem, 1fr));
  gap: var(--zev-space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.zev-precio {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 7.5rem;
  align-items: center;
  gap: var(--zev-space-3);
  padding: var(--zev-space-2) var(--zev-space-3);
  background: var(--zev-surface-raised);
  border: var(--zev-border-width) solid var(--zev-border);
  border-left: 3px solid var(--zev-gray-300);
  border-radius: var(--zev-radius-sm);
}

/* Cargado: el filo izquierdo verde dice cuáles ya tienen precio
   sin tener que leer los números uno por uno. */
.zev-precio--cargado {
  border-left-color: var(--zev-success);
}

.zev-precio__modelo {
  min-width: 0;
}

.zev-precio__nombre {
  display: block;
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-sm);
  font-weight: 700;
  color: var(--zev-ink);
  overflow-wrap: anywhere;
  cursor: pointer;
}

.zev-precio__grupo {
  display: block;
  margin-top: 0.15rem;
  font-size: var(--zev-text-2xs);
  line-height: 1.4;
  color: var(--zev-gray-600);
}

.zev-precios__nada {
  margin: var(--zev-space-3) 0 0;
  padding: var(--zev-space-4);
  text-align: center;
  font-size: var(--zev-text-sm);
  color: var(--zev-gray-600);
  background-image: var(--zev-hatch);
  border: var(--zev-border-width) dashed var(--zev-border-fuerte);
  border-radius: var(--zev-radius-sm);
}

@media (max-width: 575.98px) {
  .zev-precios__lote {
    margin-left: 0;
    width: 100%;
  }
}

/* ============================================================
   LO QUE SOBREVIVIÓ DE site.css (Sesión 6).

   site.css se borró: casi todo lo que tenía era redefinir clases
   de Bootstrap —.card, .btn, .table, .form-control, .badge—, que
   es justo lo que la Regla 7 prohíbe y lo que hace que una
   actualización de la librería rompa cosas al azar. Sacarlo dejó
   a las vistas viejas con el Bootstrap de fábrica, ya retintado
   por las variables --bs-* de este archivo.

   Acá quedan las cuatro reglas que sí hacían falta y que no son
   una sobreescritura de la librería.
   ============================================================ */

/* El tag helper de validación alterna esta clase con
   .validation-summary-errors sobre un recuadro que el markup ya
   trae escrito. Sin esta regla, el recuadro rojo se ve siempre,
   vacío, en cada formulario de la aplicación. */
.validation-summary-valid {
  display: none;
}

/* Barra de scroll horizontal espejo sobre las tablas anchas, la
   dibuja table-scroll-top.js. Delgada a propósito: no agrega alto
   visible por encima de la tabla. */
.table-scroll-top {
  overflow-x: auto;
  overflow-y: hidden;
  height: 16px;
  margin-bottom: 2px;
}

.table-scroll-top > div {
  height: 1px;
}

/* Los botones de variante de PDF del detalle de un documento se
   dibujan ahora con `zev-btn` en la cabecera de la página, así que
   la clase `.zev-btn-pdf` que vivía acá se borró: ninguna vista la
   usaba — el markup decía `btn-pdf-variante`. */

/* ============================================================
   Utilidades de las vistas que todavía no se rediseñaron.

   No son un sistema de utilidades al estilo Tailwind: son
   exactamente las cinco cosas que los 21 `style=` heredados
   decían, escritas una vez. Existen para que la CSP estricta
   pueda entrar (Regla 7 + guarda 3 de §4), no para crecer.
   ============================================================ */

/* Íconos decorativos grandes de las pantallas de estado (sesión
   cerrada, acceso denegado, un asistente sin datos todavía). */
.zev-icono {
  font-size: 2rem;
  line-height: 1;
}

.zev-icono--sm { font-size: 1.5rem; }
.zev-icono--lg { font-size: 3rem; }
.zev-icono--xl { font-size: 4rem; }

/* Texto que el usuario escribió en un textarea: los saltos de
   línea son parte del dato y no se pueden colapsar al mostrarlo. */
.zev-texto-libre {
  white-space: pre-wrap;
}

/* Traza de un error: se corta donde sea antes que desbordar la
   página, y no crece sin fin. */
.zev-traza {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  max-height: 31rem;
  overflow-y: auto;
}

/* Listas largas dentro de un formulario: el bloque se queda
   compacto y hace su propio scroll en vez de estirar la página. */
.zev-lista-scroll {
  max-height: 13rem;
  overflow-y: auto;
}

.zev-tabla-scroll {
  max-height: 25rem;
  overflow-y: auto;
}

/* Columna de descripción de una matriz: sin un ancho mínimo, el
   nombre del ítem se parte en cinco líneas y la fila deja de
   leerse. */
.zev-col-min {
  min-width: 20rem;
}

/* --- Permisos por módulo (Sesión 7) ---
   Eran catorce tarjetas de tres casillas cada una: había que
   recorrerlas con la rueda del mouse para contestar "¿quién puede
   crear prefacturas?". Ahora es una matriz de módulos por acción,
   que es la forma de la pregunta. La fila con algún permiso se
   marca sola con `:has()`, sin una línea de JavaScript. */
.zev-permisos .zev-permisos__col {
  width: 6rem;
  text-align: center;
}

.zev-permisos__casilla {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 34px;
  margin: 0;
  cursor: pointer;
}

.zev-permisos__casilla input[type="checkbox"] {
  width: 1.15rem;
  height: 1.15rem;
  accent-color: var(--zev-azul-profundo);
  cursor: pointer;
}

.zev-permisos tbody tr:has(input:checked) td:first-child {
  box-shadow: inset 2px 0 0 var(--zev-success);
}

/* --- Pantallas de acceso (Sesión 7) ---
   Entrar, registrarse y salir: una columna angosta y centrada,
   porque no hay nada más en pantalla y un formulario de dos campos
   estirado a mil pixeles se lee peor. */
.zev-acceso {
  max-width: 26rem;
  margin: var(--zev-space-8) auto;
}

.zev-acceso__titulo {
  margin: 0 0 var(--zev-space-4);
  font-family: var(--zev-font-display);
  font-size: var(--zev-text-xl);
  font-weight: 700;
}

/* ============================================================
   IMPRESIÓN.

   Casi todo lo que esta institución archiva sale como PDF firmado
   desde el servidor, no del navegador. Pero las pantallas de
   detalle y el consolidado se imprimen a mano, y sin esto salían
   con la barra lateral oscura ocupando un cuarto de la hoja y los
   botones de acción en el papel.

   La regla es una sola: se imprime el contenido, no el marco de
   trabajo.
   ============================================================ */

@media print {
  :root {
    --zev-surface: #fff;
    --zev-surface-raised: #fff;
  }

  body {
    background: #fff;
  }

  /* El marco de trabajo no se imprime. */
  .zev-sidebar,
  .zev-topbar,
  .zev-migas,
  .zev-skip,
  .zev-toast-stack,
  .zev-paleta,
  .zev-guardar,
  .zev-form__lado,
  .zev-filtros,
  .zev-paginacion,
  .zev-acciones,
  .zev-page-header .zev-btn,
  .zev-capturas,
  .zev-lienzo__barra,
  .btn,
  .dropdown,
  form[method="get"] {
    display: none !important;
  }

  .zev-app,
  .zev-main,
  .zev-contenido {
    display: block;
    height: auto;
    overflow: visible;
    padding: 0;
  }

  /* Los paneles pierden la caja y quedan como secciones de un
     documento; el borde de papel lo pone la hoja. */
  .zev-panel,
  .card {
    border: none !important;
    box-shadow: none !important;
    break-inside: avoid;
  }

  .zev-panel__head,
  .card-header {
    border-bottom: 1px solid #000 !important;
    background: none !important;
    color: #000 !important;
  }

  /* En papel la tabla se queda con lo único que se imprime bien: las
     líneas. Fondo de cabecera y banda alterna gastan tóner y no aportan
     nada sobre una hoja. */
  .zev-table thead th {
    background: none !important;
    color: #000 !important;
    border-bottom: 2px solid #000 !important;
  }

  .zev-table tbody tr,
  .zev-table tbody tr:nth-child(even) {
    background: none !important;
  }

  .zev-table tbody td:first-child::before {
    display: none !important;
  }

  /* Una fila partida entre dos hojas obliga a comparar contra la
     página anterior, que es justo lo que la tabla existe para
     evitar. */
  .zev-table tr,
  tr {
    break-inside: avoid;
  }

  thead {
    display: table-header-group;
  }

  /* Los bloques con scroll propio se imprimen enteros: en papel no
     hay forma de desplazarlos. */
  .zev-lista-scroll,
  .zev-tabla-scroll,
  .zev-traza,
  .table-responsive {
    max-height: none !important;
    overflow: visible !important;
  }

  a[href]::after {
    content: "";
  }
}

/* ============================================================
   MATRIZ DE UN PLAN DE MANTENIMIENTO.

   Estaba en un <style> dentro de la vista, que la CSP estricta
   bloquea igual que a un <script> embebido (Sesión 6). Es ancha y
   alta: sin la cabecera y el nombre de la tarea fijos, las
   casillas dejan de significar nada apenas se desplaza.
   ============================================================ */

/* La cabecera de la matriz se pega al borde de ESTE contenedor, no al de la
   ventana, así que mientras el contenedor sea más bajo que la pantalla el que
   scrollea es el documento y la cabecera se va igual. Con casi toda la altura
   disponible, apenas se llega a la tabla el documento ya no tiene a dónde
   seguir y el desplazamiento pasa adentro, que es donde la cabecera queda. */
.matriz-scroll {
  /* Lo que queda de pantalla descontando la banda superior —que es sticky y
     taparía la cabecera de la tabla si el contenedor le pasara por debajo— y la
     barra de guardar de abajo. Con esto, al llegar al final de la página el
     contenedor entra justo y el resto del desplazamiento ocurre adentro. */
  max-height: calc(100vh - var(--zev-alto-banda) - 9rem);
  min-height: 20rem;
  overflow: auto;

  /* Sin esto la tabla completa —3.100 px con 54 tareas— seguía contando para el
     alto de scroll del documento aunque el contenedor la recorte: la página
     tenía 2.300 px de nada abajo, y bajar hasta ahí sacaba de pantalla la
     tabla entera, cabecera incluida. `overflow: hidden` no alcanza; hace falta
     contener el pintado. */
  contain: paint;
}

.matriz-plan td.col-tarea {
  position: sticky;
  left: 0;
  z-index: 2;
  background-color: var(--zev-surface-raised);
  min-width: 20rem;
}

/* El `position: sticky` de arriba no pegaba: `.zev-table tbody td:first-child`
   le pone `position: relative` para anclar la franja del hover y tiene más
   especificidad, así que la columna de la tarea scrolleaba junto con las
   doscientas casillas — justo lo que la columna fija existe para evitar. Va
   sola, y no subiéndole la especificidad a la regla entera, para no pisarles el
   fondo a las filas de categoría y a las que no tienen ítem. */
.zev-table.matriz-plan tbody td.col-tarea {
  position: sticky;
}

.matriz-plan th.col-tarea {
  position: sticky;
  left: 0;
  min-width: 20rem;
}

/* La cabecera queda pegada arriba. Repite el fondo de `zev-table thead`
   porque al despegarse pasa por encima de las filas y sin fondo propio se
   transparenta sobre ellas. */
.matriz-plan thead th {
  position: sticky;
  top: 0;
  z-index: 3;
  background-color: var(--zev-gray-100);
}

.matriz-plan thead th.col-tarea {
  z-index: 4;
}

.matriz-plan .fila-categoria .col-tarea {
  background-color: var(--zev-gray-50);
}

.matriz-plan .fila-tarea--sin-item .col-tarea {
  background-color: var(--zev-warning-bg);
}

.matriz-plan td.casilla,
.matriz-plan th.casilla {
  text-align: center;
  vertical-align: middle;
  min-width: 76px;
  padding: 0;
}

/* El área de clic es la celda entera, no el cuadradito: 18 px de
   checkbox es un blanco demasiado chico cuando hay cuarenta
   columnas pegadas. */
.matriz-plan .casilla label {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 34px;
  margin: 0;
  cursor: pointer;
}

.matriz-plan .casilla input[type="checkbox"] {
  width: 1.15rem;
  height: 1.15rem;
  cursor: pointer;
}

/* Columna del kilometraje elegido: ancla visual para no perder la
   vertical. */
.matriz-plan .columna-activa {
  background-color: var(--bs-primary-bg-subtle) !important;
  box-shadow: inset 1px 0 0 var(--bs-primary-border-subtle),
              inset -1px 0 0 var(--bs-primary-border-subtle);
}

/* En vista de comparación las filas se numeran, que es como viene
   la hoja impresa. */
.matriz-plan.comparando tbody {
  counter-reset: fila;
}

.matriz-plan.comparando tr.fila-tarea {
  counter-increment: fila;
}

/* El número de fila reusa el mismo ::before que pinta la franja tricolor al
   apuntar una fila, así que hay que deshacerle todo lo de la franja. Sin esto
   heredaba `position: absolute`, el degradado de la marca y el `scaleY(0)`: el
   número no se veía nunca y al pasar el mouse aparecía un bloque de 35 px de
   color tapando el nombre de la tarea. */
.matriz-plan.comparando tr.fila-tarea .col-tarea::before {
  content: counter(fila) ".";
  position: static;
  display: inline-block;
  min-width: 2.2rem;
  background: none;
  transform: none;
  color: var(--zev-gray-600);
  font-variant-numeric: tabular-nums;
}


/* Fila sin ítem del catálogo: la prefactura no la va a sugerir
   nunca, así que tiene que saltar a la vista. Antes lo hacía la
   clase .table-warning de Bootstrap, que la Regla 7 no quiere
   ver acá. */
.matriz-plan .fila-tarea--sin-item {
  background-color: var(--zev-warning-bg);
}

.matriz-plan .fila-categoria {
  background-color: var(--zev-gray-50);
}

.matriz-plan .fila-categoria .col-tarea {
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--zev-gray-600);
}

.matriz-plan .casilla input[type="checkbox"] {
  accent-color: var(--zev-azul-profundo);
}

/* La barra de filtros de la matriz lleva cuatro campos y un botón,
   y se queda pegada arriba: sin ancho fijo por campo, el buscador
   se come la fila entera. */
.zev-filtros--matriz .zev-filtros__campo {
  min-width: 9rem;
}

.zev-matriz__pie {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--zev-space-3);
  margin-top: var(--zev-space-3);
  padding-top: var(--zev-space-3);
  border-top: var(--zev-border-width) solid var(--zev-border);
}

.zev-matriz__cuenta {
  margin-left: auto;
  font-family: var(--zev-font-datos);
  font-size: var(--zev-text-2xs);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--zev-gray-600);
}

.zev-matriz__nada {
  text-align: center;
  color: var(--zev-gray-600);
}

/* La barra de filtros ya no se pega arriba. Se pegaba en `top: 0`, o sea por
   debajo de la banda superior, y sobre todo tapaba la cabecera de la tabla, que
   es la que hace falta todo el tiempo: sin ella una casilla marcada no dice a
   qué kilometraje corresponde. Los filtros se usan de a ratos y quedan a un
   scroll de distancia; la cabecera se necesita en cada fila que se lee. */
.barra-filtros {
  z-index: 5;
}

/* El equivalente en horas del intervalo, debajo del kilometraje. */
.zev-nota-columna {
  display: block;
  font-size: 0.7rem;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  color: var(--zev-gray-300);
}

/* ============================================================
   Muestras de color -- una clase por token, para /DesignSystem.
   Existen para no romper la Regla 7 (cero CSS inline) al mostrar
   el catálogo de colores.
   ============================================================ */

.zev-swatch {
  border-radius: var(--zev-radius);
  border: var(--zev-border-width) solid rgba(0, 0, 0, 0.08);
  height: 4rem;
}

.zev-swatch--celeste { background: var(--zev-celeste); }
.zev-swatch--azul { background: var(--zev-azul-profundo); }
.zev-swatch--rojo { background: var(--zev-rojo); }
.zev-swatch--gray-50 { background: var(--zev-gray-50); }
.zev-swatch--gray-100 { background: var(--zev-gray-100); }
.zev-swatch--gray-200 { background: var(--zev-gray-200); }
.zev-swatch--gray-300 { background: var(--zev-gray-300); }
.zev-swatch--gray-400 { background: var(--zev-gray-400); }
.zev-swatch--gray-500 { background: var(--zev-gray-500); }
.zev-swatch--gray-600 { background: var(--zev-gray-600); }
.zev-swatch--gray-700 { background: var(--zev-gray-700); }
.zev-swatch--gray-800 { background: var(--zev-gray-800); }
.zev-swatch--gray-900 { background: var(--zev-gray-900); }
.zev-swatch--success { background: var(--zev-success); }
.zev-swatch--warning { background: var(--zev-warning); }
.zev-swatch--danger { background: var(--zev-danger); }
.zev-swatch--info { background: var(--zev-info); }

/* Fondo de la propia página del catálogo y de sus demos. */
.zev-demo-narrow {
  max-width: 26rem;
}

.zev-demo-hatch {
  background-image: var(--zev-hatch);
}

/* ============================================================
   ALTA DE MANO DE OBRA EN UN PLAN, Y LOS DATOS DEL PLAN.

   Agregar era la última fila de la matriz: con doscientas
   columnas el botón quedaba fuera de la pantalla y solo dejaba
   agregar de a una. Ahora es un panel propio con dos listas
   marcables — el catálogo y los kilometrajes — que se
   desplazan solas en vez de estirar la página.
   ============================================================ */

.zev-agregar {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  gap: 1.5rem;
  align-items: start;
}

.zev-agregar__col {
  min-width: 0;
}

.zev-agregar__pie {
  grid-column: 1 / -1;
  display: flex;
  justify-content: flex-end;
}

@media (max-width: 768px) {
  .zev-agregar {
    grid-template-columns: minmax(0, 1fr);
  }
}

.zev-marcable {
  list-style: none;
  margin: 0.5rem 0 0;
  padding: 0.25rem;
  max-height: 18rem;
  overflow-y: auto;
  border: var(--zev-border-width) solid var(--zev-border-fuerte);
  background: var(--zev-surface-raised);
}

.zev-marcable--km {
  max-height: 21.5rem;
}

.zev-marcable label {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  padding: 0.25rem 0.5rem;
  margin: 0;
  cursor: pointer;
}

.zev-marcable label:hover {
  background: var(--zev-border);
}

/* Lo que ya está en el plan se ve, para no volver a buscarlo, pero no se puede elegir. */
.zev-marcable .zev-marcable--puesta {
  opacity: 0.55;
  cursor: default;
}

.zev-marcable input[type="checkbox"] {
  flex: none;
  width: 1rem;
  height: 1rem;
}

.zev-plan-datos {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.75rem;
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: var(--zev-border-width) solid var(--zev-border);
}

.zev-plan-datos__campo {
  min-width: 12rem;
}

/* ============================================================
   LISTADO EN TARJETAS (angosto). Debajo de 992px —el mismo corte en
   que la lateral pasa a panel deslizable— una tabla de diez columnas
   en 340px obligaba a desplazarse de lado para leer una sola fila.
   Cada fila pasa a ser una tarjeta: la primera celda es el título,
   el resto va en pares rótulo/valor, y el rótulo lo copia del <th>
   el módulo `tabla-tarjetas`. Las cabeceras ordenables quedan arriba
   como chips para no perder el orden.
   Úsese solo con cabecera de una fila y primera columna que
   identifique la fila.
   ============================================================ */

@media (max-width: 991.98px) {
  .zev-tarjetas .zev-table,
  .zev-tarjetas .zev-table thead,
  .zev-tarjetas .zev-table tbody,
  .zev-tarjetas .zev-table tfoot {
    display: block;
  }

  .zev-tarjetas .zev-table thead tr {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 1rem;
    padding: 0.5rem var(--zev-space-3);
    background: var(--zev-gray-100);
    border-bottom: 2px solid var(--zev-azul-profundo);
  }

  .zev-tarjetas .zev-table thead th {
    padding: 0.35rem 0;
    border: 0;
    background: none;
  }

  .zev-tarjetas .zev-table thead th:not([data-sort-key]) {
    display: none;
  }

  .zev-tarjetas .zev-table thead:not(:has([data-sort-key])) {
    display: none;
  }

  .zev-tarjetas .zev-table tbody {
    display: grid;
    gap: var(--zev-space-3);
    padding: var(--zev-space-3);
  }

  .zev-tarjetas .zev-table tbody tr,
  .zev-tarjetas .zev-table tfoot tr {
    display: block;
    position: relative;
    min-width: 0;
    padding: 0.4rem var(--zev-space-3);
    border: var(--zev-border-width) solid var(--zev-border);
    border-radius: var(--zev-radius);
  }

  .zev-tarjetas .zev-table tfoot tr {
    margin: 0 var(--zev-space-3) var(--zev-space-3);
    background: var(--zev-gray-100);
  }

  .zev-tarjetas .zev-table tbody td,
  .zev-tarjetas .zev-table tfoot td {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--zev-space-3);
    width: auto;
    min-width: 0;
    padding: 0.35rem 0;
    border-bottom: 0;
    text-align: right;
    white-space: normal;
    overflow-wrap: anywhere;
  }

  .zev-tarjetas .zev-table tbody td + td,
  .zev-tarjetas .zev-table tfoot td + td {
    border-top: 1px dashed var(--zev-border);
  }

  .zev-tarjetas .zev-table td:not(:first-child)[data-label]:not([data-label=""])::before {
    content: attr(data-label);
    flex: none;
    max-width: 45%;
    font-size: var(--zev-text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    text-align: left;
    color: var(--zev-gray-600);
  }

  /* Primera celda: título de la tarjeta. La franja de la fila apuntada
     pasa a ser el filo izquierdo de la tarjeta. */
  .zev-tarjetas .zev-table tbody td:first-child {
    display: block;
    position: static;
    padding: 0.35rem 3rem 0.5rem 0;
    font-size: var(--zev-text-base);
    text-align: left;
  }

  /* El menú de la fila va arriba a la derecha, a la altura del título. */
  .zev-tarjetas .zev-table tbody td.zev-acciones:has(> .zev-acciones-fila, > .zev-menu-btn) {
    position: absolute;
    top: 0.3rem;
    right: var(--zev-space-2);
    width: auto;
    padding: 0;
    border-top: 0;
  }

  .zev-tarjetas .zev-table td[data-label=""] {
    justify-content: flex-end;
  }

  .zev-tarjetas .zev-table td:empty {
    display: none;
  }

  /* Celda que abarca varias columnas: fila de «sin resultados» o rótulo de totales. */
  .zev-tarjetas .zev-table td[colspan] {
    justify-content: flex-start;
    text-align: left;
  }

  /* Detalle desplegable (Consolidado): cerrado no ocupa lugar en la grilla; abierto es
     un bloque de ancho completo debajo de su tarjeta, sin marco propio. */
  .zev-tarjetas .zev-table tbody tr.zev-fila-detalle:not(:has(.show, .collapsing)) {
    display: none;
  }

  .zev-tarjetas .zev-table tbody tr.zev-fila-detalle {
    grid-column: 1 / -1;
    margin-top: calc(-1 * var(--zev-space-2));
    padding: 0;
  }

  .zev-tarjetas .zev-table tbody tr.zev-fila-detalle > td {
    display: block;
    padding: 0;
  }

  /* Los ítems dentro del detalle son decenas: una tarjeta de seis renglones por ítem
     hacía un detalle de seis mil píxeles. Van compactos: tipo y descripción a lo ancho,
     y los cuatro números en dos columnas con el rótulo encima. */
  .zev-tarjetas .zev-fila-detalle .zev-table tbody tr {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 var(--zev-space-3);
    padding: var(--zev-space-2) 0;
    border-width: 0 0 var(--zev-border-width);
    border-radius: 0;
  }

  .zev-tarjetas .zev-fila-detalle .zev-table tbody {
    display: block;
    padding: 0 var(--zev-space-3);
  }

  .zev-tarjetas .zev-fila-detalle .zev-table tbody td {
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    padding: 0.15rem 0;
    border-top: 0;
    text-align: left;
  }

  .zev-tarjetas .zev-fila-detalle .zev-table tbody td:nth-child(-n + 2) {
    grid-column: 1 / -1;
    padding-right: 0;
    font-size: var(--zev-text-sm);
  }

  .zev-tarjetas .zev-fila-detalle .zev-table tbody td:nth-child(2)::before {
    content: none;
  }

  .zev-tarjetas .zev-fila-detalle .zev-table td[data-label]:not([data-label=""])::before {
    max-width: none;
  }

  .zev-tarjetas .zev-table tbody tr.zev-fila-detalle .collapse.show,
  .zev-tarjetas .zev-table tbody tr.zev-fila-detalle .collapsing {
    padding: var(--zev-space-2) 0;
  }
}

@media (min-width: 576px) and (max-width: 991.98px) {
  .zev-tarjetas .zev-table tbody {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* Los toasts flotantes no pueden medir más que la pantalla: con 26rem en
   un teléfono de 375px se salían por la izquierda y ensanchaban la página. */
.zev-toast-stack--flotante {
  width: min(26rem, calc(100vw - 2 * var(--zev-space-4)));
}

/* En un teléfono «Agregar repuesto sin mano de obra» medía más que la pantalla y, como
   el botón no envuelve, empujaba la página de lado. Un botón nunca pasa el ancho de su
   contenedor: en angosto el texto largo baja de renglón en vez de salirse. */
@media (max-width: 575.98px) {
  .zev-btn {
    max-width: 100%;
    white-space: normal;
  }
}

/* Con el dedo: el botón que abre la lateral medía 32px y cada opción del menú 38px,
   por debajo de los 44px del objetivo táctil (§3). Son lo que más se toca en un teléfono. */
@media (pointer: coarse) {
  .zev-icon-btn {
    width: 44px;
    height: 44px;
  }

  .zev-nav-item {
    min-height: 44px;
  }
}

/* Un teléfono hace zoom sobre cualquier campo de menos de 16px al enfocarlo, y el zoom no
   vuelve solo: la página queda ampliada y corrida hasta que la persona la pellizca. Los
   campos del sistema son de 14px. Con el dedo se escriben a 16px; con mouse no cambia nada. */
@media (pointer: coarse) {
  .zev-input,
  .zev-filtros input,
  .zev-filtros select,
  .zev-filtros textarea {
    font-size: var(--zev-text-base);
  }
}
