/* LocalMX OS · el aspecto del backoffice
   ══════════════════════════════════════════════════════════════════════════════════════════
    VIVÍA DENTRO DE `index.html`, Y ESE ARCHIVO TENÍA 6118 LÍNEAS
   ══════════════════════════════════════════════════════════════════════════════════════════

   425 de ellas eran esto. Sale por tres razones, y ninguna es de gusto:

     · Quien viene a cambiar un color tenía que desplazarse por el marcado de nueve
       formularios para encontrarlo, y quien viene a tocar un formulario se topaba con 425
       líneas de CSS antes de llegar.
     · El navegador lo guarda en caché por su cuenta: hoy se vuelve a bajar entero cada vez
       que cambia una línea del script, que es todos los días.
     · Un archivo `.css` lo entiende cualquier herramienta. Dentro de un `<style>` en un HTML
       de seis mil líneas, no.

   Lo que NO cambia: sigue siendo el mismo CSS, en el mismo orden. El orden en una hoja de
   estilo es la cascada, y reordenar «para agrupar mejor» cambia qué regla gana. */

:root{
  --papel:#F5F6F1; --papel-2:#FFFFFF; --papel-3:#ECEEE6;
  --tinta:#16211C; --tinta-2:#3F4A44; --tinta-3:#6B756E;
  --linea:#D6DACF; --nopal:#1E7A4C; --nopal-suave:#E3F0E7;
  --alerta:#B23A20; --alerta-suave:#F6E4DE;
  --clave:#1D4E89; --clave-suave:#E1E9F3;
  --sombra:0 1px 2px rgba(22,33,28,.05), 0 8px 24px -16px rgba(22,33,28,.25);
  /* EL VELO DEL BORDE DE LO QUE SE DESLIZA. Tiene que ser un token y no un `rgba` negro
     escrito en la regla: sobre el tema oscuro, un negro al 26 % sobre un fondo casi negro no
     se ve — se pintó, se miró, y la sombra no estaba. En oscuro el velo es CLARO. */
  --velo:rgba(22,33,28,.34);
}
@media (prefers-color-scheme:dark){:root:not([data-theme=light]){
  --papel:#101815; --papel-2:#16211C; --papel-3:#1D2A24;
  --tinta:#EDF1EC; --tinta-2:#B3BEB7; --tinta-3:#87938B;
  --linea:#2A3831; --nopal:#57BE86; --nopal-suave:#173325;
  --alerta:#E4805F; --alerta-suave:#33201A;
  --clave:#7FAEE0; --clave-suave:#16283C;
  --sombra:0 1px 2px rgba(0,0,0,.3), 0 8px 24px -16px rgba(0,0,0,.7);
  --velo:rgba(237,241,236,.30);
}}
*{box-sizing:border-box}
body{margin:0;background:var(--papel);color:var(--tinta);
  font-family:"Source Serif 4",Georgia,serif;font-size:16px;line-height:1.55;-webkit-font-smoothing:antialiased}
h1,h2,h3,button,label,th,.eyebrow,.chip,.marca,nav a{font-family:Archivo,"Helvetica Neue",Arial,sans-serif}
[hidden]{display:none !important}

/* ── Entrada ─────────────────────────────────────── */
.portada{min-height:100vh;display:grid;place-items:center;padding:24px}
.tarjeta{width:100%;max-width:400px;background:var(--papel-2);border:1px solid var(--linea);
  border-radius:4px;padding:30px 28px;box-shadow:var(--sombra)}
.marca{font-size:24px;font-weight:800;letter-spacing:-.02em;margin:0}
.marca span{color:var(--nopal)}
.lema{color:var(--tinta-3);font-size:14px;margin:6px 0 24px}
label{display:block;font-size:12px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--tinta-3);margin:14px 0 6px}
input{width:100%;padding:11px 13px;font-size:15px;font-family:inherit;color:var(--tinta);
  background:var(--papel);border:1px solid var(--linea);border-radius:3px}
input:focus{outline:2px solid var(--nopal);outline-offset:1px;border-color:var(--nopal)}
/* ══ UNA CASILLA NO ES UN CAMPO DE TEXTO ═══════════════════════════════════
   La regla de arriba da `width:100%` y `padding:11px 13px` a TODO `input`, y eso tiene sentido
   para un campo de texto y ninguno para una casilla o un botón de radio: los estira al ancho de
   su contenedor y los infla con 26 px de relleno. Había un reset, pero sólo DENTRO de
   `.ficha-casillas` —`.ficha-casillas .casilla input{width:auto}`—, así que valía para el único
   sitio que usa ese contenedor y para ninguno de los otros cinco.

   Medido: en Marketing y en Turismo la etiqueta se salía de su caja por 7 px, **en los dos
   anchos** —no es cosa del teléfono—. Un componente que sólo funciona dentro de un padre
   concreto es un componente que se rompe la primera vez que alguien lo usa suelto, y aquí pasó
   cinco veces de seis.

   Va en la raíz y no en cada sitio: el defecto no era de Marketing ni de Turismo. */
input[type=checkbox],input[type=radio]{width:auto;min-width:0;padding:0;margin:0;
  flex:0 0 auto;border-radius:0}
/* ══ LA JERARQUÍA DE LOS BOTONES ═══════════════════════════════════════════
   TODOS eran iguales —fondo oscuro, relleno— y por eso un usuario nuevo no sabía cuál era la
   acción principal y cuál era una de apoyo. En una tabla con ocho renglones, ocho botones
   rellenos son un muro negro donde nada destaca: la vista no tiene dónde ir.

   Cuatro niveles, y cada uno dice algo distinto:
     · PRINCIPAL  relleno. UNO por pantalla o por formulario: el que hace avanzar.
     · SECUNDARIO contorno. Acciones de apoyo que no son el camino principal.
     · DISCRETO   solo texto con borde tenue. Lo de los renglones de una tabla, que se repite
                  ocho veces y no puede gritar ocho veces.
     · PELIGRO    borde rojo. Lo que quita algo: cancelar un apunte, apagar una pieza,
                  suspender a un negocio. Se distingue ANTES de tocarlo, no después. */
button{font-size:14px;font-weight:600;padding:11px 18px;border-radius:3px;cursor:pointer;
  background:var(--tinta);color:var(--papel);border:1px solid var(--tinta);
  font-family:Archivo,"Helvetica Neue",Arial,sans-serif;min-height:40px;
  transition:background .12s ease,border-color .12s ease}
button:hover{opacity:.9}
button:focus-visible{outline:3px solid var(--nopal);outline-offset:2px}
button[disabled]{opacity:.45;cursor:not-allowed}
@media (prefers-reduced-motion:reduce){button{transition:none}}

button.secundario{background:transparent;color:var(--tinta);border-color:var(--linea)}
button.secundario:hover{border-color:var(--tinta-2);background:var(--papel-3)}

/* ══ LLAMAR Y ESCRIBIR SON DOS BOTONES, NO UN NÚMERO Y UNA «wa» DE DOS LETRAS ══════════════
   Rodrigo, 13-oct-2026: «pon dos botones, uno para llamada y otro para WhatsApp».

   Y tenía razón: la columna pintaba el número como enlace `tel:` y, al lado, las letras «wa».
   En un teléfono eso son dos blancos de siete píxeles pegados, y quien quiere llamar acaba
   abriendo WhatsApp. Son dos acciones distintas —al socio se le LLAMA cuando urge y se le
   ESCRIBE cuando no—, así que se ven como dos cosas distintas y se pueden pulsar con el pulgar.

   Son `<a>` y no `<button>` a propósito: llevan a `tel:` y a `wa.me`, y un enlace se puede
   abrir en otra pestaña, copiar y compartir. La clase les da la pinta sin quitarles eso. */
/* ══ Y SON ICONOS, NO BOTONES CON TEXTO ═══════════════════════════════════════════════════
   Primera versión: dos botones que decían «Llamar» y «WhatsApp». Medían 190 px juntos, y en la
   tarjeta de un socio van además hasta tres redes — casi 400 px de controles en una pantalla de
   375. Rodrigo: «por el tamaño y la maquetación y first mobile deberían ser iconos».

   40×40 es el mínimo que se pulsa con el pulgar sin fallar. El dibujo va a 20 y el resto es
   aire — y ese aire ES el área que se toca, no un hueco de relleno. Cinco iconos caben en 220
   px, que es lo que deja una pantalla de teléfono con sus márgenes. */
.ico{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;
  border-radius:3px;text-decoration:none;color:var(--tinta-2);border:1px solid transparent;
  transition:color .12s ease,background .12s ease,border-color .12s ease}
