/* ==========================================================================
   UltraHub · Capa base
   --------------------------------------------------------------------------
   Esta hoja es la única fuente de verdad del diseño. La cargan TODAS las
   pantallas, incluidas las seis que antes no cargaban ninguna hoja común
   (tecnico, realizar_control, calendario, jefe_estadisticas, admin_firma y el
   header del jefe). Por eso existe: sin esto había 225 colores sueltos
   repetidos 1.038 veces y ningún token llegaba a la mitad de la app.

   Va ANTES de Bootstrap en el orden de carga para los tokens, y hay un bloque
   al final que ajusta a Bootstrap. No reemplaza a Bootstrap: se monta encima.

   Regla que ordena todo el sistema de color:

       El acento (azul) significa "se puede tocar".
       El verde, el ámbar y el rojo significan ESTADO y nada más.

   Antes el verde era las dos cosas a la vez —color de marca y "al día"— así
   que un botón y una camioneta sana se veían igual. Un color no puede querer
   decir dos cosas.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */

:root {
    /* --- Neutrales -------------------------------------------------------
       Una sola familia de grises, todos tintados con la matiz de la marca
       (226°). Mezclar grises cálidos y fríos es lo que hace que una interfaz
       se vea sucia sin que se note por qué. */
    --u-neutro-0:    #ffffff;
    --u-neutro-50:   #f8f9fb;
    --u-neutro-100:  #f2f3f7;
    --u-neutro-200:  #e3e6ed;
    --u-neutro-300:  #cdd0db;
    --u-neutro-400:  #989dae;
    --u-neutro-500:  #6b7185;   /* 4.85 sobre blanco · mínimo para texto */
    --u-neutro-600:  #505568;
    --u-neutro-700:  #363a4a;
    --u-neutro-800:  #212431;
    --u-neutro-900:  #131620;

    /* --- Acento ----------------------------------------------------------
       El azul de marca, desaturado de 94% a 70% y levantado para que se pueda
       usar como color de texto. El #0522a5 original es tan oscuro que sobre
       blanco compite con el texto en vez de destacarse de él. */
    --u-acento:          #234ac7;   /* 7.30 sobre blanco · AAA */
    --u-acento-fuerte:   #183595;   /* hover, pulsado */
    --u-acento-suave:    #e6eaf9;   /* fondos, chips seleccionados */
    --u-acento-borde:    #b9c4ee;

    /* --- Estado ----------------------------------------------------------
       Reservados. No se usan nunca para un botón, un link ni un encabezado
       decorativo: si aparecen, es porque algo está en ese estado. */
    --u-ok:           #1f8455;   /* al día, completado, resuelto */
    --u-ok-fondo:     #eafaf3;
    --u-ok-borde:     #c2f0da;

    --u-aviso:        #976417;   /* por vencer, pendiente, en pausa */
    --u-aviso-fondo:  #fbf4e9;
    --u-aviso-borde:  #f0ddc2;

    --u-riesgo:       #b84028;   /* vencido, sin hacer, fuera de término */
    --u-riesgo-fondo: #faedea;
    --u-riesgo-borde: #f0c9c2;

    --u-parado:       #99293b;   /* fuera de circulación, trabada, bloqueado */
    --u-parado-fondo: #faebed;
    --u-parado-borde: #efc3ca;

    /* --- Marca -----------------------------------------------------------
       Los colores del manual de UltraHub. Van SOLO donde va la marca: login,
       barra lateral, header del jefe, favicon.

       No reemplazan a los de abajo. En la interfaz de trabajo el verde sigue
       significando "al día" y el azul "se puede tocar"; si el verde de marca
       se usara como acento, un botón y una camioneta sana volverían a verse
       igual, que es justo lo que este sistema vino a arreglar. */
    --u-marca-indigo: #2A1268;   /* símbolo y titulares sobre claro */
    --u-marca-azul:   #3163C6;   /* inicio del degradado */
    --u-marca-teal:   #38A399;   /* paso intermedio */
    --u-marca-verde:  #3DC682;   /* cierre del degradado */
    --u-marfil:       #F4F2EC;   /* fondos claros de marca */
    --u-tinta:        #0D0722;   /* fondos oscuros de marca */

    --u-degradado: linear-gradient(135deg,
        var(--u-marca-azul) 0%,
        var(--u-marca-teal) 52%,
        var(--u-marca-verde) 100%);

    /* --- Semánticos de superficie ---------------------------------------- */
    --u-fondo:            var(--u-neutro-50);
    --u-superficie:       var(--u-neutro-0);
    --u-superficie-alta:  var(--u-neutro-0);
    --u-superficie-baja:  var(--u-neutro-100);
    --u-borde:            var(--u-neutro-200);
    --u-borde-fuerte:     var(--u-neutro-300);
    --u-texto:            var(--u-neutro-900);
    --u-texto-suave:      var(--u-neutro-500);
    --u-texto-tenue:      var(--u-neutro-400);
    --u-texto-invertido:  var(--u-neutro-0);

    /* --- Tipografía ------------------------------------------------------
       Geist para texto, Geist Mono para todo lo que sea un dato que se lee en
       columna: patentes, kilómetros, fechas, horas, cantidades. Los números
       en fuente proporcional bailan y en una app de datos eso se nota. */
    --u-fuente: 'Geist', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    --u-fuente-dato: 'Geist Mono', ui-monospace, 'SF Mono', 'Cascadia Mono',
                     Consolas, monospace;

    /* Escala tipográfica. Los tamaños grandes llevan tracking negativo: a más
       cuerpo, menos aire entre letras hace falta. */
    --u-txt-3xs:  0.6875rem;  /* 11px · etiquetas de tabla */
    --u-txt-2xs:  0.75rem;    /* 12px · metadatos */
    --u-txt-xs:   0.8125rem;  /* 13px · texto denso */
    --u-txt-sm:   0.875rem;   /* 14px · cuerpo secundario */
    --u-txt-base: 0.9375rem;  /* 15px · cuerpo */
    --u-txt-lg:   1.0625rem;  /* 17px */
    --u-txt-xl:   1.25rem;    /* 20px · título de tarjeta */
    --u-txt-2xl:  1.5rem;     /* 24px · título de sección */
    --u-txt-3xl:  1.9375rem;  /* 31px · título de pantalla */
    --u-txt-4xl:  2.5rem;     /* 40px · cifras de tablero */
    --u-txt-5xl:  3.25rem;    /* 52px · display */

    --u-track-display: -0.03em;
    --u-track-titulo:  -0.018em;
    --u-track-normal:  0;
    --u-track-etiqueta: 0.04em;

    --u-peso-normal:  400;
    --u-peso-medio:   500;
    --u-peso-semi:    600;
    --u-peso-fuerte:  700;

    --u-alto-apretado: 1.15;
    --u-alto-titulo:   1.25;
    --u-alto-normal:   1.5;
    --u-alto-comodo:   1.65;

    /* --- Espaciado (base 4px) -------------------------------------------- */
    --u-esp-1:  0.25rem;
    --u-esp-2:  0.5rem;
    --u-esp-3:  0.75rem;
    --u-esp-4:  1rem;
    --u-esp-5:  1.25rem;
    --u-esp-6:  1.5rem;
    --u-esp-8:  2rem;
    --u-esp-10: 2.5rem;
    --u-esp-12: 3rem;
    --u-esp-16: 4rem;

    /* --- Radios ----------------------------------------------------------
       Escala real, no doce valores sueltos. Lo de adentro siempre más cerrado
       que lo que lo contiene: un chip dentro de una tarjeta con el mismo radio
       que la tarjeta se ve mal pegado. */
    --u-radio-xs:  4px;    /* chips, badges */
    --u-radio-sm:  7px;    /* inputs, botones */
    --u-radio-md:  11px;   /* tarjetas */
    --u-radio-lg:  16px;   /* paneles, hojas */
    --u-radio-xl:  22px;   /* hojas a pantalla completa */
    --u-radio-full: 999px; /* sólo avatares y puntos */

    /* --- Sombras ---------------------------------------------------------
       Tintadas con la matiz del fondo (226°), no negro puro. Una sombra negra
       sobre un gris frío se ve como suciedad; una sombra tintada se ve como
       profundidad. Todas con la luz viniendo de arriba. */
    --u-sombra-xs: 0 1px 2px rgba(19, 22, 32, 0.05);
    --u-sombra-sm: 0 1px 2px rgba(19, 22, 32, 0.05),
                   0 2px 6px rgba(19, 22, 32, 0.04);
    --u-sombra-md: 0 2px 4px rgba(19, 22, 32, 0.04),
                   0 6px 16px rgba(19, 22, 32, 0.07);
    --u-sombra-lg: 0 4px 8px rgba(19, 22, 32, 0.05),
                   0 16px 32px rgba(19, 22, 32, 0.10);
    --u-sombra-xl: 0 8px 16px rgba(19, 22, 32, 0.06),
                   0 28px 56px rgba(19, 22, 32, 0.14);
    /* Sombra de color, para lo que está seleccionado o activo. */
    --u-sombra-acento: 0 2px 8px rgba(35, 74, 199, 0.22);

    /* --- Movimiento ------------------------------------------------------
       Curvas tipo resorte: arrancan rápido y frenan largo, como algo que tiene
       masa. El easing por defecto del navegador es lo que hace que una
       interfaz se sienta de software y no de objeto. */
    --u-curva-salida:  cubic-bezier(0.32, 0.72, 0, 1);      /* entra algo */
    --u-curva-entrada: cubic-bezier(0.4, 0, 0.6, 1);        /* se va algo */
    --u-curva-suave:   cubic-bezier(0.4, 0, 0.2, 1);        /* cambio de estado */
    --u-curva-resorte: cubic-bezier(0.34, 1.56, 0.64, 1);   /* rebote corto */

    --u-vel-instante: 100ms;   /* pulsado */
    --u-vel-rapida:   180ms;   /* hover, color */
    --u-vel-normal:   260ms;   /* aparecer, desplegar */
    --u-vel-lenta:    380ms;   /* hojas, paneles */

    /* --- Capas -----------------------------------------------------------
       Escala cerrada. Antes había 10, 100, 200, 999, 1000, 1040, 1050, 1060,
       1070, 1080, 1090 y 9999 conviviendo. */
    --u-capa-base:      0;
    --u-capa-elevada:   10;
    --u-capa-pegajosa:  100;   /* encabezados que quedan fijos */
    --u-capa-barra:     200;   /* barra lateral, header del jefe */
    --u-capa-fondo:     900;   /* velo detrás de un panel */
    --u-capa-panel:     1000;  /* modales, hojas */
    --u-capa-visor:     1100;  /* visor de fotos, a pantalla completa */
    --u-capa-aviso:     1200;  /* avisos flotantes: siempre arriba de todo */

    /* --- Medidas ---------------------------------------------------------- */
    --u-ancho-lectura: 68ch;
    --u-ancho-maximo:  1440px;
    --u-barra-ancho:   270px;
    --u-tacto-minimo:  44px;   /* mínimo de Apple para algo que se toca */
}

