/* ============================================================================
   El sistema de diseño de AL3D — una sola hoja para las tres superficies.

   Aquí viven los tokens (los azules muestreados del logotipo, la rampa de neutros, la
   escala de siete tamaños de letra, los tres radios, el barro), y todo el estilo del
   cotizador. La plataforma (css/plataforma.css) y el anidador (anidador-vectores/css/
   anidador.css) añaden encima solo lo que el cotizador no tiene, y nunca redefinen un token.

   Hasta septiembre de 2026 este archivo era una COPIA GENERADA del <style> de
   cotizador.html, y había que acordarse de regenerarla. Ya no: esta es la única fuente, y
   cotizador.html la enlaza como cualquier otra página.

   Ley de la hoja: entre dos reglas con la misma especificidad gana la ÚLTIMA, y una media
   query no pesa más por ser más estrecha. La hoja va en capas —(1) estructura, (2) teléfono,
   (3) dedo, (4) barro, (5) lo que tiene que ganar por orden, (6) impresión, (7) tema
   oscuro— y una regla nueva va en la capa que le toca, no al final.
   ============================================================================ */

:root{
  /* ===================== El sistema =====================
     Antes de esto la hoja tenía 23 tamaños de letra distintos —de 9 a 30 px, en saltos de
     medio píxel—, 39 sombras y 18 degradados. Ninguno estaba mal por sí solo; el problema
     es que no eran un sistema, eran decisiones sueltas tomadas de una en una a lo largo de
     meses. Una pantalla hecha así se siente desordenada aunque cada pieza esté bien.

     Ahora hay una escala de cada cosa y todo sale de ahí. Los nombres viejos se quedan
     como alias, apuntando a los nuevos, para que las mil líneas de CSS que ya los usan
     sigan funcionando sin tocarlas.

     ----- El rediseño responsive: por qué cambia lo que hay debajo y no las mil reglas -----

     La app era de BARRO: radios de 38 px, tres capas de sombra en cada pieza, degradados de
     marca, y el lienzo teñido con dos manchas radiales. Eso se ve bien en una pantalla y se
     desarma en cinco: a 360 px un radio de 38 se come la esquina de una tarjeta que mide 90
     de alto, y catorce sombras apiladas en una lista de proyectos son catorce capas que
     pintar en un teléfono de gama media.

     La dirección nueva es HÍBRIDA —la estructura y la sobriedad de la guía THIQA con los
     azules del logotipo AL3D— y su forma es la contraria: superficie plana, un borde de 1 px,
     esquinas casi rectas (6 px la tarjeta, 4 el control, 3 la ficha), una sola sombra y solo
     donde una pieza de verdad flota, y un único botón de color por pantalla.

     Nada de eso se escribe regla por regla. Las mil líneas de abajo ya piden --card, --line,
     --muted, --r, --sh; lo que cambia es a QUÉ apuntan esos nombres. Por eso este bloque es
     el rediseño: los tokens del traspaso entran arriba como la fuente, y los nombres viejos
     se quedan colgando de ellos. Una hoja que no se toca no se puede romper. */

  /* La app es clara a propósito. Sin esto, Chrome de Android le aplica su tema oscuro
     automático —invierte las tarjetas y los grises, pero no los rellenos de marca ni
     el lienzo del escalador— y queda a medias. También deja en claro los controles
     nativos de iOS: datalist, teclado numérico, selector de archivo y autorrelleno. */
  color-scheme:light;

  /* ----- Los tokens del traspaso -----
     Los diez nombres con los que está escrito el rediseño. Van primero porque son la fuente:
     la rampa de neutros de aquí abajo sale de ellos y no al revés. */
  --fondo:#f3f4fb;                    /* el lienzo, plano */
  --sup2:#f7f8fd;                     /* la superficie hundida: un hueco dentro de una tarjeta */
  --linea:#dcdff2; --linea2:#eceef8;  /* el borde de una pieza y el renglón de dentro */
  --tinta:#1a1d33; --tinta2:#5c6184;  /* la tinta y la segunda tinta */
  --nav:#171a33; --nav2:#232744;      /* la barra lateral y su ítem encendido */
  --nav-rgb:23,26,51;                 /* el mismo, en partes, para el velo de los modales */

  /* La TERCERA tinta, y aquí hay una decisión medida que se aparta del traspaso.
     El documento la da como #8b90b8 y a la vez pone la regla —«nada con texto encima baja de
     4,5:1»—. Las dos cosas no pueden ser verdad: #8b90b8 sobre blanco da 3,10:1, y en el
     diseño lleva texto de verdad —el folio, «sin fecha», el subtítulo del encabezado, la
     leyenda del mes—. Es exactamente la trampa que esta hoja ya documenta con #6090f8.
     Así que se conserva el PAPEL —una tinta más callada que --tinta2— y se oscurece hasta
     que pueda serlo: #666d9b da 4,97:1 sobre --sup, 4,68:1 sobre --sup2 y 4,53:1 sobre
     --fondo. El tono de la muestra se queda en la rampa, en --n5, que es el escalón que no
     lleva texto: de ahí salen los filetes, los separadores y el icono de un estado vacío. */
  --tinta3:#666d9b;

  /* ----- Neutros -----
     Fríos y con un toque de lavanda, no grises puros: el lienzo tiene que ser del mismo mundo
     que las piezas. Salen del azul del logotipo desaturado, y desde el rediseño son los
     mismos números del traspaso: --n1 es --fondo, --n2 es --linea2, --n3 es --linea, --n6 es
     --tinta2 y --n8 es --tinta. Así, `color:var(--muted)` escrito hace un año pinta hoy la
     segunda tinta del diseño nuevo sin que nadie vaya a buscarlo. */
  --n0:#fbfcff; --n1:#f3f4fb; --n2:#eceef8; --n3:#dcdff2; --n4:#b9bede;
  --n5:#8b90b8; --n6:#5c6184; --n7:#3d4166; --n8:#1a1d33; --n9:#171a33;

  /* ----- El acento, sacado del logotipo -----
     Los tres azules son los que de verdad trae el archivo del logo, muestreados píxel por
     píxel: #3018f8 en el círculo oscuro, #4060f8 en el grande —el dominante— y #6090f8 en
     el chico. No son "un azul parecido": son los suyos, y por eso la app y la marca se ven
     de la misma familia. El violeta y el aguamarina se derivan del mismo tono para tener
     con qué acentuar sin salirse. */
  --a:#4060f8; --a-fuerte:#3018f8; --a-claro:#6090f8; --a-suave:#e9edff; --a-borde:#b9c5fe;
  /* Los dos que el rediseño separa y que antes eran el mismo número usado para dos cosas:
     --a-fill es el RELLENO de lo elegido y del único botón de color de la pantalla —lleva
     blanco encima, así que tiene que aguantarlo— y --a-tx es el azul cuando es TEXTO o un
     filete. En claro los dos salen de los azules del logotipo; en oscuro se separan de
     verdad, porque el que se lee como texto sobre marino y el que aguanta blanco encima ya
     no pueden ser el mismo. */
  --a-fill:#4060f8; --a-tx:#3018f8;
  --a2:#7b3ff8;            /* violeta: el mismo azul girado, para el segundo acento */
  --a3:#18b6d8;            /* aguamarina: para lo que informa sin ser acción */
  /* MEDIDO, y es el detalle que hunde a la mitad de los diseños de este estilo: con blanco
     encima, --a-claro (#6090f8) da 3,07:1 y --a3 (#18b6d8) da 2,41:1. Los dos son bonitos y
     los dos son ilegibles. Así que el azul claro y el aguamarina son DECORACIÓN —sombras,
     el lienzo, un borde, un trazo— y nunca fondo de texto. Lo que sí aguanta blanco encima
     empieza en --a: 4,95:1; --a-fuerte da 8,04:1 y --a2, 5,37:1. */
  /* Era un degradado y ahora es un color. En una superficie grande el degradado es justo lo
     que hace que una pieza se vea de hace diez años, y la dirección nueva no tiene ninguno:
     el nombre se queda para las veinte reglas que ya lo piden. */
  --grd-deco:var(--a-fill);

  /* ----- Estados ----- vivos, no apagados; medidos contra su relleno. */
  --ok:#0a7d4a; --ok-bg:#e2f8ec; --ok-borde:#a9e8c6;
  /* El verde tiene la misma separación que el azul: --ok es TINTA —el que se lee sobre una
     superficie clara— y --ok-fill es RELLENO —el que aguanta texto blanco encima—. De día
     coinciden (blanco sobre #0a7d4a da 5,21:1); de noche --ok sube a #6fd6a4 para poder ser
     tinta y con blanco encima daría 1,78:1, así que el relleno se queda oscuro. Es la trampa
     que --a y --a-fill ya documentan, y `.btn-ok` estaba cayendo en ella. */
  --ok-fill:#0a7d4a;
  --av:#8a5100; --av-bg:#fff2dd; --av-borde:#ffd79c;
  --mal:#c62828; --mal-bg:#ffeceb; --mal-borde:#ffc4c1;

  /* ----- Tipografía ----- siete pasos, y dos familias.
     El traspaso lista dieciséis tamaños —de 10,5 a 28 px—. Dieciséis no es una escala: es la
     lista de lo que salió al maquetar, y adoptarla tal cual sería deshacer justo la auditoría
     que dejó siete. Así que se conservan SIETE y se retunean a los pasos que el diseño de
     verdad usa: 11 rótulo, 12,5 secundario, 14 cuerpo, 15 título de tarjeta y campo, 20
     título de pantalla, 24 la cifra de una estación, 28 el total y las cuentas del tablero.
     Los intermedios del documento (10,5 · 11,5 · 13 · 13,5 · 14,5 · 17 · 18) caen al escalón
     más cercano, que es la regla que esta hoja ya se dio.

     Y las familias pasan a ser dos, como manda el traspaso: Outfit 600 para lo que se cuenta
     —títulos, cifras, folios, el número de un paso— y Figtree para todo lo demás. Outfit
     tiene las cifras más estrechas y más verticales, y una columna de importes escrita así se
     lee de un barrido; Figtree es más ancha de ojo que Inter en tamaños chicos, que es donde
     vive el 80 % de esta app. */
  --t1:11px; --t2:12.5px; --t3:14px; --t4:15px; --t5:20px; --t6:24px; --t7:28px;
  --f-texto:'Figtree','Segoe UI',Roboto,Helvetica,Arial,'Apple Color Emoji','Segoe UI Emoji','Noto Color Emoji','Apple Symbols','Segoe UI Symbol','Noto Sans Symbols 2',sans-serif;
  --f-cifra:'Outfit','Figtree','Segoe UI',Roboto,Helvetica,Arial,sans-serif;

  /* ----- Espacio ----- múltiplos de 4. */
  --e1:4px; --e2:8px; --e3:12px; --e4:16px; --e5:24px; --e6:32px; --e7:48px;

  /* ----- Iconos ----- cuatro tamaños, y de aquí salen todos.
     Faltaba la escala y se notaba. `.svgi` mide 1em, así que hasta ahora el tamaño del
     icono lo decidía por accidente el font-size de quien lo tuviera dentro: medido en una
     sola pantalla de la plataforma había iconos de 12,5, 13,3, 14, 16 y 32 px a la vez.
     El de 12,5 vivía dentro de un botón de 44 px de alto —un glifo perdido en el centro de
     una pieza grande— y el de 32 estaba en un botón azul al lado de otros de 14. Ninguno
     de esos cinco números lo eligió nadie: salieron de la letra de la etiqueta.

     Que un icono siga a su texto ESTÁ BIEN cuando el icono va dentro de una frase o de un
     título: ahí crece y encoge con ella y eso es lo que se quiere. Deja de estar bien en
     cuanto el icono es la pieza y no el adorno —una pestaña, un botón de solo icono, el
     signo de un estado vacío—, porque entonces su tamaño tiene que salir de la CAJA que lo
     contiene, no de una etiqueta que a lo mejor ni existe. Estos cuatro son para ese caso;
     el resto se queda en 1em a propósito. */
  --ico1:16px;   /* dentro de un renglón: la ficha de un dato, un aviso, un chip */
  --ico2:18px;   /* la pieza es el icono: pestaña, botón de solo icono, paso del calendario */
  --ico3:20px;   /* acción grande: los botones de 46-58 px de alto y los encabezados de panel */
  --ico4:32px;   /* estado vacío: aquí el icono es la ilustración, no una etiqueta */

  /* ----- Radios -----
     Casi rectos. Eran 16 · 22 · 30 · 38 px, que es lo que hacía que una superficie se leyera
     como una pieza de barro; el rediseño quiere lo contrario —estructura, no blandura— y
     además había una razón dura para bajarlos: en un teléfono de 360 px una tarjeta de
     lista mide 90 px de alto, y un radio de 38 se come sus cuatro esquinas hasta dejarla con
     forma de pastilla. Tres pasos y ya: la ficha, el control, la tarjeta.
     El cuarto se queda apuntando al tercero porque hay ciento y pico de reglas que lo piden;
     lo que ya no hay es una cuarta forma. */
  --rr1:3px; --rr2:4px; --rr3:6px; --rr4:6px;

  /* ===================== La sombra, una sola =====================
     Aquí vivía la receta del barro: tres capas por pieza —luz interior, sombra interior,
     sombra exterior teñida— repartidas en cuatro variantes. La dirección nueva pone la
     jerarquía en el BORDE y en la superficie, no en la profundidad, así que la sombra deja de
     ser la forma de las cosas y pasa a significar una sola cosa: esta pieza flota de verdad
     por encima de las demás. La llevan las tarjetas del tablero de proyectos y los controles
     que van sueltos sobre el mapa. Nada más.

     Los cuatro nombres del barro siguen existiendo porque los piden unas doscientas reglas, y
     cada uno cae donde le toca: `--clay` es la sombra, `--clay-alto` la del panel que se abre
     encima de todo, y los dos hundidos se apagan —lo hundido ahora se dice con un fondo
     --sup2 y un borde, que es lo que hace el diseño—. */
  --sombra:0 1px 2px rgba(35,39,68,.06),0 8px 24px -12px rgba(48,24,248,.18);
  --sombra-alta:0 2px 6px rgba(35,39,68,.08),0 24px 48px -16px rgba(48,24,248,.28);
  --clay:var(--sombra);
  --clay-alto:var(--sombra-alta);
  --clay-a:var(--sombra);
  --clay-in:none;
  --clay-in-pc:none;

  /* ===================== Los seis matices de partida =====================
     El problema que resuelven: seis partidas seguidas eran seis rectángulos blancos
     idénticos, y dentro de cada una los chips, los campos y los grupos también eran
     blancos. Al abrir la tercera no había nada que dijera «esta es la tercera» ni dónde
     terminaba ella y empezaba lo que lleva dentro. Se contaban los renglones.

     Ahora cada partida trae un matiz propio y ese matiz tiñe TODO lo suyo: el número, el
     lomo de la izquierda, la banda del encabezado, su sombra, y —esto es lo que de verdad
     ata las cosas— los chips que están elegidos DENTRO de ella. Lo que se eligió en la
     partida 3 se ve del color de la partida 3.

     Tres decisiones que no son de gusto:

     · Solo la mitad fría del círculo, de cian a magenta. El verde, el ámbar y el rojo ya
       significan algo en esta app —autorizado, falta, error— y un matiz de partida que
       cayera ahí convertiría «la partida 4» en «la partida con problema».

     · El orden NO es el del arcoíris. Puestos en orden de tono, dos partidas vecinas se
       parecerían; puestos así, entre una y la siguiente hay como mínimo 47° de tono y casi
       siempre más de 70°. Lo que importa no es que la paleta se vea bonita en una fila de
       muestras: es que la 2 no se confunda con la 3.

     · El color NUNCA va solo. El número, la ficha del tipo y la descripción siguen
       distinguiendo las partidas sin él, porque hay quien no ve estos seis tonos como seis
       cosas distintas —y porque en papel no hay color.

     MEDIDO, uno por uno, con la fórmula de contraste de la WCAG: cada tinta da entre 6,5:1
     y 8:1 sobre blanco y no baja de 5,7:1 sobre su propio relleno tenue, que es donde de
     verdad se lee (el chip elegido es tinta sobre relleno). El tono medio, que es el que
     entra en los degradados y lleva blanco encima, da 4,59:1 o más. Nada de esto se puede
     cambiar «un poco» sin volver a medirlo. */
  /* ----- Y por qué los seis son ahora uno -----
     Todo lo de arriba sigue siendo cierto sobre el problema. Lo que cambió es la respuesta,
     y la cambia el rediseño con una frase: «el azul solo significa ELEGIDO». Con seis matices
     encima, un chip relleno de ciruela no dice «elegido»: dice «partida 4», y el estado —lo
     único que hay que leer a toda prisa mientras se captura delante del cliente— se cuenta
     con un color distinto en cada renglón de la cotización.

     Y la partida rediseñada resuelve mejor la pregunta original. «Dónde termina esta y empieza
     la otra» ya no lo contesta un tinte: lo contesta el RESUMEN FIJO, que se queda pegado
     arriba mientras se hace scroll dentro de la partida y enseña su número, su descripción,
     su total y las fichas de lo que lleva elegido. Eso dice más que un matiz, y lo dice
     también en papel y también para quien no distingue los seis tonos.

     Los treinta nombres se quedan —los piden unas doscientas reglas de esta hoja— y los seis
     apuntan al mismo azul. Volver a tener seis matices es volver a escribir seis renglones. */
  --pc-1:#3018f8; --pc-1-md:#4060f8; --pc-1-bd:#b9c5fe; --pc-1-sv:#e9edff; --pc-1-rgb:64,96,248;
  --pc-2:#3018f8; --pc-2-md:#4060f8; --pc-2-bd:#b9c5fe; --pc-2-sv:#e9edff; --pc-2-rgb:64,96,248;
  --pc-3:#3018f8; --pc-3-md:#4060f8; --pc-3-bd:#b9c5fe; --pc-3-sv:#e9edff; --pc-3-rgb:64,96,248;
  --pc-4:#3018f8; --pc-4-md:#4060f8; --pc-4-bd:#b9c5fe; --pc-4-sv:#e9edff; --pc-4-rgb:64,96,248;
  --pc-5:#3018f8; --pc-5-md:#4060f8; --pc-5-bd:#b9c5fe; --pc-5-sv:#e9edff; --pc-5-rgb:64,96,248;
  --pc-6:#3018f8; --pc-6-md:#4060f8; --pc-6-bd:#b9c5fe; --pc-6-sv:#e9edff; --pc-6-rgb:64,96,248;
  /* El matiz por omisión es el de la marca. Existe para que nada de lo que use --pc se
     rompa fuera de una partida: en CSS, un rgba(var(--x),.1) con --x sin definir no cae a
     un color por defecto, tira la declaración entera y la superficie se queda sin fondo.
     Con esto, el bloque de opciones y el hueco teñido se pueden reusar en cualquier sitio
     y salen azules, que es lo correcto donde no hay partida a la que pertenecer. */
  /* El triplete de --a, en un solo sitio. Vivía aquí como número suelto y otras 24 veces
     escrito a mano como rgba(var(--a-rgb),...), que además NO es --a (#4060f8) sino un cuarto azul
     que no está en ningún token: el sistema tenía un color de marca declarado y otro pintado. */
  --a-rgb:64,96,248;
  /* ----- Superficie, luz y tinta -----
     Tres tokens que antes eran «#fff» y «rgba(255,255,255,…)» repetidos 130 veces: la
     SUPERFICIE de una tarjeta, la LUZ del barro (el brillo de arriba de cada pieza) y la
     TINTA de las sombras. Son tres cosas distintas que en claro casualmente valen blanco,
     blanco y azul-marino; en oscuro no, y por eso tienen nombre. */
  --sup:#ffffff; --sup-rgb:255,255,255;
  --luz-rgb:255,255,255;
  --tinta-rgb:35,39,68;
  --n1-rgb:243,244,251; --n2-rgb:236,238,248; --n3-rgb:220,223,242; --n4-rgb:185,190,222; --n5-rgb:139,144,184;
  --af-rgb:48,24,248; --ac-rgb:96,144,248; --a2-rgb:123,63,248; --a3-rgb:24,182,216;
  --ok-rgb:21,160,106; --av-rgb:200,140,20; --av-borde-rgb:255,215,156; --mal-rgb:216,69,63;
  --a-suave-2:#dfe6ff; --a2-suave:#f1ecfd;
  /* El azul del traspaso para el chip elegido en oscuro necesita su propio par; en claro los
     dos coinciden con --a-fill y con blanco encima. */
  --a-fill-tx:#ffffff;
  --a3-texto:#0b6e85;                 /* el aguamarina, oscurecido hasta poder ser texto */
  --wa:#0f7a6c; --wa-rgb:18,140,126;  /* el verde de WhatsApp, medido sobre blanco */

  --pc:var(--a-fuerte); --pc-md:var(--a); --pc-bd:var(--a-borde); --pc-sv:var(--a-suave); --pc-rgb:var(--a-rgb);

  /* ----- Movimiento -----
     Una curva, y sale del rediseño: `cubic-bezier(.2,.8,.2,1)`, que arranca rápido y frena
     largo. Eran tres, y dos de ellas rebotaban —`.34,1.56,.64,1` se pasa de largo y vuelve—
     porque el barro es blando y tiene que ceder. Sobre una pieza plana con borde, el rebote
     se lee como un fallo de pintado: la caja se sale de su sitio y vuelve, y el borde delata
     los dos píxeles. Los tres nombres se quedan, y lo que cambia es la duración: la entrada
     de una pantalla dura .32 s, un cambio de estado .2 y un color .16.
     --mv-t es la de la transición de elemento compartido, que es más larga a propósito: el
     total recorre media pantalla y en .3 s ese viaje no se sigue con la vista. */
  --mv:.32s cubic-bezier(.2,.8,.2,1);
  --mv-r:.2s cubic-bezier(.2,.8,.2,1);
  --mv-s:.16s cubic-bezier(.2,.8,.2,1);
  --mv-t:.5s cubic-bezier(.2,.8,.2,1);

  /* ----- Alias de los nombres viejos -----
     Esta lista ES el rediseño, para las mil líneas de abajo: cada nombre viejo cuelga del
     token nuevo que le toca, y una regla escrita hace un año pinta hoy la dirección nueva. */
  --bg:var(--fondo); --card:var(--sup); --ink:var(--tinta); --fg:var(--tinta); --muted:var(--tinta2); --line:var(--linea);
  --brand:var(--a); --brand-2:var(--a); --brand-strong:var(--a-fuerte); --navy:var(--nav);
  --soft:var(--sup2); --soft-2:var(--linea2);
  --green:var(--ok); --green-ico:#15a06a; --green-bg:var(--ok-bg);
  --amber:var(--av); --amber-ico:#c1830f; --amber-bg:var(--av-bg);
  --red:var(--mal); --red-bg:var(--mal-bg); --gray:var(--n6); --gray-bg:var(--n2);
  --sc-guide:#0093ad;
  --r:var(--rr4); --r-sm:var(--rr2); --r-xs:var(--rr1); --r-lg:var(--rr4);
  --sh:var(--sombra); --sh-sm:var(--sombra);
  --sh1:var(--sombra); --sh2:var(--sombra-alta);
  /* El degradado de marca deja de ser degradado del todo. Ya venía diciéndolo —«en una
     superficie grande el degradado es justo lo que hace que un botón se vea de hace diez
     años»— y se quedaba a medias, con un degradado de --a a --a-fuerte. Ahora es el relleno
     plano de lo elegido, del botón de color y del interruptor encendido. */
  --brand-grd:var(--a-fill);
}
*{box-sizing:border-box;margin:0;padding:0}
/* ----- `hidden` tiene que ganar -----
   La regla del navegador es `[hidden]{display:none}`, y CUALQUIER regla de autor que ponga
   `display` le gana, porque una clase pesa más que un selector de tipo. O sea que
   `el.hidden = true` sobre algo con `display:flex` en la hoja no esconde nada.
   Costó dos veces en este rediseño —el total chiquito de la barra de pasos se quedaba puesto
   durante el paso 2, y el botón de «Continuar a partidas» se quedaba flotando encima de las
   partidas ya abiertas— y ya había costado una tercera en la plataforma, donde
   css/plataforma.css lleva esta misma regla escrita desde entonces. Aquí vale para las tres
   superficies, y así no hay una cuarta. */
[hidden]{display:none!important}
::-webkit-scrollbar{width:6px;height:6px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:rgba(var(--n5-rgb),.22);border-radius:4px}
::-webkit-scrollbar-thumb:hover{background:rgba(var(--a-rgb),.32)}
body{
  /* Las fuentes de emoji van nombradas y antes del genérico: los pocos emoji que
     quedan (los de las referencias rápidas, los avisos emergentes) salen del mismo
     sitio en los dos sistemas en vez de depender del último recurso del navegador. */
  /* Las de símbolos van después de las de emoji y antes del genérico: los pocos
     glifos que siguen siendo texto (▾ ▸ ▴ de los plegados, ↺ de los avisos, → de los
     botones que se reescriben por JS) no están en el subconjunto latin de Inter y los
     resolvía el último recurso del navegador —Apple Symbols en iOS, Noto Sans Symbols
     en Chrome—, cada uno con otro grosor y otra línea base. Nombradas, salen del mismo
     sitio en los dos sistemas. */
  font-family:var(--f-texto);
  /* El lienzo es PLANO. Aquí vivían dos manchas radiales del acento, fijas al viewport, que
     eran la mitad de lo que hacía que la app se leyera como barro. Con la dirección nueva
     estorban por dos motivos: tiñen el fondo de la barra lateral y de las tarjetas cuando se
     translucen, y en el teléfono el `background-attachment:fixed` obliga a repintar el fondo
     entero en cada scroll. */
  background:var(--fondo);
  color:var(--ink);line-height:1.45;font-size:var(--t3);
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
}
/* Las cifras siempre tabulares y con la letra de las cifras: una columna de importes donde el
   4 y el 1 miden distinto no se lee de un barrido, se lee número por número. */
h1,h2,h3,.brand .t,.cifra{font-family:var(--f-cifra);letter-spacing:-.1px}
.cifra,.folio,[data-shared="total"]{font-variant-numeric:tabular-nums}
body::before{
  content:'';position:fixed;top:env(safe-area-inset-top,0px);left:0;right:0;height:3px;
  /* El filete es lo único de la marca que se ve SIEMPRE, en las dos apps. Deja de ser un
     degradado por lo mismo que los demás, y deja de existir donde hay barra lateral: allí la
     marca es la barra, y un filete azul cruzando por encima de ella la corta en dos. */
  background:var(--a);
  z-index:200;
}

/* ---------- Topbar ----------
   La barra del cotizador SUELTO. Dentro de la plataforma este documento va empotrado y quien
   manda es el encabezado de allá; aquí es lo único que dice de qué app se trata y qué se
   puede hacer sin bajar a la pantalla.

   Se alinea con el encabezado del rediseño —el de la plataforma, `.pf-cab`—: 64 px de alto,
   blanco con un borde abajo, el título a la izquierda con su línea al lado, y a la derecha
   las acciones como controles de 36 px con borde. Antes eran píldoras de 10 px de radio con
   la letra en azul y en negrita 700: cuatro botones azules seguidos, que en una barra donde
   nada es LA acción es cuatro veces el color que en esta app significa «esto es la acción».
   Ahora el azul de esa barra queda para una sola cosa: el enlace a la plataforma. */
.topbar{background:var(--sup);backdrop-filter:none;-webkit-backdrop-filter:none;
  border-bottom:1px solid var(--linea);position:sticky;top:3px;z-index:30}
.topbar-in{max-width:1240px;margin:0 auto;display:flex;align-items:center;justify-content:space-between;gap:var(--e3);flex-wrap:wrap;
  min-height:64px;
  padding:max(10px,env(safe-area-inset-top,0px)) max(var(--e5),env(safe-area-inset-right,0px)) 10px max(var(--e5),env(safe-area-inset-left,0px))}
.brand{display:flex;align-items:center;gap:12px}
/* El logotipo es lo que dispara el selector de archivos; antes el onclick vivía en .brand y en
   la portada del Fold 6 eso era el renglón entero.
   Aquí vivían además .logoslot, .lg-al y .lg-3d: la ranura punteada con el «AL 3D» escrito a
   mano que se veía mientras no hubiera logotipo. Se fueron con ella —ahora la marca es
   logo-al3d.svg desde el primer píxel pintado— y con ellas el salto de la barra al arrancar,
   que venía de que la ranura medía 49 px de alto y lo que la sustituía 44. */
.logobtn{display:flex;align-items:center;min-height:44px;border:none;background:none;padding:0;margin:0;border-radius:10px;font-family:inherit;cursor:pointer;flex-shrink:0}
.logoimg{height:38px;width:auto;display:block;max-width:200px;object-fit:contain}
/* El título de la app, a la medida del encabezado de la plataforma: 20 px con la letra de las
   cifras. Y su línea al LADO, no debajo: debajo obligaba a que la barra midiera dos renglones
   de texto y la subtitulaba como si fuera un dato; al lado es lo que es, una aclaración de
   qué app es ésta, y cabe en los 64 px. En el teléfono se cae debajo por falta de ancho, que
   es donde tener dos renglones sí se paga. */
.brand .t{font-family:var(--f-cifra);font-size:var(--t5);font-weight:600;letter-spacing:-.1px;
  display:flex;align-items:baseline;gap:var(--e2);flex-wrap:wrap;line-height:1.2}
.brand .t small{font-family:var(--f-texto);font-size:var(--t2);font-weight:400;color:var(--tinta3);letter-spacing:0}
/* MEDIDO: entre 561 y 594 px la página entera se desplazaba de lado. `.topbar-in` sí
   envuelve, así que este bloque se bajaba de renglón completo — pero él no envolvía, y sus
   seis hijos (deshacer, Clientes, Historial, Plataforma, folio y el selector de rol) miden
   572 px en una banda donde el contenedor da 513. De 595 px para arriba caben y de 560 para
   abajo manda `display:contents`, que los reparte a mano; los 34 anchos de en medio se
   quedaron sin nadie que los acomodara. Envolviendo, se parten en dos renglones y se pegan a
   la derecha, que es de donde cuelga esta barra. */
.rolewrap{display:flex;align-items:center;justify-content:flex-end;flex-wrap:wrap;gap:10px}
.folio{font-size:var(--t2);color:var(--n6);font-weight:500;background:var(--n1);padding:6px 12px;border-radius:var(--rr1);border:1px solid var(--n2);font-variant-numeric:tabular-nums}
/* Folio aún no confirmado: no cuenta todavía en el contador de cotizaciones */
#folio.prov{color:var(--muted);background:var(--soft);border-color:var(--line);border-style:dashed}
/* Y la condición que no puede pasar callada: este teléfono ya no está guardando. Rojo, no
   ámbar: el ámbar de esta app significa «falta un dato», y aquí no falta nada, se está
   perdiendo. Gana sobre `.prov`, que va antes. */
#folio.nosave{color:var(--mal);background:var(--mal-bg);border-color:var(--mal-borde);border-style:solid}
.folio-mal{font-weight:700;text-transform:uppercase;font-size:9.5px;letter-spacing:.4px;margin-left:2px}
.seg{display:inline-flex;background:var(--n1);border:1px solid var(--n2);border-radius:var(--rr1);padding:3px;gap:2px}
.seg button{border:none;background:none;min-height:44px;padding:7px 14px;font-size:var(--t2);font-weight:500;color:var(--n6);border-radius:6px;cursor:pointer;transition:background .12s,color .12s}
.seg button.on{background:var(--sup);color:var(--n8);font-weight:600;box-shadow:0 1px 2px rgba(var(--tinta-rgb),.07)}

/* ===================== Iconos =====================
   Un icono mide 1 em —el alto de la letra que lleva al lado— y se pinta con el color
   del texto, así que sigue al botón cuando cambia de estado sin reglas aparte.
   pointer-events:none para que el toque siempre lo reciba el botón y no el trazo. */
.svgi{width:1em;height:1em;flex:0 0 auto;vertical-align:-.135em;pointer-events:none;
  fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}
/* Los emoji que sí siguen siendo emoji porque dibujan una cosa del mundo —una puerta,
   una persona, el tono de la luz— y un trazo monocromo no lo diría igual. Se les fija
   la fuente y el tamaño para que no crezcan más que el texto. */
.emo{font-family:'Apple Color Emoji','Segoe UI Emoji','Noto Color Emoji',sans-serif;
  font-size:.95em;line-height:1;font-style:normal;font-weight:400;vertical-align:-.05em}


/* ===================== Precios difuminados en borrador =====================
   Mientras la cotización es un borrador, los importes salen difuminados: se captura
   delante del cliente y el precio no tiene por qué leerse desde el otro lado de la
   mesa antes de estar autorizado. Se espían manteniéndolos tocados, y se destapan
   solos al solicitar autorización —de ahí en adelante el precio ya es un dato firme.

   Se difuminan los importes, no las tarifas de los chips de material: esas son el
   catálogo con el que se captura, no el precio del trabajo.

   El filtro va sobre el texto y no sobre un rectángulo encima, así que la caja no
   cambia de tamaño y nada se mueve de sitio al destaparse. */
body.precios-ocultos .lt,
body.precios-ocultos #s-sub,
body.precios-ocultos #s-iva,
body.precios-ocultos #s-neto,
body.precios-ocultos #s-calc,
body.precios-ocultos #s-anti-rest,
body.precios-ocultos .mbar-amt,
body.precios-ocultos .anti .inp-money,
/* El precio unitario de una partida manual y la tarifa a mano de una caja de luz son
   precio de ESTE trabajo, no del catálogo. Plegada la partida sí se tapaban (van marcados
   como .ptok.dinero), pero el input de donde salió el número, unos centímetros más arriba,
   los enseñaba en claro. */
body.precios-ocultos .partida .inp-money,
body.precios-ocultos .formula .dinero,
/* Dos fichas de la cara plegada llevan precio de este trabajo y no del catálogo: la
   tarifa personalizada de una caja de luz y el precio unitario de una partida manual.
   Se escapaban del difuminado, y plegada esa ficha es la superficie visible del
   borrador —justo lo que no se lee desde el otro lado de la mesa—. */
body.precios-ocultos .ptok.dinero{
  filter:blur(7px);
  transition:filter .16s;
  user-select:none;-webkit-user-select:none;
  cursor:pointer;
}
/* Espiando: se sueltan todos a la vez, no de uno en uno */
body.precios-ocultos.precios-a-la-vista .lt,
body.precios-ocultos.precios-a-la-vista #s-sub,
body.precios-ocultos.precios-a-la-vista #s-iva,
body.precios-ocultos.precios-a-la-vista #s-neto,
body.precios-ocultos.precios-a-la-vista #s-calc,
body.precios-ocultos.precios-a-la-vista #s-anti-rest,
body.precios-ocultos.precios-a-la-vista .mbar-amt,
body.precios-ocultos.precios-a-la-vista .anti .inp-money,
body.precios-ocultos.precios-a-la-vista .partida .inp-money,
body.precios-ocultos.precios-a-la-vista .formula .dinero,
body.precios-ocultos.precios-a-la-vista .ptok.dinero{filter:none}
/* Al escribir un importe hay que ver lo que se escribe */
body.precios-ocultos .anti .inp-money:focus-within,
body.precios-ocultos .partida .inp-money:focus-within{filter:none}
/* Quien las pidió sin animación no las tiene */
@media(prefers-reduced-motion:reduce){
  body.precios-ocultos .lt,body.precios-ocultos #s-sub,body.precios-ocultos #s-neto{transition:none}
}
.precios-ver{flex-shrink:0;margin-left:auto;border:1px solid var(--line);background:transparent;
  color:inherit;font-family:inherit;font-size:11.5px;font-weight:700;padding:4px 10px;border-radius:7px;cursor:pointer}