.ico:hover{color:var(--tinta);background:var(--papel-3);border-color:var(--linea)}
.ico:focus-visible{outline:3px solid var(--nopal);outline-offset:2px}
/* Cada marca con su color al pasar por encima: es como se reconocen sin leer la etiqueta. */
.ico.wa:hover{color:#25D366}
.ico.facebook:hover{color:#1877F2}
.ico.instagram:hover{color:#E4405F}
.ico.tiktok:hover{color:var(--tinta)}
@media (prefers-reduced-motion:reduce){.ico{transition:none}}
/* En una celda estrecha se apilan en vez de salirse: la tabla de socios ya es ancha. */
.ligas-contacto{display:flex;flex-wrap:wrap;gap:2px;align-items:center}

/* Los de los renglones de una tabla. Pequeños, con borde, y con su color solo al pasar por
   encima: se ven como acciones sin competir con el contenido de la fila. */
.acciones button{background:transparent;color:var(--clave);border:1px solid var(--linea);
  padding:6px 11px;font-size:12.5px;min-height:34px}
.acciones button:hover{border-color:var(--clave);background:var(--clave-suave)}

/* Lo que QUITA algo se ve distinto antes de tocarlo. Un «Cancelar» idéntico a un «Ver» es un
   clic de más el día que alguien va deprisa. */
button.peligro,.acciones button.peligro{background:transparent;color:var(--malo);
  border-color:var(--malo)}
button.peligro:hover,.acciones button.peligro:hover{background:var(--malo);color:#fff}

button.ancho{width:100%;margin-top:22px}

/* UN ENLACE QUE ES LA ACCIÓN PRINCIPAL, y tiene que verse como un botón. Es un `<a>` y no un
   `<button>` porque abre WhatsApp en otra pestaña: `window.open()` después de un `await` lo
   come el bloqueador de ventanas SIN AVISAR, y un enlace que se ve y se pulsa no se puede
   bloquear en silencio. Que se vea igual que un botón no es cosmética — es lo que hace que
   alguien lo encuentre como el paso siguiente. */
/* EL CONTADOR DE AVISOS. Rojo solo si hay algo urgente: un contador que siempre grita deja
   de leerse, y entonces el día que sí importa tampoco se lee. */
#btnAvisos b{display:inline-block;margin-left:6px;padding:1px 7px;border-radius:9px;
  font-size:12px;background:var(--linea);color:var(--tinta)}
#btnAvisos.urge b{background:var(--malo);color:#fff}
.aviso-fila{border:1px solid var(--linea);border-left:3px solid var(--linea);border-radius:3px;
  padding:12px 14px;margin-bottom:9px;background:var(--papel-2)}
.aviso-fila.u1,.aviso-fila.u2{border-left-color:var(--malo)}
.aviso-fila.u3{border-left-color:var(--aviso,#8A5B00)}
.aviso-fila .num{font-family:Archivo,sans-serif;font-weight:700;font-size:20px}

/* En pantalla grande manda la etiqueta larga; el teléfono la cambia. Ver el bloque de 520px. */
.quien .largo{display:inline}
.quien .corto{display:none}

a.boton-a{display:inline-flex;align-items:center;justify-content:center;
  font-size:14px;font-weight:600;padding:11px 18px;border-radius:3px;min-height:40px;
  background:var(--tinta);color:var(--papel);border:1px solid var(--tinta);
  text-decoration:none;font-family:Archivo,"Helvetica Neue",Arial,sans-serif}
a.boton-a:hover{opacity:.9;color:var(--papel)}
a.boton-a:focus-visible{outline:3px solid var(--nopal);outline-offset:2px}

/* El mensaje tal como va a llegar al teléfono. Con el fondo de una nota y los renglones
   respetados: lo que se lee aquí es lo que va a leer la persona, y por eso no se reflowea. */
pre.previo{white-space:pre-wrap;font:14px/1.55 Archivo,"Helvetica Neue",Arial,sans-serif;
  background:var(--papel-3);border:1px solid var(--linea);border-left:3px solid var(--clave);
  border-radius:3px;padding:12px 14px;margin:0;max-height:38vh;overflow:auto}
/* Un ENLACE con aspecto de botón, no un botón que finge navegar: `otpauth://` lo tiene que
   abrir el sistema operativo del teléfono, y eso solo lo hace un <a href> de verdad. */
.boton-liga{display:block;text-align:center;text-decoration:none;font-size:14px;font-weight:600;
  padding:11px 18px;border-radius:3px;background:var(--tinta);color:var(--papel);
  border:1px solid var(--tinta)}
.boton-liga:focus-visible{outline:3px solid var(--nopal);outline-offset:2px}
.liga{background:none;border:0;color:var(--nopal);font-size:13px;padding:8px 0;cursor:pointer;
  font-family:Archivo,sans-serif;text-decoration:underline}
.recado{margin-top:16px;padding:11px 14px;border-radius:3px;font-size:14px;border-left:4px solid}
.recado.mal{background:var(--alerta-suave);border-color:var(--alerta)}
.recado.bien{background:var(--nopal-suave);border-color:var(--nopal)}
.recado.aviso{background:var(--clave-suave);border-color:var(--clave)}
.recado code{font-family:ui-monospace,monospace;font-size:15px;font-weight:600;letter-spacing:.06em}

/* ── Aplicación ──────────────────────────────────── */
.barra{display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;
  padding:12px 22px;background:var(--papel-2);border-bottom:2px solid var(--tinta)}
.barra .marca{font-size:18px}
/* La marca y el ☰, en el mismo renglón. En la computadora el ☰ está oculto y esto no es más
   que la marca; en el teléfono es lo que evita el tercer renglón de la cabecera. */
.cima{display:flex;align-items:center;gap:12px}
.quien{display:flex;align-items:center;gap:12px;font-size:13px;color:var(--tinta-2)}
.chip{font-size:10px;font-weight:600;letter-spacing:.09em;text-transform:uppercase;
  padding:3px 8px;border-radius:2px;background:var(--nopal-suave);color:var(--nopal)}
.chip.entorno{background:var(--clave-suave);color:var(--clave)}
main{max-width:1080px;margin:0 auto;padding:26px 22px 80px}
/* ══ EN PANTALLA ANCHA, QUE EL CONTENIDO LA USE · 8-oct-2026 ══════════════════════════════
   El tope de 1080 px dejaba el contenido en 774 px —el menú se lleva 232— aunque la pantalla
   tuviera 1440: media pantalla sin usar, y una tabla de once columnas cortada al lado del
   hueco. El tope no tenía una razón escrita; es una medida de comodidad de lectura, y en una
   pantalla de 1440 sigue habiendo comodidad con 1140.
   Sólo a partir de 1280 px, para no tocar las que ya están justas. El gate mide las 159
   pantallas en 1440, 1024 y 375, así que si esto rompiera alguna lo diría. */
@media (min-width: 1280px) { main{max-width:1420px} }

/* El menú está SIEMPRE a la vista: nada escondido en submenús. */
nav{display:flex;flex-wrap:wrap;gap:7px;margin-bottom:26px}
nav a{font-size:13px;font-weight:600;padding:8px 13px;border-radius:3px;text-decoration:none;
  color:var(--tinta-2);background:var(--papel-2);border:1px solid var(--linea);cursor:pointer}
nav a:hover{border-color:var(--nopal);color:var(--tinta)}
nav a.activo{background:var(--tinta);color:var(--papel);border-color:var(--tinta)}

h2{font-size:22px;font-weight:800;margin:0 0 4px;letter-spacing:-.015em}
.sub{color:var(--tinta-3);font-size:14px;margin:0 0 20px}

.rejilla{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:13px}
.modulo{background:var(--papel-2);border:1px solid var(--linea);border-radius:3px;padding:15px 17px}
.modulo.apagado{opacity:.55}
.modulo h3{font-size:15px;font-weight:600;margin:0 0 4px}
.modulo p{font-size:13.5px;color:var(--tinta-2);margin:0 0 10px}
.fila{display:flex;align-items:center;justify-content:space-between;gap:10px}
.nivel{font-size:10.5px;color:var(--tinta-3);font-family:Archivo,sans-serif;letter-spacing:.06em;text-transform:uppercase}

table{width:100%;border-collapse:collapse;font-size:14px;background:var(--papel-2)}
th,td{text-align:left;padding:9px 11px;border-bottom:1px solid var(--linea)}
th{font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--tinta-3);font-weight:600}
/* ══ UNA TABLA QUE SE DESLIZA TIENE QUE DECIRLO ════════════════════════════
   `overflow-x:auto` estaba bien puesto en las veinticinco tablas, y en un teléfono no basta:
   el navegador esconde la barra de desplazamiento hasta que alguien desliza, así que lo que
   queda a la derecha NO EXISTE para quien mira.

   Medido en el directorio a 390 px: la tabla sobra 522 px y las columnas «En la landing» y las
   acciones —«Publicar», «Ficha», «A revisión»— quedan enteras fuera de pantalla. Desde un
   teléfono, el directorio de afiliados se ve y no se puede operar.

   Las cuatro capas: las dos de `local` viajan CON el contenido y tapan a las de `scroll`, que
   están quietas. La sombra sale solo del lado por el que queda algo y desaparece sola al
   llegar al final — sin JavaScript y sin nada a lo que suscribirse. */
.tabla-caja{overflow-x:auto;border:1px solid var(--linea);border-radius:3px;
  background:
    linear-gradient(to right, var(--papel-2), transparent) left center / 30px 100% no-repeat local,
    linear-gradient(to left, var(--papel-2), transparent) right center / 30px 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%, var(--velo), transparent) left center / 16px 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, var(--velo), transparent) right center / 16px 100% no-repeat scroll,
    var(--papel-2)}
/* LA TABLA SE QUEDA TRANSPARENTE, y esto NO es un detalle: la sombra va en el fondo del
   contenedor, debajo del contenido. Con la tabla pintando su propio `--papel-2` encima, la
   sombra queda tapada y el arreglo no sirve de nada — se vería igual de bien que antes, que es
   la peor clase de arreglo. El color lo pone ahora el contenedor, en la última capa. */
.tabla-caja > table{background:transparent}

/* ══ CUANDO LA TABLA NO CABE · 8-oct-2026 ═════════════════════════════════════════════════
   Medido: en la lista de actividades, a 1440 px de pantalla la caja mide 772 y la tabla 1151
   — se cortan 379 px y dos columnas quedan enteras fuera. A 1024, tres.

   Tres cosas, y cada una arregla algo distinto:

   1 · LA PRIMERA COLUMNA SE QUEDA. Al desplazar en horizontal se perdía de vista el nombre de
       la tarea, así que las columnas de la derecha quedaban sin dueño: números sin saber de
       quién. Con la columna pegada, siempre se sabe de qué fila se está leyendo.
       Lleva su propio fondo porque si no, el contenido que pasa por debajo se transparenta.
   2 · EL BORDE DERECHO SE MARCA cuando hay más tabla, para que el corte se vea como un corte
       y no como el final.
   3 · Y el aviso con el número de columnas lo pinta `tabla.js`, MIDIENDO. Aquí sólo se le da
       forma: va en la barra de la tabla, al lado de cuántos renglones hay.

   Nada de esto aplica en el teléfono: ahí cada fila ya es una tarjeta y no hay nada que
   desplazar — ver el bloque de `@media` de más abajo, donde la tabla se vuelve bloques. */
@media (min-width: 768px) {
  .tabla-caja th:first-child,
  .tabla-caja td:first-child{position:sticky;left:0;z-index:2;background:var(--papel-2)}
  .tabla-caja.se-corta th:first-child,
  .tabla-caja.se-corta td:first-child{box-shadow:1px 0 0 var(--linea)}
}
/* ══ LA PROSA NO HACE TORRES · 9-oct-2026 ═══════════════════════════════════════════════
   Medido: la tabla de actividades daba renglones de 400 px porque dos columnas llevan prosa.
   Cuatro renglones es lo que deja ver de qué va una celda sin que el renglón se vuelva una
   columna; lo demás se abre con «ver todo», que `tabla.js` pone SÓLO donde de verdad sobra.
   En el teléfono no se recorta: ahí cada fila ya es una tarjeta y el espacio es vertical. */
/* Y NO SE RECORTA UNA COLUMNA DE NÚMEROS · 9-oct-2026 ══════════════════════════════════
   Esto decía `.tabla-caja td .celda` —todas— y lo cazó el gate a 1024 px: la caja de la celda
   numérica de Reparto medía 111 px dentro de una columna de 103, y a ese ancho no hay sitio
   donde meter la diferencia. Un número no tiene prosa que recortar, así que ahí la caja no
   aportaba nada y sólo le imponía su ancho mínimo a una columna estrecha.
   `td:not(.num)` ajusta la regla a lo que vino a resolver, en vez de taparlo con un ancho. */
/* ══ UNA COLUMNA DE PROSA NO SE DEJA ESTRANGULAR · 9-oct-2026 ═════════════════════════════
   Rodrigo mandó la captura: «Qué se le escribió» en 115 px con 400 caracteres dentro, una
   palabra por renglón. El barrido decía «159 de 159 se ven» y era cierto —la tabla no se salía
   de su caja—: lo que faltaba era medir si se PUEDE LEER. Ahora lo mide, y esto lo arregla.

   22 caracteres de ancho mínimo es el punto donde una frase deja de partirse cada dos palabras;
   60 de máximo es donde un renglón de texto se vuelve incómodo de seguir con la vista.

   Y SÍ, ESTO PUEDE EMPUJAR LA TABLA A LO ANCHO. Es a propósito: `.tabla-caja` ya desplaza y
   avisa de cuántas columnas quedan a la derecha. Una tabla ancha que se lee desplazándola es
   utilizable; una tabla angosta con una cinta vertical dentro no lo es por mucho que quepa. */
@media (min-width: 768px) {
  .tabla-caja th.prosa,.tabla-caja td.prosa{min-width:22ch;max-width:60ch}
}
@media (min-width: 768px) {
  .tabla-caja td:not(.num) .celda{display:-webkit-box;-webkit-box-orient:vertical;
    -webkit-line-clamp:4;overflow:hidden}
  .tabla-caja td:not(.num) .celda.abierta{-webkit-line-clamp:unset;overflow:visible}
  .tabla-caja td .ver-todo{font-size:11.5px;margin-top:2px;display:inline-block}
}
/* ══ EL AVISO NO EXISTE EN EL TELÉFONO · 9-oct-2026 ═══════════════════════════════════════
   Lo cazó el gate: ocho pantallas desbordando su caja entre 2 y 17 px a 375 px de ancho. La
   causa era este mismo aviso: `white-space:nowrap` sobre «→ 5 columnas más a la derecha» empuja
   la barra de la tabla más allá del borde, y ahí no hay desplazamiento que lo salve.
   Y sobre todo: en el teléfono NO HAY NADA QUE DESPLAZAR — cada fila es una tarjeta, no una
   fila. Un aviso que ofrece desplazar lo que no se desplaza es peor que no tenerlo. */
/* ══ ARRASTRAR EN EL TABLERO · 9-oct-2026 ═══════════════════════════════════════════════
   Dos señales y nada más: la que se lleva se aclara, y la columna que recibe se marca. Sin la
   segunda, soltar es a ciegas — no se sabe si va a caer donde uno cree. */
article[data-act][draggable]{cursor:grab}
article[data-act].arrastrando{opacity:.45;cursor:grabbing}
[data-suelta].recibiendo{outline:2px dashed var(--clave);outline-offset:4px;border-radius:6px}
.tabla-corte{font-size:12.5px;font-weight:600;white-space:nowrap}
@media (max-width: 767px) {
  .tabla-corte{display:none}
  /* ══ Y LA CAJA DE LA CELDA DESAPARECE DEL MAQUETADO · 9-oct-2026 ═══════════════════════════
     La caja se añadió para poder recortar la prosa, y sólo recorta de 768 px para arriba. En el
     teléfono no sirve de nada y además ESTORBA: se metió entre `td.acciones` —que es
     `display:flex` con `flex-wrap:wrap`— y sus botones, así que los botones dejaron de ser
     hijos del flex y dejaron de bajar de renglón. Ocho pantallas desbordaban su caja entre 2 y
     17 px, y lo cazó el gate midiendo geometría, no mirando.
     `display:contents` hace que el div no genere caja: el maquetado queda EXACTAMENTE como
     antes de que existiera. */
  .tabla-caja td .celda{display:contents}
  /* ══ PERO SÓLO DONDE HAY BOTONES · 2-nov-2026 ═══════════════════════════════════════════
     Fuera de `td.acciones`, `contents` suelta cada pieza de la celda como hija del flex de la
     ficha (`td[data-col]`, etiqueta al lado del dato). Una celda con «nombre<br>etiqueta» —el
     patrón de afiliados, bitácora, correo, documental, sistema, protocolos y las cuentas de
     repartidores— ponía el nombre y la etiqueta LADO A LADO y el nombre se partía a media
     palabra: «Beto Vencid / o», medido a 375 px. El `<br>` dentro de un flex no baja de
     renglón. El barrido no lo veía porque nada se sale de su caja: se lee mal, no desborda.
     En las demás celdas, la caja es UN bloque junto a su etiqueta, y dentro el texto fluye.
     Las numéricas se quedan como estaban: un importe es una sola pieza, y como bloque se iba
     alineado a la orilla derecha, lejos de su etiqueta (medido en «Saldo» y «Vencido»). */
  .tabla-caja td[data-col]:not(.acciones):not(.num) .celda{display:block;flex:1 1 auto;min-width:0}
  /* ══ Y LAS NUMÉRICAS TAMBIÉN, PERO SIN ESTIRARSE · 2-nov-2026 ═════════════════════════════
     Dejarlas fuera era a medias: «Precio» y «Costo» de paquetes y «Papeles» de repartidores son
     numéricas con «dato<br>nota», y seguían con el `<br>` sin bajar —lo cazó `brQueNoBaja` en el
     armado completo de 2c9b9ed, 322 de 324—. Como bloque que NO crece (`flex:0 1 auto`) la caja
     mide lo que su contenido: queda pegada a su etiqueta, como un importe suelto, y el `<br>`
     baja dentro. Alineada a la izquierda para que la nota no cuelgue de la orilla derecha. */
  .tabla-caja td[data-col].num:not(.acciones) .celda{display:block;flex:0 1 auto;min-width:0;text-align:left}
}
.tabla-corte[hidden]{display:none}

/* ══ LA PUESTA EN MARCHA ═══════════════════════════════════════════════════════════════
   Va arriba de la ficha, con un borde de color a la izquierda: es lo primero que se pregunta
   al abrir un afiliado y tiene que distinguirse de las seis secciones que vienen debajo.
   Cuando no falta nada cambia a verde — un bloque de aviso permanente deja de avisar. */
.puesta{border:1px solid var(--linea);border-left:4px solid var(--clave);border-radius:4px;
  padding:14px 16px;margin:18px 0}
.puesta.lista{border-left-color:var(--nopal);background:var(--nopal-suave)}
/* Ahora es un `<summary>`: se le quita el triángulo del navegador —diminuto y distinto en
   cada uno— y se le pone uno propio, igual que en `.plegable`. */
.puesta-cima{display:flex;align-items:baseline;justify-content:space-between;gap:12px;
  cursor:pointer;list-style:none;min-height:44px;user-select:none}
.puesta-cima::-webkit-details-marker{display:none}
.puesta-cima>span:first-child::before{content:"";display:inline-block;width:0;height:0;
  margin-right:9px;border-left:6px solid var(--tinta-3);border-top:5px solid transparent;
  border-bottom:5px solid transparent;transition:transform .15s ease}
.puesta[open] .puesta-cima>span:first-child::before{transform:rotate(90deg)}
@media (prefers-reduced-motion:reduce){.puesta-cima>span:first-child::before{transition:none}}
.puesta-cima h4{margin:0;font-family:Archivo,"Helvetica Neue",Arial,sans-serif;font-size:14px}
.puesta-cuenta{font-family:Archivo,"Helvetica Neue",Arial,sans-serif;font-size:13px;
  font-weight:600;color:var(--tinta-2);white-space:nowrap}
/* La barra es un dibujo, no un control: `role="img"` con su etiqueta en palabras, porque un
   porcentaje de ancho no existe para quien usa lector de pantalla. */
.puesta-barra{height:6px;border-radius:3px;background:var(--papel-3);margin:8px 0 10px;
  overflow:hidden}
.puesta-barra span{display:block;height:100%;background:var(--clave);
  transition:width .25s ease}
.puesta.lista .puesta-barra span{background:var(--nopal)}
.puesta-sigue{margin:0 0 12px;font-size:13px;line-height:1.5}
.puesta-sigue.bien{color:var(--nopal)}
.puesta-grupo{margin-top:12px}
.puesta-titulo{display:block;font-family:Archivo,"Helvetica Neue",Arial,sans-serif;font-size:11px;
  letter-spacing:.08em;text-transform:uppercase;color:var(--tinta-3);margin-bottom:4px}
/* Cuántos faltan en el grupo, como pastilla. `.cuenta` sólo tenía estilo dentro de
   `.submodulos`, así que aquí salía un número suelto pegado al título. */
.puesta-titulo .cuenta{display:inline-block;margin-left:5px;padding:1px 7px;border-radius:9px;
  font-size:10.5px;font-weight:700;letter-spacing:0;background:var(--papel-3);color:var(--tinta-2)}
.puesta-titulo .cuenta.urge{background:var(--clave-suave);color:var(--clave)}
/* Cada paso es una fila de tres: marca, texto, acción. Con `grid` y no con `flex` para que la
   columna del botón mida lo mismo en todos y las etiquetas no bailen de renglón a renglón. */
.puesta-paso{display:grid;grid-template-columns:22px minmax(0,1fr) auto;gap:8px;
  align-items:start;padding:7px 0;border-top:1px solid var(--linea)}
.puesta-marca{font-size:14px;line-height:1.5;color:var(--nopal)}
.puesta-paso.falta .puesta-marca{color:var(--tinta-3)}
.puesta-nombre{display:block;font-size:13.5px;line-height:1.4}
/* LO QUE FALTA PESA MÁS QUE LO HECHO, al revés de lo que pide el instinto: lo hecho ya no hay
   que mirarlo. Lo pendiente va en negrita y lo hecho se atenúa, sin llegar a esconderse —que
   se pueda repasar lo hecho es la mitad de para qué sirve la lista. */
.puesta-paso.falta .puesta-nombre{font-weight:600}
.puesta-paso.hecho .puesta-nombre{color:var(--tinta-2)}
/* `.nivel` es la etiqueta de una cifra —«ABIERTOS AHORA»— y por eso va en versalitas. Aquí
   dentro son FRASES: «sin contrato firmado no hay nada que cobrar ni nada que exigir». En
   mayúsculas una frase de dos renglones no se lee, se descifra. */
.puesta-paso .nivel{display:block;font-size:11.5px;line-height:1.45;margin-top:3px;
  text-transform:none;letter-spacing:0;font-family:"Source Serif 4",Georgia,serif;
  color:var(--tinta-3)}
.puesta-sigue .nivel{display:inline;text-transform:none;letter-spacing:0;
  font-family:"Source Serif 4",Georgia,serif;font-size:12.5px}
.puesta-donde{color:var(--tinta-3);font-style:italic}
/* EL COMENTARIO DE QUIEN FUE. En cursiva y entre comillas porque es la VOZ de una persona —«el
   dueño no estaba, firmó su hijo»—, no un campo del sistema: así se distingue de un vistazo de
   la evidencia, que es el dato duro del renglón de arriba. */
.puesta-comentario{display:block;font-size:11.5px;line-height:1.45;margin-top:3px;
  font-family:"Source Serif 4",Georgia,serif;font-style:italic;color:var(--tinta-2)}
.puesta-accion{min-width:92px;text-align:right}
.puesta-accion button{padding:5px 11px;font-size:12px;min-height:32px}
.puesta-nota{margin:12px 0 0;font-size:11px;line-height:1.5}

/* El avance en la tabla del directorio: la barra y el número juntos. La barra sola no dice
   cuántos faltan; el número solo no se compara de un vistazo entre doce filas. */
.avance{display:inline-flex;align-items:center;gap:7px;white-space:nowrap}
.avance-barra{display:inline-block;width:54px;height:5px;border-radius:3px;
  background:var(--papel-3);overflow:hidden}
.avance-barra span{display:block;height:100%;background:var(--clave)}
.avance.lista .avance-barra span{background:var(--nopal)}
.avance-num{font-family:Archivo,"Helvetica Neue",Arial,sans-serif;font-size:11.5px;
  font-weight:600;color:var(--tinta-2)}
.avance.lista .avance-num{color:var(--nopal)}

/* ══ CÓMO VA HOY ═══════════════════════════════════════════════════════════════════════
   Las cifras son CONTEXTO y van en una tira chica arriba; lo que ocupa la pantalla son los
   atascos. Al revés —cifras grandes y la acción abajo— sale un tablero que se mira dos días
   y se deja de mirar, porque no pide nada. */
.tira{display:flex;flex-wrap:wrap;gap:10px;margin:16px 0 4px}
/* ══ EL CONTENEDOR QUE `.cifra-tira` LLEVABA ESPERANDO ═════════════════════════════════════
   `.cifra-tira` es `flex:1 1 118px` —quiere un padre flexible— y tres pantallas lo metían
   dentro de `<div class="cifras">`: el tablero, el material de marketing y, desde hoy, «Quién
   vuelve». Esa clase NO EXISTÍA en esta hoja, así que el div era un bloque corriente y cada
   indicador ocupaba un renglón entero: cuatro cifras que caben en una fila se comían media
   pantalla. Se vio en la primera captura de «Quién vuelve», y al buscarla aquí resultó que el
   tablero llevaba igual desde que se escribió.

   Se arregla en la clase y no en cada pantalla, que es donde estaba el agujero. */
.cifras{display:flex;flex-wrap:wrap;gap:8px}
.cifra-tira{flex:1 1 118px;min-width:108px;border:1px solid var(--linea);border-radius:3px;
  padding:8px 11px;background:var(--papel-2)}
.cifra-num{display:block;font-family:Archivo,"Helvetica Neue",Arial,sans-serif;font-size:19px;
  font-weight:700;line-height:1.2}
.cifra-que{display:block;font-size:11px;color:var(--tinta-3);margin-top:2px;line-height:1.35}

/* Cada atasco trae qué pasa, por qué importa, qué hacer y dónde. El borde dice cuánto corre
   prisa; el color solo no basta, así que la urgencia también está en el orden. */
.atasco{border:1px solid var(--linea);border-left:4px solid var(--linea);border-radius:3px;
  padding:11px 14px;margin-bottom:9px;background:var(--papel-2)}
.atasco.u1{border-left-color:var(--alerta)}
.atasco.u2{border-left-color:var(--clave)}
.atasco.u3{border-left-color:var(--linea)}
.atasco-que{display:flex;flex-wrap:wrap;align-items:baseline;gap:10px}
.atasco-que strong{font-size:14.5px}
.atasco-que .nivel{text-transform:none;letter-spacing:0;font-size:12px}
.atasco-porque{margin:5px 0 0;font-size:12.5px;line-height:1.5;color:var(--tinta-2)}
.atasco-haz{margin:6px 0 0;font-size:13px}
.atasco-haz .nivel{display:inline;text-transform:none;letter-spacing:0;font-size:11.5px}
@media (max-width:520px){
  /* En el teléfono el botón baja: tres columnas en 343 px dejan el nombre del paso partido en
     cuatro renglones, y es el nombre lo que se viene a leer. */
  .puesta-paso{grid-template-columns:22px minmax(0,1fr)}
  .puesta-accion{grid-column:2;text-align:left;margin-top:6px}
  .puesta-accion button{width:auto;min-height:38px}
}
.acciones{display:flex;gap:6px;flex-wrap:wrap}
.acciones button{padding:5px 10px;font-size:12px}
.forma{background:var(--papel-2);border:1px solid var(--linea);border-radius:3px;padding:18px 20px;margin-bottom:20px}
.forma .campos{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:12px}
.vacio{color:var(--tinta-3);font-size:14px;padding:18px;text-align:center}

/* ── SUBMÓDULOS: la jerarquía DENTRO de un módulo ───────────────────────
   Un módulo con seis pantallas amontonadas en una sola no tiene jerarquía: todo pesa igual y
   nada se encuentra. Estas pestañas son el segundo nivel, y cada una lleva su dirección en el
   hash (`#/caja/arqueo`), así que se puede pegar en un mensaje y «atrás» regresa a la
   anterior. En móvil se desplazan en horizontal en vez de apilarse en seis renglones. */
/* ══ LA BARRA DE PESTAÑAS SE DESLIZA, Y HAY QUE PODER SABERLO ══════════════
   Se desliza en horizontal con la barra de desplazamiento ESCONDIDA. En un escritorio da
   igual: caben todas. En un teléfono de 390 px, «Marketing» enseña dos pestañas y las otras
   dos quedan fuera sin ninguna señal — para quien mira, ese módulo tiene dos secciones y las
   otras dos no existen. Medido: «Campaña Usuarios» empieza en el píxel 326 y «Campaña
   Repartidores» en el 474, con la ventana en 390.

   La sombra usa las cuatro capas del truco clásico: las dos de `local` viajan CON el contenido
   y tapan a las de `scroll`, que están quietas. Así la sombra solo se ve del lado por el que
   queda algo, y desaparece sola al llegar al final. Sin una línea de JavaScript y sin un
   `resize` al que suscribirse. */
.submodulos{display:flex;gap:2px;margin:0 0 20px;border-bottom:1px solid var(--linea);
  overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;
  background:
    linear-gradient(to right, var(--papel), transparent) left center / 26px 100% no-repeat local,
    linear-gradient(to left, var(--papel), transparent) right center / 26px 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%, var(--velo), transparent) left center / 14px 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, var(--velo), transparent) right center / 14px 100% no-repeat scroll}