/* --------------------------------------------------------------------------
   2. Reinicio mínimo
   -------------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html {
    -webkit-text-size-adjust: 100%;
    /* `scroll-behavior: smooth` NO va en html.
       Los paneles se recargan solos cuando un tecnico toca algo, y despues
       restauran el scroll con window.scrollTo(). Con smooth global, esa
       restauracion se ve como que la pantalla se mueve sola cada tanto.
       El desplazamiento suave se pide donde se quiere, no en todos lados. */
    scroll-behavior: auto;
}

/* Solo para los saltos a un ancla dentro de la misma pagina. */
:target { scroll-margin-top: var(--u-esp-16); }

body {
    margin: 0;
    font-family: var(--u-fuente);
    font-size: var(--u-txt-base);
    line-height: var(--u-alto-normal);
    color: var(--u-texto);
    background: var(--u-fondo);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    font-variant-numeric: tabular-nums;
}

/* Esta regla tiene que estar acá y no sólo en style.css: los atributos
   [hidden] se usan para abrir y cerrar modales en todas las pantallas, y una
   sola regla `display: flex` en otro lado los deja visibles tapando la app
   entera. Ya pasó: un visor de fotos abierto sin verse se comía todos los
   clicks de la pantalla. */
[hidden] { display: none !important; }

/* --------------------------------------------------------------------------
   3. Tipografía
   -------------------------------------------------------------------------- */

h1, h2, h3, h4, h5, h6 {
    margin: 0 0 var(--u-esp-3);
    font-weight: var(--u-peso-semi);
    line-height: var(--u-alto-titulo);
    letter-spacing: var(--u-track-titulo);
    text-wrap: balance;   /* evita la palabra huérfana en la última línea */
}

h1 { font-size: var(--u-txt-3xl); letter-spacing: var(--u-track-display);
     font-weight: var(--u-peso-fuerte); line-height: var(--u-alto-apretado); }