.precios-ver:hover{background:rgba(var(--sup-rgb),.5)}
/* Un Ctrl+P sobre el borrador salía con todos los importes borrosos: el difuminado existe
   para que el precio no se lea desde el otro lado de la mesa, no para inutilizar la
   impresión. El @media print de más abajo ya revierte el plegado; esto revierte el blur. */
@media print{
  /* Carta vertical, que es el papel de México y de Estados Unidos. Sin esto, un Ctrl+P sobre la
     app salía en A4 en cualquier configuración regional que no sea una de esas dos, y la maqueta
     se recortaba por la derecha. Solo «size»: el «margin:0» que sí lleva el documento que se
     genera es correcto allí —dibuja su propio margen— y aquí dejaría el contenido pegado al
     borde no imprimible del papel. */
  @page{size:letter portrait}
  body.precios-ocultos *{filter:none!important}
  /* La barra fija de abajo es de la maqueta táctil y al imprimir salía encima de la hoja,
     con el hueco que se le reserva al pie de la página. */
  .mbar{display:none!important}
  .topbar{position:static!important}
  .wrap{padding-bottom:0!important}
}
/* El aviso de que se pueden espiar. Solo mientras están tapados. */
.precios-nota{display:none;font-size:11px;color:var(--muted);line-height:1.45;
  padding:0 20px 12px;align-items:center;gap:6px}
body.precios-ocultos .precios-nota{display:flex}
.precios-nota .svgi{flex-shrink:0;color:var(--brand)}

/* ---------- Layout ---------- */
.wrap{max-width:1240px;margin:0 auto;display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:16px;align-items:start;
  padding:26px max(24px,env(safe-area-inset-right,0px)) 70px max(24px,env(safe-area-inset-left,0px))}
/* Las dos columnas pueden encogerse por debajo de su contenido: sin esto, cualquier
   texto largo que no quepa —un nombre de cliente, una fórmula— ensancha la rejilla y
   la página entera se desplaza a lo ancho en el teléfono. */
.wrap>main,.wrap>aside{min-width:0}
@media(max-width:759px){.wrap{grid-template-columns:minmax(0,1fr)}}
/* La banda del Fold abierto —880 px— conserva las dos columnas y la del dinero baja a 272 px,
   que es lo que pide el rediseño para ese ancho: con 320 px, la columna de las partidas se
   queda en 500 y la rejilla de materiales pasa de tres opciones por fila a dos.
   La regla de abajo es la de siempre para cuando SÍ se cae a una columna: la del dinero se
   queda en su ancho y pegada a la derecha en vez de estirarse a 850 px y dejar 610 entre
   «Subtotal» y su cifra. El «screen and» deja el papel fuera, que imprime a una columna. */
@media screen and (min-width:760px) and (max-width:920px){
  .wrap{grid-template-columns:minmax(0,1fr) 272px}
}
@media screen and (min-width:561px) and (max-width:759px){
  .wrap>aside{width:100%;max-width:320px;margin-left:auto}
}

/* ----- Las dos pantallas -----
   La pantalla 1 es una columna sola y estrecha: son cinco campos, y estirarlos a 1 180 px
   los deja nadando y obliga a barrer la vista de un lado a otro para leer una etiqueta y su
   campo. La 2 recupera las dos columnas, porque ahí el resumen de la derecha se lee CONTRA
   las partidas de la izquierda y separarlos costaría un desplazamiento por cada cambio. */
/* 560 px y no 660: son cinco campos y una nota, y el rediseño los quiere en una columna que
   se lea sin barrer la vista de un lado a otro. A 660 px, «Cliente» y «Teléfono» en dos
   columnas dan campos de 320 px para escribir un nombre y un teléfono. */
.wrap.p-cliente{grid-template-columns:minmax(0,560px);justify-content:center}
.pasos{grid-column:1/-1;display:flex;align-items:stretch;gap:4px;margin-bottom:2px}
.paso-tab{display:flex;align-items:center;gap:9px;min-height:44px;padding:9px 15px 9px 11px;border:1px solid transparent;border-radius:var(--r-sm);
  background:rgba(var(--sup-rgb),.7);cursor:pointer;text-align:left;color:var(--muted);font-family:inherit;transition:.15s;min-width:0}
.paso-tab .tx{display:flex;flex-direction:column;min-width:0;font-size:var(--t2);font-weight:550;line-height:1.25}
/* El nombre del cliente debajo del paso 1: es el único dato de la pantalla que se acaba de
   dejar atrás y que hace falta no perder de vista mientras se captura la otra. Nunca
   envuelve —se recorta— para que la barra no crezca de alto. */
.paso-tab .tx small{font-size:var(--t1);font-weight:400;color:var(--n6);margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:22ch}
.paso-tab .n{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;flex-shrink:0;border-radius:7px;
  background:var(--n2);color:var(--n6);font-size:var(--t2);font-weight:600}
