/* Fuente del 8082 (Plus Jakarta Sans) AUTO-HOSPEDADA: la CSP de la 8091 es
   font-src 'self' y el cobrador anda en la calle con datos — nada de CDN. */
@font-face {
  font-family: 'Plus Jakarta Sans';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('./fonts/PlusJakartaSans-var.woff2') format('woff2');
}
:root {
  color-scheme: light;
  /* Tokens alineados al 8082 (Tailwind gray/blue + brand #2563eb) */
  --bg: #f8fafc;
  --card: #ffffff;
  --text: #111827;
  --muted: #6b7280;
  --line: #e5e7eb;
  --line-soft: #f3f4f6;
  /* CHG-2026-0719 — LA BANDA QUE SUSTITUYE A LAS RAYAS.
     Eddy, 30-ago-2026: *"quiero que quites las rallas de mi app para que se vea
     todo lizo como en whatasp"*. Pero WhatsApp no borro sus rayas: las cambio por
     AIRE entre renglones del mismo grupo y por una BANDA de lado a lado entre
     grupos distintos (medido en su pantalla de perfil el 30-ago). Borrar las 16
     rayas sin esto deja un mazacote: 7 renglones pegados sin saber donde termina
     uno. Por eso la banda es una variable y no un `#hex` suelto: es el reemplazo,
     no un adorno. */
  --banda: #eceff3;
  --primary: #2563eb;
  --primary-dark: #1d4ed8;
  --soft: #eff6ff;
  --danger: #dc2626;
  /* CHG-2026-0834 (10-sep-2026): medido con cj-diseno -- #16a34a daba 3.15:1
     contra #f8fafc y 3.3:1 contra blanco (piso 4.5), en .prow-comision-monto
     y otros usos de texto (22+ hallazgos). Mismo verde, mas oscuro (Tailwind
     green-700): 4.79:1 / 5.02:1. */
  --ok: #15803d;
  /* Igual con #d97706 -- 3.07:1/3.19:1 en "Pendiente" y afines. Mismo ambar,
     mas oscuro (Tailwind amber-700): 4.84:1 / 5.02:1. */
  --warning: #b45309;
}
* { box-sizing: border-box; }
body {
  margin: 0;
  font-family: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  background: var(--bg);
  color: var(--text);
  /* CHG-2026-0876 (F15) — LA BASE ES 15px, no los 16 del navegador. Todo lo
     que no traiga su propio tamano (botones, parrafos, h2) heredaba 16px y se
     quedaba fuera de la escala de Eddy (13 y 15) sin que ninguna regla del CSS
     lo dijera: no estaba escrito en ningun sitio, era el default. */
  font-size: 15px;
  line-height: 1.5;
}
/* Los controles NO heredan la letra del cuerpo: hay que decirselo. */
button, input, select, textarea { font-size: 15px; }
/* Íconos SVG inline estilo Material Symbols (mismo lenguaje visual del 8082) */
.mi { width: 1.25em; height: 1.25em; fill: currentColor; display: block; flex-shrink: 0; }
.app {
  width: min(920px, 100%);
  margin: 0 auto;
  padding: 18px;
}
.hero {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 4px 10px;
}
h1, h2, p { margin-top: 0; }
h1 { margin-bottom: 6px; font-size: 15px; line-height: 1.5; }
h2 { margin-bottom: 14px; font-size: 15px; }
.eyebrow { margin-bottom: 6px; color: var(--primary); font-weight: 700; text-transform: uppercase; letter-spacing: .08em; font-size: 13px; }
.version { margin: 8px 0 0; color: var(--ok); font-weight: 800; font-size: 15px; }
.muted, .hint { color: var(--muted); }
.hint { margin: 10px 0 0; font-size: 15px; }
.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 18px;
  /* CHG-2026-0694 — NO tocar el padding aqui: lo pisa `.card` del bloque "UX PRO
     14-jul" (mas abajo en el archivo), que fija 16px/8px. Medido: el computado
     era 16px con esta puesta en 14. La densidad se cambia ALLA. */
  padding: 18px;
  margin: 14px 0;
  box-shadow: 0 8px 24px rgba(23, 32, 51, .06);
}
.grid { display: grid; gap: 12px; }
.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* 7px entre el rotulo y su caja quedaba por debajo del minimo de separacion
   (8px). Se ve en Capital / Interes de la pantalla de cobrar, medido el
   19-sep-2026. Ocho es el escalon de la escala 4/8/12/16. */
label { display: grid; gap: 8px; font-weight: 650; margin-bottom: 12px; }
input, select, textarea {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 13px 12px;
  font: inherit;
  background: #fff;
  color: var(--text);
  /* CHG-2026-0679 — 44px es el minimo de un blanco tactil (regla dura de la
     skill ui-ux-pro-max, severidad alta). El barrido del 26-ago los midio en
     38px: entre ellos `interesPagado` y `montoTotal`, o sea los campos donde el
     cobrador escribe DINERO, de pie en la puerta de un cliente y con el telefono
     en una mano. El padding solo no llegaba; los botones ya cumplian. */
  min-height: 44px;
}
input:focus, select:focus, textarea:focus { outline: 3px solid rgba(27, 110, 243, .15); border-color: var(--primary); }
button {
  border: 0;
  border-radius: 12px;
  padding: 13px 16px;
  font: inherit;
  font-weight: 800;
  background: var(--primary);
  color: white;
  cursor: pointer;
}
button:hover { background: var(--primary-dark); }
button:disabled { opacity: .55; cursor: not-allowed; }
.secondary { background: var(--soft); color: var(--primary); }
.secondary:hover { background: #dce9ff; }
.actions { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
/* CHG-2026-0552 — el botón pegado abajo TAPABA el último campo.
 *
 * Con `bottom: 0` el bloque se queda pegado al borde inferior de la ventana, que
 * es justo donde vive la barra de navegación (fija, ~74px + safe-area). Resultado
 * medido el 16-ago-2026 a 360x800 en CUATRO pantallas — Registrar pago, Nuevo
 * cliente, Pedir un cambio y el Recibo: la Nota quedaba debajo del botón, y el
 * botón debajo de la barra.
 *
 * Es la trampa #3 del barrido del 31-jul (CHG-2026-0306), que se arregló en un
 * panel y volvió en los demás. Por eso ahora el arreglo va en la clase, no en la
 * pantalla: quien use `.sticky-actions` lo hereda.
 *
 * Dos partes, y hacen falta las dos:
 *   · `bottom` levanta el bloque por encima de la barra.
 *   · el `padding-bottom` del contenedor reserva el hueco para que el último
 *     campo pueda subir por encima del botón al llegar al final.
 * Sin la segunda, el botón sigue tapando lo último aunque ya no lo tape la barra. */
.sticky-actions {
  position: sticky;
  bottom: calc(84px + env(safe-area-inset-bottom, 0px));
  background: var(--bg);   /* CHG-2026-0980 (vigilante #881/#889): el fondo del lienzo, sin plancha blanca */
  padding-top: 10px;
  backdrop-filter: blur(8px);
  z-index: 5;
}
/* El hueco al final del panel que contiene el botón. Va por el hermano: cualquier
   contenedor con un `.sticky-actions` dentro reserva sitio. */
.step-panel:has(> .sticky-actions),
.card:has(> .sticky-actions),
section:has(> .sticky-actions) {
  padding-bottom: calc(96px + env(safe-area-inset-bottom, 0px));
}
.badge {
  flex: 0 0 auto;
  border-radius: 999px;
  padding: 8px 12px;
  background: #fff1f0;
  color: var(--danger);
  font-weight: 800;
  border: 1px solid #ffd6d3;
}
.badge.ok { background: #ecfdf3; color: var(--ok); border-color: #abefc6; }
.section-title { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.summary {
  border: 1px dashed var(--line);
  border-radius: 14px;
  padding: 12px;
  margin: 8px 0 14px;
  background: #fbfcff;
}
.dashboard-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
}
.dashboard-grid.single { grid-template-columns: 1fr; }
h3 { margin: 0 0 8px; font-size: 15px; }
.client-list {
  display: grid;
  gap: 8px;
}
.client-card {
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 12px;
  background: #fbfcff;
}
.client-card strong { display: block; margin-bottom: 4px; }
.client-card .meta { color: var(--muted); font-size: 15px; line-height: 1.5; }
.client-card button { margin-top: 8px; width: 100%; padding: 10px 12px; }
.client-card.due { border-color: #84caff; background: #eff8ff; }
.client-card.overdue { border-color: #fda29b; background: #fff1f3; }
.client-card.paid { border-color: #abefc6; background: #ecfdf3; }
.cash-summary {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}
.cash-summary > div,
.detail-panel {
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 12px;
  background: #fbfcff;
}
.cash-summary span,
.field-title {
  display: block;
  color: var(--muted);
  font-weight: 700;
  font-size: 15px;
  margin: 0 0 6px;
}
.cash-summary strong { font-size: 15px; }
.detail-panel { margin: 8px 0 12px; line-height: 1.5; }
.commission-panel { border-color: #abefc6; background: #ecfdf3; font-weight: 700; }
.detail-panel h3 { margin: 0 0 8px; }
.detail-table { width: 100%; border-collapse: collapse; font-size: 15px; }
.detail-table th,
/* CHG-2026-0719 — sin raya: lo que separa es aire (ver la cabecera de este archivo). */
.detail-table td { padding: 11px 6px; text-align: left; vertical-align: top; }
.detail-table th { color: var(--muted); font-size: 13px; }
.specs-table th { width: 44%; }
.loan-pill {
  display: block;
  width: 100%;
  text-align: left;
  margin: 8px 0;
  background: #fff;
  color: var(--text);
  border: 1px solid var(--line);
}
.loan-pill.active { border-color: var(--primary); background: var(--soft); color: var(--primary); }
.payment-type-panel { margin: 10px 0 14px; }
.choice-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.choice-button.active { background: var(--primary); color: white; }
.warnings {
  border: 1px solid #fedf89;
  border-radius: 14px;
  padding: 12px;
  margin: 8px 0 14px;
  background: #fffaeb;
  color: #93370d;
  font-weight: 650;
}
.receipt, .log {
  white-space: pre-wrap;
  background: #101828;
  color: #e4e7ec;
  border-radius: 14px;
  padding: 14px;
  min-height: 120px;
  overflow: auto;
}
.log { min-height: 90px; max-height: 220px; font-size: 15px; }
.log-card { margin-bottom: 32px; }
@media (max-width: 720px) {
  .hero { display: block; }
  .badge { display: inline-block; margin-top: 10px; }
  .two, .three, .dashboard-grid, .cash-summary, .choice-grid { grid-template-columns: 1fr; }
  .section-title { align-items: flex-start; flex-direction: column; }
  button { width: 100%; }
}

/* Rediseño móvil tipo app */
.mobile-shell {
  width: min(520px, 100%);
  /* CHG-2026-0677: 94px aqui y 100px mas abajo, y ganaba el de abajo. El hueco
     lo reserva la barra flotante; sin barra lo recoge `body.sin-barra`. */
  padding-bottom: calc(100px + env(safe-area-inset-bottom));
}
.mobile-header {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 4px 10px;
  background: rgba(246, 247, 251, .94);
  backdrop-filter: blur(12px);
}
.brand-row { display: flex; align-items: center; gap: 12px; }
/* A7 (CHG-2026-0863) — Eddy: quitarle el fondo azul al logo de DENTRO de la
   app (junto a "Inicio") y dejarlo suelto. El logo (icon-192.png) ya trae su
   propio color; la caja azul de detrás era decoración de cuando el ícono era
   un glifo blanco sobre fondo — con la imagen real encima, se ve un logo
   dentro de un cuadrado azul. Se quita el relleno/sombra; el tamaño se queda
   igual para no mover el resto del encabezado. NO toca `.auth-brand .app-icon`
   (la pantalla de login, que no es "por dentro de la app" y no se pidió). */
.app-icon {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 15px;
  background: none;
  color: white;
  font-weight: 900;
  box-shadow: none;
}
.mobile-header h1 { margin: 0 0 2px; font-size: 15px; }
.mobile-header .eyebrow { margin: 0 0 2px; font-size: 13px; }
.mobile-header .muted { margin: 0; font-size: 13px; }
.screen { display: none; animation: fadeIn .18s ease-out; }
.screen.active { display: block; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
.stat-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin: 8px 0 14px;
}
.stat-card {
  border: 1px solid var(--line);
  border-radius: 18px;
  padding: 14px;
  background: var(--card);
  box-shadow: 0 8px 20px rgba(23, 32, 51, .06);
}
.stat-card span:not(.stat-icon) { display: block; color: var(--muted); font-weight: 750; font-size: 13px; margin-bottom: 8px; }
.stat-card strong { display: block; font-size: 15px; line-height: 1.5; }
.stat-card.blue { border-color: #b2ccff; background: #eff4ff; }
.stat-card.orange { border-color: #fedf89; background: #fffaeb; }
.stat-card.green { border-color: #abefc6; background: #ecfdf3; }
.stat-card.purple { border-color: #d9d6fe; background: #f4f3ff; }
.quick-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.compact-title { align-items: center; flex-direction: row; }
.small-btn { width: auto; padding: 9px 12px; font-size: 15px; }
/* CHG-2026-0694 — el boton de atras es SOLO la flecha. Eddy, 28-ago: *"no tengan
   texto como los botones de hacia atras"*. El destino vive en el `aria-label` que
   escribe pintarRotulosVolver(); aqui no se pinta ningun texto.
   Los 40px son el circulo visible; el area tactil llega a 44 por el padding, que
   es el minimo que se puede acertar caminando. */
/* CHG-2026-0719 — SOLO LA FLECHA, como la de WhatsApp.
   Eddy, 30-ago-2026: *"como se ven los botones como el de ir hacia atras quiero
   que el mio se vea asi"*. Medido en la pantalla de ajustes de WhatsApp Business
   el 30-ago: su flecha va suelta, sin circulo, sin borde, sin sombra y sobre el
   mismo fondo de la pagina. La de aqui tenia las cuatro cosas.

   ⛔ LO QUE NO SE TOCA: el area que responde al dedo sigue en 44x44. La flecha se
   ve mas chica que el circulo de antes, pero el boton NO se encogio — es el
   minimo de la skill `ui-ux-pro-max` (44pt) y el motivo por el que el cobrador le
   acierta caminando. Si alguien baja estos 44, el test O2 falla.

   El margen negativo pega la flecha al borde de la pantalla, como WhatsApp: sin
   el, los 44px de caja la dejan flotando separada del margen. */
.back-btn {
  width: 44px; height: 44px; padding: 0;
  display: grid; place-items: center;
  border: 0; border-radius: 999px;
  background: transparent; color: var(--text);
  box-shadow: none;
  margin-left: -10px;
}
.back-btn .mi { width: 24px; height: 24px; }
.back-btn:active { background: rgba(15, 23, 42, .06); }

/* ── ⛔ CHG-2026-0720 — LA FLECHA QUE SE QUEDABA "SELECIONADA" ────────────────
 *
 * Eddy, 30-ago-2026, la SEGUNDA vez que lo reporta: *"cuando estoy en detalle del
 * cliente y le doy asia atras, el boton de asia atras en el prefil parese
 * selecionado"*. Y al acotarlo: *"no me importa que la flecha se vea azul cuando
 * se selecione, lo que no es que se quede selecionado si no que se quede limpio"*.
 *
 * El CHG-2026-0719 le echo la culpa al `:hover` pegado, lo tapo, y NO basto —
 * porque quedaban otras dos marcas encima del mismo boton:
 *
 *   1. El `-webkit-tap-highlight-color` del navegador: WebKit pinta un velo gris
 *      sobre lo que tocaste. Se apaga aqui.
 *   2. El FOCO. Y este es el que hacia que "se quedara": `#headerBackBtn` es UN
 *      SOLO boton para toda la app (index.html:203) — no hay uno por pantalla. Al
 *      tocarlo en Detalle del cliente se queda enfocado, y como es el MISMO
 *      elemento, llega enfocado al Perfil. El foco no viajaba con el usuario:
 *      viajaba con el boton.
 *
 * Por eso el contorno pasa a `:focus-visible` (solo teclado). Con el dedo ya no
 * se pinta nada, y quien navegue con teclado sigue viendo donde esta parado —
 * quitarle el `:focus` a secas sin reponer esto lo habria dejado a ciegas.
 * El `blur()` de app.js remata: el foco tampoco se ARRASTRA a la otra pantalla.
 *
 * ⚠️ El `:active` de arriba NO se toca: es el aviso momentaneo del dedo, dura lo
 * que dura el toque, y Eddy dijo expresamente que ese esta bien. */
.back-btn { -webkit-tap-highlight-color: transparent; }
.back-btn:focus { outline: none; }
.back-btn:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.search-label { margin-bottom: 14px; }
.preview-card {
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 12px;
  background: #fbfcff;
  margin-top: 12px;
}
.bottom-nav {
  position: fixed;
  left: 50%;
  bottom: 10px;
  transform: translateX(-50%);
  z-index: 50;
  width: min(520px, calc(100% - 18px));
  display: grid;
  /* CHG-2026-0694: esto decia repeat(6, 1fr) y era codigo muerto — las dos barras
     que existen (barra-nav y barra-cliente) tienen 3 botones y lo pisan siempre. */
  grid-template-columns: repeat(3, 1fr);
  gap: 4px;
  padding: 8px;
  border: 1px solid var(--line);
  border-radius: 24px;
  background: rgba(255, 255, 255, .96);
  box-shadow: 0 14px 38px rgba(23, 32, 51, .18);
  backdrop-filter: blur(14px);
}
.nav-item {
  display: grid;
  place-items: center;
  gap: 2px;
  padding: 7px 4px;
  border-radius: 16px;
  background: transparent;
  color: var(--muted);
  font-size: 13px;
  font-weight: 850;
}
.nav-item span { font-size: 15px; line-height: 1.5; }
/* CHG-2026-0720 — el resaltado es el COLOR, no un cuadro detras. Eddy, 30-ago-2026:
   *"cuando selecione uno solo se resalte el icono y no pararesca un cuadro atras en
   azul"*. El icono es un <svg> con `fill: currentColor`, asi que el color del boton
   ya lo resalta solo — el `background` no aportaba nada mas que el cuadro.
   El `:hover` cae con el mismo hachazo a proposito: es la trampa del hover pegado
   del CHG-2026-0719 (en un telefono el navegador lo deja clavado al ultimo boton
   tocado). Arreglar solo `.active` habria dejado el cuadro azul vivo por ese lado. */
.nav-item:hover { background: transparent; color: var(--primary); }
.nav-item.active { background: transparent; color: var(--primary); }
/* Y el velo que pinta WebKit sobre lo que tocaste: es gris, no azul, pero deja el
   mismo cuadro detras del icono. Misma causa que en `.back-btn`. */
.nav-item { -webkit-tap-highlight-color: transparent; }
.nav-item:focus { outline: none; }
.nav-item:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
.nav-primary {
  transform: translateY(-16px);
  background: var(--primary);
  color: white;
  box-shadow: 0 10px 20px rgba(27, 110, 243, .28);
}
.nav-primary.active, .nav-primary:hover { background: var(--primary); color: white; }
.nav-primary span { font-size: 15px; }
.client-card .actions-row { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 8px; }
@media (min-width: 721px) {
  .mobile-shell { width: min(720px, 100%); }
  .bottom-nav { width: min(720px, calc(100% - 18px)); }
}
@media (max-width: 420px) {
  .stat-grid, .quick-actions { grid-template-columns: 1fr; }
  .nav-item { font-size: 13px; }
}

/* Clientes como historial de actividad */
.compact-client-card {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 3px 10px;
  text-align: left;
  color: var(--text);
  cursor: pointer;
}
.compact-client-card:hover { background: #f8fbff; }
.compact-client-card.selected { outline: 3px solid rgba(27, 110, 243, .16); border-color: var(--primary); }
.compact-client-card .client-card-title { font-weight: 900; }
.compact-client-card .client-status {
  align-self: start;
  border-radius: 999px;
  padding: 3px 8px;
  background: rgba(255,255,255,.7);
  color: var(--muted);
  font-size: 13px;
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: .02em;
}
.compact-client-card .meta {
  grid-column: 1 / -1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.client-activity-detail h3 { margin-top: 12px; }
.client-detail-header { display: flex; justify-content: space-between; gap: 12px; align-items: flex-start; }
.client-detail-header p { margin: 0; }
.client-detail-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: 12px 0;
}
.active-loans-list { display: grid; gap: 8px; margin-bottom: 10px; }
.activity-timeline { display: grid; gap: 8px; }
.activity-item {
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 10px 12px;
  background: #fff;
}
.activity-item strong { display: block; margin-bottom: 3px; }
.activity-item span { color: var(--muted); font-size: 15px; line-height: 1.5; }
.activity-item.payment { border-left: 4px solid var(--ok); }
.activity-item.loan { border-left: 4px solid var(--primary); }
@media (max-width: 420px) {
  .client-detail-actions { grid-template-columns: 1fr; }
}

/* Registrar: selector Pago / Préstamo */
.register-mode-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  margin: 4px 0 16px;
}
.register-mode-card {
  min-height: 74px;
  display: grid;
  place-items: center;
  gap: 2px;
  font-size: 15px;
}
.register-mode-card span { font-size: 15px; line-height: 1.5; }
.register-mode-card.active { background: var(--primary); color: #fff; }
.new-loan-panel {
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 14px;
  background: #fbfcff;
}
.new-loan-panel button { margin-top: 8px; }
@media (max-width: 420px) {
  .register-mode-grid { grid-template-columns: 1fr; }
}

/* Nuevo borrador corregido: Inicio + + + Ajustes */
.compact-bottom-nav {
  grid-template-columns: 1fr 1.1fr 1fr;
}
.home-stat-grid {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin-bottom: 8px;
}
.home-stat-grid .stat-card {
  padding: 10px;
  border-radius: 15px;
}
.home-stat-grid .stat-card span {
  font-size: 13px;
  margin-bottom: 5px;
}
/* CHG-2026-0552 — los montos salían CORTADOS: "RD$2,850.0", "RD$96,415.(",
 * "RD$4,820.7". Tres tarjetas fijas en 360px de ancho no dan para un monto de
 * seis cifras a 1.05rem.
 *
 * No se abrevia (nada de "RD$96.4k"): en una app de cobros un monto a medias o
 * redondeado es peor que uno chico. Se deja que el número BAJE de tamaño solo
 * hasta donde quepa, con `clamp` sobre el ancho del contenedor, y se le permite
 * partir si aun así no entra. */
.home-stat-grid .stat-card strong {
  font-size: 15px;
  overflow-wrap: anywhere;
  hyphens: none;
}
.home-stat-grid .stat-card { container-type: inline-size; }
.compact-home-card {
  margin: 8px 0 0;
  padding: 12px;
}
/* CHG-2026-0677 — UNA sola declaracion. Estaba en tres sitios (aqui, en la 1322
   y en la 1692) y las tres se contradecian: la primera ponia `max-height:42dvh`
   con `overflow-y:auto` y la ultima lo desactivaba. Lo que de verdad regia era lo
   de abajo; ahora esta escrito una vez, que es lo unico que evita que manana
   alguien "arregle" el scroll mirando la regla equivocada. */
.compact-history {
  display: grid;
  gap: 6px;
  max-height: none;
  /* OJO: `overflow-x: hidden` NO sirve aqui. Por spec CSS, si un eje no es
     `visible`, el otro se computa como `auto` — o sea que poner el candado
     horizontal reponia el scroll vertical que este cambio vino a quitar (medido:
     overflowY salia 'auto' aun sin declararlo). `clip` corta igual y deja el eje
     Y en visible de verdad. El candado de palabras largas del 14-jul sigue
     entero: min-width 0 y overflow-wrap, aqui abajo. */
  overflow-y: visible;
  overflow-x: clip;
  padding-bottom: 4px;
}
.compact-movement {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 8px;
  align-items: center;
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 8px 10px;
  background: #fff;
  font-size: 15px;
}
.compact-movement strong { color: var(--primary); }
.compact-movement span {
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.historial-row span {
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  line-height: 1.5;
}
.flow-panel { margin-top: 10px; }
.scroll-client-list {
  display: grid;
  gap: 8px;
  max-height: 42dvh;
  overflow-y: auto;
  padding: 2px 2px 88px;
  overscroll-behavior: contain;
}
.client-row-button {
  width: 100%;
  display: grid;
  gap: 3px;
  text-align: left;
  background: #fbfcff;
  color: var(--text);
  border: 1px solid var(--line);
  padding: 11px 12px;
}
.client-row-button:hover { background: var(--soft); color: var(--text); }
.client-row-button span {
  color: var(--muted);
  font-size: 13px;
}
.summary-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}
.summary-grid > div {
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 9px;
  background: #fff;
}
.summary-grid span {
  display: block;
  color: var(--muted);
  font-size: 13px;
  font-weight: 800;
  margin-bottom: 4px;
}
.summary-grid strong { font-size: 15px; }
@media (max-width: 420px) {
  .home-stat-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .home-stat-grid .stat-card { padding: 8px 6px; }
  .home-stat-grid .stat-card span { font-size: 13px; }
  .home-stat-grid .stat-card strong { font-size: 15px; }
  .summary-grid { grid-template-columns: 1fr; }
}

/* Borrador 2: flujo por pantallas */
.step-header {
  margin: 0 0 10px;
}
.step-panel[hidden] { display: none !important; }
.step-panel h2 { margin-bottom: 12px; }

/* Borrador 3: pago compacto sin scroll */
#paymentLoanStep.active-compact,
#paymentFormPanel.active-compact { overflow: hidden; }
#paymentLoanStep .detail-panel,
#paymentFormPanel {
  margin-top: 4px;
}
.compact-summary-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px;
}
.compact-summary-grid > div {
  padding: 7px 8px;
}
.compact-summary-grid span {
  font-size: 13px;
  margin-bottom: 2px;
}
.compact-summary-grid strong {
  font-size: 13px;
  line-height: 1.5;
}
#paymentLoanStep h2,
#paymentFormPanel h2 {
  margin-bottom: 8px;
  font-size: 15px;
}
#paymentLoanStep h3 {
  margin-bottom: 7px;
  font-size: 15px;
}
#paymentFormPanel .payment-type-panel {
  margin: 4px 0 8px;
}
#paymentFormPanel .field-title,
#paymentFormPanel .hint {
  display: none;
}
#paymentFormPanel .choice-grid {
  grid-template-columns: repeat(3, 1fr);
  gap: 4px;
  padding: 3px;
  border: 1px solid var(--line);
  border-radius: 13px;
  background: #fff;
}
#paymentFormPanel .choice-button {
  min-height: auto;
  padding: 8px 5px;
  border-radius: 10px;
  font-size: 13px;
  line-height: 1.5;
}
#paymentFormPanel label {
  gap: 4px;
  margin-bottom: 7px;
  font-size: 13px;
}
#paymentFormPanel input,
#paymentFormPanel select,
#paymentFormPanel textarea {
  padding: 9px 9px;
  border-radius: 10px;
  font-size: 15px;
}
#paymentFormPanel .grid {
  /* 8, no 7: dos campos que se tocan no pueden quedar a menos de 8px. Y esta
     regla le gana a `#paymentAmountsGrid` (id + clase pesa mas que id solo):
     subir el gap de la rejilla de los montos no movia el numero porque el que
     mandaba era ESTE. Medido el 19-sep-2026, tres intentos. */
  gap: 8px;
}
#paymentFormPanel .warnings {
  padding: 8px;
  margin: 6px 0;
  font-size: 13px;
}
#paymentFormPanel .sticky-actions {
  padding-top: 5px;
}
#paymentFormPanel .sticky-actions button,
#showPaymentFormBtn {
  padding: 10px 12px;
}
.compact-client-row {
  padding: 9px 10px;
}
.compact-client-row span {
  font-size: 13px;
}
.compact-client-row.paid {
  border-color: #abefc6;
  background: #f0fdf4;
}
.compact-client-row.pending {
  border-color: #fedf89;
  background: #fffbeb;
}
@media (max-width: 420px) {
  #paymentFormPanel .three {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  #paymentFormPanel .two {
    grid-template-columns: 1fr 1fr;
  }
  #paymentFormPanel textarea {
    min-height: 38px;
  }
}