h2 { font-size: var(--u-txt-2xl); }
h3 { font-size: var(--u-txt-xl); }
h4 { font-size: var(--u-txt-lg); }
h5, h6 { font-size: var(--u-txt-base); }

p { margin: 0 0 var(--u-esp-4); text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

/* Los párrafos de texto corrido se limitan solos. Una línea de 160 caracteres
   obliga al ojo a buscar dónde sigue. No aplica a celdas de tabla. */
.u-lectura { max-width: var(--u-ancho-lectura); }

a { color: var(--u-acento); text-decoration-thickness: 1px;
    text-underline-offset: 0.18em;
    transition: color var(--u-vel-rapida) var(--u-curva-suave); }
a:hover { color: var(--u-acento-fuerte); }

/* Todo lo que sea un dato que se compara en columna. */
.u-dato, .u-patente, .u-km, .u-fecha, .u-hora, .u-cifra {
    font-family: var(--u-fuente-dato);
    font-variant-numeric: tabular-nums;
    font-feature-settings: 'tnum' 1, 'zero' 1;
}
.u-patente {
    font-weight: var(--u-peso-semi);
    letter-spacing: 0.02em;
}
.u-cifra {
    font-size: var(--u-txt-4xl);
    font-weight: var(--u-peso-semi);
    letter-spacing: var(--u-track-display);
    line-height: var(--u-alto-apretado);
}

/* Etiqueta de campo. Minúscula, no MAYÚSCULA: el versal sostenido se lee más
   lento y en un formulario de 20 campos eso se acumula. */
.u-etiqueta {
    display: block;
    font-size: var(--u-txt-2xs);
    font-weight: var(--u-peso-medio);
    color: var(--u-texto-suave);
    letter-spacing: var(--u-track-normal);
    margin-bottom: var(--u-esp-1);
}

/* --------------------------------------------------------------------------
   4. Foco
   -------------------------------------------------------------------------- */

/* Antes había dos `:focus-visible` en 6.190 líneas: la app era prácticamente
   inusable con teclado. El anillo va por fuera del elemento para que nunca lo
   tape un borde ni un fondo. */
:focus-visible {
    outline: 2px solid var(--u-acento);
    outline-offset: 2px;
    border-radius: var(--u-radio-xs);
}
:focus:not(:focus-visible) { outline: none; }

/* Saltar al contenido: obligatorio para quien navega con teclado y no quiere
   pasar por los 15 links de la barra lateral en cada pantalla. */
.u-saltar {
    position: absolute;
    left: var(--u-esp-4);
    top: calc(-1 * var(--u-esp-16));
    z-index: var(--u-capa-aviso);
    padding: var(--u-esp-3) var(--u-esp-5);
    background: var(--u-acento);
    color: var(--u-texto-invertido);
    border-radius: var(--u-radio-sm);
    font-weight: var(--u-peso-medio);
    text-decoration: none;
    box-shadow: var(--u-sombra-lg);
    transition: top var(--u-vel-normal) var(--u-curva-salida);
}
.u-saltar:focus { top: var(--u-esp-4); color: var(--u-texto-invertido); }

/* --------------------------------------------------------------------------
   5. Superficies
   -------------------------------------------------------------------------- */

.u-tarjeta {
    background: var(--u-superficie);
    border: 1px solid var(--u-borde);
    border-radius: var(--u-radio-md);
    box-shadow: var(--u-sombra-xs);
}
/* Borde O sombra, nunca las dos fuertes a la vez. La tarjeta con borde +
   sombra + fondo blanco es el componente más genérico que existe. */
.u-tarjeta-plana { border: 1px solid var(--u-borde); box-shadow: none; }
.u-tarjeta-flotante { border: none; box-shadow: var(--u-sombra-md); }

.u-tarjeta-tocable {
    cursor: pointer;
    transition: transform var(--u-vel-rapida) var(--u-curva-suave),
                box-shadow var(--u-vel-rapida) var(--u-curva-suave),
                border-color var(--u-vel-rapida) var(--u-curva-suave);
}
.u-tarjeta-tocable:hover {
    transform: translateY(-1px);
    box-shadow: var(--u-sombra-md);
    border-color: var(--u-borde-fuerte);
}
.u-tarjeta-tocable:active { transform: translateY(0) scale(0.995); }

/* Material translúcido. Se usa sólo en lo que flota sobre contenido: barras
   pegajosas y encabezados de hoja. Con respaldo sólido para los navegadores
   que no soportan backdrop-filter. */
.u-material {
    background: rgba(255, 255, 255, 0.82);
    border-bottom: 1px solid var(--u-borde);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .u-material {
        background: rgba(255, 255, 255, 0.72);
        -webkit-backdrop-filter: saturate(180%) blur(20px);
        backdrop-filter: saturate(180%) blur(20px);
    }
}

/* Textura. Un ruido muy leve y fijo sobre el fondo: rompe la planitud digital
   sin que se note como un efecto. */
.u-grano::after {
    content: '';
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: var(--u-capa-base);
    opacity: 0.02;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='r'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23r)'/%3E%3C/svg%3E");
}

/* --------------------------------------------------------------------------
   6. Estado
   -------------------------------------------------------------------------- */

/* Un solo componente para los cinco estados. Antes cada pantalla inventaba el
   suyo: había pill azul, pill negra, pill verde, pill gris y pill naranja
   conviviendo en la misma tarjeta del técnico. */
.u-estado {
    display: inline-flex;
    align-items: center;
    gap: var(--u-esp-1);
    padding: 0.15em 0.55em;
    border-radius: var(--u-radio-xs);
    font-size: var(--u-txt-2xs);
    font-weight: var(--u-peso-medio);
    line-height: 1.45;
    letter-spacing: var(--u-track-normal);
    white-space: nowrap;
    border: 1px solid transparent;
}
.u-estado::before {
    content: '';
    width: 5px; height: 5px;
    border-radius: var(--u-radio-full);
    background: currentColor;
    flex: none;
}
.u-estado-ok     { color: var(--u-ok);     background: var(--u-ok-fondo);     border-color: var(--u-ok-borde); }
.u-estado-aviso  { color: var(--u-aviso);  background: var(--u-aviso-fondo);  border-color: var(--u-aviso-borde); }
.u-estado-riesgo { color: var(--u-riesgo); background: var(--u-riesgo-fondo); border-color: var(--u-riesgo-borde); }
.u-estado-parado { color: var(--u-parado); background: var(--u-parado-fondo); border-color: var(--u-parado-borde); }
.u-estado-neutro { color: var(--u-neutro-600); background: var(--u-neutro-100); border-color: var(--u-borde); }
.u-estado-acento { color: var(--u-acento); background: var(--u-acento-suave); border-color: var(--u-acento-borde); }

