/* ═══════════════════════════════════════════════════════════════════════
   BASE — reset, cáscara, tipografía, escritorio, tacto y responsive.

   Copiado TAL CUAL de desarrollo/mockup-ux-interfaz.html (§ SHELL,
   TIPOGRAFÍA, ESCRITORIO, TACTO, RESPONSIVE). "Se copia, no se interpreta":
   estas medidas están verificadas con Chrome real por
   herramientas/verificar-interfaz-navegador.js (0 objetivos táctiles por
   debajo de 24/44px, 0 desbordes, 0 rejillas desparejas, en 390 y en 1440)
   y reescribirlas a ojo es cómo se pierde esa verificación.
   ═══════════════════════════════════════════════════════════════════════ */

*{box-sizing:border-box}
/* WCAG 2.2 · 2.4.11 Focus Not Obscured (AA): cuando algo recibe foco de
   teclado no puede quedar entero debajo de las barras pegajosas. El
   archivo tenía scroll-margin-top en [data-sec], que cubre el salto del
   índice pero NO el foco por teclado — tabulando por una sección el
   botón enfocado quedaba tapado por la barra superior más el índice.
   scroll-padding-top va en el elemento que scrollea (html) y aplica a
   todo desplazamiento por foco, no sólo a los saltos del índice.
   Mismo número que el scroll-margin para que no se desincronicen. */
html{-webkit-text-size-adjust:100%;scroll-padding-top:calc(var(--mtop) + 62px)}
body{
  margin:0;
  background:var(--paper);
  color:var(--ink);
  font-family:var(--fuente);
  font-size:var(--t-body);
  line-height:var(--lh-2);
  -webkit-font-smoothing:antialiased;
}
/* ── Los pesos, como escala ───────────────────────────────────────────
   De la entrada «Enterprise SaaS Mobile» del dataset de la skill, que es
   la que mejor describe a Campo: 800 titulo de pantalla, 700 encabezado
   de seccion, 600 titulo de tarjeta y botones, 400 cuerpo. Antes los
   tres niveles de encabezado pesaban 600 y la jerarquia la cargaba sola
   el tamano — con cinco pasos de escala eso deja el peso sin trabajo. */
h1,h2,h3{margin:0;letter-spacing:-.02em;line-height:var(--lh-0)}
h1{font-weight:800}
h2{font-weight:700}
h3{font-weight:600}
/* ── Cifras en mono ───────────────────────────────────────────────────
   Aporte de la familia «Finanzas»: Campo es una app de conteos —86
   clientes, 173 visitas, 2.186 unidades, «hace 78 dias», «cada 10
   dias»— y todos esos numeros se dibujaban con la misma fuente que la
   prosa. En mono el numero se lee COMO numero, y las columnas de
   conteos dejan de bailar de fila en fila. */
/* Mono para las cifras que viven EN COLUMNA o dentro de una frase: ahi lo
   que se gana es que no bailen de fila en fila. */
.num,.viz-v,.chip .n,.snav-i .n,.badge,.cnt{
  font-family:var(--mono);font-variant-numeric:tabular-nums;
  letter-spacing:-.02em;
}
/* Las cifras GRANDES de los KPI no van en mono: son tipografia de
   despliegue, no una columna, y en mono el punto de miles ocupa un ancho
   de caracter entero — «2.186» se lee «2 . 186». Se quedan en la sans, con
   figuras tabulares, que es lo que da la alineacion sin el efecto. */
.kpi-n{font-variant-numeric:tabular-nums;letter-spacing:-.03em}
/* El micro-rotulo de dato: mono, mayuscula, tracking abierto. Es el
   registro que usan los paneles financieros para decir «esto de aca
   abajo es un dato y no una frase». Le da a la app un segundo tono de
   voz, que es lo que no tenia: todo estaba escrito igual. */
.rot{
  font-family:var(--mono);font-size:11px;font-weight:600;
  text-transform:uppercase;letter-spacing:.09em;color:var(--muted);
  display:block;margin-bottom:var(--sp-3);
}
p{margin:0}
button{font-family:inherit;font-size:inherit;color:inherit;background:none;border:none;padding:0;cursor:pointer}

