/* ══ Lactisoft · auth y panel ══ */
/*
|==============================================================================
| LOS COLORES · UNA SOLA DEFINICIÓN, DOS TEMAS
|==============================================================================
|
| Todo color del panel sale de aquí. No es una preferencia de estilo: es lo que
| hace posible el tema oscuro. Antes había 125 colores escritos a mano repartidos
| por las cuatro hojas, y con eso un cambio de paleta dejaba la mitad de la
| pantalla en claro — fondos claros con texto claro encima, tablas ilegibles.
|
| ═══ CÓMO SE LEE ESTA PALETA ═══
|
| Hay tres familias y se comportan distinto al cambiar de tema:
|
|   MARCA        petróleo, mantequilla, pradera, rojo. Son la identidad y NO
|                cambian: un botón de guardar es del mismo verde azulado en los
|                dos temas, porque si cambiara dejaría de ser el mismo producto.
|
|   SUPERFICIE   papel, leche, líneas, tinta. Éstas se INVIERTEN. Es todo el
|                trabajo del tema oscuro.
|
|   SIDEBAR      `--side-*`. Ojo con éstas: el sidebar YA era oscuro en el tema
|                claro, así que en oscuro casi no se mueven. Invertirlas sería
|                blanquear la única zona que ya estaba bien.
|
| ═══ POR QUÉ HAY TOKENS QUE PARECEN REPETIDOS ═══
|
| `--mal-f`, `--mal-t` y `--mal-b` son fondo, texto y borde de lo mismo (un
| error). Van separados porque en oscuro NO se transforman igual: el fondo pasa
| a un rojo muy apagado, el texto tiene que ACLARARSE para seguir legible, y el
| borde queda en medio. Un solo token con `opacity` encima no da ese resultado.
*/
:root{
    color-scheme: light;

    --tinta:#101B21; --tinta-2:#25373F;
    --petroleo:#155E6E; --petroleo-osc:#0C333D; --petroleo-cl:#2E8296;
    --leche:#FBFAF6; --papel:#FFFFFF;
    --crema:#F2E9D8; --mantequilla:#E8B33C; --pradera:#2F7D53; --rojo:#B23A48;
    --gris:#5F7078; --gris-cl:#8FA2A9; --linea:#E6E2D7; --linea-2:#F0EDE5;
    --sombra:0 1px 2px rgba(12,51,61,.05), 0 8px 24px -12px rgba(12,51,61,.18);
    --r:12px;

    /* ── superficies · SE INVIERTEN ── */
    --sup:#FFFFFF;          /* el papel de una tarjeta, un modal, una tabla */
    --sup-app:#FBFAF6;      /* el fondo detrás de todo */
    --sup-sutil:#FCFBF7;    /* el hover de un renglón, zonas apenas marcadas */
    --sup-gris:#EEF0F1;
    --bor-gris:#E1E5E7;
    --txt-3:#5F7078;

    /* Texto sobre un fondo sólido de marca (botón petróleo, chip activo).
       NO se invierte: ese botón sigue siendo petróleo en oscuro, así que su
       texto sigue teniendo que ser blanco. */
    --sobre-solido:#FFFFFF;

    /*
     | TEXTO FUERTE: títulos y cifras grandes. En claro es el petróleo oscuro de
     | siempre; en oscuro se aclara. No se usa `--petroleo-osc` para esto porque
     | ése es el FONDO del sidebar y no cambia de tema: como color de texto, en
     | oscuro quedaba petróleo sobre petróleo y el título desaparecía.
    */
    --titulo:#0C333D;

    /* ── sidebar · YA ERA OSCURO, casi no se mueve ── */
    --side-hondo:#0A2B34;
    --side-hover:#134454;
    --side-linea:#16414E;
    --side-acento:#124E5C;
    --side-txt:#E8F1F4;
    /*
     | Subido de #7C99A4 (4.5:1) a #8FAAB4 (5.5:1) sobre el fondo del sidebar.
     |
     | 4.5:1 es el MÍNIMO de la norma, y aquí se estaba usando para texto de
     | 0.78rem —el nombre de la empresa, el rol— o sea el caso donde el mínimo no
     | alcanza. Se reportó como «casi no se ve», que es exactamente lo que pasa
     | cuando se toma el umbral como objetivo en lugar de como suelo.
    */
    --side-txt-2:#8FAAB4;
    --side-txt-3:#9DBAC3;
    --side-txt-4:#5D7E8B;

    /* ── estados · fondo / texto / borde ── */
    --mal-f:#FBEAEC;  --mal-t:#8A2733;  --mal-b:#F1D2D6;
    --av-f:#FDF6E4;   --av-t:#7A5A12;   --av-b:#F0DFB2;  --av-vivo:#D9A62E;
    --ok-f:#E9F4ED;   --ok-t:#1C5636;   --ok-b:#CBE5D6;  --ok-vivo:#2FBF71;
    --info-f:#E4EEF1; --info-b:#CFE2E7; --info-t:#124E5C;

    /* ── neutros crudos que quedaban sueltos ── */
    --n-negro:#000; --n-111:#111; --n-333:#333;
    --n-444:#444;   --n-666:#666; --n-999:#999;

    /*
     | ALTO REALMENTE DISPONIBLE EN PANTALLA
     |
     | `100vh` miente en el teléfono: mide la ventana con la barra del navegador
     | ESCONDIDA. Una hoja de `94vh` se sale por abajo y su pie —donde está
     | «Guardar»— queda fuera de la pantalla, y como el cuerpo del modal nunca
     | llega a desbordar, tampoco aparece scroll: el formulario simplemente no
     | se puede terminar. Ese es el bug que se estaba reportando.
     |
     | Y hay un segundo caso que NINGUNA unidad CSS resuelve, ni `dvh`: el
     | teclado en pantalla. Al enfocar un campo, el teclado tapa media pantalla
     | pero `dvh` no se enrata, así que los campos de abajo quedan detrás de él.
     |
     | Por eso el alto se resuelve en tres niveles, del peor al mejor:
     |
     |   1. `100vh`            respaldo para navegadores sin `dvh`
     |   2. `100dvh`           descuenta la barra del navegador
     |   3. `--vv-alto` (JS)   descuenta la barra Y el teclado
     |
     | `--vv-alto` y `--vv-abajo` los escribe `lactisoft.js` midiendo
     | `window.visualViewport`. Si el JS no corre quedan los respaldos y todo
     | sigue siendo usable: nunca se esconde nada que dependa del script.
    */
    --alto-util:100vh;
}