/* Sin el punto, para cuando el estado ya lleva un icono. */
.u-estado-liso::before { display: none; }

/* Franja de color al costado de una fila o tarjeta. Comunica el estado sin
   pintar el fondo entero: el rojo pleno a pantalla completa es el recurso más
   fuerte que hay y no puede usarse veinte veces seguidas. */
.u-franja { border-left: 3px solid var(--u-borde-fuerte); }
.u-franja-ok     { border-left-color: var(--u-ok); }
.u-franja-aviso  { border-left-color: var(--u-aviso); }
.u-franja-riesgo { border-left-color: var(--u-riesgo); }
.u-franja-parado { border-left-color: var(--u-parado); }
.u-franja-acento { border-left-color: var(--u-acento); }

/* --------------------------------------------------------------------------
   7. Botones
   -------------------------------------------------------------------------- */

.u-boton {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--u-esp-2);
    min-height: var(--u-tacto-minimo);
    padding: var(--u-esp-2) var(--u-esp-4);
    border: 1px solid transparent;
    border-radius: var(--u-radio-sm);
    font-family: inherit;
    font-size: var(--u-txt-sm);
    font-weight: var(--u-peso-medio);
    line-height: 1.4;
    text-decoration: none;
    cursor: pointer;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
    transition: background-color var(--u-vel-rapida) var(--u-curva-suave),
                border-color var(--u-vel-rapida) var(--u-curva-suave),
                color var(--u-vel-rapida) var(--u-curva-suave),
                box-shadow var(--u-vel-rapida) var(--u-curva-suave),
                transform var(--u-vel-instante) var(--u-curva-suave);
}

/* El pulsado es lo que hace que un botón se sienta físico. Antes había cinco
   `:active` en toda la app, y el técnico usa la suya sólo con el dedo: sin
   hover, el pulsado es el único aviso de que el toque entró. */
.u-boton:active { transform: scale(0.97); }

.u-boton:disabled, .u-boton[aria-disabled='true'] {
    opacity: 0.45;
    cursor: not-allowed;
    transform: none;
}

.u-boton-principal {
    background: var(--u-acento);
    color: var(--u-texto-invertido);
    box-shadow: var(--u-sombra-acento);
}
.u-boton-principal:hover:not(:disabled) { background: var(--u-acento-fuerte); color: var(--u-texto-invertido); }

.u-boton-secundario {
    background: var(--u-superficie);
    color: var(--u-texto);
    border-color: var(--u-borde-fuerte);
    box-shadow: var(--u-sombra-xs);
}
.u-boton-secundario:hover:not(:disabled) { background: var(--u-neutro-50); border-color: var(--u-neutro-400); color: var(--u-texto); }

.u-boton-tenue {
    background: transparent;
    color: var(--u-texto-suave);
}
.u-boton-tenue:hover:not(:disabled) { background: var(--u-neutro-100); color: var(--u-texto); }

/* Para lo que no se puede deshacer: dar de baja, borrar, sacar de circulación.
   Es el único botón que usa un color de estado, y es a propósito. */
.u-boton-riesgo {
    background: var(--u-superficie);
    color: var(--u-riesgo);
    border-color: var(--u-riesgo-borde);
}
.u-boton-riesgo:hover:not(:disabled) { background: var(--u-riesgo-fondo); color: var(--u-riesgo); }

.u-boton-chico { min-height: 32px; padding: var(--u-esp-1) var(--u-esp-3); font-size: var(--u-txt-2xs); }
.u-boton-grande { min-height: 52px; padding: var(--u-esp-3) var(--u-esp-6); font-size: var(--u-txt-base); }
.u-boton-ancho { width: 100%; }

/* --------------------------------------------------------------------------
   8. Campos
   -------------------------------------------------------------------------- */

.u-campo {
    display: block;
    width: 100%;
    min-height: var(--u-tacto-minimo);
    padding: var(--u-esp-2) var(--u-esp-3);
    font-family: inherit;
    font-size: var(--u-txt-base);
    color: var(--u-texto);
    background: var(--u-superficie);
    border: 1px solid var(--u-borde-fuerte);
    border-radius: var(--u-radio-sm);
    transition: border-color var(--u-vel-rapida) var(--u-curva-suave),
                box-shadow var(--u-vel-rapida) var(--u-curva-suave);
}
.u-campo::placeholder { color: var(--u-texto-tenue); }
.u-campo:hover:not(:disabled) { border-color: var(--u-neutro-400); }
.u-campo:focus {
    outline: none;
    border-color: var(--u-acento);
    box-shadow: 0 0 0 3px var(--u-acento-suave);
}
.u-campo:disabled { background: var(--u-neutro-100); color: var(--u-texto-tenue); cursor: not-allowed; }
.u-campo[aria-invalid='true'] { border-color: var(--u-riesgo); }
.u-campo[aria-invalid='true']:focus { box-shadow: 0 0 0 3px var(--u-riesgo-fondo); }

/* Error debajo del campo, no en una caja del navegador. */
.u-error-campo {
    display: flex;
    align-items: center;
    gap: var(--u-esp-1);
    margin-top: var(--u-esp-1);
    font-size: var(--u-txt-2xs);
    color: var(--u-riesgo);
}

/* --------------------------------------------------------------------------
   9. Estados de carga y vacío
   -------------------------------------------------------------------------- */

/* Esqueleto con la forma del contenido que viene, en vez de una ruedita que
   no dice nada sobre cuánto falta ni qué va a aparecer. */
.u-esqueleto {
    background: linear-gradient(90deg,
        var(--u-neutro-100) 25%,
        var(--u-neutro-200) 37%,
        var(--u-neutro-100) 63%);
    background-size: 400% 100%;
    border-radius: var(--u-radio-xs);
    animation: u-brillo 1.4s ease-in-out infinite;
}
@keyframes u-brillo {
    from { background-position: 100% 50%; }
    to   { background-position: 0 50%; }
}
.u-esqueleto-linea { height: 0.85em; margin-bottom: var(--u-esp-2); }
.u-esqueleto-linea:last-child { width: 60%; margin-bottom: 0; }