/* AGREGADO AL PORTAR EL SISTEMA A public/ (16/09/2026).
   El mockup no tiene un solo <a> —navega con `<button data-go>` y un listener
   global— así que nunca necesitó esta regla. Acá los destinos SÍ son enlaces
   de verdad (`<a href="#/clientes/c123">`), y eso es mejor que un botón por
   tres motivos concretos, ninguno estético:
     · andan sin JS, o sea que un error de un módulo no deja la app muerta;
     · el teclado y los lectores de pantalla los anuncian como destinos;
     · mantener presionado abre el menú del navegador, que es como la gente
       de verdad usa una lista en el teléfono.
   Sin este reset, Chrome los dibuja con su azul y su subrayado por encima del
   sistema: verificado en captura, las 30 tarjetas salían subrayadas.
   Los enlaces DE TEXTO corrido no entran acá: ésos sí llevan su color y su
   subrayado, y por eso la regla está acotada a los roles de navegación. */
a.row,a.tab,a.btn,a.fab,a.rail-link,a.hall,a.chip,a.fchip,a.snav-i{color:inherit;text-decoration:none}
input,textarea,select{font-family:inherit;color:inherit}
::selection{background:var(--ember-soft)}
svg{flex:none}
:focus-visible{outline:2px solid var(--ember);outline-offset:2px;border-radius:var(--r-1)}
@media (prefers-reduced-motion:reduce){
  *{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}
}

/* ═══════════════ SHELL ═══════════════ */
#app{display:flex;min-height:100vh}

.rail{
  width:var(--rail);flex:none;padding:var(--sp-6) var(--sp-4);position:sticky;top:0;height:100vh;
  display:flex;flex-direction:column;border-right:1px solid var(--line-soft);
}
.brand{display:flex;align-items:center;gap:var(--sp-3);padding:0 var(--sp-3) var(--sp-5);font-weight:600;font-size:var(--t-body);letter-spacing:-.02em}
.brand-dot{width:9px;height:9px;border-radius:50%;background:var(--ember)}
.rail-nav{display:flex;flex-direction:column;gap:var(--sp-1)}
/* El panel del dia en el rail. Ocupa el hueco que quedaba entre la
   navegacion y el pie, y no compite con nada: es lectura, no destinos. */
.rail-hoy{margin-top:var(--sp-7);padding:0 var(--sp-3)}
.rail-h{
  display:block;width:100%;text-align:left;
  font-size:var(--t-meta);color:var(--ink-2);line-height:var(--lh-1);
  padding:var(--sp-2) 0;
}
.rail-h .num{color:var(--ink);font-weight:600}
.rail-h.vacio{color:var(--muted-2)}
.rail-h.link-z{
  margin-top:var(--sp-3);padding-top:var(--sp-3);min-height:var(--tap);
  border-top:1px solid var(--line-soft);color:var(--ember-tx);font-weight:600;
}
.rail-h.link-z:hover{color:var(--ink)}
.rail-link{
  display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-2) var(--sp-3);border-radius:var(--r-1);
  color:var(--muted);font-size:var(--t-body);font-weight:500;width:100%;text-align:left;
  transition:background .12s,color .12s;
}
.rail-link:hover{background:var(--hover);color:var(--ink)}
.rail-link.on{background:var(--hover);color:var(--ink);font-weight:600}
.rail-link .n{margin-left:auto;font-size:var(--t-meta);color:var(--muted-2);font-variant-numeric:tabular-nums}
.rail-link.on .n{color:var(--muted)}

/* ── Submenú del rail (escritorio) ────────────────────────────────────
   La navegación de secciones de las vistas de `EN_RAIL` vive acá en
   escritorio, y por eso la barra de arriba de esas vistas se esconde
   (`.snav.en-rail`, al pie de este bloque). Es una MUDANZA, no una
   copia: el mismo control no puede estar en los dos lados.

   Forma de menú lateral, no de pestaña: la pestaña usa subrayado
   porque vive sobre una línea horizontal; acá la lista es vertical, así
   que el activo se marca con la barrita de la izquierda y el peso de
   la tinta. Si se hubiera copiado el subrayado, el rail habría quedado
   con cuatro rayitas sueltas que no se apoyan en nada. */
.rail-sub{display:flex;flex-direction:column;gap:1px;margin:var(--sp-2) 0 var(--sp-1);
  padding-left:calc(17px + var(--sp-3));border:0}