.submodulos::-webkit-scrollbar{display:none}
.submodulos button{background:none;border:none;border-bottom:2px solid transparent;
  border-radius:0;color:var(--tinta-3);font-size:13.5px;font-weight:600;padding:10px 14px;
  white-space:nowrap;min-height:44px}
.submodulos button:hover{color:var(--tinta-2)}
.submodulos button[aria-current=page]{color:var(--clave);border-bottom-color:var(--clave)}
/* La cuenta pegada al nombre: cuántos hay que atender. Cero no se pinta — un contador en cero
   es ruido que enseña a no mirar los contadores. */
.submodulos .cuenta{display:inline-block;margin-left:6px;padding:1px 6px;border-radius:9px;
  background:var(--linea);color:var(--tinta-2);font-size:11px;font-weight:600}
.submodulos .cuenta.urge{background:var(--malo);color:#fff}

/* Las cifras grandes de un tablero. `.cifra.mal` se usa para un faltante: el color es el
   mismo `--malo` de todo el sistema, no un rojo inventado aquí. */
.cifra{font-size:26px;font-weight:600;margin:2px 0 0;font-variant-numeric:tabular-nums}
.cifra.bien{color:var(--bueno)} .cifra.mal{color:var(--malo)}
.modulo.destaca{border-left:4px solid var(--clave)}
td.num,th.num{text-align:right;font-variant-numeric:tabular-nums}



/* ══ DÓNDE ESTÁS ═══════════════════════════════════════════════════════════
   El menú marcaba el módulo abierto y nada más. Dentro de Caja hay cuatro secciones y dentro
   de Publicidad cuatro espacios: se entra a «Cerrar el día» y el menú sigue diciendo «Caja y
   conciliación» a secas, así que no se sabe en qué pantalla se está ni cómo se llegó.

   La miga vive FUERA de `#vista` a propósito: cada pantalla reemplaza `#vista` entero, y una
   miga dentro se borraría en cada repintado — que es justo cuando más falta hace. */
/* DÓNDE VA, lo dice la rejilla de `main` con áreas nombradas. Aquí NO: un `grid-column:2`
   suelto coloca este elemento y deja a los demás autocolocándose, que es exactamente el
   defecto que tuvo esta pantalla. */
.miga{display:flex;flex-wrap:wrap;align-items:center;gap:6px;
  padding:14px 28px 0;font-family:Archivo,"Helvetica Neue",Arial,sans-serif;font-size:12.5px;
  color:var(--tinta-3)}
.miga span,.miga button{font-size:12.5px}
.miga .sep{opacity:.5}
.miga .aqui{color:var(--tinta);font-weight:600}
/* El grupo y el módulo son botones porque LLEVAN a algún sitio: volver al módulo desde una
   de sus secciones es el camino que más se usa, y un texto muerto no lo permite. */
.miga button{background:none;border:none;padding:2px 4px;min-height:auto;color:var(--tinta-3);
  font-weight:600;border-radius:3px;cursor:pointer}
.miga button:hover{color:var(--clave);background:var(--clave-suave)}
.miga button:focus-visible{outline:2px solid var(--clave);outline-offset:1px}
@media (max-width:860px){.miga{padding:12px 18px 0}}

/* ── LA PANTALLA DEL SITIO PÚBLICO ──────────────────────────────────────
   Se dibuja sola del catálogo, así que el estilo tiene que servir para CUALQUIER campo que
   alguien agregue mañana: uno de una línea, un párrafo o una lista de doce renglones. */
.campo-sitio{margin:0 0 18px;padding:0 0 16px;border-bottom:1px solid var(--linea)}
.campo-sitio:last-child{border-bottom:none;padding-bottom:0;margin-bottom:0}
.campo-sitio label{display:block;font-weight:600;font-size:13.5px;margin:0 0 6px}
.campo-sitio input,.campo-sitio textarea{width:100%}
/* El «por qué se pide» va DEBAJO del campo y no encima: quien ya sabe qué escribir no lo
   lee, y quien no, lo encuentra justo donde se detuvo. */
.ayuda{font-size:12.5px;color:var(--tinta-3);margin:6px 0 0;max-width:78ch;line-height:1.5}
.ayuda code{background:var(--papel);padding:1px 4px;border-radius:2px}
.barra-publicar{display:flex;flex-wrap:wrap;gap:12px;align-items:center;
  justify-content:space-between;background:var(--papel-2);border:1px solid var(--linea);
  border-left:4px solid var(--clave);border-radius:3px;padding:14px 16px;margin-bottom:18px}
.barra-publicar a{text-decoration:none}
.lista-falta{margin:8px 0 0;padding-left:18px;font-size:13.5px;line-height:1.6}
.lista-falta li{margin-bottom:4px}
.sel,select{width:100%;padding:11px 13px;font-size:15px;font-family:inherit;border:1px solid var(--linea);
  border-radius:3px;background:var(--papel);color:var(--tinta)}
textarea:focus,select:focus{outline:2px solid var(--nopal);outline-offset:1px}
/* Los diálogos propios. Heredan el papel y la tinta del sistema: un diálogo del navegador
   con tipografía ajena rompe la pantalla justo cuando pide una decisión. */
.dialogo{border:1px solid var(--linea);border-radius:10px;background:var(--papel-2);
  color:var(--tinta);padding:0;max-width:420px;width:calc(100% - 32px);
  box-shadow:0 18px 50px rgba(0,0,0,.35)}
.dialogo::backdrop{background:rgba(10,12,10,.55)}
.dialogo form{padding:20px}
.dialogo h3{margin:0 0 8px;font-size:16px}
.dialogo p{margin:0 0 14px;font-size:13px;color:var(--tinta-2)}
.dialogo input{width:100%}
.dialogo-pie{display:flex;gap:8px;justify-content:flex-end;margin-top:16px}

/* ── EL VISOR: LA FOTO COMPLETA, NO LA MINIATURA ──────────────────────────
   Rodrigo: «antes se podía ver la foto completa al dar clic y ahora no se puede».

   El diálogo de la casa mide 420 px, que es lo que necesita una pregunta y lo que ARRUINA una
   foto: una pieza de 1080 × 1080 dentro de 420 px de ancho se ve más pequeña que en la propia
   reja de miniaturas, y entonces abrirla no sirve de nada. 900 px es el ancho en el que una
   pieza de redes se lee —el texto de dentro se puede revisar— sin llenar la pantalla.

   El pie NO se desplaza con la imagen: la imagen tiene su tope en `vh` y el pie se queda
   debajo, visible. Sin eso, en una pieza vertical hay que desplazarse dentro del diálogo para
   leer de quién es, y nadie lo hace. */
.dialogo.visor{max-width:900px}
.dialogo.visor form{padding:16px 18px}
/* La imagen del visor manda sobre la regla de la teja: aquí NO se recorta, se contiene. */
.dialogo.visor img{max-width:100%}
.dialogo.visor .dialogo-pie{flex-wrap:wrap;justify-content:space-between}
@media (max-width:700px){
  /* En el teléfono el tope de alto baja: con los botones en dos renglones, 68vh de imagen más
     el pie no cabe y el botón de cerrar queda fuera de la pantalla. */
  .dialogo.visor img{max-height:52vh}
  .dialogo.visor .dialogo-pie{justify-content:stretch}
  .dialogo.visor .dialogo-pie button,.dialogo.visor .dialogo-pie a.boton-a{flex:1 1 auto}
}

/* ══════════════════════════════════════════════════════════════════════════
   LA FICHA LARGA: TREINTA CAMPOS QUE SÍ SE LLENAN
   ══════════════════════════════════════════════════════════════════════════
   Un diálogo de 420 px con treinta campos en una columna es una tira de dos pantallas y media
   que nadie termina. Éste es más ancho, los campos van en rejilla —dos o tres por renglón en
   cuanto hay sitio— y van AGRUPADOS con su título: «quién es», «cómo se le llega», «dónde
   está». El grupo es lo que deja saber cuánto queda, y sin eso se abandona a la mitad.

   El alto se limita al 85% de la pantalla y el contenido rueda dentro, con el pie fuera del
   desplazamiento: si el botón de guardar rodara con los campos, habría que recorrer treinta
   casillas para llegar a él cada vez. */
.dialogo-ancho{max-width:860px;padding:20px;display:flex;flex-direction:column;
  max-height:85vh}
.dialogo-ancho>h3,.dialogo-ancho>p,.dialogo-ancho>.recado{flex:none}
.dialogo-ancho>#fichaPros{overflow-y:auto;flex:1;min-height:0;margin:4px -4px 0;padding:0 4px}
.dialogo-ancho .dialogo-pie{flex:none;border-top:1px solid var(--linea);padding-top:14px}

.ficha-grupo{border:1px solid var(--linea);border-radius:8px;padding:12px 14px 14px;
  margin:0 0 14px;background:var(--papel)}
.ficha-grupo>legend{font-family:Archivo,sans-serif;font-size:11px;font-weight:700;
  letter-spacing:.1em;text-transform:uppercase;color:var(--tinta-2);padding:0 6px}
.ficha-grupo .campos{display:grid;gap:12px;
  grid-template-columns:repeat(auto-fit,minmax(210px,1fr))}
.ficha-grupo .campo-ancho{grid-column:1/-1}
.ficha-grupo label{display:block;font-size:12px;margin-bottom:4px;color:var(--tinta-2)}
.ficha-grupo input,.ficha-grupo select,.ficha-grupo textarea{width:100%}
.ficha-ayuda{font-size:11px;margin:5px 0 0;color:var(--tinta-3);line-height:1.4}
/* EL OBLIGATORIO SE MARCA CON UN PUNTO Y SU TÍTULO, no con un asterisco rojo. Un asterisco rojo
   en un formulario de treinta campos con uno solo obligatorio lee como un error. */
.ficha-obliga{color:var(--clave);font-weight:700}
.ficha-casillas{border:0;padding:0;margin:0;display:flex;flex-wrap:wrap;gap:6px 14px}
.ficha-casillas>legend{font-size:12px;color:var(--tinta-2);padding:0;margin-bottom:6px}
/* `.casilla` SE VALE SOLA. Estaba escrita como descendiente de `.ficha-casillas` y de seis usos
   sólo uno vive ahí: los otros cinco —Marketing, Turismo y tres de Gente— no recibían ni una de
   estas propiedades. El tamaño de letra sí se queda atado a la ficha, que es donde hace falta
   más chico; lo demás es del componente. */
.casilla{display:inline-flex;align-items:center;gap:6px;color:var(--tinta);margin:0}
.ficha-casillas .casilla{font-size:12.5px}

/* ══════════════════════════════════════════════════════════════════════════
   LOS ADJUNTOS DEL EXPEDIENTE, UNO POR RENGLÓN
   ══════════════════════════════════════════════════════════════════════════
   Eran cuatro botones en fila y ahora son ocho papeles, cada uno con lo que se puede hacer con
   él —que no es lo mismo para todos—. En fila no se lee cuál botón va con cuál papel; por
   renglón sí, y cabe la razón por la que se pide cada uno. */
.adjuntos{display:flex;flex-direction:column;gap:2px}
.adjunto{display:flex;gap:12px;align-items:center;flex-wrap:wrap;
  padding:9px 0;border-bottom:1px solid var(--linea)}
.adjunto:last-child{border-bottom:0}
.adjunto-que{flex:1;min-width:190px;display:flex;flex-direction:column;gap:2px}
.adjunto-que b{font-size:13px;font-weight:600}
.adjunto-que .chip{align-self:flex-start}
.adjunto-que .nivel{font-size:11px;line-height:1.35}
.adjunto-como{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.adjunto-como .subir{margin:0}

/* ══════════════════════════════════════════════════════════════════════════
   LOS COLORES QUE FALTABAN, Y LOS QUE NO PASABAN
   ══════════════════════════════════════════════════════════════════════════
   `var(--malo, #c96a5e)` y `var(--aviso, #d9a441)` se usaban SIN estar definidos en
   `:root`: siempre caía el respaldo, y el respaldo da 3.68:1 y 2.25:1 sobre blanco — los dos
   por debajo del 4.5:1 de AA. La alerta de «precio alterado fuera del sistema» y el aviso
   del catálogo eran el texto MENOS legible de la pantalla, justo por ser alertas.
   `--tinta-3` sobre `--papel` daba 4.40:1 y es el color de todos los subtítulos. */
:root{
  --tinta-3:#5F6A63;          /* 5.29:1 sobre --papel · antes #6B756E daba 4.40:1 */
  --malo:#A33A2B;             /* 6.03:1 sobre blanco */
  --aviso:#8A5B00;            /* 5.61:1 sobre blanco · el #d9a441 daba 2.25:1 */
  /* `--bueno` FALTABA y se estaba por usar en la cifra de un arqueo que cuadra. Sin definir,
     `var(--bueno)` no cae en un respaldo: cae en la nada, el navegador descarta la regla y el
     texto hereda el color del padre. Habría quedado negro sobre papel —legible, sí, pero sin
     decir «cuadra»— y nadie lo habría notado nunca. Es el mismo defecto de arriba. */
  --bueno:#186B44;            /* 5.42:1 sobre blanco */
}
@media (prefers-color-scheme:dark){:root:not([data-theme=light]){
  --tinta-3:#929E96; --malo:#E98A78; --aviso:#E0B155; --bueno:#63C08D;
}}

/* ══ LA PANTALLA OCUPADA ═══════════════════════════════════════════════════
   Mientras una petición que ESCRIBE está en vuelo, los botones no aceptan otro toque y se
   ve una barra arriba. Sin esto el doble toque en «Pagar» de nómina paga dos veces — y en
   3G sin señal de vida, tocar dos veces es lo razonable, no un descuido. */
body[data-ocupado="1"] button:not(.liga):not([data-siempre]){
  pointer-events:none;opacity:.55;cursor:progress}
body[data-ocupado="1"]::before{
  content:"";position:fixed;top:0;left:0;right:0;height:3px;z-index:99;
  background:linear-gradient(90deg,transparent,var(--nopal),transparent);
  background-size:40% 100%;background-repeat:no-repeat;
  animation:vuela 1.1s linear infinite}
@keyframes vuela{from{background-position:-40% 0}to{background-position:140% 0}}
@media (prefers-reduced-motion:reduce){
  body[data-ocupado="1"]::before{animation:none;background:var(--nopal);opacity:.5}}

/* ══ LEGIBILIDAD ═══════════════════════════════════════════════════════════
   La capa de datos vivía entre 10 y 12 px: los encabezados de las 25 tablas a 10.5px en
   mayúsculas, los estados a 10px, el texto de los 28 requisitos a 12px. A pleno sol de
   sierra, con el teléfono en una mano, eso no se lee. Los mínimos suben a 13px. */
.chip{font-size:12px}
.nivel{font-size:12px}
th{font-size:12px;letter-spacing:.05em}
td{font-size:15px}

/* ══ IOS HACE ZOOM CON MENOS DE 16px, Y NO LO DESHACE ══════════════════════
   Safari en iPhone amplía la página cuando el campo enfocado mide menos de 16px, y al salir
   NO vuelve. La ejecutiva tocaba «Nombre del negocio», la página saltaba a 1.3×, y capturaba
   los otros diecinueve campos desplazando de lado. Los campos de evidencia estaban a 12px. */
input,select,textarea,.sel{font-size:16px !important}

/* ══ OBJETIVOS DE TOQUE ════════════════════════════════════════════════════
   Los botones de las tablas medían 31px de alto con 6px de separación, y «Borrar» estaba
   pegado a «Agotado», «Dar de baja» pegado a «Ficha». Un dedo en movimiento sobre objetivos
   de 31px separados por 6px borra un producto sin querer. */
.acciones{display:flex;flex-wrap:wrap;gap:10px}
.acciones button{min-height:44px;font-size:14px;padding:10px 14px}

/* ══ UNA CELDA NO PUEDE SER UNA CAJA FLEXIBLE ══════════════════════════════
   `.acciones` es la misma clase en dos sitios: 24 veces sobre un `<td>` y 6 sobre un `<div>`.
   Sobre el `<div>` está bien. Sobre el `<td>`, `display:flex` lo SACA DEL MODELO DE TABLA: deja
   de ser una celda, el navegador inventa una celda anónima para meterlo, y la columna se
   descuelga — los separadores entre filas terminan antes de llegar a ella y los botones quedan
   flotando fuera del marco de la tabla. Se ve exactamente como lo que es: algo roto.

   La celda vuelve a ser celda y sus hijos se alinean en línea. `white-space:nowrap` hace el
   trabajo que hacía `flex-wrap:nowrap`, y encima lo hace en la celda de verdad. */
td.acciones{display:table-cell;white-space:nowrap;vertical-align:middle}
td.acciones>*{display:inline-flex;align-items:center;vertical-align:middle}
td.acciones>*+*{margin-left:10px}
/* ══ PERO EN EL TELÉFONO, CUATRO BOTONES NO CABEN EN UNA LÍNEA ════════════════════════════
   `white-space:nowrap` es lo correcto mientras los botones quepan. Medido a 375 px con datos
   de verdad: la celda de acciones de Reparto —«Escribirle · Qué le falta · Corregir · Borrar»—
   mide 324 px dentro de una celda de 311, y la de Publicidad 326. El último botón queda
   cortado y **sin forma de alcanzarlo**: a ese ancho ya no hay desplazamiento horizontal.

   No se vio nunca porque sin repartidores ni piezas sembrados esas tablas no pintaban una sola
   celda de acciones. El defecto llevaba ahí desde que se escribió la regla.

   En estrecho los botones se parten en dos líneas. No se toca el modelo de tabla —ésa fue la
   lección de la regla de arriba—: sólo se deja de prohibir el salto, y como los hijos ya son
   `inline-flex`, saltan solos. */
@media (max-width: 560px) {
  td.acciones{white-space:normal}
  td.acciones>*{margin-top:6px;margin-bottom:6px}
  td.acciones>*+*{margin-left:6px}
}

/* ══ Y CON RATÓN NO HACE FALTA TANTO ═══════════════════════════════════════
   La regla de arriba es para dedos, y es correcta ahí. Con un ratón cobra un precio que
   nadie pidió: medido en el directorio, dos botones —«Ficha» y «Mandar a revisión»— no
   caben en los 232 px de su celda, se apilan uno encima del otro, y CADA FILA MIDE 118 px.
   Dos negocios llenan la pantalla; con doce hay que desplazarse para ver el directorio de un
   municipio de diez.

   `pointer:fine` pregunta por el dispositivo que de verdad hay delante, no por el ancho de la
   ventana: una tableta con lápiz no es un escritorio, y una ventana angosta en una Mac sigue
   teniendo ratón. Es la pregunta correcta para una regla que existe por el tamaño del dedo. */
/* LLEVA TAMBIÉN EL ANCHO, Y NO ES REDUNDANCIA. `pointer:fine` es la pregunta correcta, pero no
   se puede comprobar: Chrome sin cabeza contesta `fine` aunque se le emule un teléfono y se le
   fuerce el medio, así que la rama táctil no se puede medir aquí — y una regla de accesibilidad
   que no se puede verificar es una regla que un día está mal sin que nadie lo sepa.

   Con `min-width:901px` la condición se vuelve comprobable: por debajo de eso mandan los 44 px
   pase lo que pase, y eso sí se mide. Si el navegador miente sobre el puntero, el error cae
   del lado seguro — botones grandes de más, nunca de menos. */
@media (pointer:fine) and (min-width:901px){
  /* `nowrap` Y NO UN ANCHO MÍNIMO A OJO. Medido: los dos botones piden 143.1 px y la columna
     les daba 141. Dos píxeles. Con `wrap`, la disposición automática de la tabla calcula el
     ancho mínimo de la celda como el del botón MÁS ANCHO —porque partir es legal— y luego
     parte; el resultado es una fila del doble de alto por dos píxeles que nadie ve.

     Con `nowrap`, ese mínimo pasa a ser la SUMA, y la tabla reparte el ancho sabiendo lo que
     de verdad hace falta. Y si un día no cupiera, `.tabla-caja` ya desplaza en horizontal:
     una tabla que se desliza se entiende; una fila que se parte en dos parece rota. */
  .acciones{gap:6px}
  td.acciones>*+*{margin-left:6px}
  .acciones button{min-height:32px;font-size:12.5px;padding:6px 11px;white-space:nowrap}
}
/* Y lo que destruye se separa de lo que no, además de llevar su color. */
.acciones button[data-borrapr],.acciones button[data-off],
.acciones button[data-q2fa],.acciones button[data-hacia="baja"]{
  margin-left:auto;border-color:var(--malo);color:var(--malo)}

/* ══ LAS TABLAS NO DESBORDAN: SE ESTRANGULAN ═══════════════════════════════
   El envoltorio con `overflow-x:auto` estaba bien puesto en las 25 tablas, pero
   `table{width:100%}` sin `min-width` hace que la tabla obedezca el 100% y comprima las
   columnas en vez de desplazarse: seis columnas en 331px útiles son 50px cada una, y un
   correo se parte en fideos de cuatro caracteres. */
.tabla-caja table{min-width:620px}

/* ══ EL MENÚ SE COMÍA LA PRIMERA PANTALLA ══════════════════════════════════
   Quince módulos a 13px con `flex-wrap` envuelven a siete renglones: ~240px de menú antes de
   cualquier contenido, en cada pantalla. En móvil pasa a una tira que se desplaza de lado:
   sigue estando todo a la vista, en un renglón. */
nav a{min-height:44px;display:flex;align-items:center}
nav a:focus-visible{outline:3px solid var(--nopal);outline-offset:2px}

@media (max-width:820px){
  main{padding:20px 16px 60px}
  nav{flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;
    scroll-snap-type:x proximity;padding-bottom:6px;margin:0 -16px;padding-left:16px;padding-right:16px}
  nav a{flex:0 0 auto;scroll-snap-align:start}
  .barra{flex-wrap:wrap;gap:10px}
  .quien{font-size:13px;gap:8px}
  /* El cuerpo sube a 16px: es el que se lee de pie y con el sol de frente. */
  body{font-size:16px}
  .campos{grid-template-columns:1fr}
  .doble{grid-template-columns:1fr}
  h2{font-size:22px}
  .forma{padding:16px}
  /* Los formularios largos necesitan que el botón de guardar se vea sin buscarlo. */
  .forma button[type=submit],.forma>button{width:100%;min-height:48px}
}

@media (max-width:520px){
  .acciones{flex-direction:column;align-items:stretch}
  .acciones button{width:100%}
  .rejilla{grid-template-columns:1fr}

  /* ══ LA CABECERA EN EL TELÉFONO ════════════════════════════════════════
     «Rodrigo Martínez · Super administrador» partía en cuatro renglones y empujaba los
     botones fuera de la pantalla: para cerrar sesión había que desplazarse.

     El NOMBRE se queda —es lo que confirma con qué cuenta estás, y en un sistema donde una
     cuenta mueve dinero eso no es decoración— y el ROL se esconde: se puede consultar en su
     pantalla, y en un teléfono ocupa el sitio de los dos botones que sí se usan.

     Y DOS RENGLONES, NO TRES. `.quien` ocupa el ancho entero, así que el ☰ —que venía detrás—
     se caía a un tercero él solo: 50 px de una pantalla de 812, en todas las pantallas del
     sistema y para siempre. Agrupado con la marca, la cabecera pasa de 156 px a 118.

     En la tableta el cambio CUESTA 12 px —el renglón de la marca pasa a medir lo que mide el
     botón, 44— y se acepta a sabiendas: sigue en dos renglones, y lo que se usa en Agua Blanca
     es el teléfono y la computadora de la oficina, donde no cambia nada. */
  .quien{width:100%;justify-content:space-between;gap:6px;flex-wrap:nowrap}
  #quienSoy{flex:1 1 auto;min-width:0;white-space:nowrap;overflow:hidden;
    text-overflow:ellipsis;font-size:12.5px}
  #quienSoy .rol{display:none}
  .quien button{flex:0 0 auto;padding:8px 10px;font-size:12.5px;min-height:38px}
  /* «Mi segundo factor» son tres palabras donde caben dos botones: en el teléfono se abrevia.
     Con DOS `<span>` y `display:none`, no con `font-size:0` y un `::after`: lo segundo deja el
     texto largo en el árbol de accesibilidad y un lector de pantalla acaba leyendo las dos
     etiquetas seguidas —«Mi segundo factor 2.º factor»—. `display:none` saca la que sobra. */
  .quien .largo{display:none}
  .quien .corto{display:inline}
}

/* ══ LA ALARMA NO PUEDE SER EL TEXTO MÁS TENUE ═════════════════════════════
   `.modulo.apagado{opacity:.55}` significa «apagado» en todo el sistema, y se reutilizaba
   para señalar ALARMA en el inventario en negativo: el texto bajaba a 2.82:1 y la
   advertencia se volvía ilegible justo por ser advertencia. */
.modulo.alarma{opacity:1;border-color:var(--malo);border-left-width:4px;
  background:var(--alerta-suave,var(--papel-2))}
.modulo.alarma .nivel{color:var(--malo);opacity:1}

/* El módulo abierto se marca con algo más que el color invertido. */
nav a.activo::after{content:"";display:block;position:absolute;left:12px;right:12px;bottom:0;
  height:3px;background:var(--nopal);border-radius:2px}
nav a{position:relative}

/* Línea de lectura en escritorio: 120-140 caracteres por renglón en serif es demasiado
   para los párrafos de política que hay que leer con cuidado. */
.sub,.forma p,.modulo p{max-width:72ch}

/* ── Subir archivos ───────────────────────────────────────────────────── */
.subir{display:inline-flex;flex-direction:column;gap:2px;cursor:pointer;
  border:1px dashed var(--linea);border-radius:4px;padding:12px 16px;min-height:44px;
  justify-content:center;background:var(--papel);font-family:Archivo,sans-serif}
.subir:hover{border-color:var(--nopal);border-style:solid}
.subir span:first-of-type{font-size:14px;font-weight:600;color:var(--nopal)}
.subir .lim{font-size:11px;color:var(--tinta-3);font-weight:400}
.miniatura{width:52px;height:52px;object-fit:cover;border-radius:4px;border:1px solid var(--linea)}
.sin-r2{background:var(--clave-suave);border-left:4px solid var(--clave);
  padding:12px 15px;border-radius:4px;font-size:13px;margin:10px 0}

/* ── Lo que se abre solo cuando hace falta ────────────────────────────────
   Una ficha se abre veinte veces para consultar y una para corregir. Treinta campos siempre
   desplegados empujan media pantalla hacia abajo todo lo que sí se viene a ver.

   El triángulo por omisión del navegador es diminuto y distinto en cada uno. Se apaga con
   `::-webkit-details-marker` y `list-style` —hacen falta los dos: uno es de Safari y el otro
   del resto— y se dibuja uno propio que gire al abrir. */
.plegable{border:1px solid var(--linea);border-radius:5px;background:var(--papel-2);
  margin:16px 0;overflow:hidden}
/* ══ EL RESUMEN SE PARTE EN DOS RENGLONES ANTES QUE RECORTAR UN NOMBRE ═════
   Es una fila `flex` con el nombre de la cosa a la izquierda y su contador a la derecha, y el
   contador va `nowrap` a propósito —«3 suyas · 12 sin la suya» partido por la mitad no se lee—.
   En un teléfono eso deja al nombre con lo que sobre: medido en Imágenes del menú, el nombre
   del negocio pedía 79 px y tenía 54. El resto queda FUERA, sin puntos suspensivos y sin
   desplazamiento — simplemente cortado, y quien lo mire no sabe de qué negocio es el renglón.

   `flex-wrap` deja que el contador baje a su propia línea cuando no cabe, en vez de comerse el
   nombre. Cuesta un renglón de alto y salva el único dato que identifica la fila. */
.plegable>summary{cursor:pointer;padding:14px 16px;font-family:Archivo,sans-serif;
  font-weight:600;font-size:14px;display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  list-style:none;min-height:44px;user-select:none}
.plegable>summary::-webkit-details-marker{display:none}
.plegable>summary::before{content:"";width:0;height:0;flex:0 0 auto;
  border-left:6px solid var(--tinta-3);border-top:5px solid transparent;
  border-bottom:5px solid transparent;transition:transform .15s ease}
.plegable[open]>summary::before{transform:rotate(90deg)}
.plegable>summary:hover{background:var(--papel-3)}
.plegable[open]>summary{border-bottom:1px solid var(--linea)}
.plegable>div{padding:0 16px 16px}
/* Dentro del pliegue la forma ya tiene el marco del pliegue: dos bordes concéntricos a 1 px
   se leen como un error de dibujo. */
.plegable>div>.forma{border:0;padding:0;background:transparent}
@media (prefers-reduced-motion:reduce){.plegable>summary::before{transition:none}}

/* ── La galería de imágenes de un negocio ─────────────────────────────────
   UNA IMAGEN SE MIRA, NO SE LEE EN UNA COLUMNA. Los archivos se enseñaban en una tabla con
   una miniatura de 52 px en la primera celda: para saber si el gráfico de un negocio era el
   bueno había que abrirlo en otra pestaña. La reja enseña la imagen a tamaño de reconocerla.

   `auto-fill` con `minmax` y no un número de columnas: son tres en un escritorio, dos en una
   tableta y una en un teléfono, sin una consulta de medios por cada corte. */
.galeria{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));
  gap:12px;margin:12px 0 0}