/* Borrador 3: préstamo compacto sin scroll */
#loanFormPanel,
#clientFormPanel {
  overflow: hidden;
}
#loanFormPanel h2,
#clientFormPanel h2 {
  margin-bottom: 8px;
  font-size: 15px;
  line-height: 1.5;
}
#loanFormPanel label,
#clientFormPanel label {
  gap: 4px;
  margin-bottom: 7px;
  font-size: 13px;
}
#loanFormPanel input,
#clientFormPanel input,
#clientFormPanel select,
#clientFormPanel textarea {
  padding: 9px 9px;
  border-radius: 10px;
  font-size: 15px;
}
#loanFormPanel .grid,
#clientFormPanel .grid {
  gap: 7px;
}
#loanFormPanel button,
#clientFormPanel button {
  margin-top: 2px;
  padding: 10px 12px;
}
#loanFormPanel .three {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
#loanFormPanel .two,
#clientFormPanel .two {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
#clientFormPanel textarea {
  min-height: 38px;
}
@media (max-width: 420px) {
  #loanFormPanel .three {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  #loanFormPanel .two,
  #clientFormPanel .two {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  #loanFormPanel input,
  #clientFormPanel input,
  #clientFormPanel select,
  #clientFormPanel textarea {
    font-size: 13px;
    padding: 8px 7px;
  }
}

/* Borrador 3 app-only: modalidad préstamo y eliminar del app */
.loan-mode-toggle {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px;
  padding: 3px;
  margin: 2px 0 8px;
  border: 1px solid var(--line);
  border-radius: 13px;
  background: #fff;
}
.loan-mode-button {
  padding: 8px 6px;
  border-radius: 10px;
  font-size: 13px;
}
.loan-mode-button.active {
  background: var(--primary);
  color: #fff;
}
.compact-loan-grid {
  margin-bottom: 2px;
}
.compact-movement {
  width: 100%;
  text-align: left;
  color: var(--text);
}
.compact-movement.selected {
  border-color: var(--danger);
  background: #fff1f0;
  outline: 2px solid rgba(180, 35, 24, .12);
}
.danger-action {
  width: 100%;
  margin-top: 8px;
  background: #fff1f0;
  color: var(--danger);
  border: 1px solid #fda29b;
}
.danger-action:hover {
  background: #fee4e2;
  color: var(--danger);
}

/* Borrador 4: basurero al lado y métricas revertidas */
.compact-movement-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 6px;
  align-items: stretch;
}
.compact-movement-row.selected .compact-movement {
  border-color: var(--danger);
  background: #fff1f0;
  outline: 2px solid rgba(180, 35, 24, .12);
}
.movement-actions {
  display: grid;
  grid-template-columns: auto auto;
  gap: 6px;
}
.movement-edit,
.movement-trash {
  min-width: 42px;
  padding: 0 10px;
  display: grid;
  place-items: center;
  border-radius: 12px;
  font-size: 15px;
}
.movement-edit {
  border: 1px solid var(--line);
  background: #fff;
  color: var(--text);
}
.movement-trash {
  border: 1px solid #fda29b;
  background: #fff1f0;
  color: var(--danger);
}
.movement-edit:hover { background: #f9fafb; }
.movement-trash:hover {
  background: #fee4e2;
  color: var(--danger);
}

/* Edición/eliminación rápida desde la app */
.client-manage-row,
.manage-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 8px;
  align-items: center;
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 8px;
  background: #fff;
}
.client-manage-row .client-row-button {
  border: 0;
  padding: 4px;
  background: transparent;
}
.management-panel {
  display: grid;
  gap: 7px;
  margin-top: 12px;
}
.management-panel h4 {
  margin: 8px 0 0;
  font-size: 15px;
}
.manage-row.active { border-color: var(--primary); background: var(--soft); }
.manage-row.payment { border-left: 4px solid var(--ok); }
.manage-row strong { display: block; font-size: 15px; }
.manage-row span { display: block; color: var(--muted); font-size: 13px; line-height: 1.5; }
.manage-actions { display: flex; gap: 6px; align-items: center; }
.danger-mini {
  width: auto;
  padding: 9px 10px;
  border: 1px solid #fda29b;
  background: #fff1f0;
  color: var(--danger);
  font-size: 13px;
}
.danger-mini:hover { background: #fee4e2; color: var(--danger); }
.manage-empty { margin: 0; font-size: 13px; }
@media (max-width: 420px) {
  .client-manage-row,
  .manage-row { grid-template-columns: 1fr; }
  .manage-actions { display: grid; grid-template-columns: 1fr 1fr; }
  .manage-actions .small-btn,
  .manage-actions .danger-mini { width: 100%; }
}


/* Implementación borrador 2026-05-27 */
input[type=number]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
input[type=number] { -moz-appearance: textfield; }
.locked-field,
input[readonly] {
  background: #f8fafc;
  color: #667085;
}
.loan-preset-panel {
  display: grid;
  gap: 7px;
  margin: 0 0 8px;
}
.loan-preset-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
}
.loan-preset-button {
  min-height: auto;
  padding: 8px 6px;
  border-radius: 12px;
  background: #fff;
  color: var(--text);
  border: 1px solid var(--line);
}
.loan-preset-button strong,
.loan-preset-button span {
  display: block;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.loan-preset-button strong { color: var(--primary); font-size: 13px; }
.loan-preset-button span { color: var(--muted); font-size: 13px; margin-top: 2px; }
#loanValidationMessage {
  padding: 8px 10px;
  margin: 4px 0 8px;
  border-radius: 12px;
  border: 1px solid #fda29b;
  background: #fff1f0;
  color: var(--danger);
  font-size: 13px;
  font-weight: 800;
}
.client-row-button,
.compact-movement,
.manage-row > div,
.client-manage-row > div { min-width: 0; }
.client-row-button strong,
.client-row-button span,
.compact-movement strong,
.compact-movement span,
.manage-row strong,
.manage-row span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
@media (max-width: 420px) {
  .loan-preset-grid { grid-template-columns: 1fr; }
}