/*
|==============================================================================
| TEMA OSCURO
|==============================================================================
|
| ═══ SÓLO SE ACTIVA CON `data-theme="dark"` EXPLÍCITO ═══
|
| Y NO con `@media (prefers-color-scheme: dark)`, que era lo primero que se
| escribió aquí. La razón es concreta: esta hoja no la carga sólo el panel. La
| cargan también el acceso, el back-office de plataforma, la pantalla de cuenta
| suspendida y el retorno de pagos — seis vistas en total.
|
| Con la regla de preferencia, cualquiera con el sistema operativo en oscuro
| habría visto TODAS esas pantallas a medio oscurecer, sin interruptor para
| salir y sin que nadie las hubiera revisado. El modo oscuro se pidió para el
| panel, que es donde se trabaja horas seguidas.
|
| Así que quien decide es el panel: su script de cabecera lee lo que la persona
| eligió y, si no eligió nada, consulta la preferencia del sistema. Las demás
| pantallas nunca ponen el atributo y se quedan en claro siempre.
|
| Lo que tampoco cambia de tema: los PDF y los tickets. Van a papel blanco y a
| impresora térmica, y tienen sus propias hojas embebidas.
*/

:root[data-theme="dark"] {
    color-scheme: dark;

    /* ── superficies · invertidas, con tinte petróleo para que no sea gris muerto ── */
    --sup:#17242B;          /* tarjetas, modales, tablas */
    --sup-app:#0F1A20;      /* el fondo: MÁS hondo que las tarjetas, o no levantan */
    --sup-sutil:#1E2E36;    /* hover de renglón */
    --sup-gris:#243139;
    --bor-gris:#2C3B44;
    --papel:#17242B;
    --leche:#0F1A20;
    --linea:#2C3B44;
    --linea-2:#22303A;
    --crema:#2A2519;

    /* ── texto ── */
    --tinta:#E9EFF1;
    --tinta-2:#C4D2D8;
    --gris:#95A8AF;
    --gris-cl:#6E838C;
    --txt-3:#95A8AF;

    /*
     | LA MARCA SUBE DE LUMINOSIDAD, NO CAMBIA DE COLOR.
     |
     | `--petroleo` a #155E6E sobre una tarjeta #17242B casi no se distingue del
     | fondo: un botón sólido dejaría de leerse como botón. Sube lo justo para
     | despegarse, y el blanco encima sigue teniendo contraste de sobra.
     |
     | Pradera y rojo suben por otra razón: en claro se usan como TEXTO sobre
     | papel, y esos mismos valores sobre fondo oscuro quedan por debajo del
     | mínimo legible.
    */
    --petroleo:#1B7186;
    --petroleo-cl:#4FAAC0;
    --titulo:#E3EEF1;
    --pradera:#4FA97A;
    --rojo:#E0697A;

    /* La sombra en oscuro no puede ser una sombra clara: se nota como niebla. */
    --sombra:0 1px 2px rgba(0,0,0,.4), 0 8px 24px -12px rgba(0,0,0,.7);

    /*
     | EL SIDEBAR CASI NO SE MUEVE. Ya era oscuro en el tema claro; lo único que
     | cambia es que se hunde un poco para quedar por debajo de las tarjetas y no
     | parecer la zona iluminada de la pantalla.
    */
    --side-hondo:#071D24;
    --side-hover:#123E4C;
    --side-linea:#143A46;
    --side-acento:#11424F;

    /* ── estados · fondo apagado, texto CLARO, borde en medio ── */
    --mal-f:#3A2126;  --mal-t:#F2A7B1;  --mal-b:#5B2E36;
    --av-f:#332A11;   --av-t:#EFCE82;   --av-b:#57461C;   --av-vivo:#D9A62E;
    --ok-f:#153121;   --ok-t:#8FD9AC;   --ok-b:#25563A;   --ok-vivo:#2FBF71;
    --info-f:#152B34; --info-b:#25454F; --info-t:#8FCFDD;

    /* ── neutros crudos: los de texto se aclaran, los de borde se apagan ── */
    --n-negro:#C4D2D8; --n-111:#E9EFF1; --n-333:#D2DDE2;
    --n-444:#C4D2D8;   --n-666:#5B6C75; --n-999:#4E5D66;
}