.teja{margin:0;display:flex;flex-direction:column;background:var(--papel);
  border:1px solid var(--linea);border-radius:5px;overflow:hidden}
/* La imagen manda su proporción a un alto fijo y se recorta centrada: sin esto, un gráfico
   de 1080×1920 al lado de uno cuadrado desalinea toda la fila y la reja se ve rota. */
.teja img{width:100%;height:132px;object-fit:cover;display:block;background:var(--papel-3)}
.teja-doc{display:flex;align-items:center;justify-content:center;height:132px;
  background:var(--papel-3);color:var(--tinta-3);font-family:Archivo,sans-serif;
  font-size:13px;letter-spacing:.08em}
.teja figcaption{display:flex;flex-direction:column;gap:2px;padding:9px 10px 8px;
  border-top:1px solid var(--linea)}
.teja figcaption b{font-size:13px;line-height:1.3;overflow-wrap:anywhere}
.teja figcaption .nivel{font-size:11px}
.teja-pie{display:flex;gap:5px;padding:0 10px 10px;flex-wrap:wrap}
.teja-pie button{font-size:11px;padding:5px 8px}

/* ── Los huecos: lo que le falta a este negocio ───────────────────────────
   UN HUECO ES UN BOTÓN. Enseñar «falta el logo» sin nada que pulsar obliga a subir a buscar
   el formulario, elegir el negocio otra vez y elegir el destino otra vez — tres pasos para
   hacer lo que el aviso acaba de decir. Aquí el aviso ES el primer paso. */
.huecos{display:flex;gap:7px;flex-wrap:wrap;margin-top:11px}
.hueco{background:transparent;color:var(--tinta-2);border:1px dashed var(--linea);
  border-radius:4px;padding:7px 11px;font-size:12px;font-family:Archivo,sans-serif;
  cursor:pointer}
.hueco:hover{border-style:solid;border-color:var(--nopal);color:var(--nopal)}

/* ══════════════════════════════════════════════════════════════════════════
   EL MENÚ: CINCO GRUPOS, Y UN CAJÓN EN EL TELÉFONO
   ══════════════════════════════════════════════════════════════════════════
   Quince fichas planas del mismo peso no tienen jerarquía: el ojo no encuentra dónde
   apoyarse y la pantalla se ve suelta. Y en un teléfono ocupaban la primera pantalla
   entera — antes de cualquier contenido, en cada módulo. */
.grupo{display:flex;flex-direction:column;gap:2px;margin-bottom:18px}
.grupo-nombre{font-family:Archivo,sans-serif;font-size:11px;font-weight:700;
  letter-spacing:.12em;text-transform:uppercase;color:var(--tinta-3);
  padding:0 10px 6px;border-bottom:1px solid var(--linea);margin-bottom:6px}
