/* ==========================================================
   parts.css — componentes del sistema Fern
   ==========================================================

   Extraído VERBATIM de fuentes/Reference/fern-design-system.html. Donde este
   archivo y la referencia no coincidan, la referencia manda: es implementación
   viva, no documentación.

   Depende de tokens.css y base.css. No define ni un color ni un radio propios.

   ---------------------------------------------------------------------------
   NOTA DE LA SEGUNDA EXTRACCIÓN

   La primera versión de este archivo estaba INCOMPLETA y el proyecto se
   construyó tres fases con botones y campos sin estilo. El motivo: el script
   partía el CSS en bloques sin quitar antes los comentarios, así que la "cabeza"
   de toda regla precedida por un comentario de sección quedaba como
   la cabecera de un comentario de sección seguida del selector, y el parser de
   selectores devolvía None. La regla se descartaba EN SILENCIO.

   Se perdieron exactamente las primitivas: .btn, .card, .in, .f, .pill y .rows.
   Los tests del sistema de diseño no lo vieron porque verifican que no haya
   colores fuera de tokens ni :hover suelto — no que las reglas EXISTAN.
   Ahora hay un test que verifica que estén.

   Esta versión trae los componentes completos, incluidos la barra de filtros y
   las líneas de log (§8 y §9) y las primitivas de gráfica (§7), que las Fases
   6b y 9 van a usar. Descartarlos por prefijo fue lo que rompió la primera vez.

   TRES desvíos respecto de la referencia, y los tres son porque Fern viola sus
   propias reglas:
     · cuatro `#fff` literales pasaron a var(--onaccent)
     · `.seg i` animaba `width` además de transform
     · `.barfill` y `.gauge i` animaban `width`: ahora usan
       `transform: scaleX(var(--fill))`, que hace lo mismo sin disparar layout
       en cada frame. Quien las use debe fijar `--fill` (0 a 1), no `width`.
   ========================================================== */


.h1{font-size:var(--f30);font-weight:700;letter-spacing:-.03em;line-height:1.15}

.h2{font-size:var(--f24);font-weight:700;letter-spacing:-.03em;line-height:1.2}

.h3{font-size:var(--f17);font-weight:600;letter-spacing:-.02em;margin:var(--s8) 0 var(--s3)}

.h3:first-child{margin-top:0}

.h4{font-size:var(--f14);font-weight:600;letter-spacing:-.01em}

.lead{color:var(--ink2);font-size:var(--f15);max-width:66ch;margin-top:var(--s3)}

.txt{color:var(--ink2);font-size:var(--f14);max-width:72ch;margin-top:var(--s3)}

/* Lo que emite `services/manualTexto` — el manual, el acta de una reunión y las
   notas de una actividad. Vive acá y no en `manual.css` porque una pantalla
   nueva que use ese renderizador no tiene por qué acordarse de cargar una hoja
   aparte: olvidarlo no da error, las viñetas salen como renglones sueltos.
   La MEDIDA DE LECTURA sí se queda en `manual.css`, que es de ese documento. */
.pasos,.vinetas{padding-left:0;list-style:none;display:grid;gap:var(--s3)}
.pasos{counter-reset:paso}
.pasos>li,.vinetas>li{position:relative;padding-left:var(--s7);color:var(--ink2);font-size:var(--f14)}

/* El número va DIBUJADO y no como marcador de lista: así la segunda línea de un
   paso largo alinea con la primera en vez de meterse debajo del número. */
.pasos>li::before{counter-increment:paso;content:counter(paso);position:absolute;left:0;top:0;
  width:22px;height:22px;border-radius:var(--rp);background:var(--acc-wash);color:var(--acc-text);
  font-size:var(--f12);font-weight:700;display:grid;place-items:center}

.vinetas>li::before{content:"";position:absolute;left:8px;top:9px;width:5px;height:5px;
  border-radius:var(--rp);background:var(--ink3)}


.eyebrow{font-size:var(--f13);font-weight:600;color:var(--acc-text)}

.muted{color:var(--ink3);font-size:var(--f13)}

.grid{display:grid;gap:var(--s3)}

.g2{grid-template-columns:1fr}

.g3{grid-template-columns:1fr}

.row{display:flex;flex-wrap:wrap;gap:var(--s3);align-items:center}



.card{background:var(--card);border:1px solid var(--line-soft);border-radius:var(--rl);box-shadow:var(--sh1)}

.card__top{display:flex;align-items:center;gap:var(--s3);padding:var(--s4) var(--s5);
  border-bottom:1px solid var(--line-soft)}

.card__b{padding:var(--s5)}

.card__foot{padding:var(--s4) var(--s5);border-top:1px solid var(--line-soft);font-size:var(--f13);
  color:var(--ink2);background:var(--inset);border-radius:0 0 var(--rl) var(--rl)}

.note{display:grid;gap:8px;justify-items:start;padding:var(--s4) var(--s5);border-radius:var(--rm);
  background:var(--inset);border:1px solid var(--line-soft);font-size:var(--f14);color:var(--ink2)}

.note--acc{background:var(--acc-wash);border-color:var(--acc-line)}

.note--att{background:var(--att-wash);border-color:var(--att-line)}

.note--bad{background:var(--bad-wash);border-color:var(--bad-line)}

.note b{color:var(--ink);font-weight:600}

.stamp{display:inline-flex;align-items:center;height:22px;padding:0 10px;border-radius:var(--rp);
  background:var(--ink);color:var(--card);font-size:var(--f12);font-weight:600}

.stamp--acc{background:var(--acc);color:var(--onaccent)}

.stamp--att{background:var(--att-face);color:var(--onaccent)}

.stamp--bad{background:var(--bad-face);color:var(--onaccent)}

.list>li{display:grid;gap:3px;padding:var(--s4) 0;border-bottom:1px solid var(--line-soft)}

.list>li:last-child{border-bottom:0}

.list .t{font-size:var(--f14);font-weight:600}

.list .d{font-size:var(--f14);color:var(--ink2)}

.list .k{font-family:var(--fm);font-size:var(--f12);color:var(--acc-text)}



.btn{--bg:transparent;--fg:var(--ink);--bd:transparent;
  position:relative;display:inline-flex;align-items:center;justify-content:center;gap:8px;
  height:var(--ctl);padding:0 18px;border:1px solid var(--bd);background:var(--bg);color:var(--fg);
  border-radius:var(--rp);font-size:var(--f14);font-weight:600;letter-spacing:-.01em;cursor:pointer;
  white-space:nowrap;user-select:none;
  transition:background-color var(--tq) linear,border-color var(--tq) linear,color var(--tq) linear,
             box-shadow var(--tm) var(--ease),transform var(--tq) var(--ease)}

.btn:active:not(:disabled){transform:scale(.97)}

.btn:disabled{opacity:.45;cursor:not-allowed}

/* El botón principal usa el COLOR DE ACCIÓN de la firma si lo configuró, y si
   no, el derivado del color de marca. El `var(--x, respaldo)` es lo que hace que
   una firma que no toca nada siga viéndose igual que siempre.
   El texto lo calcula el servidor —blanco o tinta, el que más contraste dé—
   porque un verde claro con letras blancas es un botón que no se lee, y esa
   decisión no debería depender de quién elige el color. */
.btn--main{--bg:var(--cta,var(--acc));--fg:var(--cta-fg,var(--onaccent));
  --bd:var(--cta,var(--acc));box-shadow:var(--sh1)}

/* El botón secundario. Lleva relleno Y borde de control, y las dos cosas
   importan: el relleno lo separa de la página —era blanco sobre blanco en claro
   y oscuro sobre oscuro en oscuro— y el borde es lo que lo declara tocable, con
   el 3:1 que WCAG pide para el contorno de un control. La sombra sola no
   alcanzaba: a 1.04 de contraste no hay sombra que salve nada. */
.btn--soft{--bg:var(--ctl-bg);--bd:var(--line-ctl);box-shadow:var(--sh1)}

.btn--bare{--fg:var(--ink2)}

.btn--warn{--bg:var(--bad-face);--fg:var(--onaccent);--bd:var(--bad-face)}

.btn--sm{height:32px;padding:0 14px;font-size:var(--f13)}

.btn--wide{width:100%}

.btn--round{width:var(--ctl);padding:0}

.btn--round.btn--sm{width:32px}

.btn.busy{color:transparent!important;pointer-events:none}

.btn.busy::after{content:"";position:absolute;width:15px;height:15px;border-radius:var(--rp);
  border:2px solid var(--fg);border-top-color:transparent;animation:spin 640ms linear infinite}

@keyframes spin{to{transform:rotate(360deg)}}



.f{display:grid;gap:6px;min-width:0}

.f__l{font-size:var(--f14);font-weight:600}

.f__h{font-size:var(--f13);color:var(--ink3)}

.f__e{font-size:var(--f13);color:var(--bad);display:flex;gap:6px;align-items:center}

.in,.ta{height:var(--ctl);width:100%;padding:0 14px;background:var(--card);color:var(--ink);
  border:1px solid var(--line-firm);border-radius:var(--rs);
  transition:border-color var(--tq) linear,box-shadow var(--tm) var(--ease)}

.ta{height:auto;min-height:84px;padding:11px 14px;resize:vertical;line-height:1.55;border-radius:var(--rm)}

.in::placeholder,.ta::placeholder{color:var(--ink3)}

.in:focus,.ta:focus{outline:0;border-color:var(--acc);box-shadow:var(--ring)}

.in[aria-invalid="true"]{border-color:var(--bad-face)}

.step{display:inline-flex;align-items:center;background:var(--card);border:1px solid var(--line-firm);
  border-radius:var(--rp);padding:3px}

.step button{width:34px;height:34px;border:0;border-radius:var(--rp);background:transparent;cursor:pointer;
  color:var(--ink2);display:grid;place-items:center;font-size:var(--f17);
  transition:background-color var(--tq) linear,color var(--tq) linear}

