/* ============================================================================
   Solo lo que la plataforma añade.

   Todo lo demás —los azules del logotipo, el barro, la escala de siete tamaños de letra,
   los tres radios, las dos sombras, las curvas de movimiento— sale de css/sistema.css, que
   es el sistema de diseño de las tres superficies. Aquí no se define ni un color nuevo ni un
   tamaño de letra nuevo: si algo hiciera falta y no estuviera en la escala, la respuesta es
   usar el paso de la escala que más se acerque, no añadir un paso.

   Las dos reglas de contraste del sistema se respetan sin excepción:
     · de --n5 hacia arriba, ningún tono de la rampa lleva texto;
     · --a-claro y --a3 son DECORACIÓN —sombra, lienzo, borde, trazo— y nunca fondo de texto.
   ============================================================================ */

/* ============================================================================
   POR QUÉ AQUÍ NO SE USA EL ATAJO `font:`

   Hasta esta auditoría, 41 de las 43 declaraciones de tipografía de este archivo estaban
   escritas así:

       font:600 var(--t3)/1.35 inherit

   y NINGUNA de las 41 hacía nada. El atajo `font` exige una familia de verdad al final, e
   `inherit` no lo es. Normalmente eso sería un error de sintaxis y el navegador tiraría la
   declaración al leerla; pero como la línea trae un `var()`, la especificación obliga a
   aplazar el análisis hasta el momento de calcular el valor, y lo que no se puede analizar
   entonces se declara «inválido en tiempo de cómputo»: cada propiedad que el atajo tocaba
   —tamaño, peso y alto de línea— se queda con lo heredado.

   Medido en el navegador antes de arreglarlo, sobre .pf-fila-t, que es el título de un
   renglón y la pieza más repetida de la plataforma:

       declarado   600  ·  14 px  ·  interlínea 1,35   (18,9 px)
       real        400  ·  16 px  ·  interlínea 1,5    (24 px)

   O sea: la escala de siete tamaños que este archivo dice respetar nunca se aplicó en la
   plataforma. Los títulos salían más grandes y más ligeros que sus descripciones —sin
   contraste de peso entre uno y otra—, y cada renglón medía un 27 % más de alto del que se
   diseñó. Eso es de dónde salía buena parte de «se ve muy apretado todo»: no era falta de
   aire, era que todo estaba un paso más grande de lo que debía y no cabía.

   El cotizador nunca tuvo el problema: sus 0 declaraciones `font:` con `inherit` lo dicen.
   Por eso las dos apps se veían distintas aunque compartan la hoja de tokens.

   Ahora se escriben las tres propiedades por separado. Las dos únicas `font:` que quedan en
   el archivo son las de la tipografía monoespaciada, que sí traen familia de verdad y sí
   son válidas.

   Y AQUÍ VA EL DETALLE QUE CASI SE ESCAPA. El atajo roto estaba arreglando otra cosa sin
   querer: un <button> no hereda la familia tipográfica, la coge del navegador —Arial—, y
   como una declaración inválida en tiempo de cómputo deja cada propiedad en `unset`, la
   familia de esos botones caía en «heredar» y acababa siendo Inter por accidente. Al
   escribir las tres propiedades buenas, el accidente desaparece y los botones se iban a
   Arial. Se vio al medir, no al leer.

   Así que la familia se declara de una vez para todos los controles, que es lo que el
   `inherit` del atajo intentaba decir y lo que el cotizador viene diciendo componente por
   componente en catorce sitios distintos. Una regla, y no se vuelve a olvidar. */
button,input,select,textarea,optgroup{font-family:inherit}

/* ============================================================================
   EL ESQUELETO: barra lateral, encabezado y barra de abajo
   ============================================================================
   Tres anchos y tres formas, y las tres salen de la misma pieza de marcado:

     ≥ 1024 px  barra lateral de 216 px · encabezado blanco de 64 px
     760–1023   barra lateral de 168 px (el Fold abierto mide 880) · el mismo encabezado
     ≤ 759 px   sin barra lateral · encabezado marino · barra de módulos abajo

   La barra lateral es `position:fixed` y el hueco lo hace un `padding-left` en `.pf-wrap` y
   en el encabezado. El porqué está escrito en index.html: un contenedor con scroll propio se
   lleva por delante el scroll por ruta, los `position:sticky` y la impresión. */
/* El ancho de la barra lateral. Vale 0 mientras no hay barra —el teléfono— y las dos medias
   queries de abajo lo suben; `.pf-wrap` y `.pf-cab` leen de aquí el hueco que tienen que
   dejar, así que el ancho se cambia en UN sitio y no en tres. */
:root{--lat:0px}

.pf-lat{display:none}
.pf-abajo{display:none}

/* El filete de marca de arriba no cruza la plataforma. En la computadora la marca es la
   barra lateral y una raya azul por encima la corta en dos; en el teléfono el encabezado ya
   es marino, y tres píxeles de azul encima de él se leen como un borde mal puesto. En el
   cotizador suelto y en el anidador se queda, que es donde no hay ni barra ni encabezado
   marino que lo digan. */
body.pf::before{display:none}