/* ══ DIECINUEVE CAJAS NO SON UNA JERARQUÍA ═════════════════════════════════
   Cada módulo se dibujaba como una tarjeta con su borde, su fondo y su esquina redonda. Con
   diecinueve, el resultado es el que ya estaba escrito arriba de este archivo para otra cosa:
   diecinueve elementos del mismo peso, sin nada donde apoyar el ojo. Y medido, el menú
   entero mide 1104 px contra una pantalla de 1000: la barra de navegación no cabe en la
   pantalla, así que la página se desplaza para poder ver el menú.

   Los grupos ya dan la jerarquía —los pinta `.grupo-nombre` con su línea—. El borde por
   ítem la borra en vez de añadirla. Se quita, se apoya el ojo en el hueco y se reserva el
   fondo para lo que de verdad significa algo: dónde estoy y dónde está el puntero.

   `min-height` baja de 42 a 34: sigue siendo cómodo con ratón, y en táctil la media query de
   abajo lo devuelve a 48, que es donde importa. 19×34 + los cinco grupos caben. */
#menu a{display:flex;align-items:center;min-height:34px;padding:6px 10px;border-radius:5px;
  font-size:14px;font-weight:600;color:var(--tinta-2);text-decoration:none;cursor:pointer;
  border:1px solid transparent;background:transparent}
#menu a:hover{background:var(--papel-3);color:var(--tinta)}
/* El activo es lo ÚNICO con color de fondo en toda la columna: así se encuentra sin leer. */
#menu a.activo{background:var(--nopal-suave);color:var(--nopal);border-color:var(--nopal)}
#menu a.activo::after{display:none}
#menu a:focus-visible{outline:3px solid var(--nopal);outline-offset:-2px}

.abre-menu{display:none;background:none;border:1px solid var(--linea);border-radius:8px;
  width:44px;height:44px;font-size:20px;line-height:1;color:var(--tinta);cursor:pointer}
.tapa-menu{display:none}

/* ══ LA REJILLA DICE DÓNDE VA CADA HIJO, POR SU NOMBRE ══════════════════════════════
   ══════════════════════════════════════════════════════════════════════════════════
    EL DEFECTO QUE ESTO ARREGLA: EL CONTENIDO DEBAJO DEL MENÚ
   ══════════════════════════════════════════════════════════════════════════════════

   Esto era `grid-template-columns:232px 1fr` y nada más, con DOS hijos —el menú y la vista—.
   El día que la miga se metió dentro de `<main>` pasaron a ser TRES, y la colocación
   automática hizo lo que tenía que hacer:

     fila 1 · columna 1 → el menú      fila 1 · columna 2 → la miga
     fila 2 · columna 1 → LA VISTA     fila 2 · columna 2 → vacío

   Es decir: la pantalla entera, en la columna de 232 px, empezando 1 120 px más abajo, tapada
   por el menú. En un monitor de 900 px de alto eso se ve como **una pantalla en blanco**, y
   así estuvo: la miga arriba a la derecha diciendo dónde estás, y debajo nada.

   No reventaba. No salía en la consola. El texto estaba todo en `#vista` —430 caracteres en
   Prospección— y por eso mi propio barrido de las 34 pantallas lo dio por bueno: medía
   `innerText.length`, que dice que el texto EXISTE, no que se VEA. Lo cazó Rodrigo mirando.

   La cura no es volver a poner un `grid-column` suelto —eso fue el primer parche, y colocó la
   miga dejando a la vista autocolocándose—: es que la rejilla diga dónde va CADA hijo, por su
   nombre. Un hijo nuevo sin área declarada ya no puede empujar a otro fuera de su sitio, y el
   candado del gate comprueba que ninguno se quede sin nombrar. */
@media (min-width:901px){
  /* `minmax(0,1fr)` Y NO `1fr` A SECAS. `1fr` es `minmax(auto,1fr)`, y ese `auto` es el ancho
     MÍNIMO del contenido: en cuanto la vista trae una tabla ancha, la columna se estira hasta
     lo que mida la tabla y la página entera se sale de ancho —se comprobó a 901 px: la miga
     llegaba a 906—. Con `minmax(0,…)` la columna puede ser más estrecha que su contenido, y lo
     que no cabe se desplaza DENTRO de `.tabla-caja`, que ya tiene su `overflow-x`.
     Antes no pasaba porque la vista estaba en la columna FIJA de 232 px, que es el defecto. */
  main{display:grid;grid-template-columns:232px minmax(0, 1fr);
    /* LA FILA `aviso` EXISTE AUNQUE NO HAYA AVISO, y mide cero: una fila `auto` vacía no ocupa
       nada. Está declarada porque el contenido del sistema a veces tiene algo que decir ANTES
       de la pantalla —«faltan módulos por sembrar»— y ese algo necesita un sitio propio. */
    grid-template-areas:"menu aviso"
                        "menu miga"
                        "menu vista";
    /* `auto auto 1fr` Y NO todo automático: el menú abarca las tres filas y mide casi mil
       píxeles; con filas automáticas el sobrante se reparte entre ellas y las de arriba crecen,
       dejando un hueco entre la miga y el contenido. Con `1fr` al final, las de arriba miden lo
       que mide su contenido y la de la vista se queda con todo lo demás. */
    grid-template-rows:auto auto 1fr;
    /* 0 entre filas: la miga ya trae su propio espacio abajo, y 30 aquí lo duplicaban. */
    gap:0 30px;align-items:start}
  #menu{grid-area:menu;position:sticky;top:20px;flex-direction:column}
  #miga{grid-area:miga}
  #vista{grid-area:vista}
  #avisoSistema{grid-area:aviso}

  /* ══════════════════════════════════════════════════════════════════════════════════════
      Y CUALQUIER HIJO QUE APAREZCA MAÑANA CAE EN LA COLUMNA DE LA DERECHA
     ══════════════════════════════════════════════════════════════════════════════════════

     Esto ya mordió DOS VECES, y la segunda fui yo.

     La primera: `main` tenía dos hijos y dos columnas. El día que la miga se metió dentro
     pasaron a ser tres, el tercero se auto-colocó en la primera celda libre —la del menú, fila
     dos— y el contenido quedó DEBAJO del menú, 232 px de ancho y fuera de la primera pantalla.
     Dieciséis pantallas en blanco que costaron tres reportes.

     La segunda: se añadió el aviso de «faltan módulos por sembrar» con un cuarto hijo. Sin
     área, se auto-colocó exactamente igual — encima del menú, ilegible, las dos cosas pisadas.
     Mismo defecto, misma rejilla, mismo mes.

     Una rejilla de áreas nombradas se rompe cada vez que alguien añade un hijo, y quien lo
     añade no está leyendo este archivo. Así que en vez de confiar en que la próxima persona se
     acuerde, se declara la regla: lo que no tenga área va a la columna 2, con el contenido.
     Se verá en el sitio equivocado dentro de la columna buena; nunca encima del menú. */
  main > *:not(#menu):not(#miga):not(#vista):not(#avisoSistema){grid-column:2}
}

@media (max-width:900px){
  .abre-menu{display:flex;align-items:center;justify-content:center}
  /* DONDE HAY ☰, VA AL BORDE DERECHO. Es donde está el botón del menú en cualquier
     aplicación, y buscarlo en medio de la cabecera es una duda que no hace falta tener. */
  .cima{width:100%;justify-content:space-between}
  #menu{position:fixed;top:0;left:0;bottom:0;width:270px;z-index:40;overflow-y:auto;
    background:var(--papel-2);border-right:1px solid var(--linea);padding:20px 14px;
    transform:translateX(-100%);transition:transform .18s ease;flex-direction:column}
  #app[data-menu="1"] #menu{transform:none}
  .tapa-menu{display:block;position:fixed;inset:0;z-index:39;border:0;padding:0;
    background:rgba(0,0,0,.45);opacity:0;pointer-events:none;transition:opacity .18s ease}
  #app[data-menu="1"] .tapa-menu{opacity:1;pointer-events:auto}
  #menu a{min-height:48px;font-size:15px}
  .grupo{margin-bottom:22px}
}
@media (prefers-reduced-motion:reduce){#menu,.tapa-menu{transition:none}}

/* ── Las cifras de un bloque del tablero ──────────────────────────────────
   Tres números en una tarjeta, en fila y con su etiqueta debajo. `auto-fit` y no tres
   columnas fijas: hay bloques de un número y bloques de tres, y una rejilla de tres deja
   dos huecos en los de uno. */
.cifras-fila{display:grid;grid-template-columns:repeat(auto-fit,minmax(80px,1fr));
  gap:10px;margin-top:8px}
.cifras-fila .cifra{margin:0;font-size:26px;line-height:1.1}
.cifras-fila .nivel{font-size:11px}

/* ══════════════════════════════════════════════════════════════════════════
    EN UN TELÉFONO, UNA TABLA DE SEIS COLUMNAS DEJA DE SER UNA TABLA
   ══════════════════════════════════════════════════════════════════════════

   Medido en el directorio a 390 px: la tabla sobra 522 px, y lo que queda fuera no es un
   dato de adorno — son «Publicar», «Ficha» y «A revisión». Desde un teléfono se veían tres
   negocios y no se podía hacer nada con ninguno.

   La sombra de deslizamiento (arriba) avisa de que hay más, y avisar no es suficiente cuando
   lo que está escondido es TODO lo que se puede hacer. Seis columnas no caben en 390 px por
   mucho que se anuncie que están ahí.

   Así que por debajo de 700 px cada renglón se convierte en una FICHA: los datos uno debajo
   de otro, con el nombre de su columna al lado —de ahí `data-col`, porque la cabecera
   desaparece y «oro» a secas no significa nada— y las acciones al final, dentro de la
   pantalla. Es el mismo HTML: no hay una segunda tabla que mantener.

   700 y no 520: a 600 px la tabla del directorio ya no cabía, y esperar al tamaño de un
   teléfono dejaba rotas las tabletas en vertical. */
@media (max-width:700px){
  .tabla-caja{overflow-x:visible;background:var(--papel-2)}
  .tabla-caja table,.tabla-caja tbody,.tabla-caja tr,.tabla-caja td{display:block;width:auto}
  .tabla-caja table{min-width:0}
  /* La cabecera se va: sus nombres los lleva ahora cada celda. */
  .tabla-caja thead{display:none}
  .tabla-caja tr{padding:14px 15px;border-bottom:1px solid var(--linea)}
  .tabla-caja tr:last-child{border-bottom:0}
  /* ══ NADA SE SALE DE LA PANTALLA POR UNA CADENA LARGA ═══════════════════════════════════
     Medido a 375 px: la bitácora sobresalía **108 px** del ancho del teléfono y el marco
     documental 5 px. La causa no era la tabla sino su CONTENIDO: un correo, una huella SHA o
     un identificador no tienen espacios, así que no hay dónde partirlos y empujan el bloque
     entero más allá del borde. Media columna queda fuera, sin forma de alcanzarla — aquí ya no
     hay desplazamiento horizontal, porque a este ancho la tabla es una ficha apilada.

     Y no lo cazaba nada: el barrido miraba si se desbordaba el BODY, y un hijo que se sale de
     SU caja no mueve el body ni un píxel. Lo encontré midiendo `scrollWidth` contra
     `clientWidth` elemento por elemento.

     `anywhere` y no `break-word`: con una huella de 64 caracteres hexadecimales, `break-word`
     sólo parte si la palabra no cabe NI en una línea entera, y en una celda de ficha a veces
     cabe por poco y se sale igual. */
  .tabla-caja td,.tabla-caja th{overflow-wrap:anywhere}
  .tabla-caja td{padding:4px 0;border:0}
  /* Una celda vacía en una tabla es una columna sin dato; apilada es un renglón en blanco. */
  .tabla-caja td:empty{display:none}
  /* El nombre de la columna, delante del dato y en pequeño. La primera celda no lo lleva:
     es el nombre del negocio, y no necesita que le digan que es el nombre. */
  /* LA ETIQUETA AL LADO DEL DATO, no encima. Encima son dos renglones por campo y la ficha de
     cada negocio medía 428 px: un directorio de diez se vuelve cuatro pantallas. Al lado se
     lee como una lista de «campo: valor», que además es más fácil de recorrer con la vista
     porque los valores quedan alineados en una columna. */
  .tabla-caja td[data-col]{display:flex;gap:10px;align-items:baseline}
  .tabla-caja td[data-col]::before{content:attr(data-col);flex:0 0 92px;
    font-family:Archivo,sans-serif;font-size:11px;font-weight:700;letter-spacing:.06em;
    text-transform:uppercase;color:var(--tinta-3);line-height:1.6}
  /* Las acciones, en fila y dentro de la pantalla: es a lo que se vino. */
  /* `flex:0 0 auto` y `width:auto` EXPLÍCITOS. Medido: cada botón salía de 326 px —el ancho
     entero de la celda— y los tres quedaban uno debajo de otro, con la ficha de cada negocio
     en 432 px de alto. Un botón por renglón convierte un directorio de diez negocios en
     cuatro pantallas de desplazamiento. */
  /* `flex-direction:row` EXPLÍCITO, porque hay una regla a 520 px que pone `.acciones` en
     columna y a lo ancho. Tenía sentido cuando la tabla se deslizaba: apilar los botones era
     la única forma de alcanzarlos. Ahora el renglón ES una ficha, caben en fila, y apilarlos
     sumaba 60 px por botón — medido, la ficha pasaba de 367 a 428 px solo por eso.
     No se toca aquella regla: los seis `.acciones` que NO son celdas siguen necesitándola. */
  .tabla-caja td.acciones{display:flex;flex-direction:row;flex-wrap:wrap;gap:8px;margin-top:6px;
    white-space:normal;align-items:center}
  .tabla-caja td.acciones button,.tabla-caja td.acciones a.boton-a{width:auto}
  .tabla-caja td.acciones[data-col]::before{flex:0 0 100%;margin-bottom:0}
  .tabla-caja td.acciones>*{margin-left:0;flex:0 0 auto;width:auto}
}

/* ══ EL SEMÁFORO ═══════════════════════════════════════════════════════════
   Lo dibuja `publico/app/motores/semaforo.js` y lo usan dos pantallas: «Mi día» —compacto, solo
   lo que no está bien— y «Quién está abierto», donde cada fila abre el horario de ese negocio.

   ERA UNA TABLA DE CINCO COLUMNAS con cuatro tarjetas de cifras encima. Contestaba «¿a qué hora
   abre?»; la pregunta de las dos de la tarde es «¿quién está vendiendo AHORA y quién no», y esa
   se contesta de un vistazo o no se contesta.

   EL COLOR NO VA SOLO: cada fila lleva su palabra («abierto», «sin horario») y su posición en la
   lista, que está ordenada por urgencia. Uno de cada doce hombres no distingue rojo de verde; un
   estado dicho solo con color no está dicho. El color acelera, no sustituye. */
.sem-cima{display:flex;flex-wrap:wrap;gap:6px 16px;align-items:baseline;
  justify-content:space-between;margin:0 0 6px}
.sem-reloj{font-family:Archivo,sans-serif;font-size:15px;font-weight:700;color:var(--tinta)}
.sem-reloj .nivel{margin-left:6px;font-weight:400}
.sem-cuentas{font-size:13px;color:var(--tinta-2)}
.sem-n{font-family:Archivo,sans-serif;font-variant-numeric:tabular-nums}
.sem-n.sem-abierto{color:var(--bueno)}
.sem-n.sem-por-cerrar{color:var(--aviso)}
.sem-n.sem-sin-horario{color:var(--malo)}
.sem-dice{margin:0 0 12px}
.sem-bien{margin:10px 0 0;padding:12px 14px;border-radius:10px;
  background:var(--nopal-suave);color:var(--tinta);font-size:13.5px}

.sem-lista{display:flex;flex-direction:column;border:1px solid var(--linea);border-radius:12px;
  overflow:hidden;background:var(--papel-2)}

/* LA FILA ENTERA ES EL BLANCO cuando se puede tocar. Antes la acción vivía en un botón
   «Horario» de ochenta píxeles al final de la fila: el blanco más pequeño de la pantalla para
   la única cosa que se hace aquí. Como es un `<button>`, hay que deshacer lo que el estilo de
   botón del sistema le pone — y el `text-align:left` es lo primero, o el nombre sale centrado. */
.sem-fila{display:grid;align-items:baseline;gap:2px 12px;width:100%;
  grid-template-columns:10px minmax(0,1fr) auto;
  grid-template-areas:"luz nombre estado" ".  porque porque" ".  dias dias";
  padding:11px 14px;margin:0;border:0;border-top:1px solid var(--linea);border-radius:0;
  background:none;box-shadow:none;font:inherit;color:var(--tinta);text-align:left;
  min-height:0;letter-spacing:normal;text-transform:none}
.sem-lista>.sem-fila:first-child{border-top:0}
button.sem-fila{cursor:pointer}
button.sem-fila:hover{background:var(--papel-3)}
button.sem-fila:focus-visible{outline:2px solid var(--clave);outline-offset:-2px}

/* LA LUZ. Un círculo de diez píxeles alineado con la primera línea del nombre — no con el centro
   de la fila, que se mueve según cuánto texto traiga el «por qué». */
.sem-luz{grid-area:luz;width:10px;height:10px;border-radius:50%;background:var(--tinta-3);
  position:relative;top:-1px}
.sem-nombre{grid-area:nombre;font-family:Archivo,sans-serif;font-size:14.5px;font-weight:600;
  overflow-wrap:anywhere}
.sem-nombre .nivel{margin-left:6px;font-weight:400}
.sem-estado{grid-area:estado;justify-self:end;font-family:Archivo,sans-serif;font-size:11px;
  font-weight:700;letter-spacing:.06em;text-transform:uppercase;white-space:nowrap}
.sem-porque{grid-area:porque;font-size:12.5px;color:var(--tinta-2);line-height:1.5}
.sem-porque:empty{display:none}
/* Los días que abre, con cifras de ancho fijo para que las columnas se lean en vertical. */
.sem-dias{grid-area:dias;font-size:11.5px;color:var(--tinta-3);letter-spacing:.04em}

/* LOS CUATRO ESTADOS. El borde izquierdo repite lo que dice la luz: en una lista larga el borde
   se sigue con la vista de arriba abajo y los puntos sueltos no. */
.sem-abierto .sem-luz{background:var(--bueno)}
.sem-abierto .sem-estado{color:var(--bueno)}
.sem-por-cerrar .sem-luz{background:var(--aviso)}
.sem-por-cerrar .sem-estado{color:var(--aviso)}
.sem-por-cerrar{box-shadow:inset 3px 0 0 var(--aviso)}
/* SIN HORARIO ES EL ESTADO QUE IMPORTA, y es un defecto nuestro, no del negocio: nadie le
   preguntó su horario, así que aparece CERRADO siempre en el sitio público y el negocio concluye
   que la plataforma no sirve. Va primero en la lista y es el único con fondo. */
.sem-sin-horario .sem-luz{background:var(--malo)}
.sem-sin-horario .sem-estado{color:var(--malo)}
.sem-sin-horario{box-shadow:inset 3px 0 0 var(--malo);background:var(--alerta-suave)}
button.sem-sin-horario:hover{background:var(--alerta-suave);filter:brightness(.97)}
.sem-cerrado .sem-estado{color:var(--tinta-3)}

/* En el teléfono el estado baja a su propio renglón: en fila con el nombre, un nombre largo
   lo empujaba fuera y «sin horario» quedaba partido en dos. */
@media (max-width:520px){
  .sem-fila{grid-template-columns:10px minmax(0,1fr);
    grid-template-areas:"luz nombre" ".  estado" ".  porque" ".  dias"}
  .sem-estado{justify-self:start}
}

/* ══ LA CARPETA DEL SOPORTE ════════════════════════════════════════════════
   La insignia que dice si un movimiento de dinero tiene su papel: quién pagó, la referencia y
   el comprobante. La dibuja `publico/app/motores/anexos.js` y la usan caja y gastos.

   TRES ESTADOS Y NO DOS, porque son tres trabajos distintos: al que solo le falta la factura se
   le pide al proveedor mientras todavía se le puede pedir; al que no tiene nada hay que
   reconstruirlo preguntando. Una lista que los pinta igual obliga a abrir los dos para saber
   cuál es cuál.

   Y la palabra va SIEMPRE, no solo el color — la misma regla que el semáforo. */
.anx-sello{display:inline-block;font-family:Archivo,sans-serif;font-size:10.5px;font-weight:700;
  letter-spacing:.05em;text-transform:uppercase;padding:3px 7px;border-radius:999px;
  white-space:nowrap;border:1px solid transparent}
.anx-documentado{color:var(--bueno);background:var(--nopal-suave);border-color:transparent}
.anx-a-medias{color:var(--aviso);border-color:currentColor;background:none}
.anx-sin-documentar{color:var(--malo);background:var(--alerta-suave)}

/* El bloque de captura, dentro del diálogo. `.campos` ya hace la rejilla; esto solo le da aire
   al pie y evita que el diálogo crezca más que la pantalla en un teléfono. */
.anx{margin:4px 0 2px}
.anx .campos{gap:12px}
dialog.dialogo .anx{max-height:none}

/* ══ LA TABLA DE DATOS ═════════════════════════════════════════════════════
   La dibuja `publico/app/motores/tabla.js`. Antes eran 48 `<table>` escritas a mano, cada una
   con sus anchos y su criterio: ninguna mejora podía llegar a las 48 a la vez, y por eso
   ordenar y buscar no existían en NINGUNA. Son las dos operaciones más usadas de una hoja de
   cálculo, y eran justo las dos que faltaban. */

/* PARA QUIEN NO VE LA PANTALLA. Un `<th></th>` vacío y una tabla sin título se leen como una
   lista de celdas sueltas; esto pone el nombre sin ocupar un píxel. No se usa `display:none`:
   eso también se lo esconde al lector. */
.solo-lectores{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0}

.tabla-barra{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin:0 0 10px}
.tabla-busca{flex:0 1 280px;min-width:160px}
.tabla-cuantas{font-family:Archivo,sans-serif;font-size:12px;color:var(--tinta-3);
  font-variant-numeric:tabular-nums}

/* LA CABECERA ORDENA, Y SE TIENE QUE NOTAR QUE SE PUEDE TOCAR. Es un `<button>` y no un `<th>`
   con un `onclick` porque así se alcanza con el teclado y se anuncia como control. Se le quita
   todo el aspecto de botón: lo que debe parecer es una cabecera que responde. */
.th-ordena{all:unset;display:inline-flex;align-items:center;gap:4px;cursor:pointer;
  font:inherit;color:inherit;width:100%;padding:2px 0;border-radius:4px}
.th-ordena:hover{color:var(--nopal)}
.th-ordena:focus-visible{outline:2px solid var(--clave);outline-offset:2px}
th[aria-sort="ascending"] .th-ordena,th[aria-sort="descending"] .th-ordena{color:var(--nopal)}

/* LA CABECERA SE QUEDA ARRIBA AL DESPLAZAR. Con treinta filas, perder los nombres de columna a
   la mitad obliga a subir para recordar qué columna es cuál. */
.tabla-caja thead th{position:sticky;top:0;z-index:1;background:var(--papel-3)}

/* Y EL `min-width` SALE DEL CONTENIDO, no de un número fijo. Había un `min-width:620px` escrito
   para la tabla de ocho columnas del libro de caja y aplicado a TODAS: el horario de un negocio
   —tres columnas— se deslizaba en horizontal sin ninguna razón. */
.tabla .tabla-caja table{min-width:0}
@media (min-width:701px){.tabla .tabla-caja table{min-width:520px}}

/* EL MENSAJE DE ERROR, PEGADO A SU CAMPO. Iba al pie de un formulario de cincuenta campos: había
   que bajar a leerlo y volver a subir a corregir, y con dos datos mal solo se señalaba uno. */
.campo-error{margin:5px 0 0;font-size:12.5px;line-height:1.4;color:var(--malo);
  font-family:Archivo,sans-serif}
.campo-error::before{content:"▲ ";font-size:10px}
input[aria-invalid="true"],select[aria-invalid="true"],textarea[aria-invalid="true"]{
  border-color:var(--alerta)}

/* ══ INDICADORES Y GRÁFICOS ════════════════════════════════════════════════
   Lo que acompaña a `publico/app/motores/grafico.js`.

   LA PALETA DE SERIES ESTÁ MEDIDA, NO ELEGIDA A OJO. Los cuatro tonos de cada tema pasaron, con
   el validador de daltonismo, la banda de luminosidad, el piso de croma, la separación
   protan/deutan/tritan entre TODOS los pares —no solo los contiguos— y el contraste ≥3:1 contra
   la superficie de la tarjeta de su tema. El par más apretado, azul contra morado, queda en la
   banda 6–8: eso solo es admisible si hay un segundo canal además del color, y por eso el motor
   pone siempre leyenda, etiqueta directa y 2 px de aire entre rellenos contiguos.

   NO SE AÑADE UN QUINTO TONO. La quinta categoría se agrupa en «otros» con el gris de línea y se
   desglosa en la tabla. Un color generado al vuelo rompe lo que se midió. */
:root{
  --serie-1:#2563A8;  /* azul      · lo principal, lo que se cuenta primero */
  --serie-2:#C2410C;  /* terracota · lo segundo */
  --serie-3:#1E7A4C;  /* nopal     · el verde de la marca */
  --serie-4:#7C3AED;  /* morado    · el cuarto y último */
  --g-bien:var(--bueno); --g-ojo:var(--aviso); --g-mal:var(--malo);
}
@media (prefers-color-scheme:dark){:root:not([data-theme=light]){
  --serie-1:#4984BF; --serie-2:#DB703B; --serie-3:#32A155; --serie-4:#AB73E4;
}}
[data-theme=dark]{
  --serie-1:#4984BF; --serie-2:#DB703B; --serie-3:#32A155; --serie-4:#AB73E4;
}

/* ── LA LOSETA DE INDICADOR ──
   Tres renglones, tres tamaños, tres pesos, siempre en el mismo orden. Sin sombra —lleva borde—
   para que el indicador no compite con las tarjetas de contenido, que sí la llevan. */
.g-kpis{display:grid;gap:10px;margin:0 0 14px;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,var(--g-min,168px)),1fr))}
.g-kpi{display:flex;flex-direction:column;align-items:flex-start;gap:1px;
  background:var(--papel-2);border:1px solid var(--linea);border-radius:12px;
  padding:11px 13px;text-align:left;min-height:0;width:100%;
  font-family:inherit;color:var(--tinta);box-shadow:none}