.rail-si{
  display:flex;width:100%;align-items:center;justify-content:space-between;gap:var(--sp-2);
  text-align:left;font-size:var(--t-meta);font-weight:500;color:var(--muted);min-height:30px;
  padding:var(--sp-2) var(--sp-3);border-left:2px solid var(--line-soft);
  border-radius:0 var(--r-1) var(--r-1) 0;transition:background .12s,color .12s,border-color .12s;
}
.rail-si:hover{background:var(--hover);color:var(--ink);border-left-color:var(--muted-2)}
.rail-si.on{color:var(--ink);font-weight:600;border-left-color:var(--ember);background:var(--hover)}
.rail-si-t{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rail-si .n{font-size:var(--t-meta);color:var(--muted-2);font-variant-numeric:tabular-nums;flex:none}
.rail-si.on .n{color:var(--muted)}
/* Igual que en la barra de la vista: el conteo en rojo es el único
   color del menú, y sólo cuando hay algo vencido o en problemas. */
.rail-si.urge .n{color:var(--alerta-tx)}

.rail-cta{
  margin:var(--sp-5) 0 0;display:flex;align-items:center;justify-content:center;gap:var(--sp-3);
  padding:var(--sp-3);border-radius:var(--r-2);background:var(--ember);color:var(--sobre-ember);font-weight:600;font-size:var(--t-body);
  transition:filter .15s,transform .08s;
}
.rail-cta:hover{filter:brightness(1.07)}
.rail-cta:active{transform:scale(.985)}
/* Segunda CTA del rail, para Presupuesto rápido. Nunca ".sec": esa clase
   ya existe para "sección" y el 1/09 costó un bug real por esa colisión
   de nombres (".btn.sec" heredaba el margin-top de ".sec"). Tono bajo a
   propósito — dos botones color ember uno arriba del otro competirían
   por la misma jerarquía que "Dictar nota" ya ocupa. */
.rail-cta.quiet{margin-top:var(--sp-3);background:none;color:var(--ink-2);border:1px solid var(--line)}
.rail-cta.quiet:hover{background:var(--hover);filter:none}

.rail-foot{margin-top:auto;padding:0 var(--sp-3);font-size:var(--t-meta);color:var(--muted-2);line-height:var(--lh-1)}
/* (23/09) El pie del rail lleva el aviso de «sin subir» y, sólo para un
   admin, el enlace a /admin. Los dos arrancan con `hidden`, y `.rail-link`
   declara `display:flex`, que le gana al `hidden` del navegador: sin esto
   el enlace de administración se le veía a cualquiera. */
.rail [hidden]{display:none}
/* En el mockup el CTA era un <button>; acá es un enlace a #/dictar, y sin
   esto hereda el subrayado de los <a>. */
.rail-cta{text-decoration:none}
.rail-foot .rail-link{margin:0 calc(-1 * var(--sp-3))}
.rail-foot .sync{padding:var(--sp-2) 0}

.col{flex:1;min-width:0;display:flex;justify-content:center}
.col-in{width:100%;max-width:var(--measure);padding:var(--sp-7) var(--sp-8) 120px}

.mtop{display:none}

/* ═══════════════ TIPOGRAFÍA / BLOQUES ═══════════════ */
.ptitle{font-size:var(--t-title);font-weight:600;letter-spacing:-.025em}
.psub{color:var(--muted);font-size:var(--t-meta);margin-top:var(--sp-1)}
.phead{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--sp-5);margin-bottom:var(--sp-7)}

.sec{margin-top:var(--sp-8)}
.sec:first-of-type{margin-top:var(--sp-7)}
/* Grupo de la lista de clientes. Es una sección a los efectos del
   índice, pero NO lleva los 44px de aire de .sec: separa tramos de una
   misma lista homogénea, no temas distintos. Con 86 clientes, cuatro
   márgenes de sección serían media pantalla de teléfono gastada en
   aire, sobre la vista que ya es la segunda más alta de la app. */
.cli-grupo{margin-top:var(--sp-6)}
.cli-grupo:first-child{margin-top:var(--sp-4)}
/* ── Jerarquía invertida (30/08, noche) ──────────────────────────────
   Antes: título de sección 11,5px uppercase a 4,8:1 de contraste;
   nota explicativa 13px a 5,5:1; nombre de cliente 15px a 16,8:1.
   O sea: la aclaración pesaba más que el título que aclara, y el
   contenido le ganaba a los dos. Scrolleando rápido no se veía
   estructura, se veía un campo parejo de nombres propios.
   Ahora el orden de peso visual es el orden de la jerarquía:
   título (16px/ink) > lead (14,5px/ink-2) > fila (14,5px) > nota (12,5px). */
/* Cualquier destino del índice reserva el alto de las dos barras
   pegajosas, para no aterrizar debajo de ellas. */
[data-sec]{scroll-margin-top:calc(var(--mtop) + 62px)}
/* `.slabel` es flex, y flex le gana al display:none del user-agent para
   [hidden]. Es la tercera vez que aparece este tropiezo en este archivo. */