.u-vacio {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--u-esp-3);
    padding: var(--u-esp-12) var(--u-esp-6);
    text-align: center;
    color: var(--u-texto-suave);
}
.u-vacio-icono {
    display: grid;
    place-items: center;
    width: 52px; height: 52px;
    border-radius: var(--u-radio-md);
    background: var(--u-neutro-100);
    color: var(--u-texto-tenue);
    font-size: var(--u-txt-2xl);
}
.u-vacio-titulo {
    font-size: var(--u-txt-lg);
    font-weight: var(--u-peso-medio);
    color: var(--u-texto);
    margin: 0;
}
.u-vacio p { max-width: 44ch; font-size: var(--u-txt-sm); margin: 0; }

/* --------------------------------------------------------------------------
   10. Movimiento
   -------------------------------------------------------------------------- */

/* Entrada escalonada. Nada aparece todo junto: las filas entran una atrás de
   otra con un retraso mínimo, que es lo que hace que una lista se sienta que
   llega en vez de que parpadea. */
@keyframes u-entrar {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: none; }
}
.u-entra { animation: u-entrar var(--u-vel-normal) var(--u-curva-salida) both; }
.u-entra-1 { animation-delay: 30ms; }
.u-entra-2 { animation-delay: 60ms; }
.u-entra-3 { animation-delay: 90ms; }
.u-entra-4 { animation-delay: 120ms; }
.u-entra-5 { animation-delay: 150ms; }
.u-entra-6 { animation-delay: 180ms; }

@keyframes u-aparecer { from { opacity: 0; } to { opacity: 1; } }
@keyframes u-subir-hoja {
    from { opacity: 0; transform: translateY(100%); }
    to   { opacity: 1; transform: none; }
}
@keyframes u-crecer-panel {
    from { opacity: 0; transform: scale(0.96) translateY(8px); }
    to   { opacity: 1; transform: none; }
}

/* Todo el movimiento se apaga si el sistema lo pide. No es un detalle de
   accesibilidad opcional: para alguien con sensibilidad vestibular, una
   interfaz que se mueve sola marea de verdad. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* --------------------------------------------------------------------------
   11. Estructura
   -------------------------------------------------------------------------- */

.u-contenedor {
    width: 100%;
    max-width: var(--u-ancho-maximo);
    margin-inline: auto;
    padding-inline: var(--u-esp-4);
}
@media (min-width: 768px) {
    .u-contenedor { padding-inline: var(--u-esp-6); }
}

/* El padding de abajo va un poco más que el de arriba: ópticamente, lo mismo
   arriba y abajo se ve corrido hacia abajo. */
.u-seccion { padding-top: var(--u-esp-8); padding-bottom: var(--u-esp-10); }

.u-pila { display: flex; flex-direction: column; }
.u-pila-1 { gap: var(--u-esp-1); } .u-pila-2 { gap: var(--u-esp-2); }
.u-pila-3 { gap: var(--u-esp-3); } .u-pila-4 { gap: var(--u-esp-4); }
.u-pila-6 { gap: var(--u-esp-6); }

.u-fila { display: flex; align-items: center; }
.u-fila-1 { gap: var(--u-esp-1); } .u-fila-2 { gap: var(--u-esp-2); }
.u-fila-3 { gap: var(--u-esp-3); } .u-fila-4 { gap: var(--u-esp-4); }
.u-empuje { margin-left: auto; }

/* Grilla que se acomoda sola. CSS Grid en vez de cuentas de porcentajes con
   flex, que es de donde salen los desbordes raros en pantallas intermedias. */
.u-grilla { display: grid; gap: var(--u-esp-4); }
.u-grilla-auto { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.u-grilla-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.u-grilla-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 767px) {
    .u-grilla-2, .u-grilla-3 { grid-template-columns: minmax(0, 1fr); }
}

/* 100dvh y no 100vh: en Safari de iOS, 100vh cuenta la barra de direcciones
   que después se esconde, y la pantalla salta al primer scroll. */
.u-alto-pantalla { min-height: 100vh; min-height: 100dvh; }

/* Respeta la zona del notch y la barra de gestos del teléfono. */
.u-seguro-abajo { padding-bottom: max(var(--u-esp-4), env(safe-area-inset-bottom)); }
.u-seguro-arriba { padding-top: max(var(--u-esp-4), env(safe-area-inset-top)); }

/* --------------------------------------------------------------------------
   12. Utilidades
   -------------------------------------------------------------------------- */