@supports (height:100dvh){
    :root{--alto-util:100dvh}
}
*{margin:0;padding:0;box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{font-family:'Inter',system-ui,sans-serif;background:var(--leche);color:var(--tinta);line-height:1.55;font-size:15px;
     font-feature-settings:'cv05','ss01';-webkit-font-smoothing:antialiased}
a{color:inherit;text-decoration:none}
svg{flex-shrink:0}
.mono{font-family:'JetBrains Mono',ui-monospace,'SF Mono',Menlo,monospace;font-variant-ligatures:none}
.display{font-family:'Archivo',sans-serif;font-variation-settings:'wdth' 112;font-weight:800;letter-spacing:-.022em}
:focus-visible{outline:2.5px solid var(--petroleo-cl);outline-offset:2px;border-radius:4px}

/* ── Controles ── */
.campo{margin-bottom:15px}
.campo label{display:block;font-size:.815rem;font-weight:600;margin-bottom:6px;color:var(--tinta-2);letter-spacing:.005em}
.campo input,.campo select,input[type=date],input[type=datetime-local],input[type=number],input[type=text],input[type=email],input[type=password],input[type=search],input[type=tel],select{
    width:100%;padding:10px 12px;border:1.5px solid var(--linea);border-radius:9px;font-size:.94rem;font-family:inherit;
    background:var(--papel);color:var(--tinta);transition:border-color .14s,box-shadow .14s}
.campo input:focus,.campo select:focus,input:focus,select:focus{outline:none;border-color:var(--petroleo);box-shadow:0 0 0 3.5px rgba(21,94,110,.11)}
.campo input::placeholder{color:var(--gris-cl)}
/* La nota de ayuda también fuera de un `.campo` (debajo de una fila de dos campos,
   al pie de una tarjeta): ahí no tenía estilo y salía del tamaño del texto normal. */
.pista{font-size:.775rem;color:var(--gris);line-height:1.45}
.pista strong{color:var(--tinta-2)}
form > .pista{margin-bottom:15px}
.campo .pista{font-size:.775rem;color:var(--gris);margin-top:5px;line-height:1.45}
select{appearance:none;background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%235F7078'%3E%3Cpath d='M7 10l5 5 5-5z'/%3E%3C/svg%3E");
    background-repeat:no-repeat;background-position:right 8px center;background-size:18px;padding-right:30px}

.btn{display:inline-flex;align-items:center;justify-content:center;gap:7px;padding:10px 18px;border-radius:9px;font-weight:600;
     font-size:.9rem;border:none;cursor:pointer;font-family:inherit;transition:transform .12s,box-shadow .16s,background .14s;white-space:nowrap}
.btn:active{transform:translateY(1px)}
.btn-solido{background:var(--petroleo);color:var(--sobre-solido);box-shadow:0 1px 2px rgba(12,51,61,.2)}
.btn-solido:hover{background:var(--petroleo-osc);box-shadow:0 4px 14px -4px rgba(12,51,61,.4)}
.btn-linea{background:var(--papel);border:1.5px solid var(--linea);color:var(--tinta-2)}
.btn-linea:hover{border-color:var(--petroleo-cl);color:var(--petroleo)}
.btn-full{width:100%}
.btn-mini{padding:6px 12px;font-size:.8rem;border-radius:7px;gap:5px}
.btn-google{width:100%;gap:10px;background:var(--papel);border:1.5px solid var(--linea);color:var(--tinta);padding:11px}

/*
 | ── El campo de contraseña con su botón de «ver» ──
 |
 | Va en ESTA hoja y no en `acceso.css` porque lo usan las dos maquetas: las pantallas
 | de acceso y los formularios del panel (alta de usuario, reponer contraseña).
 |
 | El `padding-right` del campo es lo que impide que el texto pase por debajo del
 | botón: sin él, una contraseña larga se lee tapada por el ojo justo cuando se acaba
 | de pulsar «ver», que es el único momento en que a alguien le importa leerla.
*/
.clave{position:relative;display:block}
.clave input{padding-right:46px}
.clave-ojo{
    position:absolute;top:50%;right:6px;transform:translateY(-50%);
    display:flex;align-items:center;justify-content:center;
    width:34px;height:34px;padding:0;border:0;border-radius:8px;
    background:none;color:var(--gris);cursor:pointer;
    transition:color .14s,background .14s}
.clave-ojo:hover{color:var(--petroleo);background:var(--linea-2)}
.clave-ojo[aria-pressed="true"]{color:var(--petroleo)}
/*
 | Qué ojo se ve. Lo gobierna `aria-pressed`, que es el mismo dato que anuncia el
 | estado a un lector de pantalla: así el icono no puede decir una cosa y la etiqueta
 | otra. Antes se alternaban con el atributo `hidden` desde el JS y se veían LOS DOS,
 | porque la regla `[hidden]{display:none}` del navegador no alcanza a un <svg>.
*/
.clave-ojo .ojo-cerrado{display:none}
.clave-ojo[aria-pressed="true"] .ojo-abierto{display:none}
.clave-ojo[aria-pressed="true"] .ojo-cerrado{display:block}
/* El anillo de foco por dentro: pegado al borde del campo, uno por fuera se solapa. */
.clave-ojo:focus-visible{outline:2px solid var(--petroleo-cl);outline-offset:-2px}
.btn-google:hover{border-color:var(--gris-cl)}

.alerta{padding:11px 15px;border-radius:10px;margin-bottom:16px;font-size:.89rem;font-weight:500;display:flex;gap:9px;align-items:flex-start;border:1px solid transparent}
.alerta-ok{background:var(--ok-f);color:var(--ok-t);border-color:var(--ok-b)}
.alerta-error{background:var(--mal-f);color:var(--mal-t);border-color:var(--mal-b)}

/* ── Auth ── */
.auth-body{display:flex;align-items:center;justify-content:center;min-height:100vh;padding:26px 20px;
    background:radial-gradient(1100px 520px at 50% -8%, var(--info-f) 0%, var(--leche) 62%)}
.auth-caja{width:100%;max-width:410px}
.auth-caja.ancha{max-width:560px}
.auth-logo{text-align:center;margin-bottom:24px}
.auth-logo .marca{font-family:'Archivo',sans-serif;font-variation-settings:'wdth' 118;font-weight:900;font-size:1.65rem;color:var(--petroleo);letter-spacing:-.02em}
.auth-logo .marca span{color:var(--mantequilla)}
.auth-logo p{color:var(--gris);font-size:.9rem;margin-top:5px}
.card{background:var(--papel);border:1px solid var(--linea);border-radius:16px;padding:28px;box-shadow:var(--sombra)}
.divisor{display:flex;align-items:center;gap:12px;margin:17px 0;color:var(--gris-cl);font-size:.78rem;font-weight:500}
.divisor::before,.divisor::after{content:'';flex:1;border-top:1px solid var(--linea)}
.auth-pie{text-align:center;margin-top:17px;font-size:.88rem;color:var(--gris)}
.auth-pie a{color:var(--petroleo);font-weight:600}
.seccion-titulo{font-size:.72rem;font-weight:700;letter-spacing:.13em;text-transform:uppercase;color:var(--pradera);margin:4px 0 14px;
    display:flex;align-items:center;gap:9px}
.seccion-titulo::after{content:'';flex:1;border-top:1px solid var(--linea)}
.sub-preview{font-family:ui-monospace,monospace;font-size:.85rem;background:var(--leche);border:1.5px dashed var(--linea);
    border-radius:8px;padding:9px 12px;margin-top:6px;color:var(--gris)}
.sub-preview strong{color:var(--petroleo);font-weight:700}

/* ── Panel ── */
/*
 | ═══ EL PANEL OCUPA LA PANTALLA QUE HAY, SEA LA QUE SEA ═══
 |
 | `minmax(0,1fr)` y no `1fr` a secas: un `1fr` no baja del contenido mínimo de
 | la columna, así que una tabla ancha la estiraba y sacaba scroll horizontal a
 | la página entera. Con el mínimo en cero manda la rejilla, y lo que se pasa de
 | ancho se desplaza DENTRO de su propia caja.
 |
 | Importa más ahora que puede haber una tercera columna —el riel de Lía, ver
 | lactisoft-lia.css—: al abrirse, el centro tiene que encoger de verdad.
*/
.panel-wrap{display:grid;grid-template-columns:var(--nav-ancho,252px) minmax(0,1fr);min-height:100vh}
/* El sidebar —caja, renglones, pie y estados— vive en navegacion.css. */

/*
 | ═══ SIN `max-width`: LA PANTALLA COMPLETA ES LA MEDIDA ═══
 |
 | Tenía un tope de 1240 px heredado de una maqueta de blog. En el monitor de un
 | mostrador —1920 px es lo normal— eso dejaba casi 500 px de leche vacía a la
 | derecha mientras las tablas de inventario se partían dentro de su caja. Aquí
 | no se lee un artículo: se comparan renglones, y cada columna que cabe es una
 | columna que no hay que ir a buscar con scroll.
 |
 | El respiro lateral lo da el relleno, y es fluido: 20 px en una tablet, hasta
 | 56 px en un monitor grande. Un `clamp` en vez de tres `@media` porque la
 | pantalla no viene en tres tamaños, viene en todos.
*/
.panel-main{padding:30px clamp(20px,2.4vw,56px) 60px;width:100%;min-width:0}
.panel-main h1{font-family:'Archivo',sans-serif;font-variation-settings:'wdth' 108;font-weight:800;font-size:1.5rem;
    color:var(--titulo);margin-bottom:22px;letter-spacing:-.02em;display:flex;align-items:center;gap:11px}
.panel-main h1 svg{color:var(--petroleo-cl)}
.panel-main h2{font-size:.95rem;font-weight:700;color:var(--tinta-2);margin-bottom:11px;letter-spacing:-.005em}
.sub-nota{font-weight:400;color:var(--gris);font-size:.82rem}
.barra{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:18px}

.grid-2{display:grid;grid-template-columns:minmax(0,1fr) 350px;gap:22px;align-items:start}
/*
 | Cuatro columnas cuando caben, las que quepan cuando no.
 |
 | Era `repeat(4,1fr)` fijo, y con el riel de Lía abierto los cuatro indicadores
 | se apretaban hasta que el número —que es lo único que se mira— se partía en
 | dos renglones. Con `auto-fit` se reacomodan solos a 3, a 2 o a 1 según el
 | ancho que quede, y en un monitor grande siguen viéndose los cuatro en fila
 | porque las pistas sobrantes se colapsan.
*/
.grid-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:14px;margin-bottom:26px}
.stat{background:var(--papel);border:1px solid var(--linea);border-radius:var(--r);padding:17px 18px;box-shadow:var(--sombra)}
.stat .n{font-family:'Archivo',sans-serif;font-weight:800;font-size:1.62rem;color:var(--titulo);letter-spacing:-.03em;line-height:1.15}
.stat .l{font-size:.79rem;color:var(--gris);margin-top:3px;line-height:1.35}
.stat.acento{background:linear-gradient(160deg,var(--side-acento),var(--petroleo-osc));border-color:transparent}
.stat.acento .n{color:var(--sobre-solido)}.stat.acento .l{color:var(--side-txt-3)}