.slabel[hidden]{display:none!important}
.slabel{
  display:flex;align-items:center;gap:var(--sp-3);margin-bottom:var(--sp-3);
  font-size:var(--t-sec);font-weight:600;letter-spacing:-.015em;color:var(--ink);
}
.slabel .n{
  font-size:var(--t-meta);background:var(--line);color:var(--muted);border-radius:var(--r-pill);
  padding:var(--sp-1) var(--sp-3);letter-spacing:0;font-weight:600;position:relative;top:-1px;
}
.slabel .grow{flex:1}
.slabel .act{font-size:var(--t-meta);text-transform:none;letter-spacing:0;color:var(--muted);font-weight:500}
.slabel .act:hover{color:var(--ember-tx)}
/* Acción en línea dentro de una frase. Se usa en dos lugares y no tenía
   ninguna regla: con el reset de `button` de más arriba se dibujaba como
   texto plano, indistinguible de la oración que la rodea. NO fija tamaño
   a propósito —uno de los dos usos vive en una .note de 12,5px y el otro
   en cuerpo de 15px—: lo que la hace un enlace es el color y el
   subrayado, no el tamaño. */
.link{
  color:var(--ember-tx);font-weight:500;
  text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:3px;
}
.link:hover{color:var(--ink);text-decoration-thickness:2px}
/* El lead: la respuesta de la sección, antes de la lista que la
   respalda. Es el mismo principio que ya cumplían los cruces del
   Panorama con .titular, bajado a la escala de una sección común. */
.slead{
  font-size:var(--t-body);line-height:var(--lh-2);color:var(--ink-2);margin-bottom:var(--sp-4);
}
.slead b{font-weight:600;color:var(--ink)}
.slead .mal{color:var(--alerta);font-weight:600}

.note{color:var(--muted);font-size:var(--t-meta);line-height:var(--lh-1)}
.hr{height:1px;background:var(--line-soft);margin:var(--sp-6) 0}


/* ═══════════════ ESCRITORIO: usar el ancho ══════════════════════════
   Hasta acá la app era UNA columna de 680px, centrada, en cualquier
   pantalla. En un monitor de 1440px eso son 680px de contenido y 760 de
   nada, y todo el material apilado en un scroll único — que es
   exactamente lo que se ve: bloque, caja, bloque, caja, scroll.

   Los tres archivos de referencia hacen lo contrario: rejilla. El gráfico
   grande a la izquierda y dos tarjetas de KPI apiladas a la derecha, y
   recién debajo la tabla. La información se ordena en el ESPACIO, no en
   una fila india vertical.

   Y hay un segundo motivo, que no es de estética: la pasada 4 midió que
   la medida de línea estaba invertida —las notas a 12,5px corrían 92
   caracteres, por encima del techo de Butterick— justamente porque una
   columna de 680px es demasiado ancha para el texto chico. En dos
   columnas cada una queda en ~530px, o sea ~70 caracteres. **La rejilla
   arregla la medida de línea de paso.**

   Qué ocupa las dos columnas: lo que encabeza o resume (el encabezado, el
   índice, el guion, los KPI, las notas de diseño). El resto fluye. */