.paso-tab:hover{background:var(--sup);border-color:var(--line)}
.paso-tab.on{background:var(--sup);border-color:var(--n3);color:var(--n8)}
.paso-tab.on .n{background:var(--a);color:#fff}
.paso-tab.hecho .n{background:var(--ok-bg);color:var(--ok)}
.paso-tab.hecho .n::after{content:'✓'}
.paso-tab.hecho .n>span,.paso-tab.hecho .n{font-size:12px}
/* El paso que todavía no toca: ámbar, el mismo de todo lo que falta. No se deshabilita
   —tocarlo dice qué falta y lleva al hueco—, porque un botón gris no explica nada. */
.paso-tab.espera .n{background:var(--amber-bg);color:var(--amber);box-shadow:none}
.paso-tab.espera{color:var(--amber)}
/* Los chevrones entre pestañas se van. Con las cuatro dentro de una tarjeta blanca y la
   actual con su fondo, la secuencia ya se lee; tres flechas más son tres cosas que pintar y
   36 px de ancho que en un teléfono le faltan a los nombres. */
.paso-flecha{display:none}
/* Cierre de la pantalla 1. En el teléfono desaparece: ahí la barra fija de abajo ya es
   «Continuar a partidas», y dos botones iguales a un dedo de distancia hacen dudar de si
   son el mismo. En escritorio no hay barra fija, así que este es el único. */
/* El botón de cerrar el paso 1 va a la DERECHA y con su ancho, no de borde a borde.
   Un botón de 560 px de ancho pesa más que la tarjeta de campos que lo precede, y en una
   pantalla con un solo botón eso convierte «continuar» en el asunto de la pantalla en vez de
   en su final. A la derecha es además donde cae el pulgar y donde la maqueta lo pone.
   En el teléfono no existe: ahí la acción vive en la barra fija de abajo, que es la que
   siempre está a la vista. */
.p1-cierre{margin-top:15px;display:flex;justify-content:flex-end}
.p1-cierre .btn{width:auto;min-height:44px;padding:0 20px}
@media(max-width:759px){ .p1-cierre{display:none} }
/* ----- Cuatro pasos en un teléfono -----
   MEDIDO: con su nombre, las cuatro pestañas más sus flechas miden 442 px. Un iPhone SE da
   320 px de ancho y el Fold cerrado menos: la barra desbordaba la página entera y la dejaba
   con desplazamiento horizontal, que es exactamente la regresión que este proyecto ya arregló
   una vez.

   Así que en el teléfono el nombre lo lleva solo la pestaña en la que estás —la única que
   hay que leer— y las otras tres se quedan en su número o su palomita, que es lo que se viene
   a mirar de ellas: cuál está hecho y cuál falta. Tres pastillas de 40 px, tres flechas y la
   actual con el resto: entra en 320 px con aire. El nombre del cliente no se pierde porque
   viaja en el `small` de la pestaña actual, y «qué sigue» lo dice la barra fija de abajo, que
   es la pieza que este proyecto ya encarga de eso en el teléfono. */
@media(max-width:560px){
  .pasos{gap:2px}
  .paso-tab{padding:8px 10px 8px 8px;gap:7px}
  .paso-tab .tx{font-size:12.5px}
  .paso-tab:not(.on) .tx{display:none}
  .paso-tab:not(.on){padding:8px 9px;gap:0}
  /* La actual se queda con lo que sobre y recorta su `small` contra ese ancho, no contra las
     22 ch de la regla base: a 320 px, 22 ch no caben. */
  .paso-tab.on{flex:1 1 auto;min-width:0}
  .paso-tab.on .tx small{max-width:none}
  .paso-flecha{font-size:14px}
}
/* En papel no hay pantallas: sale la cotización entera, las dos partes, sin la barra. */
@media print{
  .pasos,.p1-cierre{display:none!important}
  .wrap{grid-template-columns:1fr!important}
  #card-proy,#card-partidas,#sidebox{display:block!important}
}
/* Las medidas del teléfono —relleno de tarjetas, rejillas, tamaños— viven en el
   bloque «Teléfono: aprovechar la pantalla» del final de la hoja. Aquí solo queda lo
   que no repite un selector base: entre dos reglas con la misma especificidad gana la
   última, y las de ese bloque son las últimas. */
@media(max-width:560px){
  .topbar-in{padding:max(8px,env(safe-area-inset-top,0px)) 12px 8px;gap:8px}
  .brand .t{font-size:13.5px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .brand .t small{display:none}
}
/* ---------- Móvil: sin zoom automático de iOS al enfocar campos + áreas táctiles más grandes ----------
   Hasta 920 px, que es donde la página ya es de una sola columna y aparece la barra
   inferior: entre 761 y 920 px la maqueta era de teléfono pero las medidas seguían
   siendo de escritorio, y ahí cae la pantalla interna del Fold 6 (832 px). */
html{-webkit-text-size-adjust:100%;text-size-adjust:100%;scroll-padding-top:calc(var(--top-fijo,70px) + 12px)}
@media(max-width:920px){
  /* iOS/Safari hace zoom al enfocar un campo con letra <16px; forzamos 16px solo en móvil */
  input,select,textarea,.rv-field input,.rv-field select,.autoctr input{font-size:16px}
  .btn,.addbtn,.ai-btn{min-height:46px}
  .chip{padding:9px 14px;font-size:13px}
  .seg button{padding:9px 14px}
  /* Un icono de 22 px con 6 px de relleno daba una zona de toque de 34 px de alto,
     por debajo de los 44 px, y con tres botones juntos se erraba. Ahora el icono baja
     a 19 px y la caja sube a 40x40. */
  .del,.dup,.pdf-vis{font-size:19px;padding:0;width:40px;height:40px;
    display:inline-flex;align-items:center;justify-content:center;border-radius:9px}
  .btn-maps{padding:11px 10px}
  /* Chips a lo ancho: cada opción se estira para llenar su renglón, así el dedo
     acierta sin apuntar y las etiquetas largas no quedan a medias. */
  .optgrp .chips{gap:7px}
  .optgrp .chip{flex:1 1 auto;justify-content:center;text-align:center;min-height:44px;padding:10px 12px}
  .optgrp .chips>.switch{flex:1 1 100%;margin:0 0 2px 0}
  /* La columna vacía del bloque de medidas solo servía para alinear en escritorio */
  .fld-relleno{display:none}
  .ai-btn .solo-desk{display:none}
}
/* ---------- Barra de arriba en el teléfono ----------
   Va después del bloque de 760 px porque ahí se reajustan .seg y .chip: entre dos
   media queries con la misma especificidad gana la última, no la más estrecha.
   El contenedor de la derecha se disuelve (display:contents) para que sus tres
   controles se acomoden como hermanos de la marca. Quedan dos renglones: arriba la
   marca —logotipo y nombre— y abajo los tres controles que de verdad se usan, folio,
   rol e historial.

   Y de esos dos renglones solo el segundo se queda pegado al desplazarse:
   ajustarTopbarMovil() le pone a la barra un desplazamiento negativo del alto exacto
   de la marca, así el logotipo se va con el scroll y lo que permanece a la vista es
   la fila útil. La barra fija baja de 115 px a ~50 px —una séptima parte de la
   pantalla del teléfono que regresa a la cotización— y la marca vuelve a aparecer
   sola al subir hasta arriba.

   Los selectores van acotados a .topbar-in: la píldora del folio comparte clase con
   el contador de partidas, y un `order` suelto se lo llevaba también a él, que vive
   en otra caja y con otro orden. */
/* En las pantallas angostas —iPhone SE, 13 mini— la palabra «Historial» era justo lo
   que hacía que el selector de rol ya no cupiera y se fuera a un tercer renglón, que
   es el que se queda pegado y cuesta pantalla. Se queda el icono con su nombre
   accesible: el destino sigue siendo el mismo y la fila cabe entera. */
@media(max-width:385px){
  .topbar-in .btn-hist .lbl{display:none}
  .topbar-in .btn-hist{padding:0;width:44px;min-height:44px;display:inline-flex;align-items:center;justify-content:center}
  .topbar-in .btn-hist .svgi{width:var(--ico2);height:var(--ico2)}
  /* Aquí no caben los dos iconos junto al selector de rol: se midió, el renglón útil de una
     pantalla de 360 px son 336 px y el selector solo —con la palabra «Autorizador» dentro—
     pide 190 px de contenido mínimo que ningún flex-basis puede bajar.

     El primer intento fue esconder el enlace a la plataforma, para no meter un tercer
     renglón. Estuvo mal, y se supo en cuanto se publicó: el propio director no encontró la
     plataforma en su teléfono. Un atajo que no se ve no es un atajo, y «está en la pantalla
     de inicio como otra app» no sirve de nada si nadie lo sabe.

     Así que el que se baja de renglón es el SELECTOR DE ROL, que es lo correcto: se elige
     una vez y no se vuelve a tocar en semanas, mientras que ir a la plataforma es
     navegación de todos los días. El renglón de arriba se queda con lo que se usa —folio,
     historial, plataforma— y el rol se va abajo, donde estorba menos. */
  .topbar-in .seg{order:6;flex:1 1 100%}
}
@media(max-width:560px){
  .rolewrap{display:contents}
  .topbar-in .brand{order:1;flex:1 1 100%;min-width:0;gap:8px}
  .topbar-in .folio{order:2;flex:0 0 auto;padding:5px 9px;font-size:11.5px;white-space:nowrap}
  /* Base de 150 px: si con el folio y el historial ya no cabe —pantallas de 320 px—
     el selector de rol se pasa solo al renglón de abajo en vez de partir su texto. */
  .topbar-in .seg{order:3;flex:1 1 150px;width:auto}
  .topbar-in .seg button{flex:1;padding:0 10px;min-height:44px;font-size:12.5px}
  .topbar-in .btn-hist{order:4;flex:0 0 auto;padding:0 12px;min-height:44px}
  /* El enlace a la plataforma pierde su palabra en cuanto la pantalla es de teléfono, no a
     los 385 px como «Historial»: son dos controles y con los dos escritos el renglón del
     folio y el selector de rol ya no cabía. Un tercer renglón en esta barra es el error que
     esta hoja ya arregló una vez —está tres bloques más abajo— y no se vuelve a cometer. */
  .topbar-in .btn-pf .lbl{display:none}
  .topbar-in .btn-pf{order:5;padding:0;width:44px;min-height:44px;display:inline-flex;align-items:center;justify-content:center}
  .topbar-in{row-gap:7px}
}
/* En el celular la palabra «Historial» era justo lo que hacía que el selector de rol ya
   no cupiera y se fuera a un tercer renglón, que es el que se queda pegado y cuesta
   pantalla. Con «Clientes» al lado, esa cuenta ya no sale en NINGÚN teléfono: dos botones
   con texto empujan al tercer renglón hasta en un iPhone de 390 px. Así que en toda la
   maqueta de móvil —el mismo corte de arriba, no un número nuevo— se quedan los dos
   iconos con su nombre accesible: el destino sigue siendo el mismo y la fila cabe entera.
   De 560 px para arriba caben los dos con su palabra y se lee la palabra. */
@media(max-width:560px){
  .topbar-in .btn-hist .lbl{display:none}
  .topbar-in .btn-hist{padding:0;width:44px;min-height:44px;display:inline-flex;align-items:center;justify-content:center}
  .topbar-in .btn-hist .svgi{width:var(--ico2);height:var(--ico2)}
}
/* Nada de zoom por doble toque ni destello gris al tocar: en el celular ese medio
   segundo de espera del navegador hace que la app se sienta lenta. */
button,.chip,.tg,.switch,.ptok,.psum,.tipo-seg button,.seg button,summary{touch-action:manipulation;-webkit-tap-highlight-color:transparent}

/* ---------- El texto de la interfaz no es texto que se edita ----------
   Reporte textual: «los textos de los títulos se pueden borrar como si fuese un texto
   modificable». Se comprobó y borrarse no se borran —no hay un solo contenteditable en
   todo el repositorio, y con el título entero seleccionado la tecla de retroceso no
   cambia nada—. Lo que pasa es peor de explicar y igual de real: se COMPORTAN como si lo
   fueran.

   Un título es texto suelto en el documento, así que hasta ahora tenía la conducta que el
   navegador le da a cualquier párrafo. En un Samsung, tocarlo pintaba encima el rectángulo
   celeste de Android —el `-webkit-tap-highlight-color` de fábrica, rgba(51,181,229,.4), que
   esta hoja ya apagaba para los botones y no para los títulos—; mantenerlo pulsado abría la
   selección con sus dos manijas y la barra de Cortar · Copiar · Compartir. En un iPhone,
   la lupa y el menú Copiar · Buscar. Eso es, gesto por gesto, lo mismo que hace un campo de
   captura. Quien ve su nombre resaltado en azul con dos manijas encima no tiene forma de
   saber que no lo está a punto de borrar.

   Así que el reparto es explícito: el CHROME —títulos, etiquetas, nombres de pestaña, los
   días de la semana— no se selecciona, porque no es contenido, es el mueble. El DATO sí:
   el nombre del cliente, un teléfono, una dirección, un folio, un importe son cosas que
   uno quiere copiar y pegar en WhatsApp, y quitarles la selección sería cambiar un problema
   por otro peor. Por eso la lista de abajo son selectores de mueble y no `body`. */
:is(h1,h2,h3,h4,label,legend,summary,.fld-lab,.cal-dow,.paso-tab,.pf-tab,.seg button,
   .chip,.tg,.tipo-seg button,.btn,.btn-hist,.vacio-t,.vacio-d,.hintnote,.badge,.pf-etapa){
  -webkit-user-select:none;user-select:none;-webkit-touch-callout:none;
  -webkit-tap-highlight-color:transparent;
}
/* Pero dentro de un título puede ir el dato —«Orden de trabajo — Farmacia San Juan»— y ese
   sí se copia. Lo que lleve `.dato` vuelve a ser seleccionable aunque esté en un h2. */
.dato,.selec{-webkit-user-select:text;user-select:text;-webkit-touch-callout:default}
.chip:active,.tipo-seg button:active,.seg button:active{transform:scale(.97)}

/* ---------- Barra de acción de abajo (solo móvil) ----------
   En una sola columna el total y el botón de continuar quedaban hasta el fondo de la
   página: había que hacer scroll a ciegas para saber cuánto llevaba la cotización.
   Esta barra los deja siempre a la mano, con el mismo estado que el panel de resumen. */
.mbar{display:none}
/* 759 px y no 920. La barra fija existe para la pantalla en la que la columna del dinero ya
   no está al lado —o sea cuando el resumen se cae debajo de todas las partidas y el total
   queda a mil píxeles de scroll—. Desde el rediseño eso pasa a los 760, no a los 920: el
   Fold abierto mide 880 y ahí SÍ hay dos columnas, con el total a la vista. Con el corte en
   920, el Fold llevaba las dos cosas —la columna del dinero a la derecha Y una barra fija
   abajo con el mismo total—, que es el mismo número dos veces y 84 px de página menos. */
@media(max-width:759px){
  .mbar{
    display:flex;position:fixed;left:0;right:0;bottom:0;z-index:45;gap:10px;align-items:center;
    background:var(--sup);
    border-top:1px solid var(--linea);box-shadow:none;
    padding:9px 14px;padding-bottom:calc(9px + env(safe-area-inset-bottom,0px));
    padding-left:max(14px,env(safe-area-inset-left,0px));
    padding-right:max(14px,env(safe-area-inset-right,0px));
  }
  /* El hueco de abajo tiene que contar la franja del gesto de inicio del iPhone:
     con 96 px fijos, la barra —65 px más 34 px de franja— tapaba el final de la
     página y el último renglón quedaba inalcanzable. */
  .wrap{padding-bottom:calc(84px + env(safe-area-inset-bottom,0px))}
  /* Sin esto, al llegar con Tab el control enfocado quedaba debajo de la barra fija: 13 de
     58 paradas del recorrido, enteras y sin saber dónde estaba el cursor. */
  html{scroll-padding-bottom:calc(84px + env(safe-area-inset-bottom,0px))}
}
.mbar-tot{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;align-items:flex-start;gap:1px;
  border:none;background:none;padding:2px 0;font-family:inherit;cursor:pointer;text-align:left}
.mbar-lab{font-size:var(--t1);font-weight:500;color:var(--n6);display:flex;align-items:center;gap:var(--e1)}
.mbar-lab .chev{font-size:9px;opacity:.7}
.mbar-amt{font-size:var(--t5);font-weight:650;color:var(--n9);letter-spacing:-.5px;font-variant-numeric:tabular-nums;line-height:1.15}
.mbar-amt.desc{color:var(--green)}
.mbar-btn{flex:0 0 auto;max-width:62%;border:1px solid transparent;border-radius:var(--rr1);background:var(--a);color:#fff;
  font-family:inherit;font-size:var(--t3);font-weight:550;padding:0 18px;min-height:46px;cursor:pointer;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mbar-btn:active{transform:scale(.98)}
/* El 62% de arriba existe para que el botón no le coma el sitio al total. En la pantalla
   del cliente no hay total: el botón es el único hijo de la barra y renderMobileBar le
   pone width:100%, pero max-width siempre gana, así que la llamada a la acción principal
   de la primera pantalla salía usando 224 px de una barra de 390 y dejando el resto en
   blanco. */
.mbar-btn:only-child{max-width:100%}
/* Deshacer en la barra de abajo. Cuadrado y sin etiqueta: al lado del botón que dice el
   siguiente paso, dos textos compitiendo dejan a los dos sin leer. */
.mbar-undo{flex:0 0 auto;width:46px;min-height:44px;display:inline-flex;align-items:center;justify-content:center;
  border:1px solid var(--n3);border-radius:var(--rr1);background:var(--sup);color:var(--brand);
  font-size:17px;cursor:pointer;font-family:inherit;padding:0}
.mbar-undo:active{transform:scale(.96)}
/* Con el deshacer al lado, el botón principal deja de ser hijo único y perdía su ancho
   completo contra el tope del 62%: en la pantalla del cliente, «Continuar a partidas» se
   encogía a dos tercios en cuanto había algo que deshacer, sin que nada más cambiara. */
.mbar-undo+.mbar-btn:last-child{max-width:none;flex:1 1 auto}
.mbar-btn:disabled{opacity:.42;box-shadow:none;cursor:not-allowed}
.mbar-btn.ok{background:var(--ok)}
.mbar-btn.gho{background:#fff;color:var(--n7);border-color:var(--n3)}

/* Por debajo de ~325 px el texto del botón principal no cabía en un renglón y se
   recortaba («⚡ Autorizar yo …»). 340 px es guarda holgada; el 62% de arriba no se toca. */
@media(max-width:340px){ .mbar-btn{white-space:normal;line-height:1.15;padding:0 12px;text-align:center} }

/* ---------- Botón de plegar de una tarjeta ----------
   Lo usan dos botones con destinos distintos: «Ocultar» los datos del proyecto y
   «Plegar todas» las partidas. El aspecto es base —lo comparten— y lo que se decide
   por ancho es solo QUIÉN se ve: plegar los datos del proyecto sigue siendo cosa del
   celular, donde esa tarjeta estorba después de capturarla; plegar las partidas sirve
   en cualquier pantalla y su botón (#fold-all-btn, más abajo) se enseña siempre. */
.card-fold{display:none;align-items:center;gap:7px;border:1.5px solid var(--line);background:var(--sup);
  color:var(--brand-strong);border-radius:9px;padding:7px 11px;font-family:inherit;font-size:11.5px;
  font-weight:700;cursor:pointer;max-width:60%;min-height:40px}
/* min-width:0 para que el «…» funcione de verdad: un elemento flexible no baja de
   lo que mide su texto mientras conserve el min-width automático, así que con un
   nombre de cliente largo el resumen no se recortaba, empujaba la tarjeta y con
   ella toda la página a lo ancho. */
.card-fold .txt{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.card-fold .chev{font-size:10px;flex-shrink:0;transition:transform .18s}
.card-fold:hover{border-color:var(--brand);background:var(--soft-2)}
@media(max-width:920px){
  .card-fold{display:inline-flex}
  /* Estas tres se quedan atadas al ancho a propósito: _foldProy se guarda en el
     dispositivo y la tarjeta puede llegar a escritorio con la clase puesta. Si el
     estado plegado valiera en cualquier ancho, quien la plegó en el celular se la
     encontraría cerrada en la pantalla grande y sin el botón para abrirla. */
  .card.folded .card-fold .chev{transform:rotate(-90deg)}
  .card.folded .card-b{display:none}
  .card.folded .card-h{padding-bottom:16px}
}

/* ----- La tarjeta -----
   Sin sombra. Una línea de un píxel sobre un lienzo más claro separa igual de bien y no
   infla la página: tres tarjetas con sombra, cada una con recuadros con sombra dentro, era
   la mitad del desorden. El título deja de ser un renglón de mayúsculas diminutas en azul
   con un filete al lado —eso es decoración— y pasa a ser lo que es: un título, en el
   tamaño y el peso que le tocan, en tinta. */
.card{background:var(--card);border:1px solid var(--n3);border-radius:var(--rr3);overflow:hidden}
.card+.card{margin-top:var(--e4)}
.card-h{padding:var(--e5) var(--e5) 0;display:flex;align-items:baseline;justify-content:space-between;gap:var(--e3)}
.card-h :is(h2,h3){font-size:var(--t4);font-weight:650;letter-spacing:-.2px;color:var(--n8);display:flex;align-items:center;gap:var(--e2)}
.card-b{padding:var(--e4) var(--e5) var(--e5)}

label,.fld-lab{display:block;font-size:var(--t2);font-weight:500;color:var(--n6);margin-bottom:var(--e2)}
/* .fld-lab es el mismo renglón de arriba de un campo, pero para lo que NO es un campo:
   la lista de API keys y el segmentado de proveedor. Un <label> que no apunta a ningún
   control se lee como texto suelto, así que ahí va un div con id y el grupo lo nombra
   con aria-labelledby. */
/* Campos: borde de un píxel y fondo blanco. El borde de píxel y medio con fondo azulado
   engordaba cada campo y, con quince en pantalla, era medio dibujo de más. */
input,select,textarea{width:100%;min-height:44px;border:1px solid var(--n3);border-radius:var(--rr1);padding:11px 13px;font-size:var(--t3);color:var(--n8);background:var(--sup);outline:none;font-family:inherit;transition:border-color .12s,box-shadow .12s}
input::placeholder,textarea::placeholder{color:var(--n6)}
input:hover:not(:disabled),textarea:hover:not(:disabled){border-color:var(--n4)}
input:focus,select:focus,textarea:focus{border-color:var(--a);box-shadow:0 0 0 3px var(--a-suave)}
/* El autorrelleno de Safari pinta el campo de amarillo y el texto de negro sobre él */
input:-webkit-autofill,input:-webkit-autofill:focus{-webkit-text-fill-color:var(--ink);
  -webkit-box-shadow:0 0 0 100px var(--sup) inset;caret-color:var(--ink)}
input:disabled,select:disabled,textarea:disabled{background:var(--n1);border-color:var(--n2);color:var(--n6);cursor:not-allowed}
textarea{resize:vertical;min-height:46px}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.grid3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px}
.fld{margin-bottom:13px}.fld:last-child{margin-bottom:0}
/* ----- Campos obligatorios -----
   Cliente, teléfono y proyecto se piden antes de la primera partida, así que se
   anuncian desde el principio con un asterisco en la etiqueta: enterarse de que un
   campo era obligatorio al momento de que te frenan es enterarse tarde.
   El asterisco es decorativo —el dato para el lector de pantalla es aria-required en
   el campo— y el ámbar del hueco solo se pinta cuando ya se intentó continuar. */
.fld label .req{color:var(--amber-ico);font-weight:800;margin-left:1px}
.fld.falta label{color:var(--amber)}
.fld.falta input,.fld.falta textarea{border-color:var(--amber-ico);background:var(--amber-bg)}
.fld.falta input:focus,.fld.falta textarea:focus{border-color:var(--brand);background:var(--sup)}

/* ---------- Partidas ---------- */
.empty{text-align:center;color:var(--muted);font-size:13px;padding:30px 10px;border:1.5px dashed var(--line);border-radius:var(--r-sm);background:var(--soft)}
/* ----- La partida -----
   Deja de ser una tarjeta dentro de una tarjeta. Es una sección separada por una línea, con
   su número a la izquierda: el mismo recurso que usa cualquier lista larga que se lee bien.
   Sin borde propio, sin sombra y sin el filete azul de tres píxeles, que competía con el
   único azul que sí significa algo —lo seleccionado— en cada renglón de la cotización. */
.partida{padding:var(--e5) 0;border-top:1px solid var(--n2);position:relative;background:none}
#items>.partida:first-of-type{border-top:none;padding-top:var(--e2)}
.partida-top{display:flex;align-items:center;gap:10px;margin-bottom:14px;flex-wrap:wrap}
.pnum{display:flex;align-items:center;gap:8px;flex-shrink:0}
.ptop-actions{display:flex;align-items:center;gap:2px;margin-left:auto;flex-shrink:0}
/* El número de la partida es una etiqueta, no una acción: en azul de marca competía con
   lo único que ese color debería señalar dentro de la partida, que es lo seleccionado. */
.pnum .n{width:24px;height:24px;border-radius:7px;background:var(--n1);border:1px solid var(--n2);color:var(--n6);font-size:var(--t2);font-weight:600;display:flex;align-items:center;justify-content:center;flex-shrink:0;font-variant-numeric:tabular-nums}
/* Control segmentado, del que se usa en todos lados: la pastilla del elegido se desliza
   sobre un carril gris. Sin relleno de marca ni sombra de 10 px: dentro de una partida es
   una elección entre cinco, no la acción principal de la pantalla. */
.tipo-seg{display:inline-flex;background:var(--n1);border:1px solid var(--n2);border-radius:var(--rr1);padding:3px;flex-wrap:wrap;gap:2px}
.tipo-seg button{border:none;background:none;min-height:44px;padding:6px 11px;font-size:var(--t2);font-weight:500;color:var(--n6);border-radius:6px;cursor:pointer;transition:background .12s,color .12s}
.tipo-seg button.on{background:#fff;color:var(--n8);font-weight:600;box-shadow:0 1px 2px rgba(var(--tinta-rgb),.07)}
/* Cada tipo trae su nombre largo y uno corto; en el teléfono se cambia al corto para
   que los cinco quepan en un solo renglón (ver el bloque del final de la hoja). */
.tipo-seg .sm,.ptipo .sm{display:none}
/* En móvil el selector de tipo se apilaba en 5 renglones y parecía una lista desplegable:
   rejilla de 3 columnas para que se vea de un golpe cuál está activo. (Va después de la
   regla base porque una media query no gana por sí sola cuando la especificidad empata.) */
@media(max-width:760px){
  .tipo-seg{order:9;flex-basis:100%;width:100%;display:grid;grid-template-columns:repeat(3,1fr);gap:3px}
  .tipo-seg button{padding:10px 5px;font-size:11.5px;line-height:1.25;text-align:center;min-height:44px}
}
.del{border:none;background:none;color:var(--n5);font-size:19px;cursor:pointer;line-height:1;padding:3px 6px;border-radius:7px;transition:.12s}
.del:hover{color:var(--red);background:var(--red-bg)}

.chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:4px}
/* Chip sin elegir: plano y discreto. Chip elegido: relleno, con palomita y sombra.
   La diferencia tiene que verse de un vistazo, sin leer. */
/* ----- El chip -----
   Era una píldora gris que al elegirla se volvía azul con degradado, sombra de 14 px y un
   rebote. Multiplicado por los cinco materiales, las tres complejidades y los tres acabados
   de cada partida, lo seleccionado era lo más ruidoso de la pantalla justo por estar
   decidido. Ahora es un botón plano de esquina suave; el elegido se marca con fondo tenue
   del acento, su borde y su tinta —queda claro sin gritar— y el ✓ hace el resto. */
.chip{display:inline-flex;align-items:center;gap:var(--e2);padding:9px 14px;border:1px solid var(--n3);border-radius:var(--rr1);
  font-size:var(--t2);font-weight:500;cursor:pointer;background:var(--sup);color:var(--n7);transition:background .12s,border-color .12s,color .12s;user-select:none}
.chip small{font-weight:500;color:var(--n6);font-variant-numeric:tabular-nums}
.chip .ck{display:none}
.chip.on{border-color:var(--a-borde);background:var(--a-suave);color:var(--a-fuerte);font-weight:600}
.chip.on small{color:var(--a-fuerte);opacity:.75}
.chip.on .ck{display:inline-flex;align-items:center;font-size:11px;line-height:1;color:var(--a)}
.chip:hover:not(.on){border-color:var(--n4);background:var(--n1)}
.chip:focus-visible{outline:2.5px solid var(--brand);outline-offset:2px}
/* Un chip apagado —cotización autorizada, o el candado de las partidas— conservaba
   `cursor:pointer` y su `:hover`, así que se veía y se comportaba como uno vivo hasta que
   lo tocabas y no pasaba nada. No existía una sola regla [aria-disabled] en la hoja. El
   apagado se hace con color y no con opacidad: el chip dice QUÉ material se eligió, y eso
   hay que poder leerlo. El elegido se queda relleno —es la respuesta— pero sin la sombra
   ni el rebote, que son lo que promete que se puede tocar. */
.chip[aria-disabled="true"]{cursor:default;background:transparent;border-color:var(--n2);color:var(--n6)}
.chip[aria-disabled="true"]:hover:not(.on){background:transparent;border-color:var(--n2);color:var(--n6)}
.chip[aria-disabled="true"].on{background:var(--n2);border-color:var(--n3);color:var(--n7)}
.chip[aria-disabled="true"].on small{color:var(--n6)}
.chip[aria-disabled="true"].on .ck{color:var(--n6)}
/* Mismo problema y mismo criterio en los dos botones que quedaban: el selector de tipo y
   la × de borrar salían idénticos a los vivos —el tipo elegido seguía siendo la píldora
   azul con degradado y sombra, el objeto más llamativo de la partida— y hasta conservaban
   el encogido al pulsar y el rojo al pasar el ratón. Se cubren las dos formas de apagado,
   `disabled` y `aria-disabled`, porque la partida usa una u otra según qué candado sea. */
.tipo-seg button:is(:disabled,[aria-disabled="true"]){cursor:default}
.tipo-seg button:is(:disabled,[aria-disabled="true"]):active{transform:none}
.tipo-seg button:is(:disabled,[aria-disabled="true"]).on{background:var(--gray-bg);color:var(--ink);box-shadow:none;animation:none}
.del:is(:disabled,[aria-disabled="true"]){cursor:default;color:var(--n4)}
.del:is(:disabled,[aria-disabled="true"]):hover{color:var(--n4);background:none}
@keyframes chipPop{0%{transform:scale(.84)}65%{transform:scale(1.07)}100%{transform:scale(1)}}
/* `inline-flex` y no `inline-block`: la nota casi siempre empieza con un icono, y como
   caja de bloque el único separador entre el icono y el texto era un espacio de texto
   literal —' ' en el JS— que a 12,5 px mide 3,3 px, contra los 8 del resto del sistema. Era
   el único par icono/etiqueta de la app con un hueco distinto, y además el texto que pasaba
   de un renglón volvía a empezar DEBAJO del icono en vez de alinearse con la primera línea.
   Con flex el hueco sale del mismo --e2 que todo lo demás, el espacio literal deja de
   contar —el flex ignora los nodos de solo espacio— y el texto se acomoda en su columna. */
.hintnote{font-size:var(--t2);color:var(--n6);background:var(--n1);border-radius:var(--rr1);padding:8px 12px;display:inline-flex;align-items:flex-start;gap:var(--e2);line-height:1.5}
.hintnote>.svgi{flex-shrink:0;margin-top:.15em}
/* Los avisos con color van con el mismo relleno tenue y borde de un píxel que todo lo
   demás; el filete de tres píxeles a la izquierda era el único elemento de la hoja que se
   dibujaba así, y con tres colores distintos. */
.hintnote.nota-av{background:var(--av-bg);border:1px solid var(--av-borde);color:var(--av)}
.hintnote.nota-ok{background:var(--ok-bg);border:1px solid var(--ok-borde);color:var(--ok)}

/* Los siete interruptores eran <label class="switch"> con un <span class="tg"> dentro:
   sin for y sin control dentro, ni entraban en el orden de tabulación ni respondían a
   Espacio, y el único indicio del estado era el color del span. Ahora son <button
   role="switch">, así que hacen falta los reajustes de un botón. El margin-bottom es el
   que traían heredado de label{margin-bottom:5px}: sin él, los tres del vectorizador y
   del escalador se pegaban 5 px al bloque de abajo. Se queda en display:flex —no
   inline-flex— para que sigan en su propio renglón; un <button> con width:auto se ajusta
   a su contenido, así que el blanco de 250 px que había a la derecha del texto deja de
   responder, y lo que se toca es exactamente lo que se ve. */
.switch{display:flex;align-items:center;gap:9px;font-size:13px;font-weight:600;color:var(--ink);cursor:pointer;user-select:none;
  border:none;background:none;font-family:inherit;text-align:left;padding:0;margin-bottom:5px}
.switch:disabled{cursor:default}
/* Un interruptor apagado solo cambiaba el cursor: seguía azul de marca y con su sombra,
   o sea exactamente igual que uno vivo. Mismo criterio que los chips —el estado se lee,
   pero no promete que se pueda tocar—: el encendido se queda encendido, en gris de
   reposo, y el texto conserva su color de siempre. */
.switch:disabled .tg{background:var(--n4);box-shadow:none}
.switch:disabled .tg.on{background:var(--n5)}
.tg{width:42px;height:24px;background:var(--n5);border-radius:13px;position:relative;transition:.2s;flex-shrink:0}
/* La perilla se ve de 42×24, pero se toca en 50×44: la capa invisible crece la zona
   sensible sin mover nada de sitio. Es el control del IVA, de la iluminación y del
   pegado a guías; con 24 px de alto se erraba. */
.tg::before{content:'';position:absolute;inset:-10px -4px;border-radius:16px}
.tg.on{background:var(--brand-grd)}
.tg::after{content:'';width:18px;height:18px;background:#fff;border-radius:50%;position:absolute;top:3px;left:3px;transition:.2s;box-shadow:0 1px 4px rgba(0,0,0,.2)}
.tg.on::after{left:21px}

.pline{display:flex;align-items:center;justify-content:flex-start;gap:var(--e3);margin-top:var(--e4);padding-top:var(--e3);border-top:1px solid var(--linea2)}
.pline .formula{font-size:11.5px;color:var(--muted)}
/* inline-block para que el difuminado de la cifra no descuadre el renglón */
.formula .dinero{display:inline-block}
.pline .formula b{color:var(--ink);font-weight:700}
.pline .lt{font-size:var(--t4);font-weight:600;color:var(--n8);font-variant-numeric:tabular-nums}
/* Partida con precio puesto a mano por el autorizador: se enseña el que se va a cobrar y,
   al lado, el calculado tachado. Antes la pantalla decía el calculado y el PDF el
   autorizado, y nada avisaba de que eran dos números distintos. */
.pline .lt .lt-calc{font-size:12.5px;font-weight:600;color:var(--muted);text-decoration:line-through;margin-right:5px}
.addbtn{width:100%;padding:12px;border:1px dashed var(--n4);border-radius:var(--rr1);background:none;color:var(--n7);font-size:var(--t2);font-weight:500;cursor:pointer;transition:border-color .12s,background .12s}
.addbtn:hover{background:var(--n1);border-color:var(--n5);color:var(--n8)}
.addbtn:disabled{opacity:.45;cursor:not-allowed}

/* Duplicate button */
.dup{border:none;background:none;color:var(--n5);font-size:16px;cursor:pointer;line-height:1;padding:2px 6px;border-radius:6px}
.dup:hover{color:var(--brand);background:var(--soft-2)}
/* Drag & drop reorder */
.drag-handle{cursor:grab;color:var(--n5);font-size:18px;padding:0 5px 0 0;user-select:none;line-height:1;display:inline-flex;align-items:center}
.drag-handle:active,.drag-handle:hover{cursor:grabbing;color:var(--brand)}
/* ----- La cara de la partida plegada -----
   Lo que se está cotizando en esa partida, y nada más: la descripción arriba y debajo
   las fichas de lo elegido. Lo que falta se resume en una sola ficha ámbar; el itemizado
   de los huecos se lee abajo, en el renglón de la fórmula, para no decirlo dos veces. */
.psum{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 14px;align-items:center}
/* La descripción se lleva su propio renglón (flex-basis:100%) y NUNCA envuelve: una
   descripción larga se corta con puntos suspensivos en vez de crecer la cara plegada.
   min-width:0 es lo que hace que el recorte funcione dentro de un contenedor flexible. */
.pdsc{flex:1 1 100%;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-size:13px;font-weight:700;color:var(--ink);line-height:1.35}
/* Sin descripción no se regaña en ámbar: no frena la autorización ni sale en el aviso de
   partidas sin terminar, así que se dice en gris y se invita a escribirla. */
.pdsc.vacia{font-weight:600;font-style:italic;color:var(--muted)}
/* ----- La cara de la partida plegada -----
   Estos son DATOS, no selecciones: lo que ya está decidido en esa partida. Iban con el
   fondo y la tinta del acento —el mismo lenguaje que el chip elegido— y una partida plegada
   se veía como seis cosas recién escogidas parpadeando en azul. Ahora son neutros y el ✓ es
   lo que dice que están puestos; el color se guarda para lo que falta y para lo apagado,
   que son los dos casos en los que hace falta mirar. */
.ptok{display:inline-flex;align-items:center;gap:var(--e1);font-size:var(--t2);font-weight:500;padding:4px 10px;border-radius:var(--rr1);background:var(--n1);color:var(--n7);border:1px solid var(--n2);max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* MEDIDO: --n5 sobre el blanco de la tarjeta da 3,02:1, y a 10 px eso no se lee en la
   calle. Y no es un adorno: en la cara plegada de la partida, el ✓ y el — son LO ÚNICO que
   distingue una opción puesta de una apagada —los dos fondos, --n1 y transparente, se
   diferencian en 1,02:1 sobre blanco, o sea nada—. Con --n6 son 5,43:1 y el tamaño sube al
   primer paso de la escala, que es 11 px. Es la superficie que se le enseña al cliente del
   otro lado de la mesa. */
.ptok::before{content:'✓';font-size:var(--t1);font-weight:600;color:var(--n6)}
.ptok.falta{background:var(--av-bg);color:var(--av);border-color:var(--av-borde)}
.ptok.falta::before{content:'!';font-weight:700;color:var(--av)}
.ptok.off{background:transparent;color:var(--n6);border-color:var(--n2)}
.ptok.off::before{content:'—';font-weight:700;color:var(--n6)}
/* Cada bloque de opciones va encerrado y con su valor elegido en el encabezado */
/* ----- El grupo de opciones -----
   Era un recuadro con borde y fondo dentro de la partida, que a su vez era una tarjeta
   dentro de otra tarjeta: tres marcos para enseñar cinco botones. Ahora es lo que siempre
   fue —una etiqueta y sus opciones debajo— y lo que los agrupa es el espacio. La etiqueta
   deja de ser mayúsculas diminutas con interletrado: eso se lee peor y grita más. */
.optgrp{margin-bottom:var(--e4)}
.optgrp-h{display:flex;align-items:baseline;gap:var(--e2);flex-wrap:wrap;margin-bottom:var(--e2)}
.optgrp-t{font-size:var(--t2);font-weight:600;color:var(--n6)}
.optgrp-v{font-size:var(--t2);font-weight:600;color:var(--av);display:inline-flex;align-items:center;gap:var(--e1);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.optgrp-v::before{content:'·';font-weight:700}
.optgrp .chips{margin:0}
.optgrp .hintnote{margin-top:8px}
.partida.drag-over{box-shadow:inset 0 2px 0 var(--a)}
.partida.dragging{opacity:.35}
/* Auto-counter for letter count */
/* Renglón propio debajo de la rejilla: metido en la media columna de «# Letras»
   el marcador «Escribe el texto →» quedaba recortado a 126 px. */
.autoctr{display:flex;align-items:center;gap:6px;margin-top:5px}
.autoctr input{font-size:12px;padding:5px 8px;flex:1;min-width:0}
.autoctr .cnt{font-size:11px;color:var(--brand);font-weight:700;white-space:nowrap;min-width:42px;text-align:right}

/* ---------- Resumen (sticky) ---------- */
.side{position:sticky;top:calc(3px + 78px)}
/* ----- El resumen -----
   Eran dos bloques de color a pantalla completa —uno azul de marca para el subtotal y uno
   marino con degradado para el total— apilados uno encima del otro. Pintar de color un
   número no lo hace más importante: lo hace más ruidoso, y ahí estaban los dos objetos más
   llamativos de la pantalla compitiendo entre sí. Ahora la jerarquía la hace el tamaño: el
   total es el número grande de la columna y no necesita nada más. */
.sum{background:var(--card);border:1px solid var(--n3);border-radius:var(--rr3);overflow:hidden}
.sum-rows{padding:var(--e4) var(--e5) var(--e2)}
.srow{display:flex;justify-content:space-between;align-items:center;gap:var(--e3);font-size:var(--t3);color:var(--n6);padding:var(--e2) 0}
.srow.ivt{border-top:1px solid var(--n2);margin-top:var(--e1)}
.srow .v{font-weight:500;color:var(--n8);font-variant-numeric:tabular-nums}
.srow.subtotal{font-size:var(--t3);font-weight:500;color:var(--n7);padding:var(--e2) 0}
.srow.subtotal .v{font-size:var(--t4);font-weight:600;color:var(--n8)}
.neto{padding:var(--e4) var(--e5) var(--e5);border-top:1px solid var(--n2);display:flex;justify-content:space-between;align-items:flex-end;gap:var(--e3)}
.neto .lab{font-size:var(--t2);font-weight:500;color:var(--n6)}
.neto .neto-calc{font-size:var(--t1);color:var(--n6);margin-top:2px}
.neto .amt{font-size:var(--t7);font-weight:650;letter-spacing:-1px;color:var(--n9);font-variant-numeric:tabular-nums;line-height:1}
.anti{padding:var(--e4) var(--e5);border-top:1px solid var(--n2)}
.sum-rows-2{padding-top:0;padding-bottom:0;border-top:1px solid var(--n2);margin-top:var(--e2)}
.srow.subtotal .v small{font-size:var(--t1);font-weight:500;color:var(--n6);margin-left:var(--e1)}

/* ---------- Autorización ---------- */
.auth{padding:var(--e4) var(--e5) var(--e5);border-top:1px solid var(--n2)}
.statusrow{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--e3)}
.statusrow .lab{font-size:var(--t2);font-weight:500;color:var(--n6)}
.badge{display:inline-flex;align-items:center;gap:var(--e2);font-size:var(--t1);font-weight:500;padding:4px 10px;border-radius:var(--rr1)}
.badge .dot{width:7px;height:7px;border-radius:50%}
.badge.borrador{background:var(--gray-bg);color:var(--gray)} .badge.borrador .dot{background:var(--gray)}
.badge.pendiente{background:var(--amber-bg);color:var(--amber)} .badge.pendiente .dot{background:var(--amber)}
.badge.autorizada{background:var(--green-bg);color:var(--green)} .badge.autorizada .dot{background:var(--green)}
.badge.rechazada{background:var(--red-bg);color:var(--red)} .badge.rechazada .dot{background:var(--red)}

/* Un solo botón lleva color de relleno en cada pantalla: el que hace lo que se vino a
   hacer. Los demás son neutros con borde. Cuando todos gritan, ninguno dirige. */
.btn{width:100%;padding:12px 16px;border-radius:var(--rr1);font-size:var(--t3);font-weight:550;border:1px solid transparent;cursor:pointer;
  transition:background .12s,border-color .12s,color .12s;display:flex;align-items:center;justify-content:center;gap:var(--e2)}
/* El icono de un botón grande no sigue a la letra del botón. Con `1em` heredaba los 14 px
   de --t3 y quedaba un glifo de 14 dentro de una pieza de 46 a 58 px de alto: se leía como
   una errata, no como parte del botón. */
.btn .svgi{width:var(--ico3);height:var(--ico3)}
.btn+.btn{margin-top:var(--e2)}
/* Dos botones en un renglón: el margen de arriba los descuadra —el hermano sin margen se
   estira al alto de la fila y el otro queda 8 px más abajo y 8 px más chico—. Apilados el
   margen sí es lo correcto, así que el selector no se amplía más allá de estas dos filas. */
.btn-fila{display:flex;gap:8px}
.btn-fila .btn+.btn,.vt-dl .btn+.btn{margin-top:0}
.btn-pri{background:var(--a);color:#fff}.btn-pri:hover{background:var(--a-fuerte)}
.btn-ok{background:var(--ok);color:#fff}.btn-ok:hover{filter:brightness(1.08)}
.btn-dgr{background:var(--sup);color:var(--mal);border-color:var(--mal-borde)}.btn-dgr:hover{background:var(--mal-bg)}
.btn-gho{background:var(--sup);color:var(--n7);border-color:var(--n3)}.btn-gho:hover{border-color:var(--n4);background:var(--n1)}
.btn:disabled{opacity:.45;cursor:not-allowed;box-shadow:none}
/* ----- Los tres pasos de la entrega -----
   Un renglón por paso, en el orden en que se hacen. El que toca lleva el único relleno de la
   columna; el que ya está se queda neutro, con su palomita y su fecha, y sigue tocable: un
   PDF se reimprime y un chat se vuelve a abrir. La palomita va en verde y la fecha en el
   secundario de la app —5,5:1 sobre blanco—, porque son un dato al margen y no la acción. */
.hito-ok{color:var(--ok)}
.hito-fecha{font-size:var(--t1);font-weight:400;color:var(--muted);white-space:nowrap}
/* La pista va DENTRO del botón de relleno, así que hereda su tinta blanca. Sin opacidad: la
   separan el tamaño y el peso, que es como este proyecto hace la jerarquía, y así no hay nada
   que medir — blanco sobre el degradado de marca son 10:1 de sobra. Con un 82 % de opacidad
   quedaba en 5,1:1, que pasa, pero pagar contraste por una diferencia que ya está hecha con
   el cuerpo de la letra es pagar de más. */
/* La pista va en su propio renglón dentro del botón: al lado le robaba el ancho al nombre y lo
   partía en dos —«Enviar por / WhatsApp  adjunta el PDF…»—, que es peor que no decir nada,
   porque lo primero que hay que leer de un botón es qué hace.
   El `flex-wrap` se pone SOLO en estos tres botones y no en `.btn`, que es la clase de todos
   los botones grandes de las dos apps: `css/sistema.css` se genera de esta hoja y la plataforma
   la hereda, así que envolver ahí habría cambiado el alto de botones de seis pantallas que no
   tienen nada que ver con esto. */
.btn.hito{flex-wrap:wrap}
.hito-pista{flex-basis:100%;font-size:var(--t1);font-weight:400;color:var(--muted);text-align:center;margin-top:1px}
.btn-pri .hito-pista{color:inherit}
/* Sin relleno y con la palomita, el nombre del botón ya no es lo primero que se lee, así que
   se le devuelve el peso: es el nombre de la acción, y sigue siendo tocable. */
.hito-hecho{color:var(--n7)}
/* El pliegue de «otras salidas» va después de los tres renglones y antes del cierre. El
   <details> no es un .btn, así que se le da el mismo aire que separa dos botones. Va en
   secundario y no en azul de marca —el azul es de lo que se elige y de lo que se hace— y el
   selector lleva el `details` delante porque `details.ai-cfg summary` gana por especificidad. */
.otras-salidas{margin-top:var(--e2)}
/* Tres clases y no dos: `details.ai-cfg summary` tiene la MISMA especificidad y vive más
   abajo en la hoja, así que empataba y ganaba ella. Se veía: el resumen salía en azul de
   marca sobre el lienzo del pliegue, MEDIDO en 4,48:1 — por debajo del mínimo de esta app, y
   además el azul aquí no significa nada, porque no es una selección ni la acción principal. */
details.ai-cfg.otras-salidas summary{color:var(--muted);font-weight:550}
/* `display:flex` en el <summary> se lleva el triangulito del navegador, así que el pliegue no
   parecía un pliegue: aquí es el único camino a Canva y al prompt de imagen, y un control que
   no se ve que abre algo es una función escondida. */
.os-chev{display:inline-block;transition:transform var(--mv);color:var(--n5);font-size:11px}
details.otras-salidas[open] .os-chev{transform:rotate(180deg)}
/* «Nueva cotización» estaba a un dedo de «Registrar venta». Una línea y aire la separan de
   lo que se hace con ESTA cotización. */
.auth-cierre{margin-top:var(--e3);padding-top:var(--e3);border-top:1px solid var(--line)}
.auth-cierre .btn{margin-top:0}
.authnote{font-size:12.5px;color:var(--n7);line-height:1.55;background:var(--sup);border:1px solid var(--line);border-radius:var(--r-sm);padding:11px 13px;margin-bottom:10px}
.authnote b{color:var(--ink)}
.mini{font-size:11.5px;color:var(--muted);margin-top:9px;text-align:center;line-height:1.5}

.toast{position:fixed;bottom:26px;left:50%;transform:translateX(-50%) translateY(90px);background:#11162e;color:#fff;padding:13px 20px;border-radius:13px;font-size:14px;font-weight:600;z-index:100;transition:transform .3s cubic-bezier(.2,.8,.2,1);box-shadow:0 8px 40px rgba(0,0,0,.28);display:flex;align-items:center;gap:14px;width:max-content;max-width:min(92vw,540px);text-align:left;visibility:hidden;transition:transform .3s cubic-bezier(.2,.8,.2,1),visibility 0s linear .3s}
/* Al aparecer se hace visible de inmediato; al ocultarse espera a que termine de
   deslizarse. Con una transición normal de visibility el botón "Deshacer" tardaba
   en volverse tocable. */
.toast.show{transform:translateX(-50%) translateY(0);visibility:visible;transition:transform .3s cubic-bezier(.2,.8,.2,1),visibility 0s linear 0s}
/* Mientras se va deslizando sigue visible 0.3 s y se comía el toque del botón que
   quedaba debajo: ya retirado, no estorba. */
.toast:not(.show){pointer-events:none}
/* Solo se animan color y borde: con "transition:.13s" (que aplica a todas las
   propiedades) el botón heredaba la animación de visibility del aviso y tardaba
   en volverse tocable justo cuando el usuario quiere apretarlo. */
.toast-act{flex-shrink:0;border:1.5px solid rgba(255,255,255,.35);background:rgba(255,255,255,.12);color:#fff;font-family:inherit;font-size:13px;font-weight:800;padding:7px 15px;border-radius:9px;cursor:pointer;transition:background .13s,border-color .13s}
.toast-act:hover{background:rgba(255,255,255,.24);border-color:#fff}
.toast.ok{background:var(--ok)} .toast.err{background:var(--mal)}
/* En móvil el aviso se sube por encima de la barra de acción: si no, la tapa justo
   cuando trae un botón —«Deshacer»— que hay que poder apretar. Va aquí abajo, después
   de la regla base, porque una media query no gana por sí sola cuando empata la
   especificidad. La regla del escalador (.scaler-modal-bg.show+.toast) manda sobre
   esta por ser más específica, así que el escalador conserva su propia altura. */
@media(max-width:759px){
  .toast{bottom:calc(20px + 66px + env(safe-area-inset-bottom,0px))}
}

/* ----- Cola de autorización ----- */
.queue-list{border:1.5px solid var(--line);border-radius:var(--r-sm);overflow:hidden;margin-bottom:11px}
.queue-empty{font-size:12.5px;color:var(--muted);text-align:center;padding:16px 10px;background:var(--soft)}
.queue-item{display:flex;align-items:center;gap:9px;padding:10px 13px;cursor:pointer;border-bottom:1px solid var(--line);transition:.12s;background:var(--sup)}
.queue-item:last-child{border-bottom:none}
.queue-item:hover:not(.active){background:var(--soft)}
.queue-item.active{background:var(--soft-2);border-left:3px solid var(--brand);padding-left:10px}
.qi-dot{width:8px;height:8px;border-radius:50%;border:2px solid var(--brand);flex-shrink:0;margin-top:2px}
.queue-item.active .qi-dot{background:var(--brand)}
.qi-body{flex:1;min-width:0}
.qi-folio{font-size:10px;font-weight:800;color:var(--brand);letter-spacing:.4px;text-transform:uppercase}
.qi-name{font-size:12.5px;font-weight:600;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.qi-fecha{font-size:10.5px;color:var(--muted)}
.qi-total{font-size:12px;font-weight:800;color:var(--ink);white-space:nowrap}
.auth-divider{font-size:10.5px;font-weight:800;text-transform:uppercase;letter-spacing:.7px;color:var(--muted);margin:2px 0 11px;border-top:1px solid var(--line);padding-top:11px}
.descuento-info{font-size:12px;color:var(--green);font-weight:700;margin-top:4px;min-height:16px}
.descuento-info.inc{color:var(--amber)}
.auth-adj{border-top:1px solid var(--line);padding:11px 20px 4px;background:var(--green-bg)}
.auth-adj .adj-label{font-size:12px;color:var(--green);font-weight:600}
.auth-adj .adj-amt{font-size:18px;font-weight:800;color:var(--green)}
.auth-adj .adj-desc{font-size:11.5px;color:var(--green);padding-bottom:10px}
/* Cuando el autorizador sube el precio en vez de bajarlo, el bloque cambia a ámbar
   para que no se lea como un descuento. */
.auth-adj.inc{background:var(--amber-bg)}
.auth-adj.inc .adj-label,.auth-adj.inc .adj-amt,.auth-adj.inc .adj-desc{color:var(--amber)}
.anti-rest{font-size:11.5px;color:var(--muted);font-weight:600;margin-top:7px}

/* ----- IA ----- */
/* Los tres accesos —IA, escalar, vectorizar— son tres herramientas del mismo rango, y sin
   embargo uno era una barra azul sólida a todo lo ancho, otro tenía borde verde y el otro
   morado. Tres pesos y tres colores para tres cosas iguales. Ahora los tres son el mismo
   botón neutro; el color se reserva para la acción principal de la pantalla. */
.ai-btn{width:100%;padding:10px 14px;border:1px solid var(--n3);border-radius:var(--rr1);background:#fff;color:var(--n7);font-size:var(--t2);font-weight:500;cursor:pointer;margin-bottom:var(--e4);display:flex;align-items:center;justify-content:center;gap:var(--e2);transition:border-color .12s,background .12s}
.ai-btn:hover{background:linear-gradient(135deg,#2e3dbf,#4d5ee8);box-shadow:0 4px 16px rgba(var(--a-rgb),.35)}
.modal-bg{position:fixed;inset:0;background:rgba(17,22,46,.6);display:none;align-items:center;justify-content:center;z-index:60;backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);
  padding:calc(18px + env(safe-area-inset-top,0px)) calc(18px + env(safe-area-inset-right,0px)) calc(18px + env(safe-area-inset-bottom,0px)) calc(18px + env(safe-area-inset-left,0px))}
.modal-bg.show{display:flex}
/* La imagen a pantalla completa se abre DESDE el historial, así que tiene que quedar
   por encima de él: los dos son .modal-bg y con el z-index empatado en 60 ganaba el
   panel por ir después en el documento — la pantalla se oscurecía y no se veía nada.
   El 80 está libre (modales 60, vectorizador 56, escalador 55, aviso 100). */
#lightbox{z-index:80}
.modal{background:var(--sup);border-radius:20px;max-width:460px;width:100%;box-shadow:0 24px 80px rgba(0,0,0,.28);overflow:hidden;
  display:flex;flex-direction:column;max-height:calc(100dvh - 36px - env(safe-area-inset-top,0px) - env(safe-area-inset-bottom,0px))}
.modal-h{display:flex;align-items:center;justify-content:space-between;padding:16px 20px;border-bottom:1px solid var(--line);background:var(--sup);flex-shrink:0}
.modal-h b{font-size:15px;font-weight:700}
.modal-h button{border:none;background:none;font-size:22px;color:var(--muted);cursor:pointer;line-height:1;width:30px;height:30px;border-radius:8px;display:flex;align-items:center;justify-content:center;transition:.12s}
.modal-h button:hover{background:var(--soft);color:var(--ink)}
.modal-b{padding:18px 20px 20px;overflow-y:auto;flex:1 1 auto;min-height:0;-webkit-overflow-scrolling:touch}
.ai-status{font-size:12.5px;margin-top:11px;min-height:16px;font-weight:600}
.ai-status.err{color:var(--red)} .ai-status.ok{color:var(--green)} .ai-status.work{color:var(--brand)}
.ai-link{color:var(--brand);font-weight:600;text-decoration:none}.ai-link:hover{text-decoration:underline}
details.ai-cfg{margin-bottom:13px;border:1px solid var(--line);border-radius:var(--r-sm);padding:9px 12px;background:var(--soft)}
/* El renglón que abre el pliegue medía 18 px de alto: la mitad del pulgar de cualquiera.
   Es el control que descubre los campos que salen en el PDF y el de la clave de la IA, o
   sea que fallar el toque cuesta buscar dónde se abre. Con `display:flex` el <summary>
   deja de encoger al alto de su letra y el triángulo se alinea con ella. */
details.ai-cfg summary{display:flex;align-items:center;gap:var(--e2);min-height:44px;
  font-size:12px;color:var(--brand);cursor:pointer;font-weight:700}
.ai-merge{margin-top:11px;background:var(--amber-bg);border:1.5px solid rgba(var(--av-rgb),.28);border-radius:var(--r-sm);padding:11px 13px}
.ai-merge .switch{font-size:12.5px;font-weight:700;color:var(--av)}
.ai-merge-note{font-size:11.5px;color:var(--av);line-height:1.5;margin-top:7px}
/* Campo de API key: se oculta con text-security en vez de type="password" para que
   el navegador no lo tome por una contraseña y ofrezca guardarla. */
.key-in{-webkit-text-security:disc;text-security:disc;font-family:inherit;letter-spacing:.08em}
.key-saved{display:flex;align-items:center;gap:8px;flex-wrap:wrap;background:var(--green-bg);border:1px solid rgba(var(--ok-rgb),.22);border-radius:var(--r-sm);padding:8px 11px}
.key-list{display:flex;flex-direction:column;gap:6px}
.key-list:not(:empty){margin-bottom:7px}
.key-add{display:flex;gap:7px;align-items:stretch}
.key-add .key-in{flex:1;min-width:0}
.key-btn.add{white-space:nowrap;padding:0 13px;background:var(--soft-2)}
.key-mask{flex:1;min-width:0;font-size:12px;font-weight:700;color:var(--green);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.key-btn{border:1px solid var(--line);background:var(--sup);color:var(--a-fuerte);border-radius:8px;padding:4px 10px;font-size:11.5px;font-weight:700;cursor:pointer;font-family:inherit}
.key-btn:hover{background:var(--soft-2)}
.key-btn.del{color:var(--red)}
.key-note{font-size:11.5px;color:var(--muted);line-height:1.5;margin-top:9px;border-top:1px dashed var(--line);padding-top:9px}
.ai-tag{display:inline-block;font-size:9.5px;font-weight:700;color:var(--a-fuerte);background:var(--a-suave);border-radius:5px;padding:1px 5px;margin-left:5px;vertical-align:middle;text-transform:none;letter-spacing:0}
/* Origen del análisis cuando no es un archivo suelto sino lo que se acaba de medir */
.ai-src{display:flex;gap:11px;align-items:flex-start;background:var(--green-bg);border:1.5px solid rgba(var(--ok-rgb),.28);border-radius:var(--r-sm);padding:10px 12px;margin-bottom:13px}
/* contain, no cover: de un plano o un boceto hay que reconocer el conjunto, y
   recortarlo a un cuadrado deja fuera justo lo que se va a cotizar. */
.ai-src-img{width:76px;height:76px;object-fit:contain;border-radius:9px;border:1px solid rgba(var(--ok-rgb),.25);flex-shrink:0;background:var(--sup);padding:3px}
.ai-src-b{flex:1;min-width:0}
.ai-src-t{font-size:12.5px;font-weight:800;color:var(--green)}
.ai-src-n{font-size:11.5px;color:var(--ok);line-height:1.45;margin:3px 0 8px}
/* ----- Entregarle el archivo a la IA: arrastrarlo, tocarlo o pegarlo -----
   El archivo entraba solo por el selector nativo, así que un diseño que el cliente manda
   por WhatsApp había que bajarlo al disco primero y después ir a buscarlo a la carpeta de
   descargas. El recuadro punteado es lo que dice «suéltalo aquí»; el arrastre se acepta en
   todo el modal, pero lo que se resalta es esto, para que se vea dónde va a caer. */
#ai-file-fld{position:relative}
.ai-drop{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;
  padding:20px 16px;border:2px dashed var(--a-borde);border-radius:var(--r-sm);
  background:var(--soft);cursor:pointer;text-align:center;transition:border-color .12s,background .12s,box-shadow .12s}
.ai-drop:hover{border-color:var(--brand);background:var(--a-suave)}
.ai-drop:focus-visible{outline:3px solid var(--brand);outline-offset:2px}
.ai-drop.sobre{border-color:var(--brand);border-style:solid;background:var(--a-suave);box-shadow:0 0 0 4px rgba(var(--a-rgb),.16)}
.ai-drop .ico{font-size:26px;color:var(--brand)}
.ai-drop .t{font-size:13.5px;font-weight:800;color:var(--n7)}
.ai-drop .s{font-size:11.5px;color:var(--muted);line-height:1.5}
/* En un celular no hay nada que arrastrar, así que el recuadro dice ahí lo que ahí sí se
   puede hacer. Se elige por tipo de puntero y no por ancho de pantalla, igual que el resto
   de la hoja: el mismo archivo abierto en la laptop sigue diciendo «arrastra». */
.ai-drop .solo-dedo{display:none}
.ai-drop>*{pointer-events:none}
/* El <input type=file> sigue ahí y sigue siendo el que abre la galería del celular: lo que
   se le quita es la caja, porque el recuadro de arriba ya es su botón. No se oculta con
   display:none para que el navegador lo siga tomando por un control de verdad. */
.ai-file-in{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
/* El archivo ya elegido. El selector nativo lo decía con su propio texto gris; con el
   recuadro ese texto ya no está, y analizar a ciegas es justo el error que cuesta una
   llamada a la API y el viaje de vuelta. */
.ai-pick{display:flex;gap:10px;align-items:center;background:var(--green-bg);border:1.5px solid rgba(var(--ok-rgb),.28);border-radius:var(--r-sm);padding:9px 11px;margin-top:9px}
.ai-pick-img{width:52px;height:52px;object-fit:contain;border-radius:8px;border:1px solid rgba(var(--ok-rgb),.25);background:var(--sup);flex-shrink:0;padding:2px}
.ai-pick-ph{width:52px;height:52px;display:flex;align-items:center;justify-content:center;border-radius:8px;border:1.5px dashed var(--red);background:var(--red-bg);color:var(--red);flex-shrink:0;font-size:20px}
.ai-pick-b{flex:1;min-width:0}
.ai-pick-n{font-size:12.5px;font-weight:800;color:var(--green);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ai-pick-m{font-size:11.5px;color:var(--ok);margin-top:2px}
.ai-pick-x{border:none;background:none;color:var(--ok);font-size:18px;line-height:1;cursor:pointer;padding:3px 7px;border-radius:6px;flex-shrink:0;font-family:inherit}
.ai-pick-x:hover{color:var(--red);background:var(--red-bg)}
/* Con el archivo encima del modal, el modal entero se anuncia como destino: quien suelta
   ve que la ventana correcta es la que va a recibirlo. */
#aimodal.arrastrando .modal{box-shadow:0 0 0 3px var(--brand),0 24px 60px rgba(var(--tinta-rgb),.28)}
/* Segunda entrada a lo mismo, desde la vista previa que queda junto a las partidas */
.sc-prev-ia{width:100%;margin-top:9px;padding:9px 12px;border:none;border-radius:var(--r-sm);background:var(--brand-grd);color:#fff;font-size:12.5px;font-weight:800;font-family:inherit;cursor:pointer;box-shadow:0 2px 10px rgba(var(--a-rgb),.25)}
.sc-prev-ia:hover{filter:brightness(1.06)}
.ai-prev-big{border:1px solid var(--line);border-radius:var(--r-sm);background:var(--soft);padding:12px;margin-bottom:14px}
.ai-prev-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:9px}
.ai-prev-head .ttl{font-size:11.5px;font-weight:700;color:var(--brand);line-height:1.4}
.ai-prev-head .x{border:none;background:none;color:var(--n5);font-size:18px;cursor:pointer;line-height:1;padding:2px 6px;border-radius:6px;flex-shrink:0;transition:.12s}
.ai-prev-head .x:hover{color:var(--red);background:var(--red-bg)}
.ai-prev-img{display:block;width:100%;max-height:440px;object-fit:contain;border-radius:9px;border:1px solid var(--line);background:repeating-conic-gradient(var(--n1) 0% 25%,var(--sup) 0% 50%) 50%/16px 16px;cursor:zoom-in}
.ai-prev-pdf{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;height:130px;border-radius:9px;border:1.5px dashed var(--red);background:var(--red-bg);color:var(--red);font-weight:700;font-size:13px;cursor:pointer;text-align:center;padding:10px}
.ai-prev-big .sub{font-size:11px;color:var(--muted);margin-top:8px;text-align:center}
/* ----- Vista previa de la imagen del escalador, junto a las partidas ----- */
.sc-prev-box{border:1px solid var(--line);border-radius:var(--r-sm);background:var(--soft);padding:12px;margin-bottom:16px}
.sc-prev-head{display:flex;align-items:center;justify-content:space-between;gap:10px;cursor:pointer;user-select:none}
.sc-prev-head .ttl{font-size:11.5px;font-weight:700;color:var(--brand);line-height:1.4}
.sc-prev-head .chev{font-size:11px;font-weight:700;color:var(--muted);white-space:nowrap;flex-shrink:0}
.sc-prev-img{display:block;width:100%;height:auto;max-height:420px;margin-top:9px;border-radius:9px;border:1px solid var(--line);background:repeating-conic-gradient(var(--n1) 0% 25%,var(--sup) 0% 50%) 50%/16px 16px;cursor:pointer;object-fit:contain}
.sc-prev-box .sub{font-size:11px;color:var(--muted);margin-top:8px;text-align:center}
.lightbox-close{position:fixed;top:max(20px,calc(env(safe-area-inset-top,0px) + 8px));right:max(24px,calc(env(safe-area-inset-right,0px) + 8px));width:42px;height:42px;border-radius:50%;background:rgba(255,255,255,.15);border:none;color:#fff;font-size:24px;cursor:pointer;display:flex;align-items:center;justify-content:center;z-index:70;transition:.12s}
.lightbox-close:hover{background:rgba(255,255,255,.28)}
.lightbox-img{max-width:calc(100vw - 36px - env(safe-area-inset-left,0px) - env(safe-area-inset-right,0px));max-height:calc(100dvh - 36px - env(safe-area-inset-top,0px) - env(safe-area-inset-bottom,0px));border-radius:8px;box-shadow:0 20px 60px rgba(0,0,0,.5);display:block}
.lightbox-iframe{width:min(88vw,calc(100vw - 36px));height:calc(100dvh - 36px - env(safe-area-inset-top,0px) - env(safe-area-inset-bottom,0px));border:0;border-radius:8px;background:#fff}
/* ----- Historial ----- */
/* El control de la barra de arriba: 36 px, borde de 1 px, radio de 4 y la SEGUNDA tinta.
   Era una píldora de 10 px de radio con la letra en azul y en 700, y en esa barra hay cuatro
   seguidos —Deshacer, Clientes, Historial, el tema— más el enlace a la plataforma: cinco
   veces el color que en esta app significa «esta es LA acción». Con borde y tinta neutra, el
   azul de la barra queda para el enlace a la plataforma, que es el único destino. */
.btn-hist{display:inline-flex;align-items:center;gap:var(--e2);
  min-height:36px;padding:0 12px;
  background:var(--sup);border:1px solid var(--linea);border-radius:var(--rr2);
  font-size:var(--t2);font-weight:500;color:var(--tinta2);
  cursor:pointer;transition:border-color var(--mv-s),color var(--mv-s);white-space:nowrap}
.btn-hist:hover{border-color:var(--a-borde);color:var(--tinta);background:var(--sup)}
.btn-hist .svgi{width:var(--ico1);height:var(--ico1)}
/* ----- Deshacer, junto al historial -----
   Comparte clase con el botón del historial para heredar su relieve, su hover y su
   pulsación: son dos controles del mismo rango en la misma barra, y darles estilo aparte es
   la manera de que en la siguiente pasada se vean distintos sin que nadie lo decidiera.
   Lo que agrega esta clase es que DESAPARECE cuando no hay nada que deshacer. Es la misma
   regla que ya sigue el resto de la app: un botón que se queda a la vista para negarse
   sigue diciendo «esto ya se puede». Va después de las media queries de la barra a
   propósito: con la misma especificidad, el que manda es el último. */
/* ----- Solo el icono, en todos los anchos -----
   En esta barra ya conviven Clientes, Historial y Plataforma, cada uno con su palabra, más el
   folio y el selector de rol. Medido: con «Deshacer» escrito la fila se parte a 921 y a
   960 px —la barra fija pasa de 64 a 116— y la palabra solo cabe de 1000 px para arriba.
   Solo el icono cabe en TODOS los anchos, así que se queda el icono y no un umbral más que
   volver a ajustar la próxima vez que alguien agregue un botón aquí; que es exactamente lo
   que acaba de pasar dos veces.
   Y no es un consuelo: la flecha que vuelve es de los pocos iconos que se leen sin etiqueta
   —está en todos los editores del mundo—, mientras que Clientes, Historial y Plataforma son
   destinos y sí necesitan su palabra para distinguirse. El nombre completo, con el atajo, va
   en el title y en el aria-label. */
.btn-undo{padding:0;width:36px;font-size:16px;display:inline-flex;align-items:center;justify-content:center}
.btn-undo .lbl{display:none}
.btn-undo.oculto{display:none}
/* ----- Por qué deshacer NO vive arriba en el teléfono -----
   Se midió: a 375 px la fila de controles ya va con 8 px de sobra —folio 73, selector de rol
   178 de contenido mínimo, Historial 42— y 42 px más la partían, dejando la barra fija en
   158 px en vez de 111 en un iPhone SE, un 13 mini y un 15 Pro. Y peor que el alto: como el
   botón aparece y desaparece según haya algo que deshacer, la pantalla habría dado un salto
   de 47 px en cada cambio. Recortar píxeles del folio, del rol y de los dos botones daba los
   ocho justos y se rompía con la siguiente etiqueta que creciera.
   Así que en el teléfono deshacer se va a la barra de abajo, que es donde esta app ya pone
   «lo que sigue» y donde hay lugar de sobra. No es un consuelo: en una pantalla que se
   sostiene con una mano, el pulgar llega abajo y no arriba. El corte es el mismo en el que
   aparece esa barra, así que el botón existe exactamente en un lugar a cada ancho. */
@media(max-width:920px){ .topbar-in .btn-undo{display:none} }
/* El enlace a la plataforma es un <a> para que se pueda abrir en otra pestaña y para que el
   lector de pantalla lo anuncie como lo que es. Pero el navegador le pone su subrayado y su
   azul de enlace con a:link, que es más específico que .btn-hist: sin esto, dos controles
   que hacen lo mismo se ven distintos y el de la derecha parece de otra app. */
/* Y es el ÚNICO azul de esta barra: los demás controles bajan a tinta neutra con su borde,
   así que el azul vuelve a significar «esto lleva a otro sitio». */
a.btn-hist,a.btn-hist:visited{text-decoration:none;color:var(--a-tx);border-color:var(--a-borde)}
a.btn-hist:hover{background:var(--a-suave);border-color:var(--a);color:var(--a-tx)}
.hist-panel{background:var(--sup);border-radius:var(--rr3);max-width:720px;width:100%;display:flex;flex-direction:column;overflow:hidden;
  max-height:calc(100dvh - 36px - env(safe-area-inset-top,0px) - env(safe-area-inset-bottom,0px))}
.hist-head{display:flex;align-items:center;justify-content:space-between;padding:16px 20px;border-bottom:1px solid var(--line);background:var(--sup);border-radius:var(--rr3) var(--rr3) 0 0;flex-shrink:0}
/* Cerrar el historial. El tamaño venía de un style= en línea de 32×32 px que ninguna
   hoja podía subir; como clase sí la alcanza el bloque de puntero grueso del final. */
.hist-close{border:none;background:none;font-size:19px;color:var(--muted);cursor:pointer;
  line-height:1;width:36px;height:36px;border-radius:var(--rr1);display:flex;align-items:center;
  justify-content:center;flex:0 0 auto;padding:0}
.hist-close:active{background:var(--soft-2)}
.hist-search-bar{display:flex;align-items:center;gap:10px;padding:11px 20px;border-bottom:1px solid var(--line);flex-shrink:0;background:var(--sup)}
.hist-search-bar input{flex:1;min-width:0}
.hist-count{font-size:11px;font-weight:800;color:var(--a-fuerte);background:var(--soft-2);border:1px solid rgba(var(--a-rgb),.12);padding:5px 12px;border-radius:20px;white-space:nowrap}
.hist-body{overflow-y:auto;flex:1}
.hentry-acts{display:flex;flex-direction:column;gap:5px;align-self:flex-start;flex-shrink:0}
.hentry-open{border:1.5px solid var(--line);background:var(--sup);color:var(--brand);font-family:inherit;font-size:11.5px;font-weight:700;padding:6px 11px;border-radius:var(--rr1);cursor:pointer;white-space:nowrap;transition:.12s}
.hentry-open:hover{border-color:var(--brand);background:var(--soft-2)}
.hist-empty{text-align:center;color:var(--muted);font-size:13px;padding:50px 20px}
.hentry{border-bottom:1px solid var(--line);padding:18px 20px}
.hentry:last-child{border-bottom:none}
.hentry-top{display:flex;align-items:flex-start;gap:13px;margin-bottom:12px}
.hentry-img{width:96px;height:96px;object-fit:cover;border-radius:11px;border:1px solid var(--line);cursor:zoom-in;flex-shrink:0;background:repeating-conic-gradient(var(--n1) 0% 25%,var(--sup) 0% 50%) 50%/12px 12px}
.hentry-img-ph{width:96px;height:96px;border-radius:11px;border:1.5px dashed var(--line);background:var(--soft);display:flex;align-items:center;justify-content:center;color:var(--muted);font-size:30px;flex-shrink:0}
.hentry-meta{flex:1;min-width:0}
.hentry-folio{font-size:10px;font-weight:800;color:var(--brand);letter-spacing:.5px;text-transform:uppercase}
.hentry-name{font-size:14px;font-weight:800;color:var(--ink);margin:3px 0 2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hentry-sub{font-size:11.5px;color:var(--muted);line-height:1.6}
.hentry-auth{display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:700;background:var(--green-bg);color:var(--green);padding:3px 11px;border-radius:20px;margin-top:6px}
.hentry-del{border:none;background:none;color:var(--n5);cursor:pointer;font-size:16px;padding:5px 7px;border-radius:9px;transition:.12s;align-self:flex-start;flex-shrink:0}
.hentry-del:hover{color:var(--red);background:var(--red-bg)}
.htable{width:100%;border-collapse:collapse;font-size:11.5px;margin-bottom:10px}
.htable td{padding:5px 7px;border-bottom:1px solid var(--line);color:var(--n7);vertical-align:top}
.htable td:first-child{width:28px;font-weight:800;color:var(--brand);text-align:center}
.htable td:last-child{text-align:right;font-weight:700;color:var(--ink);white-space:nowrap}
.htable tr:last-child td{border-bottom:none}
.hentry-total{display:flex;justify-content:space-between;align-items:center;font-size:13px;font-weight:800;padding:9px 7px 0;border-top:1.5px solid var(--line);color:var(--ink)}

/* ----- Cuadernos de cliente -----
   Reaprovechan la caja del historial (.hist-panel, .hist-head, .hist-body): es el mismo
   gesto —abrir una libreta encima del cotizador— y dos cajas distintas para lo mismo se
   ven como dos apps. Lo que cambia es lo de adentro. */
.cua-card{display:flex;align-items:center;gap:13px;width:100%;text-align:left;border:none;background:none;font-family:inherit;
  border-bottom:1px solid var(--line);padding:15px 20px;cursor:pointer;transition:.12s}
.cua-card:last-child{border-bottom:none}
.cua-card:hover{background:var(--soft)}
.cua-ini{display:flex;width:42px;height:42px;flex-shrink:0;border-radius:12px;background:var(--soft-2);color:var(--a-fuerte);
  display:flex;align-items:center;justify-content:center;font-size:15px;font-weight:800;letter-spacing:.5px}
.cua-card-meta{display:block;flex:1;min-width:0}
.cua-nombre{display:block;font-size:14px;font-weight:800;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cua-sub{display:block;font-size:11.5px;color:var(--muted);line-height:1.55;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cua-card-num{text-align:right;flex-shrink:0}
.cua-card-num b{display:block;font-size:13px;font-weight:800;color:var(--green)}
.cua-card-num span{display:block;font-size:10.5px;color:var(--muted);font-weight:600}
.cua-flecha{color:var(--muted);flex-shrink:0;font-size:15px}

/* Ficha de un cliente */
.cua-det-head{padding:17px 20px;border-bottom:1px solid var(--line);background:var(--soft)}
.cua-volver{border:none;background:none;font-family:inherit;font-size:11.5px;font-weight:700;color:var(--brand);
  cursor:pointer;padding:4px 0;margin-bottom:9px;display:inline-flex;align-items:center;gap:6px}
.cua-volver:hover{text-decoration:underline}
.cua-det-nom{font-size:17px;font-weight:800;color:var(--ink);line-height:1.25}
.cua-det-datos{font-size:12px;color:var(--muted);line-height:1.65;margin-top:5px}
.cua-alias{font-size:11px;color:var(--muted);margin-top:4px;font-style:italic}
.cua-det-acts{display:flex;gap:7px;flex-wrap:wrap;margin-top:11px}
.cua-det-acts button{border:1.5px solid var(--line);background:var(--sup);color:var(--brand);font-family:inherit;font-size:11.5px;
  font-weight:700;padding:7px 12px;border-radius:var(--rr1);cursor:pointer;white-space:nowrap;transition:.12s}
.cua-det-acts button:hover{border-color:var(--brand);background:var(--soft-2)}
.cua-cifras{display:flex;gap:9px;padding:13px 20px;border-bottom:1px solid var(--line);flex-wrap:wrap}
.cua-cifra{flex:1;min-width:96px;background:var(--soft);border:1px solid var(--line);border-radius:var(--rr1);padding:9px 11px}
.cua-cifra b{display:block;font-size:15px;font-weight:800;color:var(--ink);line-height:1.2}
.cua-cifra span{font-size:10px;color:var(--muted);font-weight:700;text-transform:uppercase;letter-spacing:.4px}
.cua-nota-wrap{padding:14px 20px;border-bottom:1px solid var(--line)}
.cua-nota-wrap label{display:block;font-size:11px;font-weight:800;color:var(--muted);text-transform:uppercase;letter-spacing:.4px;margin-bottom:6px}
.cua-nota-wrap textarea{width:100%;min-height:70px;resize:vertical}
.cua-nota-estado{font-size:10.5px;color:var(--muted);margin-top:5px;min-height:14px}
.cua-cots-tit{font-size:11px;font-weight:800;color:var(--muted);text-transform:uppercase;letter-spacing:.4px;padding:14px 20px 0}
.cua-cot{display:flex;align-items:center;gap:11px;padding:12px 20px;border-bottom:1px solid var(--line)}
.cua-cot:last-child{border-bottom:none}
.cua-cot-meta{flex:1;min-width:0}
.cua-cot-folio{font-size:10px;font-weight:800;color:var(--brand);letter-spacing:.5px;text-transform:uppercase}
.cua-cot-proy{font-size:13px;font-weight:700;color:var(--ink);margin:1px 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cua-cot-fecha{font-size:11px;color:var(--muted)}
.cua-cot-tot{font-size:13px;font-weight:800;color:var(--green);white-space:nowrap;flex-shrink:0}
.cua-cot-acts{display:flex;gap:5px;flex-shrink:0}
.cua-cot-acts button{border:1.5px solid var(--line);background:var(--sup);color:var(--brand);font-family:inherit;font-size:11px;
  font-weight:700;padding:6px 9px;border-radius:var(--rr1);cursor:pointer;white-space:nowrap;transition:.12s}
.cua-cot-acts button:hover{border-color:var(--brand);background:var(--soft-2)}

/* El aviso que sale bajo el campo Cliente cuando el que se está capturando ya tiene cuaderno */
.cua-aviso{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:0 0 13px;padding:8px 11px;border-radius:var(--rr1);
  background:var(--soft-2);border:1px solid rgba(var(--a-rgb),.14);font-size:11.5px;color:var(--a-fuerte);line-height:1.45}
.cua-aviso button{border:none;background:none;font-family:inherit;font-size:11.5px;font-weight:800;color:var(--brand);
  cursor:pointer;padding:0;text-decoration:underline;white-space:nowrap}
/* ----- Dirección raw del cliente ----- */
.dir-raw-actions{display:flex;gap:8px;margin-top:7px}
.btn-maps{flex:1;padding:8px 10px;border:1.5px solid var(--line);border-radius:var(--r-sm);background:var(--sup);color:var(--brand);font-size:12px;font-weight:700;cursor:pointer;transition:.15s;display:flex;align-items:center;justify-content:center;gap:5px}
.btn-maps:hover{border-color:var(--brand);background:var(--soft-2)}
.btn-maps.copy{color:var(--green);border-color:rgba(var(--ok-rgb),.25)}.btn-maps.copy:hover{background:var(--green-bg);border-color:var(--green)}
/* ----- AI preview en sidebar ----- */
.side #aiPreview:not(:empty){margin-bottom:14px}
.side .ai-prev-big{border-radius:var(--r);overflow:hidden;box-shadow:var(--sh)}
.side .ai-prev-img{max-height:220px;cursor:zoom-in}
.side .ai-prev-head .ttl{font-size:10.5px}
/* ----- Input monetario con prefijo $ ----- */
.inp-money{position:relative;display:block}
.inp-money::before{content:'$';position:absolute;left:12px;top:50%;transform:translateY(-50%);color:var(--muted);font-weight:700;font-size:13px;pointer-events:none;z-index:1}
.inp-money input{padding-left:26px}
/* ----- Auth por partida ----- */
.ia-row{border:1px solid var(--line);border-radius:8px;margin-bottom:5px;overflow:hidden;background:var(--sup)}
.ia-hdr{display:flex;align-items:center;gap:7px;padding:8px 10px;cursor:pointer;user-select:none;transition:.1s}
.ia-hdr:hover{background:var(--soft)}
.ia-num{width:20px;height:20px;border-radius:6px;background:var(--brand-grd);color:#fff;font-size:10px;font-weight:800;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.ia-desc{flex:1;font-size:11px;font-weight:600;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.ia-calc{font-size:10.5px;color:var(--muted);white-space:nowrap;font-weight:600}
.ia-arrow{font-size:11px;color:var(--brand);flex-shrink:0}
.ia-body{padding:9px 10px 10px;border-top:1px solid var(--line);background:var(--soft)}
.ia-adj{font-size:11px;color:var(--green);font-weight:600;margin-top:4px;min-height:14px}
.ia-adj.inc{color:var(--amber)}
.ia-total{display:flex;justify-content:space-between;align-items:center;font-size:12px;font-weight:700;padding:8px 10px;background:var(--soft-2);border-radius:8px;margin-top:6px;border:1px solid var(--line);margin-bottom:10px}
.ia-total.soft{background:var(--sup);color:var(--brand);margin-top:-5px}
/* ----- Barra de progreso ----- */
/* La barra de completitud es un botón: decía cuánto falta pero no qué, y ahora lleva a
   lo primero pendiente. Se conserva el aspecto que ya tenía de bloque, no de botón. */
.prog-box{display:block;width:100%;padding:10px 20px 13px;border:none;border-bottom:1px solid var(--line);background:none;font-family:inherit;text-align:left;cursor:pointer;transition:background .14s}
.prog-box:hover{background:var(--soft)}
.prog-box:disabled{cursor:default;background:none}
.prog-next{font-size:11px;color:var(--brand);font-weight:700;margin-top:6px;display:flex;align-items:center;gap:5px}
.prog-next:empty{display:none}
.prog-label{display:flex;justify-content:space-between;align-items:center;margin-bottom:5px}
.prog-label span:first-child{font-size:var(--t2);font-weight:500;color:var(--n6)}
#prog-pct{font-size:12.5px;font-weight:900;color:var(--brand)}
.prog-track{height:7px;background:var(--line);border-radius:10px;overflow:hidden}
#prog-bar{height:100%;background:linear-gradient(90deg,#f59e0b,#fb923c);border-radius:10px;transition:width .5s cubic-bezier(.22,1,.36,1),background .5s;width:0%}
/* ----- Escalador Pro (modal pantalla completa) ----- */
/* 100dvh además de inset: en el celular la barra de direcciones cambia de alto y con
   solo inset:0 el pie del panel quedaba fuera de la pantalla, sin manera de volver. */
.scaler-modal-bg{position:fixed;inset:0;height:100dvh;background:rgba(12,15,38,.75);display:none;z-index:55;flex-direction:column;backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);overscroll-behavior:contain}
.scaler-modal-bg.show{display:flex}
.sp-topbar{background:rgba(var(--sup-rgb),.96);backdrop-filter:blur(14px);border-bottom:1px solid rgba(var(--n3-rgb),.7);flex-shrink:0;padding:0 20px;height:56px;display:flex;align-items:center;gap:12px;box-shadow:0 1px 8px rgba(var(--tinta-rgb),.06)}
.sp-main{flex:1;display:flex;overflow:hidden;min-height:0}
.sp-canvas-area{flex:1;position:relative;overflow:hidden;background:#181c2e;background-image:radial-gradient(rgba(255,255,255,.04) 1px,transparent 1px);background-size:22px 22px;display:flex;align-items:center;justify-content:center;min-width:0;touch-action:none;overscroll-behavior:contain}
/* El lienzo cubre toda el área: el zoom se aplica dentro del canvas, no con transform
   de CSS, para dibujar siempre a la densidad real de la pantalla. La sombra de la foto
   se dibuja dentro del propio lienzo. */
#scalerCanvas{position:absolute;inset:0;display:block;cursor:crosshair;touch-action:none;user-select:none;-webkit-user-select:none}
.sp-overlay{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;pointer-events:none}
.sp-overlay.hide{display:none}
/* pointer-events:none: la barra ocupa los 58 px de abajo del lienzo y se estaba
   quedando con los toques de esa franja —justo el borde inferior de la foto, que es
   donde se mide el alto de unas letras—. El botón de dentro sí los recibe. */
.sp-hint-bar{position:absolute;bottom:0;left:0;right:0;background:rgba(17,22,46,.78);color:rgba(255,255,255,.9);font-size:12.5px;font-weight:600;padding:10px 20px;text-align:center;backdrop-filter:blur(8px);transition:opacity .2s;display:flex;align-items:center;justify-content:center;gap:12px;pointer-events:none;
  padding-bottom:calc(10px + env(safe-area-inset-bottom,0px))}
.sp-hint-bar>*{pointer-events:auto}
.sp-hint-bar.hide{opacity:0;pointer-events:none}
.sp-hint-act{border:1px solid rgba(255,255,255,.35);background:rgba(255,255,255,.14);color:#fff;border-radius:9px;padding:7px 13px;font-size:12px;font-weight:700;cursor:pointer;font-family:inherit;flex-shrink:0;white-space:nowrap}
.sp-hint-act:active{background:rgba(255,255,255,.3)}
/* overflow-y:auto y no hidden: con una pantalla ancha y baja —el Fold 6 abierto tiene
   716 px de alto— el contenido del panel no cabe y con `hidden` se recortaba sin manera
   de llegar al final. */
.sp-side{width:306px;flex-shrink:0;background:var(--sup);border-left:1px solid var(--line);display:flex;flex-direction:column;overflow-x:hidden;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;box-shadow:-2px 0 12px rgba(var(--tinta-rgb),.04)}
.sp-sec{border-bottom:1px solid var(--line)}
.sp-sec-h{padding:16px 20px 0}
.sp-sec-h h3{font-size:10.5px;font-weight:800;text-transform:uppercase;letter-spacing:.9px;color:var(--brand);display:flex;align-items:center;gap:8px}
.sp-sec-h h3::before{content:'';display:inline-block;width:3px;height:14px;background:var(--brand-grd);border-radius:2px;flex-shrink:0}
.sp-sec-b{padding:14px 20px 18px}
.sp-mlist{flex:1;overflow-y:auto;min-height:0;padding:10px 14px 8px}
.sp-mlist-empty{text-align:center;color:var(--muted);font-size:13px;padding:28px 12px;line-height:1.7;border:1.5px dashed var(--line);border-radius:var(--r-sm);background:var(--soft);margin-top:2px}
.sp-mitem{border:1px solid rgba(var(--n3-rgb),.8);border-left:3px solid var(--brand);border-radius:var(--r-sm);padding:12px 11px;margin-bottom:9px;background:var(--sup);box-shadow:var(--sh-sm);display:flex;align-items:stretch;gap:9px;cursor:pointer;transition:box-shadow .15s}
.sp-mitem:hover{box-shadow:0 2px 8px rgba(var(--tinta-rgb),.06),0 8px 28px rgba(var(--tinta-rgb),.1)}
.sp-mitem.sel{border-color:var(--brand-strong);background:var(--soft-2);box-shadow:0 0 0 3px rgba(var(--a-rgb),.12)}
.sp-mitem-cm{font-size:17px;font-weight:900;color:var(--brand-strong);line-height:1;letter-spacing:.1px;font-variant-numeric:tabular-nums}
.sp-mitem-cm small{font-size:11px;font-weight:600;color:var(--muted);margin-left:2px}
.sp-mitem-label{display:block;width:100%;border:none;background:transparent;padding:3px 0;font-size:12px;color:var(--ink);font-family:inherit;cursor:text;margin-top:4px;outline:none;border-bottom:1px solid transparent;transition:.15s}
.sp-mitem-label:focus{color:var(--ink);border-bottom-color:var(--line)}
.sp-mitem-label::placeholder{color:var(--n5)}
.sp-mitem-actions{display:flex;flex-direction:column;gap:4px;flex-shrink:0;padding-top:2px}
.sp-mitem-add{margin-top:8px;width:100%;padding:7px 10px;background:var(--brand-grd);color:#fff;border:none;border-radius:8px;font-size:12px;font-weight:700;cursor:pointer;font-family:inherit;display:flex;align-items:center;justify-content:center;gap:5px}
.sp-mitem-add.done{background:var(--green-bg);color:var(--green);border:1px solid rgba(var(--ok-rgb),.25);font-weight:600}
.sp-addall{margin:0 14px 10px;padding:9px 12px;width:calc(100% - 28px);border:1.5px solid var(--brand);border-radius:var(--r-sm);background:var(--soft-2);color:var(--brand-strong);font-size:12.5px;font-weight:800;font-family:inherit;cursor:pointer;transition:.15s}
.sp-addall:hover{background:var(--a-suave)}
.sp-addall:disabled{opacity:.45;cursor:default}
.sp-addall-note{margin:0 14px 10px;font-size:11.5px;color:var(--green);font-weight:700;text-align:center}
/* Del escalador a la IA: la otra salida de las medidas, la que devuelve la partida
   completa en vez de solo su altura. */
.sp-ai{margin:0 14px 7px;padding:9px 12px;width:calc(100% - 28px);border:none;border-radius:var(--r-sm);background:var(--brand-grd);color:#fff;font-size:12.5px;font-weight:800;font-family:inherit;cursor:pointer;box-shadow:0 2px 10px rgba(var(--a-rgb),.25);transition:.15s}
.sp-ai:hover{filter:brightness(1.06)}
.sp-ai:disabled{opacity:.45;cursor:default;box-shadow:none}
.sp-ai-note{margin:0 14px 10px;font-size:11px;color:var(--muted);line-height:1.45;text-align:center}
/* Volver al cotizador desde el pie del panel: en el celular es el botón que se queda
   pegado abajo, siempre a la vista aunque la lista de medidas crezca. */
.sp-back-m{display:none}
.sp-ibtn{border:none;background:none;color:var(--n5);font-size:15px;cursor:pointer;padding:3px 6px;border-radius:6px;line-height:1;transition:.12s}
.sp-ibtn:hover{color:var(--red);background:var(--red-bg)}
/* ----- Secciones plegables del panel -----
   El panel del escalador es una columna de 412 px visibles en el teléfono y su
   contenido medía 1617 px: Calibración (206 px) y Guías (452 px) iban antes de las
   medidas, así que la primera cota quedaba a 466 px de desplazamiento —invisible—.
   Plegadas ocupan su encabezado y la lista de medidas queda a la vista de entrada. */
.sp-fold>summary{list-style:none;cursor:pointer;display:flex;align-items:center;gap:9px;
  padding:13px 20px;min-height:46px;user-select:none;-webkit-tap-highlight-color:transparent}
.sp-fold>summary::-webkit-details-marker{display:none}
.sp-fold>summary::marker{content:''}
.sp-fold>summary h3{flex:1;min-width:0}
.sp-fold>summary::after{content:'▾';font-size:11px;font-weight:700;color:var(--muted);
  flex-shrink:0;transition:transform .18s}
.sp-fold[open]>summary::after{transform:rotate(180deg)}
.sp-fold>summary:active{background:var(--soft)}
.sp-fold[open]>summary{padding-bottom:0}
.sp-fold .sp-sec-b{padding-top:12px}
/* Cuántas guías hay, para no tener que desplegar la sección para saberlo */
.sp-fold-n{font-size:11px;font-weight:800;color:var(--brand);background:var(--soft-2);
  border:1px solid rgba(var(--a-rgb),.12);border-radius:20px;padding:2px 9px;flex-shrink:0}
.sp-fold-n:empty{display:none}
/* ----- Guías del escalador ----- */
.sp-gitem{display:flex;align-items:center;gap:8px;padding:8px 10px;margin-bottom:6px;border:1px solid rgba(var(--n3-rgb),.8);border-left:3px solid var(--sc-guide);border-radius:var(--r-sm);background:var(--sup);font-size:12.5px}
.sp-gitem .ico{color:var(--sc-guide);width:16px;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:15px}
.sp-gitem .lbl{flex:1;color:var(--ink);font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sp-gclear{display:block;width:100%;margin-top:2px;padding:6px;border:none;background:none;color:var(--muted);font-size:11.5px;font-weight:600;font-family:inherit;cursor:pointer;border-radius:7px;transition:.12s}
.sp-gclear:hover{color:var(--red);background:var(--red-bg)}
.sp-calib-badge{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;font-weight:700;padding:6px 12px;border-radius:20px;white-space:nowrap;flex-shrink:0;background:var(--amber-bg);color:var(--amber);border:1px solid rgba(var(--av-rgb),.2)}
.sp-calib-badge.ok{background:var(--green-bg);color:var(--green);border-color:rgba(var(--ok-rgb),.2)}
.sp-calib-badge .dot{width:7px;height:7px;border-radius:50%;background:currentColor;flex-shrink:0}
.tool-seg{display:inline-flex;background:var(--soft);border:1px solid var(--line);border-radius:var(--r-sm);padding:3px;gap:2px}
.tool-seg button{border:none;background:none;padding:7px 13px;font-size:12.5px;font-weight:600;color:var(--muted);border-radius:9px;cursor:pointer;transition:.15s;font-family:inherit;white-space:nowrap}
.tool-seg button:hover:not(.active){background:rgba(var(--a-rgb),.06);color:var(--brand)}
.tool-seg button.active{background:var(--brand-grd);color:#fff;box-shadow:0 2px 10px rgba(var(--a-rgb),.3)}
.tool-seg button:disabled{opacity:.38;pointer-events:none}
.sp-tb-btn{border:1.5px solid var(--line);background:var(--sup);border-radius:var(--r-sm);padding:8px 14px;font-size:13px;font-weight:700;color:var(--ink);cursor:pointer;transition:.14s;display:flex;align-items:center;gap:6px;white-space:nowrap;font-family:inherit}
.sp-tb-btn:hover{border-color:var(--brand);color:var(--brand);background:var(--soft)}
.sp-tb-btn.active{background:var(--brand-grd);color:#fff;border-color:var(--brand);box-shadow:0 2px 10px rgba(var(--a-rgb),.28)}
.sp-tb-btn:disabled{opacity:.42;cursor:not-allowed;pointer-events:none}
/* Salida del escalador. En el celular deja de ser una × suelta y se vuelve un botón
   con texto: es la manera obvia de regresar al cotizador. */
.sp-close{border:none;background:none;color:var(--muted);cursor:pointer;line-height:1;width:36px;height:36px;border-radius:9px;display:flex;align-items:center;justify-content:center;gap:6px;flex-shrink:0;transition:.12s;font-family:inherit}
.sp-close:hover{background:var(--soft);color:var(--ink)}
.sp-close .ico{font-size:19px;line-height:1;display:flex}
.sp-close .back,.sp-close .lbl{display:none}
.btn-scaler-open{display:flex;align-items:center;justify-content:center;gap:var(--e2);padding:10px 14px;border:1px solid var(--n3);border-radius:var(--rr1);background:var(--sup);color:var(--n7);font-size:var(--t2);font-weight:500;cursor:pointer;transition:border-color .12s,background .12s;white-space:nowrap}
.btn-scaler-open:hover{background:var(--ok-bg);border-color:var(--ok)}
.scaler-ai-row{display:flex;gap:8px;margin-bottom:14px}
.scaler-ai-row .ai-btn{flex:1;margin-bottom:0}
.sc-flash{animation:scFlash 1.5s ease-out 1}
@keyframes scFlash{0%,55%{box-shadow:0 0 0 3px rgba(var(--a-rgb),.35);border-radius:var(--r-sm)}100%{box-shadow:0 0 0 3px rgba(var(--a-rgb),0);border-radius:var(--r-sm)}}
.ref-known{display:flex;flex-wrap:wrap;gap:5px;align-items:center;margin-bottom:8px}
.ref-known-title{font-size:11px;font-weight:700;color:var(--muted);margin-right:2px;white-space:nowrap}
.ref-known button{padding:5px 9px;border:1.5px solid var(--line);border-radius:8px;background:var(--sup);font-size:11.5px;font-weight:600;cursor:pointer;color:var(--ink);transition:.12s;white-space:nowrap;font-family:inherit}
.ref-known button:hover{border-color:var(--brand);background:var(--soft-2);color:var(--brand)}
/* ----- Cuánto se enseña de las cotas -----
   El botón vive en la esquina de abajo a la izquierda, a la misma altura que los de zoom
   y en el lado contrario: es el otro mando del lienzo y así ninguno tapa al otro. Toma
   prestada la pinta de los de zoom —mismo tamaño, mismo redondeo, misma sombra— porque
   son la misma familia de botones flotantes sobre la foto.
   Los tres estados se distinguen a un vistazo: claro (todas), azul de marca (solo la
   elegida) y oscuro con el ojo tachado (ninguna). */
.sp-cotas-fab{position:absolute;left:12px;bottom:52px;display:none;z-index:6}
.sp-cotas-fab button{width:42px;height:42px;border:none;border-radius:11px;background:rgba(255,255,255,.95);color:var(--ink);font-size:19px;cursor:pointer;box-shadow:0 3px 14px rgba(0,0,0,.3);display:flex;align-items:center;justify-content:center;line-height:1;font-family:inherit}
.sp-cotas-fab button.foco{background:var(--brand-grd);color:#fff}
.sp-cotas-fab button.off{background:rgba(20,24,44,.92);color:rgba(255,255,255,.78);box-shadow:0 3px 14px rgba(0,0,0,.34),inset 0 0 0 1px rgba(255,255,255,.22)}
.sp-cotas-fab button:active{transform:scale(.94)}
/* El mismo mando en el panel, con los tres modos escritos */
.sp-cotas{padding:10px 14px 11px;border-bottom:1px solid var(--line);background:var(--soft)}
.sp-cotas-lbl{display:block;font-size:11px;font-weight:700;color:var(--muted);margin-bottom:6px}
.sp-cotas .tool-seg{display:flex;width:100%;background:var(--sup)}
.sp-cotas .tool-seg button{flex:1;padding:7px 4px;font-size:11.5px;min-width:0;overflow:hidden;text-overflow:ellipsis}
.sp-cotas .hintnote{margin-top:8px}
.sp-cotas .hintnote.hide{display:none}
/* ----- Zoom / desplazamiento y lupa del escalador ----- */
.sp-zoom{position:absolute;right:12px;bottom:52px;display:none;flex-direction:column;gap:7px;z-index:6}
.sp-zoom button{width:42px;height:42px;border:none;border-radius:11px;background:rgba(255,255,255,.95);color:var(--ink);font-size:20px;font-weight:800;cursor:pointer;box-shadow:0 3px 14px rgba(0,0,0,.3);display:flex;align-items:center;justify-content:center;line-height:1;font-family:inherit}
.sp-zoom button:active{background:var(--a-suave);transform:scale(.94)}
.sp-loupe{position:fixed;width:132px;height:132px;border-radius:50%;border:3px solid rgba(255,255,255,.92);box-shadow:0 6px 26px rgba(0,0,0,.45);display:none;pointer-events:none;z-index:60;overflow:hidden;background:#181c2e}
.sp-loupe canvas{display:block}
/* ===================== Vectorizador =====================
   Reaprovecha el armazón del escalador (.sp-topbar, .sp-main, .sp-canvas-area,
   .sp-side, .sp-sec, .sp-actions): son las mismas piezas y así las reglas de
   celular que ya existen valen para los dos modales sin duplicarlas. Aquí solo
   va lo propio del vectorizador. */
.vt-modal-bg{position:fixed;inset:0;height:100dvh;background:rgba(12,15,38,.75);display:none;z-index:56;flex-direction:column;backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);overscroll-behavior:contain}
.vt-modal-bg.show{display:flex}
.vt-modal-bg .sp-side{width:336px}
.vt-modal-bg .sp-canvas-area{cursor:default}
/* Escenario: original y vector superpuestos al milímetro para poder compararlos.
   El zoom transforma el envoltorio, así que las dos capas se mueven juntas. */
.vt-stage-wrap{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;overflow:hidden}
.vt-stage{position:relative;transform-origin:center center;transition:transform .12s ease-out}
.vt-stage canvas{position:absolute;top:0;left:0;display:block;width:100%;height:100%}
.vt-stage canvas.base{position:relative}
/* Cuadrícula de transparencia: el vector puede salir sin fondo y sin esto no se nota */
.vt-stage{background:repeating-conic-gradient(var(--n3) 0% 25%,#fff 0% 50%) 50%/18px 18px;box-shadow:0 10px 44px rgba(0,0,0,.42)}
#vt-cvs-out{clip-path:inset(0 0 0 0)}
/* Cortina de comparación */
.vt-split{position:absolute;top:0;bottom:0;width:2px;background:rgba(255,255,255,.95);box-shadow:0 0 0 1px rgba(12,15,38,.35);z-index:4;display:none;cursor:ew-resize;touch-action:none}
.vt-split.on{display:block}
.vt-split::after{content:'';position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:38px;height:38px;border-radius:50%;background:#fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232535c4' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.8 12h18.4'/%3E%3Cpath d='M6.6 8.2 2.8 12l3.8 3.8'/%3E%3Cpath d='M17.4 8.2 21.2 12l-3.8 3.8'/%3E%3C/svg%3E") center/19px 19px no-repeat;display:flex;align-items:center;justify-content:center;box-shadow:0 3px 14px rgba(0,0,0,.4)}
.vt-tag{position:absolute;top:10px;font-size:10.5px;font-weight:800;letter-spacing:.7px;text-transform:uppercase;color:#fff;background:rgba(17,22,46,.72);padding:5px 11px;border-radius:20px;z-index:5;pointer-events:none;backdrop-filter:blur(6px)}
.vt-tag.l{left:12px}
.vt-tag.r{right:12px}
.vt-tag.hide{display:none}
/* Progreso del trazado */
.vt-prog{position:absolute;inset:0;display:none;flex-direction:column;align-items:center;justify-content:center;gap:14px;background:rgba(17,22,46,.74);backdrop-filter:blur(3px);z-index:8}
.vt-prog.on{display:flex}
.vt-prog-txt{font-size:13px;font-weight:700;color:#fff;letter-spacing:.3px}
.vt-prog-track{width:min(260px,62%);height:6px;border-radius:4px;background:rgba(255,255,255,.18);overflow:hidden}
.vt-prog-bar{height:100%;width:0;background:var(--a);border-radius:3px;transition:width .2s}
/* Controles del panel */
.vt-row{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:11px}
.vt-row>label{font-size:12.5px;font-weight:600;color:var(--ink);flex:1;min-width:0}
.vt-val{font-size:12px;font-weight:800;color:var(--brand-strong);background:var(--soft-2);border:1px solid rgba(var(--a-rgb),.14);border-radius:20px;padding:2px 10px;min-width:38px;text-align:center;flex-shrink:0}
.vt-modal-bg input[type=range]{width:100%;accent-color:var(--brand);height:26px}
.vt-modo{display:grid;grid-template-columns:repeat(3,1fr);gap:6px}
.vt-modo button{padding:9px 4px;border:1.5px solid var(--line);border-radius:var(--r-sm);background:var(--sup);font-family:inherit;font-size:12px;font-weight:700;color:var(--ink);cursor:pointer;transition:.14s;display:flex;flex-direction:column;align-items:center;gap:3px;line-height:1.25}
.vt-modo button .svgi{font-size:17px}
.vt-modo button small{font-size:9.5px;font-weight:600;color:var(--muted);letter-spacing:.2px}
.vt-modo button:hover{border-color:var(--brand);background:var(--soft)}
.vt-modo button.on{background:var(--brand-grd);color:#fff;border-color:var(--brand);box-shadow:0 2px 10px rgba(var(--a-rgb),.26)}
.vt-modo button.on small{color:rgba(255,255,255,.82)}
.vt-go{width:100%;padding:12px;border:none;border-radius:var(--r-sm);background:var(--brand-grd);color:#fff;font-size:13.5px;font-weight:800;font-family:inherit;cursor:pointer;box-shadow:0 2px 12px rgba(var(--a-rgb),.3);transition:.16s;display:flex;align-items:center;justify-content:center;gap:7px}
.vt-go:hover{filter:brightness(1.07)}
.vt-go:disabled{opacity:.45;cursor:default;box-shadow:none}
/* Ficha de resultados */
.vt-stats{display:grid;grid-template-columns:1fr 1fr;gap:7px}
.vt-stat{background:var(--soft);border:1px solid var(--line);border-radius:var(--r-sm);padding:9px 10px}
.vt-stat .k{display:block;font-size:9.5px;font-weight:700;text-transform:uppercase;letter-spacing:.6px;color:var(--muted);margin-bottom:3px}
.vt-stat .v{font-size:15px;font-weight:900;color:var(--ink);line-height:1.15;letter-spacing:-.2px}
.vt-stat .v small{font-size:10.5px;font-weight:700;color:var(--muted);margin-left:2px}
.vt-stat.hl{background:var(--soft-2);border-color:rgba(var(--a-rgb),.18)}
.vt-stat.hl .v{color:var(--brand-strong)}
.vt-swatches{display:flex;flex-wrap:wrap;gap:5px;margin-top:10px}
.vt-sw{width:24px;height:24px;border-radius:7px;border:1.5px solid rgba(var(--tinta-rgb),.14);cursor:pointer;position:relative;transition:.12s;padding:0;background-clip:padding-box}
.vt-sw:hover{transform:scale(1.12)}
.vt-sw.off{opacity:.25}
.vt-sw.off::after{content:'';position:absolute;left:1px;right:1px;top:50%;height:2px;background:var(--red);transform:rotate(-45deg)}
.vt-empty{text-align:center;color:var(--muted);font-size:12.5px;padding:22px 12px;line-height:1.65;border:1.5px dashed var(--line);border-radius:var(--r-sm);background:var(--soft)}
.vt-esc-note{font-size:11.5px;color:var(--muted);line-height:1.5;margin-top:8px}
.vt-esc-ok{background:var(--green-bg);border:1px solid rgba(var(--ok-rgb),.2);border-radius:var(--r-sm);padding:9px 11px;font-size:12px;color:var(--green);font-weight:700;margin-bottom:10px;line-height:1.45}
.vt-warn{background:var(--amber-bg);border:1px solid rgba(var(--av-rgb),.22);border-radius:var(--r-sm);padding:9px 11px;font-size:11.5px;color:var(--amber);font-weight:600;line-height:1.5;margin-top:9px}
.vt-dl{display:grid;grid-template-columns:1fr 1fr;gap:7px;margin-bottom:9px}
.vt-modal-bg .sp-actions{padding:10px 14px 12px}
.btn-vector-open{display:flex;align-items:center;justify-content:center;gap:var(--e2);padding:10px 14px;border:1px solid var(--n3);border-radius:var(--rr1);background:var(--sup);color:var(--n7);font-size:var(--t2);font-weight:500;cursor:pointer;transition:border-color .12s,background .12s;white-space:nowrap;font-family:inherit}
.btn-vector-open:hover{background:var(--a2-suave);border-color:#5227b8}
/* Los dos modales de pantalla completa —escalador y vectorizador— cambian a diseño de
   teléfono a los 1000 px y no a los 760. Su barra de herramientas necesita 982 px para
   caber en un renglón, así que entre 761 y 981 px desbordaba por la derecha y dejaba
   fuera de la pantalla la insignia de calibración, el selector de modo y el botón de
   volver al cotizador —sin manera de verlos ni de tocarlos—. La pantalla interna del
   Galaxy Z Fold 6 mide 832 px y caía justo en ese hueco. */
@media(max-width:1000px){
  /* El aviso emergente sube por encima de las acciones. El escalador puede con un número
     fijo porque su pie siempre mide lo mismo; aquí no —el pie crece y encoge según haya
     medida real, y el texto de ayuda cambia de renglones—, así que la altura se mide y se
     publica en esta variable. Sin eso el aviso tapaba justo el botón de agregar partida. */
  .vt-modal-bg.show~.toast{bottom:calc(26px + var(--vt-acc-h,150px))}
  .vt-modal-bg .sp-side{width:100%}
  .vt-modo button{min-height:52px}
  .vt-go{min-height:48px}
  .vt-sw{width:30px;height:30px}
  .vt-dl button{min-height:46px}
}
/* Estos tres viven en la tarjeta de partidas, no en el modal: siguen en 760 px */
@media(max-width:399px){
  /* Debajo de 400 px los tres botones de entrada no caben en un renglón */
  .scaler-ai-row{flex-wrap:wrap}
  .scaler-ai-row .ai-btn{flex:1 1 100%}
  .btn-scaler-open,.btn-vector-open{flex:1 1 0;min-height:46px}
}
/* De 400 px para arriba los tres SÍ caben en un renglón: medido a 430 px, 157.8 + 89.9 +
   109.1 = 356.8 de 382 disponibles, con 25 px de holgura y sin un solo recorte. Eran dos
   renglones y 97.5 px de alto por creer que no cabían. Debajo de 400 px sigue envuelta. */
@media(min-width:400px) and (max-width:760px){
  .scaler-ai-row{flex-wrap:nowrap}
  .scaler-ai-row .ai-btn{flex:1 1 auto;width:auto;min-width:0}
  .btn-scaler-open,.btn-vector-open{flex:0 0 auto}
}
@media(max-width:1000px) and (max-height:820px) and (orientation:landscape){
  .vt-modal-bg.show~.toast{bottom:16px}
}
@media(max-width:1000px){
  /* Barra de herramientas: permitir salto de línea para que nada quede fuera de pantalla.
     El orden pone marca, estado y salida en el primer renglón —así el botón de volver
     al cotizador queda siempre arriba a la derecha— y las herramientas debajo. */
  .sp-topbar{height:auto;min-height:52px;flex-wrap:wrap;gap:7px;row-gap:8px;
    padding:max(8px,env(safe-area-inset-top,0px)) max(10px,env(safe-area-inset-right,0px)) 8px max(10px,env(safe-area-inset-left,0px))}
  .sp-topbar .sp-sep,.sp-topbar .sp-spacer{display:none}
  .sp-brand-sub{display:none}
  /* El logotipo se va: con él, "Sin calibrar" y la salida no cabían en el mismo
     renglón y la barra se comía cuatro filas de pantalla. */
  .sp-topbar .brand{order:1;flex:1 1 auto;min-width:0;gap:0}
  .sp-topbar .brand .logoimg{display:none}
  .sp-topbar .brand>div{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .sp-calib-badge{order:2}
  .sp-close{order:3}
  .sp-tb-btn{order:4;min-height:42px;padding:9px 13px}
  .tool-seg{order:5;width:100%}
  .tool-seg button{flex:1;min-height:40px;padding:9px 8px}
  /* Panel inferior: hoja deslizable, todo el contenido alcanzable.
     Los altos van en % del área disponible y no en vh: con vh la suma de lienzo y panel
     se pasaba de la pantalla —la barra de herramientas también ocupa— y .sp-main recorta,
     así que el pie del panel (con el botón de volver) quedaba inalcanzable. */
  .sp-main{flex-direction:column}
  .sp-canvas-area{flex:1 1 auto;min-height:120px}
  .sp-side{width:100%;height:auto;max-height:54%;flex:0 0 auto;border-left:none;border-top:1px solid var(--line);overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain}
  .sp-mlist{flex:none;overflow:visible;min-height:0}
  .sp-side .btn{min-height:46px}
  .sp-ibtn{font-size:19px;padding:0;width:44px;height:44px;display:flex;align-items:center;justify-content:center;border:1px solid var(--line);border-radius:10px;color:var(--muted)}
  .sp-mitem{padding:10px;margin-bottom:7px}
  .sp-mitem-add{min-height:44px;font-size:13px;margin-top:6px}
  .sp-mitem-label{padding:6px 0;font-size:13px}
  .ref-known button{min-height:40px;padding:8px 12px;font-size:12.5px}
  .sp-zoom button{width:46px;height:46px}
  .sp-cotas-fab button{width:46px;height:46px}
  /* Ver el comentario de la nota en cotizador.html: en el celular el panel no da para
     tres renglones de tranquilidad, y el aviso del lienzo ya dice lo mismo. */
  .sp-cotas .hintnote{display:none}
  .sp-close{width:auto;height:44px;padding:0 12px;border:1.5px solid var(--line);background:var(--sup);color:var(--ink)}
  .sp-close .ico{display:none}
  .sp-close .back{display:flex;font-size:18px;line-height:1}
  .sp-close .lbl{display:inline;font-size:13px;font-weight:800}
  /* Acciones pegadas al pie del panel: agregar las medidas y volver al cotizador
     siguen a la vista por más medidas que haya en la lista. */
  /* El pie va pegado al borde de abajo, así que tiene que contar la franja del gesto
     de inicio del iPhone: sin esto la mitad inferior del botón de volver quedaba
     debajo del indicador y no se podía tocar. */
  /* El vectorizador entra en el selector a propósito: su regla de arriba
     (.vt-modal-bg .sp-actions) tiene dos clases y ganaba por especificidad, así que su pie
     pegado perdía el margen de la franja de gestos del iPhone y los botones quedaban donde
     el gesto de volver a inicio se los come. */
  .sp-actions,.vt-modal-bg .sp-actions{order:9;position:sticky;bottom:0;z-index:4;background:var(--sup);border-top:1px solid var(--line);box-shadow:0 -7px 16px rgba(var(--tinta-rgb),.08);margin-top:4px;
    padding:9px 14px calc(10px + env(safe-area-inset-bottom,0px));
    padding-left:max(14px,env(safe-area-inset-left,0px));
    padding-right:max(14px,env(safe-area-inset-right,0px))}
  /* En la maqueta apilada el lienzo ya no toca el borde de abajo —debajo va el panel—, así
     que reservar ahí la franja de gestos solo servía para que la barra de ayuda tapara el
     borde inferior de la foto. Se devuelve en el bloque de horizontal, que es el único caso
     de teléfono donde el lienzo sí llega abajo. */
  .sp-hint-bar{padding-bottom:10px}
  .sp-actions .sp-addall{margin:0;width:100%;min-height:46px}
  .sp-actions .sp-ai{margin:8px 0 0;width:100%;min-height:46px}
  /* La nota de tres renglones se llevaba 50 px del pie fijo cada vez, y el texto del
     botón que explica ya lo dice. En el teléfono el alto es de la lista de medidas. */
  .sp-actions .sp-ai-note{display:none}
  .sp-actions .sp-addall-note{margin:8px 0 0}
  .sp-back-m{display:block;width:100%;min-height:46px;margin-top:8px;border:1.5px solid var(--line);border-radius:var(--r-sm);background:var(--sup);color:var(--brand-strong);font-size:13px;font-weight:800;font-family:inherit;cursor:pointer}
  .sp-back-m:active{background:var(--soft-2)}
  /* El aviso emergente se sube por encima de esa barra: tapaba justo el botón de volver.
     El alto lo mide scAjustarToast() y lo publica en --sc-acc-h; con los 104 px fijos que
     había antes el aviso caía DENTRO del pie —que mide entre 174 y 237 px según haya
     medidas y cuántos renglones ocupe la nota— y tapaba justo el botón que anunciaba. */
  .scaler-modal-bg.show+.toast{bottom:calc(16px + var(--sc-acc-h,150px))}
}
/* Celular acostado: el panel a un lado, si no el lienzo se queda sin alto */
@media(max-width:1000px) and (max-height:820px) and (orientation:landscape){
  .sp-main{flex-direction:row}
  .sp-canvas-area{min-height:0}
  .sp-side{width:46%;max-width:340px;height:100%;max-height:none;border-top:none;border-left:1px solid var(--line)}
  .scaler-modal-bg.show+.toast{bottom:16px}
  /* En horizontal el lienzo sí llega al borde de abajo, así que aquí la barra de ayuda
     vuelve a reservar la franja de gestos que el bloque apilado le quitó. */
  .sp-hint-bar{padding-bottom:calc(10px + env(safe-area-inset-bottom,0px))}
}
/* ----- Visibilidad en PDF / modo edición ----- */
.pdf-vis{border:none;background:none;font-size:15px;cursor:pointer;padding:2px 6px;border-radius:6px;line-height:1;transition:.12s;color:var(--brand)}
.pdf-vis.off{opacity:.4;color:var(--muted)}
.pdf-vis:hover{background:var(--soft)}
/* Oculta del PDF: no se atenúa con opacidad —eso hundía su texto a 2:1 y la partida sigue
   siendo legible por derecho— sino que se marca en el margen y lo dice con palabras. */
.partida.hidden-pdf{background:var(--n1)}
.edit-mode-banner{display:flex;align-items:center;gap:var(--e2);background:var(--av-bg);border:1px solid var(--av-borde);border-radius:var(--rr1);padding:11px 14px;margin-bottom:var(--e3);font-size:var(--t2);font-weight:500;color:var(--av)}
/* ----- El candado de las partidas -----
   Mismo ámbar que el resto de los avisos de «falta algo» —el de los huecos obligatorios y
   el del modo edición—, para que se lea como parte de la misma familia y no como un error.
   Va en la tarjeta de Partidas y no arriba de todo a propósito: el aviso tiene que estar
   donde se va a intentar capturar, que es donde surge la duda. */
.cand-partidas{display:flex;align-items:center;gap:var(--e3);width:100%;text-align:left;background:var(--av-bg);border:1px solid var(--av-borde);border-radius:var(--rr1);padding:12px 14px;margin-bottom:var(--e3);font-size:var(--t2);font-weight:500;color:var(--av);cursor:pointer;transition:border-color .12s}
.cand-partidas:hover{border-color:var(--amber-ico)}
.cand-partidas[hidden]{display:none}
.cand-partidas .svgi{flex-shrink:0;color:var(--amber-ico)}
.cand-partidas .cp-txt{flex:1;min-width:0;line-height:1.45;font-weight:600}
.cand-partidas .cp-txt b{font-weight:800}
.cand-partidas .cp-go{flex-shrink:0;font-size:16px;font-weight:800;opacity:.75}
/* Con el candado puesto, las partidas que ya traía una cotización vieja se quedan a la
   vista pero en reposo: se pueden leer, no tocar. Sin esto se veían exactamente igual que
   una partida editable y el único aviso de que no respondían era que no respondían.

   NO se apaga con `opacity`, que fue el primer intento: un .62 sobre la partida entera se
   lleva por delante el texto, y el valor de la descripción bajaba de 16,9:1 a 2,6:1 y las
   fichas ámbar a 2,7:1 —exactamente el problema que este archivo ya había arreglado una
   vez subiendo los tonos de estado—. Congelar una partida no puede volverla ilegible: leer
   es justo lo único que se puede hacer con ella. Así que lo que cambia es el marco —fondo
   de reposo y filete gris en vez del azul de marca—, y el estado real lo llevan los
   controles: los campos con su gris de deshabilitado de siempre y los chips con la regla
   de aquí abajo. El texto se queda en su contraste completo. */
.items-cand .partida{background:var(--n1)}
/* ----- Registrar Venta modal ----- */
.rv-modal-bg{position:fixed;inset:0;background:rgba(12,15,38,.7);display:none;z-index:60;align-items:center;justify-content:center;backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px)}
.rv-modal-bg.show{display:flex}
.rv-modal{background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);width:min(520px,92vw);overflow-y:auto;-webkit-overflow-scrolling:touch;
  max-height:calc(100dvh - 32px - env(safe-area-inset-top,0px) - env(safe-area-inset-bottom,0px));box-shadow:0 24px 80px rgba(0,0,0,.45),0 6px 20px rgba(0,0,0,.3)}
.rv-header{display:flex;align-items:center;justify-content:space-between;padding:18px 20px 14px;border-bottom:1px solid var(--line)}
/* .btn trae width:100% y dentro de un contenedor flex ese width es el tamaño base: el
   botón de cerrar arrancaba pidiendo el ancho del modal entero y se comía media
   cabecera. Aquí no crece y mantiene su área de toque. */
.rv-header .btn{width:auto;flex:0 0 auto;min-width:44px;min-height:44px;padding:0;justify-content:center}
.rv-header h2{font-size:15px;font-weight:700;color:var(--fg);margin:0}
.rv-body{padding:20px}
.rv-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.rv-field{display:flex;flex-direction:column;gap:5px}
.rv-field.full{grid-column:1/-1}
.rv-field label{font-size:11px;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.04em}
.rv-field input,.rv-field select{background:var(--soft);border:1.5px solid var(--line);border-radius:var(--r-sm);padding:8px 10px;font-size:13px;color:var(--fg);width:100%;outline:none;box-sizing:border-box;font-family:inherit}
.rv-field input:focus,.rv-field select:focus{border-color:var(--brand)}
.rv-field input[readonly]{opacity:.65;cursor:default}
.rv-aviso{background:var(--green-bg);border:1px solid rgba(var(--ok-rgb),.25);color:var(--green);border-radius:var(--r-sm);padding:10px 13px;font-size:12px;font-weight:600;line-height:1.5;margin-bottom:14px}
.rv-calc{background:var(--soft);border-radius:var(--r-sm);padding:12px 14px;display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:14px}
.rv-calc-item{display:flex;flex-direction:column;gap:3px}
.rv-calc-item span:first-child{font-size:10.5px;color:var(--muted);font-weight:600;text-transform:uppercase;letter-spacing:.04em}
.rv-calc-item span:last-child{font-size:14px;font-weight:700;color:var(--fg)}
.rv-calc-item.accent span:last-child{color:var(--brand)}
.rv-footer{padding:10px 20px 20px;display:flex;flex-direction:column;gap:9px}
.rv-copied{display:none;align-items:center;gap:7px;background:var(--ok-bg);border:1px solid var(--ok-borde);border-radius:var(--r-sm);padding:10px 14px;font-size:12.5px;color:var(--ok);font-weight:600}
.rv-copied.show{display:flex}

/* ===================== Material heredado =====================
   Marca visible de que el material lo puso la app —heredado de la partida anterior—
   y no la persona. Es un dato que mueve el precio: tiene que verse. */
.heredado{display:inline-block;font-size:9.5px;font-weight:700;color:var(--av);background:var(--av-bg);border:1px solid rgba(var(--av-rgb),.35);border-radius:5px;padding:0 5px;margin-left:6px;vertical-align:middle;text-transform:none;letter-spacing:0}

/* ===================== Agregar partida =====================
   Duplicar la anterior ya existía en el ⧉ del encabezado de cada partida, pero
   escondido arriba a la derecha. Aquí queda junto a la acción que se usa después de
   capturar una partida, que es cuando de verdad se necesita.

   `.addbtn` trae `width:100%` de cuando era un botón solo a lo ancho de la tarjeta. En
   la fila, esa anchura es la que resuelve el `flex-basis:auto` de «Igual que la
   anterior»: su tamaño base pasaba a ser el 100% del renglón, no el de su texto. Sin
   espacio libre que repartir, «+ Agregar partida» —con base 0 y `min-width:0`— se
   quedaba en sus 20 px de relleno, con el texto partido en «Ag pa» y cortado. Pasaba
   en todos los anchos, también en el escritorio. Por eso la fila devuelve la anchura a
   `auto`: el botón de duplicar vuelve a medir lo que mide su texto.

   Y la fila envuelve. Con la letra de verdad —Inter, más ancha que la del sistema— los
   dos textos suman más que un teléfono angosto: en vez de aplastar el botón principal,
   el de duplicar se baja a su propio renglón y ahí se estira a lo ancho.

   El sobrante se reparte 2 a 1 para que agregar —la acción principal— sea el botón
   más ancho de los dos, que si no el texto más largo de duplicar lo dejaba en segundo
   lugar. */
.addrow{display:flex;flex-wrap:wrap;gap:9px;align-items:stretch}
/* El atributo `hidden` es `display:none` de la hoja del navegador, y una regla de autor con
   `display` le gana: sin esto, la fila de agregar seguía a la vista con el paso 1 sin
   terminar aunque el atributo estuviera puesto. */
.addrow[hidden]{display:none}
.addrow .addbtn{flex:2 1 auto;width:auto;min-width:0}
.addbtn.igual{flex:1 1 auto;white-space:nowrap;border-style:solid;border-color:var(--line);background:var(--sup);color:var(--brand)}
.addbtn.igual:hover{border-color:var(--brand);background:var(--soft-2)}

/* ===================== Revisión previa: partidas sin terminar ===================== */
.falt-intro{font-size:12.5px;color:var(--muted);line-height:1.5;margin-bottom:13px}
.falt-list{display:flex;flex-direction:column;gap:8px;margin-bottom:15px}
.falt-row{display:flex;align-items:center;gap:11px;padding:10px 12px;border:1.5px solid rgba(var(--av-rgb),.45);background:var(--amber-bg);border-radius:var(--r-sm);width:100%;text-align:left;font-family:inherit;transition:.14s}
.falt-ir{flex:1;min-width:0;display:flex;align-items:center;gap:11px;border:none;background:none;font-family:inherit;text-align:left;cursor:pointer;padding:0}
.falt-n{width:26px;height:26px;border-radius:8px;background:var(--amber);color:#fff;font-size:12px;font-weight:800;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.falt-b{flex:1;min-width:0}
.falt-t{display:block;font-size:12.5px;font-weight:800;color:var(--ink);line-height:1.35}
.falt-d{display:block;font-size:11.5px;color:var(--av);line-height:1.45;margin-top:2px}
.falt-go{font-size:14px;color:var(--amber);flex-shrink:0;font-weight:800}
.falt-quitar{border:1.5px solid rgba(var(--mal-rgb),.3);background:var(--sup);color:var(--red);font-family:inherit;font-size:11px;font-weight:700;padding:6px 10px;border-radius:8px;cursor:pointer;flex-shrink:0;transition:.14s}
.falt-quitar:hover{background:var(--red-bg);border-color:var(--red)}

.hist-ayuda{margin:0;padding:0 20px 12px;font-size:11.5px;color:var(--muted);line-height:1.5}
.hist-ayuda b{color:var(--ink);font-weight:700}

/* ===================== Respaldo, restauración y CSV ===================== */
.hist-foot{display:flex;gap:8px;padding:11px 20px 13px;border-top:1px solid var(--line);flex-shrink:0;background:var(--soft);flex-wrap:wrap;border-radius:0 0 var(--rr4) var(--rr4)}
.hist-foot button{flex:1;min-width:104px;border:1.5px solid var(--line);background:var(--sup);color:var(--brand);font-family:inherit;font-size:12px;font-weight:700;padding:9px 8px;border-radius:var(--rr1);cursor:pointer;transition:.14s;white-space:nowrap}
.hist-foot button:hover{border-color:var(--brand);background:var(--soft-2)}
.hist-foot .foot-nota{flex-basis:100%;font-size:10.5px;color:var(--muted);line-height:1.45;text-align:center;margin-top:2px}
/* Lo que ya se hizo con esta cotización. Va entre la tabla y el total, en el secundario de la
   app: es un dato al margen y no una acción. */
.hentry-hitos{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:7px;
  font-size:var(--t1);color:var(--muted);line-height:1.5}
.hentry-hitos .svgi{width:13px;height:13px;color:var(--ok);flex-shrink:0}

/* ===================== WhatsApp ===================== */
.btn-wa{background:var(--sup);color:var(--wa);border:1.5px solid rgba(var(--wa-rgb),.32)}
.btn-wa:hover{background:var(--ok-bg);border-color:var(--wa)}

/* ===================== Teléfono: aprovechar la pantalla =====================
   Este bloque va al final de la hoja a propósito. Varias reglas de aquí repiten
   selectores que ya existen más arriba y, entre dos reglas con la misma
   especificidad, gana la última: una media query no pesa más por ser más estrecha.
   Por eso el `.card-b{padding:16px}` y el `.grid2/.grid3` de una sola columna que
   estaban en el primer bloque de 560 px nunca llegaron a aplicarse —las reglas base
   de más abajo los pisaban— y en el celular seguían saliendo los 22 px de relleno
   pensados para el escritorio.

   La regla al elegir medidas: se recorta el marco (rellenos, huecos, notas), nunca
   el blanco de lo que se toca. Todo lo tocable sigue en 40 px o más.

   Ojo: el bloque del plegado que sigue ya NO es de esta sección —vale en cualquier
   ancho—, pero se queda aquí porque necesita este lugar exacto de la hoja: después de
   las reglas base que compiten con él y antes del bloque de puntero grueso, que sube el
   ▾ a 44 px para el dedo. Lo suyo empieza en su propio encabezado. */

/* ===================== Partidas plegables, en cualquier pantalla =====================
   Una partida de letras mide 1 293 px en un iPhone: con dos capturadas ya no cabía
   ninguna completa en pantalla y había que desplazarse a ciegas para compararlas.
   Plegada deja a la vista lo que se está cotizando —descripción, tipo, lo elegido y su
   total— y se abre con un toque. El estado vive fuera de la cotización: no se guarda ni
   viaja al PDF.

   Nació como arreglo del teléfono y por eso todo esto vivía dentro de la media query de
   920 px, pero el problema no era del teléfono: era de las partidas. En escritorio la
   columna de captura mide ~690 px y una partida de letras abierta se lleva 600 px de
   alto enseñando el catálogo COMPLETO —los cinco materiales, las tres complejidades,
   los tres acabados— multiplicado por cada partida de la cotización. Con cinco partidas
   eran 3 000 px de opciones para leer dos datos. Así que el plegado vale igual en las
   dos pantallas y las reglas son base.

   Van en este hueco de la hoja a propósito, no al final: aquí ya quedaron atrás todas
   las reglas base que compiten (.partida-top, .tipo-seg, .pline, .psum) y todavía no
   llega el bloque de `@media(hover:none),(pointer:coarse)`, que sube el ▾ a 44 px para
   el dedo. Al final de la hoja, ese 44 px se perdería. */
.ptipo{display:none}
.ph-acts{display:flex;align-items:center;justify-content:flex-end;gap:8px;flex-wrap:wrap;min-width:0}
/* Una sola definición del ▾, para que no exista un `display:none` que pisarse después. */
.pfold{display:inline-flex;align-items:center;justify-content:center;border:none;background:none;
  color:var(--brand);font-size:13px;font-weight:400;line-height:1;cursor:pointer;
  padding:0;width:30px;height:30px;border-radius:8px;transition:transform .18s}
.pfold:active{background:var(--soft-2)}
/* Con ratón el ▾ necesita decir que es tocable; sus tres vecinos de la misma barra
   —duplicar, ojo del PDF y borrar— ya lo dicen. */
.pfold:hover{background:var(--soft-2)}
.partida.folded .pfold{transform:rotate(-90deg)}
.partida.folded .tipo-seg,.partida.folded .pbody{display:none}
.partida.folded .partida-top{margin-bottom:9px}
.partida.folded .psum{margin-bottom:0;cursor:pointer}
/* Plegada, la fórmula sola no dice nada que la cara plegada no diga ya con sus fichas, y el
   total vive arriba desde el rediseño. Se va con el cuerpo. */
.partida.folded .pline{display:none}
/* ----- El resumen se queda a la vista también con la partida ABIERTA -----
   Aquí decía `.partida:not(.folded) .psum{display:none}`, y el argumento era bueno mientras
   la partida cupiera en la pantalla: las fichas repetían lo que ya dicen los encabezados de
   cada bloque de opciones —✓ elegido / ! sin elegir— y el renglón del total, o sea 94 px
   duplicados por partida.

   Deja de ser verdad en cuanto la partida abierta mide 700 px y hay que desplazarse dentro de
   ella. A mitad de la captura, esos encabezados están fuera de la vista y en pantalla no
   queda nada que diga en cuál de las seis partidas estás ni qué material tiene puesto. Es
   justo la pregunta que antes contestaba el matiz de color por partida, que el rediseño
   retiró para que el azul signifique una sola cosa.

   Así que el resumen se queda, y lo que lo hace útil es que se PEGA: `.pcab` —el encabezado
   más el resumen— se queda arriba mientras el cuerpo se desplaza por debajo. Ya no es
   información duplicada: es la única copia que se ve cuando hace falta. */
/* DOS COSAS SIN LAS QUE ESTO NO PEGA, y las dos costaron una vuelta:

   1. `#card-partidas` tenía `overflow:hidden` —lo hereda de `.card`— y un `overflow` distinto
      de `visible` en CUALQUIER ancestro deja inerte a un `position:sticky` de dentro, sin
      error y sin aviso: el encabezado simplemente se va con el scroll. El recorte estaba para
      las esquinas de la banda teñida del encabezado de tarjeta, que el rediseño quitó.
   2. El `top` no es 0: encima hay una barra fija propia. Con `top:0` el resumen se queda
      pegado DEBAJO de ella y no se ve. `--top-fijo` es el alto real de esa barra, medido y
      publicado por `ajustarTopbarMovil()` en los dos anchos; el 74 de reserva es por si ese
      guion no llegara a correr. */
#card-partidas{overflow:visible}
.pcab{position:sticky;top:calc(var(--top-fijo,74px) + 4px);z-index:5;background:var(--sup);
  margin:calc(var(--pp) * -1) calc(var(--pp) * -1) var(--e4);
  padding:var(--pp) var(--pp) 0;
  border-radius:var(--rr3) var(--rr3) 0 0}
.partida:not(.folded) .pcab{padding-bottom:var(--e3);border-bottom:1px solid var(--linea)}
.partida:not(.folded) .psum{display:flex;margin-bottom:0}
.partida:not(.folded) .partida-top{margin-bottom:10px}
/* Plegada no hay nada que desplazar, así que el encabezado no se pega ni se separa con una
   línea: la partida entera ES el encabezado. */
.partida.folded .pcab{position:static;margin-bottom:0;padding-bottom:0;border-bottom:0}
/* El total, en el encabezado. Se subió desde `.pline` —el porqué está en partidas.js— y aquí
   se le da el peso que tiene en la maqueta: la letra de las cifras, 16 px, tabular. */
.partida-top>.lt{margin-left:auto;font-family:var(--f-cifra);font-size:16px;font-weight:600;
  color:var(--tinta);font-variant-numeric:tabular-nums;white-space:nowrap}
.partida-top>.lt+.ptop-actions{margin-left:0}
.partida.folded .ptipo{display:inline-flex;align-items:center;font-size:11px;font-weight:800;
  color:var(--brand-strong);background:var(--soft-2);border:1px solid rgba(var(--a-rgb),.16);
  padding:4px 9px;white-space:nowrap}
#fold-all-btn{max-width:none;display:inline-flex}
#fold-all-btn.oculto{display:none}
#fold-all-btn[aria-expanded="false"] .chev{transform:rotate(-90deg)}
@media(max-width:920px){
  /* El asa de arrastre no sirve en el teléfono —el arrastre de HTML no existe al
     tocar— así que su lugar, el borde de entrada de la partida, lo toma el plegado.
     En escritorio el arrastre con ratón sí existe, así que ahí conviven las dos. */
  .drag-handle{display:none}
}
/* Imprimir la pantalla del cotizador no es la manera de sacar la cotización —el PDF se
   arma aparte, con su propio documento—, pero si alguien le da Ctrl+P a la app, nada de
   lo plegado puede llevarse el detalle al papel: en pantalla se abre con un toque, en
   una hoja ya no. Va DESPUÉS del bloque de arriba y del de la tarjeta de proyecto porque
   pesa lo mismo que ellos: aquí sí manda el orden de la hoja.

   No se toca el selector de tipo: plegada, la partida ya lleva su chip .ptipo con el
   nombre del tipo, y devolverle el selector obligaría a acertar entre el inline-flex de
   base y la rejilla de tres columnas de ≤760 px. La cara plegada sí se esconde, porque
   abajo va el formulario completo y sería decir lo mismo dos veces. */
@media print{
  .pfold{display:none}
  /* El reposo de las partidas y la ficha del candado son de la pantalla táctil. El papel
     no tiene estados: la hoja sale igual esté el candado puesto o no. El fondo importa
     porque body lleva print-color-adjust:exact, así que sí se imprimiría, y una cotización
     con medio bloque gris se lee como una impresión sucia. La ficha ámbar, además, no le
     dice nada a quien recibe la hoja. */
  .items-cand .partida{background:#fff}
  .cand-partidas{display:none!important}
  .partida.folded .pbody{display:block}
  .partida.folded .psum{display:none}
  /* Los datos del proyecto se pliegan en el celular y el estado se guarda: sin esto, un
     Ctrl+P desde el teléfono imprime la cotización sin cliente, teléfono ni dirección. */
  .card.folded .card-b{display:block}
}

@media(max-width:560px){
  /* ----- Marco: menos cáscara, más cotización -----
     Entre el ancho de la página, la tarjeta, la partida y el bloque de opciones se
     iban 50 px por lado antes de llegar al primer chip; ahora son 30. */
  .wrap{padding:12px 10px calc(84px + env(safe-area-inset-bottom,0px));gap:14px}
  /* El relleno lateral se PUBLICA como variable, no solo se aplica. Cualquier tira que
     quiera salirse a sangre —la barra de módulos de la plataforma es la única hoy— tiene
     que restar exactamente esto, y con el número escrito a mano en el otro archivo ya
     pasó: la barra restaba 24 px donde la página pone 10, se salía 14 px por cada lado y
     las seis pantallas de la plataforma se movían en horizontal en todos los teléfonos.
     Con la variable no hay dos números que puedan divergir. */
  .wrap{--pad-lat:max(10px,env(safe-area-inset-left,0px));--pad-lat-der:max(10px,env(safe-area-inset-right,0px))}
  .wrap{padding-left:var(--pad-lat);padding-right:var(--pad-lat-der)}
  .topbar-in{padding-left:max(12px,env(safe-area-inset-left,0px));padding-right:max(12px,env(safe-area-inset-right,0px))}
  .card+.card{margin-top:12px}
  /* El título no se parte: si compite por el ancho con el botón de plegar, «Datos del
     proyecto» se iba a dos renglones y el encabezado crecía el doble. Lo que cede el
     ancho es el botón, y para eso necesita min-width:0 —sin él un elemento flexible
     no baja de lo que mide su texto y termina empujando la página a lo ancho. */
  /* El relleno de .card-h vive ahora en el bloque «Cierre de la hoja»: aquí perdía por
     orden contra la capa de color. Lo que sí sigue vivo de esta regla es el hueco. */
  .card-h{gap:9px}
  .card-h :is(h2,h3){white-space:nowrap;flex-shrink:0}
  .card-h .card-fold{min-width:0}
  .card-b{padding:11px 13px 15px}
  .card.folded .card-h{padding-bottom:13px}
  .partida{padding:11px 11px 12px;margin-bottom:10px}
  .optgrp{padding:8px 9px 9px;margin-bottom:8px}
  .optgrp-h{margin-bottom:7px;gap:7px}
  .fld{margin-bottom:10px}
  label,.fld-lab,.switch{margin-bottom:3px}
  .hintnote{font-size:11px;line-height:1.45;padding:5px 9px;border-radius:0 6px 6px 0}
  .optgrp .hintnote{margin-top:6px}
  .psum{gap:5px;margin-bottom:11px}
  .empty{padding:22px 10px}
  .scaler-ai-row{margin-bottom:11px}
  .ai-btn{padding:11px}
  /* Los dos botones de agregar caben en un renglón si se les recorta el relleno
     lateral; lo que no se recorta es el alto, que es lo que se toca. */
  .addrow{gap:7px}
  .addbtn{padding:13px 9px;font-size:12.5px}
  .addbtn.igual{font-size:12px;padding:13px 10px}
  .hist-foot{padding:10px 13px 12px;gap:7px}
  .hist-foot button{min-width:0;font-size:11.5px;padding:9px 6px}
  /* Con dos acciones —abrir y usar como base— la columna de botones dejaba el nombre
     del proyecto en tres letras por renglón. En el teléfono bajan a su propio renglón,
     donde además caben más anchas y se tocan mejor. */
  .hentry{padding:15px 13px}
  .hentry-top{flex-wrap:wrap;gap:11px}
  .hentry-img,.hentry-img-ph{width:74px;height:74px}
  .hentry-acts{order:9;flex-basis:100%;flex-direction:row;align-items:stretch;gap:6px}
  .hentry-acts .hentry-open{flex:1;padding:9px 6px;text-align:center}
  /* En el celular la fila de una cotización no cabe en una línea: el importe y los
     botones bajan y quedan a lo ancho, como ya hacen los del historial. */
  .cua-cot{flex-wrap:wrap}
  .cua-cot-meta{flex-basis:100%}
  .cua-cot-tot{order:1}
  .cua-cot-acts{order:2;margin-left:auto}
  .cua-card{padding:14px 16px;gap:11px}
  .cua-det-head,.cua-nota-wrap,.cua-cot,.cua-cifras{padding-left:16px;padding-right:16px}
  .cua-cots-tit{padding-left:16px;padding-right:16px}
  .hentry-del{align-self:stretch;padding:5px 10px}
  /* El contenido del panel tenía tres bordes izquierdos distintos: 20 px la cabecera, la
     ayuda y la búsqueda; 13 px la entrada y el pie. En el teléfono se veía el escalón. */
  .hist-head{padding:16px 13px}
  .hist-search-bar{padding:11px 13px}
  .hist-ayuda{padding:0 13px 12px}

  /* Dos campos cortos por renglón ocupan la mitad de alto que dos renglones enteros
     y siguen siendo cómodos de tocar. En las rejillas de tres, el tercer campo
     —cuando existe, como la tarifa de la caja de luz— se pasa completo abajo. */
  .grid2,.grid3{grid-template-columns:1fr 1fr;gap:9px}

  /* ----- Tipo de partida: los cinco de un vistazo -----
     En rejilla de tres se iban dos renglones y 102 px por partida, con «Recorte
     acrílico» partido a la mitad y un hueco muerto al final. Con el nombre corto
     caben los cinco en un renglón de 40 px.

     ACOTADO A `.partida`, y esto no es cosmética. `.tipo-seg` es también la clase que
     `segmento()` de la plataforma emite para TODAS sus tiras de filtro: «Todas» en
     Proyectos, «Mes · Semana · Lista» en Agenda, «Por comprar · En almacén · Por proyecto»
     en Material. Son dos o tres opciones con sitio de sobra, y estaban heredando el
     apretón que se calculó para meter CINCO tipos de partida en un renglón: 40 px de alto
     —cuatro por debajo del mínimo— y letra de 10,5 px, que ni siquiera es un paso de la
     escala. Se veían apretadas porque llevaban puesta la ropa de otro. Sin el prefijo, el
     bloque de 760 px les da 44 px y 11,5, que es lo que les toca. */
  .partida .tipo-seg{grid-template-columns:repeat(5,1fr);gap:2px;padding:2px}
  .partida .tipo-seg button{padding:9px 2px;font-size:10.5px;line-height:1.15;letter-spacing:-.1px;min-height:40px}
  .partida .tipo-seg .lg{display:none}
  .partida .tipo-seg .sm{display:inline}

  /* El encabezado de la partida plegada se partía en dos renglones en TODO teléfono de
     320 a 390 px —y hasta 414 con «Recorte acrílico»—: 44 px pasaban a 94 y cada partida
     plegada crecía 50 px. Se recorta el marco (huecos y relleno del chip) y la ficha usa
     el nombre corto, igual que el selector de tipo. Lo tocable no se toca. */
  .partida-top{gap:6px}
  .pnum{gap:4px}
  .ptop-actions{gap:2px}
  .partida.folded .ptipo{padding:4px 7px}
  .ptipo .lg{display:none}
  .ptipo .sm{display:inline}

  /* ----- Opciones en dos columnas -----
     A lo ancho completo cada material se comía un renglón entero: los cinco de
     letras 3D medían media pantalla. En dos columnas el nombre largo se acomoda en
     dos líneas dentro del mismo chip y el bloque baja de 270 px a 155 px. El último
     chip de un renglón impar crece para no dejar el hueco a la vista. */
  .optgrp .chips{gap:6px}
  .optgrp .chip{flex:1 1 calc(50% - 3px);min-height:42px;padding:9px 8px;font-size:11.5px;line-height:1.25}
  .optgrp .chip small{font-size:10.5px}

  /* ----- Resumen y autorización ----- */
  .prog-box{padding:9px 14px 11px}
  .sum-rows{padding:13px 14px 6px}
  .anti{padding:13px 14px}
  .auth{padding:14px}
  .auth-adj{padding:10px 14px 4px}
  .neto{padding:14px}
  .neto .amt{font-size:24px}
  .mini{margin-top:7px}
  .side #aiPreview:not(:empty){margin-bottom:11px}
}

/* ===================== Anti-zoom de iOS =====================
   Safari amplía la página al enfocar un campo con letra de menos de 16 px, y no vuelve
   solo a su tamaño. La regla de 16 px ya existía en el bloque de 760 px, pero las
   reglas base de `input,select,textarea` (y las de .rv-field y .autoctr) están más
   abajo en la hoja: con la misma especificidad gana la última, así que en el teléfono
   los campos seguían en 14 px —13 px en el de registrar venta— y la página se ampliaba
   con cada toque. Por eso va aquí, al final. */
@media(max-width:920px){
  input,select,textarea,
  .rv-field input,.rv-field select,
  .autoctr input{font-size:16px}
}

/* ===================== Se toca con el dedo =====================
   Por tipo de puntero y no por ancho: así vale igual en el iPhone y en las dos
   pantallas del Fold 6, sin depender de en qué lado del punto de corte caiga cada una.
   Lo que sube es la caja, nunca la letra. */
@media(hover:none),(pointer:coarse){
  .ai-drop .solo-raton{display:none}
  .ai-drop .solo-dedo{display:inline}
  .modal-h button{width:44px;height:44px}
  .ai-pick-x{min-width:44px;min-height:44px}
  /* ----- 16 px o iOS hace zoom -----
     Safari amplía la página al enfocar un campo cuya letra mide menos de 16 px, y luego se
     queda ampliada: el resto del formulario se captura en una ventana desplazada. Los
     bloques de teléfono ya subían la letra a 16, pero se acaban en 560 px de ancho y el
     último general en 920, y un iPhone 15 Pro Max ACOSTADO mide 932 —el 16 Pro Max, 956—.
     Los dos teléfonos más anchos que existen se salían por arriba de todos los cortes de
     móvil y volvían a los 14 px de --t3. Medido: de pie, 16 px; acostado, 14 y zoom.

     Va en el bloque de lo táctil y no en un corte de ancho nuevo, porque la condición no es
     el ancho: es que se toque con el dedo. Un Fold abierto, una tableta o un teléfono
     acostado son todos el mismo caso. */
  input,select,textarea{font-size:max(16px,var(--t3))}
  .toast-act,.falt-quitar,.key-btn,.sp-gclear,.hist-foot button,
  .card-fold,.btn-maps,.chip,.seg button,.tipo-seg button{min-height:44px}
  .key-btn,.falt-quitar{padding-left:14px;padding-right:14px}
  .hentry-del{min-width:44px;min-height:44px}
  /* 40x40 con 2 px de hueco eran tres cajas pegadas de las que UNA BORRA la partida. El
     dedo medio tiene 11 mm y en 2 px no hay margen de error: se erraba. Borrar se deshace
     —_borrada guarda la partida y su índice—, pero ver desaparecer un renglón que costó
     capturar no lo arregla el deshacer.

     El hueco sube a 6 px aquí y el que borra se separa un paso más: su vecino de la
     izquierda es el ojo del PDF, que se toca a menudo. El TAMAÑO sube a 44 unos renglones
     más abajo y solo de 376 px para arriba, no aquí: se midió una variante por una y a
     344 px —la portada del Fold— el encabezado aguanta hueco de 4 y no de 6, y con los
     botones a 44 se parte en dos renglones (92 px en vez de 44). Esa es exactamente la
     regresión contra la que avisa el comentario del bloque de 560, así que aquí el techo
     es 40x40 con hueco de 4: sigue muy por encima de los 24x24 del criterio 2.5.8 de WCAG
     y el que borra ya no está pegado a su vecino. */
  .del,.dup,.pdf-vis{width:40px;height:40px;padding:0;font-size:19px;
    display:inline-flex;align-items:center;justify-content:center;border-radius:9px}
  .ptop-actions{gap:4px}
  .ptop-actions .del{margin-left:2px}
  .sp-ibtn{min-width:44px;min-height:44px}
  .optgrp .chip{min-height:44px}
  .vt-sw{width:32px;height:32px}
  /* La cola del inventario, medida en el iPhone 15 Pro Max: cerrar el historial 32×32,
     el contador de letras 37 px de alto (16 px de letra + 5+5 de padding), el plegado
     de la partida 30×30 y el asa de la cortina de comparación 38 px de diámetro. */
  .hist-close{width:44px;height:44px}
  .autoctr input{min-height:44px}
  .pfold{width:44px;height:44px}
  .vt-split::after{width:48px;height:48px;background-size:22px 22px}
}
/* Foco visible y con contraste: varios controles llevan outline:none y con teclado
   no había manera de saber dónde estaba el cursor. */
/* Sin border-radius: el contorno sigue por sí solo el radio real del elemento, y
   declararlo aquí les cambiaba la FORMA al enfocarlos —los chips de material dejaban de
   ser píldoras, los campos perdían su radio— justo en el momento en que el usuario está
   mirando ese control. */
:where(button,summary,a[href],input,select,textarea,[tabindex]):focus-visible{
  outline:2.5px solid var(--brand);outline-offset:2px}

/* ===================== Modal abierto: el fondo se queda quieto =====================
   .modal-bg es position:fixed;inset:0, pero el que hacía scroll seguía siendo el
   documento: arrastrar sobre la zona oscura del modal de IA desplazaba la cotización
   por detrás del velo. La clase la pone y la quita el vigilante de la clase 'show'.
   Va en <html> y también en <body> porque en iOS Safari con solo body no basta.
   El overscroll-behavior evita además que el scroll del cuerpo del modal se encadene
   al documento al llegar al final —los dos modales grandes ya lo traían. */
html.modal-abierto,html.modal-abierto body{overflow:hidden}
.modal-bg{overscroll-behavior:contain}

/* Solo para el lector de pantalla: sale del dibujo pero se queda en el árbol de
   accesibilidad. Lleva clip además de clip-path porque clip-path:inset(50%) sin
   overflow:hidden deja el texto seleccionable en Safari. */
.solo-voz{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);
  clip-path:inset(50%);white-space:nowrap;border:0;padding:0;margin:-1px}

/* Enlace de salto al contenido. Aparece con :focus a secas y no solo con
   :focus-visible como el resto de los controles (línea del :where de arriba): un
   enlace que no se ve al llegar a él no sirve de nada. Se mueve con transform y no
   con left:-9999px para no ensanchar el área desplazable a lo ancho, que es justo lo
   que el min-width:0 de .wrap está evitando. */
.salto{position:fixed;top:8px;left:8px;z-index:200;min-height:44px;display:inline-flex;align-items:center;background:#fff;color:var(--brand-strong);
  padding:10px 16px;border-radius:10px;font-size:13px;font-weight:800;text-decoration:none;
  box-shadow:0 8px 30px rgba(0,0,0,.28);transform:translateY(calc(-100% - 16px));transition:transform .15s}
.salto:focus{transform:translateY(0)}

/* Sin animaciones para quien las pidió apagadas en el sistema */
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important}
  .chip:active,.tipo-seg button:active,.seg button:active,.mbar-btn:active,
  .sp-zoom button:active,.sp-cotas-fab button:active{transform:none}
  body{background-attachment:scroll}
}

/* =====================================================================
   ================  CAPA DE ESTRUCTURA Y MOVIMIENTO  ==================
   =====================================================================
   Va al final a propósito: es una capa, no un parche repartido. Todo lo de
   arriba sigue siendo la estructura —qué mide qué, qué va dónde— y esto es
   el material del que están hechas las piezas. Se puede leer completa de un
   tirón, y se puede quitar de un tirón.

   Aquí vivía la CAPA DE BARRO: 780 líneas de degradados de 168°, luces
   interiores, sombras teñidas y un lomo de color por partida. Hacía bien lo
   que se propuso —una pantalla que se lee como piezas blandas— y se cambia
   entera porque el rediseño responsive pide lo contrario, y lo pide por
   razones que se ven al abrir la app en cinco anchos seguidos:

     · El barro necesita ESPACIO. Sus cuatro señales —radio grande, luz
       arriba, sombra abajo, sombra exterior larga— piden unos 20 px de aire
       alrededor de cada pieza. A 360 px eso no existe: la sombra de una
       tarjeta cae encima de la siguiente y catorce piezas apiladas se leen
       como una sola mancha.
     · El barro pinta CARO. Cuatro capas de sombra por pieza, y las tarjetas
       de un tablero de proyectos son treinta y cinco. En un teléfono de gama
       media el scroll de esa pantalla iba a tirones medibles.
     · Y el barro DICE algo, que es lo peor: si todo sobresale, nada
       sobresale. Con seis matices de partida, un botón violeta de IA, un
       total con el texto en degradado y seis pestañas con brillo propio, la
       pantalla no tenía una sola cosa más fuerte que las demás.

   La dirección nueva pone la jerarquía en tres sitios y en ninguno más:

     1. EL BORDE Y LA SUPERFICIE. Una pieza es `var(--sup)` con 1 px de
        `var(--linea)` y 6 px de radio. Lo hundido es `var(--sup2)`. Eso es
        todo: dos tonos y una línea separan continente de contenido, y
        funcionan igual a 360 px que a 1 440.
     2. EL COLOR, UNA VEZ POR PANTALLA. `--a-fill` significa una cosa y solo
        una: esto está elegido, o esta es LA acción. Un botón de color por
        pantalla, y los demás con borde.
     3. LA SOMBRA, DONDE ALGO FLOTA DE VERDAD. `--sombra` la llevan las
        tarjetas del tablero de proyectos —que se arrastran entre columnas—
        y los controles sueltos encima del mapa. Nada más.

   Y el movimiento se queda, porque el movimiento nunca fue el problema: la
   entrada de una pantalla, el latido de lo que pide una decisión, el brillo
   de la barra de completitud y el total que viaja de un paso al otro.
   ===================================================================== */

/* ---------- El lienzo ----------
   Plano. El body ya lo pinta arriba; aquí solo se recuerda por qué no hay
   nada más: sobre un lienzo teñido, una barra lateral marino y una tarjeta
   blanca son tres colores discutiendo, y la barra lateral es la que pierde. */

/* ---------- Superficies ---------- */
.card,.sum{
  background:var(--sup);
  border:1px solid var(--linea);
  border-radius:var(--rr3);
  box-shadow:none;
}
/* Una tarjeta no se levanta al pasar el ratón. Levantar treinta y cinco
   tarjetas de un tablero, una por una, es un tablero que se mueve solo. */
.card:hover,.sum:hover{box-shadow:none}

/* ---------- El encabezado de una tarjeta ----------
   Era una banda teñida del acento. Ahora es una línea: `--linea2`, que es el
   filete de dentro de una pieza, más fino que el que la limita por fuera.
   Con la banda, cada tarjeta traía su propio azul y la pantalla tenía
   catorce azules de fondo; sin ella, el azul vuelve a estar disponible para
   lo que de verdad significa algo. */
.card-h{
  padding:var(--e3) var(--e4);
  background:transparent;
  border-bottom:1px solid var(--linea2);
  box-shadow:none;
}
.card-h h2,.card-h h3{font-size:var(--t4);font-weight:600}
.card-b{padding-top:var(--e4)}
.card.folded .card-h{border-bottom:none}

/* ---------- Las partidas ----------
   La bandeja hundida se va: existía para que una partida saliente tuviera de
   dónde salir. Sin relieve no hace falta continente, y sin continente cada
   partida gana los 12 px de relleno que la bandeja se llevaba, que en un
   teléfono son la diferencia entre que el encabezado quepa en un renglón o
   no. */
#items:not(:empty){
  padding:0;
  margin:0 0 var(--e2);
  border-radius:0;
  background:none;
  box-shadow:none;
}

/* La partida: una pieza plana con su borde. Sin lomo de color, sin banda
   teñida y sin matiz —el porqué está escrito arriba, con los tokens: el azul
   solo significa «elegido», y lo que dice de quién es cada cosa es el resumen
   fijo del encabezado, que se queda pegado arriba mientras se hace scroll. */
.partida{
  --pp:var(--e4);
  --lomo:0px;
  background:var(--sup);
  border:1px solid var(--linea);
  border-radius:var(--rr3);
  padding:var(--pp);
  margin-bottom:var(--e3);
  overflow:visible;
  box-shadow:none;
  transition:border-color var(--mv-s);
}
.partida:last-child{margin-bottom:0}
.partida::before{content:none}
.partida:hover{transform:none;border-color:var(--a-borde)}

/* EL RESUMEN FIJO. Es la pieza que sustituye al matiz de color, y hace más:
   mientras se hace scroll DENTRO de una partida —que con cinco materiales,
   tres complejidades, tres luces y cuatro campos son unos 700 px— el
   encabezado se queda arriba diciendo qué partida es, cómo se llama, cuánto
   lleva y qué tiene elegido. Antes, a mitad de la captura no había en
   pantalla una sola cosa que dijera en cuál de las seis se estaba.

   `top:-1px` y no `0`: con 0, el borde de arriba de la partida asoma un
   píxel por encima del resumen pegado y se ve una línea que va y viene. */
.partida:not(.folded) .partida-top{
  position:sticky;top:-1px;z-index:5;
  margin:calc(var(--pp) * -1) calc(var(--pp) * -1) var(--e4);
  padding:var(--e3) var(--pp);
  background:var(--sup);
  border-bottom:1px solid var(--linea);
  border-radius:var(--rr3) var(--rr3) 0 0;
  box-shadow:none;
}
/* Una partida con `overflow:visible` y un hijo pegado necesita que la pieza
   no recorte: por eso arriba `overflow` dejó de ser `hidden`. El precio es
   que las esquinas de abajo ya no recortan a nadie, y no hay nadie a quien
   recortar. */
.partida:focus-within{box-shadow:none;border-color:var(--a-borde)}
.partida.folded{background:var(--sup);box-shadow:none}
.partida.folded:hover{border-color:var(--a-borde)}
/* Lo que está fuera de juego —las partidas que aún no se pueden tocar y las
   que no salen en el PDF— se queda en la superficie hundida. Es la única vez
   que quitar contraste informa. */
.items-cand .partida,.partida.hidden-pdf{background:var(--sup2);box-shadow:none}
.items-cand .partida:not(.folded) .partida-top,.partida.hidden-pdf:not(.folded) .partida-top{
  background:var(--sup2);border-bottom-color:var(--linea);
}

/* ----- El número de la partida -----
   Era una pastilla rellena del matiz. Ahora es la ficha neutra del rediseño:
   superficie hundida, borde, segunda tinta y la letra de las cifras. No
   compite con nada, que es lo que tiene que hacer un rótulo. */
.pnum .n{
  background:var(--sup2);
  border:1px solid var(--linea);
  color:var(--tinta2);
  font-family:var(--f-cifra);font-weight:600;font-size:var(--t2);
  border-radius:var(--rr1);
  min-width:26px;height:22px;padding:0 var(--e2);
  text-shadow:none;box-shadow:none;
}
.items-cand .pnum .n,.partida.hidden-pdf .pnum .n{background:var(--linea2);color:var(--tinta3)}
.partida .pfold,.partida .drag-handle{color:var(--tinta2)}
.partida .pfold:hover,.partida .pfold:active{background:var(--sup2)}

/* La ficha del tipo, en la cara plegada: neutra, como las demás fichas de lo
   que la partida lleva puesto. */
.partida.folded .ptipo{
  background:var(--sup2);
  border:1px solid var(--linea);
  color:var(--tinta2);
}

/* ---------- Los grupos de opciones ----------
   Eran un hueco excavado y teñido. El rediseño los deja como lo que son: un
   rótulo en versalitas y una rejilla debajo. El hueco resolvía «dónde acaba
   la partida y empieza lo suyo» cuando la partida era una pieza blanda; con
   un borde de 1 px esa pregunta ya no se hace. */
.optgrp{
  padding:0;
  border:0;
  border-radius:0;
  background:none;
  box-shadow:none;
  margin-bottom:var(--e4);
}
.optgrp.falta{background:none;box-shadow:none;border:0}
.optgrp-t{
  color:var(--tinta2);font-weight:600;font-size:var(--t2);
  letter-spacing:.3px;text-transform:uppercase;
}
.optgrp.falta .optgrp-t{color:var(--av)}

/* ---------- Lo elegido ----------
   Relleno `--a-fill` y texto blanco. Es LA regla de color de la app y por eso
   se escribe una sola vez para el chip suelto y para el de dentro de una
   partida: el azul significa elegido, en las seis partidas y en las tres
   pantallas. Medido: blanco sobre #4060f8 da 4,95:1 en claro; en oscuro
   --a-fill baja a #3b57e6 y da 5,69:1. */
.chip{
  border-radius:var(--rr2);
  padding:0 var(--e3);
  min-height:40px;
  background:var(--sup);
  border:1px solid var(--linea);
  color:var(--tinta);
  font-weight:500;font-size:var(--t3);
  box-shadow:none;
  transition:border-color var(--mv-s),background var(--mv-s),color var(--mv-s);
}
.chip:hover:not(.on):not([aria-disabled]){transform:none;box-shadow:none;border-color:var(--a-borde);background:var(--sup)}
.chip:active:not([aria-disabled]){transform:translateY(1px);box-shadow:none}
.chip.on,.partida .chip.on{
  background:var(--a-fill);color:var(--a-fill-tx);border-color:var(--a-fill);
  box-shadow:none;text-shadow:none;font-weight:600;
}
.chip.on small,.partida .chip.on small{color:var(--a-fill-tx)}
.chip.on .ck,.partida .chip.on .ck{color:var(--a-fill-tx)}
.chip[aria-disabled="true"]{box-shadow:none;background:var(--sup2);color:var(--tinta3);transform:none}
.chip[aria-disabled="true"].on{background:var(--linea);color:var(--tinta2);text-shadow:none;box-shadow:none;animation:none}
/* El material del catálogo es una opción de radio de 44 px, no una pastilla:
   lleva nombre y tarifa, y la tarifa tiene que caer a la derecha. */
.optgrp .chip{background:var(--sup);box-shadow:none}
.partida .chip:hover:not(.on):not([aria-disabled]){background:var(--sup2)}
.partida .tg.on{background:var(--a-fill);box-shadow:none}
.partida :is(input,select,textarea):focus{
  border-color:var(--a);box-shadow:0 0 0 3px var(--a-suave);
}
.partida .pline{border-top:1px solid var(--linea2)}
.partida .partida-top{gap:var(--e2)}
.partida .pnum{gap:6px}

/* El selector de tipo: el elegido en marino, que es el segundo estado del
   rediseño —«esta es la vista que estás mirando»— y se distingue del azul de
   «esto está elegido». Misma regla en la lente del calendario y en los chips
   de etapa de Proyectos. */
.tipo-seg,.seg{
  border-radius:var(--rr2);padding:0;gap:0;
  background:var(--sup);
  border:1px solid var(--linea);
  box-shadow:none;
  overflow:hidden;
}
.tipo-seg button,.seg button{
  border-radius:0;min-height:34px;
  color:var(--tinta2);font-weight:500;
  transition:background var(--mv-s),color var(--mv-s);
}
.tipo-seg button.on,.seg button.on{
  background:var(--nav);color:#fff;font-weight:600;
  box-shadow:none;animation:none;
}
.tipo-seg button:active,.seg button:active{transform:none}
.partida .tipo-seg{background:var(--sup);box-shadow:none}
.partida .tipo-seg button.on{background:var(--nav);color:#fff;text-shadow:none;box-shadow:none}
.items-cand .tipo-seg button.on,.partida.hidden-pdf .tipo-seg button.on{background:var(--tinta3);color:#fff}
/* Las medidas dejan de vivir en un hueco por lo mismo que las opciones. */
.partida .pbody>:is(.grid2,.grid3){
  padding:0;margin-bottom:var(--e4);border-radius:0;
  background:none;box-shadow:none;border:0;
}
.partida .pbody>:is(.grid2,.grid3)>.fld{margin-bottom:0}
/* Sobre superficie plana la etiqueta vuelve a --tinta2, que es la segunda
   tinta del sistema: el --n7 de antes corregía el contraste contra un hueco
   teñido que ya no existe. Medido: #5c6184 sobre --sup da 6,00:1. */
.partida .pbody>.fld>label,.partida .pbody :is(.grid2,.grid3)>.fld>label{color:var(--tinta2)}

/* ---------- Campos ----------
   42 px, un borde de 1 px y 4 px de radio. Al foco, el borde toma el acento y
   sale un anillo de 3 px del azul tenue: se ve dónde está el cursor sin que
   la caja crezca ni se mueva nada de sitio. */
input,select,textarea,.inp-money{
  border:1px solid var(--linea);
  border-radius:var(--rr2);
  background:var(--sup);
  color:var(--tinta);
  box-shadow:none;
  transition:border-color var(--mv-s),box-shadow var(--mv-s);
}
input:hover:not(:disabled),textarea:hover:not(:disabled){box-shadow:none;border-color:var(--n4)}
input:focus,select:focus,textarea:focus{
  outline:none;
  border-color:var(--a);
  box-shadow:0 0 0 3px var(--a-suave);
  animation:none;
}
input:disabled,select:disabled,textarea:disabled{background:var(--sup2);box-shadow:none;color:var(--tinta3)}

/* ---------- Botones ----------
   Uno de color por pantalla; los demás con borde. */
.btn,.mbar-btn,.ai-btn,.btn-scaler-open,.btn-vector-open,.addbtn,.precios-ver,.btn-maps,.card-fold,.btn-hist{
  border-radius:var(--rr2);
  transition:background var(--mv-s),color var(--mv-s),border-color var(--mv-s),transform var(--mv-s);
}
.btn-pri,.mbar-btn:not(.gho):not(.ok){
  background:var(--a-fill);color:#fff;border:1px solid var(--a-fill);
  box-shadow:none;text-shadow:none;font-weight:600;
}
.btn-pri:hover,.mbar-btn:not(.gho):not(.ok):hover{
  background:var(--a-fuerte);border-color:var(--a-fuerte);transform:none;box-shadow:none;
}
/* El verde se queda —autorizar un precio no es «continuar», y quien revisa quince
   cotizaciones seguidas encuentra el botón por el color antes que por el texto— pero pasa al
   relleno que aguanta blanco. Es el único verde de relleno de la app. */
.btn-ok,.mbar-btn.ok{
  background:var(--ok-fill);color:#fff;border:1px solid var(--ok-fill);box-shadow:none;text-shadow:none;font-weight:600;
}
/* El hover aclara un 6 % y no más: el 8 % de antes dejaba el blanco de encima en 4,29:1, por
   debajo del mínimo de esta app. Con 1,06 son 4,69:1 de día y 4,8:1 de noche. */
.btn-ok:hover,.mbar-btn.ok:hover{filter:brightness(1.06);transform:none;box-shadow:none}
.btn-gho,.btn-dgr,.ai-btn,.btn-scaler-open,.btn-vector-open,.precios-ver,.btn-maps,.card-fold,.btn-hist,.mbar-btn.gho{
  background:var(--sup);
  border:1px solid var(--linea);
  color:var(--tinta);
  box-shadow:none;
}
.btn-gho:hover,.btn-dgr:hover,.btn-scaler-open:hover,.btn-vector-open:hover,.precios-ver:hover,.btn-maps:hover,.card-fold:hover,.btn-hist:hover,.mbar-btn.gho:hover{
  transform:none;box-shadow:none;border-color:var(--a-borde);
}
/* ----- Los dos hitos que todavía no tocan -----
   Eran dos rellenos verdes debajo del relleno azul del hito que sí toca, así que la columna
   de la entrega tenía TRES botones de color y el que decía «esto es lo que sigue» no se
   distinguía de los que decían «esto viene después». Con la superficie plana ese verde ya no
   se lee como una tinta suave sino como un relleno más.
   El código de arriba pedía que se encontraran «sin gritar», y eso se conserva: la tinta se
   va del botón entero y se queda en el ICONO —el verde de WhatsApp, el mismo de la venta—,
   que es donde el color señala sin pesar. El botón es neutro como los demás. */
.btn-wa,.btn-vta{background:var(--sup);border:1px solid var(--linea);color:var(--tinta);box-shadow:none}
.btn-wa:hover,.btn-vta:hover{transform:none;box-shadow:none;border-color:var(--ok-borde);background:var(--ok-bg);color:var(--ok)}
.btn-wa .svgi{color:var(--wa)}
.btn-vta .svgi{color:var(--ok)}
.btn-wa:hover .svgi,.btn-vta:hover .svgi{color:inherit}
.btn-dgr{border-color:var(--mal-borde);color:var(--mal)}
.btn-dgr:hover{background:var(--mal-bg);border-color:var(--mal)}
/* Cede 1 px al tocar, y nada más. El pellizco de escala era del barro. */
.btn:active:not(:disabled),.mbar-btn:active:not(:disabled),.ai-btn:active,.btn-scaler-open:active,
.btn-vector-open:active,.addbtn:active,.precios-ver:active,.btn-maps:active,.card-fold:active,.btn-hist:active{
  transform:translateY(1px);box-shadow:none;
}
.btn:disabled,.mbar-btn:disabled{box-shadow:none;transform:none;opacity:.55}
.addbtn{
  background:var(--sup);
  border:1px dashed var(--a-borde);color:var(--a-tx);font-weight:600;
  box-shadow:none;
}
.addbtn:hover{background:var(--a-suave);border-color:var(--a);color:var(--a-tx);transform:none;box-shadow:none}

/* ---------- Interruptores ----------
   32 × 18 con la perilla de 14, que es la medida del rediseño. El de antes
   medía 46 × 26 y en la columna del dinero pesaba más que el renglón que
   gobierna. */
.tg{
  width:32px;height:18px;border-radius:999px;
  background:var(--linea);
  box-shadow:none;
  transition:background .2s;
}
.tg::after{
  width:14px;height:14px;top:2px;left:2px;
  background:#fff;
  box-shadow:0 1px 2px rgba(var(--tinta-rgb),.25);
  transition:left .2s;
}
.tg.on{background:var(--a-fill);box-shadow:none}
.tg.on::after{left:16px}
.switch:active .tg::after{transform:none}

/* ---------- Fichas, insignias y avisos ----------
   La tercera superficie que documentaba la capa anterior —«a ras: relleno
   sólido, borde visible y sin sombra»— es ahora la ÚNICA superficie, así que
   el problema que resolvía no se puede volver a dar: ni los campos ni las
   notas tienen relieve del que copiarse.

   Las fichas bajan a 3 px de radio, que es el escalón que el rediseño les
   reserva: una ficha con 999 px de radio se lee como un botón, y estas no se
   tocan. */
.ptok,.ptipo{
  border-radius:var(--rr1);box-shadow:none;
  border:1px solid var(--linea);background:var(--sup2);color:var(--tinta2);
  font-size:var(--t2);font-weight:600;
}
.folio,.badge{border-radius:var(--rr1);box-shadow:none;border:1px solid var(--linea);background:var(--sup2)}
.folio{font-family:var(--f-cifra);font-weight:600}
.ptok.falta{background:var(--av-bg);border-color:var(--av-borde);color:var(--av)}
/* ----- «Datos que salen en el PDF» deja de ser una caja -----
   Es el último renglón de la pantalla del cliente, y como caja con borde y fondo pesaba lo
   mismo que los cinco campos de arriba para decir «aquí hay dos cosas opcionales». En el
   rediseño es una línea y un rótulo: un separador arriba y el nombre en la segunda tinta.
   Solo este pliegue: el de la configuración de la IA sí es una caja aparte —vive dentro de un
   modal, entre otros bloques— y ahí el borde es lo que lo separa de ellos. */
#pdf-extra-box{border:0;border-top:1px solid var(--linea2);border-radius:0;
  background:none;padding:var(--e3) 0 0}
#pdf-extra-box>summary{min-height:34px;font-size:var(--t2);font-weight:600;color:var(--tinta2)}
#pdf-extra-box>summary:hover{color:var(--tinta)}

/* ----- El catálogo de material, en rejilla -----
   Los cinco materiales eran una fila que envolvía, y con nombres de largo muy distinto
   —«Acrílico + Vinil» contra «Aluminio Blanco/Negro/Pintado»— cada renglón caía distinto y las
   tarifas quedaban desalineadas por toda la caja. La rejilla del rediseño —`auto-fill` desde
   180 px— les da a todos el mismo ancho, así que los cinco precios caen en columna y se
   comparan de un barrido, que es exactamente para lo que se mira este bloque. `auto-fill` y no
   `auto-fit` a propósito: con cuatro opciones en una fila de cinco huecos, `auto-fit` estira
   las cuatro para llenar el renglón y el ancho de la opción cambia según cuántas haya.

   Solo donde hay catálogo: la clase la pone `grupo()` en js/cotizador/partidas.js, y la
   complejidad y la iluminación —tres chips cortos— se quedan en fila, como en la maqueta. */
.chips-catalogo{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:6px}
.chips-catalogo .chip{min-height:44px;justify-content:flex-start;text-align:left}
/* La tarifa, pegada a la derecha de su opción: así las cinco caen en columna. */
.chips-catalogo .chip small{margin-left:auto;padding-left:var(--e2)}

/* Lo que la partida SÍ lleva puesto va en el azul tenue; lo que le falta, en ámbar; y lo que
   está apagado a propósito —«Sin iluminación · −20%»— en la superficie hundida. Tres
   estados y tres colores, y el tipo de la partida se queda neutro porque no es una elección
   del catálogo sino lo que la partida es. `.ok` es la clase que pone caraPlegadaHTML. */
.ptok.ok,.ptok.on{background:var(--a-suave);border-color:var(--a-borde);color:var(--a-tx)}
.ptok.ok::before,.ptok.on::before{color:var(--a-tx)}
.badge.pendiente{background:var(--av-bg);border-color:var(--av-borde)}
.badge.autorizada{background:var(--ok-bg);border-color:var(--ok-borde)}
.badge.borrador{background:var(--sup2);border-color:var(--linea)}
.hintnote{border-radius:0 var(--rr2) var(--rr2) 0;box-shadow:none;border:1px solid var(--linea);
  border-left:3px solid var(--n5);background:var(--sup2)}
.hintnote.nota-av{background:var(--av-bg);border-color:var(--av-borde);border-left-color:var(--av)}
.hintnote.nota-ok{background:var(--ok-bg);border-color:var(--ok-borde);border-left-color:var(--ok)}

/* ----- Lo único que late -----
   Una pantalla puede tener UNA cosa que se mueva sola, y esta es la que pide
   una decisión antes de seguir. El latido deja de ser una sombra teñida que
   crece y mengua —que sobre una pieza plana no se ve— y pasa a ser el aro que
   usa el rediseño: un anillo del acento que sale de la pieza y se disuelve. */
@keyframes late{
  0%,100%{box-shadow:0 0 0 0 rgba(var(--a-rgb),.45)}
  60%{box-shadow:0 0 0 8px rgba(var(--a-rgb),0)}
}
/* El nombre viejo se queda: lo pide `.pf-decidir` en css/plataforma.css. */
@keyframes latido{
  0%,100%{box-shadow:0 0 0 0 rgba(var(--a-rgb),.45)}
  60%{box-shadow:0 0 0 8px rgba(var(--a-rgb),0)}
}
.cand-partidas,.edit-mode-banner{
  border-radius:var(--rr3);border:1px solid var(--a-borde);
  background:var(--a-suave);
  box-shadow:none;
}
.edit-mode-banner{border-color:var(--av-borde);background:var(--av-bg)}
.cand-partidas{animation:late 2.8s ease-in-out infinite}
.cand-partidas:hover{transform:none;animation:none;box-shadow:0 0 0 3px rgba(var(--a-rgb),.2)}

/* ---------- Barra de pasos ----------
   Cuatro pestañas dentro de una tarjeta blanca de 6 px de relleno. La actual
   lleva el azul tenue y su número relleno; las hechas, una palomita verde;
   las que no tocan todavía, ámbar. Es el mismo semáforo que el resto de la
   app: verde hecho, ámbar falta. */
.pasos{background:var(--sup);border:1px solid var(--linea);border-radius:var(--rr3);padding:6px;gap:var(--e1)}
.paso-tab{border-radius:var(--rr2);min-height:38px;transition:background var(--mv-s),color var(--mv-s)}
.paso-tab:hover{transform:none;background:var(--sup2)}
.paso-tab.on{
  background:var(--a-suave);
  border-color:transparent;color:var(--a-tx);
  box-shadow:none;
}
.paso-tab.on:hover{background:var(--a-suave)}
.paso-tab.on .tx small{color:var(--a-tx)}
.paso-tab .n{
  border-radius:999px;width:22px;height:22px;
  background:var(--sup2);border:1px solid var(--linea);color:var(--tinta2);
  font-family:var(--f-cifra);font-weight:600;font-size:var(--t2);
  box-shadow:none;transition:background var(--mv-s),color var(--mv-s);
}
.paso-tab.on .n{background:var(--a-fill);color:#fff;border-color:var(--a-fill);box-shadow:none}
.paso-tab.hecho .n{background:var(--ok-bg);color:var(--ok);border-color:var(--ok-borde);box-shadow:none;animation:none}
/* Los pasos que todavía no tocan van en ámbar, que es el color con el que esta app dice
   «falta algo» en todas partes. La clase se llama `espera` y la pone js/cotizador/proceso.js. */
.paso-tab.espera .n{background:var(--av-bg);color:var(--av);border-color:var(--av-borde)}
.paso-tab:active{transform:none}

/* El total chiquito de la barra de pasos, en el paso 1. Es la MISMA cifra que el total de la
   columna del dinero, y por eso lleva el mismo `data-shared`: al pasar a partidas, el de aquí
   es el punto de partida del vuelo y el de allá el de llegada. En el paso 2 no se pinta —el
   grande ya está en pantalla, y dos totales a la vez son dos números que se pueden leer
   distinto si uno se queda atrás—. */
/* `align-self:center` no es cosmético: `.pasos` es una fila con `align-items:stretch`, así que
   sin esto la caja del total chiquito mide lo que el resto de la barra —51 px— aunque su letra
   mida 15. Y esa caja es de donde el FLIP saca la ESCALA de partida: con ella estirada, el
   número salía volando desde 51/28 = 1,8 veces su tamaño, o sea encogiéndose desde más grande
   que su destino, que es exactamente al revés de lo que la transición cuenta. Hugging la caja,
   la escala sale de la letra, que es lo que se ve moverse. */
.paso-total{margin-left:auto;align-self:center;display:inline-flex;align-items:baseline;gap:6px;padding:0 10px;
  font-family:var(--f-cifra);font-weight:600;font-size:var(--t4);color:var(--tinta2);
  white-space:nowrap;font-variant-numeric:tabular-nums}
.paso-total small{font-family:var(--f-texto);font-weight:500;font-size:var(--t1);color:var(--tinta3)}
/* Que `hidden` lo esconda de verdad lo resuelve la regla `[hidden]` del principio de la hoja,
   para todo el documento y de una vez. */

/* ---------- Barra fija y encabezado ----------
   Sin cristal esmerilado. El `backdrop-filter` obliga al navegador a
   componer en cada cuadro lo que hay debajo de la barra, y lo que hay debajo
   en esta app es una lista larga que se desplaza. Un borde y un fondo sólido
   dicen lo mismo. */
.topbar{
  background:var(--sup);
  backdrop-filter:none;-webkit-backdrop-filter:none;
  border-bottom:1px solid var(--linea);
  box-shadow:none;
}
.mbar{
  background:var(--sup);
  backdrop-filter:none;-webkit-backdrop-filter:none;
  border-top:1px solid var(--linea);
  box-shadow:none;
}

/* ---------- La columna del dinero ----------
   Una sola pieza con sus renglones, y el total como el número más grande de
   la pantalla. Las tres profundidades de antes decían con relieve lo que
   ahora dicen el tamaño y el orden. */
.sum{padding:var(--e4)}
.sum>*{border-top:none}
.prog-box{
  border-radius:var(--rr2);
  background:var(--sup2);
  box-shadow:none;
  border:0;
  margin-bottom:var(--e3);
}
.prog-box:hover{background:var(--a-suave)}
.sum-rows,.sum-rows-2{padding-left:0;padding-right:0}
.sum-rows-2{margin-top:0;border-top:1px solid var(--linea2)}

.neto{
  margin:var(--e3) 0;
  padding:var(--e3) 0 0;
  border-top:1px solid var(--linea);
  border-radius:0;
  background:none;
  border-left:0;border-right:0;border-bottom:0;
  box-shadow:none;
}
.neto .lab{color:var(--tinta2);font-weight:600;font-size:var(--t2);letter-spacing:.3px;text-transform:uppercase}

.anti{
  border-top:0;
  margin-bottom:var(--e3);
  padding:0;
  border-radius:0;
  background:none;
  box-shadow:none;
  border:0;
}
.anti label{color:var(--tinta2);font-weight:600}
.auth,.auth-adj,.precios-nota{padding-left:0;padding-right:0}
.auth{border-top:1px solid var(--linea2);margin-top:var(--e3)}

/* ---------- El total ----------
   28 px de Outfit en la tinta de la app. Era texto con un degradado
   recortado y una sombra de caída: un número que no se puede seleccionar con
   el ratón porque su color es `transparent`, y que en el tema oscuro perdía
   contraste contra su propio fondo. El tamaño ya lo hace el número más
   importante de la pantalla; no le hace falta un color propio.

   `data-shared` es lo que engancha la transición de elemento compartido: este
   mismo número vive en la barra de pasos del paso 1, chiquito, y viaja hasta
   aquí al pasar a partidas. */
.neto .amt{
  background:none;-webkit-background-clip:border-box;background-clip:border-box;
  color:var(--tinta);
  font-family:var(--f-cifra);font-weight:600;font-size:var(--t7);line-height:1;
  font-variant-numeric:tabular-nums;
  filter:none;
  display:inline-block;
}
.neto .amt.cambio{animation:total-late var(--mv)}
@keyframes total-late{
  0%{transform:scale(1)} 35%{transform:scale(1.04)} 70%{transform:scale(.995)} 100%{transform:scale(1)}
}

/* ---------- Barra de completitud ----------
   6 px de alto y un brillo que la recorre: es lo que dice que la app está
   trabajando contigo mientras se captura.

   El color lo pone AQUÍ y no js/cotizador/partidas.js, que lo escribía como estilo en línea
   —tres degradados según el porcentaje— y por eso todas las reglas de esta hoja quedaban
   muertas. Y eran tres colores para una medida: ámbar por debajo de 40, azul hasta 80, verde
   arriba. El ámbar en esta app significa «falta un dato obligatorio» —lo dicen las pestañas
   de paso y las fichas `.ptok.falta`—, no «vas por el 30 %», así que una cotización recién
   empezada gritaba lo mismo que una a la que le falta el material. Queda una barra en el
   acento mientras se captura y verde cuando ya está: el mismo semáforo que la barra de pasos,
   y el bloque de al lado sigue diciendo con palabras QUÉ falta. */
#prog-bar{border-radius:3px;box-shadow:none;position:relative;overflow:hidden;background:var(--a-fill);
  transition:width .4s cubic-bezier(.2,.8,.2,1),background var(--mv)}
#prog-bar.lleno{background:var(--ok-fill)}
#prog-bar::after{
  content:'';position:absolute;inset:0;width:30%;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.55),transparent);
  animation:brillo 2.4s linear infinite;
}
@keyframes brillo{from{transform:translateX(-100%)}to{transform:translateX(300%)}}
.prog-track{border-radius:3px;box-shadow:none;background:var(--linea);height:6px}

/* =====================================================================
   ================  PRECIO Y ENTREGA  =================================

   Los pasos 3 y 4 heredaban la barra y los tokens y nada más, que era el trato del traspaso.
   Con la superficie plana eso ya no alcanza, porque las señales que estos dos pasos usaban
   eran todas de RELLENO —un bloque verde para el descuento, uno ámbar para el aumento, dos
   botones teñidos para los hitos que faltan— y sobre una hoja donde ya no hay relieve un
   relleno de color no es un matiz: es la cosa más fuerte de la pantalla. La columna del
   dinero tenía cuatro.

   La regla es la misma que en las otras seis pantallas: el color va en el DATO —la cifra, la
   ficha, el icono— y la superficie se queda plana con su borde. Así vuelve a haber un solo
   relleno por pantalla, y es el botón que hace lo que se vino a hacer: «Autorizar yo mismo»
   en el paso 3 del vendedor, «Autorizar precio» en el del autorizador, y el primero de los
   tres hitos que falte en el 4.
   ===================================================================== */

/* ---------- El rótulo que parte la columna ----------
   `.auth-divider` separa «Autorizando tú mismo» y «Ajuste por partida». Era 10,5 px en negrita
   máxima con 0,7 de espaciado —un rótulo que pesaba más que los datos que encabezaba—. Baja al
   escalón chico de la escala y a la tercera tinta, que es la que esta hoja mide en 4,97:1. */
.auth-divider{
  font-size:var(--t1);font-weight:600;letter-spacing:.6px;text-transform:uppercase;
  color:var(--tinta3);
  border-top:1px solid var(--linea2);
  margin:var(--e4) 0 var(--e3);padding-top:var(--e4);
}

/* ---------- La nota de la autorización ----------
   Es el bloque que dice quién autorizó y cuándo, o qué falta para poder autorizar. Superficie
   hundida y borde: ya no compite con el botón que tiene debajo. */
.authnote{
  font-size:var(--t2);line-height:1.55;color:var(--tinta2);
  background:var(--sup2);border:1px solid var(--linea);border-radius:var(--rr2);
  padding:var(--e3) var(--e4);margin-bottom:var(--e3);box-shadow:none;
}
.authnote b{color:var(--tinta);font-weight:600}
.mini,.anti-rest{font-size:var(--t1);color:var(--tinta3);line-height:1.5}
.anti-rest{font-weight:500;margin-top:var(--e2)}

/* ---------- El ajuste del autorizador ----------
   Un descuento se decía pintando el bloque entero de verde y un aumento pintándolo de ámbar.
   Ahora el bloque es el mismo en los dos casos —plano, con su filete arriba— y lo que cambia
   de color es la CIFRA, que es el dato que se vino a leer. El verde y el ámbar siguen
   significando lo mismo que en el resto de la app y ya no tapan al botón de autorizar. */
.auth-adj{
  border-top:1px solid var(--linea2);border-bottom:0;
  padding:var(--e3) 0 var(--e2);background:none;
}
.auth-adj .adj-label{font-size:var(--t2);font-weight:600;color:var(--tinta2)}
.auth-adj .adj-amt{
  font-family:var(--f-cifra);font-size:var(--t5);font-weight:600;color:var(--ok);
  font-variant-numeric:tabular-nums;
}
.auth-adj .adj-desc{font-size:var(--t1);color:var(--tinta3);padding-bottom:var(--e3)}
.auth-adj.inc{background:none}
.auth-adj.inc .adj-label{color:var(--tinta2)}
.auth-adj.inc .adj-amt{color:var(--av)}
.auth-adj.inc .adj-desc{color:var(--tinta3)}
/* Lo mismo debajo del campo del precio final: la frase «Descuento: $2,400 (12%)» lleva el
   color, no una caja. */
.descuento-info{font-size:var(--t2);font-weight:600;color:var(--ok);margin-top:var(--e2);min-height:16px}
.descuento-info.inc{color:var(--av)}

/* ---------- La cola del autorizador ----------
   La lista de lo que hay por revisar. Era una caja de borde de 1,5 px con el folio en
   mayúsculas azules a 10 px; ahora es la misma lista de renglones que el resto de la app, con
   el filete del acento marcando el que se está revisando. El azul aquí significa lo de
   siempre: esto es lo elegido. */
.queue-list{border:1px solid var(--linea);border-radius:var(--rr3);overflow:hidden;margin-bottom:var(--e3)}
.queue-empty{
  font-size:var(--t2);color:var(--tinta3);text-align:center;
  padding:var(--e5) var(--e4);background:var(--sup2);
}
.queue-item{
  gap:var(--e3);padding:var(--e3) var(--e4);
  border-bottom:1px solid var(--linea2);background:var(--sup);
  transition:background var(--mv-s);
}
.queue-item:hover:not(.active){background:var(--sup2)}
.queue-item.active{
  background:var(--a-suave);
  border-left:0;padding-left:var(--e4);
  box-shadow:inset 3px 0 0 var(--a-fill);
}
.qi-dot{width:8px;height:8px;border:2px solid var(--a-borde);margin-top:0}
.queue-item.active .qi-dot{background:var(--a-fill);border-color:var(--a-fill)}
.qi-folio{
  font-family:var(--f-cifra);font-size:var(--t1);font-weight:600;
  color:var(--tinta3);letter-spacing:.4px;
}
.queue-item.active .qi-folio{color:var(--a-tx)}
.qi-name{font-size:var(--t2);font-weight:600;color:var(--tinta)}
.qi-fecha{font-size:var(--t1);color:var(--tinta3)}
.qi-total{font-family:var(--f-cifra);font-size:var(--t2);font-weight:600;color:var(--tinta);font-variant-numeric:tabular-nums}

/* ---------- El ajuste partida por partida ----------
   Un renglón plegable por partida, con su número, su cálculo y el campo del precio
   autorizado. El número deja el degradado de marca por el relleno liso, y el cuerpo abierto
   se hunde a --sup2 en vez de teñirse. */
.ia-row{border:1px solid var(--linea);border-radius:var(--rr2);margin-bottom:var(--e2);background:var(--sup)}
.ia-hdr{gap:var(--e2);padding:var(--e2) var(--e3);min-height:38px;transition:background var(--mv-s)}
.ia-hdr:hover{background:var(--sup2)}
.ia-num{
  width:20px;height:20px;border-radius:var(--rr1);
  background:var(--a-fill);color:#fff;
  font-family:var(--f-cifra);font-size:var(--t1);font-weight:600;
}
.ia-desc{font-size:var(--t2);font-weight:500;color:var(--tinta)}
.ia-calc{font-family:var(--f-cifra);font-size:var(--t1);color:var(--tinta3);font-weight:500;font-variant-numeric:tabular-nums}
.ia-arrow{font-size:var(--t1);color:var(--tinta3)}
.ia-body{padding:var(--e3);border-top:1px solid var(--linea2);background:var(--sup2)}
.ia-adj{font-size:var(--t1);font-weight:600;color:var(--ok);margin-top:var(--e2);min-height:14px}
.ia-adj.inc{color:var(--av)}
/* Los dos renglones de suma: el subtotal ajustado y el mismo con IVA. Eran dos cajas de
   colores distintos —una gris y otra azul— para dos cifras del mismo rango. Ahora son dos
   renglones de la misma lista y lo que los separa es el peso de la letra. */
.ia-total{
  font-size:var(--t2);font-weight:600;color:var(--tinta);
  padding:var(--e3) var(--e4);margin:var(--e3) 0 0;
  background:var(--sup2);border:1px solid var(--linea);border-radius:var(--rr2);
}
.ia-total span:last-child{font-family:var(--f-cifra);font-variant-numeric:tabular-nums}
.ia-total.soft{
  background:none;border-color:transparent;color:var(--tinta2);
  margin-top:0;margin-bottom:var(--e3);padding-top:var(--e2);padding-bottom:var(--e2);
}

/* ---------- El prefijo del peso ----------
   El «$» de los campos de dinero iba en negrita a 13 px, más pesado que la cifra que
   introduce. Es una unidad, no un dato. */
.inp-money::before{color:var(--tinta3);font-weight:500;font-size:var(--t3);left:11px}

/* ---------- Los tres hitos de la entrega ----------
   La fecha de un hito hecho y la pista del que toca van al escalón chico y a la tercera
   tinta; dentro del botón relleno heredan el blanco, que es lo que ya hacía la regla de
   arriba. El nombre del hito hecho vuelve a la tinta principal: lo que dice que está hecho
   son la palomita y la fecha, no un texto apagado. */
.hito-fecha,.hito-pista{font-size:var(--t1);font-weight:400;color:var(--tinta3)}
.btn-pri .hito-pista,.btn-ok .hito-pista{color:#fff}
.hito-hecho{color:var(--tinta)}
.hito-ok{color:var(--ok)}
/* El pliegue de «otras salidas» es el último renglón de la columna y no una caja más: la
   misma decisión que «Datos que salen en el PDF» en la pantalla del cliente. */
details.ai-cfg.otras-salidas{
  background:none;border:0;border-top:1px solid var(--linea2);border-radius:0;
  padding:var(--e3) 0 0;margin-top:var(--e3);
}
details.ai-cfg.otras-salidas summary{
  min-height:34px;font-size:var(--t2);font-weight:600;color:var(--tinta2);padding:0;
}
details.ai-cfg.otras-salidas summary:hover{color:var(--tinta)}
.os-chev{color:var(--tinta3)}
/* «Nueva cotización» cierra ésta y abre otra: la línea que la separa de lo que se hace con la
   de encima se queda, con el aire de la escala. */
.auth-cierre{margin-top:var(--e4);padding-top:var(--e4);border-top:1px solid var(--linea)}

/* ---------- Modales ----------
   `.modal` traía su propio radio de 20 px y su propia sombra en línea con la regla base, así
   que el radio del rediseño solo lo alcanzaba aquí; ahora las seis superficies flotantes de la
   app —IA, registrar venta, escalador, vectorizador, historial y la imagen a pantalla
   completa— salen de una sola declaración. */
.modal,.rv-modal,.sc-modal,.vt-modal,.hist-panel,.lightbox-body{
  border-radius:var(--rr3);
  border:1px solid var(--linea);
  box-shadow:var(--sombra-alta);
  animation:entra .32s cubic-bezier(.2,.8,.2,1) both;
}
.modal{border-radius:var(--rr3);box-shadow:var(--sombra-alta)}
/* El velo se queda; el desenfoque se va. Es la misma atmósfera que el barro: cuesta una capa
   de composición por cuadro en un teléfono, y lo que separa el modal del fondo son su borde,
   su sombra y el velo, que ya lo hacen sin desenfocar nada. */
.modal-bg,.rv-modal-bg,.sc-modal-bg,.vt-modal-bg,#lightbox{
  backdrop-filter:none;-webkit-backdrop-filter:none;
  background:rgba(var(--nav-rgb),.55);
}
.modal-bg.show,.rv-modal-bg.show{animation:vela var(--mv-s)}
@keyframes vela{from{opacity:0}to{opacity:1}}

/* ----- El encabezado y el cierre, una sola vez -----
   `.modal-h` y `.hist-head` son el mismo renglón y venían con dos alturas, dos tamaños de
   letra y dos botones de cerrar de 30 y 36 px. Un modal no debería verse distinto según cuál
   de los seis se abrió. */
.modal-h,.hist-head,.cua-det-head{
  min-height:56px;padding:var(--e3) var(--e5);
  border-bottom:1px solid var(--linea);background:var(--sup);
}
.modal-h b,.hist-head b{font-family:var(--f-cifra);font-size:var(--t4);font-weight:600;color:var(--tinta);letter-spacing:-.1px}
.modal-h button,.hist-close{
  width:36px;height:36px;border-radius:var(--rr2);font-size:var(--t5);
  color:var(--tinta2);background:none;border:0;
  transition:background var(--mv-s),color var(--mv-s);
}
.modal-h button:hover,.hist-close:hover{background:var(--sup2);color:var(--tinta)}
.modal-b,.hist-search-bar{background:var(--sup)}

/* ----- El pie del historial -----
   Cuatro botones azules en fila para respaldar, restaurar, exportar y abrir los clientes. El
   azul aquí no elegía nada ni era la acción de la pantalla: eran cuatro salidas del mismo
   rango, y pintadas todas de marca no se distinguían entre sí ni de lo que sí manda. */
.hist-foot{
  gap:var(--e2);padding:var(--e3) var(--e5);
  border-top:1px solid var(--linea);background:var(--sup2);border-radius:0 0 var(--rr3) var(--rr3);
}
.hist-foot button{
  min-height:38px;border:1px solid var(--linea);background:var(--sup);color:var(--tinta2);
  font-size:var(--t2);font-weight:500;border-radius:var(--rr2);
  transition:border-color var(--mv-s),color var(--mv-s);
}
.hist-foot button:hover{border-color:var(--a-borde);color:var(--tinta);background:var(--sup)}
/* Dos clases y no una: `.hist-foot .foot-nota` vive más arriba en la hoja y con la misma
   especificidad ganaría, así que el renglón se quedaba en 10,5 px, que no es un escalón de
   esta escala. */
.hist-foot .foot-nota{font-size:var(--t1);color:var(--tinta3);line-height:1.5}
/* La cuenta de resultados de la búsqueda: una ficha, no una píldora. */
.hist-count{
  font-family:var(--f-cifra);font-size:var(--t1);font-weight:600;
  color:var(--tinta2);background:var(--sup2);border:1px solid var(--linea);
  padding:4px 10px;border-radius:var(--rr1);
}
.hist-empty,.cua-vacio{color:var(--tinta3);font-size:var(--t3);padding:var(--e7) var(--e5)}

/* ----- Un renglón del historial -----
   Cada cotización guardada. La miniatura baja a 6 px de radio como el resto de las piezas, el
   folio pasa a la cifra y la insignia de autorizada deja de ser una píldora verde rellena para
   ser la misma ficha que usa la barra de estado del paso 3. */
.hentry{border-bottom:1px solid var(--linea2);padding:var(--e4) var(--e5)}
.hentry-img,.hentry-img-ph{border-radius:var(--rr2);border:1px solid var(--linea)}
.hentry-img-ph{background:var(--sup2);color:var(--tinta3)}
.hentry-folio,.cua-cot-folio{
  font-family:var(--f-cifra);font-size:var(--t1);font-weight:600;
  color:var(--tinta3);letter-spacing:.4px;text-transform:none;
}
.hentry-name{font-size:var(--t3);font-weight:600;color:var(--tinta)}
.hentry-sub{font-size:var(--t2);color:var(--tinta2)}
.hentry-auth{
  font-size:var(--t1);font-weight:500;border-radius:var(--rr1);padding:3px 9px;
  background:var(--ok-bg);border:1px solid var(--ok-borde);color:var(--ok);
}
.hentry-open,.hentry-del{border-radius:var(--rr2)}
.hentry-open,.cua-det-acts button,.cua-cot-acts button{
  border:1px solid var(--linea);background:var(--sup);color:var(--tinta2);
  font-size:var(--t2);font-weight:500;border-radius:var(--rr2);
  transition:border-color var(--mv-s),color var(--mv-s);
}
.hentry-open:hover,.cua-det-acts button:hover,.cua-cot-acts button:hover{
  border-color:var(--a-borde);color:var(--tinta);background:var(--sup);
}
.htable{font-size:var(--t2)}
.htable td{border-bottom:1px solid var(--linea2);color:var(--tinta2)}
.htable td:first-child{font-family:var(--f-cifra);font-weight:600;color:var(--tinta3)}
.htable td:last-child{font-family:var(--f-cifra);font-weight:600;color:var(--tinta);font-variant-numeric:tabular-nums}
.hentry-total{
  font-size:var(--t3);font-weight:600;color:var(--tinta);
  border-top:1px solid var(--linea);padding-top:var(--e3);
}
.hentry-total span:last-child{font-family:var(--f-cifra);font-variant-numeric:tabular-nums}
/* El ahorro o el aumento que dejó el autorizador, al lado del total. Verde si el cliente pagó
   menos y ámbar si pagó más: es el único sitio del renglón donde el color compara algo. */
.hentry-ajuste{font-family:var(--f-texto);font-size:var(--t1);font-weight:500;color:var(--ok)}
.hentry-ajuste.inc{color:var(--av)}

/* ----- Los cuadernos de cliente -----
   La misma lista, con las mismas piezas. La inicial del cliente era un cuadro de 12 px de
   radio con la letra en azul de marca: se lee como un botón y el azul no elige nada. */
.cua-card{padding:var(--e3) var(--e5);border-bottom:1px solid var(--linea2)}
.cua-card:hover{background:var(--sup2)}
.cua-ini{
  width:38px;height:38px;border-radius:var(--rr2);
  background:var(--sup2);border:1px solid var(--linea);color:var(--tinta2);
  font-family:var(--f-cifra);font-weight:600;
}
.cua-nombre{font-size:var(--t3);font-weight:600;color:var(--tinta)}
.cua-sub,.cua-cot-fecha{font-size:var(--t2);color:var(--tinta2)}
.cua-alias{font-size:var(--t1);color:var(--tinta3)}
.cua-flecha,.cua-card-num span{color:var(--tinta3)}
.cua-card-num b,.cua-cot-tot{font-family:var(--f-cifra);font-size:var(--t3);font-weight:600;color:var(--tinta);font-variant-numeric:tabular-nums}
.cua-card-num span{font-size:var(--t1);font-weight:500;letter-spacing:.3px}
.cua-det-head{background:var(--sup2);border-bottom:1px solid var(--linea)}
.cua-volver{font-size:var(--t2);font-weight:600;color:var(--a-tx)}
.cua-det-nom{font-family:var(--f-cifra);font-size:var(--t5);font-weight:600;color:var(--tinta)}
.cua-det-datos{font-size:var(--t2);color:var(--tinta2)}
.cua-cifras{padding:var(--e3) var(--e5);border-bottom:1px solid var(--linea2)}
.cua-cifra{background:var(--sup2);border:1px solid var(--linea);border-radius:var(--rr2);padding:var(--e3)}
.cua-cifra b{font-family:var(--f-cifra);font-size:var(--t4);font-weight:600;color:var(--tinta);font-variant-numeric:tabular-nums}
.cua-cifra span,.cua-nota-wrap label,.cua-cots-tit{
  font-size:var(--t1);font-weight:600;color:var(--tinta3);
  text-transform:uppercase;letter-spacing:.6px;
}
.cua-nota-wrap{border-bottom:1px solid var(--linea2)}
.cua-nota-estado{font-size:var(--t1);color:var(--tinta3)}
.cua-cot{border-bottom:1px solid var(--linea2)}
.cua-cot-proy{font-size:var(--t3);font-weight:600;color:var(--tinta)}

/* ----- El panel de la IA -----
   El pliegue de la configuración, el campo de la clave y los dos avisos. Cuatro superficies
   teñidas —verde la clave guardada, verde el origen del análisis, ámbar el interruptor de
   conservar partidas, azul el resumen del pliegue— en un modal de 460 px. El tinte se queda
   solo donde dice un ESTADO: la clave que ya está guardada y el aviso de que se van a
   conservar las partidas. El resto pasa a la superficie hundida. */
details.ai-cfg{border:1px solid var(--linea);border-radius:var(--rr2);background:var(--sup2);padding:var(--e3) var(--e4)}
details.ai-cfg summary{font-size:var(--t2);font-weight:600;color:var(--tinta2)}
details.ai-cfg summary:hover{color:var(--tinta)}
.ai-status{font-size:var(--t2);font-weight:500}
.ai-status.work{color:var(--a-tx)}
.ai-link{color:var(--a-tx);font-weight:500}
.key-btn{
  border:1px solid var(--linea);background:var(--sup);color:var(--tinta2);
  border-radius:var(--rr2);font-size:var(--t2);font-weight:500;min-height:34px;
  transition:border-color var(--mv-s),color var(--mv-s);
}
.key-btn:hover{border-color:var(--a-borde);color:var(--tinta);background:var(--sup)}
.key-btn.add{background:var(--sup);padding:0 14px}
.key-btn.del{color:var(--mal);border-color:var(--mal-borde)}
.key-btn.del:hover{background:var(--mal-bg);border-color:var(--mal);color:var(--mal)}
.key-saved{background:var(--ok-bg);border:1px solid var(--ok-borde);border-radius:var(--rr2)}
.key-mask{font-family:var(--f-cifra);font-size:var(--t2);font-weight:600;color:var(--ok)}
.key-note{font-size:var(--t1);color:var(--tinta3);border-top:1px solid var(--linea2)}
.ai-tag{
  font-size:var(--t1);font-weight:500;color:var(--tinta2);
  background:var(--sup);border:1px solid var(--linea);border-radius:var(--rr1);padding:1px 6px;
}
.ai-merge{background:var(--av-bg);border:1px solid var(--av-borde);border-radius:var(--rr2)}
.ai-merge .switch{font-size:var(--t2);font-weight:600;color:var(--av)}
.ai-merge-note{font-size:var(--t1);color:var(--av)}
/* El origen del análisis no es un estado: es la miniatura de lo que se acaba de medir. */
.ai-src{background:var(--sup2);border:1px solid var(--linea);border-radius:var(--rr2)}
.ai-src-img{border-radius:var(--rr2);border:1px solid var(--linea)}

/* ---------- Los dos aparatos de pantalla completa ----------
   El escalador y el vectorizador son herramientas, no pantallas, y su lienzo oscuro se queda:
   una foto sin cotas se mide mejor sobre fondo hondo, y un trazo de corte se ve mejor. Lo que
   entra a la dirección nueva es su CHROME —la barra, el panel de la derecha y sus fichas—, que
   es lo que comparte lenguaje con el resto de la app.

   Los desenfoques se van, por lo mismo que en los modales y por una razón más aquí: estas dos
   barras están encima de un lienzo que se repinta en cada movimiento del dedo mientras se
   arrastra una cota, y un `backdrop-filter` cuesta una capa de composición por cuadro justo
   ahí. Superficie sólida y borde hacen el mismo trabajo. */
.scaler-modal-bg,.vt-modal-bg{backdrop-filter:none;-webkit-backdrop-filter:none;background:rgba(var(--nav-rgb),.75)}
.sp-topbar{
  background:var(--sup);backdrop-filter:none;-webkit-backdrop-filter:none;
  border-bottom:1px solid var(--linea);box-shadow:none;height:64px;
}
.sp-hint-bar{backdrop-filter:none;-webkit-backdrop-filter:none;background:rgba(var(--nav-rgb),.9);font-size:var(--t2);font-weight:500}
.sp-hint-act{border-radius:var(--rr2);font-size:var(--t2);font-weight:500}
.sp-side{border-left:1px solid var(--linea);box-shadow:none}
.sp-sec{border-bottom:1px solid var(--linea)}
/* ----- Un rótulo por sección, y un solo azul -----
   Cuatro encabezados en azul de marca, cada uno con su filete de 3 px del acento, en un panel
   de 306 px: cuatro veces el color que en esta app significa «esto está elegido». Ahora el
   rótulo es el mismo de la columna del dinero —chico, en versalitas, en la tercera tinta— y el
   filete se queda gris; el acento marca la sección ABIERTA, que es la única de las cuatro sobre
   la que se está trabajando. */
.sp-sec-h h3{
  font-size:var(--t1);font-weight:600;letter-spacing:.6px;color:var(--tinta3);
  gap:var(--e2);
}
.sp-sec-h h3::before{width:3px;height:12px;background:var(--linea);border-radius:0}
.sp-fold[open]>summary h3{color:var(--tinta2)}
.sp-fold[open]>summary h3::before{background:var(--a-fill)}
.sp-fold>summary::after{color:var(--tinta3);font-weight:400}
.sp-fold>summary:active{background:var(--sup2)}
/* Las fichas de cuenta y de valor —cuántas guías hay, cuánto detalle— eran píldoras de 20 px
   de radio en azul y 800: la misma ficha que el resto de la app, que no se toca. */
.sp-fold-n,.vt-val{
  font-family:var(--f-cifra);font-size:var(--t1);font-weight:600;
  color:var(--tinta2);background:var(--sup2);border:1px solid var(--linea);
  border-radius:var(--rr1);padding:3px 9px;
}
/* Una medida de la lista. El filete del acento se queda —dice «esto es una cota tuya» y lo
   distingue del aguamarina de las guías— y se va el relieve. */
.sp-mitem{
  border:1px solid var(--linea);border-left:3px solid var(--a-fill);
  border-radius:var(--rr2);box-shadow:none;transition:border-color var(--mv-s),background var(--mv-s);
}
.sp-mitem:hover{box-shadow:none;background:var(--sup2)}
.sp-mitem.sel{border-color:var(--a-borde);border-left-color:var(--a-fill);background:var(--a-suave);box-shadow:none}
.sp-mitem-cm{font-family:var(--f-cifra);font-size:var(--t4);font-weight:600;color:var(--tinta);letter-spacing:0}
.sp-mitem-cm small{font-family:var(--f-texto);font-size:var(--t1);font-weight:400;color:var(--tinta3)}
.sp-mitem-label{font-size:var(--t2);color:var(--tinta)}
.sp-mlist-empty{
  color:var(--tinta3);font-size:var(--t2);
  border:1px solid var(--linea);border-radius:var(--rr2);background:var(--sup2);
}
.sp-gitem{border:1px solid var(--linea);border-left:3px solid var(--sc-guide);border-radius:var(--rr2);font-size:var(--t2)}
.sp-gitem .lbl{color:var(--tinta);font-weight:500}
.sp-gclear,.sp-ai-note{font-size:var(--t1);color:var(--tinta3);font-weight:500}
.sp-ibtn,.sp-gclear{border-radius:var(--rr2)}
.sp-ibtn{color:var(--tinta3)}
/* ----- La salida del aparato, y la de al lado -----
   El botón relleno era «Cotizar esta medida con IA» y el de contorno «Agregar todas las
   medidas como partidas». Está al revés: quien abre el escalador viene a medir para cotizar, y
   pasar las medidas al cotizador es la salida por la que sale siempre; la IA es el atajo que se
   usa a veces. El relleno se muda al que hace lo que se vino a hacer, y la IA se queda neutra
   como las otras dos herramientas de su fila. */
.sp-addall{
  border:1px solid var(--a-fill);border-radius:var(--rr2);
  background:var(--a-fill);color:#fff;font-size:var(--t2);font-weight:600;min-height:38px;
  transition:background var(--mv-s),border-color var(--mv-s);
}
.sp-addall:hover{background:var(--a-fuerte);border-color:var(--a-fuerte)}
.sp-ai{
  border:1px solid var(--linea);border-radius:var(--rr2);
  background:var(--sup);color:var(--tinta2);font-size:var(--t2);font-weight:500;min-height:38px;
  box-shadow:none;transition:border-color var(--mv-s),color var(--mv-s);
}
.sp-ai:hover{filter:none;background:var(--sup);border-color:var(--a-borde);color:var(--tinta)}
.sp-addall-note{font-size:var(--t1);color:var(--ok);font-weight:500}
/* Y el botón que agrega UNA medida, uno por renglón de la lista: cinco medidas eran cinco
   rellenos de marca dentro de un panel que ya tiene el suyo abajo. */
.sp-mitem-add{
  border:1px solid var(--a-borde);border-radius:var(--rr2);
  background:var(--sup);color:var(--a-tx);font-size:var(--t2);font-weight:600;min-height:34px;
}
.sp-mitem-add:hover{background:var(--a-suave)}
.sp-mitem-add.done{background:var(--ok-bg);border-color:var(--ok-borde);color:var(--ok);font-weight:500}
/* La barra de herramientas de los dos aparatos: el mismo botón neutro de la app, y el activo
   con el relleno del acento porque ahí sí es una selección —qué se está midiendo, qué vista
   del vector se está viendo—. */
.sp-tb-btn{
  border:1px solid var(--linea);border-radius:var(--rr2);
  font-size:var(--t2);font-weight:500;color:var(--tinta2);min-height:36px;padding:0 14px;
  transition:border-color var(--mv-s),color var(--mv-s),background var(--mv-s);
}
.sp-tb-btn:hover{border-color:var(--a-borde);color:var(--tinta);background:var(--sup)}
.sp-tb-btn.active{background:var(--a-fill);color:#fff;border-color:var(--a-fill);box-shadow:none}

/* ---------- Aviso emergente ---------- */
#toast{border-radius:var(--rr2);box-shadow:var(--sombra-alta)}
#toast.show{animation:toast-sube var(--mv-s)}
@keyframes toast-sube{from{opacity:0;transform:translate(-50%,10px)}}

/* ---------- Entradas ----------
   Una sola animación para todo lo que aparece: 10 px hacia arriba y de
   transparente a opaco, en .32 s con la curva del rediseño. La escalera de
   retardos se va: con seis piezas encadenadas, la última entraba un cuarto de
   segundo después de que la pantalla ya se pudiera usar, y en una app que se
   abre cincuenta veces al día eso se siente como que va lenta. */
@keyframes entra{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
/* Los nombres viejos apuntan a la misma. */
@keyframes barro-entra{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@keyframes barro-pop{from{transform:none}to{transform:none}}
.card,.sum,.pasos,.p1-cierre{animation:entra .32s cubic-bezier(.2,.8,.2,1) both}
.pasos,#card-proy,#card-partidas,.p1-cierre,#sidebox .sum{animation-delay:0s}
.partida{animation:entra .32s cubic-bezier(.2,.8,.2,1) backwards}
#items>.partida:nth-child(1),#items>.partida:nth-child(2),#items>.partida:nth-child(3),
#items>.partida:nth-child(4),#items>.partida:nth-child(n+5){animation-delay:0s}
.wrap>main>.card,.wrap>aside{animation-name:entra}

/* ---------- Iconos y detalles ---------- */
.svgi{transition:none}
.btn:hover .svgi,.ai-btn:hover .svgi,.btn-hist:hover .svgi{transform:none}
.del:hover,.dup:hover,.pdf-vis:hover{transform:none;background:var(--sup2)}
.del,.dup,.pdf-vis,.pfold{transition:color var(--mv-s),background var(--mv-s)}
.del:hover{background:var(--mal-bg);color:var(--mal)}
.del:active,.dup:active,.pdf-vis:active,.pfold:active{transform:translateY(1px)}
.pfold{transition:transform .25s}

/* ---------- La IA sigue teniendo su propio color ----------
   Es la única cosa de la pantalla que trae algo de fuera, y el rediseño la
   deja como el único botón de color de la fila de herramientas. Lo que se
   pierde es el degradado que respiraba: en un botón de 44 px un degradado que
   se mueve solo es ruido, y el violeta ya distingue de sobra. */
.ai-btn{
  background:var(--a-fill);
  color:#fff;border:1px solid var(--a-fill);
  box-shadow:none;text-shadow:none;
  animation:none;
}
.ai-btn:hover{background:var(--a-fuerte);border-color:var(--a-fuerte);transform:none;box-shadow:none}
.ai-btn:disabled{animation:none;opacity:.5}

/* Los importes de cada partida. */
.pline .lt{font-family:var(--f-cifra);font-size:var(--t4);font-weight:600;letter-spacing:0;color:var(--tinta)}
@media screen and (max-width:920px){ .pline .lt{font-size:var(--t4);font-weight:600} }

.partida.folded .psum:hover .pdsc{color:var(--a-tx)}
.partida .ptok::before{color:var(--a-tx)}
.partida .ptok.falta::before{color:var(--av)}
.partida .ptok.off::before{color:var(--tinta3)}
.partida :where(button,summary,a[href],input,select,textarea,[tabindex]):focus-visible{
  outline-color:var(--a);
}

/* ---------- Aro de foco ---------- */
:where(button,summary,a[href],input,select,textarea,[tabindex]):focus-visible{
  outline:2px solid var(--a);outline-offset:2px;
}

/* ---------- Quien pida menos movimiento, recibe menos ----------
   No es un extra: hay gente a la que una pantalla que se mueve le provoca
   mareo de verdad. Con el barro se apagaban las animaciones y se quedaban las
   sombras, «que son lo que da el estilo»; ahora el estilo son el borde y la
   superficie, así que aquí se puede apagar el movimiento ENTERO sin que la
   app pierda una sola señal. La transición del total también se apaga, y lo
   hace en su propio código: mide, y si esto está activo no anima. */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}
  #prog-bar::after,.cand-partidas{animation:none!important}
  .btn:hover,.chip:hover,.paso-tab:hover,.ai-btn:hover{transform:none!important}
}

/* ===================== Cierre de la hoja: lo que tiene que ganar por orden =====================
   Va aquí —después de la capa de barro y del pase visual, y ANTES del @media print— porque
   entre dos reglas con la misma especificidad gana la última. Es el mismo tropiezo que ya
   documentan los comentarios de más arriba, y les había pasado a estas: medido en el
   navegador, ninguna de las reglas de este bloque llegaba a aplicarse desde donde estaba. */
@media(max-width:560px){
  /* La capa de barro le devolvía al teléfono el relleno de escritorio: .partida computaba
     24px/16px y no los 11/10 que pedía el bloque del teléfono, 209 líneas más arriba. Son
     303 px de página en el iPhone y 521 px en la portada del Fold —una partida plegada más
     a la vista—, y es lo que partía en dos renglones el encabezado de la partida plegada a
     344 px. El :first-of-type hace falta porque la regla de la capa lleva un id.

     Ya no se toca `padding` directo: se cambia --pp y con eso se recolocan solos el lomo y
     los márgenes negativos de la banda del encabezado, que es lo que antes había que
     acertar a mano tres veces. El lomo también adelgaza —6 px de tira en una pantalla de
     360 px son otra cosa que en una de 1 180. */
  .partida{--pp:11px;--lomo:5px;margin-bottom:10px}
  /* El bloque de opciones aprieta igual que antes; la capa de color le puso relleno de
     escritorio y vive más abajo en la hoja, así que gana ella si no se dice aquí. */
  .optgrp{padding:8px 9px 9px;margin-bottom:8px}
  /* La bandeja se queda casi al ras: en el teléfono el marco es lo primero que sobra. */
  #items:not(:empty){padding:6px;margin-left:-6px;margin-right:-6px}
  /* La banda teñida del encabezado de la tarjeta y el relleno del cuerpo se declaran en la
     capa de color, que vive más abajo en la hoja: las copias del bloque del teléfono, 500
     líneas más arriba, perdían por orden. */
  .card-h{padding:11px 13px}
  .card-b{padding:11px 13px 15px}
}
@media(min-width:385px) and (max-width:560px){
  /* La caja de luz es el único tipo con tercer campo de verdad —la tarifa—: mandarlo a su
     propio renglón duplicaba el alto del bloque de medidas y en tres columnas cabe. Los
     otros tipos llevan un .fld-relleno de tercer hijo y no entran aquí. */
  .grid3:has(>.fld:nth-child(3):not(.fld-relleno)){grid-template-columns:repeat(3,1fr);gap:7px}
}
@media(max-width:385px){
  /* Portada del Fold: con la marca sin ceder ancho, la barra del escalador y del
     vectorizador se iba a cuatro renglones —206 px— y «← Cotizador» se caía del primero. */
  .sp-topbar .brand{flex:1 1 0;min-width:0}
  /* Cliente y teléfono a renglón completo: en dos columnas de 140 px el nombre se leía al
     59 % mientras quedaban 143 px de blanco muerto justo debajo. */
  #fld-cli,#fld-tel{grid-column:1/-1}
}

/* ----- El teléfono grande no es un teléfono chico -----
   Faltaba este escalón y es de donde sale, literalmente, «en un iPhone 15 Pro Max y varios
   Samsung se ve muy apretado todo». Entre 385 px y 561 px no había NINGÚN corte: el bloque
   del teléfono, que empieza en 560, le daba los mismos 10 px de relleno de página y los
   mismos 11/13 de tarjeta a un iPhone SE de 320 y a un 15 Pro Max de 430. Esos números se
   afinaron contra la portada del Fold, que son 344 px y donde cada píxel de marco es una
   línea de texto menos; en 430 px sobran 86 px de ancho y lo que se siente es que la app
   está apretada contra el filo.

   El corte va en 390 y no en 400 para que el iPhone 14/15/16 normal, que mide 393, caiga
   del lado ancho: es el teléfono más común de la oficina. Abajo quedan el SE (375), el
   A54 y el S23 (360) y la portada del Fold (344), donde el ahorro sí paga.

   Va después del bloque de 560 y después de la capa de color, que es donde viven
   .card-h y .card-b: con la misma especificidad gana la última, y la última tiene que ser
   esta. */
/* De 376 px para arriba sí cabe el mínimo de la guía de Apple en las tres acciones de la
   partida sin partir el encabezado en dos renglones. Medido: a 375 el encabezado se queda
   en 44 px de alto con los botones a 44; a 360 se va a 96. */
@media(min-width:376px){
  .del,.dup,.pdf-vis{width:44px;height:44px}
  .ptop-actions{gap:var(--e2)}
}

@media(min-width:390px) and (max-width:560px){
  .wrap{--pad-lat:max(var(--e4),env(safe-area-inset-left,0px));--pad-lat-der:max(var(--e4),env(safe-area-inset-right,0px));gap:var(--e4)}
  .card+.card{margin-top:var(--e4)}
  .card-h{padding:14px 16px}
  .card-b{padding:14px 16px 18px}
  .partida{--pp:14px;margin-bottom:12px}
  .optgrp{padding:10px 12px 12px;margin-bottom:10px}
  .fld{margin-bottom:12px}
}
@media screen and (min-width:561px) and (max-width:920px){
  /* ----- El Fold 6 abierto: 773 y 900 px -----
     Esta banda recibía la maqueta de una columna con barra fija de teléfono pero ninguna de
     sus medidas: se quedó con las de escritorio. Es el hueco que nombra el comentario del
     bloque de 920 px, del que solo se habían traído tres cosas. */
  /* Con el nombre largo el selector de tipo medía 400-414 px y empujaba los tres iconos de
     acción a un renglón propio y vacío: 99 px de encabezado en lugar de 51. */
  .tipo-seg .lg{display:none}
  .tipo-seg .sm{display:inline}
  /* El carril vacío del bloque de medidas se quedaba con un tercio del renglón: display:none
     no le quita la columna a la rejilla. Se colapsa solo cuando no hay tercer campo real. */
  .grid3:not(:has(>.fld:nth-child(3):not(.fld-relleno))){grid-template-columns:1fr 1fr}
  /* El relleno de escritorio en una columna de 773 px cuesta 120 px de página. */
  .partida{--pp:16px;margin-bottom:12px}
  .optgrp{padding:9px 11px 11px;margin-bottom:10px}
  #items:not(:empty){padding:8px}
  /* El chip crecía sin tope y el reparto salía invertido: las dos etiquetas más cortas se
     llevaban las dos cajas más anchas. Que cada uno mida lo que dice. */
  /* Y cinco rangos distintos de la partida se pintaban todos a 12.5 px, así que el chip
     elegido salía del mismo tamaño que el encabezado del grupo que lo contiene. */
  .optgrp .chip{flex:0 1 auto;max-width:100%;font-size:11.5px}
  .optgrp .chip small{font-size:10.5px}
  .tipo-seg button{font-size:11.5px}
  .hintnote{font-size:11px;line-height:1.45}
}
@media(max-width:1000px){
  /* Un deslizador de 733 a 860 px de largo para elegir entre tres valores. */
  .vt-modal-bg input[type=range]{max-width:400px}
}

/* ----- Arrastrar una partida: el filete que dejó de verse -----
   `.partida.drag-over{box-shadow:inset 0 2px 0 var(--a)}` lleva escrito desde antes de todo
   esto y ahora no se aplica: pesa lo mismo (0,2,0) que `.partida:not(.folded)` y que
   `.partida.folded`, y esos dos viven más abajo en la hoja, así que su box-shadow gana y se
   lleva el filete por delante. Comprobado en el navegador: al arrastrar sobre una partida no
   cambiaba nada. Repetido aquí, al final, gana él.

   Y ya que se reescribe, se pinta del matiz de la partida sobre la que se suelta en vez del
   azul fijo de la app. La pregunta mientras uno arrastra es «¿entre cuáles va a caer?», y el
   color de la de abajo la contesta sin leer el número. Conserva la sombra exterior teñida
   para que la pieza no se aplaste justo cuando la estás señalando. */
.partida.drag-over{
  box-shadow:inset 0 4px 0 var(--pc),0 14px 28px -8px rgba(var(--pc-rgb),.28);
}

/* ---------- En papel no hay relieve ----------
   Queda muy poco que apagar: la dirección nueva ya es plana, así que este bloque pasó de
   deshacer el barro a asegurar tres cosas que el papel sí necesita.

   La primera: nada de lo que se pega a la pantalla se pega al papel. Un `position:sticky` en
   una hoja no se queda arriba —no hay dónde— pero sí se saca del flujo en algunos motores, y
   el resumen de cada partida salía montado encima de su propio cuerpo.

   La segunda: el borde de una pieza sube a un gris que sobreviva a una impresora de tinta.
   `--linea` es #dcdff2, que en escala de grises es casi blanco.

   Y la tercera: lo que lleva relleno de color —el chip elegido, el paso actual, el
   interruptor— pasa a borde, porque media oficina imprime en blanco y negro y un relleno
   azul en gris es una mancha que ya no dice «elegido». */
@media print{
  *{box-shadow:none!important;animation:none!important;text-shadow:none!important}
  body{background:#fff!important}
  .card,.sum,.partida{background:#fff!important;border:1px solid #ddd!important}
  #items:not(:empty){background:none!important;padding:0!important;margin:0!important}
  /* El resumen fijo de la partida deja de pegarse: en papel no hay a dónde. */
  .pcab{position:static!important}
  .partida:not(.folded) .partida-top{background:none!important;border-bottom:1px solid #ddd!important}
  .optgrp,.partida .pbody>.grid2,.partida .pbody>.grid3,.partida .tipo-seg{background:none!important;border:1px solid #eee!important}
  /* La columna del dinero también: la placa del total y el hueco del anticipo son relieve,
     y en papel el relieve es una caja gris que no dice nada. */
  .prog-box,.neto,.anti{background:none!important;border:1px solid #ddd!important}
  .neto .lab,.anti label,.optgrp-t{color:#2b2f4d!important}
  /* Lo que quedaba de color dentro de la partida: el interruptor encendido, el tipo
     elegido, el ▾, el asa y la palomita de las fichas. Ninguno sale en el PDF —ese se arma
     en su propio documento— pero un Ctrl+P sobre la app con «gráficos de fondo» activado
     sí los imprimía. */
  .partida .tg.on{background:#2b2f4d!important}
  .partida .tipo-seg button.on,.partida .pfold,.partida .drag-handle,.partida .ptok::before{color:#12162b!important}
  .card-h,.paso-tab.on{background:none!important;border-color:#ddd!important}
  .pnum .n{background:none!important;border:1px solid #999!important;color:#12162b!important}
  .partida .chip.on{background:none!important;border:1.5px solid #12162b!important;color:#12162b!important}
  .neto .amt{-webkit-text-fill-color:initial;color:#12162b!important;filter:none}
}
/* ----- Modo empotrado: dentro del apartado Cotizador de la plataforma -----
   NO se apaga la .topbar entera, y es lo contrario de lo que se hace en el anidador. La
   diferencia es qué lleva cada barra: en la del anidador solo hay logotipo y dos enlaces de
   salida, y aquí viven Deshacer, Clientes, Historial —la única puerta a al3d_historial, el
   dato irrecuperable del sistema—, la píldora del folio y el segmento Vendedor/Autorizador.
   Sin ellos no se puede autorizar una cotización, o sea que apagar la barra apagaría el
   trabajo.

   Lo que sobra son las dos cosas que la plataforma ya pone: el logotipo con su título, que
   apilado daría dos encabezados en la misma pantalla, y el enlace de vuelta, que navegaría
   EL MARCO y acabaría con la plataforma anidada dentro de sí misma. Con esas dos apagadas la
   barra queda como un renglón delgado de controles y no hay doble cromo.

   Se escriben como `html.empotrado` y no `.empotrado` a secas porque estas reglas terminan
   en css/sistema.css —esta hoja— y de ahí las carga index.html, donde son inertes
   porque el <html> de la plataforma nunca lleva esa clase. */
html.empotrado .brand{display:none}
html.empotrado .btn-pf{display:none}

/* ============================================================================
   (7) TEMA OSCURO

   Se enciende con html[data-tema="oscuro"], que pone js/tema.js antes del primer pintado
   leyendo la clave al3d_tema (claro, oscuro o el del sistema). No hay una segunda hoja ni
   reglas repetidas: el tema es OTRO JUEGO DE TOKENS y las mil reglas de arriba no se enteran.
   Por eso arriba no queda ningún «#fff» de superficie ni ningún «rgba(255,255,255,…)» de
   brillo suelto: los que quedan son texto blanco sobre un relleno de color, que es blanco en
   los dos temas.

   Las mismas dos reglas de contraste que en claro, medidas al revés: aquí el texto es claro
   sobre fondo oscuro, así que los acentos —el azul, el verde, el ámbar, los seis matices de
   partida— SUBEN de luminosidad para seguir siendo legibles como texto, y los degradados de
   los botones rellenos (--brand-grd, --grd-deco) se quedan saturados y oscuros para que el
   texto blanco de encima siga leyéndose. Es el único sitio donde --a y --brand-grd no salen
   del mismo número, y es a propósito.
   ============================================================================ */
html[data-tema="oscuro"]{
  color-scheme:dark;
  /* Los mismos diez tokens del traspaso, en su versión de noche. La rampa vuelve a salir de
     ellos: --n1 es --fondo, --n2 es --linea2, --n3 es --linea, --n6 es --tinta2, --n8 es
     --tinta y --n9 es la barra. */
  --fondo:#0f1124; --sup2:#20244a;
  --linea:#2f3562; --linea2:#262b4f;
  --tinta:#eceefb; --tinta2:#a7acd6;
  --nav:#0a0c1c; --nav2:#141731; --nav-rgb:10,12,28;
  /* Y la tercera tinta, medida otra vez y por el mismo motivo: el #6f76a8 del traspaso da
     3,80:1 sobre --sup y 3,4:1 sobre --sup2, o sea que de noche falla más que de día.
     #8b92c0 da 5,48:1 sobre --sup y 4,93:1 sobre --sup2. El tono de la muestra se queda,
     otra vez, en --n5, que es el escalón que no lleva texto. */
  --tinta3:#8b92c0;
  --n0:#232750; --n1:#0f1124; --n2:#262b4f; --n3:#2f3562; --n4:#454d80;
  --n5:#6f76a8; --n6:#a7acd6; --n7:#c9cdec; --n8:#eceefb; --n9:#f7f8ff;
  --sup:#1a1d38; --sup-rgb:26,29,56;
  --luz-rgb:120,132,210;
  --tinta-rgb:0,0,0;
  --n1-rgb:15,17,36; --n2-rgb:38,43,79; --n3-rgb:47,53,98; --n4-rgb:69,77,128; --n5-rgb:111,118,168;
  /* Aquí es donde --a y --a-fill dejan de ser el mismo número, y es lo único que de verdad
     obliga a separarlos. --a (#6d86ff) es el azul que se LEE sobre marino: 5,11:1 sobre
     --sup. Con blanco encima daría 3,0:1, así que no puede ser relleno. --a-fill (#3b57e6) es
     el que aguanta blanco: 5,69:1. Uno es tinta y el otro es fondo, y en claro coincidían. */
  --a:#6d86ff; --a-fill:#3b57e6; --a-tx:#a9b8ff;
  --a-fuerte:#8fa3ff; --a-claro:#5f7dff; --a-suave:#232a5a; --a-suave-2:#2a3372; --a-borde:#3d4a99;
  --a2:#b48cff; --a2-suave:#2c2450; --a3:#4fcbe6; --a3-texto:#7fd6ea;
  --brand-grd:var(--a-fill);
  --grd-deco:var(--a-fill);
  /* De noche la sombra deja de ser azulada: sobre un fondo marino una sombra teñida de azul
     no se ve, y lo que separa una pieza del lienzo es negro puro y un borde más claro. */
  --sombra:0 1px 2px rgba(0,0,0,.4),0 10px 28px -14px rgba(0,0,0,.6);
  --sombra-alta:0 2px 8px rgba(0,0,0,.5),0 28px 56px -18px rgba(0,0,0,.75);
  --ok:#6fd6a4; --ok-bg:#10331f; --ok-borde:#1f6b42; --green-ico:#3fc282;
  /* Y el relleno verde, por lo mismo que --a-fill: #0e7a4d aguanta blanco (5,37:1) y se
     distingue del marino de la superficie. */
  --ok-fill:#0e7a4d;
  --av:#f5c26b; --av-bg:#3a2a10; --av-borde:#6b4a14; --amber-ico:#e0a232; --av-rgb:245,194,107; --av-borde-rgb:107,74,20;
  --mal:#ff8a80; --mal-bg:#3a1414; --mal-borde:#7a2f2f; --mal-rgb:255,138,128;
  --wa:#5ad0bd; --wa-rgb:90,208,189;
  /* Los seis matices son uno también de noche, por lo mismo que de día. */
  --pc-1:#a9b8ff; --pc-1-md:#3b57e6; --pc-1-bd:#3d4a99; --pc-1-sv:#232a5a; --pc-1-rgb:59,87,230;
  --pc-2:#a9b8ff; --pc-2-md:#3b57e6; --pc-2-bd:#3d4a99; --pc-2-sv:#232a5a; --pc-2-rgb:59,87,230;
  --pc-3:#a9b8ff; --pc-3-md:#3b57e6; --pc-3-bd:#3d4a99; --pc-3-sv:#232a5a; --pc-3-rgb:59,87,230;
  --pc-4:#a9b8ff; --pc-4-md:#3b57e6; --pc-4-bd:#3d4a99; --pc-4-sv:#232a5a; --pc-4-rgb:59,87,230;
  --pc-5:#a9b8ff; --pc-5-md:#3b57e6; --pc-5-bd:#3d4a99; --pc-5-sv:#232a5a; --pc-5-rgb:59,87,230;
  --pc-6:#a9b8ff; --pc-6-md:#3b57e6; --pc-6-bd:#3d4a99; --pc-6-sv:#232a5a; --pc-6-rgb:59,87,230;
  --sc-guide:#2fc2dd;
}
/* El lienzo de noche también es plano. Aquí vivían tres manchas radiales. */
html[data-tema="oscuro"] body{background:var(--fondo)}
/* El aviso emergente era azul marino sobre blanco; sobre un fondo marino se perdería. */
html[data-tema="oscuro"] .toast:not(.ok):not(.err){background:var(--n8);color:var(--n1)}
html[data-tema="oscuro"] .toast:not(.ok):not(.err) .toast-act{border-color:rgba(var(--n1-rgb),.35);background:rgba(var(--n1-rgb),.08);color:var(--n1)}
html[data-tema="oscuro"] .toast:not(.ok):not(.err) .toast-act:hover{background:rgba(var(--n1-rgb),.18);border-color:var(--n1)}
/* Los campos: el degradado claro→blanco se vuelve hondo→superficie. */
html[data-tema="oscuro"] input:-webkit-autofill,html[data-tema="oscuro"] input:-webkit-autofill:focus{-webkit-box-shadow:0 0 0 100px var(--sup) inset}
html[data-tema="oscuro"] .mbar{box-shadow:0 -10px 30px -10px rgba(0,0,0,.6)}
/* El logotipo con el «AL3D» en claro. La ruta es relativa a ESTA hoja (css/), así que sirve
   igual desde la raíz y desde anidador-vectores/. Solo se cambia el logotipo de la casa: el que
   alguien subió en el cotizador (src distinto) se respeta. */
html[data-tema="oscuro"] .logoimg[src$="logo-al3d.svg"]{content:url("../logo-al3d-oscuro.svg")}
/* Los alias viejos que apuntaban a un color fijo. */
html[data-tema="oscuro"]{--card:var(--sup)}
/* El botón de IA mezcla los tres acentos, que en oscuro subieron para ser texto: aquí se queda
   con los saturados, porque lleva texto blanco encima. */
html[data-tema="oscuro"] .ai-btn{background:var(--a-fill);border-color:var(--a-fill)}
html[data-tema="oscuro"] .ai-btn:hover{background:var(--a-fuerte);border-color:var(--a-fuerte)}

/* ----- El interruptor -----
   Luna en claro («toca para oscuro»), sol en oscuro. Empotrado en la plataforma se apaga:
   manda el de la barra de arriba, y los dos documentos se enteran por el evento storage. */
.btn-tema{padding:0;width:44px;min-height:44px;display:inline-flex;align-items:center;justify-content:center}
.btn-tema .svgi{width:var(--ico2);height:var(--ico2)}
.btn-tema .sol{display:none}
html[data-tema="oscuro"] .btn-tema .luna{display:none}
html[data-tema="oscuro"] .btn-tema .sol{display:inline-block}
html.empotrado .btn-tema{display:none}

/* Al imprimir, el papel es blanco: el tema oscuro se apaga y vuelven los tokens de claro. Un
   @media no puede «quitar» un atributo, así que se redeclaran los que el oscuro tocó. */
@media print{
  html[data-tema="oscuro"]{
    color-scheme:light;
    --fondo:#f3f4fb; --sup2:#f7f8fd; --linea:#dcdff2; --linea2:#eceef8;
    --tinta:#1a1d33; --tinta2:#5c6184; --tinta3:#666d9b; --nav:#171a33; --nav2:#232744; --nav-rgb:23,26,51;
    --n0:#fbfcff; --n1:#f3f4fb; --n2:#eceef8; --n3:#dcdff2; --n4:#b9bede;
    --n5:#8b90b8; --n6:#5c6184; --n7:#3d4166; --n8:#1a1d33; --n9:#171a33;
    --sup:#ffffff; --sup-rgb:255,255,255; --luz-rgb:255,255,255; --tinta-rgb:35,39,68;
    --n1-rgb:243,244,251; --n2-rgb:236,238,248; --n3-rgb:220,223,242; --n4-rgb:185,190,222; --n5-rgb:139,144,184;
    --a:#4060f8; --a-fill:#4060f8; --a-tx:#3018f8;
    --a-fuerte:#3018f8; --a-claro:#6090f8; --a-suave:#e9edff; --a-suave-2:#dfe6ff; --a-borde:#b9c5fe;
    --a2:#7b3ff8; --a2-suave:#f1ecfd; --a3:#18b6d8; --a3-texto:#0b6e85;
    --ok:#0a7d4a; --ok-bg:#e2f8ec; --ok-borde:#a9e8c6; --green-ico:#15a06a; --ok-fill:#0a7d4a;
    --av:#8a5100; --av-bg:#fff2dd; --av-borde:#ffd79c; --amber-ico:#c1830f;
    --mal:#c62828; --mal-bg:#ffeceb; --mal-borde:#ffc4c1; --wa:#0f7a6c;
    --pc-1:#3018f8; --pc-1-md:#4060f8; --pc-1-bd:#b9c5fe; --pc-1-sv:#e9edff;
    --pc-2:#3018f8; --pc-2-md:#4060f8; --pc-2-bd:#b9c5fe; --pc-2-sv:#e9edff;
    --pc-3:#3018f8; --pc-3-md:#4060f8; --pc-3-bd:#b9c5fe; --pc-3-sv:#e9edff;
    --pc-4:#3018f8; --pc-4-md:#4060f8; --pc-4-bd:#b9c5fe; --pc-4-sv:#e9edff;
    --pc-5:#3018f8; --pc-5-md:#4060f8; --pc-5-bd:#b9c5fe; --pc-5-sv:#e9edff;
    --pc-6:#3018f8; --pc-6-md:#4060f8; --pc-6-bd:#b9c5fe; --pc-6-sv:#e9edff;
  }
  html[data-tema="oscuro"] .logoimg[src$="logo-al3d.svg"]{content:url("../logo-al3d.svg")}
}