.u-solo-lectores {
    position: absolute; width: 1px; height: 1px;
    padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

.u-txt-suave { color: var(--u-texto-suave); }
.u-txt-tenue { color: var(--u-texto-tenue); }
.u-txt-2xs { font-size: var(--u-txt-2xs); }
.u-txt-xs  { font-size: var(--u-txt-xs); }
.u-txt-sm  { font-size: var(--u-txt-sm); }
.u-txt-lg  { font-size: var(--u-txt-lg); }
.u-peso-medio { font-weight: var(--u-peso-medio); }
.u-peso-semi  { font-weight: var(--u-peso-semi); }

.u-separador { height: 1px; background: var(--u-borde); border: 0; margin: var(--u-esp-4) 0; }

/* Corta en una línea sin romper el ancho de la grilla. */
.u-una-linea {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}

/* --------------------------------------------------------------------------
   13. Ajuste a Bootstrap
   --------------------------------------------------------------------------
   Bootstrap 5.1.3 se queda (migrar de framework sería riesgo sin ganancia).
   Lo que sigue lo alinea con los tokens para que un `btn btn-primary` suelto
   en cualquier template no cante contra el resto.
   -------------------------------------------------------------------------- */

.btn {
    border-radius: var(--u-radio-sm);
    font-weight: var(--u-peso-medio);
    transition: background-color var(--u-vel-rapida) var(--u-curva-suave),
                border-color var(--u-vel-rapida) var(--u-curva-suave),
                transform var(--u-vel-instante) var(--u-curva-suave);
}
.btn:active { transform: scale(0.97); }
.btn:focus, .btn.focus { box-shadow: 0 0 0 3px var(--u-acento-suave); }

.btn-primary {
    background-color: var(--u-acento);
    border-color: var(--u-acento);
}
.btn-primary:hover, .btn-primary:focus {
    background-color: var(--u-acento-fuerte);
    border-color: var(--u-acento-fuerte);
}
.btn-outline-primary { color: var(--u-acento); border-color: var(--u-acento-borde); }
/* El color del texto va SIEMPRE junto con el del fondo. Sin esta linea el
   hover pintaba el boton de azul y dejaba el texto del mismo azul: contraste
   1.00, o sea invisible. */
.btn-outline-primary:hover,
.btn-outline-primary:focus,
.btn-outline-primary:active {
    background-color: var(--u-acento);
    border-color: var(--u-acento);
    color: var(--u-texto-invertido);
}
.btn-outline-primary:hover i,
.btn-outline-primary:hover .bi { color: inherit; }

/* Lo mismo para el resto de los outline: cualquiera que se rellene al pasar
   por encima tiene que invertir el texto. */
.btn-outline-secondary:hover, .btn-outline-secondary:focus {
    background-color: var(--u-neutro-600); border-color: var(--u-neutro-600);
    color: var(--u-texto-invertido);
}
.btn-outline-success:hover, .btn-outline-success:focus {
    background-color: var(--u-ok); border-color: var(--u-ok);
    color: var(--u-texto-invertido);
}
.btn-outline-danger:hover, .btn-outline-danger:focus {
    background-color: var(--u-parado); border-color: var(--u-parado);
    color: var(--u-texto-invertido);
}
.btn-outline-warning:hover, .btn-outline-warning:focus {
    background-color: var(--u-aviso); border-color: var(--u-aviso);
    color: var(--u-texto-invertido);
}
.btn-outline-info:hover, .btn-outline-info:focus {
    background-color: var(--u-acento); border-color: var(--u-acento);
    color: var(--u-texto-invertido);
}

/* Los rellenos tambien: si se les cambia el fondo, el texto va explicito. */
.btn-primary, .btn-primary:hover, .btn-primary:focus,
.btn-success, .btn-success:hover, .btn-success:focus,
.btn-danger, .btn-danger:hover, .btn-danger:focus,
.btn-warning, .btn-warning:hover, .btn-warning:focus,
.btn-info, .btn-info:hover, .btn-info:focus,
.btn-secondary, .btn-secondary:hover, .btn-secondary:focus {
    color: var(--u-texto-invertido);
}

.btn-success { background-color: var(--u-ok); border-color: var(--u-ok); }
.btn-warning { background-color: var(--u-aviso); border-color: var(--u-aviso); color: #fff; }
.btn-danger  { background-color: var(--u-parado); border-color: var(--u-parado); }

.card {
    border-color: var(--u-borde);
    border-radius: var(--u-radio-md);
    box-shadow: var(--u-sombra-xs);
}
.form-control, .form-select {
    border-color: var(--u-borde-fuerte);
    border-radius: var(--u-radio-sm);
    font-size: var(--u-txt-base);
}
.form-control:focus, .form-select:focus {
    border-color: var(--u-acento);
    box-shadow: 0 0 0 3px var(--u-acento-suave);
}
.badge { font-weight: var(--u-peso-medio); border-radius: var(--u-radio-xs); }
.table { --bs-table-border-color: var(--u-borde); }
.modal-content { border: none; border-radius: var(--u-radio-lg); box-shadow: var(--u-sombra-xl); }

/* Bootstrap pone los modales en 1050-1060. Los alineamos con la escala para
   que un visor de fotos propio nunca quede debajo de un modal de Bootstrap. */
.modal-backdrop { z-index: var(--u-capa-fondo); }
.modal { z-index: var(--u-capa-panel); }

/* --------------------------------------------------------------------------
   14. Avisos y paneles (reemplazo de alert/confirm/prompt)
   --------------------------------------------------------------------------
   Los estilos de lo que arma static/js/ui.js. Ver ese archivo para la física
   del arrastre.
   -------------------------------------------------------------------------- */

.uh-avisos {
    position: fixed;
    z-index: var(--u-capa-aviso);
    display: flex;
    flex-direction: column;
    gap: var(--u-esp-2);
    pointer-events: none;
}
/* En escritorio abajo a la derecha, fuera del camino. En el celular arriba,
   porque abajo está la mano y la barra de gestos del sistema. */
@media (min-width: 768px) {
    .uh-avisos { right: var(--u-esp-5); bottom: var(--u-esp-5); width: min(380px, calc(100vw - 2rem)); }
}
@media (max-width: 767px) {
    .uh-avisos {
        left: var(--u-esp-3); right: var(--u-esp-3);
        top: max(var(--u-esp-3), env(safe-area-inset-top));
    }
}

.uh-aviso {
    pointer-events: auto;
    display: flex;
    align-items: flex-start;
    gap: var(--u-esp-3);
    padding: var(--u-esp-3) var(--u-esp-3) var(--u-esp-3) var(--u-esp-4);
    background: var(--u-superficie);
    border: 1px solid var(--u-borde);
    border-left: 3px solid var(--u-neutro-400);
    border-radius: var(--u-radio-md);
    box-shadow: var(--u-sombra-lg);
    font-size: var(--u-txt-sm);
    animation: u-entrar-aviso var(--u-vel-normal) var(--u-curva-salida) both;
}
@keyframes u-entrar-aviso {
    from { opacity: 0; transform: translateY(8px) scale(0.97); }
    to   { opacity: 1; transform: none; }
}
@keyframes u-salir-aviso {
    from { opacity: 1; transform: none; max-height: 200px; }
    to   { opacity: 0; transform: translateY(-6px) scale(0.97); max-height: 0; }
}
.uh-aviso-saliendo { animation: u-salir-aviso 220ms var(--u-curva-entrada) both; }

.uh-aviso-ok    { border-left-color: var(--u-ok); }
.uh-aviso-error { border-left-color: var(--u-riesgo); }
.uh-aviso-aviso { border-left-color: var(--u-aviso); }
.uh-aviso-info  { border-left-color: var(--u-acento); }

.uh-aviso-icono { font-size: 1.05rem; line-height: 1.35; flex: none; }
.uh-aviso-ok    .uh-aviso-icono { color: var(--u-ok); }
.uh-aviso-error .uh-aviso-icono { color: var(--u-riesgo); }
.uh-aviso-aviso .uh-aviso-icono { color: var(--u-aviso); }
.uh-aviso-info  .uh-aviso-icono { color: var(--u-acento); }

.uh-aviso-texto { flex: 1; min-width: 0; line-height: var(--u-alto-normal); }

.uh-aviso-cerrar {
    flex: none;
    display: grid; place-items: center;
    width: 28px; height: 28px;
    padding: 0; border: 0;
    background: transparent;
    color: var(--u-texto-tenue);
    border-radius: var(--u-radio-xs);
    font-size: var(--u-txt-2xs);
    cursor: pointer;
    transition: background-color var(--u-vel-rapida) var(--u-curva-suave),
                color var(--u-vel-rapida) var(--u-curva-suave);
}
.uh-aviso-cerrar:hover { background: var(--u-neutro-100); color: var(--u-texto); }

/* --- Velo y panel ------------------------------------------------------- */

/* Oscurecer para concentrar: la tarea de atrás se empuja hacia el fondo. */
.uh-velo {
    position: fixed; inset: 0;
    z-index: var(--u-capa-fondo);
    background: rgba(19, 22, 32, 0.42);
    animation: u-aparecer var(--u-vel-normal) var(--u-curva-suave) both;
}
@supports (backdrop-filter: blur(1px)) {
    .uh-velo { -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); }
}
.uh-velo.uh-saliendo { animation: u-aparecer 180ms var(--u-curva-entrada) reverse both; }

.uh-sin-scroll { overflow: hidden; }

.uh-panel {
    position: fixed;
    z-index: var(--u-capa-panel);
    background: var(--u-superficie);
    color: var(--u-texto);
    box-shadow: var(--u-sombra-xl);
    /* Un <dialog> cerrado no se muestra; abierto pasa a flex. */
    display: flex;
    flex-direction: column;
    /* Escritorio: panel centrado que crece desde el centro. */
    left: 50%; top: 50%;
    transform: translate(-50%, -50%);
    width: min(440px, calc(100vw - 2rem));
    max-width: min(440px, calc(100vw - 2rem));
    max-height: 90dvh;
    padding: 0;
    /* El <dialog> trae borde y margen del navegador. */
    border: none;
    margin: 0;
    border-radius: var(--u-radio-lg);
    overflow: visible;
    animation: u-crecer-panel var(--u-vel-normal) var(--u-curva-salida) both;
}
/* Un dialog sin `open` no se muestra: esta regla solo aplica al abierto. */
dialog.uh-panel:not([open]) { display: none; }

/* El velo del <dialog> es ::backdrop, no un div aparte. Va con el mismo
   aspecto que el velo manual, para que se vean iguales. */
dialog.uh-panel::backdrop {
    background: rgba(19, 22, 32, 0.42);
    animation: u-aparecer var(--u-vel-normal) var(--u-curva-suave) both;
}
@supports (backdrop-filter: blur(1px)) {
    dialog.uh-panel::backdrop {
        -webkit-backdrop-filter: blur(3px);
        backdrop-filter: blur(3px);
    }
}
@media (prefers-reduced-transparency: reduce) {
    dialog.uh-panel::backdrop {
        background: rgba(19, 22, 32, 0.6);
        -webkit-backdrop-filter: none; backdrop-filter: none;
    }
}
.uh-panel.uh-saliendo {
    animation: u-crecer-panel 180ms var(--u-curva-entrada) reverse both;
}

/* Celular: hoja desde abajo, cerca del pulgar. Entra y sale por el mismo
   lado: si algo se fue para abajo, tiene que volver desde abajo. */
.uh-panel-hoja {
    left: 0; right: 0; top: auto; bottom: 0;
    width: auto;
    max-width: none;
    transform: none;
    max-height: 88dvh;
    border-radius: var(--u-radio-xl) var(--u-radio-xl) 0 0;
    padding-bottom: env(safe-area-inset-bottom);
    animation: u-subir-hoja var(--u-vel-lenta) var(--u-curva-salida) both;
    touch-action: none;
}
.uh-panel-hoja.uh-saliendo {
    animation: u-subir-hoja 220ms var(--u-curva-entrada) reverse both;
}

/* La manija. Además de indicar que se puede arrastrar, es la zona de agarre:
   el resto de la hoja queda libre para tocar sus botones. */
.uh-agarre {
    flex: none;
    padding: var(--u-esp-3) 0 var(--u-esp-1);
    display: grid; place-items: center;
    cursor: grab;
    touch-action: none;
}
.uh-agarre::before {
    content: '';
    width: 38px; height: 4px;
    border-radius: var(--u-radio-full);
    background: var(--u-neutro-300);
}
.uh-agarre:active { cursor: grabbing; }

.uh-panel-cuerpo {
    padding: var(--u-esp-5) var(--u-esp-5) var(--u-esp-4);
    overflow-y: auto;
}
.uh-panel-hoja .uh-panel-cuerpo { padding-top: var(--u-esp-3); }

.uh-panel-titulo {
    margin: 0 0 var(--u-esp-2);
    font-size: var(--u-txt-xl);
    font-weight: var(--u-peso-semi);
    letter-spacing: var(--u-track-titulo);
}
.uh-panel-detalle {
    margin: 0;
    color: var(--u-texto-suave);
    font-size: var(--u-txt-sm);
    max-width: 52ch;
}
.uh-panel-cuerpo .u-etiqueta { margin-top: var(--u-esp-4); }

.uh-panel-pie {
    display: flex;
    gap: var(--u-esp-2);
    padding: var(--u-esp-4) var(--u-esp-5);
    border-top: 1px solid var(--u-borde);
    background: var(--u-neutro-50);
    border-radius: 0 0 var(--u-radio-lg) var(--u-radio-lg);
}
.uh-panel-hoja .uh-panel-pie { border-radius: 0; }
.uh-panel-pie .u-boton { flex: 1; }
/* En escritorio los botones no se estiran: un "Cancelar" de 200px de ancho no
   comunica nada. En el celular sí, porque son objetivos táctiles. */
@media (min-width: 768px) {
    .uh-panel-pie { justify-content: flex-end; }
    .uh-panel-pie .u-boton { flex: none; min-width: 108px; }
}

/* --------------------------------------------------------------------------
   15. Preferencias del sistema
   -------------------------------------------------------------------------- */

/* Menos transparencia: el material se vuelve sólido en vez de desaparecer.
   Alguien que pidió esto necesita leer, no ver el fondo. */
@media (prefers-reduced-transparency: reduce) {
    .u-material { background: var(--u-superficie); -webkit-backdrop-filter: none; backdrop-filter: none; }
    .uh-velo { background: rgba(19, 22, 32, 0.6); -webkit-backdrop-filter: none; backdrop-filter: none; }
}

/* Más contraste: bordes definidos y nada de sombras haciendo de separador. */
@media (prefers-contrast: more) {
    :root {
        --u-borde: var(--u-neutro-400);
        --u-borde-fuerte: var(--u-neutro-600);
        --u-texto-suave: var(--u-neutro-700);
        --u-texto-tenue: var(--u-neutro-600);
    }
    .u-tarjeta, .uh-aviso, .uh-panel { border: 1px solid var(--u-borde-fuerte); }
    .u-material { background: var(--u-superficie); -webkit-backdrop-filter: none; backdrop-filter: none; }
}

/* ==========================================================================
   ESTADÍSTICAS DE KILÓMETROS
   --------------------------------------------------------------------------
   Barras horizontales y no verticales: las etiquetas son patentes de siete
   caracteres y en vertical habría que girarlas para que entren.
   ========================================================================== */

.km-barras { display: flex; flex-direction: column; gap: var(--u-esp-2); margin-top: var(--u-esp-3); }

.km-fila {
    display: grid;
    grid-template-columns: 76px 1fr 96px;
    align-items: center;
    gap: var(--u-esp-3);
}

.km-patente {
    font-family: var(--u-fuente-dato);
    font-size: var(--u-txt-2xs);
    font-weight: var(--u-peso-semi);
    color: var(--u-texto);
    letter-spacing: 0.02em;
}

.km-barra {
    display: block;
    height: 10px;
    background: var(--u-neutro-100);
    border-radius: var(--u-radio-xs);
    overflow: hidden;
}
.km-barra-relleno {
    display: block;
    height: 100%;
    background: var(--u-acento);
    border-radius: var(--u-radio-xs);
    transition: width var(--u-vel-lenta) var(--u-curva-salida);
}

.km-valor {
    font-family: var(--u-fuente-dato);
    font-variant-numeric: tabular-nums;
    font-size: var(--u-txt-2xs);
    font-weight: var(--u-peso-semi);
    color: var(--u-texto);
    text-align: right;
}
.km-valor small { font-weight: var(--u-peso-normal); color: var(--u-texto-tenue); }

/* Selector de camionetas para las curvas. */
.km-selector { display: flex; flex-wrap: wrap; gap: var(--u-esp-2); }

.km-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--u-esp-1);
    padding: 3px var(--u-esp-2);
    background: var(--u-superficie);
    border: 1px solid var(--u-borde);
    border-radius: var(--u-radio-xs);
    font-family: var(--u-fuente-dato);
    font-size: var(--u-txt-2xs);
    font-weight: var(--u-peso-medio);
    color: var(--u-texto-suave);
    cursor: pointer;
    user-select: none;
    transition: background-color var(--u-vel-rapida) var(--u-curva-suave),
                border-color var(--u-vel-rapida) var(--u-curva-suave),
                color var(--u-vel-rapida) var(--u-curva-suave);
}
.km-chip input { position: absolute; opacity: 0; width: 0; height: 0; }
.km-chip:hover { border-color: var(--u-borde-fuerte); color: var(--u-texto); }
.km-chip.activo { color: var(--u-texto); border-color: var(--color); background: var(--u-neutro-50); }