@media (min-width:1180px){
  :root{--measure:1400px}
  .view.on{
    display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
    gap:0 var(--sp-7);align-items:start;
  }
  .view.on > .phead,
  .view.on > .snav,
  .view.on > .guion,
  .view.on > .kpis,
  .view.on > .cmp,
  .view.on > .wm,
  .view.on > .search,
  .view.on > .fchips,
  .view.on > .bhead,
  .view.on > .btn,
  .view.on > #cli-wrap,
  .view.on > .btn-line,
  .view.on > .hr,
  .view.on > .gpan,
  .view.on > .sec.ancho{grid-column:1 / -1}
  /* Un grupo de Panorama es un envoltorio, no una seccion: si se quedara
     en una celda, las cinco secciones de «Como venis» se dibujarian en
     media pantalla con la otra media vacia. Ocupa el ancho y reparte sus
     propias secciones con la misma rejilla de dos columnas. */
  .gpan{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 var(--sp-7);align-items:start}
  /* Sin esto, hidden=true no oculta nada: el display:grid de arriba le gana
     al display:none del user-agent, y Panorama pasaba de 2,16 a 6,63
     pantallas dibujando los cuatro grupos a la vez. Es el mismo tropiezo
     que ya estaba anotado en `.mtop .ico[hidden]`. */
  .gpan[hidden]{display:none}

  /* ── Los flujos lineales NO son rejilla ──────────────────────────
     `Dictar` se dibujaba con la misma rejilla de dos columnas que las
     vistas de analisis, y el resultado era la pantalla mas rota de la
     app en escritorio: el microfono caia en la columna izquierda,
     «o escribilo» flotaba solo en la derecha 200px mas abajo, y
     quedaban ~600px verticales vacios. Justo la pantalla del flujo de
     captura —la de la metrica de 20 segundos y la que se demuestra en
     vivo— era la unica que no se podia mostrar.

     Dictar, Procesar y Perfil son secuencias de pasos: tienen UNA
     columna por definicion, y angosta, porque un formulario de 1400px
     de ancho obliga a barrer la cabeza de un lado al otro por cada
     campo. */
  .view.on[data-v="dictar"],
  .view.on[data-v="procesar"],
  .view.on[data-v="perfil"]{display:block;max-width:640px;margin-inline:auto}
  .gpan > .sec.ancho,.gpan > .wm,.gpan > .hr,
  /* Los KPI, el resumen de titulares y las pestañas del grupo cruzan el
     ancho: `.view.on > .kpis` ya lo hacia, pero desde que el Resumen vive
     adentro de un `.gpan` dejaron de ser hijos de la vista y caian en una
     sola celda, con media pantalla vacia al lado. */
  .gpan > .kpis,.gpan > .hall-top,.gpan > .hall-resto,.gpan > .fchips{grid-column:1 / -1}
  .gpan > .sec:nth-child(-n+2){margin-top:var(--sp-5)}
  /* En rejilla, la primera sección de cada columna no puede llevar el
     margen que la separaba de la anterior: no hay anterior. */
  .view.on > .sec:nth-child(-n+3){margin-top:var(--sp-5)}
  .kpis{grid-template-columns:repeat(4,minmax(0,1fr))}

  /* ── La rejilla de tarjetas, y el hueco que vino a tapar ──────────
     La rejilla de la vista reparte SECCIONES, no contenido: cada sección
     es un ítem atómico que se coloca en una celda. En una vista con una
     sección dominante —Clientes, Compras, el Resumen de Panorama— eso
     dibuja una cinta angosta con un agujero al lado. Medido a 1920px
     antes de este cambio: **Clientes dejaba 5621px de columna derecha
     vacía**, Compras 2166px, Configuración 679px. La app usó el ancho
     para el 20% de su contenido y lo desperdició para el otro 80%.

     `.sec.ancho` hace que la sección ocupe las dos columnas, y `.rejilla`
     reparte SUS TARJETAS en tantas columnas como entren. El orden de
     lectura es en Z —izquierda a derecha, fila por fila— y no en
     serpentina como haría `column-count`, que es lo correcto cuando la
     lista viene ordenada por prioridad: los primeros siguen arriba.

     340px es el mínimo por el que una tarjeta de cliente sigue siendo
     legible con nombre + evidencia. Por debajo de eso `auto-fill` deja
     una sola columna, que es exactamente el comportamiento que se
     quiere en pantallas chicas. */
  /* `align-items:start` dejaba el borde inferior de cada fila en diente
     de sierra: medido a 1440px, una fila de Hoy daba altos 113/89/65 —
     48px de diferencia— y una de Compras hasta 60px. Con `stretch` las
     tarjetas de una misma fila miden lo mismo y la rejilla se lee como
     rejilla. El contenido se ancla arriba dentro de la tarjeta, asi que
     el aire sobrante cae abajo, que es donde no molesta. */
  .rejilla{
    display:grid;grid-template-columns:repeat(auto-fill,minmax(340px,1fr));
    gap:0 var(--sp-5);align-items:stretch;
  }
  .rejilla > .row{display:flex;flex-direction:column;align-items:stretch}
  /* Y el pie de metadatos se va al fondo: con tarjetas de alto parejo,
     los pies alineados entre si dan una linea de lectura horizontal que
     antes no existia. */
  .rejilla > .row > .row-sub{margin-top:auto;padding-top:var(--sp-3)}
  /* Las de prosa necesitan más ancho: una frase de 90 caracteres en una
     columna de 340px se parte en cuatro renglones. */
  .rejilla.prosa{grid-template-columns:repeat(auto-fill,minmax(430px,1fr))}
  /* Una lista ALFABETICA se lee hacia abajo, no en zigzag. `column` reparte
     por columna y `--filas` fija cuantas entran en cada una. */
  .rejilla.encolumna{grid-auto-flow:column;grid-template-rows:repeat(var(--filas,6),auto);grid-template-columns:repeat(3,minmax(0,1fr))}
  /* En una columna angosta, el encabezado de la fila deja de entrar en
     un renglón: la píldora de estado («lo fuiste a ver · recuperaste la
     venta») empujaba el nombre del cliente a partirse en tres líneas.
     Que baje la píldora, no el nombre — el nombre es por lo que la
     tarjeta se reconoce de un vistazo. */
  .rejilla .row-top{flex-wrap:wrap}

  /* ── La medida de línea no se estira con la pantalla ─────────────
     La rejilla de dos columnas existía en parte para arreglar la medida
     de línea (la pasada 4 midió 92 caracteres, por encima del techo de
     Butterick). Al crecer `--measure` y al aparecer secciones que ocupan
     el ancho entero, ese arreglo se perdía por donde entró: un lead a
     1330px corre ~180 caracteres. El tope va en `ch`, que es la unidad
     que mide justo eso. */
  .view.on > .wm,
  .sec.ancho > .slead,
  .sec.ancho > .note,
  .sec.ancho > .titular,
  .guion-l > span:last-child{max-width:74ch}
}
/* Tercera columna de TARJETAS (no de secciones) en monitores grandes. La
   rejilla de la vista sigue en dos: tres columnas de secciones romperían
   el orden de lectura de la Ficha, que es un briefing que se lee seguido.
   Lo que sí escala bien es la cantidad de tarjetas por fila, y eso lo
   resuelve solo `auto-fill` con más ancho disponible. */