table.tabla{width:100%;border-collapse:separate;border-spacing:0;background:var(--papel);border:1px solid var(--linea);
    border-radius:var(--r);overflow:hidden;box-shadow:var(--sombra)}
.tabla th{background:var(--sup-sutil);text-align:left;padding:10px 15px;font-size:.71rem;color:var(--gris);text-transform:uppercase;
    letter-spacing:.075em;font-weight:700;border-bottom:1px solid var(--linea)}
.tabla td{padding:11px 15px;border-bottom:1px solid var(--linea-2);font-size:.9rem;vertical-align:middle}
.tabla tbody tr:last-child td{border-bottom:none}
.tabla tbody tr{transition:background .1s}
.tabla tbody tr:hover{background:var(--sup-sutil)}
.tabla .vacio{color:var(--gris-cl);font-style:italic;text-align:center;padding:28px 15px}
.num{text-align:right;font-family:ui-monospace,monospace;font-variant-numeric:tabular-nums}
/* `.tabla th` alineaba a la izquierda y ganaba: el encabezado de una columna de
   importes no quedaba encima de sus números. */
.tabla th.num{text-align:right}

/* La nota al pie de una tabla o tarjeta. Se usa en muchas vistas y no tenía
   estilo: quedaba pegada a la tabla, del tamaño del texto normal. */
.panel-main .nota{font-size:.84rem;line-height:1.55;color:var(--gris);margin:10px 2px 0;max-width:110ch}
.panel-main .nota strong{color:var(--tinta-2)}
.panel-main .nota-alerta{display:flex;gap:8px;align-items:flex-start;color:var(--av-t)}
/* Un bloque de resumen o una tabla seguidos de otra sección: aire entre las dos. */
.kpis:not(:last-child){margin-bottom:24px}
.panel-main .tabla + h2,.panel-main .nota + h2,.panel-main .kpis + h2{margin-top:30px}

.badge{display:inline-flex;align-items:center;gap:5px;font-size:.735rem;font-weight:600;padding:3.5px 10px;border-radius:99px;letter-spacing:.005em;border:1px solid transparent}
.badge-verde{background:var(--ok-f);color:var(--ok-t);border-color:var(--ok-b)}
.badge-gris{background:var(--sup-gris);color:var(--txt-3);border-color:var(--bor-gris)}
.badge-azul{background:var(--info-f);color:var(--info-t);border-color:var(--info-b)}
.badge-ambar{background:var(--av-f);color:var(--av-t);border-color:var(--av-b)}
.badge-rojo{background:var(--mal-f);color:var(--mal-t);border-color:var(--mal-b)}
.chip{font-family:ui-monospace,monospace;font-size:.8rem;font-weight:700;color:var(--petroleo);background:var(--info-f);
    padding:2.5px 8px;border-radius:6px;border:1px solid var(--info-b)}