/* El punto toma el color de la línea de esa camioneta en el gráfico. */
.km-punto {
    width: 8px; height: 8px;
    border-radius: var(--u-radio-full);
    background: var(--u-neutro-300);
    flex: none;
}
.km-chip.activo .km-punto { background: var(--color); }

#km-curvas { width: 100%; height: 300px; margin-top: var(--u-esp-3); }

/* Cifras del gráfico de la flota, arriba a la derecha. */
.km-totales-cifras { display: flex; flex-wrap: wrap; gap: var(--u-esp-5); }
.km-total-dato { display: flex; flex-direction: column; }
.km-total-dato strong {
    font-family: var(--u-fuente-dato);
    font-variant-numeric: tabular-nums;
    font-size: var(--u-txt-xl);
    font-weight: var(--u-peso-semi);
    letter-spacing: var(--u-track-titulo);
    color: var(--u-texto);
    line-height: 1.1;
}
.km-total-dato small { font-size: var(--u-txt-2xs); color: var(--u-texto-suave); }

/* La leyenda: sin esto no se sabe qué son las barras y qué la línea. */
.leyenda-barra, .leyenda-linea {
    display: inline-block;
    vertical-align: middle;
    margin-right: 6px;
}
.leyenda-barra {
    width: 9px; height: 12px;
    background: var(--u-neutro-300);
    border-radius: 2px;
}
.leyenda-linea {
    width: 16px; height: 2.5px;
    background: var(--u-acento);
    border-radius: 2px;
}
#km-flota { width: 100%; height: 320px; margin-top: var(--u-esp-3); }