/* UNA LOSETA QUE SE PUEDE ABRIR SE COMPORTA COMO BOTÓN; una que no, no finge que sí. */
button.g-kpi{cursor:pointer;transition:border-color .15s,background .15s}
button.g-kpi:hover{border-color:var(--clave);background:var(--papel-3)}
button.g-kpi:focus-visible{outline:2px solid var(--clave);outline-offset:2px}
button.g-kpi::after{content:"›";position:absolute;right:11px;top:9px;color:var(--tinta-3);
  font-size:17px;line-height:1}
button.g-kpi{position:relative;padding-right:24px}
.g-kpi-que{font-family:Archivo,sans-serif;font-size:10.5px;font-weight:600;
  letter-spacing:.055em;text-transform:uppercase;color:var(--tinta-3);line-height:1.3}
/* `tabular-nums` para que la cifra no baile al cambiar: un número que se mueve se vuelve a leer. */
.g-kpi-cuanto{font-family:Archivo,sans-serif;font-size:23px;font-weight:700;
  letter-spacing:-.02em;line-height:1.12;margin:2px 0 1px;font-variant-numeric:tabular-nums}
.g-kpi-contra{font-size:11.5px;color:var(--tinta-3);line-height:1.35;
  font-family:Archivo,sans-serif;font-variant-numeric:tabular-nums}
.g-kpi-nota{font-size:11.5px;color:var(--tinta-3);line-height:1.4;margin-top:4px}
/* EL JUICIO VA EN LA CIFRA, no en la loseta entera: cuatro tarjetas de colores son un semáforo
   roto. Solo cuando el juicio es «mal» se tiñe el borde, porque entonces sí hay que encontrarla. */
.g-kpi.g-bien .g-kpi-cuanto{color:var(--bueno)}
.g-kpi.g-ojo  .g-kpi-cuanto{color:var(--aviso)}
.g-kpi.g-mal  .g-kpi-cuanto{color:var(--malo)}
.g-kpi.g-mal{border-color:var(--alerta);background:var(--alerta-suave)}
.g-kpi-contra.g-bien{color:var(--bueno)} .g-kpi-contra.g-ojo{color:var(--aviso)}
.g-kpi-contra.g-mal{color:var(--malo);font-weight:600}
.g-chispa{display:block;margin:5px 0 1px;overflow:visible}

/* ── LA CAJA DEL GRÁFICO ── */
.g-caja{margin:0 0 14px;padding:13px 14px;background:var(--papel-2);
  border:1px solid var(--linea);border-radius:14px;position:relative}
.g-titulo{display:flex;align-items:baseline;justify-content:space-between;gap:10px;
  font-family:Archivo,sans-serif;font-size:12.5px;font-weight:700;color:var(--tinta);
  margin:0 0 10px;letter-spacing:-.01em}
.g-tope{font-size:10.5px;font-weight:600;letter-spacing:.045em;text-transform:uppercase;
  color:var(--tinta-3);white-space:nowrap;font-variant-numeric:tabular-nums}
/* `overflow:visible` Y 16 px DE AIRE EN EL viewBox: sin los dos, la etiqueta de la barra más
   alta se recorta. Es el defecto clásico de un SVG dibujado a mano. */
.g-svg{display:block;width:100%;height:auto;overflow:visible}
.g-base{stroke:var(--linea);stroke-width:1}
/* EL TEXTO DEL SVG NO HEREDA LA FUENTE DE FORMA FIABLE: se declara aquí, con su tema. */
.g-val,.g-eje{font-family:Archivo,"Helvetica Neue",Arial,sans-serif;
  font-variant-numeric:tabular-nums}
.g-val{font-size:8.5px;font-weight:600;fill:var(--tinta-2)}
.g-val-hoy{fill:var(--serie-1);font-weight:700;font-size:9.5px}
.g-eje{font-size:8.5px;fill:var(--tinta-3)}
.g-barra{cursor:default}
.g-dice{margin:9px 0 0;font-size:12.5px;line-height:1.45;color:var(--tinta-3)}
.g-vacio{background:var(--papel-3);border-style:dashed}

/* ── DONA · la leyenda ES la tabla ── */
.g-dona-par{display:grid;gap:16px;align-items:center;
  grid-template-columns:140px minmax(0,1fr)}
@media (max-width:560px){.g-dona-par{grid-template-columns:1fr;justify-items:center}}
.g-dona{position:relative;width:140px;height:140px}
/* ══ EL CENTRO DE LA DONA SE MIDIÓ CON LA BASE VACÍA ══════════════════════════════════════
   `inset:26%` de 140 px deja 67 px de ancho, y con un cero dentro sobraba sitio. Con cifras de
   verdad —$124,500— el número mide 74 px y se salía siete por fuera del círculo, recortado y
   sin forma de alcanzarlo. Lo destapó sembrar la base antes de barrer: el defecto llevaba ahí
   desde que se dibujó la dona, y no se veía porque no había qué dibujar.

   `inset:19%` da 85 px, y el tamaño baja solo con `clamp` cuando la cifra crece. Las dos cosas:
   más sitio, y un número que cede antes de romper. */
.g-dona-centro{position:absolute;inset:19%;display:flex;flex-direction:column;
  align-items:center;justify-content:center;text-align:center;gap:1px}
.g-dona-centro b{font-family:Archivo,sans-serif;font-size:clamp(12px,3.2vw,17px);font-weight:700;
  line-height:1.05;letter-spacing:-.03em;font-variant-numeric:tabular-nums;
  max-width:100%;overflow-wrap:anywhere}
.g-dona-centro span{font-size:9.5px;letter-spacing:.055em;text-transform:uppercase;
  color:var(--tinta-3);font-family:Archivo,sans-serif}
.g-leyenda-lista{list-style:none;margin:0;padding:0;display:grid;gap:5px;width:100%}
.g-leyenda-lista li{display:grid;grid-template-columns:10px minmax(0,1fr) auto auto;
  gap:8px;align-items:center;padding:7px 9px;background:var(--papel-3);
  border-radius:9px;font-size:12.5px}
/* ══ EL NOMBRE SE PARTE, NO SE CORTA ══════════════════════════════════════════════════════
   Llevaba `text-overflow:ellipsis` con `nowrap`, y eso con la base vacía no se notaba. Con
   nombres de verdad, «Afiliación mensual» se quedaba en «Afiliac…» — y en una leyenda el
   nombre ES el dato: una dona cuyos tramos no se pueden nombrar no dice nada.

   Los puntos suspensivos parecen una decisión de diseño y aquí eran una pérdida: no hay hover
   en un teléfono, no hay desplazamiento dentro de la caja, y el texto no vuelve. Partir en dos
   líneas cuesta ocho píxeles de alto y devuelve el dato entero. */
.g-leyenda-nombre{min-width:0;overflow-wrap:anywhere;line-height:1.25}
.g-leyenda-lista b{font-family:Archivo,sans-serif;font-variant-numeric:tabular-nums;
  font-size:12.5px}
.g-pc{font-size:11px;color:var(--tinta-3);min-width:30px;text-align:right;
  font-variant-numeric:tabular-nums}
.g-punto{width:10px;height:10px;border-radius:50%;display:inline-block;flex:0 0 auto}
.g-punto-otros{background:var(--linea)}
.g-leyenda{list-style:none;display:flex;flex-wrap:wrap;gap:4px 14px;margin:0 0 9px;padding:0;
  font-size:12px;color:var(--tinta-2)}
.g-leyenda li{display:flex;align-items:center;gap:6px}

/* ── BARRAS HORIZONTALES ──
   El nombre a ancho fijo, y por eso todas las barras arrancan en la misma vertical: si cada
   barra empieza donde acaba su nombre, la comparación es falsa. */
.g-barrasH{list-style:none;margin:0;padding:0;display:grid;gap:8px}
.g-barrasH li{display:grid;grid-template-columns:92px minmax(0,1fr) auto;gap:9px;
  align-items:center;font-size:12.5px}
.g-bh-nombre{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--tinta-2)}
.g-bh-pista{display:block;height:13px;background:var(--papel-3);border-radius:4px;
  overflow:hidden}
.g-bh-relleno{display:block;height:100%;border-radius:4px;transition:width .35s}
.g-bh-valor{font-family:Archivo,sans-serif;font-variant-numeric:tabular-nums;
  white-space:nowrap;font-size:12.5px}
.g-bh-nota{grid-column:2/4;font-size:11.5px;color:var(--tinta-3);margin-top:-3px}
/* EN EL TELÉFONO LA COLUMNA DEL NOMBRE SE ENCOGE, PERO NO POR DEBAJO DE LO QUE MIDE EL NOMBRE
   MÁS LARGO QUE SE USA: «Más de 60 días» es el tramo que dispara la llamada de cobranza y
   recortarlo a «Más de 60 …» obliga a abrir la tabla para saber cuál es. */
@media (max-width:420px){.g-barrasH li{grid-template-columns:86px minmax(0,1fr) auto}
  .g-bh-valor,.g-barrasH li{font-size:12px}}

/* ── ANILLO DE AVANCE ── */
.g-anillo-caja{display:flex;align-items:center;gap:14px}
.g-anillo{position:relative;width:76px;height:76px;flex:0 0 auto}
.g-anillo-pc{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  font-family:Archivo,sans-serif;font-size:17px;font-weight:700;letter-spacing:-.025em;
  font-variant-numeric:tabular-nums}