@media (min-width:1560px){
  :root{--measure:1640px}
}
/* Entre 880 y 1180 sigue siendo una columna, pero mas ancha que 680: a esa
   altura la rejilla dejaria columnas de 400px, que para una fila con nombre
   de cliente y evidencia es angosto. */
@media (min-width:881px) and (max-width:1179px){
  :root{--measure:880px}
}


.tabbar{display:none}

/* ═══════════════ TACTO ═══════════════════════════════════════════════
   Lo que mas delataba que esto era una maqueta y no una app: **nada
   respondia al dedo.** Se tocaba una fila de cliente y no pasaba
   absolutamente nada hasta que la pantalla siguiente terminaba de
   dibujarse. En un telefono eso se lee como que la app se colgo, y es
   la razon por la que uno vuelve a tocar el mismo boton.

   La respuesta va en 110ms (`--mov-1`), que es el techo de lo que se
   percibe como "instantaneo pero visible". Se anima OPACIDAD, COLOR y
   ESCALA — nunca alto, ancho ni margen: la escala no saca al elemento
   del flujo, asi que el contenido de al lado no se mueve. Es la regla
   de `pro-rules.md` (stable interaction states) y ademas es lo unico
   que el navegador puede componer sin recalcular la pagina.

   `:active` y no `:hover`: en un telefono no existe el hover, y las
   reglas de hover que ya estaban se quedan pegadas despues del toque
   —el famoso "boton que queda iluminado"— hasta que tocas otra cosa. */
.row,.chip,.fchip,.snav-i,.hall,.tab,.kv .btn,.rail-si{
  -webkit-tap-highlight-color:transparent;
  touch-action:manipulation;
}
.btn:active,.rail-cta:active,.fab:active{transform:scale(.97)}
.row:active,.hall:active{transform:scale(.99);background:var(--hover)}
.fchip:active,.chip:active,.snav-i:active,.rail-si:active{opacity:.7}
.tab:active{opacity:.6}
.btn,.row,.hall,.fchip,.chip,.snav-i,.rail-si,.tab,.fab{
  transition:transform var(--mov-1) var(--curva),
             opacity var(--mov-1) var(--curva),
             background var(--mov-1) var(--curva),
             color var(--mov-1) var(--curva),
             border-color var(--mov-1) var(--curva);
}
/* La hoja modal y su velo, con la escala de movimiento en vez de los
   .18s/.2s escritos a mano que tenian antes. Entra con la curva que
   frena; el velo la acompaña. */
.ov{transition:opacity var(--mov-2) var(--curva)}
.sheet{transition:transform var(--mov-3) var(--curva)}