.step b{min-width:104px;text-align:center;font-weight:600;font-variant-numeric:tabular-nums}

.step b small{font-weight:400;color:var(--ink3);font-size:var(--f13)}

.tog{display:flex;align-items:center;gap:12px;cursor:pointer}

.tog input{appearance:none;margin:0;flex:none;width:44px;height:26px;border-radius:var(--rp);
  background:var(--w5);position:relative;cursor:pointer;transition:background-color var(--tm) var(--ease)}

.tog input::after{content:"";position:absolute;top:3px;left:3px;width:20px;height:20px;border-radius:var(--rp);
  background:var(--onaccent);box-shadow:var(--sh1);transition:transform var(--tm) var(--ease)}

.tog input:checked{background:var(--acc)}

.tog input:checked::after{transform:translate3d(18px,0,0)}

.seg{position:relative;display:inline-flex;padding:4px;background:var(--inset);
  border:1px solid var(--line-soft);border-radius:var(--rp);
  /* Nunca más ancho que quien lo contiene, y si no cabe, desliza ADENTRO.
     Sin esto, un `.seg` con seis filtros medía 690px en un teléfono de 393 y
     arrastraba la página entera: el navegador la achicaba para que cupiera y
     TODA la pantalla se veía diminuta. Se encontró con un teléfono emulado, no
     con una ventana angosta — una ventana angosta no reproduce eso.
     Es la excepción que la regla de «el cuerpo nunca hace scroll horizontal»
     contempla: el desborde se resuelve dentro del componente, no en la página. */
  max-width:100%;overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.seg::-webkit-scrollbar{display:none}
/* Los hijos no se encogen: encogerlos parte las etiquetas en dos líneas y el
   control queda más alto que el resto de la fila. */
.seg > *{flex:none}

.seg i{position:absolute;top:4px;bottom:4px;left:4px;background:var(--card);border-radius:var(--rp);
  box-shadow:var(--sh2);transition:transform var(--tm) var(--ease);will-change:transform}

.seg button{position:relative;z-index:1;border:0;background:transparent;cursor:pointer;height:32px;padding:0 16px;
  border-radius:var(--rp);font-size:var(--f13);font-weight:600;color:var(--ink3);transition:color var(--tm) linear}

.seg button[aria-checked="true"]{color:var(--ink)}



.tiles{display:grid;gap:12px;grid-template-columns:1fr}

.tile{position:relative;text-align:left;background:var(--card);border:1px solid var(--line);
  border-radius:var(--rm);cursor:pointer;overflow:hidden;
  transition:background-color var(--tq) linear,border-color var(--tq) linear,box-shadow var(--tm) var(--ease)}

.tile__hd{display:flex;align-items:flex-start;gap:12px;padding:14px 16px}

.tile__mk{flex:none;width:20px;height:20px;margin-top:1px;border-radius:var(--rp);border:1px solid var(--line-firm);
  display:grid;place-items:center;color:transparent;
  transition:background-color var(--tm) var(--ease),border-color var(--tm) var(--ease),color var(--tm) var(--ease)}

.tile__c{min-width:0;display:grid;gap:2px}

.tile__t{font-size:var(--f14);font-weight:600}

.tile__d{font-size:var(--f13);color:var(--ink3);line-height:1.45}

.tile__row{display:flex;flex-wrap:wrap;gap:16px;padding:10px 16px;border-top:1px solid var(--line-soft);
  background:var(--inset);font-size:var(--f13);color:var(--ink3)}

.tile__row b{font-weight:600;color:var(--ink2);font-variant-numeric:tabular-nums}

.tile[aria-checked="true"]{border-color:var(--acc);box-shadow:inset 0 0 0 1px var(--acc)}

.tile[aria-checked="true"] .tile__hd{background:var(--acc-wash)}

.tile[aria-checked="true"] .tile__d{color:var(--ink2)}

.tile[aria-checked="true"] .tile__mk{background:var(--acc);border-color:var(--acc);color:var(--onaccent)}

.tile[aria-checked="true"] .tile__row{background:var(--acc-wash);border-top-color:var(--acc-line)}



.stats{display:grid;gap:12px;grid-template-columns:1fr}

.stat{background:var(--card);border:1px solid var(--line-soft);border-radius:var(--rm);overflow:hidden}

.stat__hd{padding:14px 16px 12px;display:grid;gap:4px}

.stat__l{display:flex;align-items:center;gap:8px;font-size:var(--f13);color:var(--ink3)}

.stat__v{font-size:var(--f28);font-weight:700;letter-spacing:-.03em;font-variant-numeric:tabular-nums;line-height:1.1}

.stat__row{display:flex;flex-wrap:wrap;gap:14px;padding:9px 16px;border-top:1px solid var(--line-soft);
  background:var(--inset);font-size:var(--f13);color:var(--ink3)}

.stat__row b{font-weight:600;color:var(--ink2);font-variant-numeric:tabular-nums}

.delta{display:inline-flex;align-items:center;gap:4px;height:20px;padding:0 8px;border-radius:var(--rp);
  font-size:var(--f12);font-weight:600;background:var(--inset);color:var(--ink2)}

.delta--up{background:var(--acc-wash2);color:var(--acc-text)}

.delta--dn{background:var(--bad-wash);color:var(--bad)}



.rows{border:1px solid var(--line-soft);border-radius:var(--rl);background:var(--card);overflow:hidden}
/* Lista larga dentro de una hoja: se desplaza ella, no la hoja. Sin esto, 34
   clientes empujan el botón de guardar fuera de la pantalla. */
.rows--scroll{max-height:min(46vh,340px);overflow-y:auto;overscroll-behavior:contain}
.fopt__vacio{padding:12px 14px;font-size:var(--f13);color:var(--ink3)}

.rowitem{display:flex;align-items:center;gap:14px;padding:14px 18px;border-bottom:1px solid var(--line-soft);
  transition:background-color var(--tq) linear}

.rowitem:last-child{border-bottom:0}

.rowitem__c{flex:1;min-width:0}

.rowitem__t{font-size:var(--f14);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.rowitem__d{font-size:var(--f13);color:var(--ink3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* LO QUE UNA PERSONA ESCRIBIÓ, que no es dato de apoyo y no puede ceder.

   `.rowitem__d` corta en UNA línea con puntos suspensivos — existe para lo que
   se va primero cuando no hay ancho, como el correo en la lista del equipo. Con
   la observación de un avance eso significaba que el texto NO SE PODÍA LEER
   COMPLETO POR NINGÚN CAMINO: estaba guardado entero y la pantalla mostraba
   «Se concilió el banco y quedó pendiente el extr…», sin manera de ver el
   resto. Lo reportó la firma el 06-11-2026, y el campo es obligatorio
   justamente para que alguien lo lea.

   `pre-wrap` porque el campo es un `textarea`: los renglones que alguien separó
   a mano son parte de lo que quiso decir. `overflow-wrap:anywhere` por lo mismo
   que `P.lineas` partiendo palabras en la pieza — un enlace o un NIT pegado se
   saldría de la fila. */
.rowitem__texto{font-size:var(--f13);color:var(--ink2);white-space:pre-wrap;overflow-wrap:anywhere;margin-top:var(--s1)}

/* Lo que CEDE primero cuando no hay ancho. En un teléfono el nombre es la
   identidad de la fila y el correo es dato de apoyo, así que el correo se va
   ANTES de que el nombre se corte. Sin esto, agregarle un segundo botón a la
   fila del equipo dejó las tres filas diciendo «G…», «Lid…» y «An…» en 393px:
   no da error, no rompe nada, y la pantalla deja de servir para lo único que
   hace, que es saber quién es quién.
   Va después del componente: misma especificidad, gana la última. */
@media (max-width:599px){ .rowitem__aux{display:none} }

.dotmark{width:30px;height:30px;border-radius:var(--rp);flex:none;display:grid;place-items:center;
  background:var(--inset);color:var(--ink3);font-size:var(--f13);font-weight:700}



.pill{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 12px;border-radius:var(--rp);
  background:var(--inset);color:var(--ink2);font-size:var(--f13);font-weight:600;border:1px solid transparent;
  white-space:nowrap}

.pill--on{background:var(--acc-wash2);color:var(--acc-text)}

.pill--att{background:var(--att-wash);color:var(--att)}

.pill--bad{background:var(--bad-wash);color:var(--bad)}

.pill--plain{background:transparent;border-color:var(--line);color:var(--ink3)}

.pill--sm{height:22px;padding:0 9px;font-size:var(--f12)}

.dot{width:7px;height:7px;border-radius:var(--rp);background:currentColor;flex:none}



.chart{position:relative;width:100%}

.chart svg{width:100%;height:auto;display:block;overflow:visible}

.chart .gl{stroke:var(--grid);stroke-width:1;vector-effect:non-scaling-stroke}

.chart .ax{fill:var(--ink3);font-size:11px;font-family:var(--ff)}

.chart .ln{fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;vector-effect:non-scaling-stroke}

.chart .hit{fill:transparent;cursor:crosshair}

.chart .cross{stroke:var(--ink3);stroke-width:1;stroke-dasharray:3 3;opacity:0;vector-effect:non-scaling-stroke}

.chart .knob{opacity:0}

.chart.live .cross,.chart.live .knob{opacity:1}

.ctip{position:absolute;pointer-events:none;background:var(--ink);color:var(--page);border-radius:var(--rm);
  padding:9px 12px;font-size:var(--f13);box-shadow:var(--sh3);opacity:0;
  transform:translate3d(-50%,-10px,0);transition:opacity var(--tq) linear;white-space:nowrap;z-index:2}

.chart.live .ctip{opacity:1}

.ctip b{display:block;font-size:var(--f12);opacity:.7;font-weight:400;margin-bottom:3px}

.ctip span{display:flex;align-items:center;gap:7px;font-variant-numeric:tabular-nums}

.ctip i{width:8px;height:8px;border-radius:var(--rp);flex:none}

.legend{display:flex;flex-wrap:wrap;gap:16px}

.legend span{display:flex;align-items:center;gap:7px;font-size:var(--f13);color:var(--ink2)}

.legend i{width:10px;height:10px;border-radius:var(--rp);flex:none}

.spark{width:88px;height:26px;flex:none}

.spark path{fill:none;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round;vector-effect:non-scaling-stroke}

.bars{display:grid;gap:10px}

.barrow{display:grid;grid-template-columns:104px 1fr 58px;gap:12px;align-items:center;font-size:var(--f13)}

.bartrack{height:10px;border-radius:var(--rp);background:var(--inset);overflow:hidden}

.barfill{height:100%;border-radius:var(--rp);width:100%;transform-origin:left center;
  transform:scaleX(var(--fill,0));transition:transform var(--ts) var(--ease)}

.barrow b{text-align:right;font-variant-numeric:tabular-nums;color:var(--ink2);font-weight:600}

.gauge{height:12px;border-radius:var(--rp);background:var(--inset);overflow:hidden;display:flex}

.gauge i{height:100%;flex:0 0 auto;min-width:2px}

/* CORRECCIÓN de la Fase 0b. Ahí se cambiaron `.barfill` y `.gauge i` de animar
   `width` a animar `transform`, porque Fern prohíbe animar propiedades de
   layout. Para `.barfill` estuvo bien: es UN relleno dentro de una pista, y
   escalarlo da el mismo resultado.

   Para `.gauge` estuvo MAL. Es una barra APILADA: los anchos de los segmentos
   son el dato y tienen que afectar el layout. Con `width:100%` en cada uno
   dentro de un flex, todos quedaban a ancho completo y `scaleX` los encogía
   visualmente sin ceder espacio — se pisaban unos a otros. Un gauge apilado se
   renderizaba roto y no había ninguna pantalla que lo usara para que se notara.

   La salida no es volver a animar `width`: es no animarlo. El ancho llega
   inline y no lleva transición, así que no se anima ninguna propiedad de layout
   y la regla se respeta igual.

   El `min-width:2px` es para que un segmento de 0.3% siga siendo visible en vez
   de desaparecer, y el gap de abajo es el separador de 2px que hace legible el
   límite entre dos segmentos de colores cercanos — que con esta paleta es
   justamente el problema a resolver. */
.gauge{gap:2px}
.gauge i:first-child{border-radius:var(--rp) 0 0 var(--rp)}
.gauge i:last-child{border-radius:0 var(--rp) var(--rp) 0}
.gauge i:only-child{border-radius:var(--rp)}

/* ==========================================================
   AVATAR
   ==========================================================
   La foto de una persona, o sus iniciales mientras no haya foto. Redondo y de
   tamaño fijo: una lista con avatares de alturas distintas se lee como
   desalineada aunque el texto esté perfecto.
   ========================================================== */
.avatar{display:grid;place-items:center;flex:none;
  width:32px;height:32px;border-radius:var(--rp);overflow:hidden;
  background:var(--inset);color:var(--ink2);
  font-size:var(--f12);font-weight:600;letter-spacing:.02em;
  user-select:none}

/* `object-fit:cover` y no `contain`: una foto de perfil se recorta al círculo,
   no se encoge dejando franjas. */
.avatar img{width:100%;height:100%;object-fit:cover;display:block}

.avatar--sm{width:24px;height:24px;font-size:var(--f12)}
.avatar--lg{width:72px;height:72px;font-size:var(--f24)}

/* Los cinco tonos de las iniciales salen de `--d1`..`--d5`, que Fern define como
   colores de SERIE — «none of them a state colour». Un avatar en verde o en rojo
   diría «al día» o «vencido», que es justo lo que no significa.
   El texto va en blanco: los cinco están medidos para llevarlo. */
.avatar--ini{color:var(--onaccent)}
.avatar--ini[data-tono="1"]{background:var(--d1)}
.avatar--ini[data-tono="2"]{background:var(--d2)}
.avatar--ini[data-tono="3"]{background:var(--d3)}
.avatar--ini[data-tono="4"]{background:var(--d4)}
.avatar--ini[data-tono="5"]{background:var(--d5)}

/* ==========================================================
   LA TIRA DE DÍAS DE LA AGENDA
   ==========================================================
   Una fila de días que se toca, con cuántas cosas tiene cada uno. Los conteos
   son la razón de ser: una tira que sólo dice «jue 10» obliga a entrar para
   saber si hay algo.
   ========================================================== */
.tira{border:1px solid var(--line-soft);border-radius:var(--rl);background:var(--card);
  margin-bottom:var(--s5);overflow:hidden}

.tira__top{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;
  padding:var(--s3) var(--s4);border-bottom:1px solid var(--line-soft)}

.tira__nav,.tira__anchos{display:flex;align-items:center;gap:var(--s2);flex:none}

/* Un botón que sólo lleva una flecha. */
.tira__flecha{min-width:36px;justify-content:center}

/* El chevrón, dibujado con dos bordes y un giro. Se hace con CSS y no con un
   carácter porque `←` solo, a 13px, son tres píxeles de asta y se lee como un
   guión — y porque así no depende de que la fuente traiga el glifo.
   El nombre accesible lo pone el `aria-label` del botón. */
.chev{display:block;width:7px;height:7px;flex:none;
  border-right:2px solid currentColor;border-bottom:2px solid currentColor}

.chev--izq{transform:rotate(135deg);margin-left:2px}
.chev--der{transform:rotate(-45deg);margin-right:2px}

/* Se desplaza SOLA en horizontal. Treinta días no entran en un celular, y la
   página nunca debe desplazarse en horizontal. */
.tira__dias{display:flex;gap:6px;padding:var(--s3) var(--s4);
  overflow-x:auto;overscroll-behavior-x:contain;scroll-snap-type:x proximity}

.tira__pie{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;
  padding:var(--s2) var(--s4) var(--s3);font-size:var(--f13);color:var(--ink3)}

/* Cada día. `min-width` y no `flex:1`: con siete días repartir el ancho está
   bien, con treinta cada celda quedaría de 12px — así todas miden lo mismo y la
   tira se desplaza. */
.tiradia{position:relative;flex:none;min-width:52px;scroll-snap-align:start;
  display:grid;justify-items:center;gap:2px;padding:8px 6px 10px;
  border:1px solid transparent;border-radius:var(--rm);
  text-decoration:none;color:var(--ink2);
  transition:background-color var(--tq) linear,border-color var(--tq) linear}

.tiradia__d{font-size:var(--f12);color:var(--ink3);text-transform:lowercase}

.tiradia__n{font-size:var(--f16);font-weight:600;color:var(--ink);
  font-variant-numeric:tabular-nums;line-height:1.1}

/* El conteo, con `tabular-nums` para que 9 y 11 no bailen de ancho. */
.tiradia__c{font-size:var(--f12);font-weight:600;line-height:1;
  padding:1px 6px;border-radius:var(--rp);
  background:var(--acc-wash);color:var(--acc-text);
  font-variant-numeric:tabular-nums}

/* El festivo se MARCA, no se esconde: es la decisión de la Fase 11 y vale igual
   acá. En 2026 Armenia puso un vencimiento de reteica sobre San José. */
.tiradia__f{position:absolute;top:3px;right:6px;line-height:1;
  color:var(--bad-face);font-weight:700}

.tiradia--fds .tiradia__n{color:var(--ink3)}

.tiradia--hoy{border-color:var(--acc-line)}

.tiradia--on{background:var(--acc);border-color:var(--acc)}
.tiradia--on .tiradia__n,.tiradia--on .tiradia__d{color:var(--onaccent)}
/* En la celda seleccionada el conteo se INVIERTE: pastilla blanca con el número
   en el color de acento. Con `--acc-wash2` encima de `--acc` la pastilla queda
   clara y el número blanco adentro no se lee — se veía como una mancha. */
.tiradia--on .tiradia__c{background:var(--onaccent);color:var(--acc)}

/* ==========================================================
   EL MINI CALENDARIO DEL MES
   ==========================================================
   Reusa la cuadrícula pura de la Fase 11. Un punto marca los días con algo.
   ========================================================== */
.minimes__nav{display:flex;align-items:center;gap:var(--s2);
  justify-content:center;margin-bottom:var(--s3)}

.minimes{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}

.minimes__h{display:grid;place-items:center;height:24px;
  font-size:var(--f12);font-weight:600;color:var(--ink3)}

.minimes__c{position:relative;display:grid;place-items:center;
  min-height:38px;border-radius:var(--rs);text-decoration:none;
  color:var(--ink);font-size:var(--f14);font-variant-numeric:tabular-nums;
  transition:background-color var(--tq) linear}

.minimes__c--fuera{pointer-events:none}
.minimes__c--fds{color:var(--ink3)}
.minimes__c--hoy{outline:1px solid var(--acc-line);outline-offset:-1px}
.minimes__c--on{background:var(--acc);color:var(--onaccent);font-weight:600}

/* El punto de «acá hay algo». Debajo del número, como en la referencia. */
.minimes__p{position:absolute;bottom:5px;width:4px;height:4px;border-radius:var(--rp);
  background:var(--acc)}

.minimes__c--on .minimes__p{background:var(--onaccent)}

/* ==========================================================
   TABLA DE INFORME — pieza propia, Fern no la trae
   ==========================================================
   La `.matriz` de la Fase 2 es otra cosa: 34 filas por 13 columnas con
   encabezados pegados y scroll horizontal. Esto es una tabla de informe: pocas
   columnas, todas numéricas menos la primera.

   Existe porque la tabla NO es opcional en esta fase. La paleta de Fern es
   deliberadamente apagada —sus colores de serie quedan bajo el piso de croma—
   así que la identidad no puede descansar en el color y hace falta la lectura
   numérica al lado. Es también el «tabular» que pide el módulo 11. */
.tablacard{background:var(--card);border:1px solid var(--line-soft);border-radius:var(--rm);
  overflow-x:auto;-webkit-overflow-scrolling:touch}
.tabla{width:100%;border-collapse:collapse;font-size:var(--f13)}
.tabla th{text-align:left;font-weight:600;color:var(--ink3);font-size:var(--f12);
  padding:var(--s3) var(--s4);border-bottom:1px solid var(--line);white-space:nowrap}
.tabla td{padding:var(--s3) var(--s4);border-bottom:1px solid var(--line-soft);color:var(--ink2)}
.tabla tbody tr:last-child td{border-bottom:0}
.tabla td:first-child{color:var(--ink);font-weight:500}
.tabla th.num,.tabla td.num{text-align:right;font-variant-numeric:tabular-nums}
/* Un número que exige atención. No es color solo: la columna se llama
   «Vencidas», así que el color refuerza una etiqueta que ya está. */
.tabla td.malo{color:var(--bad);font-weight:600}



.filter{display:grid;gap:12px}

.quick{display:flex;flex-wrap:wrap;gap:8px}

.qchip{display:inline-flex;align-items:center;gap:7px;height:34px;padding:0 14px;border-radius:var(--rp);
  border:1px solid var(--line);background:var(--card);color:var(--ink2);font-size:var(--f13);font-weight:600;
  cursor:pointer;transition:background-color var(--tq) linear,border-color var(--tq) linear,color var(--tq) linear}

.qchip[aria-pressed="true"]{background:var(--acc);border-color:var(--acc);color:var(--onaccent)}

.qchip small{font-weight:500;opacity:.7;font-variant-numeric:tabular-nums}

.fbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:8px;background:var(--card);
  border:1px solid var(--line);border-radius:var(--rx);
  transition:border-color var(--tq) linear,box-shadow var(--tm) var(--ease)}

.fbar:focus-within{border-color:var(--acc);box-shadow:var(--ring)}

.fbar__ico{margin-left:8px;color:var(--ink3)}

.fbar__in{flex:1;min-width:150px;height:34px;border:0;background:transparent;padding:0 4px;outline:0;font-size:var(--f14)}

.fbar__in::placeholder{color:var(--ink3)}

/* El separador de la barra de filtros: agrupa visualmente la búsqueda, el tipo
   y el resto sin dibujar tres cajas. Se esconde cuando la barra se envuelve —
   un separador vertical al principio de una línea nueva no separa nada. */
.fbar__sep{width:1px;align-self:stretch;margin:2px 4px;background:var(--line-soft);flex:none}

.fchip{display:inline-flex;align-items:center;height:32px;border-radius:var(--rp);background:var(--acc-wash2);
  color:var(--acc-text);font-size:var(--f13);font-weight:600;overflow:hidden}

.fchip__b{display:inline-flex;align-items:center;gap:6px;height:100%;padding:0 6px 0 13px;border:0;
  background:transparent;color:inherit;font:inherit;cursor:pointer}

.fchip__b span{opacity:.72;font-weight:500}

.fchip__x{width:28px;height:100%;border:0;background:transparent;color:inherit;cursor:pointer;
  display:grid;place-items:center;opacity:.6;transition:opacity var(--tq) linear,background-color var(--tq) linear}

.fadd{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 12px;border-radius:var(--rp);
  border:1px dashed var(--line-firm);background:transparent;color:var(--ink2);font-size:var(--f13);
  font-weight:600;cursor:pointer;transition:border-color var(--tq) linear,color var(--tq) linear,background-color var(--tq) linear}

.fpop .sheetgrab{display:none}

.fpop{position:absolute;z-index:var(--z-pop);width:282px;background:var(--card);border:1px solid var(--line);
  border-radius:var(--rm);box-shadow:var(--sh3);padding:8px;display:none}

.fpop.open{display:block}

.fpop__s{width:100%;height:34px;border:1px solid var(--line-soft);border-radius:var(--rs);background:var(--inset);
  padding:0 12px;margin-bottom:6px;outline:0;font-size:var(--f13)}

.fpop__s:focus{border-color:var(--acc)}

.fpop__l{max-height:228px;overflow:auto}

.fpop__hd{font-size:var(--f12);font-weight:600;color:var(--ink3);padding:4px 10px 6px}

.fopt{display:flex;align-items:center;gap:10px;width:100%;padding:8px 10px;border:0;background:transparent;
  border-radius:var(--rs);cursor:pointer;font-size:var(--f14);color:var(--ink);text-align:left}

.fopt[aria-selected="true"]{background:var(--hover)}

.fopt__box{width:18px;height:18px;border-radius:var(--rp);border:1px solid var(--line-firm);flex:none;
  display:grid;place-items:center;color:transparent;
  transition:background-color var(--tq) linear,border-color var(--tq) linear,color var(--tq) linear}

.fopt[data-on="1"] .fopt__box{background:var(--acc);border-color:var(--acc);color:var(--onaccent)}

.fopt__t{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.fopt__n{font-size:var(--f12);color:var(--ink3);font-variant-numeric:tabular-nums}
/* Un grupo de opciones en fila. `.fopt` es `width:100%` porque nació para una
   lista vertical, así que sin esto tres radios cortos ocupan tres líneas — y en
   un formulario con cinco escalones eso son cuarenta líneas de alto. */
.fopt--inline{width:auto;padding-right:14px}

.fmeta{display:flex;flex-wrap:wrap;align-items:center;gap:12px;font-size:var(--f13);color:var(--ink3)}

.fmeta b{color:var(--ink);font-weight:600;font-variant-numeric:tabular-nums}



.logs{border:1px solid var(--line-soft);border-radius:var(--rl);background:var(--card);overflow:hidden}

.log{display:grid;grid-template-columns:auto minmax(0,1fr) auto auto;gap:10px;align-items:center;width:100%;
  padding:11px 16px;border:0;background:transparent;border-bottom:1px solid var(--line-soft);
  cursor:pointer;text-align:left;font:inherit;color:inherit;transition:background-color var(--tq) linear}

.log__code{font-family:var(--fm);font-size:var(--f12);font-weight:500;height:24px;min-width:44px;
  display:grid;place-items:center;border-radius:var(--rp);padding:0 8px}

.log__code.ok{background:var(--acc-wash2);color:var(--acc-text)}

.log__code.warn{background:var(--att-wash);color:var(--att)}

.log__code.err{background:var(--bad-wash);color:var(--bad)}

.log__m{min-width:0;display:flex;flex-wrap:wrap;align-items:baseline;gap:2px 10px}

.log__p{font-family:var(--fm);font-size:var(--f13);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}

.log__src{font-size:var(--f13);color:var(--ink3);display:none}
@media (min-width:600px){
.log__src{display:inline}
}

.log__r{display:flex;align-items:center;gap:14px;font-size:var(--f13);color:var(--ink3);
  font-variant-numeric:tabular-nums;white-space:nowrap}

.log__ms{min-width:54px;text-align:right}

.log__ms.slow{color:var(--att);font-weight:600}

.log__chev{color:var(--ink3);transition:transform var(--tm) var(--ease)}

.log[aria-expanded="true"] .log__chev{transform:rotate(90deg)}

.log[aria-expanded="true"]{background:var(--inset)}

.logs > .log:last-child, .logs > .logdet:last-child{border-bottom:0}

.logdet{padding:2px 16px 16px;background:var(--inset);border-bottom:1px solid var(--line-soft)}

.logdet .kv{display:grid;grid-template-columns:110px 1fr;gap:6px 14px;font-size:var(--f13);margin-bottom:14px}

.logdet .kv dt{color:var(--ink3)}

.logdet .kv dd{margin:0;font-family:var(--fm);font-size:var(--f12);word-break:break-all}

.code{position:relative;background:var(--card);border:1px solid var(--line-soft);border-radius:var(--rm);
  padding:14px 16px;font-family:var(--fm);font-size:var(--f12);line-height:1.7;overflow:auto;
  color:var(--ink2);white-space:pre}

.code .btn{position:absolute;top:8px;right:8px}

.hl{color:var(--acc-text)}



.bone{background:linear-gradient(90deg,var(--bone1) 30%,var(--bone2) 46%,var(--bone1) 62%);
  background-size:340% 100%;animation:sweep 1.4s var(--ease) infinite;border-radius:var(--rp)}

@keyframes sweep{0%{background-position:100% 0}100%{background-position:0 0}}

.bone--l{height:11px}
 .bone--t{height:15px}
 .bone--o{width:36px;height:36px;border-radius:var(--rp)}

.in-up{animation:up var(--ts) var(--ease) both}

@keyframes up{from{opacity:0;transform:translate3d(0,6px,0)}to{opacity:1;transform:none}}



.dlg{position:fixed;inset:0;z-index:var(--z-over);display:grid;place-items:end center;pointer-events:none}

.dlg::before{content:"";position:absolute;inset:0;background:rgba(29,29,26,.34);opacity:0;
  transition:opacity var(--tm) var(--ease)}

.dlg.open::before{opacity:1}

.dlg.open{pointer-events:auto}

.dlg__p{position:relative;width:100%;max-width:520px;background:var(--card);border:1px solid var(--line-soft);
  border-bottom:0;border-radius:var(--rx) var(--rx) 0 0;box-shadow:var(--sh4);
  transform:translate3d(0,100%,0);transition:transform var(--ts) var(--ease);
  padding-bottom:env(safe-area-inset-bottom)}

.dlg.open .dlg__p{transform:none}

.dlg .sheetgrab{padding:10px 0 0}

.dlg__t{font-size:var(--f20);font-weight:700;letter-spacing:-.02em;padding:var(--s5) var(--s5) var(--s2)}

.dlg__b{padding:0 var(--s5) var(--s5);font-size:var(--f14);color:var(--ink2)}

/* Cabecera con cerrar, y cuerpo que scrollea.
   `.dlg` se extrajo en la Fase 0b y NADIE lo usaba: los formularios de la
   corrección de interfaz son su primer consumidor, y ahí faltaban dos cosas.

   La segunda importa más de lo que parece: el formulario de cliente tiene
   dieciséis campos, así que sin un cuerpo con scroll el botón de guardar queda
   fuera de la pantalla. Scrollea el CUERPO, no la página, para que la cabecera
   siga a la vista. */
.dlg__hd{display:flex;align-items:center;gap:var(--s3);flex:none;
  padding:var(--s4) var(--s5) var(--s2)}

.dlg__hd b{font-size:var(--f20);font-weight:700;letter-spacing:-.02em}

.dlg__p{display:flex;flex-direction:column;max-height:86vh}

.dlg__b{overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}

/* El cuerpo de `.dlg` es texto secundario porque nació para confirmaciones. Un
   formulario no: sus etiquetas son texto principal. */
.dlg__b--form{color:var(--ink);display:grid;gap:var(--s4)}

.dlg__f{display:flex;gap:10px;padding:var(--s4) var(--s5);border-top:1px solid var(--line-soft)}

.dlg__f .btn{flex:1}

.snacks{position:fixed;left:var(--s4);right:var(--s4);bottom:var(--s4);z-index:var(--z-note);
  display:grid;gap:10px;justify-items:center;pointer-events:none}

.snack{display:flex;align-items:center;gap:12px;max-width:460px;width:100%;padding:13px 16px;
  border-radius:var(--rx);background:var(--ink);color:var(--page);box-shadow:var(--sh4);font-size:var(--f14);
  pointer-events:auto;animation:rise var(--ts) var(--ease) both;margin-bottom:env(safe-area-inset-bottom)}

.snack.out{animation:fall var(--tm) var(--ease-in) both}

.snack button{margin-left:auto;background:transparent;border:0;color:inherit;font-weight:600;cursor:pointer;
  text-decoration:underline;text-underline-offset:3px;padding:0}

@keyframes rise{from{opacity:0;transform:translate3d(0,16px,0) scale(.98)}to{opacity:1;transform:none}}

@keyframes fall{to{opacity:0;transform:translate3d(0,10px,0)}}



.chips{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}

.chip{border-radius:var(--rm);overflow:hidden;border:1px solid var(--line-soft);background:var(--card)}

.chip i{display:block;height:48px}

.chip u{display:block;padding:8px 10px;text-decoration:none;font-family:var(--fm);font-size:10px;
  color:var(--ink3);line-height:1.5}

.chip u b{display:block;font-family:var(--ff);font-size:var(--f13);color:var(--ink);font-weight:600}

@keyframes slide{0%{transform:none}50%{transform:translate3d(calc(100% - 46px),0,0)}100%{transform:none}}
@media (min-width:600px){

  .g2,.g3{grid-template-columns:repeat(2,1fr)}

  .tiles{grid-template-columns:repeat(auto-fit,minmax(310px,1fr))}

  .stats{grid-template-columns:repeat(auto-fit,minmax(238px,1fr))}

  .list>li{grid-template-columns:210px 1fr;gap:var(--s4);align-items:baseline}

  .h1{font-size:var(--f38)}

  .chips{grid-template-columns:repeat(6,1fr)}

  .dlg{place-items:center;padding:var(--s4)}

  .dlg__p{border-bottom:1px solid var(--line-soft);border-radius:var(--rx);
    transform:translate3d(0,10px,0) scale(.99);opacity:0;
    transition:transform var(--tm) var(--ease),opacity var(--tq) linear}

  .dlg.open .dlg__p{transform:none;opacity:1}

  .dlg .sheetgrab{display:none}

  .dlg__f{justify-content:flex-end}

  .dlg__f .btn{flex:none}

  .snacks{left:0;right:0;bottom:var(--s6)}

  .log{gap:12px}
}
@media (min-width:1024px){

  .g3{grid-template-columns:repeat(3,1fr)}

  .nodesk{display:none!important}
}
@media (prefers-reduced-motion:reduce){

  .bone{background:var(--bone1)}
}
@media (hover:hover) and (pointer:fine){

.btn--main:hover:not(:disabled){--bg:var(--acc-hover);--bd:var(--acc-hover);box-shadow:var(--sh2)}

.btn--soft:hover:not(:disabled){--bg:var(--hover)}

.btn--bare:hover:not(:disabled){--bg:var(--hover);--fg:var(--ink)}

.in:hover,.ta:hover{border-color:var(--w6)}

.step button:hover{background:var(--hover);color:var(--ink)}

.tile:hover{border-color:var(--line-firm);box-shadow:var(--sh2)}

.rowitem:hover{background:var(--hover)}

.qchip:hover{background:var(--hover);border-color:var(--line-firm)}

.fchip__x:hover{opacity:1;background:rgba(0,0,0,.06)}

.fadd:hover{border-color:var(--acc);color:var(--acc-text);background:var(--acc-wash)}

.fopt:hover{background:var(--hover)}

.log:hover{background:var(--hover)}
}
@media (hover:none){

  .tile:active,.rowitem:active,.log:active,.qchip:active,.fopt:active,.nav:active{background:var(--press)}

  .fchip__b:active,.fchip__x:active{background:rgba(0,0,0,.07)}
}



.in,.ta,.fbar__in,.fpop__s{font-size:var(--in-fs)}



.btn--sm{height:var(--ctl-sm)}

.btn--round.btn--sm{width:var(--ctl-sm)}

.qchip,.fchip,.fadd,.fbar__in,.fpop__s{height:var(--ctl-sm)}

.seg button,.step button{height:calc(var(--ctl-sm) - 2px)}

.step button{width:calc(var(--ctl-sm) - 2px)}

.fopt{min-height:var(--ctl-sm)}

.log{min-height:var(--row)}

.rowitem{min-height:var(--row)}
@media (pointer:coarse){

  .tog{min-height:44px}

  .tog input{width:52px;height:32px}

  .tog input::after{width:26px;height:26px}

  .tog input:checked::after{transform:translate3d(20px,0,0)}

  .fchip__x{width:38px}

  .seg{padding:5px}

  .seg i{top:5px;bottom:5px;left:5px}
}



.chart .hit{touch-action:pan-y}

.chart{display:flex;flex-direction:column}

.chart svg{order:2}
@media (pointer:coarse){

  .chart .ctip{order:1;position:static;opacity:1;transform:none;width:100%;white-space:normal;
    background:var(--inset);color:var(--ink);box-shadow:none;border:1px solid var(--line-soft);
    margin-bottom:10px;display:flex;flex-wrap:wrap;gap:4px 16px;align-items:baseline}

  .chart .ctip b{margin:0 8px 0 0;color:var(--ink3)}

  .chart .cross,.chart .knob{opacity:1}
}



.fchips{display:contents}
@media (max-width:599px){

  .fchips{display:flex;gap:8px;order:3;flex:0 0 100%;overflow-x:auto;
    scrollbar-width:none;-webkit-overflow-scrolling:touch;padding:2px 0}

  .fchips::-webkit-scrollbar{display:none}

  .fadd{order:2}

  .fbar{border-radius:var(--rl)}

  .fmeta{gap:8px 14px}
}



.fpop{visibility:hidden;opacity:0;pointer-events:none;display:block;
  transition:opacity var(--tq) linear,transform var(--tm) var(--ease)}

.fpop.open{visibility:visible;opacity:1;pointer-events:auto}
@media (pointer:coarse),(max-width:599px){

  .fpop{position:fixed;left:0;right:0;bottom:0;top:auto;width:auto;
    border-radius:var(--rx) var(--rx) 0 0;box-shadow:var(--sh4);
    padding:0 var(--s3) calc(var(--s3) + env(safe-area-inset-bottom));
    transform:translate3d(0,101%,0);opacity:1;visibility:visible;pointer-events:none}

  .fpop.open{transform:none;pointer-events:auto}

  .fpop__l{max-height:44vh}

  .fopt{padding:12px 12px}

  .fpop .sheetgrab{display:grid}
}

.probe{display:grid;gap:10px;padding:var(--s4) var(--s5);border-radius:var(--rm);
  background:var(--inset);border:1px solid var(--line-soft)}

   SHELL — diferido de la Fase 0b
   ==========================================================
   Barra inferior en teléfono, rail persistente desde 1024px. NO hay drawer
   lateral a ningún tamaño: pone la navegación en la esquina más difícil de
   alcanzar de un teléfono y cuesta dos toques llegar a cualquier parte.
   ========================================================== */
.shell{min-height:100vh;display:flex;flex-direction:column}
@supports (min-height:100dvh){ .shell{min-height:100dvh} }

/* La barra superior es la MISMA superficie de marca que el rail, y por eso
   comparten tokens: con la barra clara y el rail oscuro se leían como dos
   piezas pegadas de aplicaciones distintas. Juntas forman una sola escuadra de
   color alrededor del contenido, que es el gesto de Siigo, de OficinaPro y de
   la propia web de Coonexa.

   Sin `border-bottom`: entre dos superficies del mismo color, una línea sólo
   marca una costura que no existe. */
/* En MÓVIL la barra sigue al tema; desde 1024px se vuelve superficie de marca.
   No es una excepción caprichosa: en escritorio la barra y el rail forman UNA
   escuadra de color alrededor del contenido, y eso se lee como el marco de la
   aplicación. En un teléfono no hay rail, así que la misma barra queda como una
   franja oscura suelta sobre una página clara — y ocupando la proporción de
   pantalla que ocupa ahí, la aplicación entera «se ve oscura» aunque el tema sea
   claro. Fue exactamente lo que reportó la firma. */
.topbar{position:sticky;top:0;z-index:var(--z-bar);display:flex;align-items:center;gap:var(--s3);
  height:56px;padding:0 var(--s4);background:var(--card);color:var(--ink);
  border-bottom:1px solid var(--line-soft)}

/* Todo lo que vive DENTRO hereda los colores de la barra. Se hace acá y no
   pintando cada pieza: si no, el día que alguien agregue un botón a la barra le
   va a salir con el color del tema y se verá oscuro sobre oscuro — que es
   exactamente el bug que acabamos de arreglar en los filtros. */

.topbar__marca{display:flex;align-items:center;gap:var(--s2);font-weight:700;letter-spacing:-.02em}
.topbar__marca i{width:24px;height:24px;border-radius:var(--rp);background:var(--acc);
  display:grid;place-items:center;flex:none}
.topbar__marca i::after{content:"";width:8px;height:8px;border-radius:var(--rp);background:var(--onaccent)}
.topbar__firma{font-size:var(--f13);color:var(--ink3);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* El logo de la firma en la barra. Va sobre un chip de BLANCO ABSOLUTO
   —`--w0`, de la Capa 1, que no cambia con el modo— y no sobre `--card`.

   El motivo: el logo que una firma entrega es su versión positiva, pensada para
   fondo claro. El de Coonexa es navy, así que sobre la barra en modo oscuro
   desaparecería. Es la misma decisión que la hoja de impresión —re-apuntar a la
   Capa 1 cuando el fondo tiene que ser claro pase lo que pase— y evita pedirle
   a la firma dos archivos.

   `height` fija y `width:auto`: un logo panorámico y uno cuadrado tienen que
   ocupar la misma altura, y el `max-width` evita que uno muy ancho empuje el
   resto de la barra. */
.topbar__logo{display:flex;align-items:center;flex:none;
  background:var(--w0);border-radius:var(--rs);padding:5px 9px}

.topbar__logo img{display:block;height:20px;width:auto;max-width:128px;object-fit:contain}

/* «Mi perfil» en la barra: el avatar y el nombre de la sección. En pantallas
   angostas se queda sólo el avatar — el texto es el que sobra, no la cara. */
.topbar__yo{display:flex;align-items:center;gap:var(--s2);flex:none;
  text-decoration:none;color:var(--ink2);font-size:var(--f13);font-weight:500;
  padding:4px 8px;border-radius:var(--rs)}

@media (max-width:599px){ .topbar__yo span{display:none} }

.topbar__gap{flex:1}

/* Los colores de la barra CUANDO es superficie de marca, o sea desde 1024px.
   Van ACÁ —después de cada componente— y no antes: puestos arriba no hacían
   nada, porque con la misma especificidad gana la última y `.topbar__yo` se
   define más abajo. El resultado era «Mi perfil» en gris oscuro sobre azul
   noche. Es la trampa que CLAUDE.md ya tiene escrita.

   Se hereda desde la barra en vez de pintar pieza por pieza: si no, el día que
   alguien agregue un control ahí le saldrá con el color del tema. */
@media (min-width:1024px){
  .topbar{background:var(--rail-bg);color:var(--rail-fg);border-bottom:0}
  .topbar .btn{--fg:var(--rail-fg)}
  .topbar .btn--bare{--fg:var(--rail-fg2)}
  .topbar .btn--soft{--bg:var(--rail-hover);--bd:var(--rail-fg2);--fg:var(--rail-fg)}
  .topbar__yo{color:var(--rail-fg2)}
  .topbar__firma{color:var(--rail-fg2)}
  .topbar__marca{color:var(--rail-fg)}
  .topbar__marca i{background:var(--rail-fg)}
  .topbar__marca i::after{background:var(--rail-bg)}
}
@media (min-width:1024px) and (hover:hover){
  .topbar .btn--bare:hover:not(:disabled){--bg:var(--rail-hover);--fg:var(--rail-fg)}
  .topbar__yo:hover{background:var(--rail-hover);color:var(--rail-fg)}
}

.contenido{flex:1;padding:var(--s6) 0 calc(var(--s16) + env(safe-area-inset-bottom))}

/* Barra inferior: cuatro destinos, a altura de pulgar, CON etiqueta de texto.
   Nada de iconos que necesiten tooltip para entenderse. */
.tabbar{position:fixed;inset:auto 0 0 0;z-index:var(--z-bar);display:flex;
  background:var(--card);border-top:1px solid var(--line);
  padding-bottom:env(safe-area-inset-bottom)}
.tabbar a{flex:1;display:grid;place-items:center;gap:2px;min-height:var(--row);
  padding:var(--s2) var(--s1);font-size:var(--f13);color:var(--ink2);text-decoration:none}
.tabbar a[aria-current="page"]{color:var(--acc-text);font-weight:600;box-shadow:inset 0 2px 0 var(--acc)}
.tabbar a:active{background:var(--press)}

.railnav{display:none}

@media (min-width:1024px){
  .tabbar{display:none}
  /* TRES filas: barra, sub-menú, contenido. Y los tres hijos del grid van
     colocados a mano, no por auto-placement.

     Costó una pantalla en blanco descubrir por qué hace falta: `.subnav` se
     agregó como hermano de `.contenido` sin colocación, así que el grid le daba
     la celda del contenido y empujaba `.contenido` a una fila implícita — y
     dentro de la columna de 216px del rail. La página quedaba vacía a la
     derecha y el contenido apretado y abajo.

     Con la fila 2 en `auto`, una pantalla sin sub-menú la colapsa a cero. */
  .shell{display:grid;grid-template-rows:auto auto auto 1fr}
  .topbar{grid-column:1/-1}
  .railnav{grid-column:1;grid-row:2 / span 3}
  /* La franja de novedades, en la columna del contenido y arriba del sub-menú.
     A todo lo ancho partiría en dos la escuadra de color que forman la barra y
     el rail. Con la fila en `auto`, sin franja colapsa a cero. */
  .novedad{grid-column:2;grid-row:2}
  .subnav{grid-column:2;grid-row:3}
  .contenido{grid-column:2;grid-row:4;min-width:0}
  /* El rail es la superficie de MARCA: fondo con el tono oscuro de la firma y
     blanco encima. La columna del grid mide lo colapsado (72px) y el rail se
     monta por arriba al abrirse, así el contenido NO se mueve cuando el puntero
     lo roza de paso — que es el defecto de los menús que empujan.

     El ancho NO se anima, y no es un olvido: `width` es layout, y el sistema
     sólo anima propiedades baratas. Se abre de golpe —que además se siente más
     rápido— y lo único que transiciona es la opacidad de los rótulos. */
  .shell{grid-template-columns:72px 1fr}
  .railnav{display:flex;flex-direction:column;gap:2px;width:72px;overflow:hidden;
    background:var(--rail-bg);color:var(--rail-fg);padding:var(--s3) 10px;
    /* La esquina superior derecha redondeada: es lo que hace que el menú se lea
       como un PANEL apoyado sobre la página y no como un bloque de color pegado
       al borde. Va en el menú y no en el contenido — lo puse en el contenido
       primero y quedaba peor, porque redondear la hoja no suaviza el panel. */
    /* Pegado a la izquierda y separado sólo de la barra, con UNA esquina
       redondeada: la de arriba a la derecha, que es la única que da a la página.
       Redondear también la izquierda lo despegaba del borde de la ventana y
       quedaba flotando; así se lee como una columna que nace del borde y se
       curva hacia el contenido. */
    border-top-right-radius:var(--rx);
    margin-top:var(--s3);
    position:sticky;top:calc(56px + var(--s3));align-self:start;
    /* Llega SIEMPRE hasta abajo, tenga dos secciones o doce. Con `align-self:
       start` y sólo `max-height` quedaba un panel flotante a media pantalla, no
       una columna — y el borde de abajo suelto se lee como que algo se cortó.
       `min-height` con la barra descontada; `max-height` para que con muchas
       secciones haga su propio scroll en vez de empujar la página. */
    /* La altura descuenta la barra Y los dos huecos, para que el panel termine
       a la misma distancia del borde de abajo que del de arriba. */
    min-height:calc(100dvh - 56px - var(--s3));
    max-height:calc(100dvh - 56px - var(--s3));overflow-y:auto;
    z-index:var(--z-rail)}

  /* Se abre con el foco además de con el puntero, y lo segundo no es un extra:
     sin `focus-within`, quien llega con Tab ve doce iconos sin nombre y no sabe
     dónde está parado. `--fijo` es el estado que deja el botón. */
  /* FIJO vs HOVER, y la diferencia importa:
     · Fijo → la columna del grid se ensancha y el contenido se corre. Si se
       montara encima, el menú fijo TAPARÍA el título y los filtros de forma
       permanente — se veía «ligaciones» donde decía «Matriz de obligaciones».
     · Hover → se monta encima, porque es pasajero: no vale mover la página
       entera cada vez que el puntero roza el borde. */
  .shell--menu{grid-template-columns:232px 1fr}
  .shell--menu .railnav, .railnav:focus-within{width:232px}
  .railnav:focus-within{box-shadow:var(--sh3)}

  .railnav a, .railnav__fijar{display:flex;align-items:center;gap:var(--s3);
    padding:10px;border-radius:var(--rs);color:inherit;text-decoration:none;font-weight:500;
    white-space:nowrap;border:0;background:transparent;cursor:pointer;font:inherit;width:100%}
  .railnav .ico{width:22px;height:22px;flex:none}

  /* El rótulo se desvanece en vez de cortarse: con `overflow:hidden` a secas
     quedarían medias palabras asomando. */
  .railnav__t{opacity:0;transition:opacity var(--tf) var(--ease)}
  .railnav:focus-within .railnav__t, .shell--menu .railnav__t{opacity:1}

  .railnav a[aria-current="page"]{background:var(--rail-activo);font-weight:600}
  .railnav a:focus-visible, .railnav__fijar:focus-visible{outline:2px solid var(--rail-fg);outline-offset:-2px}

  .railnav__gap{flex:1}
  .railnav__fijar{opacity:.85}
  .shell--menu .railnav__fijar .ico{transform:rotate(180deg)}



  /* Abrir al pasar el puntero vale SÓLO donde hay puntero. Un `:hover` suelto
     se queda pegado tras un toque en una pantalla táctil: el rail quedaría
     abierto hasta tocar otra cosa. */
  @media (hover:hover){
    .railnav:hover{width:232px;box-shadow:var(--sh3)}
    .railnav:hover .railnav__t{opacity:1}
    .railnav a:hover, .railnav__fijar:hover{background:var(--rail-hover)}
  }
  .contenido{padding:var(--s7) 0 var(--s12)}
}
/* Acá vivía `.railnav a:hover{background:var(--hover)}`, del rail anterior —el
   que era blanco y tenía la tinta del tema—. Con el rail de marca quedó
   pintando el ítem de `--hover`, que en tema CLARO es #f6f6f4: casi blanco, con
   texto blanco encima. El nombre desaparecía al pasar el puntero, y sólo en
   claro; en oscuro `--hover` es #2b2b27 y no se notaba nada.

   Iba DESPUÉS de la regla nueva, así que le ganaba por orden con la misma
   especificidad. Es la tercera vez en esta fase que muerde lo mismo: cuando se
   cambia un componente hay que BORRAR lo viejo, no sólo escribir lo nuevo. */

/* Organigrama: lista INDENTADA, no diagrama de cajas. Un árbol de cajas no cabe
   en 360px y obliga a scroll horizontal, que es justo lo que la regla de
   min-width:0 existe para evitar. Con sangría funciona en teléfono y en
   escritorio, y se recorre con teclado gratis. */
.og{display:grid;gap:2px}
.og__n{display:flex;align-items:center;gap:var(--s3);min-height:var(--row);
  padding:var(--s2) var(--s3);border-radius:var(--rs);background:var(--card);
  border:1px solid var(--line-soft)}
.og__b{min-width:0;flex:1}
.og__t{font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.og__d{font-size:var(--f13);color:var(--ink3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.og ul{padding-left:var(--s4);border-left:2px solid var(--line-soft);margin-left:var(--s3);
  display:grid;gap:2px;margin-top:2px}

/* ==========================================================
   TABLA ANCHA — pieza propia, Fern no la trae
   ==========================================================
   Su bloque más denso es la línea de log: una línea, cuatro datos. Acá son 34
   filas por 13 columnas.

   DOS VERSIONES ANTERIORES FALLARON, y el motivo de cada una importa:

   1ª — cabeceras rotadas 60 grados para que las columnas fueran angostas. No se
        podían leer, y a cinco columnas de distancia nadie sabía en qué columna
        estaba.

   2ª — cabeceras horizontales y `overflow-x: auto` en un contenedor tan alto
        como la tabla. Consecuencia: para correr en horizontal había que bajar
        hasta el final de la página a buscar la barra. Con 34 filas eso es
        inusable.

   Lo que se hace ahora, y ataca la causa en vez del síntoma:

   · ALTURA ACOTADA al viewport. La tabla scrollea DENTRO del contenedor, en los
     dos ejes, así que la barra horizontal está siempre al pie de lo que se ve.
     La cabecera queda pegada arriba y la columna del cliente pegada a la
     izquierda, así que nunca se pierde la referencia.

   · Y sobre todo: SE PUEDE DEJAR DE NECESITAR EL SCROLL. Las trece columnas se
     agrupan por autoridad, y filtrando por una sola —DIAN son 7, municipio 3—
     la tabla entra sin desplazamiento. El scroll queda para quien pide «todas».
   ========================================================== */
.matriz__scroll{display:none}

@media (min-width:1024px){
  .matriz__cards{display:none}

  .matriz__scroll{
    display:block;
    overflow:auto;
    overscroll-behavior:contain;
    /* Acotada al viewport: es lo que pone la barra horizontal al alcance en vez
       de al final de la página. El mínimo evita que con dos filas quede una
       caja enorme medio vacía. */
    max-height:calc(100vh - 22rem);
    min-height:14rem;
    background:var(--card);border:1px solid var(--line);border-radius:var(--rl);
    box-shadow:var(--sh1)}
  @supports (max-height:100dvh){
    .matriz__scroll{max-height:calc(100dvh - 22rem)}
  }

  .matriz{border-collapse:separate;border-spacing:0;font-size:var(--f13);width:100%}

  /* Cabecera de grupo: convierte trece columnas en cinco bloques. */
  .matriz thead .grupo th{position:sticky;top:0;z-index:2;background:var(--inset);
    padding:var(--s2) var(--s3);font-size:var(--f12);font-weight:600;color:var(--ink3);
    letter-spacing:.06em;text-transform:uppercase;text-align:center;
    border-bottom:1px solid var(--line)}
  .matriz thead .grupo th + th{border-left:1px solid var(--line)}

  .matriz thead .cols th{position:sticky;top:31px;z-index:2;background:var(--card);
    padding:var(--s2) var(--s2);font-size:var(--f12);font-weight:600;color:var(--ink2);
    text-align:center;vertical-align:bottom;line-height:1.25;
    border-bottom:1px solid var(--line);min-width:74px;max-width:96px}

  /* Primera columna pegada: al desplazar en horizontal siempre se ve de quién es
     la fila. Sin esto, cinco columnas adentro nadie sabe qué cliente mira. */
  .matriz .pin{position:sticky;left:0;z-index:1;background:var(--card);
    text-align:left;min-width:228px;max-width:300px;padding:var(--s2) var(--s3);
    border-right:1px solid var(--line)}
  /* La esquina: pegada arriba Y a la izquierda a la vez, y por encima de las dos
     cabeceras para que nada le pase por debajo al desplazar en diagonal. */
  .matriz thead .grupo .pin{z-index:4;background:var(--inset)}
  .matriz thead .cols .pin{z-index:4;background:var(--card)}

  .matriz td{padding:var(--s2) var(--s2);border-bottom:1px solid var(--line-soft);
    vertical-align:middle;text-align:center}
  .matriz tbody tr:last-child td{border-bottom:0}
  .matriz .sep{border-left:1px solid var(--line)}

  .matriz td.mk{color:var(--acc);font-size:var(--f17);line-height:1}
  .matriz td.mk--om{color:var(--ink3);font-size:var(--f14)}
  .matriz td.mk--no{color:var(--line-firm)}
  .matriz .inactivo td{opacity:.45}
  .matriz .nom{font-weight:600;color:var(--ink);display:block;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .matriz .sub{font-size:var(--f12);color:var(--ink3)}

  /* Aviso de que hay más a la derecha. Solo aparece cuando el JS detecta que
     efectivamente hay desbordamiento: un aviso que miente es peor que ninguno. */
  .matriz__aviso{display:none;font-size:var(--f12);color:var(--ink3);
    margin-top:var(--s2);text-align:right}
  .matriz__scroll[data-desborda="1"] + .matriz__aviso{display:block}
}
@media (min-width:1024px) and (hover:hover) and (pointer:fine){
  .matriz tbody tr:hover td{background:var(--hover)}
  .matriz tbody tr:hover .pin{background:var(--hover)}
}

/* Barra de filtros de la matriz: chips que se leen como frases y conteo en
   vivo, según §8. Sin botón Aplicar: los resultados cambian al tocar el chip. */
.filtros{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;margin-bottom:var(--s4)}
.filtros__et{font-size:var(--f13);color:var(--ink3);margin-right:var(--s1)}
.cuenta{font-size:var(--f13);color:var(--ink3);margin-bottom:var(--s4)}
.cuenta b{color:var(--ink);font-variant-numeric:tabular-nums}

/* ==========================================================
   LAYOUT — el contenedor de página
   ==========================================================
   Esto se perdió al re-extraer el CSS de Fern: la sección de adiciones vivía en
   el archivo viejo y no se conservó, así que `.wrap` desapareció y TODO quedó
   pegado a los bordes izquierdo y derecho. Es lo único que da margen
   horizontal, porque `.contenido` no lleva padding lateral a propósito.

   Los márgenes son los de §12.3 —16px bajo 600, 24px de 600 a 1023, contenido
   tope 1060 desde 1024— pero con dos correcciones que la lectura real pedía:

     · A partir de 1024 el padding sube a 32px. Con el rail al lado, 24px hacen
       que el contenido arranque casi tocando el borde de la navegación.
     · A partir de 1440 sube a 48px, porque en pantalla ancha el bloque de 1060
       centrado se ve suelto si no respira.
   ========================================================== */
.wrap{width:100%;margin:0 auto;padding:0 var(--s4);min-width:0}

@media (min-width:600px){
  .wrap{padding:0 var(--s6)}
  .tiles{grid-template-columns:repeat(2,minmax(0,1fr))}
}

@media (min-width:1024px){
  /* Contenido tope 1060px: las líneas quedan legibles y las gráficas no se
     estiran hasta volverse ruido. */
  .wrap{max-width:1060px;padding:0 var(--s8)}
  .tiles{grid-template-columns:repeat(3,minmax(0,1fr))}
}

@media (min-width:1440px){
  .wrap{padding:0 var(--s12)}
}

/* La barra superior alinea con el contenido, no con el borde de la ventana. Sin
   esto, el logo queda 16px del borde mientras el título de la página empieza
   32px más adentro, y se nota. */
.topbar{padding:0 var(--s4)}
@media (min-width:600px){ .topbar{padding:0 var(--s6)} }
@media (min-width:1024px){ .topbar{padding:0 var(--s8)} }

/* Estados de una obligación: mapea las pills de Fern a nuestro dominio. Cada
   una lleva UNA PALABRA — el punto de color es redundancia para lectores con
   daltonismo, no el mensaje. */
.pill--aldia{}
.pill--sinini{}
.pill--porvencer{}
.pill--vencido{}
.pill--sinop{}

/* ==========================================================
   RAIL LATERAL Y SCRIM — el panel que en móvil es hoja
   ==========================================================
   Extraído de Fern, verbatim. TERCERA vez que la extracción de la Fase 0b
   perdió piezas, y la tercera con un síntoma distinto:

     1a  las primitivas (.btn, .card, .in, .f, .pill, .rows) — botones sin
         estilo durante tres fases.
     2a  .wrap — todo pegado a los bordes.
     3a  esta: .rail, .rail__top, .rail__nav, .rail__foot, .scrim, .sheetgrab
         y .sheetgrip, o sea el componente entero, usado en views/app/personas
         y en views/portal/requerimientos.

   Lo que dejó de encontrarse cada vez fue distinto, así que el test de
   primitivas —que verifica una lista fija— no podía atrapar la tercera. El que
   sí la atrapó es tests/unit/clases.test.js, que va al revés: parte de las
   clases que las vistas USAN y exige que existan.

   Es el mismo componente en dos ergonomías, que es la tesis de Fern: «el ancho
   decide el layout, el puntero decide la ergonomía». Bajo 1024 es una hoja que
   sube desde abajo con scrim y agarradera; desde 1024 es una columna sticky de
   252px sin transform, sin scrim y sin agarradera. */
.rail{position:fixed;inset:auto 0 0 0;z-index:var(--z-rail);background:var(--card);
  border-top:1px solid var(--line);border-radius:var(--rx) var(--rx) 0 0;box-shadow:var(--sh4);
  display:flex;flex-direction:column;max-height:82vh;
  transform:translate3d(0,101%,0);transition:transform var(--ts) var(--ease);will-change:transform;
  padding-bottom:env(safe-area-inset-bottom);padding-left:env(safe-area-inset-left)}
.rail.open{transform:translate3d(0,0,0)}
.rail__top{display:flex;align-items:center;height:52px;padding:0 var(--s4);border-bottom:1px solid var(--line-soft)}
.rail__nav{flex:1;overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;padding:var(--s3)}
.rail__foot{padding:var(--s3);border-top:1px solid var(--line-soft)}

/* La agarradera de la hoja. `touch-action:none` es lo que permite arrastrar sin
   que el navegador se quede el gesto para hacer scroll. */
.sheetgrab{display:grid;place-items:center;padding:10px 0 8px;touch-action:none;cursor:grab;flex:none}
.sheetgrip{width:38px;height:4px;border-radius:var(--rp);background:var(--line-firm)}
.fpop .sheetgrab{display:none}
.dlg .sheetgrab{padding:10px 0 0}

/* El velo. El rgba literal es de Fern y se conserva: es el único color del
   sistema que no sale de un token, porque un velo necesita alfa y los tokens de
   color son opacos. */
.scrim{position:fixed;inset:0;z-index:var(--z-scrim);background:rgba(29,29,26,.34);opacity:0;pointer-events:none;
  transition:opacity var(--tm) var(--ease)}
.scrim.open{opacity:1;pointer-events:auto}

@supports (max-height:82dvh){ .rail{max-height:82dvh} }
@supports (max-height:86dvh){ .dlg__p{max-height:86dvh} }

@media (min-width:600px){
  .rail{max-width:560px;margin-inline:auto}
  .dlg .sheetgrab{display:none}
}

@media (pointer:coarse),(max-width:599px){
  .fpop .sheetgrab{display:grid}
}

@media (min-width:1024px){
  .rail{position:sticky;top:0;height:100dvh;max-height:none;inset:auto;width:252px;
    transform:none;transition:none;grid-row:1 / span 2;align-self:start;
    border-top:0;border-right:1px solid var(--line-soft);border-radius:0;box-shadow:none;
    padding-bottom:0}
  .rail__top{height:60px}
  .rail__x,.rail .sheetgrab{display:none}
  .scrim{display:none}
}

/* ==========================================================
   .fbar-simple — barra de búsqueda de una sola entrada
   ==========================================================
   Fern trae `.fbar` con su ícono y sus chips para el caso completo. Esto es el
   caso de una entrada sola: la búsqueda de actividades con datos incompletos,
   que es texto sobre el índice FULLTEXT y no un filtro. Usar `.fbar` ahí
   dejaba el hueco del ícono vacío. */
.fbar-simple{display:grid;gap:var(--s3);max-width:44rem}
@media (min-width:600px){ .fbar-simple{max-width:32rem} }


/* EL LIENZO DE LA PIEZA.
   La pieza dejó de ser una tabla de HTML y pasó a dibujarse en un `<canvas>`:
   lo que se ve es exactamente la imagen que se baja. Acá sólo se le da la
   medida en pantalla —el tamaño del DIBUJO lo pone el JavaScript— y por eso va
   `height:auto`: el lienzo tiene su propia proporción y una altura fija lo
   deformaría. */
.lienzo{max-width:56rem;margin:0 auto}
.lienzo canvas{display:block;width:100%;height:auto;border-radius:var(--rm);
  box-shadow:0 2px 10px rgba(0,0,0,.14)}

/* La pieza ya no se arma con HTML: se dibuja en `.lienzo` (arriba). Las reglas
   `.pieza__*` que vivían acá —banda, cuadrícula, recuadros, pie— se fueron con
   ella. Dejarlas habría sido CSS que nadie aplica y que la próxima persona
   leería como la forma de la pieza, que es peor que no tener nada. */

/* La barra de sub-navegación de una sección. Va debajo del rail y encima del
   contenido, así que necesita su propio aire: sin el margen queda pegada al
   título de la página y parece parte de él. */
.subnav{padding-top:var(--s4);padding-bottom:0}
@media (min-width:1024px){ .subnav{padding-top:var(--s5)} }

/* ==========================================================
   La entrada con portada (Fase 13)
   ==========================================================
   El login con la imagen de la firma al lado. Sin portada configurada este
   bloque no se usa y la pantalla es la de siempre — una firma que no sube nada
   no ve una caja vacía donde debería haber algo.

   La imagen va SEGUNDA en el DOM y primera en pantalla con `order`. Es a
   propósito: quien llega con lector de pantalla o con el teclado encuentra el
   formulario de una, sin atravesar una imagen decorativa. Por lo mismo lleva
   `aria-hidden` y `alt` vacío: no comunica nada que no esté escrito al lado.
   ========================================================== */
.entrada{display:grid;min-height:100dvh}
.entrada__arte{display:none}

@media (min-width:900px){
  .entrada{grid-template-columns:1fr 1fr;align-items:stretch}
  /* En pantalla angosta la imagen es lo primero que sobra: lo que hace falta en
     un teléfono es entrar, no mirar. Por eso aparece recién acá. */
  /* `--entrada-fondo` lo escribe `services/marca` cuando la firma escogió un
     color de fondo; sin él manda el del rail, que es el comportamiento que ya
     había. El degradado va DEBAJO de la imagen a propósito: si la portada tarda
     en cargar, o es un PNG con transparencia, lo que se ve es la marca y no un
     rectángulo vacío. */
  .entrada__arte{display:block;order:-1;position:relative;overflow:hidden;
    background:var(--entrada-fondo, var(--rail-bg))}
  /* Lo que va ENCIMA del degradado cuando no hay imagen: el logo y el nombre,
     centrados. En blanco, que es contra lo que se validó el par de pasos. */
  .entrada__marca{position:absolute;inset:0;display:grid;place-content:center;
    justify-items:center;gap:var(--s4);padding:var(--s7);text-align:center}
  /* El logo va sobre un chip de BLANCO ABSOLUTO, exactamente por lo mismo que en
     la barra superior: el logo que una firma entrega es su versión positiva,
     pensada para fondo claro, así que sobre el degradado de su propia marca
     desaparece. `--w0` es Capa 1 y no cambia con el modo. Evita además pedirle
     dos archivos a la firma. */
  .entrada__marca figure{margin:0;background:var(--w0);border-radius:var(--r3);
    padding:var(--s4) var(--s5);max-width:min(20rem,70%)}
  .entrada__marca img{display:block;width:100%;height:auto;max-height:5rem;object-fit:contain}
  .entrada__marca b{color:var(--w0);font-size:var(--f20);font-weight:600;letter-spacing:-.01em}
  /* `contain` y no `cover`, y costó verlo en producción: lo que una firma sube
     como «portada» casi nunca es una foto a sangre — es su logotipo. Coonexa
     subió el suyo sobre blanco, y `cover` lo agrandaba hasta recortarle las
     letras por los dos lados. Cropear una foto pierde un pedazo de paisaje;
     cropear un logotipo lo vuelve ilegible, que es un fallo de otra clase.
     Con `contain`, lo que rodea a la imagen es el degradado de la marca, así
     que una foto que no llena tampoco queda con bandas vacías: queda sobre el
     color de la firma. */
  .entrada__arte img{position:absolute;inset:0;margin:auto;
    max-width:80%;max-height:70%;width:auto;height:auto;object-fit:contain;display:block}
  .entrada > .wrap{align-self:center;padding-top:0}
}


/* ==========================================================
   La franja de novedades
   ==========================================================
   Lo único de la aplicación que le interrumpe a TODO EL MUNDO a la vez, así que
   no grita: usa el lavado del acento, no su relleno. Una franja de color pleno
   compite con el contenido de la pantalla, y la pantalla es a lo que la persona
   vino.

   Las dos acciones van juntas a la derecha y en móvil caen debajo: en un
   teléfono, con los botones al lado del texto, el título queda en dos palabras
   por renglón. */
.novedad{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s3);
  background:var(--acc-wash);border:1px solid var(--acc-line);border-radius:var(--rm);
  padding:var(--s3) var(--s4);margin:var(--s4) var(--s4) 0}
@media (min-width:1024px){ .novedad{margin:var(--s5) var(--s5) 0} }

.novedad__c{display:flex;align-items:center;gap:var(--s3);flex:1 1 260px;min-width:0}
.novedad__t{font-size:var(--f14);font-weight:600}
.novedad__d{font-size:var(--f13);color:var(--ink2)}
.novedad__b{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap}