.g-anillo-caja.g-bien .g-anillo-pc{color:var(--bueno)}
.g-anillo-caja.g-ojo  .g-anillo-pc{color:var(--aviso)}
.g-anillo-caja.g-mal  .g-anillo-pc{color:var(--malo)}
.g-anillo-pie{display:flex;flex-direction:column;gap:1px;min-width:0}
.g-anillo-pie b{font-family:Archivo,sans-serif;font-size:16px;font-weight:700;
  font-variant-numeric:tabular-nums;line-height:1.2}

/* ── LA TABLA DE TODO GRÁFICO ──
   Cerrada por omisión para no ocupar sitio; a un clic para copiar la columna a una hoja, leerla
   con un lector de pantalla o imprimirla en blanco y negro. */
.g-tabla{margin:10px 0 0;border-top:1px solid var(--linea);padding-top:8px}
.g-tabla>summary{font-family:Archivo,sans-serif;font-size:11.5px;font-weight:600;
  color:var(--tinta-3);cursor:pointer;letter-spacing:.01em}
.g-tabla>summary:hover{color:var(--clave)}
.g-tabla table{width:100%;border-collapse:collapse;margin-top:8px;font-size:12.5px}
.g-tabla th,.g-tabla td{padding:5px 7px;text-align:right;border-bottom:1px solid var(--linea);
  font-variant-numeric:tabular-nums}
.g-tabla thead th,.g-tabla th[scope=row]{text-align:left;font-weight:600;
  font-family:Archivo,sans-serif}
.g-tabla thead th{color:var(--tinta-3);font-size:11px;letter-spacing:.04em;text-transform:uppercase}
.g-tabla thead th:not(:first-child){text-align:right}
/* AL IMPRIMIR, LA TABLA SE ABRE SIEMPRE. En papel el gráfico pierde el color y el globo no
   existe: la tabla es lo único que queda, y un `<details>` cerrado no se imprime. */
@media print{.g-tabla>*{display:revert!important}.g-tabla[open],.g-tabla{display:block}
  .g-tabla table{display:table}}

/* ── EL GLOBO ──
   El dibujo rotula «$1.8k» y el globo dice «$1,842.50»: el dibujo compara, el globo comprueba. */
.g-globo{position:absolute;z-index:5;transform:translate(-50%,-100%);pointer-events:none;
  background:var(--tinta);color:var(--papel-2);padding:6px 10px;border-radius:8px;
  font-size:12px;line-height:1.35;white-space:nowrap;box-shadow:var(--sombra);
  font-variant-numeric:tabular-nums;max-width:240px}
.g-globo b{font-family:Archivo,sans-serif;margin-right:5px}
.g-globo span{display:block;white-space:normal;opacity:.82;font-size:11px;margin-top:2px}

/* QUIEN PIDE MENOS MOVIMIENTO NO LO RECIBE. */
@media (prefers-reduced-motion:reduce){
  .g-bh-relleno,button.g-kpi{transition:none}
}

/* ══ LOS ACCESOS DIRECTOS DEL TABLERO ══════════════════════════════════════
   Un tablero que dice qué pasa y no deja actuar es un informe. Estos botones son lo que lo
   convierte en el sitio desde el que se trabaja: apuntar un gasto estaba a cinco pasos —menú,
   módulo, abrir, pestaña, entrar— desde una pantalla que ya estaba abierta.

   LO URGENTE VA MARCADO Y PRIMERO, y lo marca el motor con lo que pasa hoy: «Abrir la caja» solo
   aparece si la caja de hoy no está abierta, y «Cobrar lo vencido» solo si hay algo vencido. Un
   atajo que está siempre, diga lo que diga el día, se vuelve parte del decorado. */
.atajos{display:grid;gap:9px;margin:16px 0 20px;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,218px),1fr))}
.atajo{display:flex;flex-direction:column;align-items:flex-start;gap:2px;text-align:left;
  padding:11px 13px;border-radius:12px;border:1px solid var(--linea);background:var(--papel-2);
  color:var(--tinta);cursor:pointer;width:100%;min-height:0;
  transition:border-color .15s,background .15s,transform .15s}
.atajo b{font-family:Archivo,sans-serif;font-size:14px;font-weight:700;line-height:1.25;
  letter-spacing:-.01em}
.atajo span{font-size:12px;line-height:1.35;color:var(--tinta-3)}
.atajo:hover{border-color:var(--nopal);background:var(--nopal-suave)}
.atajo:active{transform:scale(.985)}
.atajo:focus-visible{outline:2px solid var(--clave);outline-offset:2px}
/* EL URGENTE SE DISTINGUE POR BORDE Y FONDO, no solo por color de texto: tiene que encontrarse
   entre cinco botones iguales sin leerlos. */
.atajo-urge{border-color:var(--alerta);background:var(--alerta-suave)}
.atajo-urge b{color:var(--malo)}
.atajo-urge:hover{border-color:var(--alerta);background:var(--alerta-suave);
  box-shadow:var(--sombra)}
@media (prefers-reduced-motion:reduce){.atajo{transition:none}.atajo:active{transform:none}}

/* EL LIENZO DE LOS GRÁFICOS. Dos columnas en escritorio, una en el teléfono, y lo decide
   `auto-fit` sin una sola consulta de medio para las tarjetas — igual que la rejilla de
   indicadores. Una tarjeta de gráfico por debajo de 300 px deja de poder dibujar nada. */
.g-lienzo{display:grid;gap:12px;align-items:start;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,318px),1fr))}
.g-lienzo>.g-caja{margin:0}

/* ══ EL KIT DE AFILIACIÓN ══════════════════════════════════════════════════
   Una pieza del kit es un renglón con tres cosas: qué es, por qué está, y en qué estado va.
   El estado se lee por el borde izquierdo —rojo lo que falta, verde lo entregado— y además con
   su palabra en el chip: uno de cada doce hombres no distingue rojo de verde. */
.kit-piezas{list-style:none;margin:0;padding:0;display:grid;gap:8px}
.kit-pieza{display:flex;align-items:flex-start;gap:12px;flex-wrap:wrap;
  padding:11px 13px;background:var(--papel-2);border:1px solid var(--linea);
  border-left:3px solid var(--linea);border-radius:10px}
.kit-pieza-cuerpo{flex:1;min-width:200px}
.kit-pieza-cuerpo b{font-family:Archivo,sans-serif;font-size:14px;margin-right:8px}
.kit-pieza-cuerpo .sub{margin:4px 0 0;font-size:12.5px;line-height:1.4}
.kit-pieza-cuerpo .nivel{display:block;margin-top:5px}
.kit-pendiente{border-left-color:var(--alerta)}
.kit-hecho{border-left-color:var(--nopal)}
.kit-no_aplica{opacity:.62}
/* LO QUE SE DERIVA DE UN HECHO NO LLEVA BOTÓN, y se dice por qué en vez de dejar el hueco.
   Una casilla que alguien palomea es una casilla que se palomea el día que hay prisa. */
.kit-deriva{align-self:center;max-width:150px;text-align:right;font-style:italic}
/* EL ANEXO SE VE ANTES DE EMITIRLO. Un documento que se congela sin poder leerse antes se
   congela mal una de cada tres veces, y la versión mala queda con su huella. */
.anexo-previo{margin:12px 0 0;padding:14px;background:var(--papel-3);border-radius:10px;
  border:1px solid var(--linea);font-family:ui-monospace,monospace;font-size:12px;
  line-height:1.5;white-space:pre-wrap;max-height:420px;overflow:auto}

/* ══ EL CHIP TIENE ESTADOS, Y HASTA HOY NO LOS TENÍA ═══════════════════════
   `.chip` era UNA sola pinta: fondo verde claro, texto verde. Así que un chip que decía
   «FALTA» salía en verde, y los seis estados del negocio —borrador, en revisión, activo,
   suspendido, en preaviso, de baja— se pintaban los seis IGUAL. Un estado que no se distingue
   del de al lado no está dicho: ésa es, literalmente, la razón por la que «los negocios no
   tienen estado» aunque los seis existan en la base desde el primer día.

   EL TEXTO NO USA EL COLOR SEMÁNTICO, USA UNO MÁS OSCURO. `--malo` sobre `--alerta-suave` se
   lee mal a 10 px; un rojo oscuro específico sobre el mismo fondo se lee bien. Es el detalle
   que casi todo el mundo se salta y el que decide si una insignia pequeña sirve o es adorno. */