.pill-nav{display:flex;gap:7px;flex-wrap:wrap}
.pill{padding:6px 14px;border-radius:99px;font-size:.83rem;font-weight:600;border:1.5px solid var(--linea);background:var(--papel);color:var(--gris)}
.pill:hover{border-color:var(--petroleo-cl);color:var(--petroleo)}
.pill.activo{background:var(--petroleo);border-color:var(--petroleo);color:var(--sobre-solido)}

/* ══════════════════════════════════════════════════════════════════
   Cabecera de página · título + acciones (botón "Nuevo…")
   ══════════════════════════════════════════════════════════════════ */
.pagina-cab{display:flex;justify-content:space-between;align-items:flex-start;gap:14px;flex-wrap:wrap;margin-bottom:20px}
.pagina-cab h1{margin-bottom:0}
.pagina-cab .acciones{display:flex;gap:9px;flex-wrap:wrap;align-items:center}
.pagina-cab .sub{font-size:.85rem;color:var(--gris);margin-top:3px}

/* Barra de filtros reutilizable */
.filtros{background:var(--papel);border:1px solid var(--linea);border-radius:var(--r);padding:14px 16px;margin-bottom:18px;box-shadow:var(--sombra)}
.filtros form{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;align-items:end}
.filtros .campo{margin-bottom:0}
.filtros .campo-acciones{display:flex;gap:8px;align-items:end}
/* El <form> que ES la barra (y no la trae adentro) se acomoda igual. Sin esto
   cada filtro quedaba en su propio renglón, apilado como una lista. */
form.filtros:not(.linea):not(.md-filtros){display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;align-items:end}
form.filtros:not(.linea):not(.md-filtros) > .btn{justify-self:start;min-height:42px}

/* Utilidades de visibilidad por tamaño */
.solo-movil{display:none}

/* Punto de estado (en línea / inactivo) */
.punto{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--gris-cl);flex-shrink:0}
.punto.vivo{background:var(--ok-vivo);box-shadow:0 0 0 3px rgba(47,191,113,.22)}
.punto.tibio{background:var(--mantequilla);box-shadow:0 0 0 3px rgba(232,179,60,.2)}

/* Envoltura para tablas anchas en escritorio */
.tabla-envoltura{overflow-x:auto;-webkit-overflow-scrolling:touch}

/* Lista clave/valor (detalle de ticket, ficha de dispositivo) */
.dl{display:grid;grid-template-columns:auto 1fr;gap:6px 16px;font-size:.9rem}
.dl dt{color:var(--gris);font-size:.78rem;text-transform:uppercase;letter-spacing:.05em;font-weight:700;align-self:center}
.dl dd{font-weight:500;text-align:right}

/* ══════════════════════════════════════════════════════════════════
   Modales (<dialog>) · en móvil se convierten en hoja inferior
   ══════════════════════════════════════════════════════════════════ */
dialog.modal{
    /*
     | Un SOLO valor manda el alto del diálogo y el de su caja. Antes cada uno
     | traía su propio `calc(100vh - 52px)` y bastaba con tocar uno para que la
     | caja quedara más alta que el hueco donde vive, que es cuando el pie se
     | corta. Con una variable heredada no se pueden desincronizar.
    */
    --modal-max:calc(var(--vv-alto,var(--alto-util)) - 52px);

    padding:0;border:none;background:transparent;color:inherit;
    width:min(560px,calc(100vw - 28px));max-width:none;max-height:var(--modal-max);
    margin:auto;overflow:visible}
dialog.modal.ancho{width:min(860px,calc(100vw - 28px))}
dialog.modal::backdrop{background:rgba(10,38,46,.5);backdrop-filter:blur(3px)}
dialog.modal[open]{animation:modal-entra .18s ease-out}
@keyframes modal-entra{from{opacity:0;transform:translateY(10px) scale(.985)}to{opacity:1;transform:none}}

.modal-caja{background:var(--papel);border:1px solid var(--linea);border-radius:18px;box-shadow:0 24px 60px -20px rgba(12,51,61,.5);
    display:flex;flex-direction:column;max-height:var(--modal-max);overflow:hidden}
/*
 | ═══ POR QUÉ LOS FORMULARIOS NO HACÍAN SCROLL EN EL TELÉFONO ═══
 |
 | El reparto de alto dentro de la caja, ahora dicho explícitamente: cabecera y
 | pie no se encogen, el cuerpo se queda con lo que sobre y es el único que se
 | desplaza. `min-height:0` es la línea que lo hace posible — el tamaño mínimo
 | automático de un ítem flex es el de su CONTENIDO, así que sin esa línea un
 | formulario largo se niega a encogerse.
 |
 | Y ahí estaba el bug de verdad. Cuando el modal trae `accion`, el componente
 | envuelve el cuerpo y el pie en un <form> (ver `components/modal.blade.php`):
 |
 |     .modal-caja  (flex column · overflow:hidden · max-height)
 |     ├── .modal-cab
 |     └── form                    ← bloque suelto, no repartía nada
 |         ├── .modal-cuerpo       (overflow-y:auto … pero nunca desbordaba)
 |         └── .modal-pie
 |
 | Ese <form> era un ítem flex con alto de contenido y sin permiso para
 | encogerse, así que crecía hasta lo que midiera el formulario completo. El
 | cuerpo recibía todo el alto que pedía, nunca desbordaba y por lo tanto NUNCA
 | mostraba scroll; lo que sobresalía lo recortaba el `overflow:hidden` de la
 | caja. Resultado: media captura invisible y el botón de guardar fuera de la
 | pantalla. En escritorio casi no se notaba porque el modal cabía; en un
 | teléfono un formulario SIEMPRE es más alto que la pantalla.
 |
 | Son 42 modales con `accion` en el panel, o sea casi todos.
*/
.modal-cab{flex:0 0 auto;display:flex;align-items:flex-start;gap:14px;padding:18px 20px 14px;border-bottom:1px solid var(--linea);background:var(--papel)}
.modal-cab .t{font-family:'Archivo',sans-serif;font-variation-settings:'wdth' 108;font-weight:800;font-size:1.08rem;
    color:var(--titulo);letter-spacing:-.015em;display:flex;align-items:center;gap:9px;line-height:1.3}