/* El chip "Todas" se distingue de los de patente: no lleva color de línea
   porque no representa una serie, representa al conjunto. */
.km-chip-todas { font-family: var(--u-fuente); }
.km-chip-todas.activo {
    background: var(--u-acento-suave);
    border-color: var(--u-acento-borde);
    color: var(--u-acento);
}
.km-chip-todas.activo .km-punto { background: var(--u-acento); }

/* Paleta categórica de los gráficos. Propia y no la de estado: el verde, el
   ámbar y el rojo significan "al día", "por vencer" y "vencido" en toda la
   app, y usarlos para identificar camionetas los vaciaría de sentido.

   Los diez tonos salen de una búsqueda, no de elegirlos a ojo: cada uno es
   el que queda más lejos de todos los anteriores entre los que pasan AA
   sobre blanco (los chips llevan el texto en ese color). El primero es el
   azul de marca. El par más parecido queda a distancia 86 en RGB. */
:root {
    --u-serie-1: #234ac7;
    --u-serie-2: #d52020;
    --u-serie-3: #328514;
    --u-serie-4: #c920d5;
    --u-serie-5: #792073;
    --u-serie-6: #148576;
    --u-serie-7: #916e27;
    --u-serie-8: #202079;
    --u-serie-9: #7f1a1a;
    --u-serie-10: #d52080;
}


/* ==========================================================================
   APLICACION AGREGADA A LA PANTALLA DE INICIO
   --------------------------------------------------------------------------
   Cuando el sistema se abre desde el icono del celular no hay barra del
   navegador arriba ni abajo. Eso da mas pantalla util, pero tambien deja el
   contenido pegado a la muesca de la camara y a la franja de gestos: sin
   esto, en un iPhone el ultimo boton de una pantalla queda debajo de la raya
   de abajo y no se puede tocar.

   `env(safe-area-inset-*)` son las medidas que informa el propio sistema.
   Valen 0 en una pantalla sin muescas, asi que la regla no molesta a nadie.
   Requiere `viewport-fit=cover` en el <meta name="viewport">, que ya esta en
   las 18 pantallas.

   Va dentro de `display-mode: standalone` para no cambiar nada cuando el
   sistema se usa desde el navegador de siempre. Las reglas de la barra
   lateral y la superior estan en sidebar.css, que se carga despues que esta
   hoja y si no las pisaria.
   ========================================================================== */

@media (display-mode: standalone) {
    body {
        padding-bottom: max(env(safe-area-inset-bottom), 0px);
        padding-left: max(env(safe-area-inset-left), 0px);
        padding-right: max(env(safe-area-inset-right), 0px);
    }
}