/* ═══════════════ RESPONSIVE ═══════════════ */
@media (max-width:880px){
  /* El índice de pantalla se pega debajo de la barra superior y los
     destinos del índice reservan ese alto con scroll-margin-top, así
     que el token y la barra tienen que ser el MISMO número.

     Antes el token declaraba el alto que se esperaba (67px = 44 del
     botón + 22 de padding + 1 de borde) y la barra lo conseguía por
     suma de sus partes. Eran dos constantes paralelas, y se
     desincronizaron en cuanto el espaciado paso a la escala: la barra
     medía 69px y el token seguía diciendo 67. Ahora el token ES la
     altura —`height:var(--mtop)`— y no puede desincronizarse. */
  :root{--mtop:68px}
  .rail{display:none}
  /* La barra respeta el área segura de arriba: en un teléfono con
     muesca, `env(safe-area-inset-top)` es la franja que se come la
     cámara, y sin esto el título y la flecha de volver quedan debajo.
     Vale 0 en un navegador de escritorio, así que no cambia nada acá.
     El token `--mtop` sigue siendo el alto ÚTIL de la barra —el que el
     scroll-margin de los destinos tiene que compensar— y el área segura
     se suma aparte, para que no haya dos constantes que puedan
     desincronizarse (el bug que ya pasó una vez con este mismo token). */
  .mtop{
    display:flex;align-items:center;gap:var(--sp-3);position:sticky;top:0;z-index:40;
    height:calc(var(--mtop) + env(safe-area-inset-top,0px));box-sizing:border-box;
    padding:env(safe-area-inset-top,0px) var(--sp-5) 0;
    background:var(--paper);border-bottom:1px solid transparent;
    transition:border-color var(--mov-2) var(--curva),box-shadow var(--mov-2) var(--curva);
  }
  /* Elevación al desplazarse, no siempre. Una línea fija bajo la barra
     divide la pantalla incluso cuando no hay nada arriba que separar;
     la sombra aparece cuando el contenido de verdad pasa por debajo, y
     entonces sí está diciendo algo. */
  body.compacto .mtop{border-bottom-color:var(--line-soft);box-shadow:var(--sombra-2)}
  .mtop .t{font-weight:600;font-size:var(--t-body);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
    transition:opacity var(--mov-1) var(--curva)}
  .mtop .ico{width:40px;height:40px;display:flex;align-items:center;justify-content:center;border-radius:var(--r-2);margin-left:calc(-1 * var(--sp-3))}
  /* Sin esto, hidden=true no oculta nada: display:flex de arriba le gana
     al display:none que el user-agent aplica a [hidden]. */
  .mtop .ico[hidden]{display:none}
  .mtop .ico:hover{background:var(--hover)}
  .col-in{padding:var(--sp-5) var(--sp-5) calc(var(--tabbar) + var(--sp-8))}
  .ptitle,.bname{font-size:var(--t-titular)}
  .tabbar{
    display:flex;position:fixed;left:0;right:0;bottom:0;height:var(--tabbar);z-index:50;
    background:var(--paper);border-top:1px solid var(--line);align-items:center;
    justify-content:space-around;padding-bottom:env(safe-area-inset-bottom);
  }
  .tab{display:flex;flex-direction:column;align-items:center;gap:var(--sp-1);font-size:var(--t-meta);font-weight:500;color:var(--muted-2);min-width:56px;padding:var(--sp-2) var(--sp-3)}
  .tab.on{color:var(--ember-tx);font-weight:600}
  .fab{
    width:50px;height:50px;border-radius:50%;background:var(--ember);color:var(--sobre-ember);
    display:flex;align-items:center;justify-content:center;position:relative;top:-14px;
    /* mismo leftover que `.mic`, mismo arreglo — ver su comentario */
    box-shadow:0 8px 22px rgba(133,37,157,.38);
  }
  .fab-l{position:relative;top:-11px;font-size:var(--t-meta);font-weight:600;color:var(--ember-tx)}
  #toasts{bottom:calc(var(--tabbar) + 16px)}

  /* ── Objetivos táctiles ──────────────────────────────────────────
     Se usa parado en la calle y con una mano. Los controles grandes
     crecen a 44px de verdad; las píldoras chicas conservan su tamaño
     visual y expanden el área de toque con un pseudo-elemento, que es
     la técnica correcta para no engordar la interfaz. Los gaps suben
     a 10px para que dos áreas expandidas no se pisen.              */
  /* `.btn.sm` gana por especificidad a `.btn`, asi que hay que nombrarlo:
     sin esto los «Leerlo» y los «Ya esta» quedaban en 32px. */
  .btn,.btn.sm,.pick button,.hall{min-height:44px}
  .btn,.pick button{min-width:44px}
  .mtop .ico{width:44px;height:44px}
  .acts{gap:var(--sp-3)}
  .fchips{gap:var(--sp-3)}
  .fchip,.why-tgl{min-height:44px}
  /* El encabezado de pantalla es `space-between`: en escritorio el titulo
     a la izquierda y la accion a la derecha entran holgados, pero en 390px
     la accion se comprime hasta partirse en tres renglones y de paso
     angosta el subtitulo. En telefono se apila, y la accion cruza el ancho
     — que ademas es donde el pulgar la alcanza. */
  .phead{flex-direction:column;align-items:stretch;gap:var(--sp-4)}
  .phead > .btn{width:100%}
  /* Dos controles de vuelta a 100px uno del otro: la flecha de la barra
     superior y este link. En telefono gana la barra —esta siempre a la
     misma altura del pulgar— y el link se esconde. En escritorio no hay
     barra, asi que el link es la unica vuelta y se queda. */
  .volver{display:none}
  /* ── Las pestañas: una fila que se desliza, no dos que envuelven ────
     Esto contradice a propósito lo que decía acá antes («envuelven, así
     que no hay carrusel que sangrar contra el borde»), y el motivo es
     que se vio en la captura: en Hoy los cuatro rótulos con sus conteos
     miden ~520px sobre 390 de pantalla, así que «Comprobantes» caía
     solo en una segunda línea. Costo medido: ~65px de la pantalla más
     escasa que hay, y el aspecto de formulario sin terminar que es
     justo lo que delata una maqueta.

     Ahora es una tira de una sola línea, con desplazamiento por pulgar,
     `scroll-snap` y un degradé en el borde derecho —que sólo aparece si
     de verdad hay algo más allá, lo pone `pintarIndice`— para que se
     vea que sigue. Es lo que la guía de navegación móvil habilita para
     pestañas: deslizables si los rótulos son cortos.

     Y es deliberadamente DISTINTO de lo que hacen los filtros unas
     líneas más abajo, que siguen envolviendo: esconder una píldora de
     filtro esconde un valor que el usuario no sabe que existe, y eso sí
     está desaconsejado. Navegar se desliza; filtrar se ve entero. */
  .snav{
    flex-wrap:nowrap;overflow-x:auto;overscroll-behavior-x:contain;
    scroll-snap-type:x proximity;gap:0 var(--sp-6);scrollbar-width:none;
  }
  .snav::-webkit-scrollbar{display:none}
  .snav.desliza{
    -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 32px),transparent);
    mask-image:linear-gradient(90deg,#000 calc(100% - 32px),transparent);
  }
  .snav-i{min-height:44px;flex:none;scroll-snap-align:start;white-space:nowrap}
  /* Siete zonas como pestañas son cuatro filas y ~176px antes del primer
     cliente, sobre una pantalla de 844. En el telefono la pestaña de zona
     va sin conteo: el numero que importa —cuantos hay de cada estado en
     esa zona— lo dice la pildora de abajo, y decirlo dos veces cuesta una
     fila entera. En escritorio el conteo se queda, que ahi sobra ancho. */
  #cli-t{gap:0 var(--sp-5)}
  #cli-t .n{display:none}
  .slabel .act,.link,details.more > summary{min-height:44px;display:inline-flex;align-items:center}
  details.more > summary{display:flex}
  .sh-head .btn{min-height:44px}
}