.chip.bien{background:var(--nopal-suave);color:#0E4A2C}
.chip.ojo,.chip.aviso{background:#FAEFD9;color:#5C3B00}
.chip.mal{background:var(--alerta-suave);color:#7A2415}
.chip.neutro{background:var(--papel-3);color:var(--tinta-3)}
@media (prefers-color-scheme:dark){:root:not([data-theme=light]){
  --chip-bien-t:#9FE0BC; --chip-ojo-f:#3A2E14; --chip-ojo-t:#E8C684;
  --chip-mal-t:#F0A694;
}}
@media (prefers-color-scheme:dark){:root:not([data-theme=light]) .chip.bien{color:#9FE0BC}
  :root:not([data-theme=light]) .chip.ojo,
  :root:not([data-theme=light]) .chip.aviso{background:#3A2E14;color:#E8C684}
  :root:not([data-theme=light]) .chip.mal{color:#F0A694}}
[data-theme=dark] .chip.bien{color:#9FE0BC}
[data-theme=dark] .chip.ojo,[data-theme=dark] .chip.aviso{background:#3A2E14;color:#E8C684}
[data-theme=dark] .chip.mal{color:#F0A694}

/* LOS SEIS ESTADOS DEL NEGOCIO, CADA UNO CON EL SUYO.
   El orden del ciclo se lee en el color: lo que todavía no vende en ámbar, lo que vende en
   verde, lo que dejó de vender en rojo, y lo que ya se fue en gris. Y la palabra va siempre
   escrita dentro del chip — el color acelera la lectura a quien lo ve, no la hace posible. */
.chip[data-estado=borrador],.chip[data-estado=en_revision]{background:#FAEFD9;color:#5C3B00}
.chip[data-estado=activo]{background:var(--nopal-suave);color:#0E4A2C}
.chip[data-estado=suspendido],.chip[data-estado=preaviso]{background:var(--alerta-suave);color:#7A2415}
.chip[data-estado=baja]{background:var(--papel-3);color:var(--tinta-3)}
@media (prefers-color-scheme:dark){:root:not([data-theme=light]){
  }
  :root:not([data-theme=light]) .chip[data-estado=borrador],
  :root:not([data-theme=light]) .chip[data-estado=en_revision]{background:#3A2E14;color:#E8C684}
  :root:not([data-theme=light]) .chip[data-estado=activo]{color:#9FE0BC}
  :root:not([data-theme=light]) .chip[data-estado=suspendido],
  :root:not([data-theme=light]) .chip[data-estado=preaviso]{color:#F0A694}}
[data-theme=dark] .chip[data-estado=borrador],
[data-theme=dark] .chip[data-estado=en_revision]{background:#3A2E14;color:#E8C684}
[data-theme=dark] .chip[data-estado=activo]{color:#9FE0BC}
[data-theme=dark] .chip[data-estado=suspendido],
[data-theme=dark] .chip[data-estado=preaviso]{color:#F0A694}

/* LA GRAVEDAD DE UNA INCIDENCIA, por el mismo motivo y con el mismo cuidado.
   `.chip` tiene UNA pinta por omisión —fondo verde claro, texto verde— y eso ya costó una vez:
   un chip que decía «FALTA» salía en verde, igual que uno que decía «listo». Un chip nuevo sin
   su regla no sale sin color: sale con el color de la buena noticia.

   Aquí eso sería peor que feo. Una incidencia SANITARIA de gravedad alta pintada de verde es un
   dato que se lee al revés de lo que dice. La palabra va escrita dentro del chip siempre —el
   color acelera la lectura a quien lo ve, no la hace posible— y los tonos son los mismos que ya
   usan los estados, para que el rojo quiera decir lo mismo en toda la pantalla. */
.chip[data-gravedad=alta]{background:var(--alerta-suave);color:#7A2415}
.chip[data-gravedad=media]{background:#FAEFD9;color:#5C3B00}
.chip[data-gravedad=baja]{background:var(--papel-3);color:var(--tinta-3)}
@media (prefers-color-scheme:dark){
  :root:not([data-theme=light]) .chip[data-gravedad=alta]{color:#F0A694}
  :root:not([data-theme=light]) .chip[data-gravedad=media]{background:#3A2E14;color:#E8C684}}
[data-theme=dark] .chip[data-gravedad=alta]{color:#F0A694}
[data-theme=dark] .chip[data-gravedad=media]{background:#3A2E14;color:#E8C684}

/* ══ EL HORARIO: LA CASILLA POR DÍA ════════════════════════════════════════
   Decir «no abre el domingo» solo se podía BORRANDO las dos horas, y en un iPad un
   `<input type="time">` que ya tiene valor NO SE PUEDE VACIAR — no hay gesto para dejarlo en
   blanco. La única manera de marcar un día cerrado era imposible en el aparato con el que se
   captura, y el intento de rodearlo poniendo 12:00 a 12:00 lo rechazaba el servidor, con razón.

   La casilla lo dice en un toque. Y el día apagado SE VE apagado: si solo cambiara el dato,
   habría que leer catorce campos para saber qué días abre. */
.interruptor-dia{display:flex;align-items:center;gap:7px;margin:0;font-weight:400;
  text-transform:none;letter-spacing:0;cursor:pointer;white-space:nowrap}
.interruptor-dia input{width:20px;height:20px;flex:0 0 auto;margin:0;accent-color:var(--nopal)}
.interruptor-dia span{font-family:Archivo,sans-serif;font-size:11px;letter-spacing:.05em;
  text-transform:uppercase;color:var(--nopal)}
.dia-cerrado .interruptor-dia span{color:var(--tinta-3)}
/* EL DÍA APAGADO SE ATENÚA, pero su hora SIGUE LEYÉNDOSE: al volver a encenderlo aparece la
   que tenía, y eso evita teclearla otra vez por no acordarse de cuál era. */
.dia-cerrado .rh-horas{opacity:.52}
.dia-cerrado input[type=time]{text-decoration:line-through}

/* ══ LA SEMANA EN REJILLA, Y NO EN UNA `<table>` ══════════════════════════════════════════
   Era una tabla de cuatro columnas: día, casilla, abre, cierra. En 1 440 px se veía bien y en
   375 px —el teléfono con el que se captura de verdad, delante del mostrador— la cuarta
   columna salía cortada: el reloj de CERRAR, que es la mitad del dato.

   Una tabla no puede partir una fila en dos líneas; una rejilla sí. Aquí el renglón es un
   bloque que se acomoda: en ancho entra en una línea, y en estrecho la hora baja sola debajo
   del nombre y la casilla, sin cortar nada y sin scroll horizontal. */
.rejilla-horario{display:grid;gap:8px;margin:4px 0 2px}

/* ══ LA MISMA IDEA PARA UNA FORMA DE «DATO · VALOR» ═══════════════════════════════════════
   Los datos del operador eran una tabla de dos columnas con un campo en cada renglón. Mismo
   defecto, mismo arreglo: en 375 px la columna del valor se quedaba en cuatro caracteres.

   `rd-falta` marca el borde de los que están vacíos. El texto de arriba ya dice CUÁNTOS faltan;
   lo que no decía es CUÁLES, y para encontrarlos había que recorrer veintitantos renglones. */
.rejilla-datos{display:grid;gap:8px;margin:4px 0 2px}
.rd-fila{display:flex;flex-wrap:wrap;align-items:center;gap:8px 14px;margin:0;
  padding:9px 12px;border:1px solid var(--linea);border-radius:10px;
  background:var(--papel-2);font-weight:400;text-transform:none;letter-spacing:0}
.rd-fila.rd-falta{border-color:var(--aviso);border-left-width:3px}
.rd-nombre{flex:1 1 230px;min-width:0;font-size:12.5px}
.rd-nombre strong{font-family:Archivo,sans-serif}
.rd-fila input{flex:1 1 220px;min-width:0}
@media (max-width:520px){
  .rd-nombre{flex:1 1 100%}
  .rd-fila input{flex:1 1 100%}
}
.rh-dia{display:flex;flex-wrap:wrap;align-items:center;gap:10px 14px;
  padding:9px 12px;border:1px solid var(--linea);border-radius:10px;
  background:var(--papel-2)}
.rh-nombre{flex:0 0 92px;font-family:Archivo,sans-serif;font-size:12.5px;font-weight:500}
.rh-horas{display:flex;align-items:center;gap:8px;flex:1 1 210px;min-width:0}
/* `flex:1 1 210px` y no `flex:1`: con base 0 los dos relojes se comprimían hasta ilegibles
   antes de decidir bajar de línea, que es lo contrario de lo que hace falta. */
.rh-horas input[type=time]{flex:1 1 0;min-width:96px}
.rh-a{font-size:12px;color:var(--tinta-3);flex:0 0 auto}
.rh-cruza{flex:1 1 100%;font-size:11px}
.dia-cerrado.rh-dia{background:transparent}
@media (max-width:420px){
  .rh-nombre{flex:1 1 100%}
  .rh-horas{flex:1 1 100%}
}

/* ══ LA TARJETA DE VIDEO DE UNA TAREA ═════════════════════════════════════════════════════
   «Que abra y se vea un video de YouTube, para que si tienen dudas vea el video.»

   Lo que se pinta es la MINIATURA —una imagen estática de YouTube, sin un script dentro— y el
   reproductor la sustituye al tocarla. Ocho reproductores al abrir la pantalla serían ocho
   conexiones a un tercero y varios megas, en un teléfono con datos móviles en la Sierra. */
.wa-video{display:flex;flex-direction:column;gap:7px}
.wa-video-abre{position:relative;padding:0;border:1px solid var(--linea);border-radius:10px;
  overflow:hidden;background:var(--papel-3);cursor:pointer;display:block;width:100%;
  aspect-ratio:16/9;min-height:0}
.wa-video-abre img{width:100%;height:100%;object-fit:cover;display:block}
.wa-video-abre:hover{border-color:var(--tinta-2)}
/* EL TRIÁNGULO DICE QUE ES UN VIDEO Y NO UNA FOTO. Sin él, una miniatura es una imagen que
   nadie toca — y entonces el video no lo ve ninguno. */
.wa-video-play{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  font-size:30px;color:#fff;text-shadow:0 1px 6px rgba(0,0,0,.6)}
.wa-video-marco{width:100%;aspect-ratio:16/9;border:1px solid var(--linea);border-radius:10px;
  display:block}
.wa-video-dice{display:flex;flex-direction:column;gap:2px;font-size:12px;line-height:1.35}
.wa-video-dice b{font-size:12.5px}
@media (max-width:620px){
  .wa-video{margin-top:10px}
}

/* ══ LA SEMANA, DIBUJADA ═══════════════════════════════════════════════════════════════════
   «Que lo vuelva 100 % gráfico. No es posible que siga así.» — Rodrigo, 12-oct-2026.

   Siete renglones sobre una regla de veinticuatro horas FIJAS. Fijas y no encuadradas a lo que
   quepa: así la posición de una barra significa lo mismo en dos negocios distintos, que es para
   lo que sirve dibujarlo. El motor está en `publico/app/motores/semana-grafica.js` y la razón
   de cada decisión está escrita allí. */
.sg{margin:4px 0 2px}
.sg-regla{position:relative;height:17px;margin:0 0 4px 96px}
.sg-marca{position:absolute;top:0;transform:translateX(-50%);
  display:flex;flex-direction:column;align-items:center;gap:1px}
.sg-marca i{width:1px;height:5px;background:var(--linea)}
.sg-marca b{font-size:9.5px;font-weight:500;color:var(--tinta-3);
  font-family:Archivo,sans-serif;letter-spacing:.02em}
/* LAS DOS DE LOS EXTREMOS SE PEGAN AL BORDE: centradas se salen del marco y se cortan. */
.sg-marca:first-child{transform:translateX(0)}
.sg-marca:first-child b{transform:translateX(-1px)}
.sg-marca:last-child{transform:translateX(-100%)}

.sg-fila{display:flex;align-items:center;gap:10px;padding:3px 0}
/* ══ EL NOMBRE SE RECORTA, VENGA DE DONDE VENGA ════════════════════════════════════════════
   Esta regla sirve a DOS cosas: los días de la semana —«Lun», tres letras— y, dentro del
   semáforo de «Mi día», el NOMBRE DE UN NEGOCIO. La variante `.sgd` ya recortaba; ésta no, y se
   notó en PRODUCCIÓN: «Farmacia médica santa regina» pedía 155 px en una caja de 148 y se salía
   sin poder desplazarse.

   El barrido local nunca lo vio porque los nombres sembrados son cortos. Lo cazó el barrido de
   las 25 pantallas CONTRA PRODUCCIÓN, la primera vez que se corrió — 12-oct-2026. Un nombre
   largo de verdad es un dato que sólo tiene la base de verdad. */
.sg-nombre{flex:0 0 86px;font-family:Archivo,sans-serif;font-size:12px;font-weight:500;
  color:var(--tinta-2);text-align:right;
  overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
.sg-pista{position:relative;flex:1 1 auto;min-width:0;height:26px;border-radius:7px;
  background:var(--papel-3);
  /* LAS HORAS, DENTRO DE LA PISTA: sin las líneas, una barra a media pista no se puede situar
     sin subir la vista a la regla y volver a bajar, siete veces. */
  background-image:repeating-linear-gradient(to right,
    var(--linea) 0 1px, transparent 1px calc(100% / 8))}
.sg-compacto .sg-pista{height:20px}

.sg-barra{position:absolute;top:3px;bottom:3px;border-radius:5px;
  background:var(--bueno);opacity:.9;box-sizing:border-box}
.sg-cerrado .sg-pista{opacity:.55}
/* HOY SE MARCA EN EL RENGLÓN, no sólo con la línea del momento: en una pantalla de siete
   renglones iguales, saber cuál es hoy cuesta contar. */
.sg-hoy .sg-nombre{color:var(--tinta);font-weight:600}
.sg-hoy .sg-pista{outline:1.5px solid var(--linea);outline-offset:1px}
/* ══ LA RAYA DEL MOMENTO NO TOCA EL RATÓN, Y ESTO COSTÓ UN DESPLIEGUE ═══════════════════════
   Es un adorno —`aria-hidden`— puesto ENCIMA de la barra con `z-index:2`. Sin
   `pointer-events:none` se queda con la pulsación: `setPointerCapture` nunca ocurre y la barra
   NO SE ARRASTRA. Sin error, sin consola, sin nada: parece que el dibujo no sirve.

   Y es un defecto que cambia de sitio cada minuto. La raya está donde está la hora, así que
   tapa el punto de agarre de una barra distinta a cada rato: una de 9 a 21 tiene su centro en
   las 15:00, y a las 15:05 justo ahí estaba la raya. El recorrido del horario lo cazó en el
   gate del 12-oct-2026 —24 de 26— y la corrida de una hora antes había pasado entera, que es
   la firma de un defecto que depende del reloj. */
.sg-ahora{position:absolute;top:-2px;bottom:-2px;width:2px;background:var(--malo);
  border-radius:2px;z-index:2;pointer-events:none}

.sg-dice{flex:0 0 108px;font-size:11.5px;color:var(--tinta-2);
  font-variant-numeric:tabular-nums}
.sg-cerrado .sg-dice{color:var(--tinta-3)}
.sg-cruza{flex:0 0 100%;margin-left:96px;font-size:10.5px}
.sg-pie{margin:8px 0 0 96px;font-size:11.5px}

/* ══ CUANDO SE PUEDE ARRASTRAR ═══════════════════════════════════════════════════════════
   El cursor y el foco visible no son adorno: una barra que se puede arrastrar y no lo parece
   no se arrastra nunca, y entonces el dibujo es sólo un dibujo. */
.sg-editable .sg-barra{cursor:grab;touch-action:none}
.sg-editable .sg-barra:focus-visible{outline:2px solid var(--tinta);outline-offset:2px}
.sg-barra.sg-arrastrando{cursor:grabbing;opacity:1}
.sg-asa{position:absolute;top:-3px;bottom:-3px;width:11px;cursor:ew-resize;
  display:block;border-radius:4px}
/* LAS ASAS SE VEN, Y SON MÁS ANCHAS QUE LO QUE SE VE: once píxeles es lo mínimo que un dedo
   acierta, y la rayita de dentro es lo que dice dónde apuntar. */
.sg-asa::after{content:'';position:absolute;top:7px;bottom:7px;left:4px;width:3px;
  border-radius:2px;background:var(--papel-2);opacity:.85}
.sg-asa-izq{left:-5px}
.sg-asa-der{right:-5px}

/* ══ EL DÍA DE HOY, DE TODOS, EN LA MISMA REGLA ══════════════════════════════════════════
   Aquí el nombre es un nombre de negocio y no tres letras, así que la columna es más ancha y
   se corta con puntos suspensivos en vez de empujar la pista. El estado pinta la barra: el
   color acelera la lectura y la palabra de la derecha es la que la hace posible. */
/* ══ `.sgd .sg-nombre` Y NO `.sgd-nombre` ════════════════════════════════════════════════
   Las dos tienen la misma especificidad —una clase—, así que mandaba la que se escribiera
   después; y la regla estrecha de `.sg-nombre` (42 px, para las tres letras de un día) va más
   abajo en este archivo. Resultado: a 375 px el nombre de un negocio tenía 42 px de caja y 107
   de texto, y SE SALÍA. Lo cazó el barrido de geometría del gate, que mide justo eso.

   Con dos clases gana por especificidad, sin depender de quién esté escrito primero. */
.sgd .sg-nombre{flex:0 0 148px;text-align:left;font-size:11.5px;overflow:hidden;
  white-space:nowrap;text-overflow:ellipsis}
.sgd .sg-regla,.sgd .sg-pie{margin-left:158px}
.sgd-abierto .sg-barra{background:var(--bueno)}
.sgd-por-cerrar .sg-barra{background:var(--aviso)}
.sgd-cerrado .sg-barra{background:var(--tinta-3);opacity:.5}
.sgd-sin-horario .sg-pista{outline:1.5px dashed var(--malo);outline-offset:1px}
.sgd-sin-horario .sg-dice{color:var(--malo)}
.sgd-cima{font-size:12px}
@media (max-width:520px){
  /* EN ESTRECHO EL NOMBRE OCUPA SU PROPIO RENGLÓN, encima de la pista: con 42 px —que es lo que
     le toca al nombre de un DÍA— un nombre de negocio no cabe de ninguna manera, y recortarlo a
     cuatro letras deja una lista de «Taqu…», «Tort…», «Tien…» que no distingue nada. */
  .sgd .sg-nombre{flex:0 0 100%;text-align:left;margin-bottom:2px;white-space:normal}
  .sgd .sg-regla,.sgd .sg-pie{margin-left:0}
  .sgd .sg-dice{margin-left:0}
}

@media (max-width:520px){
  .sg-regla,.sg-cruza,.sg-pie{margin-left:52px}
  .sg-nombre{flex:0 0 42px}
  /* LA HORA BAJA DEBAJO DE LA PISTA en estrecho, en vez de comerse el ancho del dibujo: la
     posición de la barra es el dato, y con 108 px de texto al lado no queda pista que leer. */
  .sg-dice{flex:0 0 100%;margin-left:52px;order:3}
  .sg-fila{flex-wrap:wrap;padding:5px 0}
}

/* PONER LA MISMA HORA EN TODA LA SEMANA. Es el caso de casi todos los negocios: se pone una vez
   y se corrige el día que cambia. Antes eran catorce campos tecleados uno por uno en un iPad,
   que es exactamente donde se abandona la captura y se vuelve al papel. */
.horario-todos{display:flex;align-items:center;gap:9px;flex-wrap:wrap;
  padding:11px 13px;margin:0 0 14px;background:var(--papel-3);border-radius:10px;
  border:1px solid var(--linea)}
.horario-todos input[type=time]{width:auto;min-width:120px;flex:0 0 auto}
.horario-todos .nivel{flex:0 0 auto}
@media (max-width:520px){.horario-todos{gap:7px}
  .horario-todos button{width:100%}}

/* ══ EL PRODUCTO SIN FOTO DEL NEGOCIO ══════════════════════════════════════
   Aquí hubo tres intentos antes de éste: un emoji gigante, una ilustración vectorial y el hueco
   dicho. Los tres fallaban por lo mismo — una carta se vende con fotografías, y una carta con
   huecos no vende.

   Lo que se enseña es una FOTO GENÉRICA de ese tipo de platillo, con su marca encima diciendo
   que lo es. La marca NO es decoración: un genérico que se hace pasar por la foto del negocio
   hace que el cliente pida lo que ve y le llegue otra cosa, y que nadie vuelva a pedirle al
   negocio la suya. */
.teja-generica{position:relative}
.teja-generica img{filter:saturate(.92)}
.marca-generica{position:absolute;top:8px;left:8px;z-index:1;
  font-family:Archivo,sans-serif;font-size:9.5px;font-weight:700;letter-spacing:.12em;
  text-transform:uppercase;padding:4px 8px;border-radius:3px;
  background:rgba(22,33,28,.82);color:#F0E6DC;backdrop-filter:blur(3px)}

/* EL PRODUCTO SIN NINGUNA FOTO. No se le pone la de otro platillo, así que el hueco tiene que
   verse como lo que es: un sitio reservado y vacío, no una imagen que no cargó. Rayado y con la
   palabra escrita — una caja gris lisa se lee como «se está cargando» y nadie va por la foto. */
.teja-sin-foto .hueco-foto{height:132px;display:flex;align-items:center;justify-content:center;
  font-family:Archivo,sans-serif;font-size:10px;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;color:var(--tinta-3);
  background:repeating-linear-gradient(135deg,var(--papel-3) 0 9px,transparent 9px 18px);
  border-bottom:1px solid var(--linea)}

/* ══ EL DESGLOSE DE UN ENVÍO ══════════════════════════════════════════════════════════════
   Un recibo, no una tabla: cada renglón es un concepto con su importe, y el total abajo.
   Va en `<dl>` y no en `<table>` porque no es una lista de filas comparables —no se ordena ni
   se exporta— y pintarla como tabla obligaría a meterla al motor para tener un buscador
   sobre cuatro renglones. */
.desglose{display:grid;grid-template-columns:1fr auto;gap:5px 16px;margin:0;font-size:14px}
.desglose dt{color:var(--tinta-2)}
.desglose dd{margin:0;text-align:right;font-variant-numeric:tabular-nums}
.desglose .fuerte{font-weight:700;color:var(--tinta);border-top:1px solid var(--linea);
  padding-top:6px;margin-top:2px}

/* ══════════════════════════════════════════════════════════════════════════════════════════════
   LA BANDEJA: CONTACTO Y DETALLE DEL PEDIDO · 20-oct-2026
   ══════════════════════════════════════════════════════════════════════════════════════════════

   Rodrigo pidió poder llamar, escribir por WhatsApp, abrir el mapa y ver qué lleva el pedido sin
   salir de la bandeja. Tres de esas cuatro cosas son ENLACES y la cuarta un botón, y tenían que
   verse igual: una fila de acciones donde una pieza parece un enlace y la de al lado un botón se
   lee como si hicieran cosas de distinta clase.

   `a.chico` se iguala a `button.chico` por eso. Y la fila entera envuelve en pantallas angostas
   en vez de salirse: la bandeja se mira también desde un teléfono. */
.contacto{display:flex;flex-wrap:wrap;gap:5px}
/* LOS CUATRO SE VEN IGUAL, y eso hubo que escribirlo: tres son enlaces y uno es botón, y al
   mirarlo con datos los enlaces salían como texto azul subrayado al lado de un botón sólido.
   Se leía como si hicieran cosas de distinta clase, cuando las cuatro son «qué puedo hacer con
   este pedido». El estilo sale del `button` de la casa, en pequeño. */
.contacto .chico,.contacto a.chico{font-size:11.5px;font-weight:600;padding:5px 9px;
  min-height:0;line-height:1.3;border-radius:3px;text-decoration:none;display:inline-block;
  background:var(--tinta);color:var(--papel);border:1px solid var(--tinta);
  font-family:Archivo,"Helvetica Neue",Arial,sans-serif;cursor:pointer;white-space:nowrap}
.contacto .chico:hover,.contacto a.chico:hover{opacity:.9}

/* EL DETALLE SE ABRE DENTRO DE LA FILA. Fondo propio y una barra a la izquierda para que se lea
   como «esto cuelga del pedido de arriba» y no como una fila más de la tabla. */
.detalle{display:flex;flex-wrap:wrap;gap:18px;padding:12px 14px;
  border-left:3px solid var(--clave);background:var(--velo)}
.detalle .bloque{min-width:240px;flex:1}
.detalle .que{font-size:10.5px;letter-spacing:.06em;text-transform:uppercase;
  color:var(--tinta-3);margin-bottom:6px}
.detalle .renglon{display:grid;grid-template-columns:auto 1fr auto;gap:0 8px;
  align-items:baseline;padding:4px 0;border-bottom:1px solid var(--linea)}
.detalle .renglon .cuerpo{min-width:0}
.detalle .renglon .nivel{text-transform:none;letter-spacing:0;margin-top:2px}
.detalle .qty{font-variant-numeric:tabular-nums;color:var(--tinta-3)}
.detalle .precio{text-align:right;font-variant-numeric:tabular-nums}

/* ══ EL NÚMERO DE LA FILA, EN SU PROPIO RENGLÓN · 20-oct-2026 ═════════════════════════════════
   Se pinta dentro de la celda del folio —para no robarle el sitio fijo al desplazar— y al
   mirarlo con datos salía pegado: «1P-2F3995D4», que se lee como si el 1 fuera parte del folio.

   Va arriba, en su propio renglón y apagado: es una referencia para HABLAR —«el tres»— no un
   dato del pedido. Vacío no ocupa nada, así que las tablas sin numerar no cambian. */
.num-fila:not(:empty){display:block;font-size:11px;color:var(--tinta-3);line-height:1.2;
  font-variant-numeric:tabular-nums}
.num-fila:not(:empty)::after{content:'·';margin-left:4px;opacity:.5}

/* ── La foto de un producto, en su ficha ───────────────────────────────────
   El motor de archivos y el guardado existían desde hace meses; lo que faltaba era este
   campo, y por eso 63 de los 144 productos salen sin foto en la carta del vecino. */
.foto-prod{display:flex;gap:16px;align-items:flex-start;margin:0 0 18px}
.foto-prod .miniatura{width:92px;height:92px;object-fit:cover;border-radius:10px;flex:none}
.foto-prod-lado{flex:1;min-width:0;display:flex;flex-direction:column;gap:8px;align-items:flex-start}
.foto-prod-lado .sub{margin:0}
/* El hueco mide lo mismo que la foto: si midiera menos, la ficha daría un salto al subirla. */
.sin-foto-ficha{width:92px;height:92px;flex:none;display:flex;align-items:center;
  justify-content:center;border-radius:10px;border:1px dashed var(--linea);
  font-size:12.5px;color:var(--tinta-3);text-align:center;padding:6px}
@media(max-width:560px){.foto-prod{flex-direction:column}}