/* ----- El encabezado ----- */
.pf-cab{
  position:sticky;top:0;z-index:30;
  display:flex;align-items:center;gap:var(--e3);
  height:56px;flex:0 0 auto;
  padding:0 max(var(--e4),env(safe-area-inset-right,0px)) 0 max(var(--e4),env(safe-area-inset-left,0px));
  background:var(--nav);color:#fff;
}
.pf-cab-logo{height:24px;width:auto;flex:0 0 auto}
.pf-cab-t{flex:0 1 auto;min-width:0;font-size:17px;font-weight:600;line-height:1.2;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#fff}
/* La línea de debajo del título solo existe donde hay sitio para leerla. */
.pf-cab-d{display:none}
.pf-cab-acc{display:flex;align-items:center;gap:var(--e2);margin-left:auto}
.pf-cab-tema{margin-left:auto;width:36px;height:36px;flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;
  border:0;border-radius:var(--rr2);background:rgba(255,255,255,.08);color:#fff;cursor:pointer}
.pf-cab-tema:hover{background:rgba(255,255,255,.16)}
.pf-cab-tema .svgi{width:var(--ico2);height:var(--ico2)}
/* En el teléfono el encabezado es lo único que lleva la marca, y las acciones contextuales
   de un módulo no caben ahí junto al título: las escribe cada módulo dentro de su pantalla. */
@media(max-width:759px){ .pf-cab-acc{display:none} }

/* ----- La página ----- */
.pf-wrap{grid-template-columns:minmax(0,1fr);padding-top:var(--e4)}
.pf-wrap>main{min-width:0}

/* ----- La barra de abajo, en el teléfono -----
   52 px por botón, el icono dentro de una píldora de 44×26 que se enciende con el acento, y
   el nombre debajo en 10,5 px. La píldora existe por una razón medible: un icono de 19 px
   cambiando solo de color no se ve encendido de un vistazo en una pantalla al sol, y un
   fondo de 44×26 sí.

   El relleno de abajo lo pone el área segura: en un iPhone son los 28 px del indicador de
   inicio, y en un Android sin indicador, 8. */
@media(max-width:759px){
  .pf-abajo{
    display:flex;position:fixed;left:0;right:0;bottom:0;z-index:40;
    background:var(--nav);
    padding:6px 4px calc(8px + env(safe-area-inset-bottom,0px));
  }
  .pf-abajo button{
    flex:1;min-width:0;height:52px;border:0;background:transparent;cursor:pointer;
    display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
    font-family:inherit;font-size:10.5px;font-weight:600;letter-spacing:.2px;
    color:rgba(255,255,255,.55);
  }
  .pf-abajo button .pil{
    width:44px;height:26px;border-radius:13px;display:inline-flex;align-items:center;justify-content:center;
    background:transparent;transition:background .2s;
  }
  .pf-abajo button .svgi{width:19px;height:19px}
  .pf-abajo button.on{color:#fff}
  .pf-abajo button.on .pil{background:var(--a-fill)}
  /* La cuenta de lo que reclama atención, en el filo de la píldora. */
  .pf-abajo .cta{
    position:absolute;transform:translate(14px,-9px);
    min-width:16px;height:16px;padding:0 4px;border-radius:8px;
    background:var(--av);color:var(--nav);
    font-size:10px;font-weight:700;line-height:16px;text-align:center;
  }
  /* El hueco para la barra: lo que mide más el área segura. Sin esto, el último renglón de
     cualquier lista se queda debajo de ella y no hay forma de llegar a él. */
  .pf-wrap{padding-bottom:calc(76px + env(safe-area-inset-bottom,0px) + var(--mbar-h,0px))}
  /* Y la barra de acción del módulo se posa ENCIMA de la de módulos, no debajo. */
  .pf-mbar{bottom:calc(66px + env(safe-area-inset-bottom,0px))}
}

/* ----- La barra lateral, de 760 px para arriba ----- */
@media(min-width:760px){
  :root{--lat:168px}
  .pf-lat{
    display:flex;flex-direction:column;gap:2px;
    position:fixed;left:0;top:0;bottom:0;width:var(--lat);z-index:50;
    padding:20px 10px 14px;
    background:var(--nav);color:rgba(255,255,255,.72);
    overflow-y:auto;overscroll-behavior:contain;
  }
  .pf-lat-marca{display:flex;align-items:center;gap:10px;padding:2px 8px 18px;
    white-space:nowrap;overflow:hidden}
  .pf-lat-marca img{height:26px;width:auto;display:block}
  .pf-lat-t{font-family:var(--f-cifra);font-weight:600;font-size:var(--t4);color:#fff;letter-spacing:.2px}
  .pf-lat-pie{margin-top:auto;padding-top:var(--e3)}
  .pf-lat-item{
    display:flex;align-items:center;gap:12px;width:100%;
    height:40px;padding:0 10px;border:0;border-radius:var(--rr3);
    background:transparent;color:rgba(255,255,255,.72);
    font-family:inherit;font-size:var(--t2);font-weight:500;text-align:left;cursor:pointer;
  }
  .pf-lat-item:hover{background:rgba(255,255,255,.06);color:#fff}
  .pf-lat-item .svgi{width:var(--ico2);height:var(--ico2);flex:0 0 auto}
  /* El interruptor de tema dice A DÓNDE va, no dónde estás: en claro, «Tema oscuro» con la
     luna; en oscuro, «Tema claro» con el sol. La hoja del sistema ya enseña un glifo u otro
     según html[data-tema]; aquí hace falta lo mismo con la palabra, que en la barra lateral
     sí cabe. Sin esto salían las dos, una al lado de la otra. */
  .pf-lat-item .tx-sol{display:none}
  html[data-tema="oscuro"] .pf-lat-item .tx-luna{display:none}
  html[data-tema="oscuro"] .pf-lat-item .tx-sol{display:inline}
  .pf-lat-rol{margin-top:10px;padding:12px 10px 4px;border-top:1px solid rgba(255,255,255,.08)}
  .pf-lat-rol-t{display:block;font-size:var(--t1);font-weight:600;color:#fff;margin-bottom:6px}
  /* El segmento de rol dentro de la barra: marino sobre marino, con el elegido en claro. */
  .pf-lat-rol .seg{width:100%;background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.12)}
  .pf-lat-rol .seg button{flex:1;min-width:0;min-height:30px;padding:0 4px;font-size:var(--t1);
    color:rgba(255,255,255,.7)}
  .pf-lat-rol .seg button.on{background:rgba(255,255,255,.16);color:#fff}

  /* El hueco de la barra, y el encabezado que se vuelve blanco. */
  .pf-wrap,.pf-cab{padding-left:calc(var(--lat) + var(--e4))}
  .pf-cab{
    height:64px;
    background:var(--sup);color:var(--tinta);
    border-bottom:1px solid var(--linea);
    padding-right:max(var(--e5),env(safe-area-inset-right,0px));
    gap:var(--e4);
  }
  .pf-cab-logo{display:none}
  .pf-cab-tema{margin-left:0}
  .pf-cab-t{font-size:var(--t5);color:var(--tinta)}
  .pf-cab-d{display:block;flex:1;min-width:0;color:var(--tinta3);font-size:var(--t2);
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .pf-cab-acc{margin-left:0}
  .pf-cab-tema{background:transparent;color:var(--tinta2);border:1px solid var(--linea)}
  .pf-cab-tema:hover{background:var(--sup2);color:var(--tinta)}
}
/* Los atajos de teclado escritos, en el encabezado. Solo donde hay teclado: el hueco de
   acciones ya está apagado en el teléfono, así que esto no necesita su propia media query. */
.pf-teclas{display:inline-flex;align-items:center;gap:6px;font-size:var(--t2);color:var(--tinta3)}
.pf-teclas kbd{font:inherit;padding:1px 6px;border:1px solid var(--linea);border-radius:var(--rr1);
  color:var(--tinta2);background:var(--sup)}
@media(min-width:1024px){
  :root{--lat:216px}
  .pf-lat{padding:20px 12px 16px}
  .pf-lat-marca img{height:30px}
}

/* Al cambiar de módulo se le manda el foco a <main> para que quien navega con teclado no
   tenga que recorrer otra vez las seis pestañas. Pero <main> lleva tabindex="-1" y el
   navegador le dibuja su halo: un recuadro azul de 2 px alrededor de TODA la pantalla, en
   las seis. Se quita el halo y no se pierde nada: lo que informa del cambio es el foco en
   sí —el lector de pantalla anuncia la región— no el dibujo. El halo de los controles de
   verdad, que sí hace falta, no se toca. */
#pf-contenido:focus{outline:none}

/* Cambiar de módulo es un movimiento, no un corte: la pantalla nueva entra desde 10 px abajo
   en .32 s. Va en la sección —que es lo que el router enciende— y no en cada módulo, así que
   los ocho entran igual sin tener que acordarse. El `@media` de movimiento reducido de
   css/sistema.css lo apaga con los demás. */
.pf-mod{animation:entra .32s cubic-bezier(.2,.8,.2,1) both}

/* El ancho de las pantallas de la plataforma. La maqueta las topa en 1 240 px y la .wrap del
   cotizador venía topando en 1 180; con la barra lateral fuera del flujo, el contenido puede
   usar los 1 240 sin apretar nada. */
.pf-wrap{max-width:calc(1240px + var(--lat))}

/* La barra fija del teléfono publica su alto para que el aviso emergente se pose encima y
   no debajo. Cuando no hay barra, la variable es 0 y nada se mueve. */
/* Y el alto de los marcos empotrados —el Cotizador y el Anidador—. Se DECLARA aquí, con un
   valor que sirve solo, porque un `var()` sin declaración previa no es inválido: es una
   variable vacía, y `height:var(--pf-marco-h)` con nada dentro deja el iframe en los 150 px
   que manda la especificación. Con la declaración, si `medirMarco()` no llegara a correr el
   marco sigue teniendo un alto usable. */
:root{--mbar-h:0px;--pf-marco-h:70vh}

/* ----- `hidden` tiene que ganar -----
   Esto es un error clásico y aquí ya se cometió: la banda de degradación se pinta con
   `hidden=true` y seguía ocupando 26 px de alto. La regla del navegador es
   `[hidden]{display:none}`, y cualquier regla de autor que ponga `display` —como el
   `display:flex` de .pf-banda— le gana, porque una clase pesa más que el selector del
   navegador. El resultado era una píldora ámbar vacía arriba de las seis pantallas.

   Va aquí arriba, una sola vez y para todo, en vez de repetirlo en cada componente: los
   tres elementos que se apagan con `hidden` son la banda, la barra del teléfono y la
   navegación, y el siguiente que alguien añada también lo va a necesitar. */
[hidden]{display:none!important}

/* ----- La barra de módulos, dentro de la barra lateral -----
   No es la escalera numerada del cotizador: eso es una secuencia —primero el cliente,
   después las partidas— y esto son seis lugares donde a cualquiera se llega desde
   cualquiera.

   El elegido lleva `--nav2` con un filete de 3 px del acento a la izquierda, y no un relleno
   azul: el azul sólido significa «esta es LA acción» en toda la app, y seis lugares no
   pueden ser todos la acción. El filete es lo que hace que se lea como una pestaña activa y
   no como un botón encendido — y es la misma señal que ya usa la app para «esto está
   seleccionado» sin gastar el color. */
.pf-nav{display:flex;flex-direction:column;gap:2px}
.pf-tab{
  display:flex;align-items:center;gap:12px;width:100%;
  height:42px;padding:0 12px;border:0;border-radius:var(--rr3);
  background:transparent;color:rgba(255,255,255,.72);
  font-family:inherit;font-weight:500;font-size:var(--t3);line-height:1;text-align:left;cursor:pointer;
  transition:background var(--mv-s),color var(--mv-s);
}
.pf-tab:hover{background:rgba(255,255,255,.06);color:#fff}
.pf-tab.on{background:var(--nav2);color:#fff;font-weight:600;box-shadow:inset 3px 0 0 var(--a)}
.pf-tab .tx{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pf-tab .svgi{flex-shrink:0;width:var(--ico2);height:var(--ico2)}
/* La cuenta de lo que reclama atención. Va en ámbar y no en rojo: son cosas que hay que
   ver hoy, no cosas que ya se rompieron. */
.pf-tab .cta{flex:0 0 auto;min-width:20px;height:18px;padding:0 6px;border-radius:9px;
  background:var(--av);color:var(--nav);
  font-weight:700;font-size:var(--t1);line-height:18px;text-align:center}
/* El anillo de foco por dentro: la barra lateral no tiene aire alrededor de un ítem, y un
   anillo de 2 px con 2 de separación se recortaría contra el canto. */
.pf-tab:focus-visible,.pf-lat-item:focus-visible{outline:2px solid #fff;outline-offset:-3px}

/* ----- La banda de degradación -----
   Dice lo que es verdad en las seis pantallas: que la base no abrió, que lo que se ve del
   almacén tiene tres días, que no hay respaldo desde el 12. Va arriba de todo y con el
   mismo ámbar del candado del cotizador, porque es el mismo tipo de mensaje: no es un
   error, es «esto que estás viendo tiene una condición». */
.pf-banda{display:flex;align-items:flex-start;gap:var(--e2);margin-bottom:var(--e4);
  padding:var(--e3) var(--e4);border:1px solid var(--av-borde);border-radius:var(--rr2);
  background:var(--av-bg);color:var(--av);font-weight:500;font-size:var(--t2);line-height:1.45}
.pf-banda.mal{border-color:var(--mal-borde);background:var(--mal-bg);color:var(--mal)}
.pf-banda .svgi{flex-shrink:0;margin-top:1px;width:var(--ico2);height:var(--ico2)}
.pf-banda b{font-weight:700}
.pf-banda button{margin-left:auto;flex-shrink:0;min-height:44px;padding:0 var(--e3);
  border:1px solid currentColor;border-radius:var(--rr1);background:transparent;
  color:inherit;font-weight:700;font-size:var(--t2);line-height:1;cursor:pointer}

/* ----- El renglón, la primitiva de la plataforma -----
   Inicio, la lista de faltantes, la de proyectos sin fecha y la de cobranza son todas la
   misma forma: un icono, un texto de dos renglones y una acción. Se define una vez. Que
   las cuatro se vean iguales no es economía de CSS: es que el ojo aprende UNA forma y
   después lee cualquiera de las cuatro sin volver a mirar dónde está el botón. */
/* `flex-wrap` en todos los anchos, y `flex-basis` en el texto. La regla del teléfono ya
   envolvía; lo que faltaba era que envolviera también cuando el renglón vive en una COLUMNA
   estrecha de una pantalla ancha —la de «En el taller» del calendario mide 380 px—. Ahí, un
   botón de «Acomodar en la lámina» dejaba al título 180 px y el nombre de un cliente salía en
   cinco renglones de dos palabras. Con `1 1 220px`, el texto pide 220 y si no los tiene, la
   acción se baja sola a su propio renglón. Es lo mismo que ya hacía el teléfono, dicho por
   el espacio disponible en vez de por el ancho de la ventana. */
.pf-fila{display:flex;flex-wrap:wrap;align-items:flex-start;gap:var(--e3);padding:var(--e3) 0;
  border-top:1px solid var(--line)}
.pf-fila:first-child{border-top:0}
.pf-fila-ico .svgi{width:var(--ico2);height:var(--ico2)}
.pf-fila-ico{flex-shrink:0;width:40px;height:40px;display:grid;place-items:center;
  border-radius:var(--rr1);background:var(--n1);color:var(--n7)}
.pf-fila-ico.urge{background:var(--av-bg);color:var(--av)}
.pf-fila-ico.mal{background:var(--mal-bg);color:var(--mal)}
.pf-fila-ico.bien{background:var(--ok-bg);color:var(--ok)}
.pf-fila-tx{flex:1 1 220px;min-width:0}
.pf-fila-t{font-weight:600;font-size:var(--t3);line-height:1.35;color:var(--ink)}
.pf-fila-d{margin-top:2px;font-weight:400;font-size:var(--t2);line-height:1.45;color:var(--muted)}
.pf-fila-acc{flex-shrink:0;display:flex;flex-direction:column;gap:var(--e1);align-items:stretch}
@media(max-width:560px){
  .pf-fila{flex-wrap:wrap}
  .pf-fila-acc{width:100%;flex-direction:row;padding-left:calc(36px + var(--e3))}
  .pf-fila-acc>*{flex:1}
}

/* Cuándo pasa algo. Un dato de tres caracteres que se lee antes que el texto: «hoy» en
   ámbar salta sin necesidad de leer el renglón. */
.pf-cuando{display:inline-block;padding:1px 8px;border-radius:var(--rr1);
  font-weight:700;font-size:var(--t1);line-height:18px;background:var(--n2);color:var(--n7)}
.pf-cuando.hoy{background:var(--av-bg);color:var(--av)}
.pf-cuando.tarde{background:var(--mal-bg);color:var(--mal)}
.pf-cuando.lejos{background:var(--n1);color:var(--muted)}

/* ----- Estado vacío -----
   La única clase que el cotizador no tenía y que aquí hace falta seis veces: una plataforma
   nueva arranca con las seis pantallas vacías, y «vacío» tiene que decir por qué y qué
   hacer, no solo estar en blanco. */
.vacio{padding:var(--e6) var(--e4);text-align:center;color:var(--muted)}
/* `>` y no descendiente. Con el selector abierto, este 32 px gris se metía TAMBIÉN en el
   icono del botón que el estado vacío lleva dentro: en Proyectos, «Abrir el cotizador»
   salía con un glifo de 32 px en gris --n4 sobre el azul sólido, al lado de otros botones
   con iconos de 14. El botón trae su propio tamaño desde `.btn`. */
.vacio > .svgi{width:var(--ico4);height:var(--ico4);color:var(--n4)}
.vacio-t{margin-top:var(--e3);font-weight:600;font-size:var(--t4);line-height:1.35;color:var(--n7)}
.vacio-d{margin-top:var(--e2);font-weight:400;font-size:var(--t3);line-height:1.5;max-width:42ch;
  margin-left:auto;margin-right:auto}
.vacio .btn{margin-top:var(--e4);width:auto;display:inline-flex}

/* ----- Etapa de obra -----
   Ámbar es «está en el taller», azul «se puede instalar», verde «terminado», gris
   «archivado». Nunca solo color: cada ficha lleva su palabra, por lo mismo que los pines
   del mapa llevan forma además de color. */
.pf-etapa{display:inline-flex;align-items:center;gap:5px;padding:2px 9px;
  border-radius:var(--rr1);font-weight:700;font-size:var(--t1);line-height:18px;white-space:nowrap}
.pf-etapa.ganado   {background:var(--n2);      color:var(--n7)}
.pf-etapa.cortado  {background:var(--av-bg);   color:var(--av)}
.pf-etapa.armado   {background:var(--av-bg);   color:var(--av)}
.pf-etapa.listo    {background:var(--a-suave); color:var(--a-fuerte)}
.pf-etapa.instalado{background:var(--ok-bg);   color:var(--ok)}
.pf-etapa.cerrado  {background:var(--n1);      color:var(--muted)}

/* ============================================================================
   Calendario
   ============================================================================ */
/* La tira de controles del calendario: la lente a la izquierda, la vista a la derecha, y los
   chips de filtro debajo cuando los hay. Eran tres renglones apilados —el porqué está escrito
   en el módulo—. `--e2` de hueco y `flex-wrap`: en un teléfono, la lente ocupa el primer
   renglón entero y la vista cae debajo, que es exactamente donde tiene que caer. */
.ag-barra{display:flex;flex-wrap:wrap;align-items:center;gap:var(--e2);margin-bottom:var(--e3)}
.ag-barra-der{margin-left:auto}
.ag-barra .ag-filtros{flex:1 1 100%;margin-bottom:0}
/* Por debajo de 760 px, `css/sistema.css` le da a `.tipo-seg` un `order:9` para mandarlo al
   final de la fila de una partida, que es donde tiene sentido allá. Aquí no: la lente ES un
   `.tipo-seg` suelto, y con ese orden se iba DEBAJO del segmento de vista —el filtro pintado
   después de lo que filtra—. Se le devuelve su sitio, igual que `.ag-filtros .tipo-seg` ya
   hacía por lo mismo. */
.ag-barra>.tipo-seg{order:0}

.cal-cab{display:flex;align-items:center;gap:6px;margin-bottom:var(--e3)}
/* El mes va CENTRADO entre sus dos flechas, que es como se lee un control de mes: el nombre
   crece y encoge —«Mayo» contra «Septiembre»— y con el texto pegado a la izquierda las dos
   flechas bailaban de sitio cada vez que se cambiaba de mes. El ancho mínimo lo fija en un
   sitio. */
.cal-mes{order:2;min-width:150px;text-align:center;font-family:var(--f-cifra);font-weight:600;
  font-size:var(--t4);line-height:1.2;color:var(--ink);text-transform:capitalize}
.cal-cab .cal-nav[data-mueve="-1"]{order:1}
.cal-cab .cal-nav[data-mueve="1"]{order:3}
.cal-cab [data-hoy]{order:4;margin-left:var(--e2)}
.cal-nav{width:34px;height:34px;display:grid;place-items:center;border:1px solid var(--linea);
  border-radius:var(--rr2);background:var(--sup);color:var(--tinta2);cursor:pointer;
  box-shadow:none;font-size:var(--t4)}
.cal-nav:hover{border-color:var(--a-borde);color:var(--tinta)}
.cal-nav:active{box-shadow:none;transform:translateY(1px)}
.cal-nav .svgi{width:var(--ico1);height:var(--ico1)}
/* Los 44 px del mínimo táctil, donde de verdad se toca con el dedo. En un monitor con ratón
   un botón de 34 px es cómodo y es el que pide la maqueta. */
@media(hover:none),(pointer:coarse){ .cal-nav{width:44px;height:44px} }

/* La rejilla del mes: sin hueco entre celdas y con las líneas de dentro de 1 px, que es lo
   que la hace leerse como una tabla de calendario y no como treinta y cinco tarjetas. El
   `gap:4px` de antes multiplicaba por 35 el aire y dejaba las celdas flotando. */
.cal-rej{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:0;
  border:1px solid var(--linea);border-radius:var(--rr3);overflow:hidden;background:var(--sup)}
.cal-dow{padding:var(--e2) 0;text-align:center;font-weight:600;font-size:var(--t1);line-height:1;
  color:var(--tinta3);text-transform:uppercase;letter-spacing:.08em;
  border-bottom:1px solid var(--linea)}
.cal-dia{position:relative;min-height:92px;padding:6px;border:0;
  border-right:1px solid var(--linea2);border-bottom:1px solid var(--linea2);
  border-radius:0;background:var(--sup);text-align:left;cursor:pointer;
  display:flex;flex-direction:column;gap:3px;overflow:hidden;min-width:0}
.cal-rej>.cal-dia:nth-child(7n+7){border-right:0}
.cal-dia:disabled{cursor:default}
.cal-dia.fuera{background:var(--sup2)}
.cal-dia.fuera .cal-n{color:var(--tinta3)}
/* El número del día vive en un círculo de 24 px y centrado, y HOY es ese círculo relleno del
   acento con la cifra en blanco. Antes «hoy» era un borde azul alrededor de la celda entera,
   que a un metro de distancia se confunde con el día que está abierto —que también lleva
   fondo azul tenue— y con la celda que tiene el foco del teclado. Tres señales azules para
   tres cosas distintas. Ahora hoy es el círculo, el día abierto es el fondo, y el foco es el
   anillo del sistema. */
.cal-n{align-self:center;width:24px;height:24px;display:inline-flex;align-items:center;
  justify-content:center;border-radius:12px;
  font-family:var(--f-cifra);font-weight:600;font-size:var(--t2);line-height:1;color:var(--tinta)}
.cal-dia.hoy{border-color:var(--linea2)}
.cal-dia.hoy .cal-n{background:var(--a-fill);color:#fff}
/* Cada instalación del día, con la etapa a la izquierda como filete de color. El texto va
   sobre el lienzo claro, no sobre el color: es la regla de --n5 hacia arriba. */
.cal-ev{display:block;width:100%;padding:2px 4px 2px 6px;border-radius:6px;
  background:var(--n1);border-left:3px solid var(--n4);
  font-weight:600;font-size:var(--t1);line-height:1.3;color:var(--n8);text-align:left;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cal-ev.cortado,.cal-ev.armado{border-left-color:var(--amber-ico)}
.cal-ev.listo{border-left-color:var(--a)}
.cal-ev.instalado{border-left-color:var(--green-ico)}
.cal-ev.ganado{border-left-color:var(--n4)}
/* El semáforo de material: un punto. Es la pregunta de fabricación mirando el mes —¿llego?—
   y tiene que contestarse sin abrir nada. Va acompañado del title y del texto de la ficha:
   un punto de color solo no es una respuesta accesible. */
.cal-sem{position:absolute;top:4px;right:4px;width:8px;height:8px;border-radius:50%}
.cal-sem.ok{background:var(--green-ico)}
.cal-sem.falta{background:var(--amber-ico)}
.cal-sem.grave{background:var(--red)}
.cal-mas{font-weight:600;font-size:var(--t1);line-height:1.3;color:var(--muted);padding-left:6px}
@media(max-width:560px){
  /* 48 px de celda, que es lo que pide la maqueta: en siete columnas de una pantalla de 360
     una celda mide 47 de ancho, y más alto que ancho se lee como una columna, no como un mes. */
  .cal-dia{min-height:48px;padding:3px;gap:2px}
  .cal-ev{padding:1px 3px;font-size:9.5px}
  /* En el teléfono el mes cabe pero los títulos no: cada evento se vuelve un PUNTO de 6 px
     del color de su tipo. El chip con el texto recortado a dos letras no dice nada y ocupa
     tres veces más; el punto dice «aquí pasa algo» y el detalle está a un toque, en la lista
     del día. Se apagan el relleno, el borde y el filete de color del chip para que no quede
     una caja de 6 px con un borde de 3. */
  .cal-ev{width:6px;height:6px;min-width:6px;flex:0 0 auto;padding:0;border-radius:3px;
    border-left:0;background:var(--n5);overflow:hidden;text-indent:-99em}
  .cal-ev.cortado,.cal-ev.armado,.cal-ev.en_diseno{background:var(--av)}
  .cal-ev.listo,.cal-ev.tal{background:var(--a)}
  .cal-ev.instalado{background:var(--ok)}
  .cal-ev.tal.tarde{background:var(--mal)}
  .cal-ev.off{background:var(--linea)}
  /* La celda pasa a fila que envuelve: el número se lleva un renglón entero con
     `flex-basis:100%` y los puntos fluyen debajo, centrados. En columna —como está en
     escritorio— los puntos saldrían uno debajo de otro y en 48 px caben dos. */
  .cal-dia{flex-flow:row wrap;justify-content:center;align-content:flex-start;gap:3px}
  .cal-n{flex:0 0 100%}
  .cal-ev .tx{display:none}
  .cal-mas{flex:0 0 100%;text-align:center;padding-left:0;font-size:9.5px}
}

/* ----- Lista del día -----
   Lo que el mes no puede decir. Se abre tocando un día. */
.dia-lista{margin-top:var(--e4)}
.dia-t{font-weight:700;font-size:var(--t4);line-height:1.3;color:var(--ink);margin-bottom:var(--e2);
  text-transform:capitalize}

/* ============================================================================
   Material
   ============================================================================ */
.mat-fila{display:grid;grid-template-columns:1fr auto;gap:var(--e2) var(--e3);
  padding:var(--e3) 0;border-top:1px solid var(--line);align-items:start}
.mat-fila:first-child{border-top:0}
.mat-n{font-weight:600;font-size:var(--t3);line-height:1.35;color:var(--ink)}
.mat-med{font-weight:400;font-size:var(--t1);line-height:1.4;color:var(--muted)}
/* La cantidad. Es el número que se viene a leer, así que la jerarquía la hace el TAMAÑO,
   no el color: pintar de color un número no lo vuelve más importante. */
.mat-cant{font-weight:700;font-size:var(--t5);line-height:1;color:var(--ink);text-align:right;white-space:nowrap}
.mat-cant small{display:block;margin-top:2px;font-weight:500;font-size:var(--t1);line-height:1;color:var(--muted)}
.mat-cant.falta{color:var(--av)}
.mat-cant.cero{color:var(--muted)}

/* La fórmula. Es la mitad del valor del módulo: un número que no se puede auditar no se
   corrige nunca, y estas cantidades salen de factores supuestos que HAY que corregir.
   Va en tipografía de máquina y en el tono tenue del acento, que es decoración. */
.mat-formula{grid-column:1/-1;padding:var(--e2) var(--e3);border-radius:var(--rr1);
  background:var(--a-suave);border:1px solid var(--a-borde);
  font:500 var(--t1)/1.5 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  color:var(--n8);overflow-x:auto;white-space:nowrap}
.mat-nota{grid-column:1/-1;font-weight:400;font-size:var(--t1);line-height:1.45;color:var(--muted)}

/* La confianza del cálculo, dicha con palabras. «Estimado» no es un adorno: es la
   diferencia entre comprar con esto y comprar con esto sabiendo qué se supuso. */
.mat-conf{display:inline-flex;align-items:center;gap:4px;padding:1px 7px;border-radius:var(--rr1);
  font-weight:700;font-size:var(--t1);line-height:17px}
.mat-conf.exacta{background:var(--ok-bg);color:var(--ok)}
.mat-conf.estimada{background:var(--n2);color:var(--n7)}
.mat-conf.requiere_dato{background:var(--av-bg);color:var(--av)}

/* El sello de frescura de una existencia. Un número de almacén sin fecha es una opinión. */
.mat-sello{font-weight:400;font-size:var(--t1);line-height:1.4;color:var(--muted)}
.mat-sello.viejo{color:var(--av)}

@media(max-width:385px){
  .mat-fila{grid-template-columns:1fr}
  .mat-cant{text-align:left}
}

/* ----- La lista de compra en papel -----
   Fabricación va a la vidriería con esto. No se imprime la app: se imprime la lista. */
/* Los dos bloques del papel. Nacen apagados y solo los enciende el @media print de aquí abajo:
   así no dependen de que un display:none llegue a tiempo, que es la clase de cosa que falla en
   una impresora y no en la pantalla donde se probó. */
.imp-marca,.imp-pie{display:none}

@media print{
  /* El encabezado y el pie, FIJOS: en papel eso significa que se repiten en todas las hojas, que
     es justo lo que hace falta en una lista de compra de dos páginas. El margen de @page les
     hace sitio; sin él se montarían encima de la primera fila. */
  .imp-marca{display:flex!important;align-items:center;gap:9px;position:fixed;top:0;left:0;right:0;
    padding-bottom:6px;border-bottom:2px solid var(--a)}
  .imp-logo{height:26px;width:auto;display:block}
  .imp-bar{width:1.5px;align-self:stretch;background:var(--n8);margin:0 3px}
  .imp-t{font-size:12px;font-weight:800;letter-spacing:.04em;color:var(--n8)}
  .imp-m{margin-left:auto;font-size:9px;color:var(--n6)}
  .imp-pie{display:flex!important;justify-content:space-between;position:fixed;bottom:0;left:0;right:0;
    padding-top:5px;border-top:1px solid var(--n3);font-size:8px;color:var(--n6)}

  /* Carta vertical, igual que el cotizador y que el documento que se manda al cliente. Los dos
     caminos de impresión de la plataforma —la lista de compra y la orden de obra de más abajo—
     salían en el tamaño que el navegador tuviera por omisión, o sea A4 fuera de MX y US. */
  @page{size:letter portrait;margin:18mm 12mm 14mm}
  .topbar,.pf-lat,.pf-cab,.pf-abajo,.pf-nav,.pf-mbar,.pf-banda,.toast,.pf-modal-bg,#pf-ajustes-btn{display:none!important}
  /* Y sin barra lateral, el hueco que se le reservaba tampoco. */
  .pf-wrap{padding-left:0!important}
  /* El hueco del encabezado y del pie fijos. Sin esto se pintan ENCIMA de la primera fila: en
     papel un position:fixed se coloca dentro del área de la página, no fuera, así que el margen
     de @page no le hace sitio por sí solo. Medido sobre la lista de compra: el encabezado tapaba
     el renglón de totales y la fila de filtros. */
  .pf-wrap{padding:38px 0 30px;max-width:none}
  .card{border:1px solid #ddd!important;box-shadow:none!important;break-inside:avoid}
  .mat-fila{break-inside:avoid}
  .mat-formula{background:#fff!important;border-color:#ddd!important}
  /* Lo que en pantalla es un renglón para tocar, en papel es un renglón para tachar. */
  .mat-fila::after{content:"";display:block;grid-column:1/-1;height:0}
  .compra-check{display:inline-block!important;width:14px;height:14px;border:1.5px solid #333;
    border-radius:3px;margin-right:8px;vertical-align:-2px}
}
.compra-check{display:none}

/* ============================================================================
   Mapa
   ============================================================================ */
/* Leaflet usa z-index 400 en sus paneles y 1000 en sus controles. Sin aislar, el botón de
   zoom se pinta encima del filete de marca (200) y encima del aviso que dice que algo no se
   pudo guardar. `isolation:isolate` crea un contexto de apilamiento propio: sus 1000 se
   quedan dentro de esta caja. */
/* El mapa y la ruta, uno al lado del otro. `minmax(0,1.5fr)` y no `1.5fr` a secas: un mapa de
   Leaflet mide lo que le den y sin el mínimo en 0 la columna crece con su contenido y empuja
   la ruta fuera de la pantalla. La ruta se pega arriba al desplazarse porque es lo que se lee
   mientras se mira el mapa. */
.mapa-2col{display:grid;grid-template-columns:minmax(0,1.5fr) minmax(300px,1fr);
  gap:var(--e4);align-items:start}
.mapa-2col>.mapa-col{min-width:0}
@media(max-width:759px){
  .mapa-2col{grid-template-columns:minmax(0,1fr)}
}
@media(min-width:1100px){
  .mapa-2col>.mapa-col:last-child{position:sticky;top:calc(64px + var(--e3))}
}
/* Los cuatro filtros de etapa llevan dos nombres, el largo y el corto, en el mismo par
   `.lg`/`.sm` que el selector de tipo de una partida. En la computadora se lee «G · Vendido,
   sin empezar (1)»; en el teléfono, «G · Vendido (1)», porque con el largo los cuatro chips
   ocupaban cuatro renglones y el mapa empezaba debajo del doblez. El nombre entero sigue
   viviendo en el `aria-label` y en la leyenda de debajo del mapa. */
#mapa-etapas .sm{display:none}
@media(max-width:759px){
  #mapa-etapas .lg{display:none}
  #mapa-etapas .sm{display:inline}
}
#mapa-lienzo{position:relative;isolation:isolate;z-index:1;height:60vh;min-height:320px;
  border-radius:var(--rr3);overflow:hidden;border:1px solid var(--linea);background:var(--sup2)}
/* En el teléfono, 45 vh: la mitad de la pantalla para el mapa y la otra mitad para la ruta,
   que es la que se lee parada por parada. Con 52 vh la primera parada quedaba justo debajo
   del doblez. */
@media(max-width:759px){#mapa-lienzo{height:45vh;min-height:280px}}
/* Leaflet trae su propia tipografía y sus propios grises. Se le imponen los de la app: un
   mapa con la letra del sistema operativo dentro de una app con Inter se ve incrustado. */
.leaflet-container{font-family:inherit;background:var(--n1)}
.leaflet-popup-content-wrapper{border-radius:var(--rr1);box-shadow:var(--clay)}
.leaflet-popup-content{margin:var(--e3);font-weight:400;font-size:var(--t2);line-height:1.5;color:var(--ink)}
.leaflet-popup-content b{font-weight:700}
.leaflet-bar a{color:var(--n7)}
/* La atribución de OpenStreetMap es obligatoria por su licencia y se queda visible.
   No se esconde ni se encoge hasta que no se lea. */
.leaflet-control-attribution{font-size:10px;background:rgba(var(--sup-rgb),.85)}

/* La leyenda del mapa: forma Y palabra, nunca color solo. Uno de cada doce hombres no
   distingue el verde del ámbar, y este mapa se lee para decidir a dónde va la camioneta. */
.mapa-leyenda{display:flex;flex-wrap:wrap;gap:var(--e2) var(--e4);margin-top:var(--e3);
  font-weight:500;font-size:var(--t2);line-height:1;color:var(--muted)}
.mapa-leyenda span{display:inline-flex;align-items:center;gap:6px}
.mapa-leyenda i{width:12px;height:12px;border:2px solid;display:inline-block}
.mapa-leyenda i.listo{border-color:var(--a);border-radius:50%}
.mapa-leyenda i.taller{border-color:var(--amber-ico);border-radius:2px}
.mapa-leyenda i.instalado{border-color:var(--green-ico);border-radius:50%;background:var(--green-ico)}
/* El pin de una obra sin ubicar no existe: no hay pin en medio del océano. Van en una lista
   aparte, y la lista lo dice. */
.mapa-sinubicar{margin-top:var(--e4)}

/* ============================================================================
   Modales de la plataforma
   ============================================================================ */
/* Se apoyan en .modal-bg del sistema —el velo, el desenfoque de atrás, la entrada desde
   abajo— y solo cambian el panel. */
.pf-modal-bg{align-items:flex-start;padding-top:calc(32px + env(safe-area-inset-top,0px))}
.pf-panel{width:100%;max-width:640px;max-height:calc(100vh - 64px - env(safe-area-inset-top,0px));
  display:flex;flex-direction:column;background:var(--card);border-radius:var(--rr3);
  box-shadow:var(--clay-alto);overflow:hidden}
.pf-panel-h{display:flex;align-items:center;gap:var(--e3);padding:var(--e4);
  border-bottom:1px solid var(--line);flex-shrink:0}
.pf-panel-h h2{flex:1;font-weight:700;font-size:var(--t4);line-height:1.3;color:var(--ink);min-width:0}
.pf-panel-b{padding:var(--e4);overflow-y:auto;-webkit-overflow-scrolling:touch}
.pf-panel-f{display:flex;gap:var(--e2);padding:var(--e4);border-top:1px solid var(--line);
  flex-shrink:0;padding-bottom:calc(var(--e4) + env(safe-area-inset-bottom,0px))}
.pf-panel-f .btn{flex:1}
.pf-cerrar{width:40px;height:40px;display:grid;place-items:center;border:0;border-radius:var(--rr1);
  background:var(--n1);color:var(--n7);cursor:pointer;flex-shrink:0}
@media(max-width:560px){
  .pf-modal-bg{padding:0;align-items:flex-end}
  .pf-panel{max-width:none;border-radius:var(--rr3) var(--rr3) 0 0;
    max-height:calc(100vh - 32px - env(safe-area-inset-top,0px))}
}

/* ============================================================================
   Detalles
   ============================================================================ */
/* Dos números uno junto al otro, para las cabeceras de módulo: «6 por instalar · 2 sin
   fecha». Es la primera cosa que se lee al entrar a una pantalla. */
/* Eran una cinta de texto suelto: los números y sus nombres flotando sobre el lienzo, uno al
   lado del otro, separados por 16 px de aire. A un ancho de escritorio eso deja «5 En el
   taller hoy» y «$106,504 En el taller» a doscientos píxeles uno de otro y con nada que diga
   dónde acaba uno y empieza el siguiente: se leían como una frase.

   Ahora cada cuenta es una tarjeta de la rejilla del rediseño —`auto-fit` desde 150 px— y así
   se reparten solas: seis en una fila a 1 440 px, tres a 880, dos en un teléfono. La cifra
   sube a 28 px con la letra de las cifras, que es el paso que el rediseño le reserva al
   número más grande de una pantalla.

   El filete de 3 px de arriba es lo que dice de qué tipo es la cuenta sin gastar el relleno:
   ámbar en la que reclama atención, azul en la del dinero. Va como `inset box-shadow` y no
   como `border-top`, que sumaría 3 px de alto solo a las que lo llevan y descuadraría la
   fila. */
.pf-cuentas{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  gap:var(--e3);margin-bottom:var(--e4)}
.pf-cuenta{margin:0;padding:14px var(--e4);background:var(--sup);border:1px solid var(--linea);
  border-radius:var(--rr3);font-weight:400;font-size:var(--t2);line-height:1.35;color:var(--tinta2)}
.pf-cuenta b{display:block;margin-bottom:6px;font-family:var(--f-cifra);font-weight:600;
  font-size:var(--t7);line-height:1;color:var(--tinta);font-variant-numeric:tabular-nums}
.pf-cuenta.urge{box-shadow:inset 0 3px 0 var(--av)}
.pf-cuenta.urge b{color:var(--av)}
.pf-cuenta.mal{box-shadow:inset 0 3px 0 var(--mal)}
.pf-cuenta.mal b{color:var(--mal)}
/* La del dinero lleva el filete azul y la cifra en la tinta del acento. Es el único sitio de
   la app donde el azul se usa sobre un número que no es una acción, y se gana el permiso: en
   una fila de cuentas que se leen de un barrido, «cuánto» es otra pregunta que «cuántos». */
.pf-cuenta.dinero{box-shadow:inset 0 3px 0 var(--a)}
.pf-cuenta.dinero b{color:var(--a-tx)}
/* Y en un teléfono estrecho, dos por fila: a 150 px de mínimo cabrían dos justas en 360 px
   con el relleno de la página, pero la etiqueta de tres palabras se parte en tres renglones y
   las tarjetas de la fila crecen todas al alto de la peor. */
@media(max-width:400px){
  .pf-cuentas{grid-template-columns:repeat(auto-fit,minmax(128px,1fr));gap:var(--e2)}
  .pf-cuenta{padding:10px var(--e3)}
  .pf-cuenta b{font-size:var(--t6)}
}

/* Un renglón de dato, para las fichas: etiqueta chica arriba, valor abajo. */
.pf-dato{padding:var(--e2) 0;border-top:1px solid var(--line)}
.pf-dato:first-child{border-top:0}
.pf-dato dt{font-weight:500;font-size:var(--t1);line-height:1.4;color:var(--muted)}
.pf-dato dd{margin-top:1px;font-weight:600;font-size:var(--t3);line-height:1.4;color:var(--ink);word-break:break-word}

/* La rejilla de dos columnas de las fichas. Se cae a una en el teléfono. */
.pf-2col{display:grid;grid-template-columns:1fr 1fr;gap:0 var(--e4)}
@media(max-width:560px){.pf-2col{grid-template-columns:1fr}}

/* El botón de WhatsApp. Lleva el verde del sistema porque es el color de la marca a la que
   manda, y es la única excepción de color de toda la plataforma: cualquier otra cosa verde
   aquí querría decir «terminado». */
.btn-wa{display:inline-flex;align-items:center;justify-content:center;gap:var(--e2);
  min-height:44px;padding:0 var(--e4);border:1px solid var(--ok-borde);border-radius:var(--rr2);
  background:var(--ok-bg);color:var(--ok);font-weight:700;font-size:var(--t3);line-height:1;cursor:pointer;
  text-decoration:none;box-shadow:var(--clay)}
.btn-wa:active{box-shadow:var(--clay-in);transform:translateY(1px)}

/* La barra fija del teléfono. Mismo esqueleto que la del cotizador. */
.pf-mbar{gap:var(--e2)}
.pf-mbar .btn{flex:1;margin:0}

/* ============================================================================
   Inicio — lo que la pantalla de «Hoy» necesitaba y no existía todavía
   ============================================================================ */

/* La banda de frescura cuando NO hay nada que advertir. La versión de ámbar ya existe y es
   .pf-banda; esta es su cara tranquila, y tranquila quiere decir chica y sin caja: una
   franja verde con borde diciendo «al día» todos los días es una felicitación diaria que se
   deja de leer, y el día que se vuelva ámbar nadie va a notar el cambio. */
.pf-frescura{display:flex;align-items:center;gap:var(--e2);margin-bottom:var(--e4);
  font-weight:500;font-size:var(--t2);line-height:1.4;color:var(--muted)}

/* La tarjeta de A6 reusa .cand-partidas del cotizador completa —el ámbar, el barro y el
   latido de 2.6 s— porque es exactamente el mismo mensaje: «esto pide que hagas algo antes
   de seguir». Lo único que cambia es la caja: allá es UN renglón que se toca completo, aquí
   son N cotizaciones con dos botones cada una, así que deja de ser una línea flex y deja de
   ser un botón. El latido tampoco se apaga al pasar el ratón, porque aquí el ratón no
   activa la tarjeta: lo que se toca son los botones de adentro, y quitarle el latido al
   pasar por encima haría creer que ya se atendió. */
.pf-decidir{display:block;cursor:default}
.pf-decidir:hover{transform:none;animation:latido 2.8s ease-in-out infinite}
/* Los renglones de dentro se separan con el borde de la tarjeta, que desde el rediseño es
   azul y no ámbar: el latido de esta tarjeta ya no es una sombra ámbar que crece, es el aro
   del acento —el mismo que usa la maqueta— y un filete ámbar dentro de una pieza azul se
   lee como un aviso distinto al de la pieza que lo contiene. */
.pf-decidir .pf-fila{border-top-color:var(--a-borde)}
/* El cuadro del icono va en el tono de tarjeta y no en el de la pieza: sobre el azul tenue
   de esta tarjeta, azul sobre azul no se distingue y el icono desaparecía. */
.pf-decidir .pf-fila-ico{background:var(--sup);color:var(--a-tx)}

/* Dos botones en un renglón: el margen de arriba de .btn+.btn 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—, que
   es el mismo problema que .btn-fila resuelve en el cotizador. Estos dos contenedores ya
   separan con `gap`, así que el margen sobra en los dos ejes. */
.pf-fila-acc .btn+.btn,.pf-panel-f .btn+.btn{margin-top:0}

/* La verdad del final, en letra chica y sin adornos. Con la caja gris de .hintnote se
   leería como un consejo, y esto no es un consejo: es cómo funciona el sistema. */
.pf-nota{margin-top:var(--e4);font-weight:400;font-size:var(--t1);line-height:1.55;color:var(--muted)}

/* ============================================================================
   Proyectos — lo que el tablero por etapa necesitaba
   ============================================================================ */

/* La etapa que faltaba de las ocho. Ámbar, que en la leyenda de arriba es «está en el
   taller», que es exactamente lo que es «en diseño»: ya se vendió y todavía no se corta.
   `garantia` y `cancelado` no llevan clase propia porque no son pasos del camino sino
   salidas de él, y para eso ya está el gris de `.pf-etapa.cerrado`. */
.pf-etapa.en_diseno{background:var(--av-bg);color:var(--av)}

/* El semáforo de un renglón: el material del proyecto y la fecha que le falta. Existe
   .mat-conf, del mismo tamaño y con las mismas cajas de color, pero contesta otra pregunta
   —qué tan confiable es un cálculo— y reusarla obligaba a leer «requiere_dato» como «falta
   material». Y hacía falta el rojo: a tres días de instalar, «faltan 2 materiales» ya no es
   un aviso, es un problema. Siempre con palabra: el color solo no dice nada a uno de cada
   doce hombres, y esto se lee para decidir si hay que ir a la vidriería hoy. */
.pf-sem{display:inline-flex;align-items:center;gap:4px;padding:1px 7px;border-radius:var(--rr1);
  font-weight:700;font-size:var(--t1);line-height:17px;white-space:nowrap}
.pf-sem.ok{background:var(--ok-bg);color:var(--ok)}
.pf-sem.falta{background:var(--av-bg);color:var(--av)}
.pf-sem.grave{background:var(--mal-bg);color:var(--mal)}
.pf-sem.nada{background:var(--n2);color:var(--n7)}

/* ----- Imprimir la orden de trabajo -----
   El @media print de más arriba esconde .pf-modal-bg, y con razón: imprimir la app con el
   velo azul encima no es imprimir nada. Pero la orden de trabajo VIVE en un modal, así que
   fabricación apretaba imprimir y salía una hoja en blanco. La clase se pone en <body>
   justo antes de window.print() y se quita en 'afterprint': mientras está, se imprime SOLO
   el panel —sin velo, sin sombra, sin los dos botones del pie— y el resto del documento no
   existe. Sin `position:static` el panel sale recortado al alto de la ventana, que es lo
   que hace un `position:fixed` en papel. */
@media print{
  /* La orden de obra esconde TODO menos su panel; el encabezado y el pie del papel son la
     excepción, o esa hoja sale otra vez sin marca. */
  body.pf-print-hoja>*:not(.imp-marca):not(.imp-pie){display:none!important}
  body.pf-print-hoja>#pf-hoja{display:block!important;position:static;inset:auto;padding:0;
    background:none;backdrop-filter:none;-webkit-backdrop-filter:none}
  body.pf-print-hoja #pf-hoja .pf-panel{max-width:none;max-height:none;box-shadow:none;
    border-radius:0;overflow:visible}
  body.pf-print-hoja #pf-hoja .pf-panel-b{overflow:visible;padding:0}
  /* Y el mismo hueco para la orden de obra, que imprime su panel y no .pf-wrap. */
  body.pf-print-hoja #pf-hoja{padding:38px 0 30px}
  body.pf-print-hoja #pf-hoja .pf-panel-h{padding-left:0;padding-right:0}
  body.pf-print-hoja #pf-hoja .pf-panel-f,
  body.pf-print-hoja #pf-hoja .pf-cerrar{display:none!important}
}

/* ============================================================================
   Material — lo que las tres pestañas necesitaban y no existía todavía
   ============================================================================ */

/* Los botones de un renglón de material. `.mat-fila` es una rejilla de dos columnas —el
   nombre y la cantidad— y los dos botones de «En almacén» no caben en ninguna de las dos:
   en la del número lo empujan fuera de la vista, y debajo del nombre quedan pegados al
   texto que describen. Cruzan la rejilla completa, y el `display:flex` con su `gap` lo pone
   `.btn-fila` del sistema, que es la clase que ya resuelve dos botones en un renglón. */
.mat-acc{grid-column:1/-1;margin-top:var(--e1)}

/* Lo que no va al papel. El @media print de más arriba ya esconde la barra, la banda y los
   modales, pero la hoja de compra que fabricación se lleva a la vidriería seguía saliendo
   con las pestañas, con la tarjeta de calibración, con los botones de cada renglón y con la
   lista de lo que YA está en el taller. Un renglón que dice «no compres esto» en una hoja
   de compra se lee mal en el mostrador: se pide lo que está tachado. */
@media print{
  .no-papel{display:none!important}
}

/* ============================================================================
   Agenda — lo que el calendario necesitaba y no existía todavía
   ============================================================================ */

/* El día que está abierto. La rejilla ya marca HOY con el borde de acento, y el día que se
   está mirando necesita su propia marca: sin ella, tocar un día y que la lista apareciera
   trescientos píxeles más abajo dejaba sin saber cuál se había tocado —y en un mes con
   quince días agendados eso se resuelve tocando otro, que abre otra lista—. Fondo tenue del
   acento, el mismo recurso de `.pf-tab.on`, y el `aria-current="date"` lo dice para quien no
   ve el fondo. */
.cal-dia[aria-current="date"]{background:var(--a-suave);border-color:var(--a-borde)}

/* Dos casos que se quedaron sin filete. `en_diseno` va en ámbar por lo mismo que en
   `.pf-etapa`: ya se vendió y todavía no se corta. Y una instalación CANCELADA no se pinta
   igual que una viva —el mes estaría prometiendo una visita que no va a pasar—: se tacha,
   que es lo único que se lee igual sin distinguir colores. */
.cal-ev.en_diseno{border-left-color:var(--amber-ico)}
.cal-ev.off{border-left-color:var(--n3);color:var(--muted);text-decoration:line-through}

/* El semáforo del día, con su palabra y su frase completa. No cabe dentro de `.dia-t`
   porque ese lleva `text-transform:capitalize` y «Falta acrílico blanco 3 mm» salía como
   «Falta Acrílico Blanco 3 Mm», que se lee como un nombre propio y no como una advertencia. */
.ag-sem{display:flex;flex-wrap:wrap;align-items:center;gap:var(--e2);margin-bottom:var(--e3);
  font-weight:400;font-size:var(--t2);line-height:1.45;color:var(--muted)}

/* La tira de filtros de arriba del calendario. `.chips` ya existe pero nace pegada a su
   etiqueta (`margin-top:4px`) porque vive dentro de un `.fld`; aquí es una tira suelta y lo
   que necesita es separación abajo, no arriba. */
.ag-filtros{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:var(--e4)}
/* `.tipo-seg` se lleva `order:9` por debajo de 760 px (css/sistema.css) para irse al final
   de la fila de la partida, que es donde tiene sentido allá. Aquí no: en `.ag-filtros` eso
   pintaba el chip «Solo los días con cobro» ENCIMA de Mes/Semana/Lista en cualquier teléfono
   — el filtro antes que lo que filtra. Se devuelve al principio. */
.ag-filtros .tipo-seg{order:0}

/* ----- La lente: Taller / Instalaciones / Todo -----
   En su propio renglón y a ancho completo, arriba del segmento de vista. Son dos preguntas
   distintas —qué miro y cómo lo miro— y en la misma tira la de arriba se lee como si filtrara
   a la de abajo. A ancho completo porque es el estado principal de la pantalla. */
/* La lente ya no es una barra a ancho completo: vive en `.ag-barra` con la vista al lado.
   El bloque que la estiraba se fue con ella; lo que queda es que en el teléfono, donde la
   tira envuelve, la lente ocupe su renglón entero y sus tres botones se repartan. */
@media(max-width:559px){
  .ag-barra>.tipo-seg:first-child{flex:1 1 100%}
  .ag-barra>.tipo-seg:first-child button{flex:1;min-width:0}
  .ag-barra-der{margin-left:0}
}

/* El rótulo de un grupo dentro del calendario o del día. En versalitas y --t1, como
   `.cal-dow`, para que se lea como rótulo y no como título: «En el taller» compitiendo en
   tamaño con «lun 1 sep» son dos encabezados y ninguno manda. */
.ag-grupo{display:flex;align-items:center;gap:var(--e2);margin:var(--e3) 0 var(--e1);
  font-weight:700;font-size:var(--t1);line-height:1;color:var(--muted);
  text-transform:uppercase;letter-spacing:.04em}
.ag-grupo .svgi{width:var(--ico1);height:var(--ico1)}
.ag-grupo .n{margin-left:auto;font-variant-numeric:tabular-nums}

/* ----- La fila del taller -----
   La ventana de una a tres semanas NO se dibuja sobre la rejilla del mes: en celdas de 76 px
   —39 en el teléfono— no cabe, y partir la rejilla para meterle una capa es el cambio más
   caro y frágil del plan. Aquí cabe entera: un renglón `.pf-fila` de siempre con una pista
   debajo del texto —empezar ─ hoy ─ listo— que es un riel de 6 px con un punto. El riel
   nunca es la única fuente: la frase de arriba dice lo mismo con palabras. */
.tal-pista{display:flex;align-items:center;gap:var(--e2);margin-top:6px;
  font-weight:500;font-size:var(--t1);line-height:1;color:var(--muted);white-space:nowrap}
.tal-fecha{flex-shrink:0;font-variant-numeric:tabular-nums}
.tal-riel{position:relative;flex:1;min-width:40px;height:6px;border-radius:999px;
  background:var(--a-suave);border:1px solid var(--a-borde)}
.tal-riel.tarde{background:var(--av-bg);border-color:var(--av-borde)}
/* La ventana sin fecha de instalación es una hipótesis, y se ve: punteada. */
.tal-riel.propuesta{background:none;border-style:dashed;border-color:var(--n4)}
.tal-hoy{position:absolute;top:50%;width:12px;height:12px;margin:-6px 0 0 -6px;border-radius:50%;
  background:var(--a);border:2px solid #fff;box-shadow:0 0 0 1px var(--a-borde)}
.tal-riel.tarde .tal-hoy{background:var(--amber-ico)}

/* ----- La ficha del plazo, que además es el botón que lo corrige -----
   El plazo sale de una tabla y una tabla se equivoca con el proyecto que la contradice. Si
   corregirlo costara abrir otra pantalla nadie lo corregiría y la ventana mentiría para
   siempre. Así que leerlo y corregirlo son el mismo gesto. «Puesto a mano» manda sobre lo
   calculado, y se ve: el fondo tenue del acento con el que el sistema marca lo elegido. Para
   pagos es un <span> con la misma cara y sin cursor: no tiene nada que cambiar ahí. */
.cal-plazo{display:inline-flex;align-items:center;gap:var(--e1);
  min-height:28px;padding:0 10px;border:1px solid var(--n3);border-radius:999px;
  background:linear-gradient(168deg,var(--sup),var(--n1));box-shadow:var(--clay-in);
  color:var(--n7);font-family:inherit;font-weight:600;font-size:var(--t1);line-height:1;white-space:nowrap}
button.cal-plazo{cursor:pointer}
button.cal-plazo::after{content:'▾';font-size:9px;color:var(--muted)}
button.cal-plazo:active{transform:translateY(1px) scale(.98)}
.cal-plazo .svgi{width:var(--ico1);height:var(--ico1);color:var(--n6)}
.cal-plazo.mano{border-color:var(--a-borde);background:var(--a-suave);color:var(--a-fuerte)}
.cal-plazo.mano .svgi{color:var(--a)}
/* Los 44 px van por puntero grueso Y por ancho de teléfono: en el navegador de un escritorio
   angosto sigue siendo cómodo, y así lo mide igual quien lo prueba emulando el ancho. */
@media(hover:none),(pointer:coarse),(max-width:560px){ button.cal-plazo{min-height:44px;padding:0 14px} }

/* ----- La computadora: dos columnas cuando caben -----
   En el teléfono el calendario y la fila del taller van uno debajo del otro. En un monitor
   eso deja la mitad derecha vacía y el panel del día trescientos píxeles más abajo. De
   1 100 px para arriba —la .wrap tope en 1 180 y quita 48 de relleno— la lente «Todo» pone el
   calendario a la izquierda y la fila del taller a la derecha, con el mismo marcado: es la
   misma pantalla, solo cambia dónde cae cada cosa. La columna derecha se pega arriba al
   desplazarse porque es la que se lee mientras se mira el mes. */
.ag-cuerpo.dos,.tb-cuerpo{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--e4);align-items:start}
.ag-cuerpo.dos>*,.tb-cuerpo>*{min-width:0}
@media(min-width:1100px){
  .ag-cuerpo.dos,.tb-cuerpo{grid-template-columns:minmax(0,1fr) minmax(380px,440px)}
  .ag-cuerpo.dos>.card,.tb-cuerpo>.card{position:sticky;top:calc(3px + 78px + var(--e3))}
}
/* En la lente Taller, en el teléfono, la fila va PRIMERO: es la pregunta de la mañana. En el
   monitor las dos columnas ya la ponen al lado, y el orden no hace falta. */
@media(max-width:1099px){ .ag-cuerpo.dos.taller-primero>.card,.tb-cuerpo.taller-primero>.card{order:-1} }

/* ----- Lo que vence en el taller, en la celda del mes -----
   Un chip por hito —empezar, cortar, armar, listo— con el nombre corto y el verbo. Se
   distingue de una instalación por la FORMA, no solo por el color: el filete va punteado y
   el fondo es el tenue del acento. Tarde va en rojo con la palabra en la lista del día. */
.cal-ev.tal{border-left-style:dotted;background:var(--a-suave);color:var(--a-fuerte)}
.cal-ev.tal.empezar{border-left-color:var(--n5)}
.cal-ev.tal.cortar,.cal-ev.tal.armar{border-left-color:var(--amber-ico)}
.cal-ev.tal.listo{border-left-color:var(--a)}
.cal-ev.tal.tarde{background:var(--mal-bg);color:var(--mal);border-left-color:var(--red)}
.tal-fila-dia .pf-fila-t{font-size:var(--t3)}

/* La columna de acciones de una ficha. Existe `.pf-fila-acc`, pero en el teléfono se
   convierte en una fila horizontal con relleno a la izquierda —tiene todo el sentido dentro
   de un `.pf-fila`, donde se alinea debajo del texto— y aquí son hasta seis botones dentro
   de un panel: quedaban de cuarenta píxeles de ancho con el texto cortado. */
.pf-acciones{display:flex;flex-direction:column;gap:var(--e2);margin-top:var(--e4)}
.pf-acciones>*{width:100%}
.pf-acciones .btn+.btn,.pf-acciones .btn-wa+.btn{margin-top:0}

/* Un botón que no ocupa el ancho completo. `.btn` es ancho completo a propósito —es LA
   acción de una tarjeta— y estos son acciones sueltas dentro de un párrafo: «Agendar el 3
   de septiembre» de borde a borde se lee como la acción principal de la pantalla, y no lo es. */
.pf-btn-corto{width:auto;display:inline-flex;align-items:center;justify-content:center;
  gap:var(--e2)}

/* ============================================================================
   AJUSTES — mod/ajustes.js
   ============================================================================ */

/* Ajustes es la única pantalla que no sirve para trabajar, así que es la única que puede
   permitirse párrafos: aquí se explica por qué hace falta un Worker y qué se ve en la
   pantalla de consentimiento de Google. `.vacio-d` no sirve —centra el texto, porque nace
   de un estado vacío— y cuatro renglones centrados no se leen. */
.aj-p{margin:var(--e3) 0 0;font-weight:400;font-size:var(--t2);line-height:1.6;color:var(--n7);max-width:62ch}

/* Un bloque de campos que abre un tema nuevo dentro de la misma tarjeta. Sin la
   separación, el campo del Client ID se leía como parte del último paso. */
.aj-bloque{margin-top:var(--e5)}

/* `.hintnote` nace inline-block y sin margen porque vive pegada a un campo. En esta
   pantalla van varias seguidas y sin esto se tocan, y tres avisos pegados se leen como un
   solo párrafo de tres colores. */
.aj-nota{display:block;margin-top:var(--e3)}
.aj-nota:first-child{margin-top:0}

/* Los pasos de Fase 2 son doce pantallas de Google Cloud en un orden que no se puede
   alterar, así que van numerados de verdad: una lista de viñetas invita a leerlos
   salteados, y saltarse el que dice «déjalo en Testing» cuesta la cuenta. El reset del
   sistema pone padding:0 en todo, y sin este relleno los números se pintan fuera de la
   tarjeta. */
.aj-pasos{margin:var(--e3) 0 0;padding-left:1.5em;font-weight:400;font-size:var(--t2);line-height:1.6;color:var(--n7)}
.aj-pasos li{margin-bottom:var(--e2)}
.aj-pasos li::marker{color:var(--muted);font-weight:700}

/* Lo que le falta a la base de Notion. Es una lista para COPIAR a mano en otra pestaña, no
   para leer de corrido: cada renglón tiene que poder localizarse de un vistazo mientras se
   mira la otra ventana, y por eso el nombre va suelto y en negritas en vez de dentro de una
   frase. Sin viñeta, que aquí solo estorba: el nombre ya es el ancla. */
.aj-faltan{list-style:none;margin:var(--e3) 0 0;padding:0;
  font-weight:400;font-size:var(--t2);line-height:1.5;color:var(--n7)}
.aj-faltan li{padding:var(--e2) var(--e3);margin-bottom:var(--e2);
  /* --fondo NO EXISTE en ningún archivo del repositorio. Una var() sin definir y sin valor de
     reserva invalida la declaración ENTERA en tiempo de cómputo, así que estas dos piezas se
     quedaban sin fondo: se pintaban sobre el blanco de .card y eran texto con borde y nada
     dentro. --n1 es el fondo tenue que el sistema ya usa para lo hundido (--soft y --bg salen
     de él) y da el contraste que hace falta contra una tarjeta blanca. */
  border:1px solid var(--n3);border-radius:var(--rr1);background:var(--n1)}
.aj-faltan b{color:var(--ink)}

/* Los tres tokens, una sola vez. Va en `pre` porque es JSON que se pega tal cual en otra
   pantalla y un espacio de más lo rompe, y con `break-all` porque un UUID no tiene dónde
   partirse: sin eso, en un teléfono se sale de la tarjeta y el botón de copiar queda fuera
   de alcance. */
.aj-tokens{margin:var(--e3) 0 0;padding:var(--e3);border:1px solid var(--n3);
  border-radius:var(--rr1);background:var(--n1);color:var(--n7);
  font:400 var(--t1)/1.6 ui-monospace,SFMono-Regular,Menlo,monospace;
  white-space:pre-wrap;word-break:break-all;-webkit-user-select:all;user-select:all}

/* Elegir rol con su descripción completa. No cabe en `.tipo-seg` —son tres palabras por
   opción, no dos— ni en un `.chip`: elegir un rol sin saber qué te va a esconder es
   elegir a ciegas, y el que se equivoca aquí acaba creyendo que la plataforma no trae
   pantalla de cobranza. El elegido lleva fondo tenue del acento y su tinta, como todo lo
   elegido del sistema. */
.aj-rol{display:flex;align-items:flex-start;gap:var(--e3);width:100%;text-align:left;
  padding:var(--e3);margin-bottom:var(--e2);border:1px solid var(--n3);border-radius:var(--rr1);
  background:var(--card);color:var(--n7);font-weight:400;font-size:var(--t2);line-height:1.5;font-family:inherit;
  cursor:pointer;transition:border-color .12s,background .12s}
.aj-rol:hover{border-color:var(--n4)}
/* La ficha de rol mide 364x84: es una pieza grande y el glifo que marca cuál está elegido
   es lo primero que se busca en ella. Heredaba los 12,5 px de la descripción —cuando la
   tipografía empezó a aplicarse de verdad— y se perdía. Es el caso de --ico2: el icono ES
   la pieza, no un adorno dentro de una frase. */
.aj-rol .svgi{flex-shrink:0;margin-top:1px;width:var(--ico2);height:var(--ico2)}
.aj-rol b{display:block;font-weight:700;font-size:var(--t3);line-height:1.35;color:var(--ink);margin-bottom:2px}
.aj-rol.on{background:var(--a-suave);border-color:var(--a-borde);color:var(--a-fuerte)}
.aj-rol.on b{color:var(--a-fuerte)}

/* El tercer tono de `.hintnote`. Ya existían `nota-av` y `nota-ok`; el rojo faltaba, y el
   único lugar del sistema que lo necesita es el cordón de borrar todo, donde el aviso no
   es «ten cuidado» sino «esto no se puede deshacer». */
.hintnote.nota-mal{background:var(--mal-bg);border:1px solid var(--mal-borde);color:var(--mal)}

/* ============================================================================
   Mapa — lo que el pin necesitaba y no existía todavía
   ============================================================================ */

/* El pin. Es un `L.divIcon`, así que Leaflet le pone el ancho y el alto como estilo en
   línea (`iconSize`) y le REEMPLAZA la clase por la que se le pase: no queda nada del
   cuadrito blanco de `.leaflet-div-icon`, y por eso todo lo que se ve del pin se define
   aquí. `box-sizing` explícito porque el borde de 2 px tiene que caber DENTRO de los 26 px
   del `iconSize`; sin él el pin queda descentrado de su propia coordenada.

   Las tres formas son las de `.mapa-leyenda`, y la letra de adentro es el cuarto indicio
   después de la forma, el relleno y el color: uno de cada doce hombres no distingue el
   verde del ámbar, y este mapa se lee para decidir a dónde manejar. */
.mapa-pin{box-sizing:border-box;display:grid;place-items:center;border:2px solid;
  background:var(--card);font-weight:800;font-size:11px;line-height:1;letter-spacing:0;box-shadow:var(--clay)}
/* Vendido y sin empezar: gris, que en `.pf-etapa` es exactamente lo que significa. No se
   pinta ámbar porque ámbar es «está en el taller» y esto todavía no entró. */
.mapa-pin.ganado{border-color:var(--n4);color:var(--n7);border-radius:3px}
.mapa-pin.taller{border-color:var(--amber-ico);color:var(--av);border-radius:3px}
.mapa-pin.listo{border-color:var(--a);color:var(--a-fuerte);border-radius:50%}
/* El relleno es el indicio de «ya está puesto»: se ve incluso reducido a cuatro píxeles,
   que es como se ve un pin cuando el mapa está en toda la ciudad. El aro conserva el verde
   de la leyenda para que el cuadrito de abajo y el pin sean la misma cosa, pero el relleno
   va con --ok y no con --green-ico: la letra es blanca de 11 px, y sobre --green-ico el
   contraste es 3,39:1 —debajo del mínimo para texto chico— mientras que sobre --ok es
   5,19:1. Es el mismo par que ya usa `.btn-ok`. */
.mapa-pin.instalado{border-color:var(--green-ico);background:var(--ok);color:#fff;
  border-radius:50%}
/* En la ruta del día la letra se cambia por el número de la parada, y el pin se levanta del
   resto con un aro del acento: la numeración tiene que leerse como un conjunto. */
.mapa-pin.ruta{box-shadow:0 0 0 3px var(--a-borde),var(--clay)}
/* El pin que se está poniendo a mano: mismo tamaño, borde punteado y el icono de pin
   adentro. Punteado porque todavía no está guardado, y eso hay que verlo. */
.mapa-pin.mano{border-color:var(--a);border-style:dashed;color:var(--a-fuerte);
  border-radius:50%;background:var(--card)}
.mapa-pin.mano .svgi{width:14px;height:14px}

/* La cuarta entrada de la leyenda. Las tres que ya estaban no cubrían «vendido, sin
   empezar», y ese es el estado en el que un proyecto pasa más días. */
.mapa-leyenda i.ganado{border-color:var(--n4);border-radius:2px}

/* La línea de la ruta. Leaflet pinta el trazo con atributos de presentación (`stroke`,
   `stroke-width`), que pierden contra cualquier regla de hoja de estilos: por eso la
   polilínea se crea con `className` y su color se decide aquí, con el acento del sistema,
   en vez de quedarse con el azul suelto de la librería. Punteada porque es un orden
   sugerido, no un trazado por calles. */
.mapa-ruta-linea{stroke:var(--a);stroke-width:3;stroke-dasharray:7 7;fill:none;opacity:.85}

/* Mientras se pone un pin a mano, el cursor deja de ser la manita de arrastrar el mapa: lo
   que se va a hacer es apuntar. Va con el id porque vendor/leaflet.css se carga DESPUÉS de
   esta hoja y su `.leaflet-container{cursor:grab}` le gana a una sola clase. */
#mapa-lienzo.poniendo .leaflet-container{cursor:crosshair}

/* La barra del modo «pin a mano». Es `.hintnote.nota-av` —el mismo ámbar de «esto que
   estás viendo tiene una condición»— pero lleva dos botones adentro, y `.hintnote` es un
   inline-block pensado para texto suelto: los botones quedaban pegados a la última palabra
   y en el teléfono partían el renglón a la mitad. */
.mapa-modo{display:flex;flex-wrap:wrap;align-items:center;gap:var(--e2);width:100%;
  margin-bottom:var(--e3)}
.mapa-modo>span{flex:1 1 12ch;min-width:0}

/* La dirección tal como la escribieron, con sus renglones. Reacomodarla en un párrafo es lo
   que convierte «interior 4, atrás de la farmacia» en una calle que no existe, y esa
   dirección es lo único que tiene quien va a poner el pin a mano. */
.mapa-dir{display:block;white-space:pre-line}

/* ============================================================================
   TABLERO — la línea de estaciones
   ============================================================================ */

/* La línea de estaciones es la tubería del taller: cinco bloques en el orden del proceso,
   cada uno con cuántos hay y cuántos van atrasados. Se construye sobre `.pf-cuentas` y
   `.pf-cuenta`, que ya tienen el número grande y la etiqueta chica: lo único que hace falta
   es volverlos pulsables. Ocho declaraciones y CERO tokens nuevos. Un componente propio
   habría sido una segunda forma de decir «un número con su nombre» en el mismo producto.

   El gap es propio porque aquí los bloques son cajas con borde y el `gap:var(--e1) var(--e4)`
   de la cinta —pensado para texto suelto— los deja pegados. */
/* Cinco bloques más chicos que las cuentas de arriba: son un filtro, no el titular de la
   pantalla, así que su cifra baja un escalón —24 px— y el mínimo de la rejilla baja a 110 px
   para que los cinco quepan en una fila hasta en el Fold. El fondo es la superficie hundida,
   que es lo que dice «esto es un control» sin gastar borde de color; el elegido toma el azul
   tenue, que es la marca de «esta es la vista que estás mirando». */
.tb-linea{grid-template-columns:repeat(auto-fit,minmax(110px,1fr));gap:var(--e2)}
.tb-etapa{min-height:44px;padding:12px 12px 10px;text-align:left;
  border:1px solid var(--linea);border-radius:var(--rr2);background:var(--sup2);
  box-shadow:none;cursor:pointer;transition:background var(--mv-s),border-color var(--mv-s)}
.tb-etapa b{font-size:var(--t6);margin-bottom:5px}
.tb-etapa:hover{transform:none;border-color:var(--a-borde)}
.tb-etapa:active{box-shadow:none;transform:translateY(1px)}
.tb-etapa.on{background:var(--a-suave);border-color:var(--a-borde);color:var(--tinta2);box-shadow:none}
.tb-etapa.on b{color:var(--tinta)}
/* «2 atrasados» va en ámbar y en su propio renglón. Es el dato que no existía en ninguna
   pantalla: qué debería estar cortado y sigue en diseño. El `min-height` reserva su renglón
   también en las estaciones que no lo tienen: sin eso, las cinco cajas de la fila miden
   distinto según cuál vaya tarde hoy, y la fila entera se mueve al avanzar una etapa. */
.tb-etapa em{display:block;margin-top:2px;min-height:15px;font-style:normal;font-weight:600;
  font-size:var(--t1);line-height:1.3;color:var(--av)}

/* ============================================================================
   PROYECTOS — el tablero de columnas
   ============================================================================ */

/* Cinco columnas de 200 px como mínimo, y la fila se desliza en horizontal cuando no caben:
   a 880 px —el Fold abierto— cinco por 200 más los gaps dan 1 048, así que ahí SÍ se
   desliza, y está bien. Lo que no puede pasar es que se aprieten hasta que el nombre de un
   cliente no quepa, que es lo que haría un `1fr` sin mínimo. */
.pj-tablero{display:grid;grid-template-columns:repeat(5,minmax(200px,1fr));gap:var(--e3);
  overflow-x:auto;padding-bottom:var(--e1)}
.pj-col{display:flex;flex-direction:column;gap:var(--e2);min-width:0}
/* El encabezado de columna lleva un filete de 2 px del color de su etapa: es lo único de
   color del tablero, y es lo que hace que las cinco colas se distingan de un vistazo sin
   pintar treinta y cinco tarjetas de colores. Los colores salen de `.pf-etapa`, que es donde
   ya viven —ganado gris, en diseño y taller ámbar, listo azul—: una etapa no se puede pintar
   de un color en la ficha y de otro en la columna. */
.pj-col-h{display:flex;align-items:center;gap:var(--e2);padding:6px 4px;
  border-bottom:2px solid var(--n5)}
.pj-col-h.en_diseno,.pj-col-h.cortado,.pj-col-h.armado{border-bottom-color:var(--av)}
.pj-col-h.listo{border-bottom-color:var(--a)}
.pj-col-h.instalado{border-bottom-color:var(--ok)}
.pj-col-t{font-family:var(--f-cifra);font-weight:600;font-size:var(--t3);color:var(--ink)}
.pj-col-n{margin-left:auto;font-size:var(--t2);font-weight:600;color:var(--tinta3);
  font-variant-numeric:tabular-nums}
.pj-col-vacia{padding:var(--e3) 4px;font-size:var(--t2);color:var(--tinta3)}

/* La tarjeta. Es lo único de la app que lleva sombra además de los controles del mapa, y se
   la gana: en un tablero, una tarjeta es una pieza que se mueve de columna, y una pieza que
   se mueve tiene que verse despegada de su columna. */
.pj-tarj{display:flex;flex-direction:column;gap:3px;width:100%;text-align:left;
  padding:var(--e3);border:1px solid var(--linea);border-radius:var(--rr3);
  background:var(--sup);box-shadow:var(--sombra);cursor:pointer;font-family:inherit;
  transition:border-color var(--mv-s)}
.pj-tarj:hover{border-color:var(--a-borde)}
.pj-tarj:active{transform:translateY(1px)}
.pj-tarj-t{font-weight:600;font-size:var(--t3);line-height:1.3;color:var(--ink)}
.pj-tarj-d{font-size:var(--t2);line-height:1.35;color:var(--tinta2)}
.pj-tarj-f{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-top:7px}
.pj-tarj-inst{display:inline-flex;align-items:center;gap:4px;font-size:var(--t1);color:var(--tinta3)}
.pj-tarj-inst .svgi{width:12px;height:12px}
.pj-tarj-pie{display:flex;justify-content:space-between;align-items:baseline;gap:var(--e2);
  margin-top:7px;padding-top:var(--e2);border-top:1px solid var(--linea2)}
.pj-tarj-folio{font-size:var(--t1);color:var(--tinta3)}
.pj-tarj-monto{font-family:var(--f-cifra);font-weight:600;font-size:var(--t3);
  color:var(--ink);font-variant-numeric:tabular-nums}

/* Con tablero, la tira de etapas sobra: las columnas SON el filtro, y dos filtros que
   contestan la misma pregunta en la misma pantalla es el camino corto a que digan cosas
   distintas. En el teléfono no hay tablero y la tira es lo único que filtra, así que se
   queda. Y ahí la ficha de etapa de dentro de la tarjeta también sobra: la columna lo dice. */
@media(min-width:760px){ #pj-filtros{display:none} .pj-tarj-etapa{display:none} }

/* ----- La misma tarjeta, en una columna -----
   El lomo de 4 px es lo que en el tablero dice la columna. Va como `border-left` y no como
   sombra porque aquí sí tiene que ocupar sitio: separa el color del texto. */
.pj-lista-movil{display:flex;flex-direction:column;gap:var(--e3)}
.pj-lista-movil .pj-tarj{border-left:4px solid var(--n5);padding:14px}
.pj-lista-movil .pj-tarj.en_diseno,
.pj-lista-movil .pj-tarj.cortado,
.pj-lista-movil .pj-tarj.armado{border-left-color:var(--av)}
.pj-lista-movil .pj-tarj.listo{border-left-color:var(--a)}
.pj-lista-movil .pj-tarj.instalado{border-left-color:var(--ok)}
.pj-lista-movil .pj-tarj-t{font-size:14.5px}

/* La tira de etapas del teléfono se DESLIZA, no envuelve. Con seis etapas envolviendo, el
   filtro medía dos renglones y ochenta píxeles de alto encima de la lista que filtra, y la
   segunda fila caía centrada y descuadrada respecto de la primera. Deslizándose ocupa uno.
   `flex:0 0 auto` en los botones es lo que impide que se compriman en vez de desbordar, que
   es lo que hace un flex por omisión. */
@media(max-width:759px){
  /* `display:flex` explícito: por debajo de 760 px, css/sistema.css convierte a `.tipo-seg` en
     una rejilla de tres columnas —lo correcto para el selector de tipo de una partida, que
     tiene exactamente cinco opciones cortas—. Aquí hay seis etapas con nombres de hasta cinco
     palabras («Listo para instalar 1»), y en tres columnas eso son dos renglones de 68 px
     encima de la lista que filtran. Sin volver a flex, el `flex-wrap` de abajo no hace nada. */
  #pj-filtros .tipo-seg{display:flex;flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;
    -webkit-overflow-scrolling:touch}
  #pj-filtros .tipo-seg::-webkit-scrollbar{display:none}
  #pj-filtros .tipo-seg button{flex:0 0 auto;white-space:nowrap}
}

/* ----- Los marcos empotrados: el Cotizador y la mesa de corte -----
   Un <iframe> no tiene alto propio: sin `height` se queda en los 150 px que manda la
   especificación, y con `height:100%` se queda en CERO porque su padre no tiene alto fijo.
   El alto lo escribe `medirMarco()` en `--pf-marco-h`, declarada en :root con un valor que
   sirve solo por si ese guion no llegara a correr.

   Y el `padding-bottom` de la caja es EL arreglo de este reacomodo, no un detalle: dentro de
   un iframe todas las `env(safe-area-inset-*)` valen 0, y el cotizador tiene TREINTA, con su
   barra fija de teléfono colgando de ellas. La compensación no puede ir dentro del documento
   hijo —ahí ya es 0—: la pone el PADRE, apartando la caja de la zona insegura. Así, dentro
   del marco no hay zona insegura que proteger y sus treinta declaraciones en 0 son
   correctas. Es la objeción que cotizador.html dejó escrita en su día, resuelta donde se
   podía resolver. */
.pf-marco-caja{padding-bottom:env(safe-area-inset-bottom,0px)}
.pf-marco{display:block;width:100%;height:var(--pf-marco-h);border:0;
  border-radius:var(--rr2);background:var(--card);box-shadow:var(--clay-in)}
/* Imprimir un marco no imprime nada útil: sale la caja vacía y el papel miente. Cada app
   empotrada tiene su propio Ctrl+P adentro. */
@media print{.pf-marco,.pf-marco-caja{display:none!important}}

/* ----- El mueble de la plataforma tampoco es texto que se edita -----
   La regla del sistema (css/sistema.css, «El texto de la interfaz no es texto que se
   edita») nombra encabezados, etiquetas y controles. Eso cubre al cotizador, que titula con
   <h2>. La plataforma NO: sus títulos de renglón los pinta el JS como `.pf-fila-t` —17
   sitios— y el resto del rótulo va en `.vacio-t`, `.mat-n`, `.dia-t`, `.cal-n` y los `<dt>`
   de `.pf-dato`. Ninguno es un encabezado, así que ninguno estaba cubierto: el título de
   «Silicón estructural está bajo mínimo» seguía dando `user-select:auto`, o sea que seguía
   sacando las manijas de selección y la barra de Cortar al mantenerlo pulsado. Justo donde
   se reportó.

   El reparto es el mismo de allá: el mueble no se selecciona, el DATO sí. Por eso los `<dd>`
   de `.pf-dato` —el id del dispositivo, un folio, un teléfono— quedan fuera de la lista y
   se pueden copiar; lo que no se selecciona es el `<dt>`, que es la etiqueta. */
.pf-fila-t,.pf-fila-d,.vacio-t,.vacio-d,.mat-n,.dia-t,.cal-n,.cal-dow,.cal-mes,
.pf-dato dt,.pf-cuenta,.pf-cuando,.pf-etapa,.pf-nota,.pf-frescura,.aj-nota,.tb-etapa em{
  -webkit-user-select:none;user-select:none;-webkit-touch-callout:none;
  -webkit-tap-highlight-color:transparent;
}
/* La escotilla, igual que en el cotizador: lo que lleve `.dato` vuelve a ser copiable. */
.pf-dato dd,.dato,.selec{-webkit-user-select:text;user-select:text;-webkit-touch-callout:default}

/* El bloque que escondía la puerta del anidador a 560 px vivía aquí, y se fue con ella. Su
   razón medida —a 390 px la barra se partía en tres renglones— se evaporó sola: el botón ya
   no existe, y con él y el del cotizador la barra RECUPERÓ 88 px. Su segunda razón, «en un
   teléfono no hay SVG que exportar ni láser que alimentar», cubría CALCULAR, no LEER: el de
   corte, parado en la máquina con el teléfono, quiere ver el acomodo y cuántas hojas salen.
   Su CSS ya estaba trabajado hasta 420 px; lo único escondido era la entrada. Ahora se ve, y
   arriba del marco se dice con palabras dónde se calcula. Explicar, no esconder en silencio. */