/* ── Alto compacto: el teléfono acostado ──────────────────────────────
   El único corte del archivo era de ancho, a 880px. Un teléfono en
   horizontal entra por ese corte como «mobile» y recibe las tres barras
   dimensionadas para 844px de alto. Medido: 189px de cromo sobre 390px
   de pantalla — el 48% — con relación contenido/cromo de 1,06:1. NN/g
   ya llama mal diseñado a 2:1; acá hay casi tanto cromo como contenido.
   Es la clase height-compact de Material (<480dp de alto), que el
   archivo no tenía en ninguna forma.

   Tres recortes, y ninguno toca los objetivos táctiles de 44px:
     · Las pestañas ya no son pegajosas en ningún tamaño desde que
       dejaron de ser un índice: se leen una vez, se elige, y lo que
       queda debajo es una sección sola. Acá sólo se les recorta el aire.
     · La barra superior baja de 67px a 57px sacando padding, no altura
       de botón: el .ico sigue midiendo 44px.
     · La barra inferior baja de 60px a 48px, todavía por encima de 44.
   Cromo: 189px → 105px. Relación contenido/cromo: 1,06:1 → 2,71:1. */
@media (max-width:880px) and (max-height:480px){
  :root{--mtop:52px;--tabbar:48px}
  .snav{margin-bottom:var(--sp-5)}
  .col-in{padding-top:var(--sp-4)}
  /* Sin índice pegado, los 62px que reservaban los destinos sobran:
     dejarían al título saltado flotando a media pantalla. */
  html{scroll-padding-top:calc(var(--mtop) + var(--sp-3))}
  [data-sec],.sec-plegada > summary{scroll-margin-top:calc(var(--mtop) + var(--sp-3))}
}