.modal-cab .t svg{color:var(--petroleo-cl)}
.modal-cab .s{font-size:.82rem;color:var(--gris);margin-top:4px;line-height:1.45}
.modal-cerrar{margin-left:auto;background:none;border:none;cursor:pointer;color:var(--gris);padding:6px;border-radius:8px;
    line-height:0;flex-shrink:0;min-width:38px;min-height:38px;display:inline-flex;align-items:center;justify-content:center}
.modal-cerrar:hover{background:var(--leche);color:var(--tinta)}
.modal-cuerpo{flex:1 1 auto;min-height:0;padding:18px 20px;overflow-y:auto;-webkit-overflow-scrolling:touch;
    overscroll-behavior:contain;
    /* Aire al llevar un campo enfocado a la vista: pegado al borde no se lee. */
    scroll-padding:12px 0 20px}
.modal-cuerpo>form>.campo:last-of-type{margin-bottom:0}
/* El eslabón que faltaba: el <form> también reparte alto en lugar de crecer con
   su contenido. Los <input type=hidden> de dentro (@csrf, @method, `_form`) no
   estorban: el navegador les da `display:none !important`. */
.modal-caja>form{flex:1 1 auto;min-height:0;display:flex;flex-direction:column}
.modal-pie{flex:0 0 auto;display:flex;gap:10px;justify-content:flex-end;padding:14px 20px;border-top:1px solid var(--linea);background:var(--sup-sutil)}
.modal-pie.izq{justify-content:space-between}
.modal-fila{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.modal-fila.dos-uno{grid-template-columns:2fr 1fr}
/*
 | `hidden` GANA SIEMPRE, y hace falta decirlo.
 |
 | La regla `[hidden]{display:none}` del navegador vive en su hoja de estilos, así
 | que CUALQUIER `display` escrito aquí la pisa. Con `.modal-fila{display:grid}`, un
 | `<div class="modal-fila" hidden>` se sigue viendo — y es exactamente lo que pasaba
 | con «Desde el año» en un atributo de texto: el bloque de decimales sí se escondía
 | (`.campo` no declara display) y el de años no, así que el mismo mecanismo
 | funcionaba en un sitio y en el de al lado no.
 |
 | Va aquí, global y con `!important`, porque el bug no es de esa pantalla: es de
 | cualquier elemento con clase de layout que alguien esconda con `hidden`. Arreglarlo
 | caso por caso deja la trampa puesta para el siguiente.
*/
[hidden]{display:none !important}
.modal-checks{display:grid;grid-template-columns:1fr 1fr;gap:4px 12px;margin-top:2px}
.modal-checks label{display:flex;gap:8px;align-items:center;font-size:.88rem;font-weight:500;padding:5px 0;cursor:pointer}
.modal-checks input[type=checkbox]{width:18px;height:18px;accent-color:var(--petroleo);flex-shrink:0}
/*
 | Con un modal abierto la página de atrás no se mueve.
 |
 | `overflow:hidden` a secas no sujeta a Safari en iOS: el gesto se lo queda la
 | página y el modal parece trabado. `body.trabado` —que el JS pone SOLO en
 | pantallas chicas— fija el cuerpo y guarda la posición del scroll para
 | devolverla al cerrar. En escritorio se queda con `overflow:hidden` a secas: si
 | ahí se fijara el cuerpo desaparecería la barra de scroll y la página entera
 | daría un brinco de unos 15 px al abrir cualquier modal.
*/
body.modal-abierto{overflow:hidden}
body.trabado{position:fixed;left:0;right:0;width:100%;overflow:hidden;overscroll-behavior:none}

/* ══════════════════════════════════════════════════════════════════
   Barra superior móvil + cajón de navegación
   ══════════════════════════════════════════════════════════════════ */
.topbar{display:none}
.nav-tapa{display:none}

@media (max-width:1000px){
    .panel-wrap{grid-template-columns:1fr}

    /* La barra superior y el cajón del menú: navegacion.css, debajo de 761 px. */

    .grid-2{grid-template-columns:1fr}
    .grid-stats{grid-template-columns:1fr 1fr}
    /* En horizontal la muesca se come el costado y el sidebar ya no está ahí para
       taparla: el contenido se aparta lo que haga falta, 14 px como mínimo. */
    .panel-main{padding:20px 14px calc(48px + env(safe-area-inset-bottom));
        padding-left:max(14px,env(safe-area-inset-left));
        padding-right:max(14px,env(safe-area-inset-right))}
    .panel-main h1{font-size:1.28rem}
    .pagina-cab .acciones .btn{flex:1 1 auto}
}

@media (max-width:760px){
    /* Tablas → tarjetas. Cada <td> muestra su etiqueta con data-l="…" */
    table.tabla.responsiva{display:block;border:none;background:transparent;box-shadow:none}
    .tabla.responsiva thead{display:none}
    .tabla.responsiva tbody,.tabla.responsiva tfoot{display:block}
    .tabla.responsiva tr{display:block;background:var(--papel);border:1px solid var(--linea);border-radius:12px;
        padding:8px 14px;margin-bottom:10px;box-shadow:var(--sombra)}
    .tabla.responsiva tr:hover{background:var(--papel)}
    .tabla.responsiva td{display:flex;align-items:center;justify-content:space-between;gap:14px;
        padding:7px 0;border-bottom:1px solid var(--linea-2);text-align:right}
    .tabla.responsiva tr td:last-child{border-bottom:none}
    .tabla.responsiva td::before{content:attr(data-l);flex:0 0 40%;text-align:left;font-size:.7rem;font-weight:700;
        text-transform:uppercase;letter-spacing:.06em;color:var(--gris)}
    .tabla.responsiva td.principal{font-size:1rem;font-weight:700;border-bottom:1px solid var(--linea)}
    .tabla.responsiva td[data-l=""]::before{display:none}
    .tabla.responsiva td.acciones{justify-content:flex-end;flex-wrap:wrap;gap:8px}
    .tabla.responsiva td.acciones form{display:inline-flex}
    .tabla.responsiva .vacio{display:block;text-align:center;border:none}
    .tabla.responsiva .vacio::before{display:none}

    .solo-movil{display:block}
    .solo-escritorio{display:none}

    .dl{grid-template-columns:1fr;gap:2px}
    .dl dt{margin-top:8px}
    .dl dd{text-align:left}

    /* Móvil: 16px evita el zoom automático de iOS al enfocar un campo */
    .campo input,.campo select,.campo textarea,input,select,textarea{font-size:16px;min-height:44px}
    .btn{min-height:44px}
    .btn-mini{min-height:36px}

    /*
     | Hoja inferior. El alto sale del viewport REAL (ver `--alto-util` arriba) y
     | no de `94vh`, que en el teléfono mide de más y empujaba el pie fuera de la
     | pantalla.
     |
     | `bottom:var(--vv-abajo)` es lo que la levanta por encima del teclado. Con
     | `top:0` heredado del navegador y `margin-top:auto`, el margen automático
     | se resuelve solo y la hoja queda apoyada a esa altura, así que basta con
     | mover un número desde el JS.
    */
    dialog.modal,dialog.modal.ancho{
        --modal-max:var(--vv-alto,var(--alto-util));
        width:100%;max-width:100%;margin:auto 0 0;bottom:var(--vv-abajo,0px)}
    dialog.modal[open]{animation:hoja-entra .2s ease-out}
    @keyframes hoja-entra{from{transform:translateY(14px);opacity:.6}to{transform:none;opacity:1}}
    .modal-caja{border-radius:20px 20px 0 0;border-bottom:none}
    .modal-cab::before{content:'';position:absolute;top:7px;left:50%;transform:translateX(-50%);
        width:42px;height:4px;border-radius:99px;background:var(--linea)}
    .modal-cab{position:relative;padding-top:20px}
    .modal-cerrar{min-width:44px;min-height:44px}
    .modal-cuerpo{padding:16px 16px 20px}
    /*
     | Pie en fila, no apilado.
     |
     | Dos botones a ancho completo uno encima del otro comían ~110 px de alto, y
     | con el teclado abierto ese alto se le resta al formulario, que es
     | justamente lo que no sobra. En fila cuesta la mitad y la acción principal
     | sigue quedando a la derecha, igual que en escritorio.
    */
    .modal-pie,.modal-pie.izq{flex-direction:row;flex-wrap:wrap;align-items:center;
        padding:11px 14px calc(12px + env(safe-area-inset-bottom))}
    .modal-pie>.btn{flex:1 1 auto}
    /* La acción principal pesa un poco más que «Cancelar». */
    .modal-pie>.btn-solido{flex:1.4 1 auto}
    /* Un <form> en el pie (cancelar un ticket, descartar un descuadre) se lleva
       su propio renglón: es una acción destructiva, no compite de tú a tú. */
    .modal-pie>form{flex:1 1 100%;order:-1}
    .modal-pie>form>.btn{width:100%}
    .modal-fila,.modal-fila.dos-uno,.modal-checks{grid-template-columns:1fr}
}

@media (max-width:560px){
    /* Un filtro con etiqueta de dos palabras no cabe en media pantalla de 360 px:
       `auto-fit` resolvía dos columnas y las etiquetas se partían. */
    .filtros form,form.filtros:not(.linea):not(.md-filtros){grid-template-columns:1fr}
    .filtros .campo-acciones{flex-wrap:wrap}
    .filtros .campo-acciones .btn{flex:1 1 auto}
    /* Cabecera de página: el título y su botón dejan de pelearse por el renglón. */
    .pagina-cab{flex-direction:column;align-items:stretch}
    .pagina-cab .acciones{width:100%}
    .barra{gap:10px}
}

@media (max-width:420px){
    .grid-stats{grid-template-columns:1fr}
}

/* ══════════════════════════════════════════════════════════════════
   Táctil · lo que solo aplica cuando se toca en lugar de apuntar
   ══════════════════════════════════════════════════════════════════ */

/*
 | `hover:none` acierta donde `max-width` se equivoca: un teléfono en horizontal
 | mide más de 760 px y una laptop con pantalla táctil no es un teléfono. Aquí
 | solo van cosas del dedo, no de la medida de la pantalla.
*/
@media (hover:none){
    /* El destello gris de Android al tocar, y la espera de 300 ms que algunos
       navegadores dejan para ver si viene un doble toque. */
    a,button,summary,label,.btn,.pill,.chip-filtro{-webkit-tap-highlight-color:transparent}
    .btn,.pill,.chip-filtro,summary,.modal-cerrar{touch-action:manipulation}
    /* Sin puntero no hay hover, así que el estado «encima» se queda PEGADO
       después de tocar: el botón que acabas de usar se ve distinto al resto
       hasta que toques otra cosa. Se devuelve al estado normal y el aviso de
       «te leí» pasa a `:active`, que sí termina cuando levantas el dedo. */
    .btn:hover{transform:none}
    .btn-solido:hover{background:var(--petroleo);box-shadow:0 1px 2px rgba(12,51,61,.2)}
    .btn-linea:hover{border-color:var(--linea);color:var(--tinta-2)}
    .btn-solido:active{background:var(--petroleo-osc)}
    .btn-linea:active{border-color:var(--petroleo-cl);color:var(--petroleo)}
}

/* ── Firma de versión ─────────────────────────────────────────────────────
   La usa el componente <x-version>: sidebar del panel, back-office y accesos.

   Los colores van heredados (`currentColor` con opacidad) y no fijados, porque
   el mismo componente se pinta sobre el sidebar OSCURO del panel y sobre las
   tarjetas CLARAS de los accesos. Con un color escrito a mano habría que
   mantener dos variantes, y una de las dos acabaría ilegible.

   `font-variant-numeric: tabular-nums` en el build: son ocho dígitos que alguien
   va a leer por teléfono o copiar a un reporte, y sin cifras de ancho fijo el 1
   angosta el número y se lee peor. */
.firma-version{display:flex;flex-direction:column;gap:1px;line-height:1.35;
               font-size:.7rem;letter-spacing:.01em}
.firma-version.centrado{align-items:center;text-align:center}
.fv-producto{font-weight:600;opacity:.72}
.fv-build{font-size:.66rem;opacity:.5;font-variant-numeric:tabular-nums;letter-spacing:.04em}

/*
|==============================================================================
| EL INTERRUPTOR DE TEMA
|==============================================================================
|
| Vive en el sidebar, junto a «cerrar sesión», y por eso hereda sus colores
| `--side-*` en lugar de los de la página: ahí el fondo es oscuro en los dos
| temas.
|
| Qué ícono se ve lo gobierna `aria-pressed`, que es el MISMO dato que anuncia
| el estado a un lector de pantalla. Así el ícono no puede decir una cosa y la
| etiqueta otra — el error clásico de los interruptores de tema.
|
| Y anuncia A DÓNDE va, no dónde estás: en claro se ve la luna («cámbiame a
| oscuro»), en oscuro el sol.
*/
/*
 | La caja —relleno, radio, color, hover— la pone `.nav-pie` en navegacion.css,
 | que es la que comparten los botones del pie. Aquí queda sólo lo que es propio
 | del interruptor de tema: el cambio de ícono y el arranque.
*/

/* `hidden` no alcanza a un <svg>: la regla del navegador es para bloques, así
   que el cambio se hace con display y no con el atributo. */
.tema-boton .tema-sol{display:none}
.tema-boton[aria-pressed="true"] .tema-luna{display:none}
.tema-boton[aria-pressed="true"] .tema-sol{display:inline-flex}

/*
 | Mientras el JS no haya corrido, el botón no se pinta. Dura milésimas y evita
 | que aparezca un control que todavía no responde — y que en un navegador sin
 | JS se quedaría muerto para siempre.
*/
.tema-boton:not([data-listo]){visibility:hidden}

/* ═══════════════════════════════════════════════════════════════════════════
   LÍA TRABAJANDO · animación y barra de carga de los asistentes (lia-carga.js)
   ═══════════════════════════════════════════════════════════════════════════ */
.lia-carga{background:var(--sup);border:1px solid var(--linea);border-radius:var(--r);padding:14px 16px;
    box-shadow:var(--sombra);display:grid;gap:10px;max-width:520px;transition:opacity .45s ease}
.lia-carga-cab{display:flex;gap:12px;align-items:center}
.lia-carga-textos{display:flex;flex-direction:column;gap:2px;min-width:0}
.lia-carga-textos strong{font-size:.92rem;color:var(--tinta)}
.lia-carga-etapa{font-size:.84rem;color:var(--gris)}
.lia-carga-etapa.entra{animation:lia-carga-entra .45s ease}

/* La órbita: tres puntos girando alrededor de la chispa de Lía. */
.lia-carga-orbita{position:relative;flex:0 0 38px;width:38px;height:38px;border-radius:50%;
    background:radial-gradient(circle at 50% 50%, var(--info-f) 0 58%, transparent 60%)}
.lia-carga-orbita b{position:absolute;inset:0;display:grid;place-items:center;font-size:17px;
    color:var(--mantequilla);animation:lia-carga-latido 1.6s ease-in-out infinite}
.lia-carga-orbita i{position:absolute;inset:0;animation:lia-carga-gira 1.8s linear infinite}
.lia-carga-orbita i::before{content:'';position:absolute;top:0;left:50%;width:7px;height:7px;margin-left:-3.5px;
    border-radius:50%;background:var(--petroleo-cl)}
.lia-carga-orbita i:nth-child(2){animation-duration:2.6s;animation-direction:reverse}
.lia-carga-orbita i:nth-child(2)::before{width:5px;height:5px;background:var(--pradera)}
.lia-carga-orbita i:nth-child(3){animation-duration:3.4s}
.lia-carga-orbita i:nth-child(3)::before{width:4px;height:4px;background:var(--mantequilla)}

/* Con el logo de Lía en el centro: su placa azul y sin el latido del ✦ —el
   logo ya gira y respira solo (lia-logo.css)—. */
.lia-carga-orbita:has(.lia-logo){background:radial-gradient(circle at 50% 50%, #014057 0 58%, transparent 60%)}
.lia-carga-orbita b:has(.lia-logo){animation:none}

/* La barra: el relleno avanza con JS; el brillo que la recorre dice «sigue viva». */
.lia-carga-barra{position:relative;height:8px;border-radius:99px;background:var(--linea-2);overflow:hidden}
.lia-carga-relleno{position:absolute;inset:0 auto 0 0;width:0;border-radius:99px;
    background:linear-gradient(90deg, var(--petroleo), var(--pradera));transition:width .3s ease;overflow:hidden}
.lia-carga-relleno::after{content:'';position:absolute;inset:0;
    background:linear-gradient(90deg, transparent, rgba(255,255,255,.45), transparent);
    transform:translateX(-100%);animation:lia-carga-brillo 1.4s ease-in-out infinite}
.lia-carga-pie{display:flex;justify-content:space-between;font-size:.75rem;color:var(--gris);
    font-variant-numeric:tabular-nums}
.lia-carga.lista{opacity:0}
.lia-carga.lista .lia-carga-orbita i{animation-play-state:paused}

@keyframes lia-carga-gira{to{transform:rotate(360deg)}}
@keyframes lia-carga-latido{0%,100%{transform:scale(1);opacity:.85}50%{transform:scale(1.18);opacity:1}}
@keyframes lia-carga-brillo{to{transform:translateX(100%)}}
@keyframes lia-carga-entra{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}

@media (prefers-reduced-motion: reduce){
    .lia-carga-orbita i,.lia-carga-orbita b,.lia-carga-relleno::after,.lia-carga-etapa.entra{animation:none}
}