/* Pantalla de detalle desde historial */
.home-detail-header { padding: 4px 0 8px; }
.detail-card { padding: 12px !important; }
.detail-card h2 { font-size: 15px; margin-bottom: 8px; }
.detail-view-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px 10px;
  margin-bottom: 10px;
}
.detail-view-field { display: grid; gap: 2px; min-width: 0; }
.detail-view-field span { color: var(--muted); font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; }
.detail-view-field strong { font-size: 13px; word-break: break-word; overflow-wrap: anywhere; }
.detail-view-field.readonly strong { color: var(--muted); }
.detail-error { border: 1px solid #fda29b; border-radius: 12px; padding: 10px 12px; background: #fff1f0; color: var(--danger); font-size: 13px; font-weight: 700; margin-bottom: 12px; }
.detail-delete-confirm { border: 1px solid #fda29b; border-radius: 16px; padding: 14px; background: #fff8f7; }
.detail-delete-confirm p { margin: 0 0 12px; font-weight: 700; color: var(--danger); font-size: 15px; }
.btn-danger { background: #fff1f0; border: 1px solid #fda29b; color: var(--danger); }
.btn-danger:hover { background: #fee4e2; color: var(--danger); }
.detail-card-header { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; }
.detail-card-header h2 { margin: 0; }
.btn-danger-mini { width: auto; padding: 5px 10px; font-size: 13px; font-weight: 700; border-radius: 10px; background: #fff1f0; border: 1px solid #fda29b; color: var(--danger); white-space: nowrap; flex-shrink: 0; }
.btn-danger-mini:hover { background: #fee4e2; color: var(--danger); }

/* §12 borrador 2026-05-27: nombres largos no deben sobresalir del contenedor */
.detail-panel,
.summary-grid,
#paymentLoanSummary,
#selectedLoanClientName { min-width: 0; }
#paymentLoanSummary h3,
.detail-panel h3,
#selectedLoanClientName {
  margin: 0 0 8px;
  overflow-wrap: anywhere;
  word-break: break-word;
}
.summary-grid > div { min-width: 0; }
.summary-grid strong {
  overflow-wrap: anywhere;
  word-break: break-word;
}

/* Job #53 (Agente 5, job 5a): login + sesión de la app de Cobradores (8091). */
.auth-shell[hidden] { display: none; }
/* CHG-2026-0553 — la puerta de la app tenía CERO identidad: una tarjeta blanca
 * sobre gris plano. El 8082 ya resolvió esto (login.js: ilustración de fondo +
 * velo + tarjeta con sombra) y Eddy lo aprobó el 10-ago-2026; aquí se repite el
 * mismo tratamiento para que las dos apps se sientan la misma casa.
 *
 * El degradado va en CSS y no como imagen a propósito: esta app la abren en la
 * calle, muchas veces con datos móviles, y no vale la pena gastar 116 KB en un
 * fondo. El azul es el mismo `--primary` de la marca. */
.auth-shell {
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px 16px;
  background:
    radial-gradient(1200px 600px at 50% -10%, rgba(37, 99, 235, .22), transparent 60%),
    radial-gradient(900px 500px at 50% 110%, rgba(0, 168, 132, .14), transparent 60%),
    var(--bg);
}
.auth-card {
  width: min(420px, 100%);
  box-shadow: 0 18px 40px -18px rgba(15, 23, 42, .28);
}
/* El ojo para ver la clave. En un teléfono, a pleno sol y escribiendo con el
   pulgar, una clave de 10 caracteres sin poder mirarla es la vía rápida a
   quedarse fuera. Va dentro del label, que ya es el contenedor del input. */
.campo-clave { position: relative; }
.campo-clave input { padding-right: 44px; }
.ojo-clave {
  position: absolute;
  right: 6px;
  bottom: 4px;
  width: 38px;
  height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  padding: 0;
  color: var(--muted);
  cursor: pointer;
}
.ojo-clave:hover { color: var(--primary); background: none; }
.ojo-clave .mi { width: 20px; height: 20px; }
.auth-brand { margin-bottom: 18px; }
/* CHG-2026-0856 — el logo de la pantalla de entrar (y hermanas: olvide clave,
   reset, primer ingreso, forzar cambio, PIN). Antes heredaba el `.app-icon`
   generico de 36px (pensado para el header chico dentro de la app) y por eso
   Eddy lo vio "que no encaja". Aqui se agranda SOLO en estas pantallas y se
   quita el fondo/sombra de icono, porque ahora adentro va el logo real (con
   su propio color), no un glifo blanco sobre un cuadro de color. */
.auth-brand .app-icon {
  width: 64px;
  height: 64px;
  background: none;
  box-shadow: none;
  border-radius: 0;
}
.auth-brand .app-icon-img { width: 100%; height: 100%; object-fit: contain; display: block; }
.session-banner {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 10px 16px;
  background: var(--warning);
  color: #fff;
  font-weight: 650;
  font-size: 15px;
}
.session-banner .secondary { background: #fff; color: var(--warning); }

/* Job #57 (Agente 5, job 5b): "Olvidé mi clave". */
.link-btn {
  background: none;
  border: none;
  color: var(--accent, #2563eb);
  font-size: 15px;
  padding: 4px 0;
  margin-top: 6px;
  text-align: center;
  width: 100%;
  cursor: pointer;
  text-decoration: underline;
}

/* ═══════════════════════════════════════════════════════════════════════
   REDISEÑO 14-jul-2026 — cara CrediJim (alineado al 8082)
   Va al FINAL a propósito: el cascade pisa las reglas viejas de arriba.
   Backup: styles.css.bak-diseno-8082-20260714
   ═══════════════════════════════════════════════════════════════════════ */

/* — Tarjetas: blancas, borde gris fino, sombra sutil (como el 8082) — */
.card {
  border-radius: 14px;
  border: 1px solid var(--line-soft);
  box-shadow: 0 1px 2px rgba(17, 24, 39, .05);
}

/* — Header: barra blanca con borde, marca CrediJim — */
.mobile-header {
  background: #fff;
  border: 1px solid var(--line-soft);
  border-radius: 14px;
  padding: 10px 14px;
  margin-bottom: 6px;
  box-shadow: 0 1px 2px rgba(17, 24, 39, .05);
}
.app-icon {
  /* CHG-2026-0694 — NO se achico el logo, y aqui esta la razon medida: el alto del
     header lo manda la CAMPANA de avisos (44px, el minimo del dedo), no el logo.
     Con el logo en 32 el header seguia midiendo 62px exactos. Achicarlo era tocar
     por tocar. Ademas esta declaracion tampoco gana: la pisa `.app-icon` del
     bloque "UX PRO 14-jul" (36px), mas abajo. */
  width: 40px;
  height: 40px;
  border-radius: 12px;
  background: none;   /* A7 (CHG-2026-0863) — sin fondo azul, logo suelto */
  box-shadow: none;
}
.app-icon .mi { width: 20px; height: 20px; color: #fff; }
.mobile-header h1 { font-size: 15px; font-weight: 800; }
/* CHG-2026-0694 — los subtitulos que no decian nada se vaciaron en screenMeta.
   Sin esto el <p> vacio sigue ocupando su renglon y no se ahorra nada. */
.head-text p:empty { display: none; }
.badge { padding: 5px 10px; font-size: 13px; font-weight: 700; }

/* — Banner de sesión: EMPUJA el contenido, ya no tapa el header — */
.session-banner {
  position: sticky;
  border-radius: 0 0 12px 12px;
}

/* — Tarjetas de métricas estilo 8082: blancas + ícono en círculo de color — */
.stat-card,
.home-stat-grid .stat-card {
  display: flex;
  align-items: center;
  gap: 10px;
  background: #fff;
  border: 1px solid var(--line-soft);
  border-radius: 14px;
  padding: 12px 10px;
  box-shadow: 0 1px 2px rgba(17, 24, 39, .05);
}
.stat-icon {
  width: 34px;
  height: 34px;
  border-radius: 999px;
  display: grid;
  place-items: center;
  flex-shrink: 0;
}
.stat-icon .mi { width: 17px; height: 17px; }
.stat-icon.blue   { background: #eff6ff; color: #2563eb; }
.stat-icon.green  { background: #f0fdf4; color: #16a34a; }
.stat-icon.orange { background: #fff7ed; color: #f97316; }
.stat-icon.purple { background: #f5f3ff; color: #7c3aed; }
.stat-card > div { min-width: 0; }
.stat-card span:not(.stat-icon),
.home-stat-grid .stat-card span:not(.stat-icon) { font-size: 13px; margin-bottom: 2px; color: var(--muted); font-weight: 600; }
.stat-card strong,
.home-stat-grid .stat-card strong { font-size: 15px; font-weight: 800; color: var(--text); }
/* En móvil (el mundo real de la 8091) las 3 tarjetas van ícono-arriba para
   que el monto nunca se corte contra el borde. */
@media (max-width: 560px) {
  .stat-card, .home-stat-grid .stat-card { flex-direction: column; align-items: flex-start; gap: 6px; padding: 10px; }
  .stat-icon { width: 30px; height: 30px; }
  .stat-icon .mi { width: 15px; height: 15px; }
  .stat-card strong, .home-stat-grid .stat-card strong { font-size: 15px; }
}

/* — Chips de filtro (Por cobrar / Movimientos) estilo 8082 — */
.chip-row { display: flex; gap: 6px; flex-wrap: wrap; }
.chip {
  width: auto;
  padding: 6px 13px;
  border-radius: 999px;
  background: #fff;
  border: 1px solid var(--line);
  color: var(--muted);
  font-size: 13px;
  font-weight: 700;
}
.chip:hover { background: var(--soft); color: var(--primary); }
.chip.active { background: var(--primary); border-color: var(--primary); color: #fff; }
.chip.active:hover { background: var(--primary-dark); color: #fff; }

/* — Barra inferior: 5 posiciones + botón central elevado (patrón app móvil) — */
.bottom-nav {
  grid-template-columns: repeat(5, 1fr);
  /* CHG-2026-0834 (10-sep-2026): medido en vivo (getComputedStyle) -- esta es
     la regla que de verdad gana la cascada (el bloque de arriba, gap:4px,
     queda tapado). Con 113px por columna sobra espacio de sobra: "2px entre
     Inicio y su vecino, minimo 8" en 5 vistas del 8091 (home/movimientos/
     more, pc y telefono). */
  gap: 8px;
  padding: 6px 8px calc(6px + env(safe-area-inset-bottom));
  border-radius: 20px;
  border: 1px solid var(--line-soft);
  align-items: end;
}
.nav-item {
  padding: 7px 2px 5px;
  gap: 3px;
  font-size: 13px;
  font-weight: 700;
  border-radius: 12px;
}
.nav-item .mi { width: 21px; height: 21px; }
.nav-primary {
  width: 52px;
  height: 52px;
  padding: 0;
  border-radius: 999px;
  margin: 0 auto;
  transform: translateY(-20px);
  display: grid;
  place-items: center;
  box-shadow: 0 8px 18px rgba(37, 99, 235, .35);
}
.nav-primary .mi { width: 26px; height: 26px; }

/* — Pantalla "Más": menú de filas con ícono + descripción — */
.menu-card { padding: 6px 8px; }
.menu-row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  background: transparent;
  color: var(--text);
  border: 0;
  border-radius: 0;
  padding: 15px 6px;
  text-align: left;
}
.menu-row:last-child { border-bottom: 0; }
.menu-row:hover { background: var(--soft); border-radius: 10px; }
.menu-ico {
  width: 38px;
  height: 38px;
  border-radius: 12px;
  display: grid;
  place-items: center;
  background: var(--soft);
  color: var(--primary);
  flex-shrink: 0;
}
.menu-ico .mi { width: 19px; height: 19px; }
.menu-text { flex: 1; display: grid; gap: 1px; min-width: 0; }
.menu-text strong { font-size: 15px; font-weight: 700; }
.menu-text span { color: var(--muted); font-size: 13px; font-weight: 500; line-height: 1.5; }
/* CHG-2026-0834 (T1, 10-sep-2026): medido por cj-diseno con SELECTOR real (no
   "sin selector") -- es TEXTO (un caracter ">", no un icono material), asi que
   el piso es 4.5:1, no 3:1. #9ca3af daba 2.43:1 contra #f8fafc. Mismo tono,
   mas oscuro: ~5.0:1. */
.menu-row .chev { color: #6B6D75; font-size: 15px; font-weight: 400; }

/* — Formularios compactos como los modales del 8082 — */
label { font-size: 13px; font-weight: 600; color: #374151; gap: 5px; margin-bottom: 10px; }
input, select, textarea { padding: 10px 12px; border-radius: 10px; font-size: 15px; }
button { border-radius: 10px; font-weight: 700; }
input:focus, select:focus, textarea:focus { outline: 3px solid rgba(37, 99, 235, .15); border-color: var(--primary); }

/* — Estados vacíos centrados con aire (en vez de texto suelto) — */
.compact-history.muted,
.scroll-client-list.muted,
#paymentClientList.muted {
  display: grid;
  place-items: center;
  text-align: center;
  padding: 30px 14px;
  font-size: 15px;
}

/* — Filas de la lista "Por cobrar" de la home — */
.due-row {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px 10px;
  align-items: center;
  text-align: left;
  background: #fff;
  color: var(--text);
  border: 1px solid var(--line-soft);
  border-radius: 12px;
  padding: 10px 12px;
}
.due-row:hover { background: var(--soft); color: var(--text); }
.due-row strong { font-size: 15px; font-weight: 700; }
.due-row .due-meta { grid-column: 1; color: var(--muted); font-size: 13px; font-weight: 500; }
.due-row .estado-chip {
  grid-row: 1 / span 2;
  grid-column: 2;
  border-radius: 999px;
  padding: 4px 10px;
  font-size: 13px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .03em;
}
.estado-chip.pendiente { background: #fff7ed; color: #c2410c; }
.estado-chip.pagado { background: #f0fdf4; color: #15803d; }
.estado-chip.atrasado { background: #fef2f2; color: #b91c1c; }

/* — Fixes de visibilidad (14-jul): display:grid/flex pisaba el atributo hidden —
   La nav y el banner se veían hasta en el login. */
.bottom-nav[hidden] { display: none; }
.session-banner[hidden] { display: none; }

/* — El botón sticky de los formularios se pega ARRIBA de la nav flotante,
   no debajo (antes quedaba tapado al hacer scroll) — */
.mobile-shell .sticky-actions {
  bottom: calc(84px + env(safe-area-inset-bottom));
  border-radius: 12px;
}

/* — Fase 2 calle (14-jul): PIN, hoja de cobro y cola offline — */
.pin-input {
  font-size: 15px;
  letter-spacing: .55em;
  text-align: center;
  font-weight: 800;
}
.sheet-progress {
  display: grid;
  gap: 6px;
  padding: 4px 2px 8px;
}
.sheet-progress span { color: var(--muted); font-size: 13px; font-weight: 600; }
.sheet-progress span strong { color: var(--text); font-weight: 800; }
.sheet-bar {
  height: 8px;
  border-radius: 999px;
  background: var(--line-soft);
  overflow: hidden;
}
.sheet-bar i {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--ok);
  /* CHG-2026-0639 (hallazgo #56) — se quita `transition: width .3s ease`.
     Animar `width` fuerza remaquetado, pero aqui ni siquiera animaba: la barra
     se pinta con innerHTML desde app.js:1897 (`<i style="width:${pct}%">`), o
     sea que el nodo NACE con su ancho final y se RECREA en cada render. Una
     transicion necesita un valor previo que cambie; aqui nunca lo hubo. Era
     codigo muerto, y por eso quitarlo no le cuesta nada a la interfaz. */
}
.cola-aviso {
  width: 100%;
  text-align: left;
  font-size: 13px;
  cursor: pointer;
  margin: 0 0 8px;
}

/* ═══ Pulido profesional 14-jul (noche): sin scroll lateral + modales 8082 ═══ */

/* — FIX scroll lateral en las listas de la home: una palabra larga (nombres
   sin espacios) forzaba la fila a más ancho que la tarjeta. Candado triple:
   partir palabras, min-width 0, y jamás scroll-x en las listas. — */
.compact-history > * { min-width: 0; max-width: 100%; }
.due-row strong,
.due-row .due-meta,
.compact-movement strong {
  min-width: 0;
  overflow-wrap: anywhere;
  word-break: break-word;
}
.sheet-progress, .sheet-progress span { min-width: 0; max-width: 100%; }

/* — Letras más pequeñas en el inicio (pedido de Eddy) — */
.mobile-header h1 { font-size: 15px; }
.mobile-header .eyebrow { font-size: 13px; }
.mobile-header .muted { font-size: 13px; }
.badge { padding: 4px 9px; font-size: 13px; }
.home-stat-grid .stat-card span { font-size: 13px; }
.home-stat-grid .stat-card strong { font-size: 15px; }
.chip { padding: 5px 11px; font-size: 13px; }
.due-row { padding: 9px 11px; }
.due-row strong { font-size: 13px; }
.due-row .due-meta { font-size: 13px; }
.due-row .estado-chip { padding: 3px 8px; font-size: 13px; }
.sheet-progress span { font-size: 13px; }
.compact-home-card .section-title h2 { font-size: 15px; }

/* — Modal de confirmación estilo 8082 (overlay rgba(15,23,42,.16) + blur(3px),
   tarjeta blanca rounded-2xl border gray-100, animación fade+scale) — */
.cj-modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  background: rgba(15, 23, 42, .16);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  opacity: 0;
  transition: opacity .15s ease;
}
.cj-modal[hidden] { display: none; }
.cj-modal.abierto { opacity: 1; }
.cj-modal-card {
  width: min(400px, 100%);
  background: #fff;
  border: 1px solid var(--line-soft);
  border-radius: 16px;
  box-shadow: 0 10px 30px rgba(15, 23, 42, .12);
  transform: translateY(8px) scale(.97);
  transition: transform .18s ease-out;
}
.cj-modal.abierto .cj-modal-card { transform: none; }
.cj-modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 14px 16px 10px;
}
.cj-modal-head h2 { margin: 0; font-size: 15px; font-weight: 800; color: var(--text); }
.cj-modal-x {
  width: 30px;
  height: 30px;
  padding: 0;
  display: grid;
  place-items: center;
  border-radius: 999px;
  background: transparent;
  color: #9ca3af;
}
.cj-modal-x:hover { background: var(--line-soft); color: var(--muted); }
.cj-modal-x .mi { width: 17px; height: 17px; }
.cj-modal-msg {
  margin: 0;
  padding: 14px 16px;
  font-size: 15px;
  line-height: 1.5;
  color: #374151;
  white-space: pre-line;
  overflow-wrap: anywhere;
  max-height: 50dvh;
  overflow-y: auto;
}
.cj-modal-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  padding: 10px 16px 14px;
}
.cj-modal-actions button {
  width: auto;
  padding: 9px 18px;
  font-size: 13px;
}
.cj-modal-actions .btn-rojo {
  background: var(--danger);
  color: #fff;
}
.cj-modal-actions .btn-rojo:hover { background: #b91c1c; }
@media (max-width: 720px) {
  .cj-modal-actions button { width: auto; }
}

/* ═══════════════════════════════════════════════════════════════════════
   UX PRO 14-jul (noche 3) — jerarquía, componentes y consistencia.
   Escala de espacios: 4/8/12/16/24/32. Radios: 12-16 tarjetas, 999 chips.
   Táctil mínimo 44px. Sin scroll anidado. Backup: .bak-uxpro-20260714
   ═══════════════════════════════════════════════════════════════════════ */

/* — Tarjetas: menos sombra, borde limpio, respiración uniforme — */
/* CHG-2026-0694: padding 16 -> 12, dentro de la escala 4/8/12/16 que declara el
   encabezado de este bloque. Es la declaracion que GANA (la de arriba del archivo
   no aplica). El margen se queda en 8: tambien es de la escala. */
.card { box-shadow: none; border-radius: 14px; padding: 12px; margin: 8px 0; }
.compact-home-card { padding: 12px; margin: 8px 0 0; }
.stat-card, .home-stat-grid .stat-card { box-shadow: none; }

/* — AppHeader: UNA línea de altura, título dominante, punto de conexión — */
.mobile-header {
  box-shadow: none;
  padding: 8px 12px;
  border-radius: 12px;
  min-height: 56px;
}

/* CHG-2026-0677 — LAS BANDAS DEL HEADER STICKY.
   El header es una tarjeta blanca redondeada mas estrecha que la pantalla: el
   `.app` le pone 18px de padding a cada lado. Mientras Inicio no scrolleaba eso
   daba igual, pero ahora que baja como las demas, las tarjetas de arriba se
   veian PASAR POR DETRAS asomando por los dos costados (cazado en la captura del
   censo, no en el codigo).
   Se tapa con dos sombras solidas del color del fondo, una por lado. Lo obvio
   habria sido un `::before` estirado, pero NO sirve: `position:sticky` con
   z-index crea contexto de apilado, asi que un hijo con z-index:-1 se pinta
   ENCIMA del blanco del header y se lo come. La sombra se pinta fuera de la
   caja y no toca el contenido.
   Arriba no hace falta nada: el header se pega a top:0 y por encima no queda
   pantalla. */
.mobile-header {
  box-shadow: -18px 0 0 var(--bg), 18px 0 0 var(--bg);
}
.head-brand { min-width: 0; flex: 1; }
.head-text { min-width: 0; flex: 1; }
/* CHG-2026-0755 — en las 4 pantallas del cliente el logo se esconde (le da el
   espacio al nombre) y el nombre se vuelve tocable, con el mismo trato de dedo
   que tenia el boton que se retiro del Perfil. Las clases las pone showScreen(). */
.head-brand.sin-logo .app-icon { display: none; }
.head-text.head-text-link { cursor: pointer; min-height: 44px; display: flex; flex-direction: column; justify-content: center; }
.mobile-header h1 {
  font-size: 15px;
  line-height: 1.5;
  margin: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
/* CHG-2026-0834 (11-sep-2026, barrido a 0): mismo trato que `.mobile-header
   h1` (arriba) -- el subtitulo (nombre del cobrador, etiqueta del periodo)
   se cortaba con "…" en una sola linea en movimientos(telefono), 360px de
   ancho. Se cambia de recorte de 1 linea a envuelto con tope de 2 -- el caso
   normal (texto corto) no cambia ni un pixel; solo el texto largo usa la
   segunda linea en vez de cortarse. */
.mobile-header .muted {
  font-size: 13px;
  margin: 1px 0 0;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.app-icon { width: 36px; height: 36px; border-radius: 10px; }
.app-icon .mi { width: 18px; height: 18px; }
/* CHG-2026-0862 — la imagen de .app-icon-img NUNCA tenia una regla generica que la
   ajustara a su caja: solo existia `.auth-brand .app-icon-img` (la de la pantalla de
   entrar). Fuera de esa pantalla el navegador dibujaba el PNG a su tamaño real
   (192x192), desbordando por completo la caja de 36px del encabezado -- medido con
   WebKit antes de este cambio: contenedor 36x36, imagen 192x192. Esta regla hace que
   la imagen SIEMPRE llene la caja de .app-icon que la contenga, sea de 36px (header)
   o de 64px (entrar, via .auth-brand que sigue ganando por especificidad). */
.app-icon-img { width: 100%; height: 100%; object-fit: contain; display: block; }
.conn-dot {
  width: 10px;
  height: 10px;
  border-radius: 999px;
  background: #d1d5db;
  flex-shrink: 0;
  margin-right: 2px;
}
.conn-dot.ok { background: var(--ok); }

/* — StatusBadge: estados SIEMPRE con texto, no solo color — */
.badge-estado {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  border-radius: 999px;
  padding: 3px 9px;
  font-size: 13px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .03em;
  white-space: nowrap;
}
.badge-estado.ok    { background: #f0fdf4; color: #15803d; }
.badge-estado.warn  { background: #fff7ed; color: #c2410c; }
.badge-estado.bad   { background: #fef2f2; color: #b91c1c; }
/* CHG-2026-0551 — el neutro daba 4.39:1 medido (#6b7280 sobre #f3f4f6), justo por
   debajo del 4.5 que pide la regla de contraste. Se oscurece el texto un paso:
   mismo gris de la familia, 7.0:1. Es el mismo par que usa `.cj-badge.neutro`
   del 8082, para que el estado se vea igual en las dos apps. */
.badge-estado.neutro{ background: #f3f4f6; color: #4b5563; }
/* CHG-2026-0551 — `info` y `done` FALTABAN, y el paquete compartido las produce:
   `activo` devuelve `info` y `saldado` devuelve `done`
   (packages/formulas_comun/formulas.js). Sin estas dos reglas, esos dos estados
   salían con la forma del badge pero SIN color — un badge transparente.
   Mismos valores que `.cj-badge` del 8082: es el mismo lenguaje para las dos. */
.badge-estado.info  { background: #eff6ff; color: #1d4ed8; }
.badge-estado.done  { background: #faf5ff; color: #7e22ce; }

/* ⛔ CHG-2026-0759 (C9) — AQUI VIVIA `.pago-quien`, el vestido de la tarjeta de
   avisos de la sesion de pago. Eddy la mando quitar por ruido visual y se fue
   entera: el HTML, la funcion que la pintaba y estas reglas. Se borran en vez de
   dejarlas "por si acaso" — CSS que no viste a nadie es lo que hace que el
   proximo barrido tenga que averiguar si algo sigue vivo. */


/* CHG-2026-0654 — "Para <cliente>" en el panel de eleccion de Registrar.
   Copiaba el molde de `.pago-quien` (misma barra lateral, mismo fondo suave)
   para que las dos cajas que dicen "a quien le estas registrando esto" se
   leyeran igual; aqui va en una sola linea porque comparte renglon con "Elegir
   otro". El CHG-2026-0759 retiro `.pago-quien`, asi que estos valores ya no
   copian nada: son los suyos propios y estan escritos completos abajo. */
.registro-para {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: 0 0 14px;
  padding: 10px 12px;
  border-radius: 12px;
  background: var(--soft);
  border-left: 3px solid var(--primary);
}
/* Sin esto el `display:flex` de arriba le gana al atributo `hidden` (que solo
   trae `display:none` de la hoja del navegador) y la caja se queda VISIBLE y
   VACIA cuando no hay cliente enlazado. Lo cazo el test de CHG-2026-0654. */
.registro-para[hidden] { display: none; }

.registro-para-texto {
  font-size: 15px;
  color: var(--text);
}

/* — ClientRow: avatar + nombre + datos + saldo + estado + flecha — */
.crow {
  width: 100%;
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  gap: 4px 10px;
  align-items: center;
  text-align: left;
  background: #fff;
  color: var(--text);
  border: 1px solid var(--line-soft);
  border-radius: 12px;
  padding: 10px 12px;
  min-height: 56px;
}
/* CHG-2026-1073 (vigilante #1160 #1170 #1278): el celeste de «pasar por encima» SOLO donde hay ratón.
   En el teléfono, después de tocar una fila, :hover se queda pegado: la caja la medía como plancha
   celeste y la línea gris bajaba a contraste 4.44 sobre ella (4.62 sobre el fondo normal). */
@media (hover: hover) { .crow:hover { background: var(--soft); color: var(--text); } }
.crow .avatar {
  grid-row: 1 / span 2;
  width: 36px;
  height: 36px;
  border-radius: 999px;
  display: grid;
  place-items: center;
  background: var(--soft);
  color: var(--primary);
  font-size: 13px;
  font-weight: 800;
  flex-shrink: 0;
}
/* Una sola línea con puntos suspensivos (CHG-2026-0306): el .crow es un
   <button> de 56px y un nombre de 3 líneas desbordaba en silencio, dejando
   fuera el meta y el badge de estado. El nombre completo se ve en la ficha. */
/* CHG-2026-0552 — el nombre se leía a medias: en el barrido del 16-ago, a 360px,
 * salieron cortados los 8 de 8 ("María Altagra…", "Ana Mercede…"). El nombre es
 * lo único que identifica al cliente en la calle.
 *
 * El `nowrap` de una línea venía de CHG-2026-0306, donde el problema era el
 * contrario: un nombre de 3 líneas desbordaba la fila y empujaba fuera el meta y
 * el badge. Dos líneas con `line-clamp` resuelve las dos cosas — se lee completo
 * en la enorme mayoría de los casos y el alto sigue acotado. */
.crow .crow-nombre {
  grid-column: 2;
  font-size: 13px;
  font-weight: 700;
  min-width: 0;
  line-height: 1.5;
  display: -webkit-box;
  /* Tres líneas, no dos: con dos se leían 5 de 8 y seguían cortados los nombres
     de cuatro palabras — que en esta cartera son la norma, no la excepción
     (nombres reales de tres y cuatro palabras). La fila
     crece solo en esos casos; el `min-height: 56px` sigue mandando en el resto. */
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;
}
.crow .crow-meta {
  grid-column: 2;
  color: #475569;
  font-size: 13px;
  font-weight: 500;
  min-width: 0;
  line-height: 1.5;
  white-space: normal;   /* CHG-2026-1073 (#1164): baja de renglón, no se corta */
}
.crow .crow-monto {
  grid-column: 3;
  grid-row: 1;
  font-size: 13px;
  font-weight: 800;
  text-align: right;
  white-space: nowrap;
}
.crow .crow-badge { grid-column: 3; grid-row: 2; justify-self: end; }
.crow .chev {
  grid-column: 4;
  grid-row: 1 / span 2;
  /* CHG-2026-0834 (T1, 10-sep-2026): #c2c6d4 daba 1.63:1 contra #f8fafc, el
     peor contraste medido en TODA la caja (piso de texto 4.5:1). Mismo
     azul-gris, mas oscuro: ~4.9:1. */
  color: #6B6D75;
  font-size: 15px;
  font-weight: 400;
}
.crow .crow-atraso { color: #b91c1c; font-weight: 700; }
/* El foco/selección de una fila no debe dejar una plancha azul sobre el cliente. */
.crow:focus, .crow:active {
  background: var(--soft);
  color: var(--text);
  border-color: var(--line-soft);
}

/* — PaymentRow / CommissionRow: nombre+fecha | monto+comisión — */
.prow {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 3px 10px;
  border: 1px solid var(--line-soft);
  border-radius: 12px;
  padding: 10px 12px;
  background: #fff;
}
.prow .prow-nombre { font-size: 13px; font-weight: 700; min-width: 0; overflow-wrap: anywhere; }
/* Ancho completo (CHG-2026-0306): en 360px el detalle se partía en 3 líneas
   apretadas contra el badge de al lado. Con la fila entera para él, respira. */
.prow .prow-fecha {
  grid-column: 1 / -1;
  grid-row: 2;
  color: var(--muted);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.5;
}
.prow .prow-badge { grid-row: 3; }
.prow .prow-monto { grid-column: 2; grid-row: 1; font-size: 15px; font-weight: 800; text-align: right; white-space: nowrap; }
.prow .prow-badge { grid-column: 2; grid-row: 2; justify-self: end; }
.prow .prow-comision {
  grid-column: 1 / -1;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
  color: var(--muted);
  font-size: 13px;
  font-weight: 600;
}

/* — EmptyState — */
.empty-state {
  display: grid;
  justify-items: center;
  gap: 6px;
  padding: 28px 16px;
  text-align: center;
}
.empty-state .mi { width: 30px; height: 30px; color: #c2c6d4; }
.empty-state strong { font-size: 15px; color: var(--text); }
.empty-state span { font-size: 13px; color: var(--muted); }

/* — Scroll interno restaurado (15-jul, pedido de Eddy): la home, Mi historial
   y Comisión por pago scrollean POR DENTRO de su tarjeta; lo de arriba
   (métricas, chips, títulos) queda fijo. — */

#miHistorialList,
#miGananciaLista {
  max-height: calc(100dvh - 320px);
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  padding-bottom: 4px;
}
/* Ganancia lleva las 3 métricas arriba: la lista es un poco más corta */
#miGananciaLista { max-height: calc(100dvh - 360px); }
.scroll-client-list { max-height: 42dvh; overflow-y: auto; }
/* ── CHG-2026-0677 — INICIO BAJA COMO TODAS LAS DEMAS ───────────────────────
   Aqui habia TRES declaraciones de `.home-screen.active` (lineas 434, 1179 y
   esta), con alturas distintas y contradiciendose. La que ganaba dejaba Inicio
   como una caja de alto fijo con `overflow:hidden` y la lista de "Por cobrar"
   scrolleando POR DENTRO: un scroll dentro de otro, que es justo lo que el
   rediseno v14 quito por decision de Eddy. El cliente cortado a la mitad se leia
   como "se acabo", no como "sigue abajo".
   Ahora Inicio no tiene altura ni overflow propios: baja la pagina entera, igual
   que Mis clientes, Ajustes y las demas. Una sola declaracion, y ninguna regla
   de alto: si manana hay ocho clientes por cobrar, se ven los ocho. */
#homeHistoryList {
  /* CHG-2026-0677: sin `overflow-y:auto` ni `flex:1` — eran el segundo scroll.
     `clip` y no `hidden`, por lo mismo que en .compact-history. */
  max-height: none;
  overflow-x: clip;
  padding-bottom: 4px;
}
/* CHG-2026-0677: la tarjeta ya no reparte alto — no hay alto que repartir. Le
   quedaban `flex:1` y `min-height:0` del layout de altura fija, que sin la caja
   contenedora no hacen nada salvo confundir al que venga a leer. */
#homeMainCard .section-title { margin-bottom: 8px; }

/* — Formulario de pago: 3 secciones numeradas, campos calculados claros — */
.form-sec {
  border: 1px solid var(--line-soft);
  border-radius: 12px;
  padding: 12px;
  margin: 0 0 10px;
  background: #fff;
}
.form-sec h3 {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 10px;
  font-size: 13px;
  font-weight: 800;
  color: var(--text);
}
.form-sec-num {
  width: 20px;
  height: 20px;
  border-radius: 999px;
  display: grid;
  place-items: center;
  background: var(--soft);
  color: var(--primary);
  font-size: 13px;
  font-weight: 800;
}
.form-sec label:last-child { margin-bottom: 0; }
#paymentFormPanel .field-title, #paymentFormPanel .hint { display: block; }
#paymentFormPanel .hint { font-size: 13px; margin-top: 6px; }
.campo-calculado { position: relative; }
.campo-calculado input[readonly] {
  background: var(--line-soft);
  color: var(--muted);
  font-weight: 700;
  border-style: dashed;
}
.tag-auto {
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  font-style: italic;
}

/* — Recibo estructurado (etiqueta | valor) + jerarquía de acciones — */
.recibo-view {
  border: 1px solid var(--line-soft);
  border-radius: 12px;
  background: #fff;
  padding: 4px 14px;
  margin: 0 0 10px;
}
.recibo-view .rv-fila {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 0;
  font-size: 13px;
}
.recibo-view .rv-fila:last-child { border-bottom: 0; }
.recibo-view .rv-fila span { color: var(--muted); font-weight: 500; }
.recibo-view .rv-fila strong { text-align: right; overflow-wrap: anywhere; }
.recibo-view .rv-total { font-size: 15px; }
.recibo-view .rv-total strong { color: var(--primary); font-size: 15px; }
.recibo-acciones { gap: 8px; }
.recibo-acciones button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
}
.recibo-acciones .mi { width: 18px; height: 18px; }
#receiptPanel .form-sec h3 { color: var(--muted); }
#receiptPanel .receipt { min-height: 0; max-height: none; overflow: visible; font-size: 13px; }

/* — Menú Más: fila de salir en rojo suave — */
.menu-ico.rojo { background: #fef2f2; color: var(--danger); }
.menu-row-salir strong { color: var(--danger); }

/* — Táctil: mínimo 44px en botones de acción — */
button { min-height: 44px; }
.small-btn, .chip, .cj-modal-x, .movement-edit, .movement-trash, .nav-item { min-height: 0; }
.choice-button { min-height: 44px; }

/* (la hoja de cobro y las listas ahora renderizan .crow/.prow desde el JS) */


/* ── Refinamiento Cobradores 31-jul-2026 (CHG-2026-0304) ─────────────────── */

/* Filtro de período del Historial: los dos selects en una fila que respira.
   :not([hidden]) a propósito — un `display:flex` pelado le gana al atributo
   hidden y el filtro se quedaba visible en las otras dos pestañas (misma
   trampa que ya se cazó el 14-jul con .bottom-nav y .session-banner). */
.hist-filtro:not([hidden]) {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin: 0 0 12px;
}
.hist-filtro label {
  flex: 1 1 140px;
  margin: 0;
}
/* El `label { display: ... }` general de la app también le gana al atributo
   hidden: sin esto el selector de Mes se quedaba en pantalla con el filtro en
   "Últimos 7/15 días". */
.hist-filtro label[hidden] { display: none; }

/* Método fijo en el formulario de pago: informa, no se puede cambiar. */
.hint.metodo-fijo {
  background: #f1f5f9;
  border-radius: 8px;
  padding: 8px 10px;
  margin: 0 0 10px;
}

/* Botón Editar de cada fila de pago del Historial. */
.prow-acciones {
  grid-column: 1 / -1;
  display: flex;
  justify-content: flex-end;
  margin-top: 6px;
}
.prow-acciones .small-btn { padding: 4px 12px; font-size: 13px; }

/* Ficha del cliente: la cabecera de la tarjeta lleva su badge de estado. */
#screen-cliente .section-title.compact-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
#screen-cliente .detail-view-grid { margin-top: 4px; }

/* Cabecera de "Por cobrar": título a la izquierda, botón Clientes a la derecha. */
#homeMainCard .section-title.compact-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}


/* ── Que todo encaje y se pueda tocar en un teléfono (CHG-2026-0306) ───────
   Medido en 360x800 (Galaxy S21) con la app real, no a ojo. */

/* Los <select> salían de 23px de alto: imposibles de tocar y se veían rotos
   al lado de los demás campos. El `padding` y el `min-height` NO les hacían
   nada porque WebKit dibuja el select como control nativo y se come esas dos
   propiedades: hay que apagar el control nativo con appearance:none y ponerle
   nosotros la flechita. */
select {
  appearance: none;
  -webkit-appearance: none;
  min-height: 44px;
  padding: 11px 38px 11px 12px;
  font-size: 15px;
  background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%236b7280'%3E%3Cpath d='M7 10l5 5 5-5z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 20px 20px;
}

/* Pestañas del Historial: 27px es muy poco para el dedo. */
.chip {
  min-height: 44px;
  padding: 10px 16px;
}

/* El botón "Editar" de cada pago: 24px de alto no se acierta caminando. */
.prow-acciones .small-btn,
.small-btn {
  min-height: 44px;
  padding: 10px 16px;
}

/* "Período" quedaba pegado a las pestañas. */
.hist-filtro { margin-top: 12px; }

/* El botón sticky "Registrar pago" se montaba encima del campo Nota y del
   aviso de ubicación: sin este colchón el último campo del formulario queda
   debajo del botón y no se puede ni ver ni escribir.
   CHG-2026-1053 (T27, ficha #1026): los 64 px no alcanzaban. Este colchón es
   el que separa el botón del último campo, y el botón no es de 64 px: son los
   84 px de la barra de abajo (el `bottom` del sticky, styles.css:143-150) MAS
   el alto del propio bloque del botón (~56 px: el botón, su padding-top y el
   margen). Con los 64 px de antes la Nota quedaba TAPADA por el botón azul.
   Ahora el colchón es de 140 px (+ el safe-area del teléfono), que es lo que
   hace falta para que la Nota se vea COMPLETA por encima del botón. */
#paymentFormPanel { padding-bottom: calc(140px + env(safe-area-inset-bottom, 0px)); }
/* CHG-2026-1056 (O4.2): el botón ya está en el flujo (regla de abajo), así que el colchón de 140 px solo dejaba
   49 px de página vacía para bajar a 360×800. La barra de abajo ya tiene su espacio (#appShell, 84 px). */
#paymentFormPanel { padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px)); }

/* CHG-2026-1053 (T27, ficha #1026) — Y EL BOTÓN VUELVE AL FLUJO NORMAL.
   MEDIDO el 22-oct-2026 a 360x800, con el botón pegajoso (fotos en la carpeta del
   T27): al abrir la pantalla de cobro, el botón se SUBE hasta 84 px del borde de
   la pantalla y se come 35 de los 43 px del campo Nota: el cobrador no veía ni
   escribía la nota. El colchón de arriba NO lo arregla: el botón pegajoso se
   pega al borde y se monta sobre lo que haya justo encima, acierte o no el
   colchón (medido: 35 px de tapado con 64 px y 35 px con 140 px — lo mismo).
   La segunda opción del arreglo de la ficha: el botón al final del formulario,
   en el flujo normal, DEBAJO de la Nota y con su margen. Mismo botón, mismo
   aspecto; lo que cambia es que ya no se monta sobre el campo de arriba. */
#paymentFormPanel .sticky-actions { position: static; }
#paymentFormPanel .sticky-actions {
  margin-top: 4px;
  padding-bottom: 6px;
}

/* Los 3 tipos de pago: en 360px "Pago completo" se partía en dos líneas. */
#paymentFormPanel .choice-grid { gap: 6px; }
#paymentFormPanel .choice-button {
  min-height: 46px;
  padding: 8px 6px;
  font-size: 13px;
  line-height: 1.5;
}
/* Todo botón real de Cobrar conserva un blanco táctil mínimo de 44×44 px. */
#paymentFormPanel button { min-width: 44px; min-height: 44px; }


/* Letra mínima legible en la calle (CHG-2026-0306): el barrido en 360x800
   encontró badges a 10.2px y textos de apoyo a 11.2px. Con sol y a pie eso no
   se lee; se sube lo justo para que se lean sin desarmar la jerarquía.

   CHG-2026-0551 — ese arreglo se quedó corto: dejó estos cuatro en .72rem, o sea
   11.5px, todavía por debajo del mínimo. Y solo cubría cuatro selectores de los
   33 que estaban bajo 12px. Ahora TODOS los tamaños de esta hoja que quedaban por
   debajo llevan `max(12px, ...)`: el valor original se conserva a la vista para
   saber qué se quería, y el piso lo garantiza el max. */
.badge-estado { font-size: 13px; padding: 4px 10px; }
.crow .crow-meta { font-size: 13px; }
.prow .prow-fecha,
.prow .prow-comision { font-size: 13px; }
.tag-auto { font-size: 13px; }
.empty-state span { font-size: 13px; }
.sheet-progress { font-size: 13px; }

/* Las etiquetas de dato ("Monto prestado", "Saldo pendiente", "Teléfono"...)
   quedaban en 10.9px: son lo que el cobrador lee para saber qué mira. */
.summary-grid span,
.detail-view-field span { font-size: 13px; }
.detail-view-field strong { font-size: 15px; }

/* El badge se montaba ENCIMA del detalle de la quincena: la regla que lo
   bajaba a la fila 3 estaba antes que la original y perdia. Aqui gana. */
.prow .prow-badge {
  grid-column: 1 / -1;
  grid-row: 3;
  justify-self: end;
  margin-top: 4px;
}
/* Editar en la misma linea que el estado de la comision: antes se llevaba una
   fila entera para el solo y la tarjeta quedaba enorme y vacia. */
.prow .prow-comision {
  flex-wrap: wrap;
  row-gap: 6px;
}
.prow .prow-comision-fin {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}
.prow .prow-comision-fin .small-btn { min-height: 44px; padding: 10px 16px; }

/* ── Las 3 tarjetas de arriba (Inicio y Ganancia) — CHG-2026-0307 ──────────
   Medido en 360x800: "Faltan por cobrar" era la unica etiqueta de 2 lineas y
   empujaba su numero 13px mas abajo que los otros dos; y las mismas tarjetas
   median 104px en Inicio y 91px en Ganancia.

   El truco para que los numeros SIEMPRE queden a la misma altura, tenga la
   etiqueta una linea o dos: la tarjeta es un grid de 3 filas (icono | etiqueta
   | numero) y la fila de la etiqueta es la elastica (1fr). El numero vive
   SIEMPRE en la ultima fila, asi que arranca a la misma altura en las tres.
   `display: contents` en el div de dentro sube la etiqueta y el numero a ser
   filas de la tarjeta sin tocar el HTML. */
.home-stat-grid .stat-card {
  display: grid;
  grid-template-rows: auto 1fr auto;
  justify-items: center;
  align-items: center;
  text-align: center;
  gap: 6px;
  padding: 12px 8px;
  min-height: 100px;
}
.home-stat-grid .stat-card > div { display: contents; }
.home-stat-grid .stat-card span {
  font-size: 13px;
  line-height: 1.5;
  font-weight: 600;
  margin-bottom: 0;
  align-self: center;
}
.home-stat-grid .stat-card strong {
  font-size: 15px;
  line-height: 1.5;
  align-self: end;
}

/* La comisión del cobrador en verde: es plata a favor suyo. */
.prow .prow-comision-monto { color: var(--ok, #047857); font-weight: 700; }
.prow .prow-comision-monto.anulada { color: var(--muted); font-weight: 600; text-decoration: line-through; }

/* ── Avisos y ruta del día (CHG-2026-0313) ─────────────────────────────────
   Va al FINAL del archivo a propósito: la cascada pisa lo anterior, que es el
   patrón de esta hoja desde el rediseño del 14-jul. */

.head-acciones { display: flex; align-items: center; gap: 10px; }

/* CHG-2026-0719 — los 36px no llegaban al minimo de dedo (44). Mismo trato que
   `.back-btn`: el dibujo manda, el area tactil se mantiene. */
.icon-btn {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px;
  border: 0; border-radius: 10px;
  background: transparent; color: var(--texto, #0f172a);
  cursor: pointer;
}
.icon-btn:active { background: rgba(15, 23, 42, .06); }
.icon-btn .mi { width: 22px; height: 22px; fill: currentColor; }

/* El puntito rojo. Con `hidden` puesto NO se ve: el display de aquí no puede
   pisarlo (trampa vivida 4 veces en esta app — ver [hidden] al inicio). */
.aviso-badge {
  /* El numero se centra con flex, NO con `line-height: 17px`. Esa altura de
     renglon pegada al alto de la bolita medía 1.42 y la vara de Eddy es
     1.5-1.75 (medido el 19-sep-2026). Con flex el renglon puede ser 1.5 y la
     bolita sigue siendo una bolita. */
  position: absolute; top: 2px; right: 2px;
  min-width: 18px; height: 18px; padding: 0 4px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 9px; background: #dc2626; color: #fff;
  font-size: 13px; font-weight: 700; line-height: 1.5; text-align: center;
}

.avisos-panel { position: fixed; inset: 0; z-index: 70; }
.avisos-fondo { position: absolute; inset: 0; background: rgba(15, 23, 42, .16); backdrop-filter: blur(3px); }
.avisos-caja {
  position: absolute; top: 0; right: 0; left: 0;
  max-height: 78vh; display: flex; flex-direction: column;
  background: #fff; border-radius: 0 0 16px 16px;
  box-shadow: 0 10px 30px rgba(15, 23, 42, .18);
  padding-top: env(safe-area-inset-top);
  animation: avisosEntra .18s ease;
}
@keyframes avisosEntra { from { transform: translateY(-8px); opacity: .6; } to { transform: none; opacity: 1; } }
.avisos-cab {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 14px 10px;
}
.avisos-cab h2 { margin: 0; font-size: 15px; font-weight: 700; }
.avisos-cab-acciones { display: flex; align-items: center; gap: 6px; }
.link-btn {
  border: 0; background: transparent; color: var(--brand, #2563eb);
  font-size: 13px; font-weight: 600; cursor: pointer; padding: 6px 4px;
}
.avisos-lista { overflow-y: auto; padding: 6px 0 10px; }

.aviso-fila {
  display: grid; grid-template-columns: 1fr auto; gap: 2px 10px;
  width: 100%; text-align: left; border: 0; background: transparent;
  padding: 13px 14px; cursor: pointer;
}
.aviso-fila:active { background: rgba(15, 23, 42, .04); }
.aviso-titulo { font-size: 15px; font-weight: 600; overflow-wrap: anywhere; }
.aviso-detalle {
  grid-column: 1 / -1;
  font-size: 13px; color: var(--muted, #64748b); overflow-wrap: anywhere;
}
.aviso-fecha { font-size: 13px; color: var(--muted, #64748b); white-space: nowrap; }
.aviso-veces {
  display: inline-block; margin-left: 6px; padding: 0 6px;
  border-radius: 8px; background: var(--brand, #2563eb); color: #fff;
  font-size: 13px; font-weight: 700;
}

/* Los dos grupos de la home: "Para hoy" primero, el resto debajo. */
.grupo-ruta + .grupo-ruta { margin-top: 14px; }
.grupo-ruta-titulo {
  display: flex; align-items: center; gap: 8px;
  margin: 0 0 6px; padding: 0 2px;
  font-size: 13px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .03em; color: var(--muted, #64748b);
}
/* Es una PILDORA con un numero al lado del titulo del grupo -- lo mismo que el
   `.badge` de la app del telefono. Se llamaba `grupo-ruta-num`, y con ese nombre
   ni se leia como lo que es ni la caja podia reconocerla: salia como "cuadro de
   adorno detras de 4" (familia 15, medido el 19-sep-2026). El fondo de una
   pildora ES su forma. */
.grupo-ruta-badge {
  min-width: 20px; padding: 1px 6px; border-radius: 9px;
  background: var(--brand, #2563eb); color: #fff;
  font-size: 13px; font-weight: 700; text-align: center; letter-spacing: 0;
}
.grupo-ruta-nota { font-size: 13px; font-weight: 600; color: #b45309; text-transform: none; letter-spacing: 0; }
.grupo-ruta-vacio {
  margin: 0; padding: 12px 14px;
  font-size: 13px; color: var(--muted, #64748b); line-height: 1.5;
  background: var(--fondo-suave, #f8fafc); border-radius: 12px;
}

/* TRAMPA VIVIDA 4 VECES en esta app: cualquier `display:` del CSS pisa el
   atributo `hidden`, y el elemento se queda visible aunque el JS lo esconda —
   con el agravante de que un test que comprueba "aparece al hacer X" da verde
   porque YA estaba visible. Ninguna de las reglas de arriba declara `display`,
   así que hoy no pasa; esto lo deja blindado por si alguien agrega una. */
.avisos-panel[hidden], .aviso-badge[hidden] { display: none !important; }

/* ARREGLO tras la prueba visual (CHG-2026-0313). La captura a 360px mostró el
   título del aviso invisible y "Marcar leídos" azul sobre azul: la regla global
   `button { background: var(--primary); color: white }` de esta hoja pisaba mis
   estilos, porque yo declaraba `background: transparent` pero NO el color, y en
   `.link-btn` el fondo azul del button ganaba por orden.
   Se corrige declarando las dos cosas explícitamente. Esto solo se ve MIRANDO
   la captura: los selectores existían y el test los encontraba con su texto. */
.aviso-fila, .aviso-fila:hover {
  background: transparent;
  color: var(--texto, #0f172a);
  font-weight: 400;
  padding: 11px 14px;
  border-radius: 0;
}
.aviso-fila:active { background: rgba(15, 23, 42, .04); }
.aviso-titulo { color: var(--texto, #0f172a); }
.aviso-detalle, .aviso-fecha { color: var(--muted, #64748b); }

.link-btn, .link-btn:hover {
  background: transparent;
  color: var(--primary, #2563eb);
  font-weight: 600;
  padding: 6px 8px;
  border-radius: 8px;
  min-height: 0;
}
.link-btn:active { background: rgba(37, 99, 235, .08); }

.icon-btn, .icon-btn:hover {
  background: transparent;
  color: var(--texto, #0f172a);
  padding: 0;
  /* CHG-2026-0564 -- hallazgo #14 del vigilante.
     Antes aqui habia `min-height: 0`, y eso anulaba el `button { min-height: 44px }`
     de 117 lineas mas arriba: los dos botones de icono (Avisos y su cerrar)
     quedaban en 36x36 en telefono, bajo el minimo de 44 que pide la guia de
     accesibilidad. El dedo no acierta.
     Se toca el AREA, no el icono: el `.mi` de dentro sigue en 22px, asi que se ve
     igual -- solo es mas facil de dar. */
  min-height: 44px;
  min-width: 44px;
  width: 44px;
  height: 44px;
}
.icon-btn:active { background: rgba(15, 23, 42, .06); }


/* ── Movimiento reducido (CHG-2026-0639, hallazgo #55) ──────────────────────
   REGLA UNIVERSAL A PROPOSITO, no una lista de selectores.

   El arreglo que levanto el vigilante el 24-ago enumeraba cinco: `.screen`,
   `.avisos-caja`, `.sheet-bar i`, `.cj-modal` y `.cj-modal-card`. Hoy esos son
   TODOS los que hay (3 `transition` + 2 `animation`), asi que la lista acertaba
   — y envejeceria mal: la siguiente animacion que alguien agregue se sale sin
   error y sin log. Es la misma trampa del filtro escrito a mano que en este
   sistema ya se trago una senal tres veces.

   `.01ms` en vez de `none` es deliberado: un `animation: none` cancela el
   evento `animationend`, y una interfaz que espere ese evento para mostrar algo
   se queda colgada. Con una duracion casi cero el evento SI dispara y no se ve
   movimiento. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   CHG-2026-0651 — La ficha del cliente: Resumen + 4 pestañas, y los toques.

   Va al FINAL del archivo a proposito. `.chip` se define dos veces (linea 1135 y
   otra vez en la 1340, que lo achica todavia mas para el inicio): con la misma
   especificidad manda el ultimo, asi que el min-height tiene que estar aqui o
   la regla de arriba se lo come sin avisar.
   ═══════════════════════════════════════════════════════════════════════════ */

/* — TOQUES: minimo 44x44 (guia de UI movil). Medido antes: .chip 27px,
     .link-btn 22px, .ojo-clave 38px. La fila de cliente (.crow) ya estaba
     bien con sus 56px y no se toca. — */
.chip,
.ficha-tab {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.chip-row { gap: 8px; }
.link-btn { min-height: 44px; display: inline-flex; align-items: center; }
.ojo-clave { min-height: 44px; min-width: 44px; }

/* — Las 4 pestañas. Scroll horizontal propio: en 360px las cuatro no caben, y
     el body NUNCA debe hacer scroll lateral. — */
/* CHG-2026-0677 — las cuatro CABEN, ya no se deslizan.
   Con `display:flex` + `overflow-x:auto` median 410px en una pantalla de 360: la
   cuarta salia cortada y solo se alcanzaba deslizando, sin ninguna senal de que
   se pudiera. Un grid de 4 columnas iguales reparte los 360 y entran completas
   (junto con el rotulo "Todo", que sustituyo a "Movimientos" en app.js). */
.ficha-tabs {
  display: grid; grid-template-columns: repeat(4, 1fr);
  /* CHG-2026-0834: 6px daba "6px entre ... y su vecino, minimo 8" -- 8
     hallazgos (historial-cliente pc/telefono). Las 4 columnas caben igual. */
  gap: 8px;
  padding: 0 2px 12px; margin-bottom: 12px;
}
.ficha-tab {
  width: auto; white-space: nowrap;
  display: inline-flex; align-items: center; justify-content: center; gap: 4px;
  padding: 0 6px; border-radius: 10px;
  border: 1px solid var(--line); background: #fff; color: var(--muted);
  font-size: 13px; font-weight: 600;
}
.ficha-tab.active { background: var(--primary); border-color: var(--primary); color: #fff; }
/* CHG-2026-0677: estaba en 11px, por debajo del piso de 12 que fija esta misma
   hoja (ver el bloque de la linea ~1939). */
.ficha-tab-num { font-size: 13px; font-weight: 700; opacity: .7; }

/* — Tarjetas del Resumen — */
.rs-tj { margin-bottom: 7px; }
.rs-tit {
  margin: 0 0 7px; font-size: 13px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em; color: var(--muted);
}
.rs-grande { margin: 0; font-size: 15px; font-weight: 700; line-height: 1.5; }
.rs-grande small { font-size: 13px; font-weight: 600; color: var(--muted); margin-left: 5px; }
.rs-medio { margin: 0; font-size: 15px; font-weight: 700; line-height: 1.5; }
.rs-chico { margin: 3px 0 0; font-size: 13px; color: var(--muted); }
.rs-alerta { color: var(--warning); font-weight: 600; }
.rs-barra { height: 6px; background: var(--line-soft); border-radius: 99px; overflow: hidden; }
.rs-barra i { display: block; height: 100%; background: var(--primary); }
.rs-vigente {
  display: inline-block; margin-top: 8px;
  font-size: 13px; font-weight: 700; padding: 3px 9px;
  border-radius: 999px; background: var(--soft); color: var(--primary-dark);
}
.rs-acuerdo { border-left: 3px solid var(--warning); }

/* — Filas de evento del historial — */
.ev-mes {
  margin: 14px 2px 7px; font-size: 13px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .07em; color: var(--muted);
}
.ev-mes:first-child { margin-top: 0; }
.ev-fila {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 10px 11px; margin-bottom: 6px; min-height: 56px;
  border: 1px solid var(--line-soft); border-radius: 11px; background: #fff;
}
.ev-ic {
  width: 30px; height: 30px; border-radius: 9px; flex: 0 0 auto; margin-top: 1px;
  display: flex; align-items: center; justify-content: center; font-size: 13px;
}
.ev-pago  .ev-ic { background: #dcfce7; color: #166534; }
.ev-mora  .ev-ic { background: #fef3c7; color: #b45309; }
.ev-prest .ev-ic { background: var(--soft); color: var(--primary); }
.ev-anul  .ev-ic { background: #fee2e2; color: var(--danger); }
.ev-cuerpo { flex: 1; min-width: 0; }
.ev-cuerpo b { display: block; font-size: 13px; font-weight: 600; }
.ev-cuerpo span { display: block; font-size: 13px; color: var(--muted); margin-top: 1px; }
.ev-monto { font-size: 13px; font-weight: 700; white-space: nowrap; flex: 0 0 auto; }
.ev-tachado .ev-monto { text-decoration: line-through; color: var(--muted); }

/* ── CHG-2026-0661 · Formulario de pago: modos con los valores llenos ──────
 * El botón dice CUÁNTO va a llenar antes de que el dedo lo toque, los campos
 * que no aplican se esconden en vez de quedarse en cero, y el préstamo avisa
 * lo que debe apenas se abre. */

/* Los tres botones ya no son una línea de texto: llevan el monto debajo. */
#paymentFormPanel .choice-button { display: grid; gap: 2px; align-content: center; }
.choice-monto {
  display: block;
  font-size: 13px;
  font-weight: 600;
  opacity: .8;
  line-height: 1.5;
}
/* En el botón activo (fondo azul) el monto hereda el blanco; en los demás,
   gris para que no compita con el rótulo. */
.choice-button:not(.active) .choice-monto { color: var(--muted); }

/* En un indefinido son 2 botones, no 3 (no existe "Pago completo"): la grilla
   se reparte sola con los que quedan visibles.
   `[hidden]` necesita el display explícito porque la regla de arriba se lo gana
   — la misma trampa que ya documentaba `.hist-filtro label[hidden]`. */
#paymentFormPanel .choice-grid { grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); }
#paymentFormPanel .choice-button[hidden] { display: none; }

/* Los campos que no aplican al modo. Sin esto, el `label { display: grid }`
   general le gana al atributo `hidden` y el campo se queda en pantalla. */
#paymentFormPanel label[hidden] { display: none; }
/* La grilla de montos se ajusta a los que quedan: 3 en parcial, 2 en completo
   y en "ponerse al día", 1 en solo mora. */
#paymentAmountsGrid.one { grid-template-columns: 1fr; }
#paymentAmountsGrid.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* La nota que explica el modo ("capital e interés van en cero"). */
#paymentDistNota { margin: 0 0 10px; font-size: 13px; line-height: 1.5; }
#paymentDistNota[hidden] { display: none; }

/* ── CHG-2026-0661 · Cola visible, contador y esqueletos ──────────────────── */

/* El pago cobrado sin señal, en la MISMA lista que los confirmados. Antes solo
   existía como un contador arriba y en la lista no aparecía: en la calle eso se
   lee como que el cobro se perdió, y el cobrador lo registra otra vez. */
.prow-cola {
  border-color: #fedf88;
  background: #fffdf5;
  border-left: 3px solid var(--warning);
}
.prow-cola-error {
  border-color: #fecdc9;
  background: #fffbfa;
  border-left-color: var(--danger);
}
.prow-cola-motivo { color: var(--danger); font-weight: 700; }
/* En el resumen del período, lo que espera señal va aparte de lo cobrado:
   sumarlo inflaría el día con dinero que el servidor todavía no vio. */
.sheet-progress-cola { color: var(--warning); font-weight: 700; }
/* El pago que sí entró lo dice, para que el contraste tenga sentido. */

/* El contador de solicitudes esperando aprobación, en la barra de abajo.
   `.nav-item` es un grid, así que el globo va posicionado sobre él. */
.nav-item { position: relative; }
.nav-badge {
  position: absolute;
  /* Medido a 360/390/412: con `right:6px` el globo caia ENCIMA del icono y se
     comia el tercer punto de "Mas". Corrido a la esquina queda legible y sigue
     dentro de la barra con holgura (a 360px: globo 340, borde 351). */
  top: 0;
  right: 2px;
  /* CHG-2026-0677: iba en 11px, bajo el piso de 12 de esta hoja. El circulo
     crece con la letra: a 12px dentro de 18 se salia el numero. */
  min-width: 20px;
  height: 20px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--danger);
  color: #fff;
  font-size: 13px;
  font-weight: 800;
  display: grid;
  place-items: center;
  border: 2px solid #fff;
  line-height: 1.5;
}

/* Esqueleto de carga. `prefers-reduced-motion` apaga el brillo: hay quien se
   marea con el movimiento, y la forma ya se entiende quieta. */
.crow-esqueleto { pointer-events: none; }
.sk {
  background: var(--line-soft);
  border-radius: 6px;
  background-image: linear-gradient(90deg, var(--line-soft) 0%, #eceff3 50%, var(--line-soft) 100%);
  background-size: 200% 100%;
  animation: sk-brillo 1.3s ease-in-out infinite;
}
.sk-linea { height: 10px; display: block; }
.crow .sk-nombre { grid-column: 2; width: 68%; }
.crow .sk-meta { grid-column: 2; width: 44%; height: 8px; margin-top: 5px; }
.crow .sk-monto { grid-column: 3; grid-row: 1; width: 54px; }
.avatar.sk { border-radius: 999px; }
@keyframes sk-brillo {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .sk { animation: none; background-image: none; }
}

/* ── CHG-2026-0663 — con la barra apagada, el botón se pega al borde ─────────
 *
 * El `.sticky-actions` vive a 84px del fondo POR la barra: es el arreglo del
 * 16-ago para que no quedara tapado. Cuando `barraSegunPantalla()` apaga la
 * barra, esos 84px se quedan como un hueco con nada debajo y el botón flotando
 * — se ve peor que las dos barras juntas. Por eso el JS pone `sin-barra` en el
 * <body> y aquí se recoge el hueco.
 *
 * Va por la clase del body y no pantalla por pantalla a propósito: es la
 * trampa #3 del barrido del 31-jul (CHG-2026-0306), que se arregló en un panel
 * y volvió en los demás. Quien use `.sticky-actions` lo hereda.
 *
 * Las tres reglas hacen falta y ninguna sobra:
 *   · el `bottom` del sticky — gana a `.mobile-shell .sticky-actions` (0,2,1
 *     contra 0,2,0);
 *   · el colchón del contenedor, que reservaba sitio para la barra;
 *   · el `#paymentFormPanel`, que trae un id (1,0,0) y se lleva por delante
 *     cualquier regla de clase: sin esta línea el formulario de pago sería el
 *     único que NO recogería el hueco. */
body.sin-barra .sticky-actions {
  bottom: env(safe-area-inset-bottom, 0px);
}
body.sin-barra .step-panel:has(> .sticky-actions),
body.sin-barra .card:has(> .sticky-actions),
body.sin-barra section:has(> .sticky-actions) {
  padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
}
body.sin-barra #paymentFormPanel {
  padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
}
/* El caparazón reserva 100px para la barra flotante; sin barra, sobran. */
body.sin-barra .mobile-shell {
  padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
}

/* ═══════════════════════════════════════════════════════════════════════════
   CHG-2026-0671 — LA BARRA DE ABAJO, POR GRUPO
   Eddy, 26-ago-2026: "cambiar el menu de abajo dependiendo las pantallas" y
   "quitar el boton + del inicio y el de historial".

   Va al FINAL del archivo a proposito: .bottom-nav trae
   `grid-template-columns: repeat(5, 1fr)` de dos sitios mas arriba (linea 306 y
   1151) y la cascada es lo unico que lo pisa sin editar reglas que usan otras
   pantallas. Clases NUEVAS, ningun selector viejo tocado -- la regla #316 de la
   boveda (un cambio al CSS compartido se paga con censo del sistema completo)
   se respeta no tocando lo compartido.
   ═══════════════════════════════════════════════════════════════════════════ */

.bottom-nav.barra-nav {
  grid-template-columns: repeat(3, 1fr);
  align-items: stretch;
}

/* CHG-2026-0716 — la barra del cliente pasa a CUATRO: entro "Perfil".
   Va en su propia regla y no junta con barra-nav porque ya no comparten el
   numero de columnas. En 360px de ancho (el encaje medido de esta app) cuatro
   columnas dan 90px cada una: sobra para los 48px de area de dedo. */
.bottom-nav.barra-cliente {
  grid-template-columns: repeat(4, 1fr);
  align-items: stretch;
}

/* El area de dedo no baja de 48px (guia de touch). Con cuatro botones el padding
   lateral se aprieta a 2px: es lo unico que se cede, y solo afecta al hueco entre
   iconos, no al alto tocable. */
.barra-nav .nav-item,
.barra-cliente .nav-item {
  min-height: 48px;
  padding: 8px 4px 6px;
}

.barra-cliente .nav-item {
  padding-left: 2px;
  padding-right: 2px;
  font-size: 13px;   /* hallazgos 107/117, CHG-2026-0737: pisaba
     el piso de 12px de .nav-item por especificidad y orden */
}

/* La barra del cliente se ve IGUAL que la de inicio -- lo pidio Eddy con esas
   palabras. La unica senal de que estas un nivel adentro es el boton de volver
   de arriba, que por eso NO se toca.

   CHG-2026-0720 — y "igual que la de inicio" incluye esto: sin cuadro de fondo.
   Esta regla existe porque es MAS ESPECIFICA que `.nav-item.active` y la pisa; si
   solo se hubiera arreglado alla, las cuatro pestanas del cliente se habrian
   quedado con el cuadro azul. Las dos se tocan juntas, siempre. */
.barra-cliente .nav-item.active {
  background: transparent;
  color: var(--primary);
}

/* El candado de siempre: `hidden` tiene que ganarle al display del grid.
   Ya mordio dos veces (14-jul con .bottom-nav y .session-banner). */
.bottom-nav[hidden] { display: none !important; }

/* ═══ CHG-2026-0671 — LAS PARTIDAS DEL PAGO PARCIAL ═══════════════════════ */

/* ── CHG-2026-0759 (C6) — LAS TRES CASILLAS, EN UNA SOLA TARJETA.
   En el dibujo de Eddy las opciones no son tres tarjetas sueltas separadas por
   aire: es UN recuadro con las filas dentro, divididas por una linea fina. Antes
   `.partidas` era un grid con 6px de hueco y cada `.partida` flotaba sola sobre
   el fondo de la pantalla. Ahora el recuadro es `.partidas` y las filas se
   separan con `border-top` — que es tambien lo que hace innecesario el
   `.partida-sep` que se retiro en app.js. */
.partidas {
  display: grid; gap: 0;
  background: var(--card); border: 1px solid var(--line);
  border-radius: 12px; overflow: hidden;
}
.partida + .partida { border-top: 1px solid var(--line-soft); }
.partida {
  display: flex; align-items: center; gap: 10px; width: 100%;
  background: var(--card); border: 0;
  padding: 11px 12px; font-family: inherit; text-align: left;
  min-height: 48px;   /* area de dedo: el minimo de touch, no el del texto */
  color: var(--text); cursor: pointer;
}
.partida:last-child { border-bottom: 0; }
.partida:hover { background: var(--line-soft); }
/* CHG-2026-0885 (E1, 1.12) — la que no se puede marcar se ve apagada y no
   responde al dedo (Otro pago con una partida marcada, y al reves). */
.partida:disabled,
.partida.bloqueada { opacity: .45; cursor: not-allowed; pointer-events: none; }
.partida:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; border-radius: 8px; }

.partida-check {
  width: 22px; height: 22px; border-radius: 6px; border: 2px solid #cbd5e1;
  display: grid; place-items: center; flex-shrink: 0; background: var(--card);
  transition: background .15s ease, border-color .15s ease;
}
.partida.on .partida-check { background: var(--primary); border-color: var(--primary); color: #fff; }
.partida-check .mi { width: 14px; height: 14px; }
.partida-txt { flex: 1; font-size: 15px; font-weight: 600; min-width: 0; }
.partida-monto { font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; flex-shrink: 0; }
/* Sin marcar el monto baja de peso: lo marcado es lo que suma. El estado NO se
   dice solo con color -- la casilla tambien cambia de forma. */
.partida:not(.on) .partida-txt,
.partida:not(.on) .partida-monto { color: var(--muted); font-weight: 600; }

/* CHG-2026-0759 (C6): `.partida-sep` ya no lo pinta nadie — pintarPartidas()
   dejo de emitirlo cuando las filas pasaron a vivir dentro de una sola tarjeta.
   La regla se retira con el, para no dejar CSS apuntando a algo que no existe. */

.partidas-orden { display: flex; gap: 6px; align-items: flex-start; font-size: 13px; margin: 9px 0 0; }
.partidas-orden .mi { width: 14px; height: 14px; margin-top: 2px; flex-shrink: 0; }

/* CHG-2026-0752 (O2) — "Mora (adelantada)": sin ninguna mora pendiente, no hay
   un monto fijo que tocar; se escribe. Mismo alto de dedo que las demas filas. */
.partida-input {
  width: 96px; flex-shrink: 0; text-align: right; font-variant-numeric: tabular-nums;
  font-family: inherit; font-size: 15px; font-weight: 700; color: var(--text);
  border: 1px solid #cbd5e1; border-radius: 8px; padding: 6px 8px; background: var(--card);
}
.partida-input:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
/* CHG-2026-0756 (O12) — desde este cambio el monto sugerido esta ESCRITO en la
   casilla aunque la fila no cuente todavia. Va atenuado exactamente igual que
   el `.partida-monto` de las filas sin marcar (regla de arriba), para que un
   numero a la vista no se lea como un numero que ya se esta cobrando. */
.partida:not(.on) .partida-input { color: var(--muted); font-weight: 600; }

/* CHG-2026-0759 (C7) — el `+` del dibujo de Eddy, delante del monto de la mora
   adelantada: dice de un vistazo que ese numero se SUMA a lo demas, no que lo
   reemplaza. El signo y el campo comparten el recuadro; el borde se muda del
   input a esta caja para que se lean como una sola pieza. */
/* CHG-2026-0885 (E1, 1.13) — SIN RECUADRO. Desde el 20-sep (2.11) este monto es
   la mora por atraso y NO se escribe; el recuadro era la senial de "aqui se
   escribe" y ya mentia. Queda al aire, como el monto de las otras filas, con su
   "+" delante (ese si es del dibujo de Eddy). */
.partida-libre-caja {
  display: flex; align-items: center; gap: 4px; flex-shrink: 0;
  border: 0; border-radius: 0; padding: 4px 0;
  background: none;
}
.partida-libre-caja .partida-input {
  border: 0; padding: 0; width: 76px; background: none;
}
.partida-mas { font-size: 15px; font-weight: 700; color: var(--muted); }
.partida.on .partida-mas { color: var(--text); }
.partida-libre-caja:focus-within { outline: 2px solid var(--primary); outline-offset: 1px; }
/* CHG-2026-0755 (fix, 02-sep) — la fila SI se puede tocar ahora (antes solo
   reaccionaba a escribir en el input, y Eddy reporto que "no se puede
   selecionar"). El input adentro se queda con su propio cursor de texto. */
.partida-libre { cursor: pointer; }
.partida-libre .partida-input { cursor: text; }

/* La puerta de "Nuevo cliente" en Mis clientes (repone el boton + retirado). */
.accion-fila {
  display: flex; align-items: center; justify-content: center; gap: 9px; width: 100%;
  min-height: 46px; margin-bottom: 8px;
  background: var(--soft); border: 1px solid #bfdbfe; border-radius: 11px;
  padding: 11px 13px; color: var(--primary);
  font-family: inherit; font-size: 15px; font-weight: 700; cursor: pointer;
}
.accion-fila .mi { width: 18px; height: 18px; }
.accion-fila:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

/* El numero de las filas de solicitudes en Mas. */
.menu-cuenta {
  background: var(--danger); color: #fff; border-radius: 999px;
  font-size: 13px; font-weight: 800; padding: 2px 8px; flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}
.menu-cuenta[hidden] { display: none; }

@media (prefers-reduced-motion: reduce) {
  .partida-check { transition: none; }
}

/* CHG-2026-0671 — la tarjeta del cliente, en la sesion de pago, abre su perfil.
   Es la unica puerta: esa pantalla no tiene barra a proposito. */

/* ═══════════════════════════════════════════════════════════════════════════
   CHG-2026-0696 — CERO SCROLL DONDE LA INFORMACION NO CRECE
   Eddy, 28-ago-2026: *"que no tenga skroll y solo la tenga en la que sea
   nesesaria porque la informacion creze ... pero las demas tienen que estar
   compacta, el boton de atras solo sea una flechita"*.

   Medido a 360x800 con dedo ANTES de tocar (medir_0696.js). El alto util real es
   800 - 62 del header - 87 de la barra flotante = 651px; sin barra, 738px.
   Con permiso de scroll (listas que crecen): Inicio, Historial del cliente,
   Mis clientes y Movimientos. Las demas tienen que caber.

   Va al FINAL del archivo por lo de siempre: es lo unico que gana sin tocar
   reglas compartidas que usan otras pantallas (regla #316 de la boveda).
   ═══════════════════════════════════════════════════════════════════════════ */

/* 1 · LA FILA DEL BOTON DE ATRAS SE VA — 54px en 8 pantallas.
   El boton NO se borra: se sigue necesitando en el DOM porque cada uno lleva su
   propia logica de a-donde-vuelve, y la flecha del header le reenvia el toque.
   Se apaga la FILA, no el boton, y solo la que cuelga directo de la pantalla:
   el `#stepHeader` de Registrar vive DENTRO de su tarjeta y no se toca. */
.screen > .step-header { display: none; }

/* 2 · La flecha del header. Mismo boton redondo de siempre (.back-btn), y cuando
   se ve, el logo se aparta: en una pantalla interna la marca no aporta nada y esos
   36px de ancho le hacen falta al titulo. El alto no cambia — los dos miden menos
   que la campana, que es la que manda. */
.head-back { flex: 0 0 auto; }
/* ⛔ Aqui habia un `:has(> .head-back:not([hidden]))` y NO FUNCIONABA: el logo
   seguia saliendo al lado de la flecha. Lo cazo la CAPTURA, no los checks — y
   encima mis dos checks miraban el `.app-icon` de la pantalla de login (hay
   SIETE en el archivo), asi que uno dio falso fallo y el otro falso verde por el
   mismo motivo. La clase la pone pintarFlechaHeader(), que ya sabe cuando hay
   flecha: menos listo y se puede comprobar. */
.mobile-header.con-flecha .app-icon { display: none; }

/* 3 · AJUSTES — el PIN y su boton en la misma linea (CHG-2026-0696).
   El campo son cuatro numeros: no necesita los 360px de ancho, y apilado costaba
   un renglon de 44px de los que habia que recuperar. `align-items: end` los deja
   alineados por abajo, que es donde esta el borde del input. */
.fila-pin {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 8px;
  align-items: end;
}
.fila-pin label { margin: 0; }
.fila-pin > button { width: auto; white-space: nowrap; }

/* 4 · FICHA — la tarjeta unica del resumen (CHG-2026-0696).
   Dos cifras al lado, no apiladas: en 360px cada columna se queda con ~156px, de
   sobra para "RD$13,000.00" al tamano de `.rs-grande`. Debajo, el avance y el
   estado por prestamo, que son de renglon entero. */
/* El avance y el estado ya traen su propio aire; aqui solo se separan de las
   cifras de arriba. */
.rs-resumen .rs-barra-caja { margin-top: 8px; }
.rs-resumen .rs-estados { margin-top: 8px; }

/* 5 · ⛔ EL BUG QUE APARECIO MIDIENDO — `hidden` NO ESTABA OCULTANDO NADA.
   CHG-2026-0696. Salio de una cuenta que no cuadraba: "Pedir un cambio" medía
   991px y sus hijos visibles sumaban 541. Los 450 que faltaban eran los bloques
   que el JS cree que apaga.

   `[hidden]` del navegador es `display: none` SIN `!important`, asi que cualquier
   regla de autor con display se lo come. Y aqui hay dos, de las mas usadas del
   archivo: `.grid { display: grid }` (linea 65) y `label { display: grid }` (68).
   Resultado: en "Pedir un cambio", `mostrarCamposSolicitud()` oculta cinco cosas
   con `.hidden = true` (solObjetoPagoLabel, solObjetoPrestamoLabel,
   solTipoPagoLabel, solCamposPago y solCamposPrestamo, app.js:1160-1165) y NO SE
   OCULTA NINGUNA: el cobrador ve a la vez los campos de editar un pago y los de
   editar un prestamo, con el selector diciendo una sola cosa. Nunca dio error.

   La trampa ya se habia cazado DOS veces y se tapo solo donde dolia
   (`.hist-filtro label[hidden]` y `#paymentFormPanel label[hidden]`, con su
   comentario y todo). Esta es la regla general, para que no haya una tercera.
   `.actions`, `.detail-view-grid` y las demas que fijan display ya traen la suya
   o no se ocultan nunca; estas dos eran las que faltaban. */
.grid[hidden],
label[hidden],
/* ⛔ CHG-2026-0699 — Y AQUI ESTABA LA TERCERA. Eddy, 28-ago-2026: *"inicio no
   puede tener un boton de atras porque inicio es una pagina central"*.

   `.back-btn { display: grid }` (linea 307) le ganaba al `[hidden]` del navegador,
   asi que la flecha del header que el CHG-2026-0696 estreno se veia en TODAS las
   pantallas — Inicio incluido — aunque `pintarFlechaHeader()` la apagara bien.
   Medido: en Inicio el atributo decia `hidden=true` y `offsetParent` decia que se
   estaba viendo igual. Y en Inicio no hace nada: `botonVolverDeLaPantalla()`
   devuelve null porque `home` no tiene `.step-header`, o sea que era una flecha
   muerta invitando a tocarla.

   Es exactamente la trampa que este bloque venia a matar. Van tres. */
.back-btn[hidden] { display: none; }

/* ⛔⛔ CHG-2026-0756 — LA REGLA DE RAIZ. Van SEIS.
   Hoy cayeron dos mas: `.pago-quien` (la tarjeta de avisos que el CHG-2026-0755
   empezo a esconder, y que dejaba una barrita azul vacia sobre el formulario de
   todo cliente sin avisos) y `#gpsEstadoTexto`. Con esas van seis veces la
   MISMA trampa, y el archivo ya llevaba quince parches puntuales: uno por cada
   vez que mordio, escritos siempre DESPUES de que alguien la viera en pantalla.

   El patron esta claro y no se arregla parche a parche: `[hidden]` del navegador
   es `display:none` SIN `!important`, asi que CUALQUIER regla de autor con
   `display` lo tumba — y este archivo pone `display` en casi todo. Cada bloque
   nuevo que estrene un `display` propio y alguna vez se apague desde el JS es un
   septimo caso esperando.

   Esta linea lo cierra para toda la app: un elemento con el atributo `hidden`
   NO se pinta, tenga el display que tenga. Las quince reglas puntuales de arriba
   quedan redundantes — se dejan en su sitio porque cada una documenta el bug que
   la trajo, pero ya no son lo que sostiene el comportamiento.

   Se apoya en el atributo, no en una clase: `hidden` significa escondido por
   definicion del HTML. (Si algun dia hace falta `hidden="until-found"` — el que
   deja que Ctrl+F encuentre texto plegado — habria que exceptuarlo aqui; hoy la
   app no lo usa en ningun sitio.) */
[hidden] { display: none !important; }

/* 6 · REGISTRAR PAGO — 928px para 738 de util (CHG-2026-0696).
   Lo que se toca y por que, medido a 360x800:

   a) Los tres montos, en TRES columnas de verdad. `.grid.three` se aplana a una
      sola por debajo de 720px (linea 238), asi que Capital, Interes y Mora salian
      apilados: 192px para tres numeros cortos. En tres columnas son 64px, y cada
      caja se queda con ~105px de ancho — de sobra para "13,000.00" y sin bajar
      del minimo tactil, que es de ALTO (44px) y no se toca.
      Va por id: es el unico `.grid.three` que se quiere en tres columnas.
   b) Las tres secciones respiran un poco menos. Sigue dentro de la escala
      4/8/12/16 del bloque UX PRO. */
/* El hueco era 8px justos y en 360px el redondeo lo dejaba en 7 -- por debajo
   del minimo de separacion entre dos cosas que se tocan (medido 19-sep-2026).
   Con 10 no depende del redondeo. */
#paymentAmountsGrid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
#paymentAmountsGrid label { margin-bottom: 0; }
#paymentFormPanel .form-sec { padding: 10px; margin-bottom: 8px; }
#paymentFormPanel .form-sec h3 { margin-bottom: 6px; }
/* La nota es opcional y casi siempre va vacia: dos renglones bastan. */
#paymentFormPanel #notas { min-height: 0; }

/* 7 · FICHA — los dos botones del prestamo, uno al lado del otro.
   `@media (max-width:720px) { button { width: 100% } }` los apilaba: 98px para dos
   botones que dicen tres palabras. Lado a lado son 44px y cada uno se queda con
   ~163px de ancho. Solo dentro de la ficha: la regla general de botones anchos
   se queda como esta en el resto de la app. */
#clienteFichaContent .rs-tj > .actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}
#clienteFichaContent .rs-tj > .actions button { width: 100%; margin: 0; }

/* 8 · AJUSTES — el par de campos cortos, en dos columnas de verdad.
   No usa `.two` a proposito: esa se aplana por debajo de 720px, que es justo el
   caso. Aqui son dos claves de pocas letras y caben. */
.par-corto {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}
.par-corto > label { margin-bottom: 0; }

/* 10 · REGISTRAR PAGO — las tres cajas de dentro pierden el marco (CHG-2026-0696).
   Eran una caja dentro de otra: `.form-sec` con borde y relleno propio, dentro de
   la tarjeta que ya tiene los suyos. Solo el envase de las tres costaba 66px de
   los 125 que faltaban. Los rotulos numerados (1,2,3) se quedan — son la guia del
   paso — y una linea fina los separa, que es lo que hacia el marco de verdad. */
#paymentFormPanel .form-sec {
  border: 0;
  border-radius: 0;
  padding: 10px 0 0;
  margin: 0 0 8px;
  background: none;
}
#paymentFormPanel .form-sec:first-of-type { border-top: 0; padding-top: 0; }
/* El pie del Total, ya en el rotulo: en minuscula y sin peso, para que se lea
   como una aclaracion y no como parte del nombre del campo. */
.campo-calculado .tag-auto {
  font-weight: 500; font-size: 13px; color: var(--muted);
  text-transform: none; letter-spacing: 0;
}

/* 12 · REGISTRAR PAGO — los ultimos 4px, y algo de holgura (CHG-2026-0696).
   Con todo lo de arriba la pantalla se quedo en 742px para 738 de util: pasaba
   por CUATRO. Un margen asi no aguanta un nombre largo ni un aviso de mas, asi
   que se le sacan 10: la tarjeta que envuelve el formulario baja su relleno a 10
   (sigue dentro de la escala 4/8/12/16) y las tres secciones se separan 6 en vez
   de 8. */
.register-card { padding: 10px; }
#paymentFormPanel .form-sec { margin-bottom: 6px; }

/* ═══════════════════════════════════════════════════════════════════════════
   CHG-2026-0699 — PAGO Y PERFIL SIN SCROLL

   Eddy, 28-ago-2026: *"quiero que las pantallas de pago y perfil del cliente
   este compacta para que no tenga skroll en la app 8091"*.

   Medido ANTES, con datos reales a 360 de ancho: el Perfil pedia 863px y la
   sesion de pago 809, contra 640 de alto util en un telefono chico. El grueso
   se resolvio quitando datos en app.js/index.html (ver OBJETIVO.md); aqui va
   solo el envase de lo que quedo.
   ═══════════════════════════════════════════════════════════════════════════ */

/* 1 · La cabecera del perfil recoge el alias y el "cliente desde" que venian en
   la tarjeta «Datos del cliente», retirada. Un renglon mas fino que el del
   telefono: es contexto, no el dato por el que se abre la ficha. */
.ficha-meta {
  font-size: 13px;
  opacity: .85;
}

/* 2 · Los dos botones del prestamo, en una fila que de verdad cabe. Ya iban en
   dos columnas (bloque 7 del CHG-2026-0696), pero a 360px "Registrar pago"
   partia en dos renglones y la fila costaba 76px en vez de 40. Se les baja la
   letra y el relleno.

   ⛔ EL ALTO SUBE DE 40 A 44 (CHG-2026-0827, hallazgo #207/#215 del vigilante).
   Este bloque pisaba la regla del sistema `@media (pointer: coarse) { button {
   min-height: 44px } }`, que es el minimo tactil de la casa, y lo dejaba en 40.

   Se midio antes de tocarlo, porque el comentario de arriba justificaba el 40 y
   subirlo a ciegas podia revivir el texto partido que ese arreglo evitaba. A
   360px con dedo emulado (`pointer: coarse`), con el styles.css que sirve el
   8091: el texto ocupa 344px de los 344px utiles y CABE EN UN RENGLON con 40 y
   tambien con 44. Lo que partia el texto era el ANCHO -- la letra y el relleno,
   ya arreglados --, nunca el alto. La fila crece 8px y nada mas. */
#clienteFichaContent .rs-tj > .actions-ficha { gap: 8px; }
#clienteFichaContent .rs-tj > .actions-ficha button {
  min-height: 44px; height: 44px; padding: 0 8px;
  font-size: 13px; white-space: nowrap;
}

/* 3 · Las tarjetas del perfil respiran un punto menos. Sigue dentro de la escala
   4/8/12/16 del bloque UX PRO: 12 de relleno y 6 de hueco. */
#clienteFichaContent .card { padding: 12px; }
#clienteFichaContent .rs-tj { margin-bottom: 6px; }

/* 4 · La sesion de pago. Con «Método: Efectivo», la ayuda del tipo de pago y el
   renglon del GPS fuera, lo que queda es el envase de las tres secciones. */
#paymentFormPanel .form-sec { margin-bottom: 4px; padding-top: 8px; }
#paymentFormPanel #notas { min-height: 0; }
.register-card { padding: 10px; }

/* 5 · La tarjeta «a quién le cobro»: el pie en UN renglón de verdad.
   El bloque 11 del CHG-2026-0696 ya lo puso en flex, pero a 360px con dos
   badges el "Ver perfil ›" se partía en dos renglones y la fila costaba 76px.
   Con `nowrap` en el enlace y los badges envolviéndose a su izquierda, la fila
   vuelve a los 26px de su `min-height`. */

/* 6 · El chooser de préstamo (CHG-2026-0699). Solo aparece cuando el cliente
   tiene dos préstamos abiertos y el cobrador toca «Pago» en la barra: ahí la app
   NO puede adivinar cuál. Cada fila dice el saldo y lo que debe, que es con lo
   que el cobrador distingue uno del otro con el cliente delante. */
.elegir-pie { display: block; margin-bottom: 10px; color: var(--muted); }
.cj-modal-msg .elegir-prestamo {
  display: block; width: 100%; text-align: left;
  height: auto; min-height: 52px; padding: 8px 12px; margin-bottom: 8px;
}
.elegir-prestamo b { display: block; font-size: 15px; }
.elegir-prestamo span { display: block; font-size: 13px; color: var(--muted); }

/* 7 · El campo Total, con su aclaración EN el renglón del rótulo.
   `label { display: grid }` (línea 68) le daba una fila propia al
   `<span class="tag-auto">`: "Total" arriba, "calculado solo" debajo y el campo
   al final — tres renglones para un número que no se toca. En flex, los dos
   textos comparten renglón y el campo baja entero. */
.campo-calculado {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px;
}
.campo-calculado input { flex: 1 0 100%; }

/* ── A6 (CHG-2026-0863) — SUELTO, SIN CAJA GRIS.
   Eddy corrigió el dibujo de CHG-2026-0759: aquella vez el Total llevaba una
   "barra" con fondo gris (`var(--line-soft)`) para leerse como resultado. Su
   dibujo nuevo pide los cuatro montos (Capital, Interés, Mora y Total) SUELTOS
   — ninguno metido en una caja. Se quita el fondo/relleno de la barra; el
   Total sigue debajo de los otros tres, en su propia fila, y sigue
   distinguiéndose por peso y tamaño de letra (no por una caja). */
/* CHG-2026-0885 (E1) — `.fila-montos-total` es el MISMO Total, para Saldar, el
   Reenganche (arriba) y la Entrega en mano: una regla para los cuatro, no una
   copia que envejece aparte. */
/* CHG-2026-1012 (O3): «Pago realizado» debajo del Total; la caja pide 8px como mínimo entre los
   dos datos y salían 7. Con #paymentFormPanel delante porque `#paymentFormPanel .form-sec`
   le pone margen 0 y pesa más que el id solo (medido: el margen no se movía). */
#paymentFormPanel #numPagoWrap { margin-top: 8px; }   /* se junta con los 4px de abajo de la sección: gana el mayor */
#totalWrap.campo-calculado,
.fila-montos-total.campo-calculado {
  flex-wrap: nowrap; align-items: center; gap: 8px;
  background: none; border-radius: 0;
  padding: 0; margin-top: 10px;
  font-weight: 700;
}
#totalWrap .tag-auto,
.fila-montos-total .tag-auto { flex-shrink: 0; }
#totalWrap input,
.fila-montos-total input {
  flex: 1 1 auto; width: auto; min-width: 0;
  text-align: right; border: 0; background: none; padding: 0;
  font-size: 15px; font-weight: 700; color: var(--text);
  font-variant-numeric: tabular-nums;
}
/* Pisa el `input[readonly]` de arriba (fondo gris, borde punteado, color muted):
   el número sigue siendo el protagonista, sin caja alrededor. */
#totalWrap input[readonly],
.fila-montos-total input[readonly] {
  background: none; border-style: none; color: var(--text);
}
/* CHG-2026-1053 (O3) — los tres montos que van al servidor no se ven, ni por error. */
.p91-carry { display: none !important; }
/* CHG-2026-1053 (O4) — «Próximo interés»: el valor («RD$250.00 · 01 nov de 2026») no cabe al
   lado del rótulo en 360 px y se cortaba («…de 202»). En el teléfono baja a su propia línea. */
#p91-proximo.campo-calculado { flex-wrap: wrap; align-items: baseline; gap: 2px; }
#p91-proximo input { flex: 1 0 100%; width: 100%; text-align: left; font-size: 14px; }
/* CHG-2026-0885 (E1, 1.3) — en "Otro pago" el Total es lo UNICO que se escribe,
   y por eso lleva cuadro: la regla de Eddy es "cuadro solo donde se escribe"
   (F09, 18-sep). Los otros tres siguen al aire. */
#totalWrap input.total-escribible {
  border: 1px solid var(--line); border-radius: 10px;
  padding: 6px 9px; background: var(--card);
}
/* La fila de montos de Saldar y del Reenganche: el mismo reparto que
   #paymentAmountsGrid (3 columnas, 10px entre una y otra). */
/* CHG-2026-1053 (O2) — LA FILA DE DOS SUB-RENG LONES (molde del 8082).
   Debajo de «Cuota» van el Interés y el Capital de esa cuota, más pequeños:
   es el reparto, no una cifra que el cobrador pueda cambiar. Sin esto la fila
   se veía como tres campos de igual tamaño y el detalle se perdía. */
#paymentFormPanel .fila-sub { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 0 0 2px; }
#paymentFormPanel .fila-sub label { margin: 0; gap: 1px; font-size: 12px; font-weight: 600; line-height: 1.4; color: var(--muted); }
#paymentFormPanel .fila-sub input { min-height: 26px; height: 26px; padding: 1px 4px; font-size: 12px; }
/* CHG-2026-1053 (Eddy 21/22-oct): Interés y Capital DEBAJO de la Cuota. Fila 1 = la Cuota a todo lo ancho con sus
   dos partes; fila 2 = Mora | Atrasados (en 360 px tres columnas cortaban los montos). */
#paymentFormPanel .col-cuota { display: flex; flex-direction: column; gap: 4px; min-width: 0; grid-column: 1 / -1; }
#paymentFormPanel .fila-montos:has(> .col-cuota) { grid-template-columns: 1fr 1fr; align-items: start; }
#paymentFormPanel .fila-montos .fila-sub label { font-size: 12px; font-weight: 600; color: var(--muted); }
#paymentFormPanel .fila-montos .fila-sub input { font-size: 12px; min-height: 26px; height: 26px; }
#paymentFormPanel .fila-montos { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
/* CHG-2026-1053 (O2) — Saldar y Reenganche llevan DOS montos (Cuota y Mora): con tres columnas cada
   uno tenía un tercio del ancho y se cortaba («RD$20,497.»). */
#paymentFormPanel .fila-montos.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
#paymentFormPanel .fila-montos label { margin-bottom: 0; }
.ree-titulo-nuevo { margin-top: 16px; }

/* 8 · Los badges del pie, en el MISMO renglón que "Ver perfil ›".
   Con «Mora RD$1,750.00» + «1 cuota atrasada» + el enlace, a 360px faltaban unos
   pocos píxeles y los badges caían a dos filas (26px de más). `display: contents`
   los sube a hermanos directos del pie, así reparten el renglón con el enlace en
   vez de pelearse por un hueco ya recortado; y el relleno del badge baja de 10 a
   7 — la letra NO se toca (el piso de 12px de esta hoja manda). */

/* 9 · Los últimos píxeles, medidos CON la fuente real (CHG-2026-0699).
   Las primeras vueltas se midieron desde `apps/`, que no tiene `fonts/`: el
   navegador caía a la del sistema y la pantalla salía 16px más corta de lo que
   es de verdad. Con Plus Jakarta Sans cargada, el peor caso de la sesión de pago
   (plazo fijo con mora, «Poner al día», tres campos) daba 656 contra 640, y el
   Perfil 646. Todo lo de abajo sigue en la escala 4/8/12/16. */
.register-card { padding: 8px 10px; }
#paymentFormPanel .form-sec { margin-bottom: 2px; padding-top: 6px; }
#clienteFichaContent .card { padding: 10px; }
/* Y los 4 que faltaban, con algo de holgura para un nombre largo: el rótulo de
   sección se pega un punto más a su contenido y el pie de la tarjeta del cliente
   baja su alto mínimo — ahí no hay nada que tocar, solo badges. */
#paymentFormPanel .form-sec h3 { margin-bottom: 4px; }


/* ═══════════════════════════════════════════════════════════════════════════
   CHG-2026-0701 · LA APP PLANA — sin tarjetas
   ═══════════════════════════════════════════════════════════════════════════
   Eddy, 28-ago-2026: *"quiero que se vea moderno y sin targetas"*, y al elegir
   el formato: **plano, separado por líneas finas**. Sobre el alcance: *"Toda la
   app de una vez"* — no solo el perfil.

   ⛔ VA AL FINAL DEL ARCHIVO A PROPÓSITO. Este archivo tiene DOS reglas `.card`
   (una arriba, otra en el bloque "UX PRO 14-jul") que se pisan entre sí, y el
   propio archivo avisa de ello. Editarlas por separado era pelearse con la
   cascada; un bloque al final gana por orden, con la misma especificidad, y se
   revierte borrándolo entero.

   Para volver atrás: borrar desde esta línea hasta el final, o restaurar
   `styles.css.bak-CHG-2026-0701`.
   ═══════════════════════════════════════════════════════════════════════════ */

/* — El envase se va: nada de recuadro, borde, esquina ni sombra — */
.card,
.compact-home-card,
.mobile-header {
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  padding-left: 0;
  padding-right: 0;
  margin-left: 0;
  margin-right: 0;
}

/* CHG-2026-0719 — LO QUE SEPARA BLOQUES DISTINTOS ES UNA BANDA, NO UNA RAYA.
   Aquí decía "lo que separa ahora es una línea fina" (CHG-2026-0694). Eddy la
   quitó el 30-ago. El reemplazo es la banda gris de lado a lado que usa WhatsApp
   entre grupos de ajustes: 8px de `--banda`, a sangre completa.

   El `100vw` con `margin-left:-50vw` es lo que la saca de los márgenes del
   contenedor sin tener que tocar el layout de cada pantalla. Como el body no
   desborda en horizontal, no aparece scroll lateral. */
.card + .card,
.card + .compact-home-card,
.compact-home-card + .card {
  position: relative;
  padding-top: 22px;
}
.card + .card::before,
.card + .compact-home-card::before,
.compact-home-card + .card::before {
  content: '';
  position: absolute;
  top: 0; left: 50%;
  width: 100vw; margin-left: -50vw;
  height: 8px;
  background: var(--banda);
  pointer-events: none;
}
.mobile-header {
  padding-bottom: 12px;
  /* CHG-2026-1053 (22-oct): la barra es pegajosa (sticky) y «al aire» la dejó transparente: al bajar, el
     contenido pasaba POR DEBAJO y se leía a través del título. Con el mismo color de la página sigue
     sin caja ni borde, pero tapa lo que pasa por detrás. */
  background: var(--bg);
}

/* — Las FILAS de las listas: planas, separadas por una línea fina —
     `.due-row` (Inicio), `.crow` (Clientes), `.prow` (pagos y comisiones),
     `.activity-item`, `.compact-movement`, `.ev-fila` (historial). Todas eran
     recuadros blancos sueltos; ahora son renglones de una lista.

     ⚠️ Aquí NO entran los CONTROLES —`input`, `select`, `textarea`, `.badge`,
     `.chip`, `.loan-pill`, `.back-btn`, los botones ni `.cj-modal-card`—: esos
     tienen esquina y fondo propios porque son controles, no tarjetas, y
     aplanarlos dejaría la app sin saber dónde se toca. */
.due-row,
.crow,
.prow,
.activity-item,
.compact-movement,
.ev-fila,
.summary-grid > div,
.form-sec,
.recibo-view,
.client-manage-row,
.manage-row {
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}
/* CHG-2026-0719 — entre renglones del MISMO grupo no va raya: va aire.
   Es lo que hace WhatsApp en su lista de chats y en sus ajustes: "Add to lists" y
   "Add notes" no tienen nada entre medio, los separa el espacio y que cada uno
   arranca con su icono en la misma columna. */
.due-row + .due-row,
.crow + .crow,
.prow + .prow,
.activity-item + .activity-item,
.compact-movement + .compact-movement,
.ev-fila + .ev-fila,
.form-sec + .form-sec {
  margin-top: 10px;
}

/* — Las tres cifras de Inicio: en fila, divididas por líneas finas (O11) —
     Eddy eligió "En fila, separadas por líneas finas". Se va el recuadro de cada
     una; queda el rótulo, la cifra y una línea vertical entre ellas.

     ⚠️ Va con `.home-stat-grid .stat-card` y no solo `.stat-card`: el archivo ya
     trae esa pareja (dos clases, más específica), y un `.stat-card` a secas
     perdía la pelea de la cascada aunque estuviera al final. Medido: quitaba la
     sombra pero dejaba el fondo blanco y la esquina — o sea, la tarjeta seguía
     ahí y el censo daba verde igual. */
.stat-card,
.home-stat-grid .stat-card {
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  padding: 10px 8px;
}
/* Las cuatro variantes pintaban fondo Y borde de color. Se quedan solo con el
   color del icono, que es lo que distingue una métrica de otra. */
.stat-card.blue,
.stat-card.orange,
.stat-card.green,
.stat-card.purple {
  background: transparent;
  border-color: transparent;
}
.home-stat-grid .stat-card + .stat-card {
  border-left: 1px solid var(--line-soft);
}

/* — La barra de abajo (O10) —
     Eddy: *"que el menu de abajo ocupe todo el espacio de abajo para que no se
     vea como que esta flotando pero si haga skroll el menu de abajo no
     desaparezca y que todo tenga el mismo fondo"*.

     De borde a borde, pegada abajo, con el MISMO fondo que la zona que hace
     scroll (`--bg`, el del body), sin sombra ni esquinas. Sigue `fixed`, así que
     al hacer scroll no desaparece.

     La línea de arriba era decisión mía. CHG-2026-0719: se quita — Eddy la pidió
     fuera junto con las otras 15. Lo que separa la lista del menú es que la lista
     termina con su aire de abajo (`padding-bottom` del contenedor) y el menú va
     sobre el mismo fondo, igual que en WhatsApp. */
.bottom-nav {
  left: 0;
  right: 0;
  bottom: 0;
  transform: none;
  width: 100%;
  max-width: none;
  border: 0;
  border-radius: 0;
  background: var(--bg);
  box-shadow: none;
  backdrop-filter: none;
  padding: 8px 8px calc(8px + env(safe-area-inset-bottom, 0px));
}

/* El hueco del final: la barra ya no flota con margen, así que el contenido
   necesita su propio espacio o el último renglón queda debajo de ella. */
.mobile-shell {
  padding-bottom: calc(84px + env(safe-area-inset-bottom, 0px));
}

/* ══════════════════════════════════════════════════════════════════════════
   CHG-2026-0719 — LA FICHA DEL CLIENTE LIMPIA
   Todo lo de este bloque sale de lo que Eddy midió conmigo en WhatsApp el
   30-ago-2026, desde el teléfono Android virtual. Ver
   runtime/docs/planes/ficha-cliente-limpia-20260830/OBJETIVO.md
   ══════════════════════════════════════════════════════════════════════════ */

/* ── El perfil: UN número grande y nada más ──────────────────────────────── */
.perfil-debe { text-align: left; }
.perfil-debe .rs-tit {
  display: block; font-size: 13px; font-weight: 700;
  color: var(--muted); text-transform: uppercase; letter-spacing: .04em;
}
.perfil-debe-cifra {
  display: block; margin: 2px 0 4px;
  font-size: 15px; font-weight: 800; line-height: 1.5; color: var(--text);
}
.perfil-debe small { display: block; font-size: 13px; color: var(--muted); }
.perfil-debe .rs-alerta { color: var(--warning); font-weight: 600; }

/* ── La fila del préstamo: barra de progreso + monto prestado ────────────── */
.fila-prestamo {
  width: 100%; display: block; text-align: left; cursor: pointer;
  background: transparent; border: 0; padding: 4px 0;
  font-family: inherit; color: inherit;
  min-height: 44px;   /* area de dedo */
}
.fila-prestamo:active { background: var(--banda); border-radius: 10px; }
.fp-cab { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.fp-cab b { font-size: 15px; font-weight: 700; }
.fp-chev { width: 20px; height: 20px; fill: var(--muted); flex: 0 0 auto; }
/* ⛔ El `display:block` NO es decorativo. La barra es un `<span>` (va dentro de un
   `<button>`, donde un `<div>` seria HTML invalido), y a un elemento EN LINEA el
   navegador le ignora el `height`. Sin esto la barra existe en el DOM, mide 0px de
   alto y no se ve: en la primera corrida en el telefono salio el "25%" solo, sin
   barra. Lo cazo la CAPTURA — ningun selector lo habria visto. */
.fila-prestamo .rs-barra { display: block; margin: 9px 0 6px; }

/* ── CHG-2026-0719 — la barra con el «X de Y» encima y el % DENTRO ───────────
   Eddy la pidió como la de Inicio («18 de 22 al día»), con el porcentaje en el
   medio. Por eso sube de 6px a 22px: un texto no cabe en 6.

   La píldora clara detrás del número NO es adorno: el centro de la barra cae
   sobre el relleno azul cuando el avance pasa del 50% y sobre la pista gris
   cuando no llega. Sin ella el mismo texto sería ilegible en la mitad de los
   préstamos — y eso no se ve probando con uno solo. */
.fp-avance {
  display: block; margin-top: 8px;
  font-size: 13px; color: var(--muted);
}
.fp-avance b { color: var(--text); font-weight: 800; }
.rs-barra-alta {
  position: relative;
  height: 22px; border-radius: 99px;
}
.rs-barra-alta i { border-radius: 99px; }
.rs-barra-pct {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none;
}
.rs-barra-pct b {
  background: rgba(255, 255, 255, .92);
  color: var(--text);
  font-size: 13px; font-weight: 800; line-height: 1.5;
  padding: 3px 8px; border-radius: 99px;
}
.fp-pie {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  font-size: 13px; color: var(--muted);
}

/* ── El título de grupo de las pantallas hijas ───────────────────────────────
   Como el "Login and security" de los ajustes de WhatsApp: gris, chiquito, sin
   marco y sin fondo. */
.grupo-tit {
  margin: 0 0 8px;
  font-size: 13px; font-weight: 700;
  color: var(--muted);
}

/* ── El historial: 2 renglones por fila, sin marco ───────────────────────────
   El `border` que tenía `.ev-fila` era un recuadro alrededor de CADA fila: otra
   raya, aunque no saliera en el grep de `border-top/bottom`. */
.ev-fila {
  width: 100%; text-align: left; cursor: pointer;
  border: 0; background: transparent;
  font-family: inherit; color: inherit;
  align-items: center; min-height: 56px; padding: 10px 6px; margin-bottom: 0;
}
.ev-fila:active { background: var(--banda); border-radius: 11px; }
/* ── Los iconos van DESNUDOS, como los del menú de abajo ─────────────────────
   Eddy, 30-ago-2026, viendo la pantalla ya cambiada: *"veo que los iconos en
   historial no cambiaron"*. El dibujo sí había cambiado (de un caracter de texto
   a un SVG), pero seguía metido en un CUADRITO DE COLOR — y los del menú de abajo
   van sueltos sobre el fondo, sin caja. Eso es lo que se veía distinto.

   El color no se pierde: pasa del fondo AL TRAZO del dibujo. Y el tamaño se
   iguala al de la barra (24px), que es de donde salió la queja. */
.ev-ic {
  width: 24px; height: 24px; border-radius: 0;
  background: transparent !important;
  margin-top: 2px;
}
.ev-ic svg { width: 24px; height: 24px; fill: currentColor; }
.ev-pago  .ev-ic { color: #15803d; }   /* verde: entró dinero */
.ev-mora  .ev-ic { color: #d97706; }   /* ámbar: se generó deuda */
.ev-prest .ev-ic { color: var(--primary); }
.ev-anul  .ev-ic { color: var(--muted); }   /* gris: deshecho, no es alarma */
.ev-tachado .ev-cuerpo b { text-decoration: line-through; color: var(--muted); }

/* ── Las dos excepciones a la banda, pedidas por Eddy el 30-ago ──────────────
   La regla general es banda entre bloques. Pero dentro de «Condiciones del
   préstamo» los dos grupos son dos caras del MISMO préstamo, no dos bloques
   distintos: ahí Eddy quiere una línea fina. Y antes del botón de abajo, nada.

   ⚠️ Esta línea NO reabre las 16 que se quitaron: es la ÚNICA del archivo, está
   pedida a mano para un sitio concreto, y lleva su propia clase en vez de un
   selector amplio — si mañana alguien vuelve a contar rayas, esta sale y tiene
   que salir. */
.card.sep-linea::before {
  height: 1px;
  background: var(--line);
}
.card.sep-linea { padding-top: 18px; }
.card.sep-nada::before { display: none; }
.card.sep-nada { padding-top: 6px; }

/* ── ⛔ CHG-2026-0719 — EL AZUL PEGADO DE LOS BOTONES PLANOS ─────────────────
 *
 * Eddy, 30-ago-2026: *"cuando estoy en el detalle de un cliente y le doy atras,
 * el boton de atras en el perfil del cliente se pone azul y se queda asi"*.
 *
 * La causa NO estaba en `.back-btn`: esta en la regla global `button:hover
 * { background: var(--primary-dark) }` (linea 104). En un TELEFONO el `:hover` no
 * existe de verdad — el navegador se lo deja pegado al ultimo elemento tocado
 * hasta que tocas otra cosa. Por eso "se queda asi".
 *
 * Y le pasa a CUATRO, no a uno: este cambio convirtio en `<button>` la cabecera
 * del cliente, la fila del prestamo y cada fila del historial. Todas heredaban el
 * mismo azul. Arreglar solo la flecha habria dejado las otras tres con el bug —
 * es la regla de Eddy de arreglar la REGLA, no el caso que nombro.
 *
 * El aviso al tocar NO se pierde: lo da `:active`, que en un telefono si es
 * momentaneo (dura lo que dura el dedo encima).
 *
 * ⚠️ `:hover` va DESPUES de `:active` en el archivo a proposito: con la misma
 * especificidad manda el ultimo, y si `:hover` fuera antes se comeria el gris del
 * `:active` y el boton no daria ninguna senal al tocarlo. */
.back-btn:hover,
.icon-btn:hover,
.fila-prestamo:hover,
.ev-fila:hover {
  background: transparent;
}
/* Y el aviso momentáneo del dedo, redeclarado para que gane al :hover de arriba. */
.back-btn:active,
.icon-btn:active { background: rgba(15, 23, 42, .06); }
.fila-prestamo:active,
.ev-fila:active { background: var(--banda); }

/* El detalle del evento respeta los saltos de línea del mensaje. */
.cj-modal-msg { white-space: pre-line; }

/* CHG-2026-0719 — aqui vivian las reglas de `.rs-dos`, `.rs-estados`,
   `.rs-estado-fila`, `.rs-chip`/`.rs-cub`/`.rs-pend`, `.rs-barra-caja`,
   `.rs-barra-pie`, `.prow-listo` y `.fp-pct`. Se retiran con el barrido de
   cabos sueltos: ninguno de esos elementos se pinta ya desde que el perfil se
   redujo a cuatro cosas y el porcentaje se metio DENTRO de la barra. CSS que
   estiliza lo que nadie dibuja engorda el archivo y hace creer que la pantalla
   todavia ensena eso. */

/* ═══════════════════════════════════════════════════════════════════════════
   CHG-2026-0720 — EL ANTES Y EL DESPUES DEL MOVIMIENTO

   Eddy, 30-ago-2026: *"los pagos, mora/interes y los prestamos cuando lo
   selecione muestre el antes y despues de lo que afecta en el cliente como en
   auditoria"*.

   Mismo molde que el desplegable del Historial del 8082 (`histLinea`), adaptado
   a un telefono: alli la fila cabe en una linea de escritorio; aqui la etiqueta
   va ARRIBA y los dos valores debajo, porque "Mora · periodo del 1 al 15 de
   agosto" + dos montos no entra en 360px de ancho.

   ⚠️ `.cj-modal-msg` trae `white-space: pre-line` (dos bloques mas arriba): con
   el, cada salto de linea del HTML se pinta como un renglon vacio y el detalle
   sale con huecos enormes. Por eso el bloque lo REPONE a `normal` para sus
   hijos. El mensaje de texto pelado —los avisos y las confirmaciones— sigue
   respetando sus saltos, que es para lo que se puso.
   ═══════════════════════════════════════════════════════════════════════════ */

.det-ev { white-space: normal; display: grid; gap: 14px; }

/* La cabecera: cuando paso y quien lo hizo. */
.det-ev-cab { display: grid; gap: 2px; }
.det-ev-cab .det-ev-cuando { color: var(--muted); font-size: 13px; font-weight: 600; }
.det-ev-cab .det-ev-monto { font-size: 15px; font-weight: 800; color: var(--text); }

.det-ev-grupo { display: grid; gap: 8px; }
.det-ev-grupo > h3 {
  margin: 0;
  font-size: 13px; font-weight: 800; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted);   /* hallazgos 110/119,
     CHG-2026-0737: 0.72rem quedaba 0.5px bajo el piso tipografico de 12px */
}

.det-ev-fila { display: grid; gap: 3px; }
.det-ev-et { color: var(--muted); font-size: 13px; font-weight: 600; }

/* CHG-2026-0720 — la fila de un monto pelado (sin flecha) cabe en UNA linea:
   rotulo a la izquierda, cifra a la derecha, como el recibo. Con todas a dos
   renglones el detalle de un pago pasaba del `max-height: 50dvh` del modal y el
   ultimo dato salia cortado. Las de antes -> despues siguen a dos renglones: ahi
   la etiqueta lleva el periodo y no entra al lado de dos montos. */
.det-ev-fila-corta {
  grid-template-columns: 1fr auto;
  align-items: baseline;
  gap: 10px;
}

/* Los dos valores. `tabular-nums` alinea los montos por la coma: sin eso
   RD$1,400.00 y RD$900.00 bailan y cuesta compararlos de un vistazo, que es
   justo para lo que sirve esta pantalla. */
.det-ev-val {
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
  font-size: 15px; font-weight: 700; color: var(--text);
  font-variant-numeric: tabular-nums;
}
/* El lado "antes" va apagado y el "despues" firme: el ojo cae en el valor que
   quedo, que es el que importa. Copiado del 8082 (text-gray-400 -> gray-700). */
.det-ev-antes { color: #9ca3af; font-weight: 600; }
.det-ev-flecha { width: 15px; height: 15px; flex-shrink: 0; color: #9ca3af; }
.det-ev-nota { color: var(--muted); font-size: 13px; font-weight: 500; line-height: 1.5; }

/* ── CHG-2026-0721 — EL DETALLE PIDE MAS ALTO QUE UN AVISO ───────────────────
 *
 * `.cj-modal-msg` lleva `max-height: 50dvh` (linea 1503) porque nacio para avisos
 * de dos renglones. El detalle de un movimiento es otra cosa: con el renglon nuevo
 * de la mora total del prestamo se sale 22px — medido por el test T9, que es el
 * check que nacio de que "Método" saliera cortado en el CHG-2026-0720.
 *
 * Se sube SOLO para el detalle (`:has(.det-ev)`), no para todos los modales: un
 * aviso de una linea con medio dedo de alto libre se veria descuadrado, y la regla
 * general la usan la confirmacion y el selector de prestamo.
 *
 * El 68dvh sale de medir, no de tantear: el detalle mas largo que existe hoy es un
 * pago con capital, interes, DOS moras de periodos distintos, la mora total, la
 * deuda y el metodo. Sigue habiendo `overflow-y: auto` debajo, asi que un caso mas
 * largo scrollea en vez de cortarse — pero el que se ve todos los dias, cabe. */
.cj-modal-msg:has(.det-ev) { max-height: 68dvh; }

/* ── La barra "Hay una versión nueva" (CHG-2026-0830) ────────────────────────
 * La pinta sw-registro.js cuando hay un service worker esperando. Va en esta
 * hoja y no como <style> inline porque la CSP de server.py permite
 * `style-src 'self' 'unsafe-inline'` hoy, pero el .js del mismo origen ya
 * cumple 'self' sin depender de esa concesión — si mañana se endurece la CSP,
 * la barra sigue viéndose.
 *
 * `bottom` lleva el safe-area del iPhone: sin él, en un teléfono con muesca la
 * barra queda debajo de la franja del gesto de inicio y el botón no se puede
 * tocar. Es el mismo motivo del viewport-fit=cover del index. */
#cj-aviso-version {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  bottom: calc(18px + env(safe-area-inset-bottom, 0px));
  z-index: 99999;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 11px 14px 11px 18px;
  border-radius: 12px;
  background: #111827;
  color: #f9fafb;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .28);
  font: 500 13.5px/1.35 system-ui, -apple-system, "Segoe UI", sans-serif;
  max-width: calc(100vw - 32px);
  animation: cjAvisoEntra .28s ease-out;
}
@keyframes cjAvisoEntra {
  from { opacity: 0; transform: translateX(-50%) translateY(12px); }
  to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}
#cj-aviso-version button {
  border: 0;
  cursor: pointer;
  border-radius: 8px;
  /* 44px de alto mínimo: es la regla del hallazgo #207/#215 del vigilante
     (CHG-2026-0827). Un botón de 36px en la calle, con el dedo, falla. */
  min-height: 44px;
  padding: 8px 14px;
  background: #2563eb;
  color: #fff;
  font: 600 13px/1 inherit;
  white-space: nowrap;
}
#cj-aviso-version button:hover { background: #1d4ed8; }
#cj-aviso-version .cj-aviso-x {
  background: transparent;
  color: #9ca3af;
  padding: 8px 10px;
  font-size: 15px;
  min-width: 44px;
}
#cj-aviso-version .cj-aviso-x:hover { background: transparent; color: #f9fafb; }


/* ── CHG-2026-0875 (F07) — LOS 4 MODOS EN ICONOS ────────────────────────────
 *
 * Eddy, 18-sep-2026: los 4 modos van como iconos arriba, sin texto pegado, y
 * el nombre del modo debajo. De paso resuelve un defecto medido ese dia: los 4
 * botones grandes NO cabian a 390px y "Reenganchar" quedaba cortado.
 *
 * ⛔ 44x44 es el minimo para que un dedo lo acierte. No se baja de ahi. */
.modo-ico-btn {
  min-width: 48px;
  min-height: 48px;
  padding: 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
}
.modo-ico {
  width: 24px;
  height: 24px;
  fill: currentColor;
  pointer-events: none;   /* el clic es del boton, no del dibujo */
}
/* el monto que el boton lleva escrito (lo pinta setPaymentType) ya no cabe
   dentro de un icono: se esconde. El monto del modo activo se ve abajo. */
.modo-ico-btn .choice-monto { display: none; }

/* El nombre del modo activo, debajo de los iconos. Mismo sitio y mismo estilo
   en los cuatro: eso es lo que hace que las 3 apps se vean iguales. */
.modo-titulo {
  font-weight: 700;
  font-size: 15px;
  margin: 10px 0 12px;
  min-height: 1.4em;   /* reserva el alto: sin esto la pantalla brinca al cambiar de modo */
}

/* ── CHG-2026-0875 (F07) — CUADRO SOLO DONDE SE ESCRIBE ─────────────────────
 *
 * Eddy, 18-sep-2026: "fijate que los campos no tienen cuadro detras, estan en
 * el aire". La regla salio de sus propias imagenes: los montos que solo se
 * miran (Capital, Interes, Mora, Total) van en el aire; la caja de Nota lleva
 * cuadro porque ahi SI se escribe.
 *
 * El cuadro deja de ser adorno y pasa a ser la senial de "aqui puedes
 * escribir". La caza la familia 15 de cj-diseno (F09).
 *
 * ⛔ El NOMBRE del campo se queda siempre visible encima del monto. Se quita el
 *    cuadro, no la etiqueta: un numero suelto sin decir de que es, es peor. */
.dato-solo-mirar,
.dato-solo-mirar input[readonly],
.dato-solo-mirar input:disabled {
  background: transparent !important;
  border: 0 !important;
  box-shadow: none !important;
  padding-left: 0;
  padding-right: 0;
}

/* ── CHG-2026-0875 (F07b) — LOS 4 ICONOS, AL AIRE ───────────────────────────
 *
 * Eddy, 18-sep-2026: "los 4 iconos (al dia, pago parcial, saldar y renganche)
 * deben quedar al aire sin cuadro ni sombra por detras".
 *
 * Es la MISMA regla del cuadro (F09), aplicada tambien a los iconos: el cuadro
 * es la senial de "aqui se escribe", y en un icono no se escribe nada.
 *
 * ⛔ Entonces, ¿como se sabe cual esta marcado? Por el COLOR del dibujo, no por
 *    una caja detras: el activo va en azul de marca y lleno, los otros en gris
 *    apagado. El nombre del modo, debajo, lo confirma con palabras -- nunca se
 *    deja el color como unica senial.
 *
 * Va con !important porque pisa reglas de `.choice-button` que viven en cinco
 * sitios del archivo (medido) y que son de los botones grandes de antes. */
#paymentFormPanel .modo-ico-btn,
.modo-ico-btn,
.modo-ico-btn.secondary,
.modo-ico-btn.active {
  background: transparent !important;
  border: 0 !important;
  box-shadow: none !important;
}
/* ⛔ CHG-2026-0875 (F07d) — LOS 3 APAGADOS SE VOLVIERON INVISIBLES.
 *
 * El gris claro sobre el fondo claro los borro de la pantalla: quedaba UN icono
 * a la vista y los otros tres no se veian. Se cazo MIRANDO la captura, no
 * leyendo el codigo — el DOM decia que los cuatro estaban ahi.
 *
 * Ahora los cuatro van en el AZUL DE MARCA, como en los dibujos de Eddy. El
 * apagado se distingue por ser mas tenue (65%), no por cambiar de color, y el
 * marcado va entero y un poco mas grande. El nombre del modo, debajo, lo dice
 * con palabras: el color nunca es la unica senial. */
.modo-ico-btn .modo-ico {
  fill: var(--primary, #2563EB);
  opacity: .55;
  transition: opacity .15s, transform .15s;
}
.modo-ico-btn.active .modo-ico { opacity: 1; }
.modo-ico-btn.active { transform: scale(1.12); }

/* CHG-2026-0875 (F07c) — la CAJA que envolvia los 4 iconos, tambien fuera.
 * Eddy, 18-sep-2026, mirando la pantalla ya cambiada: "al aire, sin cuadro ni
 * sombra por detras". Los iconos quedaban al aire pero seguian dentro de una
 * caja blanca con borde, y esa caja es el mismo cuadro un nivel mas arriba.
 * En sus dibujos los 4 iconos flotan sobre el fondo, sin nada detras. */
.form-sec:has(.modo-ico-btn),
.choice-grid:has(.modo-ico-btn) {
  background: transparent !important;
  border: 0 !important;
  box-shadow: none !important;
  padding-left: 0;
  padding-right: 0;
}
/* repartidos a lo ancho, como en sus dibujos */
.choice-grid:has(.modo-ico-btn) {
  display: flex !important;
  justify-content: space-around;
  align-items: center;
  gap: 4px;
}

/* ⛔ CHG-2026-0875 (F07e) — LOS 4 ICONOS ESTABAN APILADOS, NO EN FILA.
 *
 * MEDIDO en el DOM (no supuesto): los cuatro botones existian y eran visibles,
 * pero cada uno ocupaba 348-390px de ancho con `display:grid` — uno debajo del
 * otro. En la captura se veia UNO y parecia que los otros no estaban.
 *
 * La causa: la regla anterior usaba `:has()` sobre el contenedor y no aplico.
 * Ahora la fila lleva su propia clase en el HTML (`modo-iconos-fila`), que no
 * depende de que el navegador soporte nada. Menos elegante, pero se ve.
 *
 * Y el `!important` del ancho pisa `#paymentFormPanel .choice-button`, que
 * vive en cinco sitios del archivo y estira cada boton a todo lo ancho. */
.modo-iconos-fila {
  display: flex !important;
  flex-direction: row !important;
  justify-content: space-around !important;
  align-items: center;
  gap: 8px;
  background: transparent !important;
  border: 0 !important;
  box-shadow: none !important;
  padding: 4px 0 0 !important;
}
/* ⛔ `:not([hidden])` NO ES ADORNO. Sin el, el `display:inline-flex !important`
 *    de aqui PISA el `display:none` que trae el atributo `hidden`, y el boton
 *    escondido vuelve a la vista. Salieron CINCO iconos en vez de cuatro: el
 *    "Poner al dia" del indefinido, que solo aplica a otro tipo de prestamo.
 *    Se cazo mirando la captura. Un !important sobre `display` siempre tiene
 *    que excluir los ocultos. */
.modo-iconos-fila .modo-ico-btn:not([hidden]) {
  display: inline-flex !important;
  width: auto !important;
  min-width: 48px !important;
  max-width: 64px;
  flex: 0 0 auto !important;
}

/* el escondido se queda escondido, pase lo que pase */
.modo-iconos-fila .modo-ico-btn[hidden] { display: none !important; }

/* ── Aviso AL AIRE — el texto sobre el fondo de la tarjeta ─────────────────
 * CHG-2026-1033 (O2, ficha #1016; hermana de la #1012). Eddy, 19-oct-2026:
 * «quitar». Manda su regla vieja y general: «nada de cuadros: el contenido va
 * al aire sobre el fondo de la pantalla».
 *
 * HISTORIA (para que no vuelva): el CHG-2026-0876 (F15) le puso fondo azul y
 * marco, copiandolo de la app del telefono, para que el aviso de "esto es una
 * SOLICITUD, no crea nada" dejara de parecer la letra chica de otra cosa. El
 * TEXTO se queda -- es lo que evita que un cobrador crea que ya registro al
 * cliente -- pero la CAJA se va: el azul del propio texto ya lo separa, y el
 * fondo le robaba el sitio a la tarjeta (medido por el auditor: 26.082 px2 de
 * azul detras del aviso de Nuevo prestamo). Quedan padding, margen y tipografia:
 * sin `padding` el texto pegaria con el campo de arriba/abajo.
 *
 * Vale para los 4 usos de la clase en esta app (los 2 avisos de solicitud y los
 * 2 de ayuda del formulario de pago): la regla es UNA.
 * ⛔ La 8092 NO se toca: alli `.aviso-info` es OTRA regla (styles.css:638-642)
 *    y este encargo es de la 8091. */
.aviso-info {
  display: flex; gap: 8px; align-items: flex-start;
  margin: 8px 0 12px; padding: 10px;
  color: #1e40af;
  font-size: 13px; font-weight: 400; line-height: 1.5;   /* CHG-2026-1009 (#4072/#4073): era 600, competía con los campos */
}

/* CHG-2026-0885 (E2) — la barra pegada abajo de la pantalla de pago lleva el
   MISMO color del fondo de la pantalla (--bg), no un blanco al 92%: se ve igual
   y deja de ser una plancha (medido: la caja la contaba, 17.820 px2). Igual que
   en la 8092. */
#paymentFormPanel .sticky-actions { background: var(--bg); }

/* ══════════════════════════════════════════════════════════════════════════
   CHG-2026-0940 (O4) — PANTALLA ANCHA: la banda y la barra siguen la columna.
   En el teléfono (el uso real de la 8091) no cambia nada. En una pantalla ancha el
   contenido vive en una columna de 720 px al centro, y:
   · ficha 3263: la banda gris (CHG-2026-0719, «de lado a lado» en el teléfono) cruzaba
     toda la ventana; ahora mide lo que la columna.
   · ficha 3259: la barra de abajo sigue de borde a borde (Eddy: «que ocupe todo el
     espacio de abajo para que no se vea como que está flotando»), pero sus botones se
     alinean con la columna en vez de abrirse a las esquinas de la ventana.
   ══════════════════════════════════════════════════════════════════════════ */
@media (min-width: 721px) {
  .card + .card::before,
  .card + .compact-home-card::before,
  .compact-home-card + .card::before {
    width: 720px; margin-left: -360px;
  }
  .bottom-nav {
    padding-left: max(8px, calc(50% - 342px));
    padding-right: max(8px, calc(50% - 342px));
  }
}

/* CHG-2026-0940 (O4) — fichas 3271/3266/3272/3274/3269/3270 de la 8091. */
.btn-accion-ficha {
  display: flex; align-items: center; justify-content: center; width: 100%;
  min-height: 44px; margin-top: 16px; border-radius: 12px; border: 0;
  background: var(--primary); color: #fff; font-size: 15px; font-weight: 700; text-decoration: none;
}
/* 3272: el título del grupo sigue gris (como WhatsApp) pero en la letra de títulos (15), más
   grande que las etiquetas de los campos (13): se nota que manda sobre lo de abajo. */
.grupo-tit { font-size: 15px; }
/* 3274: «Cerrar sesión» se separa del grupo de arriba. */
.menu-row-salir { margin-top: 28px; }
/* 3269: el monto que solo se mira es el dato: negrita y color de texto; la etiqueta, gris. */
#capitalWrap, #interesWrap, #moraWrap { color: var(--muted); }
input.monto-dinero { color: var(--text) !important; font-weight: 700 !important; -webkit-text-fill-color: var(--text); opacity: 1; }
/* 3270: toda la fila de «No enviar recibo al cliente» es la zona que se toca (44 px). */
#cobroReciboSec label[for="cobroNoRecibo"] { min-height: 44px; }


/* ── CHG-2026-0980 — PIZARRA DEL VIGILANTE, FASE 3 (8091) ─────────────────────
   Va al final a propósito: la cascada pisa lo anterior (patrón de esta hoja). */

/* #3507/#3571 — Capital, Interés y Mora en tres columnas cortaban la cifra a 360px
   («RD$1,667.0»). En el teléfono: una fila por partida, rótulo a la izquierda y el
   monto entero a la derecha. */
/* Dos ids: `#paymentFormPanel .three` (id + clase, @media 420) le ganaba a un id solo. */
@media (max-width: 560px) {
  #paymentFormPanel #paymentAmountsGrid { grid-template-columns: 1fr; gap: 8px; }
  #paymentFormPanel #paymentAmountsGrid > label { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
  #paymentFormPanel #paymentAmountsGrid > label > span { flex: 0 0 auto; }
  #paymentFormPanel #paymentAmountsGrid > label input { flex: 0 1 60%; width: auto; min-width: 0; text-align: right; }
}

/* #3567 — «RD$22,640.00» se partía en dos renglones. Una cifra no se parte:
   se achica lo justo para caber. #3509/#3636 — el bloque de tres cifras ocupaba
   media pantalla; se compacta (icono más chico, menos aire). */
.home-stat-grid .stat-card strong { white-space: nowrap; font-size: clamp(12px, 3.6vw, 15px); }
.home-stat-grid .stat-card { min-height: 0; gap: 4px; padding: 6px 4px; }
.home-stat-grid .stat-icon { width: 28px; height: 28px; }

/* #3381 — los cobros seguidos no tenían separación: una línea fina entre uno y otro. */
#miHistorialList .prow + .prow { border-top: 1px solid var(--line-soft); padding-top: 8px; margin-top: 8px; }   /* CHG-2026-1009 (#4071): era 16/16 */
#miHistorialList .prow .prow-comision { margin-top: 4px; }

/* #3508/#3634 — el nombre largo va en su propia fila de ancho completo. */
.detail-view-grid .detail-view-field.ancho { grid-column: 1 / -1; }

/* #3572 — el correo partía «gmail.com» en dos columnas: fila propia. */
#cuentaDatos .detail-view-field:has(#cuentaCorreo) { grid-column: 1 / -1; }
#cuentaDatos .detail-view-field { align-content: start; }   /* CHG-2026-1009 (#4075): rótulo y valor juntos */

/* #3382 — Guardar la clave quedaba pegado a los campos. */
.par-corto + .actions { margin-top: 16px; }

/* #3569/#3570 — lo escogido en el selector, entero. */
.sel-completo { margin: 8px 0 0; font-size: 13px; color: var(--muted); white-space: normal; overflow-wrap: anywhere; }

/* #3383/#3384 — la acción del vacío o del error, a 16px y con 44px de alto. */
.vacio-accion { margin-top: 16px; justify-content: center; }
.vacio-accion button { min-height: 44px; }

/* CHG-2026-1009 (#4069/#4070, Eddy 12-oct-2026) — el Total destaca sobre sus partidas con el azul
   que ya usa el total del recibo. `input.monto-dinero` fuerza el color con !important; esta regla es
   más específica y lo gana. Solo el Total: Capital, Interés y Mora siguen en color de texto. */
#totalWrap input#rp-total { color: var(--primary) !important; -webkit-text-fill-color: var(--primary); font-weight: 800 !important; }

/* CHG-2026-1025 (O8): la lista de préstamos de «Mover pago». */
.mover-pago label { display: block; margin: 0.5rem 0; }
.mover-pago textarea { width: 100%; margin-top: 0.25rem; }

/* ═══ CHG-2026-1026 (O7) — LA TARJETA DE AVISO DE LA 8082 (cj-toast.js), PRESTADA ═══════════════════════
   Eddy, 17-oct-2026: después de registrar un pago, «solo un aviso como en la app 8082 donde muestre el
   estado de los eventos». cj-toast.js es el MISMO archivo en la 8082, la 8091 y la 8092; este tramo es
   el de sistema.css de la 8082 (líneas de cj-toast) tal cual, con los valores claros de la 8082 para las
   variables que esta app no tiene, y ajustes de teléfono al final (sobre la barra de abajo y letra
   de teléfono). */
.cj-toasts {
  --c-texto: #111b21; --c-texto-suave: #5C6B74; --c-texto-tenue: #69757D;
  --cj-borde: #e5e7eb; --cj-surface: #ffffff; --mov: 270ms; --mov-curva: cubic-bezier(.34, 1.42, .48, 1);
  --r-contenedor: .75rem; --r-control: .5rem; --z-aviso: 80;
}
/* ═══ Tarjetas de aviso de la esquina — cj-toast.js (CHG-2026-0688) ═══════════
   Los valores copiados de DentalPin (Nuxt UI v4 por defecto) están en la
   cabecera de cj-toast.js, con la línea de fuente de cada uno. Aquí solo se
   pintan. El `.cj-notif-panel` de arriba es el hermano de esto: mismo radio,
   mismo borde y misma curva de entrada, para que no parezcan de dos apps. */
.cj-toasts {
  position: fixed;
  /* Abajo a la derecha: el defecto de Nuxt UI (theme/toaster.ts:54). */
  right: 1rem; bottom: 1rem;
  /* Por encima de los diálogos a propósito: `--z-aviso` es 80 y cj-dialog.js
     apila desde 80, así que un aviso disparado DESDE un diálogo quedaría
     debajo del propio diálogo y no se vería. Se le da aire por arriba. */
  z-index: calc(var(--z-aviso, 80) + 20);
  display: flex; flex-direction: column; gap: .75rem;
  width: min(23rem, calc(100vw - 2rem));
  /* El contenedor no debe comerse los clics de la pantalla que hay debajo;
     cada tarjeta se los devuelve. */
  pointer-events: none;
}
.cj-toast {
  pointer-events: auto;
  position: relative; overflow: hidden;
  display: flex; align-items: flex-start; gap: .625rem;
  padding: .7rem .75rem;
  /* ⚠️ `--cj-surface` y NO `--panel`: `--panel` no está definido en ninguna hoja
     de esta app (se comprobó, 27-ago-2026), así que siempre cae al blanco del
     respaldo — también en tema oscuro. El token bueno lo define tema-oscuro.css
     y cambia con el tema. */
  background: var(--cj-surface, #fff);
  border: 1px solid var(--cj-borde, rgba(11, 28, 48, .12));
  border-left: 3px solid var(--cj-toast-color, #2563eb);
  border-radius: var(--r-contenedor);
  box-shadow: 0 10px 34px rgba(11, 28, 48, .22);
  animation: cj-toast-entra var(--mov) var(--mov-curva) both;
  touch-action: pan-y;   /* deja el gesto horizontal para descartar */
}
/* Mientras se arrastra no hay transición: el dedo tiene que mandar directo. */
.cj-toast.cj-toast-agarrada { transition: none; cursor: grabbing; }
.cj-toast:not(.cj-toast-agarrada) { transition: transform .18s ease, opacity .18s ease; }

.cj-toast-icono {
  flex-shrink: 0; width: 1.6rem; height: 1.6rem; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 13px !important;
}
.cj-toast-texto { flex: 1; min-width: 0; }
/* ⚠️ OJO CON LA ESCALA AL ELEGIR TOKENS AQUÍ — mordió dos veces el 27-ago-2026.
   `--t-1`, `--t-2` y `--t-3` llevan un piso ABSOLUTO de 12px (CHG-2026-0551),
   pero los tokens grandes son en REM. Y el root de esta app es
   `clamp(11.5px, 0.6667vw, 16px)`: por debajo de 1728px de ancho vale 11.5px,
   así que `--t-6` (1rem) mide 11.5px reales — MENOS que los 12px del piso de
   `--t-3`. Resultado: la descripción salía MÁS GRANDE que el título.

   Primero se probó t-4/t-2 (10px contra 12px, peor todavía) y después t-6/t-3
   (11.5 contra 12, seguía invertido). Lo único que aguanta a cualquier ancho de
   pantalla es darle al título su propio piso, igual que hizo CHG-2026-0551 con
   los tokens chicos. Medido: 13px contra 12px en 1440px y en 1920px. */
.cj-toast-titulo {
  font-size: 13px; font-weight: 700; color: var(--c-texto, #111b21);
  line-height: 1.3; overflow-wrap: anywhere;
}
.cj-toast-desc {
  font-size: 13px; color: var(--c-texto-suave, #667781);
  margin-top: .15rem; line-height: 1.35; overflow-wrap: anywhere;
}
.cj-toast-acciones { display: flex; gap: .4rem; margin-top: .45rem; flex-wrap: wrap; }
.cj-toast-accion {
  font-size: 13px; font-weight: 600; padding: .25rem .6rem;
  border-radius: var(--r-control, 8px); cursor: pointer;
  color: var(--cj-toast-color, #2563eb);
  background: color-mix(in srgb, var(--cj-toast-color, #2563eb) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--cj-toast-color, #2563eb) 28%, transparent);
}
.cj-toast-accion:hover { background: color-mix(in srgb, var(--cj-toast-color, #2563eb) 18%, transparent); }

.cj-toast-x {
  flex-shrink: 0; padding: .1rem; border-radius: 50%; cursor: pointer;
  color: var(--c-texto-tenue, #8696a0); line-height: 0;
}
.cj-toast-x:hover { background: rgba(11, 28, 48, .08); }
.cj-toast-x .material-symbols-outlined { font-size: 13px !important; }

/* La barra ES el reloj: su animación y el temporizador de JS duran lo mismo, y
   al pasar el ratón se pausan las dos (ver cj-toast.js). Si fueran dos cuentas
   distintas, la barra mentiría en cuanto alguien pasara el ratón por encima. */
.cj-toast-progreso {
  position: absolute; left: 0; bottom: 0; height: 2px;
  background: var(--cj-toast-color, #2563eb); opacity: .55;
  width: 100%; transform-origin: left;
  animation: cj-toast-cuenta linear forwards;
}
/* hallazgo 98/116, CHG-2026-0737: animaba `width` (recalcula la maqueta en
   cada fotograma durante los 5000ms). `transform: scaleX()` pinta el mismo
   encogimiento por composicion, sin tocar el layout -- el elemento ya traia
   `transform-origin: left`, listo para esto. */
@keyframes cj-toast-cuenta { from { transform: scaleX(1); } to { transform: scaleX(0); } }
@keyframes cj-toast-entra {
  from { opacity: 0; transform: translateY(10px) scale(.98); }
  to   { opacity: 1; transform: translateY(0)    scale(1); }
}
/* hallazgo 161, CHG-2026-0781: animaba `max-height` y `margin-top`, y los dos
   recalculan la maqueta en CADA fotograma de los 200ms -- con hasta cinco
   tarjetas a la vez. Es el mismo defecto que ya se corrigio arriba en la barra
   de cuenta atras (hallazgo 98/116): opacidad y `transform` los pinta el
   compositor sin tocar el layout.

   LO QUE SE PIERDE, DICHO CLARO: el hueco de la tarjeta ya no se cierra poco a
   poco; las de abajo suben de golpe cuando el elemento sale del DOM. Se acepta
   por dos razones medidas: (1) ese cierre gradual ya era falso -- `max-height`
   arrancaba en 12rem y la tarjeta real mide bastante menos, asi que la primera
   mitad de la animacion no encogia nada; (2) el salto ocurre cuando la tarjeta
   ya esta en opacidad 0, o sea que no se ve desaparecer nada, solo subir las de
   abajo. Un fotograma de reacomodo a cambio de 200ms de maqueta recalculada. */
@keyframes cj-toast-sale {
  from { opacity: 1; transform: translateX(0); }
  to   { opacity: 0; transform: translateX(24px); }
}
.cj-toast-sale { animation: cj-toast-sale .2s ease-in forwards !important; }

/* Con el movimiento reducido encendido: nada de deslizamientos ni de barra que
   corre. La tarjeta aparece y ya. La cuenta atrás la sigue llevando el
   temporizador de JS, así que se cierra igual de sola. */
@media (prefers-reduced-motion: reduce) {
  .cj-toast, .cj-toast-sale { animation: none !important; }
  .cj-toast-progreso { animation: none !important; width: 100%; }
}


/* Teléfono: encima de la barra de abajo, a lo ancho, y con letra de teléfono. */
.cj-toasts { left: 12px; right: 12px; width: auto; bottom: calc(84px + env(safe-area-inset-bottom, 0px)); }
.cj-toast-titulo { font-size: 15px; }
/* CHG-2026-1053 (T27, ficha #4393): las DESCRIPCIONES de los avisos bajan a la
   letra de cuerpo de la app (13 px) con interlineado 1,5. Los TÍTULOS se
   quedan en 15 px: la jerarquía se mantiene. */
.cj-toast-desc { font-size: 13px; line-height: 1.5; }
.cj-toast-icono { width: 28px; height: 28px; }
.cj-toast-svg svg { width: 16px; height: 16px; fill: currentColor; }
.cj-toast-x svg { width: 14px; height: 14px; fill: currentColor; }

/* CHG-2026-1026 (O8) — Movimientos: la fila se toca para ver el detalle del pago, y dice si el recibo le
   llegó al cliente. Los cuatro tonos vienen de la base (estado_recibo_pago.tono). */
.prow-tocable { cursor: pointer; }
.prow-tocable:active { background: rgba(37, 99, 235, .06); }
.prow .prow-recibo { grid-column: 1 / -1; font-size: 13px; font-weight: 600; }
.prow-recibo-bien   { color: #15803d; }
.prow-recibo-espera { color: #b45309; }
.prow-recibo-mal    { color: #b91c1c; }
.prow-recibo-gris   { color: #6b7280; }
/* CHG-2026-1026 (O7): en esta app los botones son de ancho entero y con fondo; la X de la tarjeta no. */
.cj-toasts .cj-toast-x { width: 32px; height: 32px; min-width: 32px; min-height: 0; flex: 0 0 32px; padding: 0;
  margin: -4px -4px 0 0; background: transparent; border: 0; box-shadow: none; color: #64748b;
  display: flex; align-items: center; justify-content: center; border-radius: 50%; }
.cj-toasts .cj-toast-accion { width: auto; min-height: 0; }

/* CHG-2026-1033 (O2, ficha #4328) — «Pedir un cambio»: el resumen de arriba (el pago o el
   préstamo que se va a corregir) va AL AIRE, sin cuadro (regla de Eddy: «nada de cuadros: el
   contenido va al aire»), y el botón «Cambiar selección» queda separado de él para que no se
   lea como parte de la frase. Solo da aire; ni un tamaño de letra nuevo (la escala 13/15 manda). */
#solContexto { margin: 0 0 14px; }
/* CHG-2026-1053 (T27, ficha #1029): el interlineado del contexto (título, el
   <strong> del cliente y la ayuda) sube a 1,5 — el mínimo de la app. Estaba en
   1,45 y el texto se leía más apretado que el resto. El `line-height` se
   hereda, pero se pone en los tres para que no dependa de eso. */
#solContexto p { margin: 0 0 6px; font-size: 15px; line-height: 1.5; }
#solContexto p.hint { margin: 0 0 10px; font-size: 15px; line-height: 1.5; }
#solContexto strong { color: var(--text); line-height: 1.5; }

/* CHG-2026-1053 (T27, ficha #4395) — «Mi sesión» sale de la rejilla de datos
   personales y se queda con «Estado de conexión», debajo de WhatsApp y antes de
   Seguridad, a TODO el ancho y al aire (sin caja, sin título, sin marco). */
.sesion-campo { margin-top: 10px; }

/* ══════════════════════════════════════════════════════════════════════════
 * CHG-2026-1056 (O4) — LA PANTALLA DE PAGO CON EL MOLDE DE EDDY (el mismo de la
 * ventana del 8082): caja gris con Fila 1 Cuota (↳ Interés, ↳ Capital) · Cuota
 * atrasada · Mora (indefinido: Capital · Interés) y Fila 2 Cuotas realizadas ·
 * Saldo restante; debajo Total a pagar, Sin recibo, Nota y el botón. Aquí no hay
 * «Método» a propósito: el cobrador solo recibe efectivo (refinamiento 31-jul).
 * ══════════════════════════════════════════════════════════════════════════ */
#paymentFormPanel .p91-caja-montos { background: var(--bg); border: 1px solid var(--line); border-radius: 12px;
  padding: 10px 10px 8px; margin-bottom: 6px; }
#paymentFormPanel .p91-caja-montos .fila-montos { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; align-items: start; }
#paymentFormPanel .p91-caja-montos .fila-montos:has(> .col-cuota) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
#paymentFormPanel .p91-caja-montos .col-cuota { grid-column: auto; gap: 1px; }
#paymentFormPanel .p91-caja-montos .fila-montos.two, #paymentFormPanel #p91-fila-indef,
#paymentFormPanel #p91-fila-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
#paymentFormPanel .p91-caja-montos label { display: grid; gap: 0; margin: 0; font-size: 13px; font-weight: 600; line-height: 1.5; color: var(--muted); }
#paymentFormPanel .p91-caja-montos input.dato-solo-mirar { min-height: 0; height: auto; padding: 0 !important; border: 0;
  background: transparent; font-size: 14px; font-weight: 700; line-height: 1.5; color: var(--text); text-align: left;
  white-space: nowrap; overflow: visible; }
#paymentFormPanel .p91-caja-montos .fila-sub { grid-template-columns: 1fr; gap: 0; margin: 2px 0 0; }
#paymentFormPanel .p91-caja-montos .fila-sub label { font-size: 12px; line-height: 1.5; }
#paymentFormPanel .p91-caja-montos .fila-sub input.dato-solo-mirar { font-size: 12px; font-weight: 600; color: var(--muted);
  padding-left: 14px !important; }
#paymentFormPanel #p91-fila-2 { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--line); }
#paymentFormPanel #numPagoWrap, #paymentFormPanel #saldoDespuesWrap { min-height: 0; }
#paymentFormPanel #numPagoValor { white-space: normal; }
/* La Nota y el Motivo en un renglón: rótulo visible a la izquierda y la casilla al lado. */
#paymentFormPanel .fila-inline, #reenganchePanel .fila-inline, .fila-inline { display: flex !important; align-items: center; gap: 8px; }
.fila-inline > input { flex: 1; min-width: 0; min-height: 40px; }
#cobroReciboSec label[for="cobroNoRecibo"] { min-height: 40px; }
/* CHG-2026-1056 (O4) — en el teléfono la Fila 1 del molde SIGUE en tres columnas (Cuota · Cuota atrasada ·
   Mora): la regla de #3507 (renglones con el monto a la derecha) se cambia por cifras de 13 px que no se
   parten. La prueba de este cambio mide que ninguna cifra quede cortada a 360 px. Dos ids para ganarle a la
   regla de @media de arriba. */
@media (max-width: 560px) {
  #paymentFormPanel #paymentAmountsGrid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }   /* CHG-2026-1073 (#1161): 8 px entre datos */
  #paymentFormPanel #paymentAmountsGrid > label, #paymentFormPanel #paymentAmountsGrid .col-cuota > label {
    display: grid; justify-content: stretch; gap: 0; }
  #paymentFormPanel #paymentAmountsGrid > label input, #paymentFormPanel #paymentAmountsGrid .col-cuota > label input {
    width: 100%; text-align: left; font-size: 13px; }
  #paymentFormPanel #paymentAmountsGrid .col-cuota { grid-column: auto; }
  #paymentFormPanel .p91-caja-montos label { font-size: 12px; }
}
#paymentFormPanel #totalWrap { margin: 4px 0 0; min-height: 36px; white-space: nowrap; }
#paymentFormPanel #totalWrap .tag-auto { font-size: 12px; }
#paymentFormPanel #cobroReciboSec { padding-top: 0; margin: 0; }
#paymentFormPanel #cobroReciboSec label[for="cobroNoRecibo"] { min-height: 40px; }
#paymentFormPanel .form-sec { margin-bottom: 4px; }

/* CHG-2026-1056 (O4.2) — Saldar y Reenganche: la fila Saldo · Mora en la caja gris y el préstamo nuevo
   en tres columnas, con casillas de 36 px, para que quepan sin bajar en 360×800. */
#paymentFormPanel #saldarPanel h3, #paymentFormPanel #reenganchePanel > h3 { margin: 0 0 4px; }
#paymentFormPanel #reenganchePanel .ree-tres { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
#paymentFormPanel #reenganchePanel label { margin-bottom: 2px; gap: 1px; font-size: 12px; line-height: 1.3; }
#paymentFormPanel #reenganchePanel input:not(.dato-solo-mirar), #paymentFormPanel #reenganchePanel select {
  min-height: 36px; height: 36px; padding: 4px 8px; font-size: 14px; }
#paymentFormPanel #reenganchePanel #reeCuotaPartes input { min-height: 0; height: auto; padding: 0; font-size: 14px; }
#paymentFormPanel #reenganchePanel .fila-montos-total { margin: 2px 0; min-height: 30px; }
#paymentFormPanel #reenganchePanel .actions, #paymentFormPanel #saldarPanel .actions { margin-top: 6px; gap: 6px; }
#paymentFormPanel #reenganchePanel .actions button, #paymentFormPanel #saldarPanel .actions button { min-height: 44px; }
#paymentFormPanel #reenganchePanel .p91-caja-montos, #paymentFormPanel #saldarPanel .p91-caja-montos { padding: 8px 10px; }
#paymentFormPanel #reenganchePanel .fila-montos-total, #paymentFormPanel #saldarPanel .fila-montos-total { white-space: nowrap; }
#paymentFormPanel #reenganchePanel #reeEntregaWrap input { font-weight: 700; color: var(--text); padding: 6px 0; }
#paymentFormPanel #reenganchePanel .ree-titulo-nuevo { margin: 4px 0 2px !important; }
#paymentFormPanel #reenganchePanel .p91-caja-montos { margin-bottom: 2px; }
#paymentFormPanel #reenganchePanel #reeCuotaPartes { margin: 0; }
#paymentFormPanel #reenganchePanel .fila-inline { margin: 2px 0; }
/* CHG-2026-1056 (O4.2): los 17 px que le faltaban al Reenganche de un préstamo con cuota a 360×800. */
/* CHG-2026-1073 (vigilante #1038/#1166): 44 de alto, el minimo comodo para el dedo. Medido: Reenganche
   sigue sin scroll a 360x800 (el ultimo boton bajo de 617 a ~630 de 800). */
#paymentFormPanel .choice-button.modo-ico-btn { min-height: 44px; }
#paymentFormPanel #modoTitulo { margin: 2px 0 4px; }
#paymentFormPanel #reenganchePanel input:not(.dato-solo-mirar), #paymentFormPanel #reenganchePanel select { min-height: 34px; height: 34px; }
#paymentFormPanel #reenganchePanel .ree-tres { row-gap: 2px; }
/* CHG-2026-1056: dentro de la Fila 2 del molde, «Cuotas realizadas» y «Saldo restante» van a la MISMA altura
   (el margen de 8 px de «Pago realizado» de v93 era para cuando iba suelto debajo del Total). */
#paymentFormPanel #p91-fila-2 #numPagoWrap, #paymentFormPanel #p91-fila-2 #saldoDespuesWrap { margin: 0 !important; padding: 0 !important; }
#paymentFormPanel #p91-proximo { margin: 0 0 4px; min-height: 0; gap: 0; }
#paymentFormPanel #p91-proximo input { padding: 0 !important; min-height: 0; height: auto; line-height: 1.5; }
