/* =====================================================================
   cascaron.css — el menú, la pantalla de inicio y la pantalla pendiente

   Va aparte de `estilos.css` a propósito: aquél viste la pantalla de
   captura (el CTMOVI09, que es la réplica fiel), y éste viste el chasis
   que la contiene. Son dos cosas con vidas distintas — el día que se
   replique una segunda pantalla, este archivo no cambia.

   Lo que se pinta aquí es el árbol REAL volcado de la instalación de
   producción: 354 comandos en 10 módulos, hasta 6 niveles de profundidad.
   `menu.js` lo construye desde `menu-concar.json`; esto sólo lo hace
   mirable.

   Misma regla que `estilos.css`, heredada de Ratio: ni un hex aquí. Todo
   sale de un token semántico de `olympium-tokens.css`.
   ===================================================================== */

/* --------------------------- barra de menú --------------------------- */

.menu-modulo { position: relative; }

.menu-titulo {
  display: flex; align-items: center; gap: var(--oly-space-2);
  height: var(--oly-control-height-sm);
  padding: 0 var(--oly-space-3);
  font-family: var(--oly-font-family);
  font-size: var(--oly-font-size-xs);
  font-weight: var(--oly-font-weight-medium);
  color: var(--oly-text-secondary);
  background: transparent;
  border: none;
  border-radius: var(--oly-radius-sm);
  cursor: pointer; white-space: nowrap;
  transition: background var(--oly-motion-duration-fast) var(--oly-motion-ease-productive),
              color var(--oly-motion-duration-fast) var(--oly-motion-ease-productive);
}
.menu-titulo:hover { background: var(--oly-surface-hover); color: var(--oly-text-primary); }
.menu-abierto > .menu-titulo {
  background: var(--oly-action-primary-subtle);
  color: var(--oly-text-on-primary-subtle);
}

/* El recuento por módulo va en la barra a propósito: es la primera
   respuesta a la pregunta "cuánto es CONCAR", sin abrir nada. */
.menu-cuenta {
  font-size: var(--oly-font-size-3xs);
  font-variant-numeric: tabular-nums;
  color: var(--oly-text-tertiary);
  background: var(--oly-surface-subtle);
  border-radius: var(--oly-radius-full);
  padding: 0 var(--oly-space-2);
  line-height: var(--oly-line-height-xs);
}
.menu-abierto > .menu-titulo .menu-cuenta {
  color: var(--oly-text-on-primary-subtle);
  background: var(--oly-action-primary-subtle-pressed);
}

/* Los paneles de primer nivel también van `fixed` y también los coloca
   `menu.js`. Con `position: absolute; left: 0` los módulos del extremo
   derecho se salían de la pantalla —medido: "Nuevo PCGE" se iba 273px y
   generaba scroll horizontal real de la página, scrollWidth 1713 contra
   clientWidth 1425—. La lógica de volteo estaba sólo en las ramas
   interiores; ahora es la misma para los dos niveles. */
.menu-lista {
  display: none;
  position: fixed; top: 0; left: 0; z-index: 70;
  /* 470px cortaba «Genera Archivo Mensual Compras IGV 18%» justo en el
     dígito. Con 560 entra entero en un renglón; lo que aun así no entre,
     envuelve (ver `.menu-opcion-nombre`), no se recorta. */
  min-width: 320px; max-width: 560px;
  /* El alto lo fija `menu.js` midiendo el hueco que queda por debajo del
     panel. Aquí sólo va un respaldo por si el JS no llegó a colocarlo.
     Había un `min(72vh, 640px)` fijo y estaba mal: en una ventana de 847px
     recortaba el panel a 610 y sacaba barra de scroll con media pantalla
     vacía debajo. La regla es al revés -- usar el espacio que hay, y
     encoger sólo cuando de verdad no entra. */
  max-height: calc(100vh - 120px);
  overflow-y: auto; overflow-x: hidden;
  margin: 0; padding: var(--oly-space-1);
  list-style: none;
  background: var(--oly-surface);
  border: 1px solid var(--oly-border);
  border-radius: var(--oly-radius-sm);
  box-shadow: var(--oly-shadow-lg);
}
.menu-abierto > .menu-lista { display: block; }

/* Las ramas se abren AL COSTADO, en cascada, como el menú de escritorio de
   CONCAR. Hubo un intento de resolverlo con sangría hacia adentro, tipo
   acordeón, para esquivar el problema de los 6 niveles: se descartó porque
   rompe el modelo mental del contador, que es justo lo que esta pantalla
   no puede tocar.

   El submenú va `position: fixed` y no `absolute`. No es capricho: la lista
   raíz necesita `overflow-y: auto` (Reportes tiene 165 opciones) y eso
   recortaría cualquier hijo absoluto. Un elemento `fixed` escapa del
   recorte de sus ancestros con overflow, siempre que ninguno cree un
   bloque contenedor con `transform`, `filter` o `will-change` — por eso la
   barra de menú no lleva ninguno.

   Como `fixed` se posiciona contra el viewport, las coordenadas las calcula
   `menu.js` al pasar el mouse, y ahí decide también si abre a la derecha o
   a la izquierda según el espacio que quede. */
.menu-rama { position: relative; }
.menu-rama > .menu-lista {
  position: fixed; display: none;
  top: 0; left: 0;
  /* 🔴 Este era el tope que cortaba de verdad. La lista raíz tiene el suyo
     (560px) pero las opciones de compras viven TRES niveles adentro
     —Reportes › Libros y Registros Oficiales › Registro de Compras— y ahí
     mandaba este 440. Medido el 03/09/2026: el nombre disponía de 306px y
     «Genera Archivo Mensual Compras IGV 18%, 10.5% y 10% 2023-2026» pide
     474. */
  min-width: 300px; max-width: 560px;
  max-height: min(70vh, 620px);
}
.menu-rama.rama-abierta > .menu-lista { display: block; }

/* La flecha gira cuando la rama está desplegada, como en cualquier menú en
   cascada: dice hacia dónde se abrió. */
.menu-rama.rama-abierta > .menu-opcion {
  background: var(--oly-selection-hover-surface);
  color: var(--oly-text-on-primary-subtle);
}

.menu-opcion {
  display: flex; align-items: center; gap: var(--oly-space-2);
  width: 100%;
  padding: var(--oly-space-2) var(--oly-space-2);
  font-family: var(--oly-font-family);
  font-size: var(--oly-font-size-2xs);
  text-align: left;
  color: var(--oly-text-secondary);
  background: transparent;
  border: none; border-radius: var(--oly-radius-xs);
  cursor: pointer;
  transition: background var(--oly-motion-duration-fast) var(--oly-motion-ease-productive),
              color var(--oly-motion-duration-fast) var(--oly-motion-ease-productive);
}
.menu-opcion:hover {
  background: var(--oly-selection-hover-surface);
  color: var(--oly-text-on-primary-subtle);
}
.menu-rama > .menu-opcion {
  font-weight: var(--oly-font-weight-semibold);
  color: var(--oly-text-primary);
}

/* El nombre cede antes que el código: `min-width: 0` es lo que permite que
   un hijo flex se encoja por debajo de su contenido, y sin él "Mantenimiento
   de Bienes y Servicios por Cuenta" empujaba la lista a lo ancho y sacaba
   una barra de scroll horizontal dentro del desplegable.

   🔴 PERO NO SE RECORTA CON PUNTOS SUSPENSIVOS. Lo cazó el usuario el
   03/09/2026: `CTREGC25`, `CTREGC26` y `CTREGC27` se llaman «Genera Archivo
   Mensual Compras IGV 18%», «... 19%» y «... 10%», y con la elipsis los tres
   quedaban en «Genera Archivo Mensual Compras IGV 1…» -- TRES ENTRADAS
   IDÉNTICAS en pantalla, donde lo único que las distingue es justo el
   porcentaje que se comía el recorte. Elegir una era adivinar.

   Se deja envolver a dos renglones en vez de cortar. El `min-width: 0` se
   queda: sigue siendo lo que impide la barra de scroll horizontal dentro
   del desplegable. */
.menu-opcion > .menu-opcion-nombre {
  flex: 1 1 auto; min-width: 0;
  white-space: normal; overflow-wrap: anywhere;
}
.menu-flecha { flex: none; color: var(--oly-icon-muted); font-size: var(--oly-font-size-xs); }

/* El código de programa va visible porque es como se nombran las
   pantallas entre contadores: "entrá al 09". */
.menu-opcion-codigo {
  flex: none;
  font-size: var(--oly-font-size-3xs);
  font-variant-numeric: tabular-nums;
  color: var(--oly-text-tertiary);
  background: var(--oly-surface-subtle);
  border-radius: var(--oly-radius-full);
  padding: 0 var(--oly-space-2);
  line-height: var(--oly-line-height-xs);
}

/* Lo que YA está construido se distingue de lo que sólo está
   inventariado. Es la diferencia entre una demo honesta y una que promete
   de más: de 354 opciones hay una sola construida y se ve cuál. */
/* 🔴 Y «construida» NO ES «igual a CONCAR». Son dos colores, no uno.

   Lo cazó el usuario el 03/09/2026 en `CTLIBR81`: la opción salía en verde
   con su `LISTO` y la pantalla tenía un desplegable de mes y un botón
   `Emitir` donde CONCAR tiene caja de texto MM, combo de moneda, casilla y
   un marco `Orden` con seis radios. El verde prometía una comparación que
   nadie había hecho.

     VERDE  `LISTO`    -- comparada contra una captura de CONCAR y coincide
     ÁMBAR  `PARCIAL`  -- funciona, pero todavía no coincide o no se comparó

   La clase la pone `menu.js`, y la de ámbar es la que sale por omisión. */
.menu-lista-construido .menu-opcion-nombre { font-weight: var(--oly-font-weight-semibold); }
.menu-lista-construido::after {
  flex: none;
  font-size: var(--oly-font-size-3xs);
  font-weight: var(--oly-font-weight-bold);
  letter-spacing: .06em; text-transform: uppercase;
  border-radius: var(--oly-radius-full);
  padding: 0 var(--oly-space-2);
  line-height: var(--oly-line-height-xs);
}

.menu-opcion-medida .menu-opcion-nombre { color: var(--oly-status-success-strong); }
.menu-opcion-medida .menu-opcion-codigo {
  color: var(--oly-status-success-strong);
  background: var(--oly-status-success-subtle);
}
.menu-opcion-medida::after {
  content: "listo";
  color: var(--oly-text-on-status-success);
  background: var(--oly-status-success-filled);
}

.menu-opcion-parcial .menu-opcion-nombre { color: var(--oly-status-warning-strong); }
.menu-opcion-parcial .menu-opcion-codigo {
  color: var(--oly-status-warning-strong);
  background: var(--oly-status-warning-subtle);
}
.menu-opcion-parcial::after {
  content: "parcial";
  color: var(--oly-text-on-status);
  background: var(--oly-status-warning);
}

/* ------------------------- pantalla de inicio ------------------------ */

.inicio-intro { padding: var(--oly-space-5) var(--oly-space-5) var(--oly-space-1); }
.inicio-intro p {
  margin: 0 0 var(--oly-space-4); max-width: 84ch;
  font-size: var(--oly-font-size-xs);
  color: var(--oly-text-secondary);
}
.inicio-intro strong { color: var(--oly-text-primary); }

.buscador-menu { display: flex; }
.buscador-menu input {
  flex: 1 1 auto;
  height: var(--oly-control-height-md);
  font-size: var(--oly-font-size-xs);
  border-radius: var(--oly-radius-sm);
}

.rejilla-modulos {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(310px, 1fr));
  gap: var(--oly-space-3);
  padding: var(--oly-space-4) var(--oly-space-5) var(--oly-space-5);
  align-items: start;
}

.tarjeta-modulo {
  background: var(--oly-surface);
  border: 1px solid var(--oly-border);
  border-radius: var(--oly-radius-sm);
  overflow: hidden;
  transition: border-color var(--oly-motion-duration-fast) var(--oly-motion-ease-productive),
              box-shadow var(--oly-motion-duration-fast) var(--oly-motion-ease-productive);
}
.tarjeta-modulo:hover { box-shadow: var(--oly-shadow-sm); }
.tarjeta-modulo.modulo-abierto { border-color: var(--oly-selection-border); }

.cabecera-modulo {
  display: flex; align-items: center; gap: var(--oly-space-2);
  width: 100%;
  min-height: var(--oly-menu-row-height);
  padding: var(--oly-space-3) var(--oly-space-4);
  font-family: var(--oly-font-family); text-align: left;
  background: transparent; border: none;
  cursor: pointer;
  transition: background var(--oly-motion-duration-fast) var(--oly-motion-ease-productive);
}
.cabecera-modulo:hover { background: var(--oly-surface-hover); }

.nombre-modulo {
  flex: 1;
  font-size: var(--oly-font-size-xs);
  font-weight: var(--oly-font-weight-semibold);
  color: var(--oly-text-heading);
}
.total-modulo {
  font-size: var(--oly-font-size-2xs);
  font-variant-numeric: tabular-nums;
  color: var(--oly-text-tertiary);
}
.chevron-modulo {
  color: var(--oly-icon-muted);
  font-size: var(--oly-font-size-3xs);
  transition: transform var(--oly-motion-duration-moderate) var(--oly-motion-ease-productive),
              color var(--oly-motion-duration-fast) var(--oly-motion-ease-productive);
}
.modulo-abierto .chevron-modulo {
  transform: rotate(180deg);
  color: var(--oly-action-primary);
}

.cuerpo-modulo {
  padding: 0 var(--oly-space-2) var(--oly-space-2);
  max-height: 470px; overflow-y: auto;
  border-top: 1px solid var(--oly-border-subtle);
}
/* Dentro de la tarjeta la lista NO flota: aquí el menú es contenido que se
   navega leyendo, no un desplegable que se recorre con el mouse. Las ramas
   se abren en línea, con sangría, y se quedan abiertas. Es la vista de
   inventario; la cascada flotante es la de la barra de arriba. */
.cuerpo-modulo .menu-lista {
  display: block; position: static;
  min-width: 0; max-width: none; max-height: none;
  margin: 0; padding: var(--oly-space-1) 0 0;
  background: transparent; border: none; box-shadow: none;
}
.cuerpo-modulo .menu-rama > .menu-lista {
  display: none;
  margin: var(--oly-space-1) 0 var(--oly-space-2) var(--oly-space-3);
  padding: 0 0 0 var(--oly-space-1);
  border-left: 2px solid var(--oly-border-subtle);
}
.cuerpo-modulo .menu-rama.rama-abierta > .menu-lista { display: block; }
/* Hacia abajo cuando abre en línea, hacia el costado cuando flota. */
.cuerpo-modulo .menu-rama.rama-abierta > .menu-opcion .menu-flecha {
  transform: rotate(90deg);
}
.menu-flecha {
  display: inline-block;
  transition: transform var(--oly-motion-duration-fast) var(--oly-motion-ease-productive);
}

/* ------------------------------ buscador ----------------------------- */

.resultados-busqueda { padding: var(--oly-space-1) var(--oly-space-5) var(--oly-space-5); }

.cabecera-resultados {
  padding: var(--oly-space-2) 0 var(--oly-space-3);
  font-size: var(--oly-font-size-3xs);
  letter-spacing: .06em; text-transform: uppercase;
  font-weight: var(--oly-font-weight-semibold);
  color: var(--oly-text-tertiary);
}

.resultado {
  display: flex; align-items: baseline; gap: var(--oly-space-3);
  width: 100%;
  padding: var(--oly-space-2) var(--oly-space-3);
  margin-bottom: var(--oly-space-1);
  font-family: var(--oly-font-family); text-align: left;
  background: var(--oly-surface);
  border: 1px solid var(--oly-border-subtle);
  border-radius: var(--oly-radius-xs);
  cursor: pointer;
  transition: background var(--oly-motion-duration-fast) var(--oly-motion-ease-productive),
              border-color var(--oly-motion-duration-fast) var(--oly-motion-ease-productive);
}
.resultado:hover {
  background: var(--oly-selection-hover-surface);
  border-color: var(--oly-selection-border);
}
.resultado-construido { border-color: var(--oly-status-success); }

.resultado-codigo {
  flex: none; width: 86px;
  font-size: var(--oly-font-size-2xs);
  font-weight: var(--oly-font-weight-semibold);
  font-variant-numeric: tabular-nums;
  color: var(--oly-action-primary-selected);
}
.resultado-nombre {
  flex: 1 1 auto;
  font-size: var(--oly-font-size-xs);
  color: var(--oly-text-primary);
}
.resultado-ruta {
  flex: 0 1 auto; max-width: 42%;
  font-size: var(--oly-font-size-3xs);
  color: var(--oly-text-tertiary);
  text-align: right; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.corte-resultados {
  padding: var(--oly-space-3) 0;
  font-size: var(--oly-font-size-2xs);
  color: var(--oly-text-tertiary);
  font-style: italic;
}

/* ---------------------- pantalla no construida ----------------------- */

.cuerpo-pendiente { padding: var(--oly-space-8) var(--oly-space-6); max-width: 76ch; }

.sello-pendiente {
  display: inline-block;
  font-size: var(--oly-font-size-2xs);
  font-weight: var(--oly-font-weight-semibold);
  font-variant-numeric: tabular-nums;
  letter-spacing: .04em;
  color: var(--oly-status-warning-strong);
  background: var(--oly-status-warning-subtle);
  border-radius: var(--oly-radius-full);
  padding: var(--oly-space-1) var(--oly-space-3);
}
.cuerpo-pendiente h2 {
  margin: var(--oly-space-4) 0 var(--oly-space-1);
  font-size: var(--oly-font-size-lg);
  line-height: var(--oly-line-height-lg);
  font-weight: var(--oly-font-weight-semibold);
  color: var(--oly-text-heading);
}
.ruta-pendiente {
  margin: 0 0 var(--oly-space-5);
  font-size: var(--oly-font-size-2xs);
  color: var(--oly-text-tertiary);
}

.aviso-pendiente {
  margin: 0 0 var(--oly-space-5);
  padding: var(--oly-space-4);
  font-size: var(--oly-font-size-xs);
  line-height: var(--oly-line-height-sm);
  color: var(--oly-text-secondary);
  background: var(--oly-surface-subtle);
  border: 1px solid var(--oly-border-subtle);
  border-left: var(--oly-space-1) solid var(--oly-status-warning);
  border-radius: var(--oly-radius-sm);
}
.aviso-pendiente strong { color: var(--oly-text-primary); }
/* Una opción DECIDIDA no es una pendiente, y no se pinta igual: el ámbar del
   borde izquierdo dice «esto va a llegar», y estas tres no van a llegar. Se
   usa el gris del borde normal para que se lea como una nota y no como un
   aviso de trabajo pendiente. */
.aviso-decidido { border-left-color: var(--oly-border-subtle); }

.boton-ir-compras {
  height: var(--oly-control-height-md);
  padding: 0 var(--oly-space-5);
  font-family: var(--oly-font-family);
  font-size: var(--oly-font-size-xs);
  font-weight: var(--oly-font-weight-semibold);
  color: var(--oly-text-on-action);
  background: var(--oly-action-primary);
  border: 1px solid var(--oly-action-primary);
  border-radius: var(--oly-radius-xs);
  cursor: pointer;
  transition: background var(--oly-motion-duration-fast) var(--oly-motion-ease-productive);
}
.boton-ir-compras:hover {
  background: var(--oly-action-primary-hover);
  border-color: var(--oly-action-primary-hover);
}

/* Si el árbol de menús no carga, la pantalla construida tiene que seguir
   siendo alcanzable: es lo único que hay. */
.aviso-menu {
  grid-column: 1 / -1;
  padding: var(--oly-space-4); margin-bottom: var(--oly-space-3);
  font-size: var(--oly-font-size-xs);
  color: var(--oly-status-danger-strong);
  background: var(--oly-status-danger-subtle);
  border: 1px solid var(--oly-status-danger);
  border-radius: var(--oly-radius-sm);
}

/* ------------------- la barra no cabe, y es un hecho ------------------ */
/* Los diez módulos de CONCAR más el rótulo de empresa piden 2.132px. En
   una pantalla de 1.440 faltan 702, y no alcanza ni escondiendo los diez
   contadores (467px): seguirían faltando 235.

   Así que la barra envuelve en dos filas en lugar de recortarse. Se
   descartó el scroll horizontal —una barra de menú que hay que arrastrar
   no es una barra de menú— y se descartó esconder módulos, que es
   justamente lo que esta pantalla existe para no hacer. */
.barra-menu { flex-wrap: wrap; row-gap: var(--oly-space-1); }

/* El rótulo de empresa puede ser largo ("EMPRESA 0002 - EMPRESA
   PCGE-2020"); se le pone tope y se recorta con puntos suspensivos, que
   es un recorte legible y no uno silencioso. */
.barra-menu .empresa-actual {
  max-width: 280px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Por debajo de 1.700px los contadores se van: el mismo dato está en las
   tarjetas de la pantalla de inicio, así que no se pierde nada. */
@media (max-width: 1700px) {
  .menu-cuenta { display: none; }
  .menu-titulo { padding: 0 var(--oly-space-2); }
}

@media (max-width: 780px) {
  .rejilla-modulos { grid-template-columns: 1fr; }
  .menu-lista { min-width: 240px; max-width: calc(100vw - var(--oly-space-8)); }
  .resultado { flex-wrap: wrap; }
  .resultado-ruta { max-width: 100%; text-align: left; }
}

/* =====================================================================
   PANTALLA DE LOGIN
   =====================================================================
   Réplica de la de CONCAR en lo que importa: los mismos dos campos, con
   «Password» en inglés porque así lo rotula el original, los mismos dos
   botones y las mismas teclas rápidas. Lo que no se copia es la marca de
   Real Systems, que es suya.

   El ancho es fijo y chico a propósito: la de CONCAR es una ventana
   pequeña centrada, no una portada a pantalla completa.
   ===================================================================== */

.pantalla-login {
  position: fixed; inset: 0; z-index: 100;
  display: grid; place-items: center;
  padding: var(--oly-space-4);
  background: var(--oly-surface-subtle);
  overflow-y: auto;
}

.tarjeta-login {
  width: 100%; max-width: 396px;
  background: var(--oly-surface);
  border: 1px solid var(--oly-border);
  border-radius: var(--oly-radius-md);
  box-shadow: var(--oly-shadow-lg);
  overflow: hidden;
}

.cabecera-login {
  padding: var(--oly-space-6) var(--oly-space-6) var(--oly-space-5);
  border-bottom: 1px solid var(--oly-border-subtle);
}

.marca-login { display: flex; align-items: baseline; gap: var(--oly-space-2); }
.marca-nombre {
  font-size: var(--oly-font-size-lg);
  line-height: var(--oly-line-height-lg);
  font-weight: var(--oly-font-weight-bold);
  letter-spacing: -.015em;
  color: var(--oly-text-heading);
}
.marca-sufijo {
  font-size: var(--oly-font-size-2xs);
  font-weight: var(--oly-font-weight-semibold);
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--oly-text-on-primary-subtle);
  background: var(--oly-action-primary-subtle);
  border-radius: var(--oly-radius-full);
  padding: 2px var(--oly-space-2);
}
.marca-bajada {
  margin: var(--oly-space-1) 0 0;
  font-size: var(--oly-font-size-2xs);
  color: var(--oly-text-tertiary);
}

.cuerpo-login { padding: var(--oly-space-6); }

/* La etiqueta a la izquierda y el campo a la derecha, como el original.
   El ancho fijo de la etiqueta es lo que alinea los dos campos entre sí. */
.fila-login {
  display: flex; align-items: center; gap: var(--oly-space-3);
  margin-bottom: var(--oly-space-4);
}
.fila-login:last-child { margin-bottom: 0; }
.fila-login label {
  flex: none; width: 84px;
  text-align: right;
  font-size: var(--oly-font-size-xs);
  font-weight: var(--oly-font-weight-medium);
  color: var(--oly-field-label);
}
.fila-login input {
  flex: 1 1 auto; min-width: 0;
  height: var(--oly-control-height-md);
  padding: 0 var(--oly-space-3);
  font-family: var(--oly-font-family);
  font-size: var(--oly-font-size-xs);
  color: var(--oly-field-text);
  background: var(--oly-surface);
  border: 1px solid var(--oly-border-strong);
  border-radius: var(--oly-radius-xs);
  outline: none;
  transition: border-color var(--oly-motion-duration-fast) var(--oly-motion-ease-productive),
              box-shadow var(--oly-motion-duration-fast) var(--oly-motion-ease-productive);
}
.fila-login input:hover { border-color: var(--oly-field-border-hover); }
.fila-login input:focus {
  border-color: var(--oly-field-border-focus);
  box-shadow: 0 0 0 3px var(--oly-selection-ring);
}

/* El mensaje del servidor, tal cual. Misma regla que la barra de error del
   CTMOVI09: el usuario ve lo que pasó, no un texto genérico. */
.error-login {
  margin: var(--oly-space-4) 0 0;
  padding: var(--oly-space-3);
  font-size: var(--oly-font-size-2xs);
  line-height: var(--oly-line-height-sm);
  color: var(--oly-status-danger-strong);
  background: var(--oly-status-danger-subtle);
  border: 1px solid var(--oly-status-danger);
  border-radius: var(--oly-radius-xs);
}

.pie-login {
  display: flex; align-items: center; gap: var(--oly-space-3);
  flex-wrap: wrap;
  padding: var(--oly-space-4) var(--oly-space-6);
  background: var(--oly-surface-subtle);
  border-top: 1px solid var(--oly-border-subtle);
}
.aviso-login {
  flex: 1 1 140px; margin: 0;
  font-size: var(--oly-font-size-3xs);
  line-height: var(--oly-line-height-2xs);
  color: var(--oly-text-tertiary);
}

.botones-login { display: flex; gap: var(--oly-space-2); }
.botones-login button {
  height: var(--oly-control-height-sm);
  padding: 0 var(--oly-space-4);
  font-family: var(--oly-font-family);
  font-size: var(--oly-font-size-2xs);
  font-weight: var(--oly-font-weight-semibold);
  color: var(--oly-text-primary);
  background: var(--oly-surface);
  border: 1px solid var(--oly-border-strong);
  border-radius: var(--oly-radius-xs);
  cursor: pointer;
  transition: background var(--oly-motion-duration-fast) var(--oly-motion-ease-productive);
}
.botones-login button:hover { background: var(--oly-surface-hover); }
.botones-login button:first-child {
  color: var(--oly-text-on-action);
  background: var(--oly-action-primary);
  border-color: var(--oly-action-primary);
}
.botones-login button:first-child:hover {
  background: var(--oly-action-primary-hover);
  border-color: var(--oly-action-primary-hover);
}
.botones-login button:disabled { opacity: .6; cursor: progress; }
.botones-login u { text-underline-offset: 2px; }

/* Cerrar sesión, en la barra de menú. */
.boton-cerrar-sesion {
  flex: none; margin-left: var(--oly-space-2);
  height: var(--oly-control-height-sm);
  padding: 0 var(--oly-space-3);
  font-family: var(--oly-font-family);
  font-size: var(--oly-font-size-2xs);
  font-weight: var(--oly-font-weight-medium);
  color: var(--oly-text-secondary);
  background: transparent;
  border: 1px solid var(--oly-border);
  border-radius: var(--oly-radius-xs);
  cursor: pointer;
  transition: background var(--oly-motion-duration-fast) var(--oly-motion-ease-productive),
              color var(--oly-motion-duration-fast) var(--oly-motion-ease-productive);
}
.boton-cerrar-sesion:hover {
  background: var(--oly-status-danger-subtle);
  color: var(--oly-status-danger-strong);
  border-color: var(--oly-status-danger);
}

/* Usuario y Password quedan en sólo lectura tras el primer Aceptar: ya
   cumplieron, y así quedan excluidos de la validación nativa —que si no
   bloquea el segundo envío por el `required` de una clave ya borrada—. Se
   ven apagados para que se entienda que ese paso está hecho. */
.fila-login input[readonly] {
  color: var(--oly-text-disabled);
  background: var(--oly-field-surface-filled);
  border-color: var(--oly-border);
  cursor: default;
}
.fila-login input[readonly]:focus { box-shadow: none; border-color: var(--oly-border); }

/* =====================================================================
   PANTALLAS DE MAESTROS (B2)
   =====================================================================
   Las cuatro comparten esta rejilla porque en CONCAR también son la misma
   con distinto contenido. Densa a propósito: el plan de cuentas real de
   una empresa llega a 4.860 filas y se recorre leyendo, no admirando.
   ===================================================================== */

.filtros-maestro {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--oly-space-3);
  padding: var(--oly-space-3) var(--oly-space-5);
  border-bottom: 1px solid var(--oly-border-subtle);
}
.filtros-maestro label {
  font-size: var(--oly-font-size-2xs);
  font-weight: var(--oly-font-weight-medium);
  color: var(--oly-text-secondary);
}
.filtros-maestro input[type="search"] { flex: 1 1 240px; max-width: 380px; }
.filtros-maestro select { flex: 0 1 300px; }

/* El conteo es de la CONSULTA, no de la página: «61 filas» dice algo. */
.conteo-maestro {
  margin-left: auto;
  font-size: var(--oly-font-size-2xs);
  font-variant-numeric: tabular-nums;
  color: var(--oly-text-tertiary);
}

.scroll-maestro {
  overflow: auto;
  max-height: calc(100vh - 260px);
  border-bottom: 1px solid var(--oly-border-subtle);
}

.grilla-maestro {
  width: 100%;
  border-collapse: separate; border-spacing: 0;
  font-size: var(--oly-font-size-2xs);
}
/* 🔴 SIN `text-transform: uppercase`, Y ESTO NO ES ESTILO: ES EL ROTULO.
   Hasta el 08/09/2026 esta regla convertia en MAYUSCULAS la cabecera de TODAS
   las rejillas de la replica. El marcado decia `Sec.`, `Cuenta`, `Subdiario`
   --las cadenas medidas-- y la pantalla ensenaba `SEC.`, `CUENTA`,
   `SUBDIARIO`. Medido en el navegador a 1440x900 en `CTMOVI09`: 33 `th`, los
   33 en `uppercase`, y 26 de ellos con un texto que CAMBIA al aplicarla.

   Y CONCAR escribe minusculas, medido en DOS programas distintos --que es la
   regla de «una pantalla no es el sistema»--:

     `ctmovi09-0002-detalle-090001-cuadrado.png` .. Sec. Cuenta Anexo Cos. F
                                                   Importe TP Docmto Fec.Doc.
                                                   Fec.Ven. Area
     `ctmovi02-0002-situacion.png` ................ Subdiario Comprobante Fecha
                                                   Mon Total Glosa Conv Situa Img

   Es la capa PANTALLA, que se copia al pie de la letra, y ademas es la clase
   de defecto que un arnes estatico NO VE: `las-once-columnas-del-detalle.mjs`
   lee el HTML y estaba en verde con la pantalla ensenando otra cosa. Lo caza
   `los-rotulos-no-se-gritan.mjs`, que cuenta los selectores con esta
   propiedad y solo admite los que NO son rotulos de CONCAR.
   Ver DIFERENCIAS §171. */
.grilla-maestro th {
  position: sticky; top: 0; z-index: 2;
  padding: var(--oly-space-2) var(--oly-space-3);
  text-align: left; white-space: nowrap;
  font-size: var(--oly-font-size-3xs);
  font-weight: var(--oly-font-weight-semibold);
  letter-spacing: .06em;
  color: var(--oly-text-tertiary);
  background: var(--oly-surface-subtle);
  border-bottom: 1px solid var(--oly-border);
}
.grilla-maestro td {
  padding: var(--oly-space-2) var(--oly-space-3);
  border-bottom: 1px solid var(--oly-border-subtle);
  vertical-align: top;
  /* El espaciado interior del texto ES dato, no formato.
     Los campos de CONCAR son de ancho fijo y hay descripciones con espacios
     dobles: la cuenta 103 se llama "EFECTIVO Y CHEQUES EN  TRANSITO", con dos.
     El HTML los colapsa, así que en pantalla salía con uno y no coincidía
     carácter por carácter con la pantalla original.

     `pre-wrap` y no `pre`: conserva los espacios y deja que las descripciones
     largas sigan cortando de línea. */
  white-space: pre-wrap;
}
.grilla-maestro tbody tr:nth-child(even) { background: var(--oly-surface-subtle); }
.grilla-maestro tbody tr:hover { background: var(--oly-selection-hover-surface); }

/* Los códigos alinean por dígito o no se pueden comparar de un vistazo. */
.grilla-maestro .col-codigo {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  font-weight: var(--oly-font-weight-medium);
}
.grilla-maestro .col-corta { white-space: nowrap; text-align: center; width: 1%; }
.grilla-maestro .col-mes {
  font-variant-numeric: tabular-nums;
  text-align: right; white-space: nowrap; width: 1%;
}
/* Lo que él va a mirar primero: la contrapartida automática y qué exige. */
.grilla-maestro .col-genera {
  font-variant-numeric: tabular-nums; white-space: nowrap;
  color: var(--oly-action-primary-selected);
}
.grilla-maestro .col-exige {
  color: var(--oly-text-secondary);
  font-size: var(--oly-font-size-3xs);
}

/* 4.149 anexos tienen un RUC que no son 11 dígitos, uno dice `DIEGO`. Se
   marca en vez de esconderlo: es dato histórico real y su saneamiento está
   por decidir con contabilidad. */
.grilla-maestro .dato-sospechoso {
  color: var(--oly-status-warning-strong);
  background: var(--oly-status-warning-subtle);
}

.grilla-maestro .fila-vacia td {
  padding: var(--oly-space-8);
  text-align: center; font-style: italic;
  color: var(--oly-text-tertiary);
  background: transparent;
}

.paginas-maestro { margin-left: auto; display: flex; align-items: center; gap: var(--oly-space-2); }
.num-pagina { font-variant-numeric: tabular-nums; }
.boton-pagina {
  min-width: 26px; height: 22px;
  font-family: var(--oly-font-family); font-size: var(--oly-font-size-2xs);
  color: var(--oly-text-secondary);
  background: var(--oly-surface);
  border: 1px solid var(--oly-border);
  border-radius: var(--oly-radius-xs);
  cursor: pointer;
}
.boton-pagina:hover:not(:disabled) { background: var(--oly-surface-hover); }
.boton-pagina:disabled { opacity: .4; cursor: default; }


/* La segunda línea del título en las pantallas que la tienen. CONCAR la
   centra sobre la grilla, así que aquí también. */
.subtitulo-maestro {
  margin: 0 0 var(--oly-space-2);
  text-align: center;
  font-size: var(--oly-font-size-sm);
  color: var(--oly-text-secondary);
}


/* La regla de posiciones que CONCAR pinta bajo el contenido de una tabla
   general. Sólo sirve si es monoespaciada: es para contar caracteres. */
.regla-ancho-fijo {
  font-family: ui-monospace, "Cascadia Mono", Consolas, "Liberation Mono", monospace;
  letter-spacing: 0;
  color: var(--oly-text-secondary);
}

/* La palabra de modo del título. En CONCAR va suelta al lado del nombre de
   la ventana, no dentro de él. */
.modo-ventana {
  margin-left: var(--oly-space-3);
  font-size: var(--oly-font-size-sm);
  color: var(--oly-text-secondary);
}

/* El hueco de los avisos, al lado del pie y sin robarle el sitio. */
.aviso-maestro {
  font-size: var(--oly-font-size-sm);
  color: var(--oly-text-secondary);
  margin-left: var(--oly-space-3);
}

/* Una fila que se abre tiene que parecerlo. */
.grilla-maestro tbody tr.fila-abrible { cursor: pointer; }


/* ===================== LA BARRA DE BOTONES ==========================
   CONCAR la pone debajo de la grilla, pegada a la derecha, con los botones
   juntos y un separador antes de Salir. Se replica la disposición; el aspecto
   es el nuestro, que es lo único que el encargo deja cambiar. */
.barra-botones {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 2px;
  padding: var(--oly-space-2) var(--oly-space-3);
  border-top: 1px solid var(--oly-border-subtle);
}

.boton-maestro {
  min-width: 30px;
  height: 28px;
  padding: 0 var(--oly-space-2);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  color: var(--oly-text-primary);
  background: var(--oly-surface);
  border: 1px solid var(--oly-border);
  border-radius: var(--oly-radius-sm);
}
.boton-maestro:hover:not(:disabled) { background: var(--oly-selection-hover-surface); }

/* El dibujo del botón. `currentColor` hace que el trazo siga al color del
   texto, así que el estado deshabilitado se apaga solo con el `opacity` de
   abajo y no hace falta una regla aparte.
   Los iconos son Iconoir, del mismo diseño del que salen estos tokens
   (@imperiumtechai/olympium-ui). Ver frontend/iconos-olympium.svg. */
.icono-boton {
  display: block;
  width: 16px;
  height: 16px;
  margin: 0 auto;
  color: currentColor;
  pointer-events: none;
}

/* Los que escriben van deshabilitados y TIENEN QUE PARECERLO. Un botón que se
   ve activo y no hace nada es peor que uno que se ve apagado: el segundo dice
   la verdad. El motivo va en su `title`. */
.boton-maestro:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* El hueco que CONCAR deja antes de Salir. */
.separador-botones {
  width: var(--oly-space-4);
}


/* ===================== LA FRANJA DE EDICIÓN =========================
   CONCAR pone los campos debajo de la grilla, no en una ventana aparte.

   🔴 REESCRITA EL 10/09/2026. Era `display:flex; flex-wrap:wrap` y los campos
   se partían por donde cayera el ancho: en `CTNUME01` el aviso de compañía
   quedaba entre dos rótulos, `Descripción` terminaba en un renglón y su caja
   en el siguiente, y `Cerrar` salía pegado a una caja como si fuera parte del
   campo. El usuario lo puso al lado de su CONCAR: «todo el footer está
   horrible».

   Lo que hace CONCAR, medido en las dos capturas de `CTNUME01` que mandó ese
   día (modo `Modificación` y modo `Consulta`) y confirmado en la ficha de
   `CTANEX01`:

     · es un `Frame` de VB6: un recuadro de una línea con el RÓTULO ENCAJADO
       en el borde de arriba a la izquierda, y el rótulo dice `Consulta`,
       `Modificación` o `Creación` según lo que se pulsó;
     · los campos van en DOS COLUMNAS y UNO POR RENGLÓN -- `Subdiario`, `Año`,
       `Mes`, `Ult. Comprobante`, `Ult. Comprob. Real`, cada uno con su rótulo
       a la izquierda;
     · las cajas NO se estiran: la de `Año` mide dos dígitos y ahí se queda.
   ==================================================================== */
.franja-edicion {
  padding: var(--oly-space-3);
  border-top: 1px solid var(--oly-border);
  background: var(--oly-surface-subtle);
}
/* El recuadro con el rótulo dentro del borde. */
.marco-ficha {
  border: 1px solid var(--oly-border);
  border-radius: 2px;
  padding: var(--oly-space-3);
  margin: 0;
  min-width: 0;
}
/* El rótulo que cambia con la acción. Es una `<legend>`, así que el navegador
   ya la encaja en el borde: no hace falta posicionarla a mano. */
.marco-ficha > legend.titulo-franja {
  padding: 0 var(--oly-space-2);
  font-weight: 600;
  font-size: var(--oly-font-size-sm);
  color: var(--oly-text-secondary);
}
/* Rótulo | caja. `max-content` en la primera para que todos los rótulos de la
   misma pestaña se alineen entre sí, y `1fr` en la segunda para que las cajas
   arranquen todas en la misma columna --que es lo que hace el `Frame`--
   aunque cada una conserve su propio ancho. */
.rejilla-ficha {
  display: grid;
  grid-template-columns: max-content 1fr;
  align-items: center;
  gap: var(--oly-space-2) var(--oly-space-3);
}
.rejilla-ficha > label {
  justify-self: start;
  font-size: var(--oly-font-size-xs);
  color: var(--oly-text-secondary);
}
/* La caja y su nota azul comparten celda: si la nota fuera una tercera
   columna, los renglones que no la tienen desalinearían todo lo demás. */
.celda-ficha {
  display: flex;
  align-items: center;
  gap: var(--oly-space-2);
  min-width: 0;
}
/* Los botones al pie del marco, en su renglón, a la derecha. */
.pie-ficha {
  display: flex;
  justify-content: flex-end;
  gap: var(--oly-space-2);
  margin-top: var(--oly-space-3);
}
/* En qué compañía se escribe: su propio renglón, arriba del todo. */
.marco-ficha > .donde-escribe {
  display: block;
  margin: 0 0 var(--oly-space-2);
  padding: 2px 0;
  border-right: 0;
}

/* Las pestañas de la ficha -- `CTANEX01` tiene cuatro. Se dibujan como las de
   CONCAR: solapas pegadas al borde de arriba del panel, la elegida en blanco
   y sin línea inferior, las demás hundidas. */
.pestanas-ficha {
  display: flex;
  gap: 2px;
  margin-bottom: -1px;
}
.pestana-ficha {
  padding: 4px var(--oly-space-3);
  font-size: var(--oly-font-size-xs);
  color: var(--oly-text-secondary);
  background: var(--oly-surface-subtle);
  border: 1px solid var(--oly-border);
  border-bottom-color: var(--oly-border);
  border-radius: 3px 3px 0 0;
  cursor: pointer;
}
.pestana-ficha.elegida {
  color: var(--oly-text-primary);
  font-weight: 600;
  background: var(--oly-surface);
  border-bottom-color: var(--oly-surface);
}
.panel-ficha {
  border: 1px solid var(--oly-border);
  border-radius: 0 3px 3px 3px;
  padding: var(--oly-space-3);
  background: var(--oly-surface);
}
/* Un marco CON rótulo dentro de una pestaña: `AFP Independiente`. */
.marco-campos {
  border: 1px solid var(--oly-border-subtle);
  border-radius: 2px;
  margin: var(--oly-space-3) 0 0;
  padding: var(--oly-space-2) var(--oly-space-3) var(--oly-space-3);
  min-width: 0;
}
.marco-campos > legend {
  padding: 0 var(--oly-space-2);
  font-size: var(--oly-font-size-xs);
  color: var(--oly-text-secondary);
}

.franja-edicion input {
  padding: 4px 6px;
  border: 1px solid var(--oly-border);
  border-radius: var(--oly-radius-sm);
  background: var(--oly-surface);
  color: var(--oly-text-primary);
}
/* La clave bloqueada al modificar tiene que PARECERLO. */
.franja-edicion input[readonly] {
  background: var(--oly-surface-subtle);
  color: var(--oly-text-secondary);
}
.boton-guardar {
  padding: 5px var(--oly-space-3);
  cursor: pointer;
  color: var(--oly-text-on-accent, #fff);
  background: var(--oly-accent);
  border: 1px solid var(--oly-accent);
  border-radius: var(--oly-radius-sm);
}

/* La fila elegida. En CONCAR lleva un triangulito a la izquierda; aquí se
   resuelve con el fondo, que es lo que el encargo deja cambiar. */
.grilla-maestro tbody tr.fila-elegida,
.grilla-maestro tbody tr.fila-elegida:nth-child(even) {
  background: var(--oly-selection-surface, var(--oly-selection-hover-surface));
  outline: 1px solid var(--oly-accent);
  outline-offset: -1px;
}
.grilla-maestro tbody tr { cursor: default; }

/* =====================================================================
   `.grilla-concar` — LA GRILLA DE CONCAR, UNA SOLA VEZ

   Es un MODIFICADOR de `.grilla-maestro`, no otra tabla: se escribe
   `class="grilla-maestro grilla-concar"`. El patrón no es nuevo — es el
   mismo con el que `.grilla-situacion` extiende la base desde el principio.

   🔴 POR QUÉ EXISTE. Hasta el 04/09/2026 había CINCO clases de grilla en
   este archivo, y tres de ellas —`.grilla-honp`, `.grilla-comp` y
   `.grilla-regc22`— eran la MISMA regla copiada. Ya se habían separado, y
   la separación se puede medir:

     · `.grilla-honp` llevaba borde en la tabla; las otras dos, no.
     · `.grilla-regc22` tenía `position: sticky` en el `th`; las otras dos, no.
     · `.grilla-comp` definía su fila elegida 150 líneas más abajo que su
       propia tabla, y sin el `cursor: pointer` que las otras dos sí tenían.
     · Y la clase de la fila marcada se llamaba `elegida` en las tres y
       `fila-elegida` en la base — dos nombres para la misma cosa.

   Ninguna de esas cuatro diferencias fue una decisión: son el desgaste de
   tener el mismo dibujo en tres sitios. Es la sexta vez esta semana que
   este repositorio topa con la misma forma de defecto (§59, §60, §64, §65,
   §67), y se cierra igual: un solo sitio, y una comprobación de que no
   puede haber dos —`herramientas/grillas.mjs`—.

   QUÉ AÑADE A LA BASE, Y POR QUÉ CADA COSA
   ----------------------------------------
   Sólo lo que está MEDIDO de las grillas de CONCAR y la base no tiene:

     · la columna del selector, sin encabezado, donde va el ▶;
     · la fila actual INVERTIDA —fondo pleno y texto claro—, que es como se
       ve en `demo15-03`, y no el realce suave de la base;
     · el cursor de mano, porque en estas pantallas el clic elige fila.

   Lo demás —tipografía, relleno, cebra, encabezado— viene de la base a
   propósito: es la piel de la réplica, y tenerla distinta en tres pantallas
   era justo lo que se veía mal.
   ===================================================================== */
.grilla-concar tbody tr { cursor: pointer; }

/* La columna del triangulito. En CONCAR no tiene encabezado y el glifo lo
   pone `fila-actual.js`, que es el único sitio donde se dibuja (§60). */
.grilla-concar .marca {
  width: 18px;
  padding-right: 0;
  text-align: center;
  color: var(--oly-text-secondary);
}

/* La fila actual. Invertida, no realzada: `demo15-03` la enseña en negro
   pleno con el texto en claro. */
.grilla-concar tbody tr.elegida,
.grilla-concar tbody tr.elegida:nth-child(even) {
  color: var(--oly-selection-text, #fff);
  background: var(--oly-selection-surface, #0a64c8);
}
.grilla-concar tbody tr.elegida .marca,
.grilla-concar tbody tr.elegida .dato-sospechoso { color: inherit; }
.grilla-concar tbody tr.elegida:hover {
  background: var(--oly-selection-surface, #0a64c8);
}

/* =====================================================================
   LA CELDA ACTUAL — el apartamiento que pidió el usuario (DIFERENCIAS §245)
   =====================================================================
   La marca de FILA de arriba no se toca: ésta va DENTRO y es más fina, para
   que un contador pueda pararse en un importe y copiarlo, que es lo que
   pidió. El recuadro no es un color de relleno: es un borde, para que el
   dato siga leyéndose igual --invertir la celda encima de una fila ya
   invertida deja el número ilegible-- y para que se distinga de la marca de
   fila, que sí es relleno. */
.grilla-concar td.celda-actual {
  outline: 2px solid var(--oly-selection-surface, #0a64c8);
  outline-offset: -2px;
  /* Sin esto el navegador dibuja ADEMAS su propio anillo de foco encima. */
  box-shadow: none;
}
.grilla-concar tbody tr.elegida td.celda-actual {
  /* Sobre la fila invertida el azul no se ve: se recorta en claro. */
  outline-color: var(--oly-selection-text, #fff);
}
/* El parpadeo de «copiado». 320 ms, que es lo que dura el `setTimeout` de
   `celda-actual.js`; no hace falta un aviso de texto que tape la grilla. */
.grilla-concar td.celda-copiada {
  background: var(--oly-exito-suave, #d8f5e3);
  transition: background 120ms ease-out;
}
@media (prefers-reduced-motion: reduce) {
  .grilla-concar td.celda-copiada { transition: none; }
}
/* Y la celda enfocada NO lleva el anillo del navegador: ya tiene el suyo. */
.grilla-concar td:focus { outline: none; }
.grilla-concar td.celda-actual:focus {
  outline: 2px solid var(--oly-selection-surface, #0a64c8);
  outline-offset: -2px;
}
.grilla-concar tbody tr.elegida td.celda-actual:focus {
  outline-color: var(--oly-selection-text, #fff);
}

/* Las cifras alinean a la derecha o no se pueden comparar de un vistazo. */
.grilla-concar .cifra { text-align: right; font-variant-numeric: tabular-nums; }


/* En qué compañía se va a escribir. Va DENTRO de la franja de edición, donde
   no se puede no verlo: el fallo del 02/09/2026 no fue que faltara una
   comprobación, fue que nadie lo decía. */
.donde-escribe {
  padding: 2px var(--oly-space-2);
  font-weight: 600;
  font-size: var(--oly-font-size-sm);
  color: var(--oly-text-secondary);
  border-right: 1px solid var(--oly-border);
  margin-right: var(--oly-space-2);
}
/* Cuando NO es la 0002 se ve distinto. Las otras 26 espejan CONCAR: una fila
   de más en ellas es una diferencia con el original. */
.donde-escribe-ojo {
  color: var(--oly-status-danger);
  border-right-color: var(--oly-status-danger);
}

/* ---------------------------------------------------------------------------
   CTCUEN04 y CTCUEN05: el pie de la grilla y el panel de parámetros.

   CONCAR pone las dos cosas DEBAJO de la grilla: primero una línea que explica
   cómo se marca una cuenta, y después una rejilla de tres o cuatro parámetros
   con su valor en una casilla y su descripción al lado. Se replica esa forma,
   con los tokens de Olympium.
   --------------------------------------------------------------------------- */
.pie-grilla {
  margin: 4px 0 0;
  padding: 4px 8px;
  font-size: 12px;
  color: var(--oly-text-secondary, #555);
  background: var(--oly-surface-subtle, #f5f5f5);
  border: 1px solid var(--oly-border, #ddd);
}

.panel-parametros {
  display: grid;
  /* Rótulo · casilla del valor · descripción. La descripción se lleva el
     espacio sobrante, como en CONCAR. */
  grid-template-columns: auto auto 1fr;
  gap: 6px 10px;
  align-items: center;
  margin-top: 8px;
  padding: 10px 8px;
  border: 1px solid var(--oly-border, #ddd);
}

.etiqueta-parametro { font-size: 12px; }
.texto-parametro { font-size: 12px; color: var(--oly-text-secondary, #555); }

/* El par «Todas / Para Regularización». Van juntos y no se parten de línea. */
.opcion-radio {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-right: 12px;
  font-size: 12px;
  white-space: nowrap;
}

/* ==================================================================== */
/* CPPAGP01 — Medio de Pago por Programa                                */
/*                                                                      */
/* Dos paneles enfrentados, como en CONCAR: los programas a la izquierda */
/* y los medios de pago con casilla a la derecha, cada uno con su        */
/* cabecera centrada encima. Medida en FACILITA el 02/09/2026.           */
/* ==================================================================== */

.paneles-pagp {
  display: grid;
  /* En CONCAR el panel derecho es más ancho: le entra el texto largo de los
     medios de pago, que llega a «CARTA DE CREDITO DOCUMENTARIO - COMERCIO
     EXTERIOR». La proporción es la de la pantalla real. */
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: var(--oly-space-3);
  padding: var(--oly-space-3);
  align-items: start;
}

.panel-pagp { min-width: 0; }

/* CONCAR la dibuja centrada y hundida sobre cada lista. */
.cabecera-panel {
  margin: 0 0 2px;
  padding: 2px var(--oly-space-2);
  font-size: 12px;
  text-align: center;
  color: var(--oly-text-primary);
  background: var(--oly-surface-subtle);
  border: 1px solid var(--oly-border);
  border-radius: var(--oly-radius-sm);
}

.lista-pagp {
  margin: 0;
  padding: 2px;
  list-style: none;
  height: 300px;
  overflow-y: auto;
  /* La lista larga se corta como en CONCAR, sin barra horizontal. */
  overflow-x: hidden;
  background: var(--oly-surface);
  border: 1px solid var(--oly-border);
  border-radius: var(--oly-radius-sm);
}

.fila-pagp {
  padding: 1px var(--oly-space-2);
  font-size: 12px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: clip;   /* CONCAR corta en seco, sin puntos suspensivos */
}

.lista-programas .fila-pagp { cursor: pointer; }
.lista-programas .fila-pagp:hover { background: var(--oly-selection-hover-surface); }
.lista-programas .fila-pagp.elegida {
  color: var(--oly-selection-text, #fff);
  background: var(--oly-selection-surface, #0a64c8);
}

/* Ni `table` ni columnas alineadas: CONCAR pone código y descripción como
   texto corrido con relleno, y por eso la descripción de CTCHEQ01 arranca un
   carácter más a la derecha. Se copia, no se arregla. */
/* Los digitos, de ancho fijo: si no, `CTMOVI01` y `CTMOVI03` --que en CONCAR
   alinean-- salen corridos uno respecto del otro. El relleno entre el codigo y
   la descripcion lo manda el servidor, que es donde esta medido. */
.codigo-programa,
.codigo-medio { font-variant-numeric: tabular-nums; }
.codigo-medio::after { content: "\00a0\00a0\00a0\00a0"; }

.casilla-medio {
  display: flex;
  align-items: center;
  gap: 0;
  cursor: pointer;
}
.casilla-medio input[type="checkbox"] {
  margin: 0 var(--oly-space-2) 0 0;
  flex: none;
}

/* La barra de abajo: una franja hundida y ancha, y los dos botones a la
   derecha. En CONCAR la franja está vacía; acá dice qué pasó al grabar. */
.barra-pagp {
  display: flex;
  align-items: stretch;
  gap: var(--oly-space-2);
  padding: var(--oly-space-2) var(--oly-space-3);
  border-top: 1px solid var(--oly-border-subtle);
}
.franja-pagp {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  padding: 0 var(--oly-space-2);
  font-size: 12px;
  color: var(--oly-text-secondary, var(--oly-text-primary));
  background: var(--oly-surface-subtle);
  border: 1px solid var(--oly-border);
  border-radius: var(--oly-radius-sm);
}
.franja-pagp.aviso-mal { color: var(--oly-text-danger, #b42318); }
.barra-pagp .barra-botones { border-top: none; padding: 0; }

/* ==================================================================== */
/* CTHONP01 — Parámetros de Registro de Honorarios                      */
/*                                                                      */
/* Seis pestañas, dos formas de contenido y TRES RECETAS de barra en DOS  */
/* SITIOS. Acá decía «TRES barras de botones» y manda a buscar en la     */
/* pantalla un tercer sitio que no existe: los sitios son dos --el pie de */
/* la ventana y el marco Creación-- y lo que hay tres son las recetas de  */
/* contenido (`S`, `C M E G`, `M G`). `PANTALLAS-MEDIDAS.md` y            */
/* `botones-maestro.js` ya decían «dos barras». Corregido el 10/09/2026;  */
/* ver DIFERENCIAS §218 punto 4.                                          */
/* Medida en FACILITA el 02/09/2026, ampliando al 150 % y al 500 %.     */
/*                                                                      */
/* Lo que esta hoja copia y no decide:                                  */
/*   · las etiquetas de la ficha van VERTICALES, una por línea, no en   */
/*     línea como las de CTTABL01 -- de ahí la rejilla de dos columnas; */
/*   · los rótulos de aportaciones y de tasas van EN AZUL, que es una   */
/*     convención de CONCAR en esta pantalla;                           */
/*   · la Clave se ve hundida y gris en las cuatro fichas de grilla.    */
/* ==================================================================== */

.pestanas-honp {
  display: flex;
  gap: 2px;
  padding: var(--oly-space-3) var(--oly-space-3) 0;
  border-bottom: 1px solid var(--oly-border);
}

/* Azul, como las de CONCAR; la elegida en negrita y con el fondo del cuerpo,
   que es lo que le da el aire de pestaña delantera. */
.pestana-honp {
  padding: 3px var(--oly-space-3);
  font: inherit;
  font-size: 12px;
  color: var(--oly-link, #1a3f9c);
  cursor: pointer;
  background: var(--oly-surface-subtle);
  border: 1px solid var(--oly-border);
  border-bottom: none;
  border-radius: var(--oly-radius-sm) var(--oly-radius-sm) 0 0;
}
.pestana-honp:hover { background: var(--oly-selection-hover-surface); }
.pestana-honp.elegida {
  font-weight: 700;
  background: var(--oly-surface);
  /* Tapa la línea de la tira: la pestaña elegida se une al cuerpo. */
  margin-bottom: -1px;
  padding-bottom: 4px;
}

/* EL CUERPO SE ACOTA Y SE DESPLAZA POR DENTRO, y no es una decisión estética.
   «Parámetros Varios» mide 893 px con sus cuatro grupos, así que con la
   ventana a 900 la barra del pie -- la que lleva `Salir` -- caía en 940, ENTERA
   BAJO EL PLIEGUE. Es el mismo defecto que ya se cazó una vez: un botón que
   parece no hacer nada porque no se ve.

   En CONCAR no pasa porque sus controles son más apretados y todo entra en los
   522 px de la ventana, con la puerta roja siempre a la vista. Acotar el cuerpo
   conserva ESO, que es lo que importa: la barra no se mueve nunca. */
.cuerpo-honp {
  padding: var(--oly-space-3);
  /* 265 px es lo que ocupan la barra de menú, el título de la ventana, la
     tira de pestañas y la propia barra del pie, medido a 1440x900: con 230 la
     barra terminaba en 910 y seguía 10 px fuera. */
  max-height: calc(100vh - 265px);
  overflow-y: auto;
}
.ficha-honp,
.grupo-varios {
  margin: var(--oly-space-3) 0 0;
  padding: var(--oly-space-3);
  border: 1px solid var(--oly-border);
  border-radius: var(--oly-radius-sm);
}
.ficha-honp > legend,
.grupo-varios > legend {
  padding: 0 var(--oly-space-2);
  font-size: 12px;
  color: var(--oly-text-secondary);
}

/* Etiqueta a la izquierda, cajas a la derecha, una fila por campo. */
.campo-honp,
.campo-varios {
  display: grid;
  grid-template-columns: minmax(0, 260px) auto;
  gap: var(--oly-space-2);
  align-items: center;
  margin-bottom: 3px;
  font-size: 12px;
}
.campo-varios { grid-template-columns: minmax(0, 300px) auto auto auto; }
.cajas-honp { display: flex; gap: var(--oly-space-2); align-items: center; }

.caja-honp {
  width: 150px;
  padding: 1px var(--oly-space-2);
  font: inherit;
  font-size: 12px;
  color: var(--oly-text-primary);
  background: var(--oly-surface);
  border: 1px solid var(--oly-border);
}
.caja-corta { width: 90px; }
.caja-ancha { width: 340px; }
/* El desplegable de CONCAR: se dibuja la flecha, no un `select`, porque la
   pantalla es de sólo lectura y un `select` invitaría a elegir. */
.caja-lista {
  width: 170px;
  background-image: linear-gradient(45deg, transparent 50%, var(--oly-text-secondary) 50%),
                    linear-gradient(135deg, var(--oly-text-secondary) 50%, transparent 50%);
  background-position: calc(100% - 11px) 8px, calc(100% - 7px) 8px;
  background-size: 4px 4px;
  background-repeat: no-repeat;
}
/* La Clave, bloqueada y gris también en CONCAR. */
.caja-fija { color: var(--oly-text-secondary); background: var(--oly-surface-subtle); }

.rotulo-azul { font-weight: 700; color: var(--oly-link, #1a3f9c); }
.rotulo-sangrado { padding-left: var(--oly-space-5, 24px); }
.signo-honp { color: var(--oly-text-secondary); }
/* «Comisión» titula las dos filas de comisión y no tiene campo propio. */
.rotulo-suelto {
  margin: 0 0 3px;
  font-size: 12px;
  font-weight: 700;
  color: var(--oly-link, #1a3f9c);
}

.linea-varios { display: flex; flex-wrap: wrap; gap: var(--oly-space-4); }
.linea-varios .campo-varios { grid-template-columns: auto auto auto; margin-bottom: 0; }
.columnas-varios {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 260px);
  gap: var(--oly-space-4);
  align-items: start;
}
.subgrupo-varios { margin-top: var(--oly-space-2); }

.rotulo-lista { margin: 0 0 3px; font-size: 12px; }
.sistemas-honp {
  margin: 0;
  padding: 2px;
  height: 70px;
  overflow-y: auto;
  font-size: 12px;
  list-style: none;
  background: var(--oly-surface);
  border: 1px solid var(--oly-border);
}
.sistemas-honp li { padding: 1px var(--oly-space-2); white-space: nowrap; }
.codigo-sistema {
  display: inline-block;
  width: 34px;
  font-variant-numeric: tabular-nums;
}

/* LA BARRA DEL PIE DE CONCAR, UNA SOLA VEZ.
   Una franja hundida que cruza el ancho, y pegados a su derecha los botones
   de icono. La misma en CTHONP01, CTCOMP01 y CTMOVI09 -- medidas las tres.

   Estaba escrita DOS VECES, `.barra-honp-pie/.franja-honp` y
   `.barra-comp-pie/.franja-comp`, byte a byte iguales salvo el `aviso-mal`.
   Se descubrio el 04/09/2026 al ir a escribir la TERCERA para CTMOVI09. Es la
   octava vez que aparece la misma forma --dos dibujos de la misma cosa y
   nadie comparandolos-- y la respuesta es la de siempre: un solo sitio, mas
   una comprobacion de que no puedan volver a ser dos (`herramientas/barras-pie.mjs`). */
.barra-pie-concar,
.barra-panel-concar {
  display: flex;
  gap: var(--oly-space-2);
  align-items: center;
  margin-top: var(--oly-space-3);
}
.barra-pie-concar {
  margin: 0;
  padding: var(--oly-space-2) var(--oly-space-3) var(--oly-space-3);
}
.franja-pie-concar {
  flex: 1;
  min-width: 0;
  padding: 2px var(--oly-space-2);
  font-size: 12px;
  color: var(--oly-text-secondary);
  background: var(--oly-surface-subtle);
  border: 1px solid var(--oly-border);
  border-radius: var(--oly-radius-sm);
}
.franja-pie-concar.aviso-mal { color: var(--oly-text-danger, #b42318); }
.barra-pie-concar .barra-botones,
.barra-panel-concar .barra-botones { border-top: none; padding: 0; }

/* Un botón de barra que CONCAR dibuja como LETRA y no como icono: la `A` de
   `CTPBIS01`. Se le da el mismo cuadro que al `.icono-boton` para que no
   descuadre la fila de botones. */
.letra-boton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 15px;
  font-weight: 700;
  line-height: 1;
}

/* La banda del filtro de `CTPBIS01` cuando pasa a `Actualización Masiva`.
   El marco cambia de rótulo, la casilla `Todos` se va, el desplegable se
   habilita y aparece el disquete. Ver DIFERENCIAS §250. */
.banda-modo {
  display: flex;
  align-items: center;
  gap: var(--oly-space-2);
  margin-left: auto;
}
.filtros-maestro.en-masiva {
  border: 1px solid var(--oly-status-warning, #b26b00);
  border-radius: 2px;
  padding: var(--oly-space-2) var(--oly-space-3);
}
.rotulo-banda {
  font-size: var(--oly-font-size-xs);
  font-weight: 600;
  color: var(--oly-text-secondary);
  margin-right: var(--oly-space-2);
}
.filtros-maestro.en-masiva .rotulo-banda {
  color: var(--oly-status-warning, #b26b00);
}

/* La anotación azul que CONCAR pone a la derecha de un campo de la ficha.
   La primera es `(Longitud Variable)` en CTTABE01, medida el 03/09/2026. */
.nota-campo {
  color: #1a5fb4;
  font-size: 0.85rem;
  margin-right: 0.75rem;
  white-space: nowrap;
}

/* `Descripción Detallada` de CTTABE01 es un área multilínea, no una caja. */
.area-ficha {
  font-family: inherit;
  font-size: inherit;
  min-width: 24rem;
  resize: vertical;
}

/* ==================================================================== */
/* LOS CUATRO PAPELES DEL FLUJO DE COMPRAS                              */
/* CTDIAR02 · CTMAYO02 · CTCOST32 · CTLIBR81                            */
/*                                                                      */
/* Esta hoja copia una cosa y decide otra, y conviene tenerlas          */
/* separadas:                                                           */
/*                                                                      */
/* SE COPIA de las capturas del 03/09/2026 (§6 de la pasada):           */
/*   · tipografía de ancho fijo -- CONCAR emite un reporte de columnas  */
/*     alineadas, no una grilla;                                        */
/*   · las cifras a la DERECHA de su columna;                           */
/*   · los subtotales con el rótulo pegado a la cifra, a la derecha del */
/*     cuerpo, no debajo de la primera columna.                         */
/*                                                                      */
/* SE DECIDE, y no está medido al píxel:                                */
/*   · los ANCHOS exactos de cada columna. De las capturas se leyó el   */
/*     ORDEN de las columnas y qué campo va en cada una, no su ancho en */
/*     caracteres. Los de acá están puestos para que el contenido       */
/*     medido quepa sin cortarse y las cifras alineen entre renglones;  */
/*     el día que alguien mida el ancho real de `CTDIAR02`, se cambian  */
/*     estos números y nada más.                                        */
/*   · el papel tiene fondo claro y borde.                            */
/*                                                                      */
/* 🔴 Y ESTA CABECERA DECÍA UNA COSA FALSA hasta la vuelta 46: que      */
/* CONCAR «lo abre en una ventana de previsualización que no se         */
/* capturó». SÍ se capturó, y DOS veces, en este mismo repositorio --   */
/* `artifacts/rig/shots/libr81-pantalla.png` restaurada y                */
/* `libr81-vista.png` maximizada--. La ventana está medida y construida  */
/* en `#pantalla-vista-previa`. Un comentario que declara no medido algo  */
/* medido es peor que no tener el comentario: nadie vuelve a buscar.      */
/* Ver DIFERENCIAS 138.                                                  */
/*                                                                       */
/* Y HASTA LA VUELTA 47 ESTA CABECERA DECÍA que `.papel-reporte` era «el  */
/* del RESTO de los reportes, que siguen dibujando en el cuerpo». Ya no:  */
/* la ventana resultó GENÉRICA --sale de `CTLIBR81`, `CTMAYO02`,          */
/* `CTCOST32` y `CTDIAR02`, diez capturas, barra idéntica al píxel-- y    */
/* los cuatro reportes de la réplica la abren. `.papel-reporte` sigue     */
/* pintándose EN EL CUERPO a propósito: de ahí leen los arneses que        */
/* cuentan caracteres, y la ventana clona. Ver DIFERENCIAS 139.           */
/* ==================================================================== */

.franja-parametros {
  display: flex;
  align-items: center;
  gap: var(--oly-space-2);
  padding: var(--oly-space-2) var(--oly-space-3);
  border-bottom: 1px solid var(--oly-border-subtle);
  background: var(--oly-surface);
}
.franja-parametros label {
  font-size: 12px;
  color: var(--oly-text-secondary, var(--oly-text-primary));
}
.franja-parametros label.oculto,
.franja-parametros span.oculto { display: none; }

.papel-reporte {
  /* `overflow-x` y no `wrap`: un reporte de ancho fijo que se parte en dos
     renglones deja de cuadrar a la vista, que es para lo que sirve. Se
     desplaza, como se desplazaría el papel. */
  overflow-x: auto;
  padding: var(--oly-space-4);
  margin: var(--oly-space-3);
  background: var(--oly-surface);
  border: 1px solid var(--oly-border-subtle);
  border-radius: var(--oly-radius-sm);
  font-family: ui-monospace, "Cascadia Mono", Consolas, "Liberation Mono", monospace;
  font-size: 12px;
  line-height: 1.45;
  white-space: pre;
  min-height: 8rem;
}

.titulo-papel {
  margin: 0;
  text-align: center;
  font-weight: var(--oly-font-weight-medium);
}
.rotulo-papel { margin: 0; }
.blanco-papel { margin: 0; }

/* 🔴 `margin: 0`, Y ES UNA MEDICIÓN, no un ajuste de gusto. Sus hermanos
   (`.titulo-papel`, `.rotulo-papel`, `.blanco-papel`) lo tenían y ésta no, así
   que cada renglón del papel estructurado se llevaba los 12 px de margen por
   omisión del `<p>`: **26,5 px de paso** medidos en el navegador, contra los
   **14** que mide CONCAR. Y los 14 no son sólo del 8.1: contados los arranques
   de renglón con PIL sobre `mayo-vista.png` (19 pasos de 14), `cost32-vista.png`
   (5) y `pv-max.png` (15), el paso dominante es 14 en los TRES programas --los
   28 son renglones en blanco--. El defecto se vio al mandar este papel a la
   ventana `PrintPreview`, donde el paso medido SÍ está puesto (§138): el mismo
   papel salía a un renglón y a otro según por dónde entrara. Ver §139. */
.linea-papel { display: flex; margin: 0; }

/* Toda cifra de dinero con `tabular-nums` y a la derecha -- la regla de la
   cabecera de estilos.css, y acá además es lo que hace que dos renglones
   consecutivos se puedan comparar de un vistazo. */
.linea-papel .cifra {
  margin-left: auto;
  min-width: 11ch;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
/* Cuando hay DOS cifras (el 8.1 y sus totales), sólo la primera empuja: la
   segunda va pegada a su derecha con su propio ancho. */
.linea-papel .cifra + .cifra { margin-left: 0; }

.linea-papel .celda { flex: none; padding-right: 1ch; }

.col-comprobante { width: 8ch; }
/* 🔴 LA PRIMERA COLUMNA DEL 5.1 NO ES `col-comprobante`, y esto se vio en el
   navegador y en ningún otro sitio. Esa clase mide `8ch` porque en el Libro
   Diario y el Mayor la celda lleva sólo el número del comprobante (`010001`,
   seis caracteres). El 5.1 lleva `<subdiario> -<comprobante>` --`01 -010001`,
   DIEZ caracteres, medido en el fotograma `e0091`-- así que la celda
   DESBORDABA: medido el 09/09/2026, `scrollWidth > clientWidth` en las 7.032
   filas, el número salía cortado en `01 -0100` y encima de la fecha de al
   lado, y el rótulo `REGISTRO OPERACION` se partía en cuatro trozos.
   Ni el arnés ni el JSON lo podían ver: los dos datos estaban bien. */
.col-registro51 { width: 11ch; }
.col-dia         { width: 3ch; }
/* 🔴 `8ch` SE MEDÍA CONTRA `border-box` SIN CONTAR EL PADDING.
   `estilos.css:50` pone `box-sizing: border-box` en TODO, y
   `.linea-papel .celda` (línea ~1496) le suma `padding-right: 1ch`: con
   `width: 8ch` el CONTENIDO disponible era `8 - 1 = 7ch`. Medido el
   09/09/2026 contra FACILITA (`SELECT length(cuenta), count(*) FROM
   libro_diario WHERE empresa_id=145 AND ejercicio=2026 AND mes=1 GROUP BY
   1`): de 7.032 cuentas del mes, 5.971 miden 6 dígitos y **1.061 miden 8**
   -- exactamente el caso que desborda. `scrollWidth > clientWidth` no lo
   detecta porque el padding ABSORBE el desborde en vez de mostrarlo; se
   ve comparando el ancho del texto contra `clientWidth`.

   🔴 UNA VERSIÓN ANTERIOR DE ESTE COMENTARIO MEDÍA MAL Y LO ANOTABA COMO
   HECHO -- la auditoría del 09/09 lo cazó. Medía con un `<span>` clonado de
   la propia celda (mismas clases `celda col-cuenta`) parado como HERMANO en
   el mismo `.linea-papel`: ese clon se traía puesto el `padding-right: 1ch`
   de `.celda`, así que el "ancho de texto" que devolvía ya llevaba 1ch de
   más sumado (`63.28px` para `94659601`, contra los `56.25px` reales). La
   medición correcta es un `<span>` SIN clase, insertado DENTRO de la celda
   de dato de verdad (hereda la tipografía por cascada, no carga su propio
   padding): 8 dígitos (`94659601`) miden `56.25px`, y `1ch` en ese mismo
   contexto mide `7.037px` -- `56.25 / 7.037 = 7.99ch`, o sea EXACTAMENTE
   8ch: en esta tipografía monoespaciada un dígito ES un `ch`, ni más ni
   menos. `9ch` de ancho (8ch de contenido + el 1ch de separación de
   siempre) alcanza justo, con el mismo criterio que `.col-registro51`. */
.col-cuenta      { width: 9ch; }
.col-subdiario   { width: 3ch; }
.col-anexo       { width: 13ch; }
/* La columna `ANEXO` del Formato 5.1 (`e0093`, entre `DENOMINACION` y
   `MOVIMIENTO`) -- distinta de `.col-anexo` de arriba, que es la del
   Libro Diario y el Mayor Bimoneda, en otro sitio de la fila y con otro
   ancho medido. Medido el 09/09/2026 contra FACILITA, mismo mes y misma
   consulta que `.col-cuenta`: el anexo más largo mide **15** caracteres,
   no 11 -- el encargo citaba 11 y la medición en vivo no lo confirmó, así
   que se usa la medida, no la cita.

   Misma corrección que `.col-cuenta` de arriba, y por el mismo motivo: la
   primera medición (clon con su propia clase, hermano en la fila) se
   sumaba el padding y decía `112.5px`/16ch; el `<span>` sin clase, DENTRO
   de la celda de dato, da `105.475px` para 15 caracteres -- `105.475 /
   7.037 = 14.99ch`, o sea 15ch exactos, ni uno más. La leyenda `TOTAL`/
   `TOTAL SUBDIARIO`/`TOTAL GENERAL` de `subtotalFormato51` vive en esta
   MISMA columna (`TOTAL SUBDIARIO` mide igual, 15 caracteres). `16ch` de
   ancho (15ch de contenido + 1ch de separación) alcanza justo. */
.col-anexo51     { width: 16ch; }
.col-documento   { width: 17ch; }
/* El `NUMERO COMPROBANTE` del Formato 6.1 --distinto de `.col-comprobante`,
   que es la del Libro Diario y lleva solo el correlativo--. Aca la celda es
   `<subdiario>-<comprobante>`: `22-090005`, NUEVE caracteres medidos en el
   fotograma `e0097` (§4.3, filas 10 a 13).

   Pero manda el ROTULO y no el dato: `COMPROBANTE` mide ONCE caracteres, y
   con los `10ch` que pedia el dato se partia en dos renglones --visto en el
   navegador el 10/09/2026 sobre FACILITA setiembre, la cabecera decia
   `COMPROBAN` / `TE`--. `12ch` es 11ch de contenido mas el `1ch` de
   separacion de `.celda`, mismo criterio que `.col-registro51`. */
.col-comprobante61 { width: 12ch; }
.col-fecha       { width: 10ch; }
.col-fecha-larga { width: 12ch; }
.col-ceco        { width: 5ch; }
.col-tipodoc     { width: 4ch; }
.col-serie       { width: 6ch; }
.col-numero      { width: 10ch; }
.col-tipoid      { width: 2ch; }
.col-moneda      { width: 3ch; }
.col-dh          { width: 2ch; }
.col-tc          { width: 8ch; }
/* La glosa y la razón social son las dos únicas que se CORTAN: en el papel
   de CONCAR llegan cortadas también -- «TELEFONICA DEL , FACTURA…» en el
   mayor y «TELEFONICA DEL PERU» en el 8.1. Se copia el corte. */
.col-glosa,
.col-proveedor {
  width: 26ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.col-proveedor { width: 21ch; }

.subtotal-papel .rotulo-subtotal {
  margin-left: auto;
  text-align: right;
  padding-right: 2ch;
}
.subtotal-papel .cifra { margin-left: 0; }
.total-general { font-weight: var(--oly-font-weight-medium); }

/* Un dato DEDUCIDO por la réplica, no leído del maestro: el `6` del tipo de
   documento de identidad cuando el anexo no lo declara. Se marca en la
   pantalla porque es una hipótesis con una sola medición detrás y quien
   revise el papel tiene derecho a distinguirla del dato. */
.dato-deducido {
  border-bottom: 1px dotted var(--oly-text-secondary, var(--oly-text-primary));
  cursor: help;
}

/* `Glosa a Imprimir`: el grupo de radios del diálogo de CTDIAR02. En CONCAR es
   un recuadro con leyenda dentro de un modal; acá va en la franja de
   parámetros, que es la diferencia de forma que esta pantalla ya tiene. El
   `fieldset` es el elemento correcto para un grupo de radios con rótulo, y de
   paso lo lee bien un lector de pantalla. */
.grupo-glosa {
  display: flex;
  align-items: center;
  gap: var(--oly-space-2);
  margin: 0;
  padding: 0 var(--oly-space-2) var(--oly-space-1);
  border: 1px solid var(--oly-border-subtle);
  border-radius: var(--oly-radius-sm);
}
.grupo-glosa legend {
  padding: 0 var(--oly-space-1);
  font-size: 11px;
  color: var(--oly-text-secondary, var(--oly-text-primary));
}
.grupo-glosa label {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  white-space: nowrap;
}
/* Mismo arreglo que en el marco `Orden` de CTLIBR81: `input, select` de
   `estilos.css` estiraba también estos dos radios. */
.grupo-glosa input[type="radio"] {
  flex: none;
  width: auto; height: auto;
  margin: 0; padding: 0;
}
.grupo-glosa.oculto { display: none; }

/* ==================================================================== */
/* EL DIÁLOGO DE CTLIBR81                                               */
/*                                                                      */
/* MEDIDO el 03/09/2026 en la empresa 0002. No comparte la franja de     */
/* parámetros con los otros tres reportes porque su diálogo SÍ se        */
/* capturó y es distinto: dos filas de rótulo + campo, una casilla con   */
/* el texto a la IZQUIERDA de la caja, un marco `Orden` con seis radios  */
/* en DOS COLUMNAS, y una barra de cinco botones con el de Salir         */
/* separado por un hueco.                                                */
/*                                                                      */
/* Lo que NO se copia y se dice: CONCAR lo abre como ventana modal con   */
/* barra de título propia, y acá va embebido en la pantalla. Es la misma */
/* diferencia de forma que ya tenían los otros tres.                     */
/* ==================================================================== */

.dialogo-libr81 {
  padding: var(--oly-space-4) var(--oly-space-5) var(--oly-space-2);
  border-bottom: 1px solid var(--oly-border-subtle);
  background: var(--oly-surface);
}

.fila-libr81 {
  display: flex;
  align-items: center;
  gap: var(--oly-space-3);
  margin-bottom: var(--oly-space-2);
}
/* El rótulo reserva su ancho para que las dos cajas arranquen alineadas,
   como en la pantalla: `Mes de Registro Compras` y `Moneda` empiezan en la
   misma columna y sus campos también. */
.fila-libr81 > label {
  flex: none;
  width: 24ch;
  font-size: 12px;
  color: var(--oly-text-secondary, var(--oly-text-primary));
}
/* `flex: none` porque el `flex: 1 1 190px` de `estilos.css` los estiraba a
   todo el ancho de la fila, y en CONCAR la caja del mes son dos dígitos y el
   combo de moneda ocupa un tercio del diálogo. */
/* 🔴 LAS TRES CAJAS DE `CTMAYO01`, QUE SE ESTIRABAN A TODO EL ANCHO.
   Medido en el navegador el 10/09/2026, con la ventana abierta: `Mes` salía
   de **435 px** y las dos cuentas de 355 y 217, cada una distinta. Sin regla
   propia heredaban el `flex: 1 1 190px` de `estilos.css` y se repartían la
   fila, que es el defecto de fondo que el usuario ya había señalado dos veces
   --una caja no mide lo que su dato mide--.

   Lo medido, `docs/CTMAYO01-MEDIDA.md` §1: `Mes` es «caja corta, dos
   dígitos», y `Cuenta Inicial`/`Cuenta Final` son «caja + descripción a la
   derecha, FUERA de la caja», las dos del mismo tamaño porque son el mismo
   control repetido. El ancho en píxeles no está medido --el fotograma no da
   escala--, así que se usa el de la caja hermana ya construida y aceptada:
   `#libr81-mes`, 8ch. Las cuentas llevan 14ch, que es lo que ocupan sus ocho
   dígitos más el hueco de las doce que admite `maxlength`.
   Ver DIFERENCIAS §242. */
#mayo01-mes {
  flex: none;
  width: 8ch;
  text-align: left;
}
#mayo01-cuenta-inicial,
#mayo01-cuenta-final {
  flex: none;
  width: 14ch;
  text-align: left;
}
#libr81-mes {
  flex: none;
  width: 8ch;
  text-align: left;
  font-variant-numeric: tabular-nums;
}
#libr81-moneda { flex: none; width: 34ch; }

/* 🔴 LO MISMO PARA `CTLIBR51`, Y POR LA MISMA REGLA DE `estilos.css`.
   `input, select { flex: 1 1 190px }` estiraba las cinco cajas del 5.1: medido
   en el navegador el 09/09/2026, `Mes` --dos dígitos-- salía de 824 px y era
   la caja MÁS GRANDE del diálogo, mientras los tres desplegables salían
   desiguales (162 / 451 / 451). En CONCAR es al revés y está en el volcado:
   los TRES desplegables miden 265 px IGUALES (`left=125`, `width=265`), `Mes`
   mide 57 y la fecha 73 -- o sea que `Mes` es la caja más CHICA.
   Se copian las proporciones, no los píxeles: el diálogo de la réplica no
   tiene el ancho del de CONCAR. `8ch` para el mes es el mismo que ya usa el
   8.1 para su propio campo de mes de dos dígitos. */
#libr51-moneda,
#libr51-sub-inicial,
#libr51-sub-final { flex: none; width: 30ch; }
#libr51-mes {
  flex: none;
  width: 8ch;
  text-align: left;
  font-variant-numeric: tabular-nums;
}
/* 🔴 `10ch` NO ALCANZABA, Y LA CULPA ERA DEL `box-sizing`.
   El usuario lo vio el 10/09/2026 --«imprimir fecha sale cortado»--: el
   campo ensenaba `10/09/2` de `10/09/26`. `* { box-sizing: border-box }`
   (`estilos.css`) hace que ese `width` incluya el relleno, y el relleno que
   la regla global de `input` le da es `0 var(--oly-space-3)`, o sea 12 px a
   cada lado. De los 10ch --unos 76 px a 14 px de fuente-- quedaban 50 para
   el texto, que da para siete caracteres de ocho.
   Se acota el relleno a 4 px y se pone el ancho MEDIDO del control de
   CONCAR: `MSMaskWndClass`, `width: 73`, en
   `artifacts/ui/forms/2026-08-10T1519/form.ctlibr51.json` --el mismo control
   que trae `10/08/26` y `enabled: false`--.

   🔴 Y 78 Y NO LOS 73 MEDIDOS, porque copiar el numero de pixeles de otra
   tipografia NO es copiar la pantalla. Los 73 de CONCAR son con su MS Sans
   Serif de 8 pt; aca la fuente es Inter a 14 px y es mas ancha. Medido en el
   navegador con 73: `scrollWidth 73` contra `clientWidth 71`, o sea seguia
   recortando por dos pixeles -- el mismo defecto con otro numero. Lo que se
   copia es que los OCHO caracteres entren, y con 78 entran con tres pixeles
   de sobra (`scrollWidth` deja de superar a `clientWidth`). */
#libr51-fecha {
  flex: none;
  width: 78px;
  padding-inline: 4px;
  font-variant-numeric: tabular-nums;
}

/* 🔴 `Principal` Y `Movimientos` VAN UNO DEBAJO DEL OTRO, Y ESTA MEDIDO.
   El usuario lo pidio el 10/09/2026 --«el radio button principal y
   movimientos estaria uno debajo del otro no crees?»-- y el volcado de
   formulario lo zanja: en
   `artifacts/ui/forms/2026-08-10T1519/form.ctlibr51.json` el
   `ThunderRT6OptionButton` «Principal» esta en `top: 252` y «Movimientos» en
   `top: 276`, con `left` 38 y 40. Veinticuatro pixeles de diferencia
   vertical y practicamente el mismo `left`: apilados, no en fila. Y el marco
   que los contiene mide 151 x 89, que es alto para dos renglones y estrecho
   para dos columnas.

   🔴 Y SE ACOTA A ESTE DIALOGO A PROPOSITO. `.grupo-glosa` la comparten seis
   sitios, y de los otros dos que tienen DOS radios ninguno esta medido al
   pixel: el de `dialogo-mayo01` no tiene volcado de formulario --`CTMAYO01`
   no lo tiene, ver `docs/C3-C6-LIBRO-DIARIO-Y-MAYOR-MEDIDOS.md` §0-- y el de
   la franja generica de `pantalla-reporte` es una forma NUESTRA, declarada
   como tal en su propio comentario. Apilar la clase entera habria torcido
   dos pantallas por una medicion que es de una sola. */
#dialogo-libr51 .grupo-glosa:has(input[type="radio"]) {
  flex-direction: column;
  align-items: flex-start;
  gap: var(--oly-space-1);
}
/* Los tres marcos en fila, con el reparto del volcado: `Glosa a Imprimir` es
   el más angosto (151 px), `Consideraciones` va en medio (169) y el de la
   fecha es el más ancho de los tres (133 de marco pero con el campo dentro).
   Se copian las proporciones, que es lo que se ve; los píxeles de CONCAR no,
   porque el diálogo de la réplica no tiene ese ancho. */
.marcos-libr51 {
  display: flex;
  align-items: flex-start;
  gap: var(--oly-space-4);
  margin-bottom: var(--oly-space-2);
}
.marcos-libr51 > .grupo-glosa { flex: 1 1 0; margin: 0; }
/* La casilla que hace de leyenda del marco `Imprimir Fecha`: pegada a su
   texto. Es un parche de ENCAJE, no de TAMAÑO.
   🔴 Acá había además un noveno parche de tamaño --`#dialogo-libr51 ...
   input[type="checkbox"] { flex: none; width: auto; height: auto }`-- escrito
   por precaución y SIN medir si hacía falta. No hacía: la exclusión de
   `estilos.css` (`input:not([type="radio"]):not([type="checkbox"])`) ya cubre
   radios y casillas en el origen. Lo cazó `los-controles-que-no-son-cajas.mjs`
   en el acto, que es exactamente para lo que existe, y es la SEGUNDA vez que
   caza este mismo movimiento (la primera fue `CTANEX03`, §133). El arreglo va
   en el origen; acá no va nada de tamaño. */
#dialogo-libr51 legend > label {
  display: inline-flex;
  align-items: center;
  gap: var(--oly-space-1);
  width: auto;
}

/* La casilla va DESPUÉS de su texto, que es como CONCAR la dibuja, y el
   bloque entero corrido a la derecha como en la pantalla. */
.fila-casilla-libr81 {
  margin: var(--oly-space-4) 0 var(--oly-space-3);
  padding-left: 4ch;
}
.fila-casilla-libr81 > label { width: auto; }

.orden-libr81 {
  display: flex;
  gap: var(--oly-space-8);
  margin: 0 0 var(--oly-space-3);
  padding: var(--oly-space-2) var(--oly-space-4) var(--oly-space-3);
  border: 1px solid var(--oly-border-subtle);
  border-radius: var(--oly-radius-sm);
}
.orden-libr81 legend {
  padding: 0 var(--oly-space-1);
  font-size: 11px;
  color: var(--oly-text-secondary, var(--oly-text-primary));
}
/* 🔴 `estilos.css` tiene `input, select { flex: 1 1 190px; height: 28px }`
   pensado para cajas de texto, y alcanza también a los radios y a las
   casillas: medido el 03/09/2026, la casilla de `Imprimir Nombre extendido`
   salía de 750px de ancho y los seis radios de 28px de alto, cada uno en su
   propio renglón. Se los devuelve a su tamaño propio.

   La misma regla afecta al grupo `Glosa a Imprimir` de los otros tres
   reportes; se arregla ahí también, más abajo, porque es el mismo defecto. */
.columna-orden input[type="radio"],
.fila-casilla-libr81 input[type="checkbox"] {
  flex: none;
  width: auto; height: auto;
  margin: 0; padding: 0;
}

.columna-orden { display: flex; flex-direction: column; gap: 4px; }
.columna-orden label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  white-space: nowrap;
}

/* La barra: los cuatro de acción juntos, un hueco, y Salir. El hueco es
   MEDIDO -- CONCAR separa Salir del resto -- y por eso es un elemento y no
   un margen suelto. */
.barra-libr81 {
  display: flex;
  /* 🔴 `wrap` PARA QUE LA AYUDA CAIGA DEBAJO, QUE ES DONDE SU PROPIO
     COMENTARIO DECIA QUE ESTABA. `index.html` dice de `#libr81-ayuda` «en su
     propio renglon», y este contenedor era `flex` sin `wrap`: la ayuda
     entraba como un hermano MAS de la fila y le comia el ancho a la franja,
     que es `flex: 1 1 auto; min-width: 0` y por tanto se encoge hasta
     partirse letra a letra. Medido el 07/09/2026 en la captura del usuario:
     «Registro Compras Mes 07 no generado» salia en una columna de unos 70 px,
     un renglon por palabra, con la ayuda solapada al lado. El comentario
     describia el arreglo que faltaba. Ver DIFERENCIAS §145. */
  flex-wrap: wrap;
  align-items: center;
  gap: 2px;
  padding-top: var(--oly-space-2);
  border-top: 1px solid var(--oly-border-subtle);
}
/* Ancho completo y AL FINAL: en el marcado va antes de los cinco botones
   --ahi la puso §129 para que se leyera pegada a la franja-- y sin `order`
   los empujaria a un tercer renglon. */
#libr81-ayuda {
  order: 10;
  flex: 0 0 100%;
}


.barra-libr81 button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px; height: 28px;
  color: var(--oly-text-secondary, var(--oly-text-primary));
  background: var(--oly-surface);
  border: 1px solid var(--oly-border-subtle);
  border-radius: var(--oly-radius-xs);
  cursor: pointer;
}
.barra-libr81 button:hover {
  color: var(--oly-text-primary);
  background: var(--oly-surface-hover);
}
/* ---------------------------------------------------------------------
   🔴 NINGUN `.icono` PUEDE SALIR A SU TAMANO INTRINSECO
   ---------------------------------------------------------------------
   Un `<svg>` sin `width`/`height` y sin regla de CSS mide 300x150 -- el
   tamano por omision del elemento reemplazado--, y eso es exactamente lo que
   pasaba en `CTMOVI09`. El usuario lo vio el 07/09/2026: «tienes que acomodar
   los iconos y los inputs porque el de desktop se ve mejor mas ordenado que
   el de concar web y la idea es que concar web se vea igual exactamente
   igual solo cambiando el .css».

   Medido en el navegador ese dia: los tres `svg.icono` de `CTMOVI09`
   --`f-crear-anexo`, `f-notas-comprobante` y `f-documentos-adjuntos`--
   renderizaban a 300x150 dentro de botones de 316x159. En CONCAR esos
   botones miden 21x21 y 35x35.

   🔴 Y LA FAMILIA ESTABA CONTADA A MEDIAS. Hay DIEZ `class="icono"` en
   `index.html`: SIETE los vestia la regla de UNA pantalla que hay justo
   debajo (`.barra-libr81 .icono`) y TRES no las vestia nadie. Es el mismo
   patron que la vuelta 38 con los radios --una regla escrita para una
   pantalla y reusada sin contar la familia-- asi que el arreglo va en el
   ORIGEN y no en un cuarto parche: este 16x16 es el SUELO de todo `.icono`,
   y quien necesite otro tamano lo dice con su clase.
   `herramientas/los-iconos-que-no-crecen.mjs` cuenta los diez y se pone rojo
   si aparece uno sin tamano. Ver DIFERENCIAS §131. */
.icono {
  width: 16px;
  height: 16px;
  flex: none;
}

.barra-libr81 .icono { width: 16px; height: 16px; }

/* ---------------------------------------------------------------------
   LOS BOTONES DE ICONO DE `CTMOVI09`, CON SU TAMANO MEDIDO
   ---------------------------------------------------------------------
   Los dos tamanos salen del volcado de formulario de la ventana, y se
   contrastaron en los OCHO volcados `form.ctmovi09*.json` que hay en
   `artifacts` --tres en `rig/share` y cinco en `ui/forms`--: los ocho dan
   los mismos numeros, y lo unico que varia entre ellos es el `visible` del
   boton `?`, que es estado y no geometria.

     el de al lado de `Codigo Proveedor`   x=674  y=352   21x21
     los dos de la derecha                 x=1011 y=418   35x35
                                           x=1047 y=418   31x35

   El de 31 y el de 35 se dibujan los dos de 35: la diferencia de 4 px es de
   los bordes 3D de VB6, que la replica no tiene, y hacer uno 4 px mas
   angosto que su gemelo se veria como un defecto en vez de como fidelidad.
   Va anotado en DIFERENCIAS §131.

   El icono va mas chico que su boton, igual que en `.icono-boton`: 14 en el
   de 21, y 24 en los de 35. */
.boton-icono-campo,
.boton-grande-campo,
.boton-gs {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  padding: 0;
  background: var(--oly-surface-subtle);
  border: 1px solid var(--oly-border);
  border-radius: var(--oly-radius-sm);
  cursor: pointer;
}
.boton-icono-campo { width: 21px; height: 21px; }
.boton-grande-campo { width: 35px; height: 35px; }
.boton-icono-campo .icono { width: 14px; height: 14px; }
.boton-grande-campo .icono { width: 24px; height: 24px; }
/* 🔴 `&G` Y `&S` NO SON CUADRADOS, Y ES LA TERCERA MEDIDA DE LA FAMILIA.
   Los dos botones del pie de CONCAR --grabar y la puerta-- miden 25 de ancho
   por 41 de ALTO. Medido en `form.ctanex03.json` (x=531 y x=558, y=401, 25x41)
   y otra vez en `form.ctmovi09.json` (x=1055 y x=1080, y=646, 25x41): dos
   pantallas distintas, la misma forma. Ponerlos con `.boton-grande-campo`
   (35x35) los habria hecho cuadrados, que es lo que NO son: son altos y
   angostos, y en la pantalla de CONCAR se reconocen por eso.

   Va acá, en el origen, y no en una regla por pantalla: es el mismo defecto
   que §131 --siete iconos vestidos por una regla de una sola ventana-- y la
   forma de no repetirlo es que la clase exista una vez. Ver DIFERENCIAS §133. */
/* El `min-width: 0` es por `.boton-maestro`, que pone 30 y EMPATA en peso
   con esta clase: sin el, un boton que lleve las dos clases se queda en 30
   de ancho y los 25 medidos no se cumplen. */
.boton-gs { width: 25px; min-width: 0; height: 41px; }
.boton-gs .icono { width: 18px; height: 18px; }

/* 🔴 LA PUERTA DE LAS TRES VENTANAS DEL PLE MIDE OTRA COSA, Y SE DIBUJABA UNA
   TERCERA. Son tres numeros distintos y conviene separarlos:

     lo que CONCAR dibuja en ESTA familia .... 33 x 43
     lo que `.boton-gs` declara arriba ....... 25 x 41
     lo que el navegador dibujaba ............ 96 x 28

   1. QUE CONCAR TIENE DOS TAMANOS DE PUERTA, Y ESTA ES LA SEGUNDA.
      El 25x41 de arriba esta medido dos veces --`form.ctanex03.json` y
      `form.ctmovi09.json`, las dos con la pareja grabar+puerta a y=401 y
      y=646--, asi que no era una casualidad ni deja de valer. Pero el volcado
      PROPIO de esta familia dice otra cosa:

        form.crea-archivo-5-1-libro-diario-ple-5-0-ctple551.json,
        `windows[0].controls`:
          [4] ThunderRT6CommandButton  `&S`                L464 T305   33x43
          [5] ProgressBarWndClass      (la franja)         L16  T311  165x15
          [3] ThunderRT6CommandButton  `Generar en &TXT`   L223 T305  115x31
          [2] ThunderRT6CommandButton  `Generar en E&xcel` L341 T305  120x31

      O sea que la pregunta que quedo abierta anoche --«o CONCAR tiene dos
      tamanos y esta familia necesita su propia regla, o el 25x41 nunca fue
      general»-- la contesta el dato: TIENE DOS. La puerta de esta familia es
      mas ancha y mas alta que la del pie de `CTMOVI09`. Se le da su regla y
      la general se queda como estaba, que es lo que sus dos mediciones piden.

   2. Y LO QUE SE DIBUJABA NO ERA NI UNA NI OTRA. Medido en el navegador el
      10/09/2026 abriendo las tres ventanas y leyendo `getBoundingClientRect`:
      las tres daban 96 x 28. La causa es una colision de especificidad que
      este mismo bloque ya avisa dos lineas mas arriba para OTRA clase:

        `.botones-regc27 button`  (0,1,1)  min-width: 96px
                                           height: var(--oly-control-height-sm)
        `.boton-gs`               (0,1,0)  width: 25px; min-width: 0; height: 41px

      `(0,1,1)` gana a `(0,1,0)`, y ademas `min-width` gana a `width`: la
      puerta salia siendo el control MAS ANCHO del pie cuando es el mas
      angosto. No lo veia ningun arnes --el marcado, la clase y el numero del
      CSS estaban los tres bien-- y no lo veia tampoco leer el CSS, que es
      como se reviso anoche: solo se ve midiendo el elemento dibujado.

   `.botones-regc27 .boton-gs` es (0,2,0) y gana a las dos. Toca EXACTAMENTE
   las tres ventanas del PLE: son las unicas tres `.botones-regc27` con una
   puerta dentro --`pantalla-lib581`, `pantalla-lib582`, `pantalla-regc27` y
   `pantalla-regc25` usan la misma caja y NO llevan `.boton-gs`--.

   🟡 LOS DOS BOTONES DE TEXTO NO SE TOCAN, y va dicho en vez de ajustado: el
   volcado los da en 115x31 y 120x31 y la replica los dibuja en 117x28 y
   124x28. Son dos y cuatro pixeles de ancho y tres de alto, y el alto sale
   del token compartido de altura de control. Cambiarlos es decidir que esta
   familia deja de compartir ese token, y eso es mas que un numero. Ver
   DIFERENCIAS 274. */
.botones-regc27 .boton-gs { width: 33px; min-width: 33px; height: 43px; }
.boton-icono-campo:disabled,
.boton-grande-campo:disabled,
.boton-gs:disabled { opacity: .45; cursor: not-allowed; }
.barra-libr81 .hueco-barra { width: var(--oly-space-4); }
/* La franja se come todo el hueco de la izquierda y empuja los cinco botones
   al borde derecho, que es donde CONCAR los pone (DIFERENCIAS §79). Antes
   llevaba `margin-left` porque iba la ULTIMA. */
.barra-libr81 #libr81-aviso { flex: 1; min-width: 0; margin-right: var(--oly-space-4); }

/* ------------------ las bandas del papel del 8.1 -------------------- */
/* El encabezado de CONCAR son DOS renglones: arriba los nombres de banda
   con su recuadro ASCII, abajo los de columna. Acá los recuadros `+--+`
   se sustituyen por un borde -- es lo mismo que ya se hizo con el resto
   del papel, que se dibuja con CSS y no con caracteres. */
/* 🔴 EL FONT-SIZE DE ESTOS DOS RENGLONES TIENE QUE SER EL DE LOS DATOS.
   Estaba en 10px mientras las filas van a 12px, y como TODOS los anchos de
   columna estan en `ch` --que es una medida del tipo de letra-- cada columna
   del encabezado medía 0,83 de la suya: NINGUN rotulo caía sobre su columna.
   Medido el 03/09/2026 en el papel bimoneda: el rotulo `GLOSA` ocupaba
   [578,730] y su dato [653,835]. Afectaba a los cinco papeles por igual y
   nadie lo habia mirado, porque de lejos el encabezado «se ve bien».
   Los rotulos largos envuelven, que es lo que CONCAR hace en su recuadro. */
.bandas-papel,
.columnas-papel {
  border-bottom: 1px solid var(--oly-border);
  color: var(--oly-text-secondary, var(--oly-text-primary));
  line-height: 1.25;
}
.bandas-papel { border-top: 1px solid var(--oly-border); }
.bandas-papel .banda {
  flex: none;
  padding: 0 1ch;
  border-left: 1px solid var(--oly-border-subtle);
  white-space: normal;
  overflow-wrap: anywhere;
}
.bandas-papel .banda:first-child { border-left: none; }
/* Los anchos salen de las columnas que cada banda cubre: las de un par de
   cifras miden dos columnas de 11ch más el hueco; las de una, una. */
/* MEDIDOS el 03/09/2026 sumando las columnas que cada banda cubre, con la
   caja en `border-box` --el `padding: 0 1ch` va DENTRO del ancho, igual que
   en las celdas de datos:

     COMPROBANTE : subdiario 3 + comprobante 8 + fecha 10 + tipodoc 4
                   + serie 6 + numero 10                        = 41ch
     PROVEEDOR   : tipoid 2 + anexo 13 + proveedor 21           = 36ch
     un par      : dos cifras de 11ch                           = 22ch
     una sola    : una cifra                                    = 11ch

   Estaban en 44/38/23/12, que es un caracter de mas en cada una: la suma
   daba 179ch contra las 176ch de los datos y las ocho bandas iban corridas,
   la ultima por tres caracteres enteros. */
.bandas-papel .banda-comprobante { width: 41ch; }
.bandas-papel .banda-proveedor   { width: 36ch; }
.bandas-papel .banda-par         { width: 22ch; }
.bandas-papel .banda-una         { width: 11ch; }
/* CTMAYO01. Sus bandas cubren columnas distintas de las del 8.1 y por eso
   tienen sus propios anchos: `COMPROBANTE` va sobre SD+NUMERO+F.+ANEXO
   = 3+8+3+13 = 27ch. Estuvo en 31ch por sumarle «1ch de separación» a cada
   columna: la caja es `border-box` y ese padding va DENTRO del ancho, así
   que la banda sobraba 4ch -- 28 px medidos -- y se comía el principio de
   DOCUMENTO. Lo levantó la auditoría del 03/09/2026 comparando el
   `getBoundingClientRect` de la banda con el de sus cuatro columnas.
   Las de moneda van sobre sus dos columnas de cifra de 11ch cada una. El hueco de 11ch es el
   del tipo de cambio, que va entre medio y no lleva banda. */
.bandas-mayo01 .banda-comprobante-mayo01 { width: 27ch; }
.bandas-mayo01 .banda-moneda-mayo01 { text-align: center; }
/* `CENTRO COSTOS` no entra en los 5ch que le bastan al diario: en el papel
   bimoneda el rotulo se partia en CUATRO renglones («CENT / RO / COST / OS»)
   y quedaba ilegible al lado de la glosa. Con 8ch parte en dos --`CENTRO`
   y `COSTOS`-- que es como lo apila CONCAR en su recuadro. El dato (`200`)
   lleva la misma clase para que la columna y su rotulo no se desalineen. */
.col-ceco-mayo01 { width: 8ch; }
/* El papel va en `white-space: pre` porque las FILAS son de ancho fijo,
   pero los rótulos de columna son largos y en su ancho no entran en un
   renglón. CONCAR los parte en cinco renglones dentro del recuadro ASCII;
   acá envuelven dentro de su celda, que es lo mismo con otra herramienta.
   Sin esto se pisaban unos con otros -- medido, se veía `NUMEROCORRELATIVO`
   encimado. */
.columnas-papel .celda {
  white-space: normal;
  overflow-wrap: anywhere;
  line-height: 1.1;
}
/* Y por lo mismo, la cifra del encabezado tampoco puede achicarse. Ademas
   necesita `width` y no solo el `min-width` heredado: sin el, un rotulo
   largo como `BASE IMPONIBLE` ESTIRA su celda --14ch contra los 11ch del
   dato-- y a partir de ahi todo el bloque de dinero queda corrido. Con el
   ancho fijo el rotulo envuelve dentro de su columna, que es lo que hace
   CONCAR en su recuadro. */
.columnas-papel .cifra { width: 11ch; }


/* El pie que dice con cuál se emitió. CONCAR no lo imprime -- es nuestro, y
   está anotado en DIFERENCIAS. */
.pie-papel {
  margin: var(--oly-space-3) 0 0;
  font-size: 11px;
  color: var(--oly-text-secondary, var(--oly-text-primary));
}

/* ================== CTMOVI02 — Situación de Comprobante ==============
   La franja de filtro del fotograma: la caja del mes es de DOS caracteres
   y los tres radios van seguidos, no uno por línea. La regla de
   `estilos.css` que da `flex: 1 1 190px` a todo `input` los hacía enormes
   -- el mismo defecto que ya se corrigió en el diálogo de `CTLIBR81`. */
.franja-situacion #situacion-mes {
  /* 🔴 `4ch` RECORTABA EL SEGUNDO DIGITO. Medido en el navegador el
     10/09/2026, con `01` dentro: `clientWidth` 33 contra `scrollWidth` 39.
     La causa no es el `4ch` -- son los `padding-inline: 12px` de la regla
     global de `estilos.css` sobre una caja `border-box`: de los 35 px que
     salian quedaban 9 para el texto, y dos digitos de Inter a 14 px piden
     17. Es el mismo mecanismo del campo `Imprimir Fecha` de §226.

     Los 57 px salen del volcado: `form.ctmovi02.json` mide el
     `MSMaskWndClass` de esta franja en `width: 57`, `height: 19`. CONCAR
     le da a dos caracteres cinco veces su ancho de glifo, asi que aca el
     numero medido y el ancho comodo son el mismo, y no hay que elegir. */
  flex: none; width: 57px; text-align: center;
}
.radios-situacion { display: flex; gap: var(--oly-space-4); align-items: center; }
.radios-situacion label {
  display: inline-flex; align-items: center; gap: var(--oly-space-1);
  font-size: var(--oly-font-size-xs); white-space: nowrap;
}
.radios-situacion input[type="radio"] {
  flex: none; width: auto; height: auto; margin: 0; padding: 0;
}

/* La grilla desborda a lo ancho dentro de SU marco, nunca la página. */
.marco-grilla { overflow-x: auto; }
.grilla-situacion { min-width: 100%; }
.grilla-situacion th.num, .grilla-situacion td.num {
  text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap;
}

.pie-ventana {
  margin: var(--oly-space-2) 0 0;
  font-size: var(--oly-font-size-xs); color: var(--oly-text-tertiary);
}

/* ---------------- La ventana hija: `Detalle de Comprobante` ----------
   Tres columnas, como el fotograma: los datos del comprobante a la
   izquierda, los dos botones y la fecha de actualización en el medio, y
   la situación y la moneda a la derecha. */
/* 🔴 ESTAS TRES REGLAS NO SE APLICABAN, Y EL USUARIO LO VIO TRES VECES.
   `.cabecera-detalle` y `.columna-detalle` estan declaradas DOS veces en
   este archivo: aqui, para el `Detalle de Comprobante` de `CTMOVI02`, y mas
   abajo (~2.960) para el detalle de `CTMOVI09`/`CTMOVI90`, que es una pila
   de campos y no tres columnas. Mismo peso de selector, asi que ganaba la
   SEGUNDA: `.columna-detalle` pasaba a `flex-direction: column` --y con eso
   el `<label>` se iba ENCIMA de su caja en vez de al lado-- y
   `.cabecera-detalle` a `display: flex`, con lo que las tres columnas se
   encogian a su contenido y la mitad derecha de la ventana quedaba vacia.

   Eso es exactamente lo que el usuario reclamo el 10/09/2026: «estoy harto
   de decirte que si tienes espacio de sobra lo aproveches, todo se ve
   aplastado a la izquierda y eso lo hace verse fatal».

   Y lo que hay que copiar esta medido: la captura
   `artifacts/rig/shots/real-0509-ctmovi02-detalle.png` (05/09/2026, `0003`)
   ensena la ventana de CONCAR con TRES columnas de rotulo+caja EN LA MISMA
   LINEA, ocupando el ancho entero --`Comprobante` a la izquierda,
   `Ver Documentos Adjuntos` en medio y `Situacion` a la derecha, los tres en
   el primer renglon-- y la grilla debajo, tambien a lo ancho.

   Se arregla acotando cada juego a SU ventana en vez de renombrar la clase:
   el HTML de las dos esta medido y no se toca. Es la misma clase de defecto
   que `.campo-regc27 input` comiendose el buscador de un desplegable
   (§226/§228): una regla escrita para una pantalla alcanzando a otra.
   Ver DIFERENCIAS §231. */
#pantalla-situacion-detalle .cabecera-detalle {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--oly-space-4) var(--oly-space-6);
  margin-bottom: var(--oly-space-4);
}
#pantalla-situacion-detalle .columna-detalle {
  display: grid; grid-template-columns: max-content minmax(0, 1fr);
  gap: var(--oly-space-2) var(--oly-space-3); align-items: center;
}
#pantalla-situacion-detalle .columna-detalle > label {
  font-size: var(--oly-font-size-xs); color: var(--oly-text-secondary);
  white-space: nowrap;
}

/* La `Glosa` es la unica caja de la ventana que ocupa las dos columnas de su
   rejilla: en la captura va de `x=95` a `x=385` mientras las demas terminan
   en 168, porque lleva `ASIENTO DE APERTURA AUTOMATICO` entero. */
#pantalla-situacion-detalle .caja-gris.ancha { grid-column: 2 / -1; }

/* Gris y de sólo lectura, que es como CONCAR dibuja TODOS los campos de
   esta ventana: es de consulta, no de edición. Un `<output>` y no un
   `<input disabled>` porque no hay nada que enviar. */
.caja-gris {
  display: block; min-height: var(--oly-control-height-sm);
  padding: 4px var(--oly-space-2);
  border: 1px solid var(--oly-border); border-radius: var(--oly-radius-sm);
  background: var(--oly-surface-subtle); color: var(--oly-text-secondary);
  font-size: var(--oly-font-size-xs);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.caja-gris.corta { width: 6ch; }
.caja-gris.ancha { grid-column: 2 / -1; }
.caja-gris.num { text-align: right; font-variant-numeric: tabular-nums; }

.par-comprobante { display: flex; gap: var(--oly-space-2); }
.par-comprobante .caja-gris { flex: 0 0 auto; width: 12ch; }
.par-comprobante .caja-gris.corta { width: 5ch; }

.boton-detalle {
  grid-column: 1 / -1; justify-self: start;
  height: var(--oly-control-height-sm); padding: 0 var(--oly-space-3);
  font-size: var(--oly-font-size-xs);
}

.pie-detalle {
  display: flex; align-items: center; gap: var(--oly-space-2);
  margin-top: var(--oly-space-3); flex-wrap: wrap;
}
.pie-detalle > label {
  font-size: var(--oly-font-size-xs); color: var(--oly-text-secondary);
  white-space: nowrap; margin-left: var(--oly-space-4);
}
.pie-detalle > label:first-child { margin-left: 0; }
.pie-detalle .caja-gris { width: 14ch; }

/* ============== `Consulta` de CTPLAN01 — la ventana modal ============
   Ancha porque CONCAR la dibuja ancha: dos columnas de campos y una fila
   de ocho casillas. `.dialogo` la centra y `.velo-dialogo` deja la grilla
   y su barra fuera de alcance, que es lo que faltaba: los campos ya
   estaban en gris, pero el botón verde de Crear seguía vivo al lado. */
.dialogo-ancho { width: min(760px, calc(100vw - 32px)); }

.titulo-dialogo { display: flex; align-items: center; justify-content: space-between; }
.cerrar-dialogo {
  border: 0; background: none; cursor: pointer; padding: 0 2px;
  color: var(--oly-text-tertiary); font-size: var(--oly-font-size-sm);
}

.pestanas-consulta {
  display: flex; gap: 2px;
  padding: var(--oly-space-2) var(--oly-space-4) 0;
  border-bottom: 1px solid var(--oly-border-subtle);
}
.pestana-consulta {
  border: 1px solid var(--oly-border); border-bottom: 0;
  border-radius: var(--oly-radius-sm) var(--oly-radius-sm) 0 0;
  background: var(--oly-surface-subtle); color: var(--oly-text-secondary);
  padding: 4px var(--oly-space-4); cursor: pointer;
  font-size: var(--oly-font-size-xs);
}
.pestana-consulta.activa {
  background: var(--oly-surface); color: var(--oly-text-primary);
  font-weight: var(--oly-font-weight-semibold);
}

.fila-consulta {
  display: flex; align-items: center; gap: var(--oly-space-2);
  margin-bottom: var(--oly-space-2);
}
.fila-consulta > label {
  flex: none; width: 13ch;
  font-size: var(--oly-font-size-xs); color: var(--oly-text-secondary);
}
.fila-consulta.doble > label:nth-of-type(2) { width: 14ch; margin-left: var(--oly-space-4); }
.caja-gris.crecer { flex: 1 1 0; min-width: 0; }
.caja-gris.corta-cuenta { flex: none; width: 14ch; }
/* El código y su descripción van en la misma caja separados por un hueco,
   que es como CONCAR los dibuja: `G      GANANCIAS Y PERDIDAS`. */
.caja-gris.par-codigo { white-space: pre; }

.bloque-consulta {
  border: 1px solid var(--oly-border-subtle); border-radius: var(--oly-radius-sm);
  padding: var(--oly-space-3); margin: var(--oly-space-3) 0;
}

/* Dos filas de cuatro, como el fotograma. */
.casillas-consulta {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--oly-space-1) var(--oly-space-3); margin-top: var(--oly-space-2);
}
.casillas-consulta label {
  display: inline-flex; align-items: center; gap: var(--oly-space-1);
  font-size: var(--oly-font-size-xs); color: var(--oly-text-secondary);
  white-space: nowrap;
}
/* Sin esto la regla `input { flex: 1 1 190px; height: 28px }` de
   estilos.css las hace enormes -- es la cuarta pantalla donde muerde. */
.casillas-consulta input[type="checkbox"] {
  flex: none; width: auto; height: auto; margin: 0; padding: 0;
}

.pie-consulta {
  display: flex; align-items: center; gap: var(--oly-space-2);
  margin-top: var(--oly-space-3);
  padding-top: var(--oly-space-3); border-top: 1px solid var(--oly-border-subtle);
}
.pie-consulta > label {
  flex: none; font-size: var(--oly-font-size-xs); color: var(--oly-text-secondary);
}
.pie-consulta button { flex: none; }
/* =====================================================================
   La pestaña `Formatos` de CTPLAN01 — dos marcos y nueve filas (§244)
   =====================================================================
   Cada fila es rótulo + caja de código + caja larga de descripción, y las
   tres columnas se alinean entre las nueve filas de los dos marcos: en la
   captura las cajas de `Estandares` y las de `Alternos` arrancan en la
   MISMA columna, así que el ancho del rótulo se reserva y no se deja al
   contenido. */
.marco-formatos {
  border: 1px solid var(--oly-border-subtle);
  border-radius: 2px;
  margin: 0 0 var(--oly-space-3);
  padding: var(--oly-space-3) var(--oly-space-3) var(--oly-space-2);
}
.marco-formatos > legend {
  padding: 0 var(--oly-space-2);
  font-size: var(--oly-font-size-xs);
  color: var(--oly-text-secondary);
}
.fila-formato {
  display: flex;
  align-items: center;
  gap: var(--oly-space-3);
  margin-bottom: var(--oly-space-2);
}
.fila-formato > label {
  flex: none;
  width: 22ch;
  font-size: var(--oly-font-size-xs);
  color: var(--oly-text-secondary);
}
/* La caja del código: corta, cuatro dígitos, como en la captura. */
.fila-formato .codigo-formato {
  flex: none;
  width: 9ch;
  text-align: left;
}
/* Y la de la descripción ocupa TODO lo que queda: en la captura llega hasta
   el borde derecho del marco. El usuario ya avisó dos veces de lo contrario
   --«si tienes espacio de sobra lo aprovechas»--. */
.fila-formato .descripcion-formato {
  flex: 1 1 auto;
  min-width: 0;
  white-space: pre;
  overflow: hidden;
  text-overflow: ellipsis;
}

.nota-panel {
  margin: 0 0 var(--oly-space-2);
  font-size: var(--oly-font-size-xs); color: var(--oly-text-tertiary);
}

/* =====================================================================
   CTCOMP01 — Parámetros de Registro de Compra
   =====================================================================
   LO QUE ESTA TIRA TIENE DE DISTINTO, y es lo medido: las trece pestañas
   NO van en una fila con scroll ni en un desplegable, van en CUATRO
   RENGLONES que rotan, y el renglón de la elegida queda ABAJO DEL TODO
   pegado al cuerpo. El orden lo calcula `parametros-compra.js`; acá sólo
   se apilan los renglones y se quita el borde a todos menos al último,
   que es el que tiene que unirse al panel.

   Es el TabControl multilínea de Windows, y copiarlo importa: un contador
   que abre las dos pantallas al lado busca su pestaña por dónde está, no
   por cómo se llama. */
.pestanas-comp {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--oly-space-3) var(--oly-space-3) 0;
}
.renglon-pestanas-comp {
  display: flex;
  gap: 2px;
}
/* Sólo el ÚLTIMO renglón lleva la línea que lo separa del cuerpo: los de
   arriba están detrás y no tocan el panel. */
.renglon-pestanas-comp:last-child {
  border-bottom: 1px solid var(--oly-border);
}

.pestana-comp {
  padding: 3px var(--oly-space-3);
  font: inherit;
  font-size: 12px;
  color: var(--oly-link, #1a3f9c);
  cursor: pointer;
  background: var(--oly-surface-subtle);
  border: 1px solid var(--oly-border);
  border-bottom: none;
  border-radius: var(--oly-radius-sm) var(--oly-radius-sm) 0 0;
}
.pestana-comp:hover { background: var(--oly-selection-hover-surface); }
.pestana-comp.elegida {
  font-weight: 700;
  background: var(--oly-surface);
  margin-bottom: -1px;
  padding-bottom: 4px;
}
/* Las cinco que todavía no tienen tabla. En cursiva y apagadas: se ve de un
   vistazo qué parte de la pantalla está construida, sin tener que abrirlas
   una por una. */
.pestana-comp.sin-modelar {
  font-style: italic;
  color: var(--oly-text-secondary);
}

/* Mismo criterio que `.cuerpo-honp`: se acota y se desplaza por dentro para
   que la barra del panel no caiga bajo el pliegue. */
/* EL CUERPO YA NO HACE SCROLL. Lo hace la grilla, en su caja.
   `overflow-y: auto` aqui, mas los 12 px de relleno de arriba, era lo que
   dejaba ver las filas POR ENCIMA de la cabecera pegajosa: el relleno esta
   dentro del scrollport, asi que la fila subia por el y la cabecera --pegada
   al borde del scrollport, no al del contenido-- se quedaba debajo. */
.cuerpo-comp {
  padding: var(--oly-space-3);
}
/* La grilla es un rectangulo de alto fijo con su propia barra, como en
   CONCAR, y debajo el marco `Creación` y la barra, siempre a la vista. */
.caja-grilla-comp {
  max-height: calc(100vh - 470px);
  min-height: 120px;
  overflow-y: auto;
  border: 1px solid var(--oly-border);
  background: var(--oly-surface);
}

/* EL PANEL, y por qué es `relative`: la barra de botones va DENTRO, abajo a
   la derecha -- no arriba, como en el resto de las pantallas de la réplica.
   Medido en las trece capturas. */
.panel-comp {
  position: relative;
  padding-bottom: 34px;
  background: var(--oly-surface);
  border: 1px solid var(--oly-border);
}

/* 🔴 LA BARRA VA EN EL FLUJO, NO FLOTANDO SOBRE EL CONTENIDO.
   Era `position: absolute; right; bottom` y ese era el defecto que el usuario
   vio el 07/09/2026: «el boton del libro y el salir estan encima de la
   grilla». Un `absolute` necesita DOS cosas --un ancestro posicionado y sitio
   reservado en el--, y de los CINCO sitios que usan esta clase (contados con
   grep sobre `index.html`: `situacion-botones`, `situacion-detalle-botones`,
   `situacion-secuencia-botones`, `movi90-detalle-botones` y
   `movi90-secuencia-botones`) NINGUNO reservaba nada: en `#movi90-detalle` la
   barra aterrizaba sobre la fila 0012 del asiento y al desplazar se paseaba
   por encima; en los dos `.ventana` sin posicionar se colgaba del bloque
   contenedor inicial, o sea del pie del DOCUMENTO.

   Donde CONCAR la pone es el PIE de la ventana, debajo del cuadre y sin
   taparlo. Medido en `movi90-nivel2.png` con lectura de pixeles: la grilla
   ACABA en y=372 y tiene su propia barra de desplazamiento, el cuadre
   `Debe/Haber` va en y=388..405 y la barra de botones en y=413..433. O sea
   tres franjas apiladas, ninguna encima de otra.

   Un pie en flujo da eso sin depender de ningun ancestro, y es lo que ya
   hacen las demas pantallas de la replica --`.pie-regc22` y
   `.barra-panel-concar`--, que es lo que pidio el usuario («fijate como estan
   en los otros maestros»).

   🔴 Y AQUI ESTUVO A PUNTO DE ENTRAR UNA AFIRMACION FALSA. Esta linea decia
   «con esto no queda ningun `position: absolute` en este archivo». Lo cazo
   `herramientas/la-barra-que-no-flota.mjs` en su PRIMERA corrida: quedaba
   uno, y era mio --la `.marca-sin-dato` de mas abajo, que se saca del reparto
   de ancho a proposito--. Lo que queda cierto y medido es que este era el
   unico `absolute` que colocaba una BARRA, y que los que quedan estan
   declarados en el arnes uno por uno. Ver DIFERENCIAS §128. */
.barra-comp {
  display: flex;
  flex: none;
  gap: var(--oly-space-2);
  justify-content: flex-end;
  padding: var(--oly-space-2) var(--oly-space-3);
  background: var(--oly-surface);
  border-top: 1px solid var(--oly-border);
}
.boton-comp {
  width: 22px;
  height: 20px;
  font: inherit;
  font-size: 12px;
  background: var(--oly-surface-subtle);
  border: 1px solid var(--oly-border);
  border-radius: var(--oly-radius-sm);
}
.boton-comp:disabled { color: var(--oly-text-secondary); cursor: not-allowed; }
/* Las nueve casillas del Formato 8.1. */
.marco-comp {
  margin: var(--oly-space-3);
  padding: var(--oly-space-3);
  border: 1px solid var(--oly-border);
}
.marco-comp legend { padding: 0 var(--oly-space-2); font-size: 12px; }
/* El marco cuyo ancho viene MEDIDO del servidor (`Parametros Varios`, 571, y
   el marco de `Parametro Detraccion`, 611). Los numeros de CONCAR son el
   ancho de FUERA, asi que aqui manda `border-box`; y el relleno se aprieta
   porque los 571 tienen que dar cabida a los 560 de la fila mas larga
   --rotulo 110 mas codigo 104 mas descripcion 334, con sus separaciones--.
   Ver DIFERENCIAS §110. */
.marco-medido {
  box-sizing: border-box;
  padding: var(--oly-space-2) 4px;
}
/* 🔴 LA SEPARACION ENTRE ROTULO Y CAJA ES DE 2 PX, NO DE 12. Con los 12 de
   la regla general el renglon mide 572 y el marco medido de 571 NO PUEDE
   cumplirse: el `min-width: min-content` del fieldset lo empuja a 582 y el
   ancho medido queda escrito y desobedecido.

   Y 2 px no es un apaño para que quepa, es lo medido: en CONCAR la caja del
   codigo empieza a 117 px del borde del marco, y aqui empieza a 5 (relleno)
   mas 110 (rotulo) mas 2 = 117. La separacion que se ve en CONCAR no la
   pone un hueco: la pone el rotulo, que es mas corto que su columna. */
.marco-medido .campo-comp { gap: 2px; }
.casilla-comp {
  display: flex;
  gap: var(--oly-space-2);
  align-items: flex-start;
  padding: 2px 0;
  font-size: 12px;
}
/* 🔴 LA CASILLA SE EXIME DE LA REGLA GENERAL DE `input`, COMO EN LAS OTRAS
   TRES PANTALLAS QUE TIENEN CASILLAS.
   El `input, select` global lleva `flex: 1 1 190px` más alto, relleno y
   borde, pensado para cajas de texto. Aplicado a un `checkbox` dentro de un
   `label` flex, la casilla CRECE hasta ocupar el sobrante --medido el
   03/09/2026 en el navegador: 423 × 28 px-- y empuja su rótulo a la derecha
   una distancia DISTINTA en cada renglón, porque el flex reparte según lo
   que mida cada texto. Los nueve rótulos arrancaban en nueve x distintas
   (657, 489, 731, 1201, …) donde `demo15-09` los tiene todos pegados a su
   casilla.
   No se veía en la captura de pantalla --que además engaña al escalar-- sino
   midiendo `getBoundingClientRect` de los nueve `span`. Mismo remedio que
   `.fila-casilla-libr81`, `.casilla-medio` y `.casillas-consulta`. */
.casilla-comp input[type="checkbox"] {
  flex: none;
  width: auto; height: auto;
  margin: 0; padding: 0;
}

/* La casilla que la compañía no tiene configurada. NO es lo mismo que
   desmarcada, y por eso se ve distinto: la marca va indeterminada y el
   renglón apagado. */
.casilla-comp.sin-configurar { color: var(--oly-text-secondary); }

.nota-comp {
  margin: 0 var(--oly-space-3) var(--oly-space-3);
  font-size: 11px;
  color: var(--oly-text-secondary);
}

/* El hueco de una pestaña medida y todavía sin tabla. Se dibuja EN VEZ de
   una grilla vacía, a propósito: ver la cabecera de `parametros-compra.js`. */
.sin-modelar-comp {
  padding: var(--oly-space-4);
  font-size: 12px;
  color: var(--oly-text-secondary);
}
.sin-modelar-comp p { margin: 0 0 var(--oly-space-2); }
.sin-modelar-comp .columnas-medidas {
  font-family: var(--oly-font-mono, monospace);
  color: var(--oly-text);
}

/* El aviso de «la tabla existe y el dato no está cargado». Ámbar y no gris:
   no es una nota al pie, es una advertencia de que lo que se ve arriba
   afirmaría algo falso si se leyera sin ella. */
.aviso-comp {
  margin: var(--oly-space-3);
  padding: var(--oly-space-2) var(--oly-space-3);
  font-size: 11px;
  color: var(--oly-text);
  background: var(--oly-warning-surface, #fff8e1);
  border-left: 3px solid var(--oly-warning-border, #e0a800);
}

/* =====================================================================
   EL MARCO `Creación` DE CTCOMP01

   🔴 SE VE SIEMPRE, no sólo al pulsar la hoja en blanco. Está en
   `demo15-02`: con la pantalla recién abierta y `CTA01` marcado, el marco ya
   está ahí, con sus cuatro cajas vacías y la `Clave` en gris. La réplica lo
   escondía hasta que alguien abría el alta, y eso hacía leer la pantalla
   como incompleta -- lo señaló el usuario el 04/09/2026 poniéndola al lado
   de la captura.

   Los campos van EN COLUMNA con el rótulo a la izquierda, como en la
   captura, y no en línea: `Descripción` es la caja larga y las demás cortas.
   ===================================================================== */
.marco-creacion-comp {
  margin: var(--oly-space-3);
  padding: var(--oly-space-2) var(--oly-space-3) var(--oly-space-2);
  border: 1px solid var(--oly-border);
}
.marco-creacion-comp legend {
  padding: 0 var(--oly-space-2);
  font-size: 12px;
  color: var(--oly-text-secondary);
}
/* 🔴 EL ALTA NO VA EN LINEA. Medido en CONCAR en vivo el 04/09/2026 (§17 del
   documento medido): el rotulo va A LA IZQUIERDA, hay UNA caja por renglon y
   cada caja tiene su ancho. La primera version las puso todas iguales en una
   fila con los rotulos encima, y por eso no se parecia.

   La columna del rotulo es `max-content`: se ajusta al rotulo mas largo de la
   pestaña, que es el efecto que se ve en CONCAR --la `x` donde empiezan las
   cajas cambia con la pestaña: 153, 155, 157, 159, 175, 177, 202--. Que sea
   ESA la regla de CONCAR no esta comprobado, y va dicho en §17. */
.campos-creacion-comp {
  display: flex;
  flex-direction: column;
  /* El aire lo pone el renglon, no el contenedor: los renglones aparecen en
     DOS sitios --aqui y sueltos dentro de `.marco-medido`, que es `block`--
     y con el hueco en el contenedor uno de los dos se quedaba sin nada. */
  gap: 0;
}
/* Un renglon. Casi siempre lleva un campo; los tres `IGV` van juntos.

   🔴 LOS 4 px DE ABAJO SON UNA DIFERENCIA DECLARADA, NO UN DESCUIDO.
   CONCAR aprieta: el volcado `form.ctcomp01.json` da las cajas en 21 px de
   alto con un paso de renglon de 22 --tops 291, 313, 335 y 445, 467, 489--,
   o sea UN pixel de aire. La replica dibuja cajas de 26 px, y hasta hoy con
   `margin-bottom: 0`: CERO aire, con los bordes de dos renglones tocandose y
   leyendose como una rejilla. El usuario lo vio el 07/09/2026 --«que no se
   vean pegados»-- y pidio el arreglo para todos los formularios.
   Se aparta del paso de CONCAR y no de su geometria medida: lo que §110 mide
   de este marco es el ANCHO (571 y 611), y el alto no esta escrito en ningun
   sitio. Los renglones cuyas posiciones SI estan medidas al pixel
   --`#form-padre .fila` del 09 y `#pantalla-movi70 .fila-libr81`-- se quedan
   con sus 2 px y no se tocan. Ver DIFERENCIAS §144. */
.renglon-creacion-comp {
  display: flex;
  gap: var(--oly-space-4);
  align-items: center;
  margin-bottom: 4px;
}
.renglon-creacion-comp:last-child { margin-bottom: 0; }

/* La barra del panel y la del pie de CTCOMP01 son la MISMA que la de
   CTHONP01: viven arriba, en `.barra-pie-concar` / `.barra-panel-concar`.
   El comentario que estaba aqui ya decia «es la misma barra, y por fin el
   mismo código» -- y no lo era: eran veinticinco lineas copiadas. */
/* Rotulo a la izquierda y caja a la derecha, alineados en columna. El
   `min-width` del rotulo es lo que alinea las cajas entre renglones. */
.campo-comp {
  display: flex;
  flex-direction: row;
  gap: var(--oly-space-3);
  align-items: center;
  font-size: 11px;
}
/* 🔴 ANCHO FIJO, NO `min-width`. Lo vio el usuario el 06/09/2026 con las
   dos pantallas al lado: «como es posible que concar tenga sus campos
   alineados y el nuestro este todo desordenado apegado cada uno a su label
   ... los inputs siempre deberian estar alineados iniciando siempre
   iguales».

   `min-width` es un SUELO, no una columna: en cuanto un rotulo lo pasa
   --`Import.Mini. Afecta. Detrac. (MN)` lo pasa-- empuja su caja a la
   derecha y ese renglon se descuelga de los demas. Con `width` el rotulo
   ENVUELVE dentro de su columna y la caja no se mueve, que es lo que hace
   CONCAR: en su `Parametros Varios` se ve `Cuenta Impuesto / Renta 1.5%
   (Liq.)` partido en dos lineas con su caja en la misma columna que las
   otras cuatro.

   Y la leccion ya estaba escrita en este mismo archivo, en el recuadro del
   papel del 8.1: «necesita `width` y no solo el `min-width` heredado: sin
   el, un rotulo largo ESTIRA su celda ... con el ancho fijo el rotulo
   envuelve dentro de su columna, que es lo que hace CONCAR». Estaba dicho
   para las columnas del papel y no se aplico a los formularios.
   Ver DIFERENCIAS §108. */
.rotulo-campo-comp {
  width: 130px;
  flex: 0 0 auto;
  overflow-wrap: anywhere;
  text-align: left;
  color: var(--oly-text-secondary);
}
/* Los tres `IGV` comparten renglon, y ahi el rotulo no necesita la columna:
   va pegado a su caja, como en la captura. */
.renglon-creacion-comp .campo-comp:not(:first-child) .rotulo-campo-comp {
  width: auto;
}
/* 🔴 Y LO MISMO PARA EL OTRO ROTULO, QUE SE HABIA QUEDADO FUERA.
   La regla de arriba existe desde que se midio que un segundo campo lleva su
   rotulo pegado a la caja; pero mira `.rotulo-campo-comp`, y la pestaña
   `Parametros Varios` usa `.rotulo-campo-parametro`. Resultado medido a
   1440x900: `Factor Minimo para Inafecto` --que en CONCAR va en UNA linea, a
   la derecha de `% Tasa de IGV` (captura
   `ctcomp01-0002-parametros-varios.png`)-- partia en DOS dentro de una
   columna de 110 px, con 135 px libres al lado en el mismo renglon.
   Los 110 son la columna del PRIMER campo de cada renglon (§110): es lo que
   alinea las cajas entre renglones, y por eso se queda. El segundo campo no
   alinea con nada, asi que su rotulo mide lo que dice.
   `max-content` y no `auto`: dentro de un flex, `auto` deja que el rotulo se
   encoja cuando el renglon aprieta, que es volver a partirlo por otra puerta.
   Ver DIFERENCIAS §144. */
.renglon-creacion-comp .campo-comp:not(:first-child) .rotulo-campo-parametro {
  width: max-content;
  max-width: 100%;
}

/* Las TRES clases de ancho medidas en §17. Los pixeles de CONCAR --73, 192,
   445-- son metricas de Win32 y no se copian; lo que se copia es la clase y
   su proporcion: corta ~16 %, media ~43 %, larga ~100 % de la anchura util. */
.campo-comp.ancho-corta input[type="text"],
.campo-comp.ancho-corta select { width: 110px; }
.campo-comp.ancho-media input[type="text"],
.campo-comp.ancho-media select { width: 260px; }
.campo-comp.ancho-larga { flex: 1; }
.campo-comp.ancho-larga input[type="text"],
.campo-comp.ancho-larga select { flex: 1; width: auto; min-width: 0; }
/* `flex: none` y ancho propio: la regla global `input, select` de este
   archivo les da `flex: 1 1 190px`, y eso ya rompió una vez la alineación de
   las casillas de esta misma pantalla. */
.campo-comp input[type="text"] {
  flex: none;
  width: 170px;
  height: auto;
  padding: 2px 4px;
  font: inherit;
  font-size: 12px;
}
.campo-comp select {
  flex: none;
  width: 170px;
  height: auto;
  padding: 2px 4px;
  font: inherit;
  font-size: 12px;
}
.campo-comp input[type="checkbox"] {
  flex: none;
  width: 13px;
  height: 13px;
  margin: 3px 0 0;
}
/* La clave bloqueada se ve gris, que es como CONCAR la enseña. */
.campo-comp input:disabled,
.campo-comp select:disabled {
  color: var(--oly-text-secondary);
  background: var(--oly-surface-subtle);
}
/* El error del servidor, tal cual lo manda: sus mensajes están redactados
   para que los lea el contador. */
.error-comp {
  flex-basis: 100%;
  margin: 0;
  font-size: 11px;
  color: var(--oly-danger-text, #a11);
}
/* =====================================================================
   CTREGC22 — Consulta/Modificación de Registro de Compras
   ===================================================================== */
.parametros-regc22 {
  display: flex;
  gap: var(--oly-space-4);
  padding: var(--oly-space-3);
  border-bottom: 1px solid var(--oly-border);
}
.parametro-regc22,
.campo-regc22 {
  display: flex;
  gap: var(--oly-space-2);
  align-items: center;
  font-size: 12px;
}
.parametro-regc22 select { flex: none; width: auto; height: auto; padding: 1px 2px; font: inherit; font-size: 12px; }
.campo-regc22 input { flex: none; width: 120px; height: auto; padding: 1px 4px; font: inherit; font-size: 12px; }

/* El marco de filtro, en gris al abrir. */
.filtro-regc22 {
  display: flex;
  gap: var(--oly-space-4);
  margin: var(--oly-space-3);
  padding: var(--oly-space-2) var(--oly-space-3);
  color: var(--oly-text-secondary);
  border: 1px solid var(--oly-border);
}
.filtro-regc22 legend { padding: 0 var(--oly-space-2); font-size: 12px; }

.cuerpo-regc22 {
  padding: 0 var(--oly-space-3);
  max-height: calc(100vh - 300px);
  overflow: auto;
}
/* El contador a la izquierda y los botones a la derecha, como la captura. */
.pie-regc22 {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--oly-space-2) var(--oly-space-3);
  border-top: 1px solid var(--oly-border);
}
/* Los botones se pegan a la DERECHA aunque no haya contador a su izquierda.
   `CTREGC22` tiene los dos --contador y barra-- y el `space-between` bastaba;
   `CTMOVI90` no tiene contador --medido en vivo el 05/09/2026-- y al quitarlo
   los botones se fueron al borde izquierdo, que es justo el sitio donde
   CONCAR no los pone. Ver DIFERENCIAS 86. */
.pie-regc22 .barra-botones { margin-left: auto; }
.contador-regc22 { font-size: 12px; color: var(--oly-text-secondary); }

/* Los niveles 2 y 3 de CTMOVI90: ventanas APILADAS, no diálogos flotantes.
   En CONCAR son ventanas de Windows -- tapan a la de atrás y se cierran de a
   una. Se fijan sobre el área de trabajo con un z-index creciente. */
/* 🔴 Y LA VENTANA ES UNA COLUMNA, NO UN BLOQUE QUE SE DESPLAZA ENTERO.
   Tenia `overflow: auto` en la ventana: el titulo, la cabecera, el cuadre y
   la barra se iban todos hacia arriba al bajar por el asiento. CONCAR no
   hace eso -- en `movi90-nivel2.png` la grilla tiene su PROPIA barra de
   desplazamiento (las flechas en x=596, y=246..372) y el resto de la ventana
   se queda quieto. Columna con `overflow: hidden` arriba y la parte que
   scrollea marcada dentro: eso es lo que reproduce la ventana de Windows. */
.ventana-apilada {
  position: fixed;
  inset: 60px 40px 40px;
  z-index: 40;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--oly-surface);
  border: 1px solid var(--oly-border);
  box-shadow: 0 4px 24px rgb(0 0 0 / 25%);
}
/* La pila de ventanas de esta familia. Cada nivel entra un poco mas y sube
   un `z-index`, que es como CONCAR apila sus ventanas hijas: la de arriba
   tapa a la de abajo sin taparla del todo, para que se vea que hay algo
   detras.

   🔴 `pantalla-movi60` LO NECESITA Y SE VIO EN EL NAVEGADOR. Sin su
   linea heredaba el `z-index: 40` de `.ventana-apilada` y el nivel 3 --que
   tiene 41-- se le pintaba ENCIMA: la ventana se abria de verdad, con sus
   datos, y quedaba detras de la que la habia abierto. En el DOM esta despues,
   asi que el orden del documento no alcanzaba: manda el `z-index`. Ver
   DIFERENCIAS §136. */
#movi90-secuencia { inset: 90px 80px 70px; z-index: 41; }
#pantalla-movi60 { inset: 120px 120px 100px; z-index: 42; }

/* 🔴 `Detalle de Comprobante`, LA VENTANA HIJA DE `CTMOVI09`, Y SALE ENCIMA.
   Hasta la vuelta 75 era una `.ventana` estatica en el flujo del documento,
   asi que se apilaba DEBAJO de `CTMOVI09` y habia que bajar con el scroll
   para verla, con la padre fuera de la vista por arriba. El usuario lo dijo
   al medirla en el navegador: «se supone que lo tienes que mostrar encima,
   ¿no?». En CONCAR es MODAL sobre la padre --el volcado de formulario trae
   las DOS ventanas a la vez, `ThunderRT6FormDC` «Detalle de Comprobante» y
   `ThunderRT6Main` «Contabilidad Concar», y en la captura se ve el borde de
   la padre por detras--. Ver `docs/CTMOVI09-DETALLE-MEDIDO.md` §5 y §7.

   ⚠️ Y NO DESHACE LA DECISION DEL USUARIO SOBRE EL PIE. Cuando se le
   pregunto por esta ventana --«cuatro hermanos y un pie», mas abajo en este
   archivo-- lo que estaba en juego era QUE EL PIE SE ALCANCE, no el apilado:
   con `.ventana-apilada` se alcanza igual o mejor, porque la seccion queda
   acotada al viewport y lo que desplaza es la rejilla. Las dos cosas se
   cumplen a la vez y `la-ventana-cabe-en-la-pantalla.mjs` lo vigila.

   🔴 EL `z-index` ES PROPIO Y NO REPITE NINGUNO: 40 es la base, 41 y 42
   son la pila de `CTMOVI90`, 45 la vista previa y 46 `Plan Cuentas`. Tiene
   que quedar POR DEBAJO del 46 y no por gusto: `Plan Cuentas` la abre `F1`
   desde el campo `Cuenta`, que vive DENTRO del marco `Creacion` de esta
   ventana, asi que un 46 aca o mas dejaria el catalogo detras de la ventana
   que lo pidio -- que es exactamente el defecto de §136.

   🟡 LA GEOMETRIA ES LA FORMA DE LA CASA, y se dice. El volcado SI trae
   numeros --marco de botones en `0,384` de 639x23, o sea un area de cliente
   de unos 639x410-- pero son coordenadas de diseno de VB6 a su metrica de
   fuente, y esta ventana ya demostro que el programa las reacomoda al
   arrancar (§168: `Importe` esta en `x=617` en el volcado y APILADO debajo en
   las tres capturas). Con 639 px de ancho los 19 campos de `Creacion` no
   caben a la metrica del navegador. Asi que se usa `inset`, como en
   `CTMOVI60` y `Plan Cuentas`, y el ancho medido queda escrito arriba en vez
   de copiado mal.

   🔴 EL 151 DE ARRIBA SI ES MEDIDO, y es la unica cifra de este `inset` que
   lo es: es donde ACABA la barra de titulo de la ventana padre, medida en el
   navegador a 1440x900 --`#ventana-padre` en `y=97` y su `.titulo-ventana` de
   98 a 151--, que a su vez sale de 77 de `#barra-menu` mas los 20 de margen
   de `.ventana`. Se pone ahi porque en CONCAR LA BARRA DE TITULO DE LA PADRE
   SE SIGUE VIENDO por encima de la hija: en
   `ctmovi09-0002-detalle-090001-cuadrado.png` el rotulo gris «Comprobantes de
   Compras - CTMOVI09» esta en `y=59` y el de la hija, azul, en `y=78`. Una
   hija que tape el titulo de su padre no es lo medido.

   Y `margin: 0 auto` no es adorno, ni en la mitad que pone cero ni en la que
   deja `auto`. `.ventana` trae `margin: 20px auto 0`: sin anular el 20 de
   arriba el `inset` de esta linea MIENTE --comprobado en el navegador, `y=100`
   con `inset-top: 80`--, y quitando tambien el `auto` de los lados la ventana
   se va al borde izquierdo, a `x=100`, mientras la padre sigue CENTRADA en
   `x=396`: medido tambien, y se ve torcido. En CONCAR las dos comparten el
   borde izquierdo (`x=8` las dos), asi que con anchos distintos lo mas cerca
   que se llega es compartir el eje: `0` arriba y abajo, `auto` a los lados.

   ⚠️ Lo que NO se reproduce es el ANCHO relativo: en CONCAR la hija mide 639
   y la padre 649, o sea que la tapa casi exactamente; aca la hija mide 1080
   --el `max-width` de `.ventana`-- y la padre 648, asi que la hija es MAS
   ancha que su padre. Es el mismo motivo que el alto: los 19 campos de
   `Creacion` en dos columnas no caben en 639 px a la metrica del navegador.
   Declarado en DIFERENCIAS §171. */
#ventana-hijo { inset: 151px 100px 60px; z-index: 44; margin: 0 auto; }

/* Y su cuerpo se reparte igual que el del nivel 2 y que `Plan Cuentas`: la
   CABECERA quieta arriba, el marco `Creacion` quieto abajo y la rejilla con
   su propia barra de desplazamiento en medio. No es una preferencia de
   estilo: el volcado pone un `DataGridSplitVScroll` de 17x94 PEGADO a la
   rejilla, dentro del marco de 625x109, y en las tres capturas la cabecera,
   la rejilla y `Creacion` se ven LAS TRES A LA VEZ. Un cuerpo que se
   desplazara entero se llevaria la cabecera hacia arriba con las filas.
   La caja de la rejilla es `.caja-grilla-detalle`, la MISMA del nivel 2. */
#ventana-hijo .cuerpo-detalle {
  display: flex;
  flex-direction: column;
  /* 🔴 `auto`, NO `hidden`, Y ESTO SE MIDIO EN EL NAVEGADOR.
     Con `hidden` --que es lo que llevan las otras tres de esta familia-- la
     rejilla quedaba en DOS PIXELES de alto: medido a 1440x900,
     `caja-grilla-detalle` con `height: 2`, `clientHeight: 0` y
     `scrollHeight: 155`. O sea el corazon de la ventana, invisible.

     La cuenta dice que no era un numero mal puesto. La ventana da 740 px de
     alto y su contenido pide 765 SIN la rejilla: titulo 53, cabecera 113,
     `Creacion` 554 y pie 45. Y ese 554 es el nudo: en CONCAR el marco
     `Creacion` mide 195 px --volcado `form.detalle-de-comprobante.2.json`,
     marco en `8,189` de 625x195-- porque sus renglones son de 21 px de paso;
     a la metrica del navegador el MISMO renglon mide 45, asi que los mismos
     19 campos piden casi el triple. La proporcion medida de CONCAR
     --rejilla 109 de 408 de area de cliente, `Creacion` 195-- NO SE PUEDE
     trasladar, y forzarla seria recortar campos.

     Asi que la ventana ensena las tres bandas a la vez cuando el viewport
     alcanza --que es lo medido en las tres capturas-- y cuando no alcanza
     DESPLAZA EL CUERPO en vez de recortarlo. El pie queda fuera del cuerpo,
     asi que se alcanza siempre, que es la regla del 07/09/2026. */
  overflow-y: auto;
  overflow-x: hidden;
  min-height: 0;
}

/* 🔴 Y LA REJILLA TIENE UN SUELO, PORQUE UNA REJILLA DE DOS PIXELES NO ES
   UNA REJILLA. El numero sale de contar bandas en la captura, no de elegirlo
   --pero el 184 anterior contaba mal DOS veces, y las dos se midieron de
   nuevo pixel a pixel en `ctmovi09-0002-detalle-090001-cuadrado.png` y en
   `-dos-lineas.png`:

   1. LA BANDA VACIA DE ABAJO NO ES UNA, SON CINCO EN TOTAL. El 184 contaba
      "las tres del asiento 090001 (0001, 0002, 0003) y una vacia debajo":
      cabecera + CUATRO. Medido en pixeles de las dos capturas --que son la
      MISMA ventana, mismo alto de caja, 101 px de cabecera+filas en las dos--
      la banda vacia de abajo no mide una fila: mide 37 px en la de tres
      lineas y 53 px en la de dos lineas, y en las dos sobra el mismo resto de
      ~5 px. O sea la vacia son DOS filas enteras cuando hay tres cargadas
      (3+2=5) y TRES filas enteras cuando hay dos cargadas (2+3=5): la caja
      siempre ensena cabecera + CINCO bandas de fila, no cuatro. El video de
      la reunion del 07/09 (`escenas/e0066.png`, empresa 0003) confirma la
      cabecera y dos filas cargadas de esa misma familia de ventana, aunque el
      aviso de grabacion de Fathom tapa la caja antes de llegar al borde
      inferior y no deja medir el resto en ese fotograma.

   2. LA CUENTA SE HIZO SIN EL MARGEN DE LA TABLA. `.grilla-lineas`, en
      `estilos.css`, trae `margin: var(--oly-space-4) var(--oly-space-5)` --16
      y 20px, medido con `getComputedStyle`-- y esos 16 arriba + 16 abajo se
      comen 32 px de la caja que el 184 no reservaba:
      con `min-height: 184px` y ocho filas inyectadas, `clientHeight` da 182 y
      solo caben TRES filas enteras (medido en el navegador), no cuatro.

   Con las dos correcciones: cabecera + 5 filas x 36,8 px medidos --`thead`
   36,8 y cada `tr` 36,8, con ocho filas inyectadas-- = 6 x 36,8 = 220,8, mas
   los 32 del margen de la tabla = 252,8 -> 253. Verificado en el navegador
   con ocho filas inyectadas: `min-height: 253px` deja cinco filas enteras
   dentro de la caja, no tres.

   Con `flex: 1 1 auto` de `.caja-grilla-detalle` la rejilla sigue creciendo si
   hay alto de sobra, y con este suelo no desaparece si no lo hay. */
#ventana-hijo .caja-grilla-detalle { min-height: 253px; }

/* 🔴 Y UN `<select>` SIN TOPE SE COME LA COLUMNA. Medido en el navegador
   con las areas de la 0002 cargadas: el envoltorio de `#f-area-gasto` medía
   556,8 px dentro de una `.fila` de 478,4 --78 px por fuera del borde derecho
   de la ventana, recortados y sin forma de llegar--. La causa es que un
   `<select>` sin ancho toma el de su opcion mas larga, y su `min-width: auto`
   --que es `min-content`-- le impide encogerse como hijo flexible.

   Se topa a la columna y se le quita el minimo. Recortar el texto DENTRO del
   combo es lo que hace CONCAR --su `Area` es un combo de ancho fijo-- y no
   choca con lo que el usuario pidio en §161, que era sobre las columnas de
   una REJILLA, no sobre un desplegable.

   🔴 Y SE TOPA EL ENVOLTORIO, NO EL `<select>`. La primera version escribio
   `#bloque-creacion select { max-width: 100% }` y NO HIZO NADA --medido: el
   envoltorio seguia en 558 px y el `scrollWidth` del cuerpo en 1102 contra un
   `clientWidth` de 1063--. El motivo es que el hijo flexible de la `.fila` es
   `.combo-buscador`, y ese envoltorio toma su ancho DEL `<select>` que lleva
   dentro, a proposito y por la razon escrita mas arriba: es lo que conserva
   los anchos medidos de cada pantalla. Un `max-width: 100%` sobre el hijo se
   resuelve contra un padre cuyo ancho lo fija ese mismo hijo, o sea contra el
   contenido: no topa nada.

   Asi que el tope va en el envoltorio --`flex: 1 1 0` con `min-width: 0`, que
   es «toma el sitio que sobra en la fila y encogete si hace falta»-- y el
   `<select>` de dentro pasa a `width: 100%` para seguirlo. Es UNA fila de
   `Creacion` la que lo necesita hoy (`Area`) y otra que lo necesitaria en
   cuanto se llene (`Dcmto.Refer.`), y por eso la regla es del bloque y no de
   un id: escribirla contra `#f-area-gasto` la habria dejado esperando el
   mismo defecto en la de al lado. */
#bloque-creacion .fila > .combo-buscador { flex: 1 1 0; min-width: 0; }
#bloque-creacion .fila > .combo-buscador > select { width: 100%; min-width: 0; }

/* `Plan Cuentas`, el catalogo que abre F1 (161). Un `z-index` PROPIO, ni el
   41/42 de la pila de `CTMOVI90` ni el 45 de la vista previa: es la regla que
   el comentario de esta misma pila dejo escrita --repetir un numero entre
   familias distintas es como nace el defecto de 136-- y esta ventana SI puede
   estar abierta a la vez que otras, porque cuelga de `CTMOVI09`.

   🟡 LA GEOMETRIA NO ESTA MEDIDA y se dice: no hay volcado de formulario de
   esta ventana --buscado en `artifacts/rig/share/`, en `artifacts/docs/` y en
   `spec/`-- y su titulo, `Plan Cuentas` a secas, no trae codigo de programa
   con el que cruzarla contra el arbol de menus. Los numeros de abajo son la
   forma de la casa, como en `CTMOVI60`. */
#pantalla-plan-cuentas { inset: 70px 200px 60px; z-index: 46; }

/* 🔴 LA QUE DESPLAZA ES LA REJILLA, NO EL CUERPO. Es la misma regla que
   `#pantalla-movi60` y por la misma razon medida: en las dos capturas de
   `Plan Cuentas` la barra de desplazamiento esta PEGADA A LA REJILLA --se ve
   su flecha arriba y abajo, dentro del marco de las cuatro columnas-- y la
   banda gris del pie queda quieta por debajo.

   Sin esta regla el `flex: 1 1 auto` de `.caja-grilla-detalle` no hace nada
   --su padre no es flex-- y la caja crece a su alto natural: MEDIDO en el
   navegador con las 2.447 cuentas de la 0002, 90.086 px de caja dentro de un
   cuerpo de 638. Desplazaba el cuerpo, asi que el marco de la rejilla se iba
   hacia arriba con las filas. El pie se alcanzaba igual, que es lo que este
   arreglo NO tenia que romper.

   🔴 Y LE FALTABA `flex-direction: column`, ocho dias. Sin ella el eje por
   omision es FILA, asi que el `<p class="ayuda-replica">` que
   `plan-cuentas.js:247` cuelga del cuerpo se ponia AL LADO de la grilla y le
   comia la mitad del ancho --la `Descripcion` partiendose en dos lineas para
   dejarle sitio a un parrafo de ayuda--. Lo vio el usuario el 08/09/2026 con
   la captura delante: «este form de plan cuentas esta mal porque esas letras
   deberian ir debajo de la grilla para que no ocupe mucho espacio».

   Es un OLVIDO, no una decision, y se prueba solo: la ventana hermana
   --`#pantalla-movi60 .cuerpo-detalle`, unas lineas mas abajo-- si la lleva,
   y el parrafo de arriba describe la reparticion en columna que esta regla
   no podia estar haciendo. Ver DIFERENCIAS §175. */
#pantalla-plan-cuentas .cuerpo-detalle {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* La `Descripcion` se lleva TODO el ancho que sobra, y por eso las otras tres
   columnas van al minimo. Es el apartamiento de 161: CONCAR la recorta a
   media palabra --`PUBLICIDAD  PUBLICACIONES  RELACIO`-- y el usuario pidio
   lo contrario el 07/09/2026, «hay nombres que tenemos que mostrar
   completo». Con `pre-wrap` heredado de `.grilla-maestro td`, una
   descripcion larga corta de linea y se lee entera, y los dobles espacios
   --`MATERIALES AUXILIARES  SUMINISTROS Y REPUESTOS`-- se conservan. */
.grilla-plan-cuentas .col-codigo { width: 1%; }
/* Y su cuerpo se reparte como el del nivel 2: la CABECERA y la FICHA quietas,
   y la grilla con su propia barra de desplazamiento.
   🔴 Tambien esto se vio en el navegador y no leyendo: sin la regla, el
   cuerpo entero se desplazaba y con 40 filas --que existen, el comprobante
   22-040020 las tiene-- la ficha de abajo quedaba fuera de la vista. En la
   captura de CONCAR la grilla y la ficha se ven LAS DOS a la vez, asi que un
   cuerpo que se desplaza entero no es lo medido.
   La caja de la grilla es `.caja-grilla-detalle`, la MISMA del nivel 2: ya
   existe en el origen y hace exactamente esto. Ver DIFERENCIAS §136. */
#pantalla-movi60 .cuerpo-detalle {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
#pantalla-movi60 .cuerpo-detalle > .fila-secuencia,
#pantalla-movi60 #movi60-ficha,
#pantalla-movi60 .ayuda-replica { flex: none; }

/* El cuerpo se come el alto que sobra. `min-height: 0` no es adorno: sin el,
   un hijo flexible no baja de su `min-content` y el `overflow` de dentro
   nunca entra en juego -- la ventana crece y vuelve a desbordar.
   El desplazamiento va ACA para las ventanas SIN grilla --el `Detalle
   Secuencia`, que es una pila de campos--; la que tiene grilla lo mueve a la
   grilla, mas abajo. */
.cuerpo-detalle {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  padding: var(--oly-space-3);
}
.cabecera-detalle {
  display: flex;
  gap: var(--oly-space-5);
  margin-bottom: var(--oly-space-3);
}
/* 🔴 `align-items: stretch`, Y ESTA LINEA NO ES REDUNDANTE.
   Mas arriba en este mismo archivo hay otra `.columna-detalle` --la de tres
   columnas de `CTMOVI02`-- que declara `align-items: center`, y esa
   propiedad NO la pisaba nadie: con `flex-direction: column` centraba los
   renglones HORIZONTALMENTE. Mientras las trece cajas median todas 150 px no
   se notaba --todos los renglones eran igual de anchos--; en cuanto cada
   caja tomo su ancho medido, los renglones quedaron escalonados y los
   rotulos parecian alineados a la derecha. Es lo que vio el usuario: «mira
   los inputs estan todo desalineado». CONCAR los pone TODOS a la misma
   izquierda --rotulo en x=11, caja en x=96--, asi que van pegados al
   arranque de la columna. Ver DIFERENCIAS §128. */
.columna-detalle {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 2px;
}
.campo-detalle {
  display: flex;
  gap: var(--oly-space-2);
  align-items: center;
  font-size: 11px;
}
/* Columna fija por lo mismo. Ver `.rotulo-campo-comp`. */
.campo-detalle > span:first-child {
  width: 92px;
  flex: 0 0 auto;
  overflow-wrap: anywhere;
}
/* 🔴 EL SELECTOR LLEVA `.cuerpo-detalle` DELANTE POR ESPECIFICIDAD, NO POR
   ADORNO. `estilos.css` gobierna las cajas de texto con
   `input:not([type="radio"]):not([type="checkbox"])`, que pesa (0,2,1) --dos
   pseudoclases y un elemento--, y `.campo-detalle input` pesa (0,1,1): la
   global GANABA. Se veia medido en el navegador el 07/09/2026: estas cajas
   computaban `14px Inter` y `padding: 0 12px` en vez de los `11px` y
   `1px 4px` que esta regla pide desde que se escribio. Con 24 px de relleno
   horizontal, una caja de los 72 px que mide CONCAR deja 46 px de hueco
   util y `01  -010001` --que necesita 60 a 11px-- se recorta. O sea: los
   anchos medidos de CONCAR estaban BIEN y lo que los rompia era el relleno
   heredado. Es el mismo defecto de la vuelta 38 --la regla global estirando
   un control que no es una caja de texto que se escribe-- pero por
   especificidad en vez de por herencia de tamano.
   `.cuerpo-detalle` no acota nada de mas: los unicos sitios donde existe
   `.campo-detalle` estan dentro de un `.cuerpo-detalle`. Lo que cambio el
   09/09/2026 es POR QUE: hasta ese dia «porque TODAS las pinta `cajaGris` y
   sus llamadores dibujan ahi dentro», y la ventana `Consulta de RUC SUNAT`
   escribe sus seis en `index.html`, a mano. Sigue siendo cierto que estan
   dentro de un `.cuerpo-detalle` --se comprueba, no se supone: el arnes
   parte el marcado por sitio y mira cual lo lleva-- pero la razon ya no es
   «cajaGris» sino la convencion, y una convencion se sostiene con una
   comprobacion o no se sostiene.

   🔴 Y SON DOS CUENTAS DISTINTAS, QUE ES DONDE ME EQUIVOQUE:

     · sitios con `.cuerpo-detalle` ....... NUEVE
       (`situacion-secuencia-cuerpo`, `movi90-detalle-cuerpo`,
        `movi90-secuencia-cuerpo`, `movi60-cuerpo`, `anex03-cuerpo`,
        `plan-cuentas-cuerpo` y `catalogo-anexos-cuerpo` -- estos dos
        ultimos tampoco traen `.campo-detalle`: dentro llevan una REJILLA,
        no cajas --, `hijo-cuerpo`, el `Detalle de Comprobante` que la
        vuelta 75 volvio `.ventana-apilada` (§171), y
        `consulta-ruc-sunat-cuerpo`, la ventana que abre el `?` de
        `Validar RUC` en `CTANEX03` el 09/09/2026)
     · de esos, los que traen `.campo-detalle` ... CINCO
       (todos menos `anex03-cuerpo`, `plan-cuentas-cuerpo` y
        `catalogo-anexos-cuerpo`, que dibujan su rejilla o sus cajas propias
        sin pasar por `cajaGris`. Y de los cinco, CUATRO los pinta `cajaGris`
        y el quinto --`consulta-ruc-sunat-cuerpo`-- los trae escritos en el
        marcado: es el primero que lo hace, y es lo que rompio la razon de
        arriba)

   Eran TRES y TRES hasta la vuelta 40, que anadio `anex03-cuerpo` --y subio
   la primera cuenta a cuatro sin que nadie la escribiera-- y la 44, que anadio
   `movi60-cuerpo` y subio las dos. La primera correccion de este comentario
   decia CUATRO para las dos cosas y la caza el arnes en su primera corrida.
   Un numero en un comentario desmentido por el codigo es la trampa 3 de este
   bucle con otra ropa, y contar la familia equivocada es la misma trampa un
   paso antes. Ver DIFERENCIAS §128 y §136.

   Y `flex: none` sigue haciendo falta por lo de siempre: la global pone
   `flex: 1 1 190px` y ya rompio una vez la alineacion de CTCOMP01. */
.cuerpo-detalle .campo-detalle input {
  flex: none;
  width: 150px;
  height: auto;
  padding: 1px 4px;
  font: inherit;
  font-size: 11px;
  color: var(--oly-text-secondary);
  background: var(--oly-surface-subtle);
}
.campo-detalle input.cifra { text-align: right; }
/* Los tres anchos de caja de `Detalle Secuencia`. Salieron de contar la
   ventana en vivo del 05/09/2026 ampliada al 300 %: la corta es la de
   `Debe/Haber` y `Secuencia`, la media la de `Centro Costo` y `Glosa`, y la
   ancha la de la descripción que va al lado del código. Sin ellos las 21
   cajas salían todas del mismo tamaño y la ventana no se parecía a la de
   CONCAR.

   🔴 Y DOS DE LOS TRES SE ENSANCHARON A PROPOSITO, POR INSTRUCCION DEL
   USUARIO (07/09/2026): «tienes espacio hasta de sobra aprovechalo porque hay
   nombres que tenemos que mostrar completo». O sea que ACA la réplica se
   aparta de los anchos de CONCAR, y §128 ya gobierna ese apartarse.

   No es a ojo. Medido en DOS pasos, los dos con números:

     1. el valor MAS LARGO que cada caja puede traer, contado en la base:
        descripción de cuenta 50 caracteres, razón social de anexo 40,
        descripción de centro de costo 60, glosa 36, número de documento 20;
     2. cuánto miden esas cadenas en el navegador con la letra de la caja
        --11px Inter-- usando `measureText`: 320 px, 257 y 385.

   Contra los anchos que había, `ancha` en 260 y `media` en 300, las cuentas
   dan que **DOS cajas recortaban de verdad**: la descripción de la cuenta
   (320 > 250 utiles) y la del centro de costo (385 > 292). La de anexo se
   salvaba por 7 px. Se vio midiendo, no mirando: con los datos de un
   comprobante cualquiera ninguna recorta, porque los valores largos son
   pocos.

   Asi que `ancha` pasa a 336 y `media` a 401: el ancho medido, mas los 10 del
   relleno, mas SEIS de holgura. La holgura no es un redondeo perezoso -- con
   el ancho justo (330 y 395) el valor mas largo entraba en 320 utiles contra
   320 necesarios, o sea EXACTO, y ahi cualquier diferencia de medio pixel
   entre `measureText` y el dibujo de verdad recorta. Comprobado: con 330 la
   comprobacion daba `320 <= 320`. `media`
   la comparten cinco campos y solo el centro de costo necesita tanto; los
   otros cuatro quedan con espacio de sobra, que es exactamente lo que el
   usuario pidio. La `corta` no se toca: sus dos campos son de uno y cuatro
   caracteres.

   El arnes mide esto EJECUTANDO: compara el maximo de la base con el ancho
   declarado aqui. Ver DIFERENCIAS §136. */
.campo-detalle input.corta { width: 64px; }
.campo-detalle input.media { width: 401px; }
.campo-detalle input.ancha { width: 336px; }

/* Un renglón del nivel 3. CONCAR pone dos o tres campos en la misma línea en
   cuatro de sus diecisiete renglones --`Importe US`/`Importe MN`,
   `Fecha`/`Vencimiento`, los tres de `Doc. Ref. 2` y los dos `Monto Base`--,
   y quién va con quién lo dice `detalle-secuencia.js`, que es donde está la
   medición. Acá sólo se dibuja. */
.fila-secuencia {
  display: flex;
  gap: var(--oly-space-4);
  align-items: center;
}
/* El aire que CONCAR deja antes del bloque de `Doc. Ref. 2`. */
.hueco-secuencia { height: var(--oly-space-3); }
/* LA AYUDA DE LA REPLICA, que no es un mensaje de CONCAR.
   Misma piel que `.marca-sin-dato` --cursiva y el ambar de aviso-- porque es
   la misma clase de cosa: algo que dice la replica y CONCAR no. Lo que NUNCA
   hace es mezclarse con el renglon de arriba, que lleva el texto de CONCAR
   palabra por palabra. Ver DIFERENCIAS §129. */
.ayuda-replica {
  margin: 2px 0 0;
  font-size: 11px;
  font-style: italic;
  color: var(--oly-warning-border, #b8860b);
}

/* Un campo que la réplica NO tiene: vacío pero DICIÉNDOLO. Un campo ausente
   se lee como descuido; uno vacío que explica, como lo que es. */
.campo-detalle.sin-dato .marca-sin-dato {
  font-size: 10px;
  font-style: italic;
  color: var(--oly-warning-border, #b8860b);
}

.cuadre-detalle {
  display: flex;
  flex: none;
  gap: var(--oly-space-5);
  margin-top: var(--oly-space-3);
  padding-top: var(--oly-space-2);
  border-top: 1px solid var(--oly-border);
}

/* ------------------------------------------------------------------ */
/* LA GEOMETRIA DEL `Detalle de Comprobante`, LEIDA A PIXELES          */
/*                                                                     */
/* Todo lo de este bloque sale de UNA medicion: `movi90-nivel2.png` --la */
/* ventana de CONCAR de FACILITA, comprobante `01-010001`, 1024x768--   */
/* recorrida pixel a pixel buscando el borde hundido de cada `TextBox`  */
/* (izquierdo `(165,165,165)+(107,107,107)`, derecho `(231,231,231)`).  */
/* Lo que salio, por renglon, en coordenadas de la ventana:             */
/*                                                                     */
/*   y        columna izquierda            columna derecha             */
/*   105-119  Comprobante   x96  w 72      Situacion      x522 w 72    */
/*   125-143  Fecha Compr.  x96  w 72      Moneda         x522 w 24    */
/*   145-163  Conversion    x96  w 24      Tipo Convers.  x522 w 24    */
/*   165-183  Glosa         x96  w290      Tipo Cambio    x522 w 72    */
/*   185-203  Origen        x96  w 24      Tipo Comprob.  x522 w 24    */
/*   205-223  Usuario       x96  w 72      Hora Actuali.  x522 w 72    */
/*            Fecha Actuali x308 w 78                                  */
/*                                                                     */
/* De ahi los CUATRO anchos --24, 72, 78 y 290-- y no uno solo de 150,  */
/* que es lo que habia y lo que recortaba la `Glosa`: el usuario vio    */
/* `RP000110 SILVANA` donde CONCAR ensena `RP000110 SILVANA BRUZON`.    */
/* La caja no estaba truncando el DATO --la API devuelve el nombre      */
/* entero-- sino dibujandose 218 px mas angosta que la de CONCAR.       */
/*                                                                     */
/* Y de ahi tambien las dos columnas de rotulos, que NO miden igual: la */
/* izquierda ocupa 96-11 = 85 px y la derecha 522-452 = 70. Con los 92  */
/* de la regla general las dos salian del mismo tamano y ninguna era la */
/* de CONCAR.                                                          */
/*                                                                     */
/* Va acotado a `#movi90-detalle` a proposito: la medicion es de ESTA   */
/* ventana. `#pantalla-situacion-detalle` usa las mismas clases con     */
/* TRES columnas y su propia medicion, y el `Detalle Secuencia` tiene   */
/* la suya --`corta`/`media`/`ancha`, arriba--. Ver DIFERENCIAS §128.   */
/* ------------------------------------------------------------------ */
#movi90-detalle .cuerpo-detalle {
  display: flex;
  flex-direction: column;
  /* La que se desplaza es la GRILLA, no el cuerpo: la cabecera y el cuadre
     se quedan quietos, como en CONCAR. */
  overflow: hidden;
}
#movi90-detalle .cabecera-detalle {
  flex: none;
  /* Los 67 px que CONCAR deja entre el borde derecho de la `Glosa` (x=385) y
     el primer rotulo de la columna derecha (x=452). */
  gap: 67px;
}
/* 375 = los 85 del rotulo mas los 290 de la `Glosa`, que es la caja mas
   ancha de la columna. Fijarla es lo que deja la columna derecha donde
   CONCAR la pone; sin esto se pega a la izquierda al angostar las cajas. */
#movi90-detalle .columna-detalle:first-child { flex: 0 0 375px; }
/* Los 85 px de CONCAR son del ORIGEN DEL ROTULO AL ORIGEN DE LA CAJA, y
   entre los dos hay 8 px de separacion (`--oly-space-2`), asi que el rotulo
   mide 77. Cabe: el rotulo mas largo de esta columna es `Fecha Actuali.`, que
   en `11px Inter` mide 74,0 px medidos con `measureText`. */
#movi90-detalle .columna-detalle:first-child .campo-detalle > span:first-child {
  width: 77px;
}
/* 🔴 78 Y NO LOS 62 QUE TOCARIAN: LA TIPOGRAFIA NO DA.
   Por la cuenta de arriba, los 70 px de CONCAR pedirian un rotulo de 62. En
   `11px Inter` --la letra de la replica-- `Tipo Comprob.` mide 78,0 px y
   `Tipo Convers.` 73,0: con 62 los dos se partian en DOS LINEAS y el renglon
   media 40 px de alto en vez de 20. Se veia en la captura del usuario.
   CONCAR los mete en 70 porque su `MS Sans Serif` de 8 pt es mas angosta.
   No se recorta el rotulo --un rotulo a medias es peor que 16 px de
   diferencia-- y la separacion queda anotada. Ver DIFERENCIAS §128. */
#movi90-detalle .columna-detalle:last-child .campo-detalle > span:first-child {
  width: 78px;
}
/* 🔴 29 Y NO LOS 24 MEDIDOS, POR LO MISMO.
   `MN` mide 18,2 px en `11px Inter`; con los 4+4 de relleno y los 2 del
   borde, una caja de 24 deja 14 px utiles y recortaba la `Moneda` --medido
   con `scrollWidth > clientWidth` en el navegador--. 29 es el minimo que la
   entra: 19 + 8 + 2. Las otras tres cajas de este ancho --`S`, `XL` y `V`,
   de 7,1, 13,7 y 7,6 px-- entraban ya en 24; se les da el mismo 29 porque en
   CONCAR las cuatro miden lo mismo y eso es lo que se copia.
   Ver DIFERENCIAS §128. */
#movi90-detalle .campo-detalle input.caja-24 { width: 29px; }
#movi90-detalle .campo-detalle input.caja-72 { width: 72px; }
#movi90-detalle .campo-detalle input.caja-78 { width: 78px; }
#movi90-detalle .campo-detalle input.caja-290 { width: 290px; }

/* 🔴 EL AVISO NO EMPUJA LA CAJA. `Tipo Comprob.` salia 52 px a la izquierda
   de los otros cinco rotulos de su columna --medido en el navegador: rotulo
   en x=323 contra los x=375 de sus vecinos-- porque su `.marca-sin-dato` es
   un hijo mas del renglon flex y ensanchaba el renglon mas alla de la
   columna. El usuario lo vio y ademas dijo bien por que importa: «creo que es
   por culpa de eso que dice sin dato en réplica pero eso no deberia
   afectar». No deberia, y ahora no afecta: el aviso se saca del reparto de
   ancho con `position: absolute` sobre un renglon `relative`, asi que sigue
   leyendose al lado de la caja y ya no mueve nada. */
#movi90-detalle .campo-detalle.sin-dato { position: relative; }
#movi90-detalle .campo-detalle.sin-dato .marca-sin-dato {
  position: absolute;
  left: calc(100% + var(--oly-space-2));
  white-space: nowrap;
}

/* La grilla del asiento, con SU barra de desplazamiento -- la que CONCAR
   dibuja en x=596. `min-height: 0` por lo mismo que en `.cuerpo-detalle`. */
.caja-grilla-detalle {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  border: 1px solid var(--oly-border);
}
.grupo-cuadre {
  display: flex;
  gap: var(--oly-space-2);
  align-items: center;
  font-size: 11px;
}
/* Mismo caso de especificidad que `.cuerpo-detalle .campo-detalle input`:
   sin el `.cuadre-detalle` delante, la global de `estilos.css` le ganaba el
   relleno y la letra a las cuatro cajas del `Debe/Haber`. */
.cuadre-detalle .grupo-cuadre input {
  flex: none;
  width: 110px;
  height: auto;
  padding: 1px 4px;
  font: inherit;
  font-size: 11px;
  text-align: right;
  color: var(--oly-text-secondary);
  background: var(--oly-surface-subtle);
}

/* ------------------------------------------------------------------ */
/* `Parámetros Varios` -- el formulario de tres marcos                  */
/*                                                                      */
/* Medido en `demo15-05` (§4) y en la captura en vivo del 04/09/2026:   */
/* rótulo a la izquierda, y cada campo de cuenta con DOS cajas -- el    */
/* código estrecho y su descripción larga, de sólo lectura.            */
/* ------------------------------------------------------------------ */
/* Misma regla que `.rotulo-campo-comp`: columna fija, no suelo. Ver arriba. */
/* 🔴 110 px, MEDIDO, no elegido. Era 210 --el doble-- y de ahi salia el
   «tenemos mas espacio de sobra» del usuario: la columna de rotulos se comia
   media pantalla y empujaba la caja de la descripcion.

   En `form.ctcomp01.json`, con el borde del marco y el borde de la caja del
   codigo: `Parametros Varios` deja 109 px de rotulo (marco en 4832, caja en
   4715) y el marco de `Parametro Detraccion` deja 99 (4850 y 4743). La clase
   es una sola para las dos pantallas, asi que va un numero DENTRO de las dos
   medidas y no la media aritmetica de nada.

   Con esta anchura los rotulos largos ENVUELVEN, que es lo que CONCAR hace:
   su captura ensena `Cuenta Impuesto / Renta 1.5% (Liq.)` partido en dos
   lineas. Ver DIFERENCIAS §110. */
.rotulo-campo-parametro {
  width: 110px;
  flex: 0 0 auto;
  overflow-wrap: anywhere;
  text-align: left;
  color: var(--oly-text-secondary);
}
.caja-codigo-parametro { width: 140px; }
.caja-valor-parametro { width: 110px; }
/* Sin ancho propio se estiraba a lo que sobrara. Ya no sobra nada: los doce
   campos llevan el suyo medido desde el servidor (334, 332 y 330 segun el
   marco), y esto queda de suelo por si algun dia llega un campo sin contar. */
.caja-descripcion-parametro { flex: 1; min-width: 0; }
/* Gris cuando esta apagada, que ahora es SOLO fuera del modo modificar y en
   el par que gobierna `Cuentas de Orden`. Antes iba gris siempre por una
   afirmacion sin medir; el volcado dice que sus veinte cajas son
   `readOnly = 0`. Ver DIFERENCIAS §110. */
.caja-descripcion-parametro:disabled {
  background: var(--oly-surface-subtle);
  color: var(--oly-text-secondary);
}

/* `Habilitar Monto Base` del marco `Creación` de `Parámetro Detracción`: va
   en el renglón de `Porcentaje Detraccion` pero pegada al borde DERECHO del
   marco, no al lado del porcentaje. Medido en `real-0409-ctcomp01-p13`. */
.campo-a-la-derecha { margin-left: auto; }

/* ---------------------------------------------------------------------
   `CTREGC27` — Genera Archivo Mensual Compras

   🔴 LOS BOTONES VAN APILADOS A LA DERECHA, no en una barra inferior. Es la
   única ventana del módulo que los pone así, y está medido en la captura:
   `Procesar` arriba y `Salir` debajo, los dos a la derecha del marco. Poner
   la barra genérica de abajo habría sido «como las demás» en vez de «como
   CONCAR». Ver DIFERENCIAS §109.
   --------------------------------------------------------------------- */
.cuerpo-regc27 {
  display: flex;
  gap: var(--oly-space-6, 32px);
  align-items: flex-start;
  padding: var(--oly-space-5, 24px);
  /* `wrap` para que la barra de `.botones-en-fila` --que pide el 100 % del
     renglón-- baje a su propia línea en vez de comprimir los campos. Sin
     esto, `flex: 0 0 100%` aplasta la columna de la izquierda.
     No cambia nada donde la barra va en COLUMNA (§109): ahí no pide el
     renglón entero y no hay nada que envolver. */
  flex-wrap: wrap;
}
.izquierda-regc27 { display: flex; flex-direction: column; gap: var(--oly-space-4, 16px); }
/* Misma regla de columna fija que el resto de los formularios: `width`, no
   `min-width`. Ver el bloque de `.rotulo-campo-comp` y §108. */
.campo-regc27 { display: flex; gap: var(--oly-space-3, 12px); align-items: center; font-size: 12px; }
.campo-regc27 > span {
  width: 190px;
  flex: 0 0 auto;
  overflow-wrap: anywhere;
  color: var(--oly-text-secondary);
}
/* 🔴 NADA SE ESTIRA EN ESTAS VENTANAS, Y ERA LA CAUSA DE LA CLASE ENTERA.
   El usuario lo dijo dos veces el 10/09/2026 --«teniendo espacio de sobra lo
   muestras todo a las justas»-- y las dos veces era el mismo mecanismo: la
   regla global `input:not(...), select { flex: 1 1 190px }` de `estilos.css`
   le da a CADA control una base de 190 px y `flex-grow: 1`, y como
   `.izquierda-regc27` es una columna que estira sus filas al ancho del hijo
   mas ancho --que suele ser un fieldset--, el ultimo control de cada fila se
   comia todo el sobrante.

   Medido en el navegador antes de esta regla: en `CTPLE551` la caja de `Mes`
   quedaba en 389 px --cuando CONCAR la mide en 57-- y el combo de `Moneda` en
   162 --cuando CONCAR lo mide en 265--, o sea los dos anchos INVERTIDOS
   respecto del original. En `CTREGC27` y `CTREGC25` el mismo mecanismo daba
   60->71 px, poco visible pero el mismo defecto.

   Las ventanas de CONCAR son de ancho FIJO y cada control tiene el suyo, asi
   que `flex: none` no es cosmetica: es la capa «pantalla», que se copia al
   pie de la letra. El ancho de cada uno se pone abajo, con su medicion. */
/* 🔴 Y LA ESPECIFICIDAD TIENE QUE GANARLE AL `:not()` DEL GLOBAL, o esto
   no hace nada. `input:not([type="radio"]):not([type="checkbox"])` pesa
   (0,2,1) --cada `:not()` aporta la de su argumento-- y `.campo-regc27 input`
   solo (0,1,1), asi que el `flex: 1 1 190px` seguia ganando. Medido en el
   navegador: la regla salia listada entre las que casan y el `flex` computado
   seguia siendo `1 1 190px`, con la caja de `Mes` en 265 px. Repitiendo los
   dos `:not()` la regla pesa (0,3,1) y gana. Y hace falta el `flex`, no basta
   el `width`: en una fila flexible la BASE manda sobre el `width`. */
.campo-regc27 input:not([type="radio"]):not([type="checkbox"]),
.campo-regc27 select { flex: none; }

/* Un piso para TODO combo de esta familia, no solo para el de `CTLIB581`:
   `max-content` de una lista vacia es casi cero --medido: 42 px-- y estos
   combos se llenan por `fetch`. 190 px es la BASE que la regla global ya les
   daba, asi que el piso no inventa un ancho: deja el de antes como minimo. */
.campo-regc27 select { min-width: 190px; }
/* 🔴 Y EL `:not(.combo-buscador-caja)` NO ES ADORNO. La caja de texto del
   buscador de un desplegable ES un `<input>` y vive DENTRO del mismo
   `.campo-regc27`, asi que esta regla se la comia: medido en el navegador el
   10/09/2026, el combo `Moneda` de `CTPLEC581` media 241 px por fuera y su
   caja de busqueda 60 px por dentro, con `MN     SOLES` recortado
   (`clientWidth` 58 contra `scrollWidth` 112). Y el `text-align: center`
   tampoco le corresponde: lo que se teclea en un buscador se lee desde la
   izquierda. Es la misma clase que el `4ch` del mes de `CTMOVI02`: una regla
   escrita para las cajas chicas alcanzando a una que no lo es. */
.campo-regc27 input:not(.combo-buscador-caja) {
  width: 60px; text-align: center; font: inherit; padding: 1px 4px;
}

/* Los anchos de `CTPLE551`, del volcado de su propia ventana
   (`form.crea-archivo-5-1-libro-diario-ple-5-0-ctple551.json`):
   `MSMaskWndClass` de `Mes` mide 57 y el `ThunderRT6ComboBox` de `Moneda`
   265. El de `Mes` lo da ya la regla de arriba (60, que es el ancho de la
   casa para un campo de dos digitos). Al combo se le pone el 265 como PISO y
   se le deja crecer con su contenido: 265 es con la tipografia de CONCAR, y
   copiar pixeles de otra fuente es lo que acaba de recortar la fecha de
   `CTLIBR51`. */
#ple551-moneda { width: max-content; min-width: 265px; }

/* 🔴 LOS TRES RADIOS DE `Detalle del Plan Contable Utilizado`, APILADOS.
   Medido en el mismo volcado: `Crear Formato 5.3` en `top: 222`, `Crear
   Formato 5.3. Sin Información` en `237` y `NO Crear Formato 5.3` en `258`,
   los tres con `left` 21-22. Tres `top` distintos y un mismo `left`: una
   columna. Y el marco que los contiene mide 483 x 83 -- alto para tres
   renglones. La replica los pintaba en fila porque `.marco-regc27` es un
   `flex` sin direccion, la misma clase que en `CTREGC27` SI va en fila (ahi
   el volcado y la captura los dan al lado). Por eso la columna se pide con
   una clase propia y no cambiando `.marco-regc27`, que romperia `CTREGC27`. */
.marco-regc27.marco-apilado-ple551 {
  flex-direction: column;
  align-items: flex-start;
  gap: var(--oly-space-1);
}
/* 🔴 LOS DOS DESPLEGABLES DE `CTPLEC581` RECORTABAN SU PROPIA DESCRIPCION.
   El usuario lo puso delante el 10/09/2026: «hay espacio hasta de sobra para
   poder mostrar los desplegables bien y estas que lo muestras tan pequeño que
   no se ve nada de la descripcion». Y sobraba de verdad: medido en el
   navegador, la ventana ocupa 1.025 px y la columna de campos 460, o sea 565
   sin usar, mientras el combo del mes quedaba en 258 px con un texto que pide
   276 (`12  Diciembre  31/12/2026 23:59:59`, medido con `measureText` en la
   fuente real del control).

   La causa es la regla global `input, select { flex: 1 1 190px }` de
   `estilos.css`: el combo tomaba una base de 190 px y crecia solo hasta donde
   la caja de su fila se lo permitia, sin mirar su contenido.

   `width: max-content` y no un numero: el ancho lo decide la opcion mas larga
   --que cambia con la compañia, porque el texto lleva la fecha y hora en que
   se genero cada mes-- y asi no hay un pixelaje que se quede corto cuando el
   dato crezca. Los 241 px que el volcado de formulario mide para estos dos
   combos (`ThunderRT6ComboBox`, `L=301 T=200/224 W=241`, en
   `artifacts/rig/share/form.ctplec581.json`) son con la tipografia de CONCAR;
   copiar ese numero con Inter a 14 px recorta igual, que es el mismo error
   que la fecha de `CTLIBR51` acaba de pagar. Lo que se copia es que la
   descripcion entera se lea. */
/* 🔴 CON UN PISO, PORQUE `max-content` DE UN COMBO VACIO ES CASI CERO.
   Las opciones de `Mes de Registro Compras` se pintan despues de un `fetch`
   --traen la fecha en que se genero cada mes-- y medido en el navegador con
   la lista vacia el combo bajaba a 42 px. O sea que un servidor que no
   contesta dejaba el control convertido en un boton. El piso es el ancho
   medido del `ThunderRT6ComboBox` de esa ventana: 241 px
   (`artifacts/rig/share/form.ctplec581.json`, los dos combos en `W=241`). */
#pantalla-lib581 .campo-regc27 select {
  width: max-content;
  min-width: 241px;
}
.marco-regc27 {
  display: flex;
  gap: var(--oly-space-6, 32px);
  align-items: center;
  border: 1px solid var(--oly-border, #c9c9c9);
  padding: var(--oly-space-3, 12px) var(--oly-space-4, 16px);
  font-size: 12px;
}
.marco-regc27 legend { font-size: 11px; color: var(--oly-text-secondary); padding: 0 4px; }
/* 🔴 `nowrap` porque el rótulo mas largo es `Sin Recálculo` y sin esto partia
   en DOS renglones mientras `Normal` iba en uno: lo vio el usuario el
   07/09/2026 y en la captura de CONCAR va en un solo renglon, al lado de
   `Normal` y dentro del mismo marco. */
.marco-regc27 label {
  display: flex; gap: 6px; align-items: center;
  white-space: nowrap;
}
/* 🔴 LAS DOS CASILLAS DEL `CTPLE551` TENIAN CLASE Y NO TENIAN REGLA. Se
   añadieron el 09/09/2026 con `class="casilla-ple551"` y esa clase no existia
   en esta hoja, asi que las dos heredaban la disposicion en bloque del
   navegador: la casilla encima y el rotulo debajo, con el tipo del documento
   en vez del de la ventana. Una clase inventada y nunca escrita no da error
   en ningun sitio --ni el navegador ni `tsc` se quejan--, y por eso conviene
   que lo diga el arnes y no el ojo.

   Los numeros son los del volcado propio (`form.…ctple551.json`): las dos
   casillas van a `l=32`, `w=360`, `h=17`, y de la una a la otra hay 28 px.
   El `gap` de 6 px y el `font-size` de 12 son los de `.marco-regc27 label`,
   que es el otro grupo de la MISMA ventana: reusar su piel en vez de copiarla
   es lo que evita que las dos mitades del formulario se desincronicen. */
/* 🔴 CORREGIDO EL 10/09/2026 POR LA NOCHE: EL ROTULO VA A LA IZQUIERDA Y LA
   CAJA AL BORDE DERECHO, EN LAS CINCO CASILLAS DE LAS TRES VENTANAS.
   Lo que habia era `gap: 6px` con el `<input>` primero, o sea caja y rotulo
   pegados a la izquierda, y ESO NO ES LO QUE CONCAR DIBUJA. Medido en dos
   capturas de la misma sesion del aparejo, recortadas y ampliadas:
   `ple551-abre.png` y `ple561-abre.png` ponen el rotulo empezando en el borde
   izquierdo del cuerpo y la casilla pegada al DERECHO, con todo el hueco en
   medio. El volcado propio del `CTPLE551` lo dice por otra via: un solo
   control `l=32, w=360`, o sea que la caja cae en el 379 y el rotulo arranca
   en el 32.
   La primera version de este arreglo se equivoco al reves: escribio una clase
   propia para el 6.1 diciendo que «va al reves que las del CTPLE551», dando
   por bueno el marcado de las hermanas. Lo cazo el auditor mirando la captura
   del 5.1. Una clase para las tres, que es lo que evita que dos mitades del
   mismo formulario se desincronicen (§136). Ver DIFERENCIAS 266.

   `space-between` y no un `margin-left` de tantos pixeles: el ancho del cuerpo
   lo decide el combo de `Moneda`, y un numero copiado de la captura se queda
   corto o largo con otra tipografia. Lo que se copia es que la casilla quede
   al borde.

   Y SIN regla de tamano para la casilla: la exclusion de `estilos.css` ya
   cubre radios y casillas --por sexta vez-- y `los-controles-que-no-son-cajas`
   se pone rojo si aparece un noveno parche por pantalla. */
.casilla-ple551 {
  display: flex;
  justify-content: space-between;
  gap: var(--oly-space-4, 16px);
  align-items: center;
  font-size: 12px;
  white-space: nowrap;
}

.botones-regc27 { display: flex; flex-direction: column; gap: var(--oly-space-3, 12px); }
/* 🔴 Y LOS BOTONES SON LOS DE LA REPLICA, NO LOS DEL NAVEGADOR.
   Aca solo habia un `min-width`, asi que `Procesar` y `Salir` salian con el
   cromo por omision --gris, borde fino, esquina viva-- en una interfaz donde
   todos los demas botones son de Olympium. Lo vio el usuario el 07/09/2026:
   «los botones procesar y salir no tienen nada que ver con la ui».
   Se reusa la regla de `.botones-dialogo button` en vez de copiarla: es la
   misma piel, y dos copias de una piel es como se desincronizan. Lo que NO se
   copia de CONCAR es el cromo del control --eso es piel de la replica-- y si
   la disposicion: apilados a la derecha, que es lo medido (§109).

   `flex: none` porque la regla que se reusa trae `flex: 1`, pensada para dos
   botones EN FILA. En esta columna eso les daba `flex-basis: 0` y los estiraba
   a lo alto. `cascaron.css` carga despues de `estilos.css`, asi que esta linea
   gana. */
.botones-regc27 button { min-width: 96px; flex: none; }
/* 🔴 PERO CTPLEC581 Y CTPLEC582 LOS PONEN EN FILA, NO EN COLUMNA.
   -----------------------------------------------------------------------
   La columna de arriba esta medida, pero de `CTREGC25`/`CTREGC27` (§109), y
   se habia reusado para las dos ventanas del PLE 8.1/8.3 SIN una medicion que
   lo autorizara. Las capturas dicen otra cosa:
   `artifacts/rig/shots/v28-581-0002.png` (0002, 06/09/2026) y
   `v28-ctlib582.png` (0002, 06/09/2026) enseñan los tres controles EN UNA
   SOLA FILA horizontal --panel gris, `Generar en TXT`, `Generar en Excel`,
   puerta roja-- y el volcado lo confirma por otra via: en
   `form.ctplec581.json` los controles 6, 7 y 9 comparten el mismo `top`.
   El hueco va a la IZQUIERDA de los tres, no entre ellos.
   Es la capa «pantalla», que se copia al pie de la letra: no es un
   apartamiento declarable, es que estaba mal. Anotado el 10/09/2026. */
.botones-regc27.botones-en-fila {
  flex-direction: row;
  justify-content: flex-end;
  align-items: center;
  /* 🔴 `flex: 0 0 100%` ES LO QUE LA BAJA AL PIE, y sin esto el arreglo
     quedaba a medias -- lo cazó el auditor el 10/09/2026.
     `.cuerpo-regc27` es una FILA (campos a la izquierda, botones a la
     derecha), pensada para la columna de §109. Con sólo `flex-direction:
     row` la barra se quedaba EN EL MISMO RENGLON que `Mes de Registro
     Compras`, con 158 px de hueco a su derecha, y el `justify-content` de
     arriba era inerte porque el div medía exactamente su contenido: no
     había espacio libre que repartir.
     En CONCAR los campos van arriba (`top` 200 y 224) y los botones abajo
     (`top` 414 en `CTPLEC581`, 305 en `CTPLE551`): es un PIE. Ocupando el
     100 % del renglón, la barra baja a su línea y el `flex-end` empieza a
     tener algo que alinear. */
  flex: 0 0 100%;
}

/* ==================================================================== */
/* LA BARRA DE PROGRESO DEL PIE DE LOS TRES `CTPLE55x`/`CTPLE561`       */
/* ==================================================================== */
/* QUE ES, Y NO ES UNA CONJETURA. El pie de estas ventanas no empieza en
   `Generar en TXT`: a su izquierda hay una franja gris hundida. El volcado
   propio de la pantalla dice QUE CONTROL ES --no hace falta deducirlo de la
   captura--:

       form.crea-archivo-5-1-libro-diario-ple-5-0-ctple551.json
         ProgressBar  ProgressBarWndClass  ''   L16 T311 W165 H15
         GroupBox     ThunderRT6Frame      ''   L16 T305 W481 H27   <- el pie
         Button       'Generar en &TXT'         L223 T305 W115 H31
         Button       'Generar en E&xcel'       L341 T305 W120 H31
         Button       '&S'                      L464 T305 W33  H43   <- la puerta

   O sea: es una BARRA DE PROGRESO de 165x15, y la puerta es el boton `&S`
   --Alt-S, `Salir`-- de 33x43, mas ALTO que los otros dos, como en la
   captura. Los cinco viven dentro de un marco sin titulo que abarca el pie.

   🔴 Y SE ESCRIBE PORQUE LA PRIMERA VERSION DE ESTE BLOQUE, ESCRITA HOY,
   DECIA «ni siquiera se sabe si es una barra de progreso o un rotulo». Era
   el error del `CLAUDE.md` --declarar una ausencia sin haber buscado-- y la
   respuesta estaba en el volcado de formulario, que es justo el sitio que
   las tres veces del 07/09 falto mirar; y ademas resumida en `index.html`,
   cuarenta lineas por encima de la ventana: «3 botones, 1 BARRA DE
   PROGRESO, 2 marcos y 3 radios».

   🟡 LO QUE SIGUE SIN MEDIRSE es que ENSEÑA la barra mientras genera. En las
   ocho capturas de las tres ventanas --recien abiertas y despues de generar--
   sale vacia, y el volcado la trae sin `text`. Se dibuja vacia y quieta.

   🟡 Y del `CTPLE553`/`CTPLE561` NO hay volcado: en `artifacts/ui/forms` solo
   esta el del 5.1 (mas su `.2`). Que las tres compartan pie sale de las tres
   capturas de apertura, que coinciden; los 165x15 son del 5.1 y se extienden
   a las hermanas por esa coincidencia, no por una medicion de cada una.

   DE CONCAR SE COPIA LA DISPOSICION Y LAS MEDIDAS; el cromo del control es
   piel de la replica, por la misma linea que `.botones-regc27 button` fija.
   Ver DIFERENCIAS 271. */
.barra-progreso-concar {
  flex: none;
  width: 165px;   /* L16 T311 W165 H15 del volcado */
  height: 15px;
  box-sizing: border-box;
  /* `auto` a la derecha: en el volcado la barra arranca en 16 --el borde
     izquierdo del pie-- y los botones se van al otro extremo. La fila ya
     lleva `justify-content: flex-end`, asi que sin esto la barra viajaria
     pegada a `Generar en TXT`. */
  margin-right: auto;
  /* Hundido, que es el relieve invertido de Win32 y lo que la captura enseña. */
  background: var(--oly-surface-sunken, #e8e8e8);
  border: 1px solid var(--oly-border-subtle);
  border-top-color: var(--oly-border-strong, #9a9a9a);
  border-left-color: var(--oly-border-strong, #9a9a9a);
}

/* 🟡 LO QUE ESTA FILA HACE AL ANCHO, DICHO PORQUE SE MIDIO.
   Al pasar los tres botones a fila, la ventana de `CTPLEC581`/`CTPLEC582`
   crece, y en un panel mas angosto que ella la PAGINA saca
   barra horizontal. Medido en el navegador: `scrollWidth` 804 contra
   `clientWidth` 520, mientras `CTREGC25`/`CTREGC27` daban 520 limpios.
   🔴 Se intento arreglar con `flex-wrap` y NO SIRVE, y vale escribir por que
   para que nadie lo vuelva a intentar: `.ventana:not(.ventana-apilada)` es
   `width: max-content` a proposito --la ventana se cine a su contenido, como
   la de CONCAR, que es de ancho fijo--, asi que el contenedor SIEMPRE crece
   hasta que los hijos entren y el `wrap` no llega a dispararse nunca. Un
   `flex-wrap` ahi es codigo muerto que aparenta una proteccion inexistente.
   No es un defecto: es la misma ventana de ancho fijo del original, y la
   regla de la casa del PIE ALCANZABLE habla del pie --el eje vertical--, no
   de esto. */
/* La casilla `Para Régimen RER` de `CTLIB581`. Va en su propio renglón,
   como en la ventana medida, y no en la columna de rótulos: su texto esta a
   la DERECHA de la casilla y no a la izquierda. */
.casilla-lib581,
.casilla-lib582 {
  display: flex;
  gap: var(--oly-space-2);
  align-items: center;
  font-size: 12px;
  padding: 2px 0;
}
/* 🔴 `white-space: pre-wrap` NO ES COSMETICA: es el mensaje de CONCAR.
   `Comprobante: 11  -100001 esta Pendiente` lleva DOS espacios porque `CSUBDIA`
   es `char(4)` y CONCAR concatena sin recortar. El 409 los trae y el JS los
   pone con `textContent`, pero HTML colapsa los espacios consecutivos: la
   pantalla ensenaba UNO. O sea que la capa «pantalla» --la que se copia al pie
   de la letra-- se apartaba de CONCAR justo en el detalle que §119 subraya como
   medido. Lo levanto el auditor de la vuelta 31 leyendo este bloque.
   `pre-wrap` y no `pre`: conserva los espacios y sigue partiendo la linea. */
.aviso-regc27 {
  margin: 0 var(--oly-space-5, 24px) var(--oly-space-3, 12px);
  font-size: 12px;
  white-space: pre-wrap;
}
.aviso-regc27.aviso-error { color: var(--oly-danger, #b00020); }
.aviso-regc27.aviso-bien { color: var(--oly-success, #0a7d3c); }
.aviso-regc27.aviso-ojo { color: var(--oly-warning, #8a6d00); }
.nota-regc27 { margin: 0 var(--oly-space-5, 24px); font-size: 11px; color: var(--oly-text-secondary); }
.tabla-regc27 { margin: 0 var(--oly-space-5, 24px) var(--oly-space-5, 24px); border-collapse: collapse; font-size: 11px; }
.tabla-regc27 th, .tabla-regc27 td { border: 1px solid var(--oly-border, #c9c9c9); padding: 2px 8px; text-align: left; }
.tabla-regc27 .cifra-regc27 { text-align: right; }


/* ---------------------------------------------------------------------
   CTREGC25 — lo que su ventana tiene y la de CTREGC27 no
   ---------------------------------------------------------------------
   Medido en `form.ctregc25.json`: los TRES radios van apilados --tops 277,
   303 y 359-- y no en una línea, y la caja `Céntimos Ajuste` cae dentro del
   marco, sangrada bajo `Ajustado` (left 263 contra los 164 de los radios).
   Los 96 px de sangría salen de esa resta.
   Ver DIFERENCIAS §114. */
.marco-regc25 {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
}

.marco-regc25 .campo-centimos {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: 96px;
}

.marco-regc25 .campo-centimos input { width: 38px; }

/* La caja sale en GRIS con `Normal` y con `Sin Recálculo`: así está en las
   cuatro capturas, y `enabled: false` en el volcado. */
.marco-regc25 .campo-centimos input:disabled { color: #8a8a8a; }
.marco-regc25 .campo-centimos:has(input:disabled) span { color: #8a8a8a; }

/* 🔴 LA FRANJA DE ESTADO NO LLEVA CLASE PROPIA, Y ESO LO DECIDIO UN ARNES.
   La primera version invento una `.franja-regc25` con su borde hundido y su
   fondo gris -- que es, punto por punto, lo que `.franja-pie-concar` ya
   hacia. `barras-pie.mjs` la caza: su censo de clases `barra-*` y `franja-*`
   existe para que una clase nueva OBLIGUE a decidir si es una forma nueva o
   la copia siguiente. Era la copia siguiente.
   Lo unico propio es que en reposo tiene que ocupar su alto igual, para que
   la ventana no se mueva al empezar a procesar. */
#regc25-franja { margin: 6px 0 0; min-height: 1.2em; }

/* =====================================================================
   LA GEOMETRIA DE `Ingreso de Anexos - CTANEX03`

   🔴 SALE DEL VOLCADO, Y DE LOS DOS. `form.ctanex03.json` y
   `form.ctanex03.2.json` traen 24 controles cada uno y su geometria es
   IDENTICA: contrastados antes de fijar un numero, como pide la regla que la
   destilacion pago con `CTMOVI99`.

   Las once filas del volcado, con el `top` de cada control:

     y=106  Tipo de anexo      combo 265x21  APAGADO (enabled:false)
     y=132  Codigo de Anexo    caja  165x20
     y=157  Tipo Persona       combo 181x21
     y=182  Apellido Paterno   caja  265x20  APAGADO
     y=208  Apellido Materno   caja  265x20  APAGADO
     y=233  Nombre             caja  265x20  APAGADO
     y=258  Razon Social       caja  369x19
     y=284  Direccion          caja  369x19
     y=309  casilla x=26 135x17 + caja x=165 135x19 + boton x=310 23x20
            + `?` x=343 17x17
     y=334  combo 167x21 + caja x=322 139x21 + boton x=468 23x20
     y=358  marco `Tipo ` x=23 217x32; radios y=370: x=63 76x16, x=155 76x18
     y=401  pie: marco 634x25, `&G` x=531 y `&S` x=558, los dos 25x41

   Todas las cajas arrancan en x=148 y el paso entre filas es 25-26 px. El
   marco exterior es 15,91 586x311.

   🔴 EL SELECTOR LLEVA `id`, Y NO ES ADORNO. `estilos.css` viste las cajas
   con `input:not([type="radio"]):not([type="checkbox"])`, que pesa (0,2,1).
   Una regla de dos clases mas el elemento empata en (0,2,1) y se decide por
   el ORDEN de las hojas, que es una forma fragil de ganar. Con el `id` pesa
   (1,2,1) y gana sin depender del orden. Es exactamente el defecto que tapo
   toda la geometria del `Detalle de Comprobante` (DIFERENCIAS §128) y la
   forma de no repetirlo es no volver a escribir una regla que empate.

   🟡 LOS ROTULOS NO SON MEDIBLES. En VB6 las etiquetas no son controles con
   ventana y el volcado no las trae: el TEXTO sale de la captura del usuario
   del 07/09/2026 y la POSICION no. La columna se dibuja a la izquierda de
   x=148, que es donde tiene que caber por descarte, con el ancho que pide la
   metrica de la fuente --ver abajo--. Queda ABIERTO medir su x real.

   Ver DIFERENCIAS §133.
   ===================================================================== */
#anex03-cuerpo { display: flex; flex-direction: column; overflow: auto; }

/* El GroupBox 15,91 586x311 del volcado. El ancho se respeta; la altura NO se
   fija, porque acá el renglon de la replica --el que dice que falta un combo
   sin medir-- suma alto que CONCAR no tiene, y recortarlo lo esconderia. */
#anex03-cuerpo .marco-anex03 {
  display: flex;
  flex-direction: column;
  gap: 4px;
  width: 586px;
  padding: var(--oly-space-3);
  border: 1px solid var(--oly-border);
  border-radius: var(--oly-radius-sm);
}

#anex03-cuerpo .fila-anex03 {
  display: flex;
  align-items: center;
  gap: var(--oly-space-2);
  /* `stretch` y no `center`: es el mismo arreglo que en `.columna-detalle`,
     donde centrar descentraba los renglones de distinto alto (§128). Acá el
     centrado vertical SI se quiere --las cajas del renglon del R.U.C. miden
     19, 20 y 21-- pero el reparto horizontal no debe estirar nada. */
}

/* 🔴 125 PX EN CONCAR Y 148 ACA, Y ES METRICA DE FUENTE, NO DISPOSICION.
   La columna de rotulos de CONCAR va de x=23 a x=148, o sea 125 px. Medido
   con `measureText` en `11px Inter`, el rotulo mas largo --`Razon Social /
   Descripción`-- no entra en 125. CONCAR dibuja con la fuente de VB6 y el
   navegador con Inter, y el mismo texto no ocupa lo mismo.

   Se ensancha la columna en vez de recortar el rotulo, por la instruccion
   explicita del usuario del 07/09/2026: «tienes espacio hasta de sobra
   aprovechalo porque hay nombres que tenemos que mostrar completo». Es un
   apartamiento deliberado de la capa pantalla y esta anotado (§128, §133).

   LOS DIEZ ROTULOS, medidos con `measureText` en el navegador --no estimados--:

     Razon Social / Descripción  139,0   <- el que manda
     Direccion / Referencia      114,9
     Tipo de Documento           102,4
     Código de Anexo              89,3
     Apellido Materno             88,6
     Apellido Paterno             85,7
     Tipo de anexo                73,6
     Tipo Persona                 68,8
     Validar RUC                  62,0
     Nombre                       41,6

   Con los 125 de CONCAR, el primero se recorta por 14 px. Con 148 entran los
   diez y sobra: verificado en el navegador, `scrollWidth == clientWidth` en
   los diez. */
#anex03-cuerpo .rotulo-anex03 {
  flex: none;
  width: 148px;
  font-size: 11px;
  color: var(--oly-text-muted);
  white-space: nowrap;
}

/* La casilla `Validar RUC` ocupa el lugar del rotulo --x=26, en la columna de
   los rotulos-- en vez de ir a la derecha de su caja. Medido. */
#anex03-cuerpo .casilla-anex03 {
  display: flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
}

/* Los siete anchos del volcado, uno por caja. Se declaran uno a uno y no con
   un ancho comun porque en CONCAR son siete numeros distintos, y un ancho
   comun seria una invencion que se lee como medida. */
/* 🔴 EL ALTO TAMBIEN SE FIJA, PORQUE `height: auto` DABA 24 Y CONCAR TIENE
   19-21. Sin `line-height` la caja hereda el 20 px del cuerpo y con el relleno
   y el borde suma 24: cuatro o cinco px mas alta que cualquiera de CONCAR, y
   multiplicado por once filas la ficha entera sale corrida.

   Los altos medidos en el volcado son 19 (razon social, direccion, la caja del
   R.U.C.), 20 (codigo y los tres del nombre) y 21 (los tres combos y la caja
   del numero de documento). Son TRES valores para lo que en CONCAR son dos
   clases de control de VB6: las cajas de texto entre 19 y 20, los combos en 21.
   Ese 19-contra-20 es ruido del dibujo de VB6, no una decision, asi que se
   toman DOS alturas --20 para las cajas y 21 para los combos-- y la diferencia
   maxima contra el volcado es de UN pixel. Se dice en vez de escribir tres
   clases que finjan medir un pixel que no significa nada.

   🔴 Y SE APARTAN CUATRO CAJAS, NO TRES. Escribi «las tres cajas de 19» y al
   medir en el navegador son CUATRO: las tres de 19 suben a 20 (+1) y
   `Num. Dcmto.`, que en el volcado mide 21 siendo caja de texto y no combo,
   baja a 20 (-1). Es la septima cuenta corta de este repositorio y la tercera
   que un arnes o una medicion caza antes de que el numero llegue al documento
   (§123). La regla es la misma: contar la familia ENTERA antes de escribir el
   numero, no contar los que uno tenia en la cabeza.

   `line-height` en px y no sin unidad: sin unidad se multiplica por el
   `font-size` de cada caja y volveria a depender de lo que herede. */
#anex03-cuerpo .fila-anex03 input,
#anex03-cuerpo .fila-anex03 select {
  flex: none;
  box-sizing: border-box;
  height: 20px;
  padding: 1px 4px;
  font: inherit;
  font-size: 11px;
  line-height: 16px;
}
#anex03-cuerpo .fila-anex03 select { height: 21px; }
/* 🔴 ACA HABIA UN NOVENO PARCHE, Y LO CAZO EL ARNES DE LA VUELTA 38.
   Escribi `#anex03-cuerpo .fila-anex03 input[type="checkbox"] { width: 13px;
   height: 13px; padding: 0 }` y `los-controles-que-no-son-cajas.mjs` se puso
   rojo al instante: los parches por pantalla son OCHO y ese habria sido el
   NOVENO. Su mensaje decia exactamente lo que pasaba --«un noveno significa que
   alguien tapo el defecto en vez de arreglarlo: el arreglo va en el ORIGEN»--.

   Y era redundante, no solo mal ubicado. La vuelta 38 arreglo el origen
   EXCLUYENDO los radios y las casillas de la regla de las cajas de texto
   (`input:not([type="radio"]):not([type="checkbox"])`), asi que ya no les llega
   ni ancho ni relleno y quedan a su tamano nativo: 13x13, medido en el
   navegador, que es el de CONCAR. No hacia falta ninguna regla.

   Se deja escrito porque es la prueba de que el arreglo de la 38 funciona: un
   arnes que caza al AUTOR de la vuelta siguiente vale mas que el que caza a un
   tercero. Ver DIFERENCIAS §126 y §133. */
#anex03-cuerpo .caja-135 { width: 135px; }
#anex03-cuerpo .caja-139 { width: 139px; }
#anex03-cuerpo .caja-165 { width: 165px; }
#anex03-cuerpo .caja-167 { width: 167px; }
#anex03-cuerpo .caja-181 { width: 181px; }
#anex03-cuerpo .caja-265 { width: 265px; }
#anex03-cuerpo .caja-369 { width: 369px; }

/* El `?` de x=343, 17x17. No lleva icono: en CONCAR es el signo dibujado. */
#anex03-cuerpo .boton-ayuda-anex03 {
  flex: none;
  width: 17px;
  height: 17px;
  padding: 0;
  font-size: 11px;
  line-height: 1;
  background: var(--oly-surface-subtle);
  border: 1px solid var(--oly-border);
  border-radius: var(--oly-radius-sm);
  cursor: pointer;
}

/* El marco `Tipo `: x=23 --o sea alineado con la columna de rotulos, no con
   las cajas-- 217x32, con los dos radios en y=370. */
#anex03-cuerpo .marco-tipo-anex03 {
  display: flex;
  align-items: center;
  gap: var(--oly-space-3);
  width: 217px;
  margin: var(--oly-space-2) 0 0;
  padding: 2px var(--oly-space-2) var(--oly-space-2);
  border: 1px solid var(--oly-border);
  border-radius: var(--oly-radius-sm);
}
#anex03-cuerpo .marco-tipo-anex03 legend {
  padding: 0 4px;
  font-size: 11px;
  color: var(--oly-text-muted);
}
#anex03-cuerpo .marco-tipo-anex03 label {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  cursor: pointer;
}

/* 🔴 ESTA ES LA VENTANA QUE EL USUARIO SEÑALÓ, TEXTUAL, el 09/09/2026:
   «ese crear proveedor parece hecho a la que me importa porque hay espacio
   de sobra a los costados... reduce o quita todo ese espacio en blanco».
   `.ventana-apilada` (mas arriba en este archivo) es `position: fixed` con
   `inset: 60px 40px 40px`: las CUATRO esquinas fijadas estiran la ventana al
   hueco entero, y `#pantalla-anex03` no tenia ningun `width` propio que la
   sacara de ahi --a diferencia de `#pantalla-movi70`, que ya lo llevaba--.
   El marco de este formulario mide 586 (medido arriba, `#anex03-cuerpo
   .marco-anex03`); la ventana se estiraba a 1280 o mas, dejando toda esa
   diferencia en blanco a la derecha.

   `width`/`height` en `max-content` ciñen la ventana al mas ancho/alto de
   sus hijos --hoy el marco de 586, mas el `.barra-comp` del pie--, y
   `max-width`/`max-height` son el TOPE para que nunca se salga de la
   pantalla ni pierda el desplazamiento si el contenido crece. Los dos
   numeros del tope son los del `inset` BASE de `.ventana-apilada` (60/40/40)
   mas el `margin-top: 20px` de `.ventana`: 60+20=80 arriba y 40 abajo -->
   `100vh - 120px`--; 40+40 a los lados --> `100vw - 80px`--. Son los MISMOS
   bordes a los que ya llegaba estirada: el tope no recorta nada que hoy se
   vea, solo deja de FORZAR el estiramiento cuando el contenido pide menos.

   Medido en el navegador a 1400x900, ANTES -> DESPUES: 1080 -> 660 de ancho
   (sobraba 837 contra el marco de 586 mas el pie), 780 -> 573 de alto. */
#pantalla-anex03 {
  width: max-content;
  max-width: calc(100vw - 80px);
  height: max-content;
  max-height: calc(100vh - 120px);
}

/* `Consulta de RUC SUNAT`, la hija que abre el `?` de `CTANEX03` (§133).
   MEDIDA EN CONCAR REAL el 09/09/2026, pero la CITA de hoy es la medición
   que el usuario dictó en el chat de esa sesión, NO un artefacto versionado:
   la captura todavía no existe en `docs/capturas-concar/` (gitignoreado, sin
   guardar). Cuando la captura llegue, esta nota se cambia por su ruta y
   nada más -- ni el marcado ni esta regla deberían necesitar tocarse.

   Se apila SOBRE `#pantalla-anex03`, que no declara `z-index` propio y por
   eso hereda el 40 base de `.ventana-apilada` (línea ~2620): el registro de
   la línea 2662 ya usa 41/42 (la pila de `CTMOVI90`), 44 (`ventana-hijo`), 45
   (vista previa) y 46 (`Plan Cuentas`) -- ninguno de esos es su padre, así
   que se le da uno PROPIO en vez de tomar prestado uno ajeno. El `inset`
   entra un poco más que el de su padre (60/40/40), como hace cada nivel de
   esta familia.

   Ceñida a su contenido con el MISMO mecanismo que `#pantalla-anex03` y
   `#pantalla-movi70`: `width`/`height` en `max-content`, con el tope en
   `max-width`/`max-height` recalculado para ESTE `inset` (90 arriba + 20 del
   `margin-top` de `.ventana` = 110, más 70 abajo -> 180 de alto; 70+70 a los
   lados -> 140 de ancho). */
#pantalla-consulta-ruc-sunat {
  inset: 90px 70px 70px;
  z-index: 43;
  width: max-content;
  max-width: calc(100vw - 140px);
  height: max-content;
  max-height: calc(100vh - 180px);
}
/* Sus rótulos son más largos que los 92px que da `.campo-detalle > span:
   first-child` -- `Condición del Contribuyente` y `Dirección del
   contribuyente` se recortarían. Medido en el navegador servido (Inter
   cargado de verdad, no el `data:` de una vista aparte) con el mismo método
   que ya usa esta hoja para esta familia (`measureText` a `11px Inter`, ver
   línea ~3117): el más largo de los seis, `Condición del Contribuyente`,
   mide 148,2 px; se redondea a 150 y no se recorta ninguno. */
#pantalla-consulta-ruc-sunat .campo-detalle > span:first-child {
  width: 150px;
}

/* ===================================================================== */
/* LA GEOMETRIA DE `CTMOVI09`, MEDIDA                                    */
/* ===================================================================== */
/* El usuario, el 07/09/2026: «tienes que acomodar los iconos y los inputs
   porque el de desktop se ve mejor mas ordenado» y «la idea es que concar web
   se vea igual exactamente igual solo cambiando el .css».

   Lo que hacia que se viera desordenado NO era el agrupamiento --los cuatro
   `fieldset` coinciden con los cuatro marcos de contenido de CONCAR-- sino que
   las cajas eran ELASTICAS: la regla general de `estilos.css` les da
   `flex: 1 1 190px`, asi que cada renglon repartia el ancho sobrante entre las
   cajas que tuviera. Dos renglones con distinta cantidad de campos daban
   columnas distintas, y de ahi el aspecto ragged que en CONCAR no existe: alla
   TODAS las cajas de la izquierda arrancan en x=578 y cada una tiene su ancho
   fijo.

   TODO NUMERO DE ESTE BLOQUE SALE DEL VOLCADO DE FORMULARIO, no de la captura.
   Contrastado en los CINCO volcados distintos que hay (ocho ficheros, tres
   pares duplicados): la geometria es IDENTICA en los cinco y solo cambian
   `visible`/`enabled` en 8 controles, que son dos estados de la pantalla.
   Eso es lo que autoriza a escribir estos numeros; si hubieran discrepado, no
   serian una medicion. La medicion entera esta en `docs/CTMOVI09-MEDIDA.md`.

   POR QUE VA ACOTADO POR `id`
   ---------------------------
   `estilos.css` viste las cajas con
   `input:not([type="radio"]):not([type="checkbox"])`, que pesa (0,2,1). Una
   regla de dos clases EMPATA y se decide por orden de hojas, que es el defecto
   que costo seis vueltas de esta semana (DIFERENCIAS §128). `#form-padre`
   pesa (1,x,y) y gana sin depender del orden.

   LO QUE **NO** ESTA MEDIDO, Y POR ESO NO SE ESCRIBE
   --------------------------------------------------
   La `x` de los ROTULOS. Un `Label` de VB6 no es un control con ventana, asi
   que no aparece en el volcado: de las etiquetas se sabe el TEXTO (de la
   captura) y nada mas. Por eso aca se posicionan las CAJAS por su numero y las
   etiquetas se dejan a la derecha de su banda, terminando donde la caja
   empieza. La banda de la izquierda mide 120 px porque la columna de entrada
   arranca en 578 y el marco en 458 -- derivado de dos numeros medidos, no
   inventado. */

/* El ancho del marco: 646 medido, y los cuatro de contenido lo comparten.

   🔴 PERO 646 ES EL SUELO, NO EL TECHO, Y ESO ES NUEVO (09/09/2026).
   Con `width: 646px` a secas, el renglon de `Anexo Ref.` --el unico que lleva
   CUATRO controles, porque el cuarto es la descripcion del anexo que CONCAR
   NO TIENE (§186 punto 5)-- media 835 de contenido dentro de un renglon de
   644, y la ventana (`width: max-content`) se quedaba en 648 porque el
   `max-content` mira el marco, que estaba clavado. Resultado: 191 px
   recortados contra el borde, con `overflow-x: hidden` y sin barra. Lo cazo el
   usuario: «la parte del nombre del anexo ref. no se ve».

   `min-width` conserva la medicion --un formulario con menos contenido sigue
   midiendo los 646 de CONCAR-- y `max-content` deja que crezca lo que haga
   falta para la caja que agregamos nosotros. Comprobado en el navegador
   ANTES de escribirlo, que es lo que hace que esto no sea una conjetura: de
   los 68 controles del formulario se movieron DOS, y son los dos botones del
   pie, que van pegados al borde derecho por diseno (§186 punto 1). Los 66 de
   CONCAR --cajas y rotulos-- quedaron en la MISMA x relativa al borde de la
   ventana, al pixel. El marco pasa de 646 a 837 y la ventana de 648 a 839. */
#form-padre {
  min-width: 646px;
  width: max-content;
  gap: 3px;                    /* los marcos se tocan: 345 contra 342 */
  padding: 4px 0;
}
#ventana-padre { max-width: none; width: max-content; }
#form-padre .bloque { padding: 4px 0; border-radius: 0; }

/* La banda de rotulos de la izquierda. La caja tiene que arrancar en 120
   (578 - 458), y de esos 120 no todos son rotulo: 1 se lo lleva el borde del
   marco y 2 la separacion rotulo-caja. Asi que el rotulo mide 117 y la caja
   cae en 120 EXACTO -- comprobado en el navegador, no calculado a mano.
   Es la misma cuenta que `.marco-medido` ya hacia para `CTCOMP01` (§110): la
   separacion que se ve en CONCAR no la pone un hueco, la pone el rotulo, que
   es mas corto que su columna. */
/* `position: relative` porque el `<p>` del error de campo (más abajo,
   `.mensaje-error-campo`) se posiciona `absolute` CONTRA ESTA fila, no
   contra `#form-padre` entero: así queda debajo del control que falló sin
   ser un ítem más del flex de la fila. Ver ese comentario para el porqué
   completo -- acá sólo el ancla. */
#form-padre .fila { gap: 2px; margin-bottom: 2px; flex-wrap: nowrap; position: relative; }
#form-padre .fila > label {
  width: 117px;
  /* Y `min-width: 0`, porque `.fila label.etiqueta-corta` pone 78 de minimo:
     las dos bandas de 76 de la detraccion se quedaban en 78 y corrian su caja
     dos pixeles. Medido en el navegador, no deducido. */
  min-width: 0;
  box-sizing: border-box;
  padding-right: 6px;
}

/* Ninguna caja se estira: cada una lleva su ancho medido. La altura de 21 es la
   MAS COMUN pero no la unica: contadas sobre los 45 controles no-marco salen
   DIEZ alturas distintas --21 en 26, 20 en 5, 19 en 4, 17 en 2 (los radios que
   no se pintan), 35 en 2 y 41 en 2 (los botones), y 13, 15, 22 y 23 en uno cada
   una--. La primera version de este comentario decia «21 en 43 de 45», que era
   la DECIMA cuenta corta de este bucle; se cazo contando antes de escribirla.
   Las que se apartan y se dibujan llevan su altura propia mas abajo. */
#form-padre .fila input:not([type="hidden"]),
#form-padre .fila select {
  flex: none;
  box-sizing: border-box;
  height: 21px;
  min-width: 0;
  padding: 1px 4px;
  font: inherit;
  font-size: 11px;
  line-height: 17px;
}

/* --------------------------------------------------------------------
   ERROR POR CAMPO (pedido del usuario 09/09/2026: "que se marque en rojo
   y muestren el mensaje debajo del input, no ese cartel horrible"). Lo
   pinta `marcarCampoInvalido` de `app.js`; acá sólo el color y la
   posición.

   El rojo NO es nuevo: `--oly-status-danger` y `--oly-status-danger-strong`
   ya visten `.barra-error` (estilos.css) -- se reusan los mismos dos, no se
   inventa un tercero.

   `#form-padre` en el selector es lo que gana sin `!important`: el foco
   nativo (`estilos.css`, `input:focus`) pesa (0,3,1) y un campo marcado
   inválido puede estar enfocado A LA VEZ (`marcarCampoInvalido` enfoca el
   primero que marca) -- sin el id, el borde azul de foco tapa el rojo que
   el operador tiene que ver primero. */
#form-padre .campo-invalido,
#form-padre .campo-invalido:focus {
  border-color: var(--oly-status-danger);
}
#form-padre .campo-invalido:focus {
  box-shadow: 0 0 0 3px var(--oly-status-danger-subtle);
}

/* El mensaje. `position: absolute` a propósito -- ver el comentario de
   `#form-padre .fila` más arriba y el de `marcarCampoInvalido` en app.js--:
   sacarlo del flujo es lo que le impide ser un ítem más del flex de la
   fila y ensancharla o partirla. `app.js` calcula `left`/`top`/`min-width`
   por control (no por fila, que puede llevar varios controles) y los pone
   como estilo en línea; acá sólo lo que no cambia con el control. */
.mensaje-error-campo {
  position: absolute;
  z-index: 1;
  margin: 0;
  padding: 1px 0 0;
  color: var(--oly-status-danger-strong);
  font-size: 10px;
  line-height: 13px;
  white-space: normal;
}

/* =====================================================================
   🔴 LAS FECHAS NO ENTRAN EN LOS 73 px QUE MIDE CONCAR — apartamiento §252
   =====================================================================
   Los anchos de abajo son los del volcado de `CTMOVI09`, pixel a pixel, y el
   de una fecha es `73x21`. En CONCAR eso alcanza: su control es un
   `MaskedTextBox` que dibuja `dd/mm/aaaa` en texto plano y nada mas.

   El de la replica es un `input[type="date"]`, que ademas del texto dibuja el
   BOTON DEL CALENDARIO. Medido en este navegador con la fuente del formulario
   --11px Inter--: necesita **111 px** para enseñar la fecha entera. En 73 px
   se ve `dd/mm/a` y el usuario lo cazo: «las fechas ni se ven completas, a
   las justas se ve un digito de los 4 numeros que tiene el año».

   O sea que copiar el ancho medido con OTRO control da una caja que no se
   puede leer, y el encargo es replicar *lo que la pantalla hace*, no sus
   pixeles cuando el control cambia. Se pone un piso en `em` --no en px-- para
   que siga cuadrando si alguien toca la fuente; el ancho medido sigue escrito
   en el comentario de cada linea, que es lo que hay que restaurar el dia que
   se dibuje una mascara propia sin boton de calendario.

   Vale para TODAS las pantallas, no solo `CTMOVI09`: el mismo control esta en
   `CTMOVI70`, en las fichas de maestros y en los filtros de reportes. */
input[type="date"],
/* Y con la especificidad de la regla que lo aplasta: `#form-padre .fila
   input` pone `min-width: 0` --que esta bien para las cajas de texto, que
   ceden-- y gana por ser un id. Sin esta segunda mitad el piso no se aplica y
   la fecha se sigue viendo cortada, que es lo que pasaba. */
#form-padre .fila input[type="date"] {
  min-width: 10.2em;
}

/* --- marco z44, identificacion --------------------------------------- */
#f-codigo-compra      { width: 289px; }   /* z48 578,231 289x21 */
#f-subdiario          { width: 289px; }   /* z49 578,252 289x21 */
#f-comprobante        { width: 73px;  }   /* z50 578,274  73x21 */
#f-fecha-comprobante  { width: 73px;  }   /* z51 578,295  73x21 (mascara) */
#f-centro-costo       { width: 289px; }   /* z46 578,316 289x21 */

/* --- marco z7, documento y proveedor --------------------------------- */
/* El renglon del proveedor: caja 94, boton pegado a 2 px (674 - 672), la
   razon social de 210, y el `R.U.C.` en 971.

   🔴 LA CAJA DE 210 EXISTE, Y AQUI DECIA QUE NO. Este comentario afirmaba que
   z23 «no existe en la replica: aca la razon social se enseña en la lista de
   sugerencias, y eso ya estaba anotado» -- estaba anotado, si, y estaba mal.
   El usuario lo midio contra CONCAR desktop el 08/09/2026 y la replica metia
   el nombre DENTRO de la caja del codigo: `20517426726  S`, con el nombre
   recortado por los 94 px. Ver §169.

   La cuenta del rotulo cambia con ella: la banda que iba de 695 a 971 --272 px
   con las dos separaciones-- ahora la ocupa la caja de 210, y al rotulo le
   quedan 272 - 210 - 2 = 60. */
#f-proveedor-buscar   { width: 94px;  }   /* z24 578,352  94x21 */
#form-padre .combo-buscable { flex: none; width: 94px; }
#f-proveedor-nombre   { width: 210px; }   /* z23 696,352 210x21, de solo lectura */
#form-padre label[for="f-ruc"]        { width: 60px; }
#f-ruc                { width: 111px; }   /* z22 971,352 111x21 */

/* El documento: el combo de 185 y UNA caja de 144 para el numero completo.
   🟡 APAGADO. Aca decia que la replica parte el documento en serie y numero y
   se reparte los 144 medidos entre las dos --45 + 2 + 97--, y que «el 45 NO es
   un ancho medido: es la mitad elegida», con la hipotesis de que el ComboBox
   oculto de 45x21 que hay en ese mismo sitio fuera la serie.
   El usuario lo midio contra CONCAR el 07/09/2026 y zanjo la pregunta por el
   otro lado: `[0:11:55]` «tu lo separaste por serie y numero. El control lo
   tienes junto, pero desde el guion detecta que lo separa para el registro».
   O sea que no hay que averiguar cuanto mide la serie: no hay caja de serie.
   Una sola caja de 144 --el ancho medido de z21-- y el guion la parte al
   grabar. Con eso desaparecen los dos anchos inventados y queda uno medido.
   Ver DIFERENCIAS §156. */
#f-tipo-documento     { width: 185px; height: 23px; }   /* z15 578,373 185x23 */
/* El -3 no es un apaño: en CONCAR el combo del tipo acaba en 763 y la caja
   del numero arranca en 762, o sea que se PISAN un pixel. Con la separacion
   de 2 que lleva el renglon, la correccion es -3. */
#f-documento          { width: 144px; margin-left: -3px; }   /* z21 762,374 144x21 */

/* Las tres fechas y el anexo: 578 -> 762 -> 971. */
#f-fecha-emision      { width: 73px;  }   /* z26 578,395  73x21 */
#form-padre label[for="f-fecha-vencimiento"] { width: 107px; }  /* -> caja en 304 */
#f-fecha-vencimiento  { width: 85px;  }   /* z25 762,398  85x21 */
#form-padre label[for="f-anexo-ref"]         { width: 120px; }  /* -> caja en 513 */
#f-anexo-ref          { width: 111px; height: 19px; }  /* z11 971,396 111x19 */
/* La descripcion del anexo NO tiene volcado que la mida --no existe en CONCAR,
   §186 punto 5--, asi que su ancho se declara aca con su razon: 210 px es lo
   que mide z23, la razon social del proveedor, que es la caja hermana de esta
   pantalla y hace el mismo trabajo. Las descripciones de anexo llegan a 40
   caracteres en la base y en 210 px entran unos 36, asi que las mas largas se
   cortan igual que se corta una razon social: se ve el principio, que es lo
   que identifica. */
#f-anexo-ref-nombre   { width: 210px; }

#f-isc                { width: 89px;  }   /* z20 578,415  89x21, DESHABILITADO */
#f-igv                { width: 89px;  }   /* z19 578,438  89x21 */
#form-padre label[for="f-tasa-igv"]          { width: 156px; }  /* -> caja en 369 */
#f-tasa-igv           { width: 85px;  }   /* z18 827,438  85x21 */
#f-importe-total      { width: 89px;  }   /* z16 578,459  89x21 */
#form-padre label[for="f-anexo-igv-buscar"]  { width: 322px; }  /* -> caja en 535 */
#f-anexo-igv-buscar   { width: 90px;  }   /* z17 993,458  90x21, DESHABILITADO alla */

/* Los dos botones grandes de la derecha son el marco z27 (1009,410 73x47) con
   z28 de 35x35 y z29 de 31x35. NO miden lo mismo, y ninguno mide 25x41 como
   los del pie. Ya estaban escritos en `.boton-grande-campo`; aca solo se
   confirma que la medida sale de este volcado. */

/* --- marco z0, detraccion -------------------------------------------- */
/* Este marco es el unico donde las cajas miden 20 de alto, no 21. Y la
   columna arranca en 577, un pixel a la izquierda de las demas: esta asi en
   los cinco volcados. */
/* Y el pixel de la izquierda: 577, no 578. Se reproduce acortando la banda
   del rotulo de ESTE marco en 1. Podria ser redondeo de twips de VB6 y no
   intencion --un twip son 1/15 de pixel-- pero esta igual en los cinco
   volcados, asi que se copia y se dice de donde sale en vez de redondearlo
   nosotros. */
/* 🔴 Y va con `:not(.etiqueta-corta)` por una razon medida en el navegador:
   sin eso, esta regla --peso (1,2,1)-- le GANA a las
   `#form-padre label[for="..."]` de abajo, que pesan (1,1,1), y les pone 116
   a las cuatro etiquetas cortas de este marco. Se vio al instante porque las
   cajas de la derecha se movieron 41 y 70 px. Es la misma familia del defecto
   de especificidad de §128, esta vez entre dos reglas MIAS. */
#form-padre .bloque-detraccion .fila > label:not(.etiqueta-corta) { width: 116px; }
#form-padre .bloque-detraccion .fila input { height: 20px; }
#f-detraccion-numero  { width: 89px;  }   /* z2 577,496  89x20 */
#form-padre label[for="f-detraccion-fecha"]   { width: 157px; }  /* -> caja en 369: uno mas,
   porque el renglon arranca en 119 y esta columna sigue siendo la de 827 */
#f-detraccion-fecha   { width: 85px;  }   /* z6 827,496  85x20 */
#form-padre label[for="f-detraccion-importe"] { width: 77px;  }  /* -> caja en 535 */
#f-detraccion-importe { width: 90px;  }   /* z1 993,497  90x20 */

/* El segundo renglon. En CONCAR existe y esta OCULTO, y son TRES cajas:
   z3 577,518 53x19 -- z5 827,518 85x20 -- z4 993,517 90x20. La replica dibuja
   CUATRO campos, por la comparacion en vivo del 07/09/2026, y esa diferencia
   va anotada. Las tres que corresponden toman su ancho medido; la cuarta --la
   descripcion del tipo de tasa, que es nuestra-- toma lo que queda. */
#f-detraccion-tipo-tasa      { width: 53px; height: 19px; }
#f-detraccion-tipo-tasa-desc { width: 106px; }
#form-padre label[for="f-detraccion-tasa"]       { width: 85px; }
#f-detraccion-tasa           { width: 85px; }
#form-padre label[for="f-detraccion-monto-base"] { width: 77px; }
#f-detraccion-monto-base     { width: 90px; }

/* --- marco z35, conversion y glosas ---------------------------------- */
#f-tipo-conversion    { width: 177px; }   /* z39 578,557 177x21 */
#f-tipo-cambio        { width: 73px;  }   /* z38 578,578  73x21 -- renglon PROPIO */
#f-fecha-cambio       { width: 73px;  }   /* z43 578,599  73x21, DESHABILITADO */
#f-glosa-comprobante  { width: 177px; }   /* z37 578,618 177x21 */
#form-padre label[for="f-glosa-movimiento"] { width: 166px; }  /* -> caja en 467 */
#f-glosa-movimiento   { width: 161px; }   /* z36 925,620 161x21 */

/* ==================================================================== */
/* LA VISTA PREVIA DE CONCAR: `PrintPreview`                            */
/* -------------------------------------------------------------------- */
/* Medida al pixel en DOS capturas del propio repositorio --una          */
/* restaurada y otra maximizada-- que coinciden en todo. Los numeros de  */
/* aca salen de `docs/CTLIBR81-VISTA-PREVIA.md` y el arnes              */
/* `herramientas/la-vista-previa-de-concar.mjs` los compara con ese     */
/* documento: una medicion escrita y no implementada es peor que no      */
/* tenerla. Ver DIFERENCIAS 138.                                        */
/* ==================================================================== */

/* Sube sobre `pantalla-reporte`. Un numero PROPIO y no el 41 o el 42 de
   la pila de `CTMOVI90`: esas dos ventanas nunca estan abiertas a la vez
   que esta, pero repetir un `z-index` entre familias distintas es como
   nace el defecto que 136 midio --la ventana que se abria detras de la
   que la habia abierto--. */
#pantalla-vista-previa { z-index: 45; }

/* EL ANCHO: TODO EL QUE HAYA, HASTA EL DEL PAPEL.
   ---------------------------------------------------------------------
   `.ventana:not(.ventana-apilada)` pone `width: max-content`, que cine la
   ventana a su hijo mas ancho -- y el papel esta dentro de una caja con
   `overflow: auto`, asi que NO empuja: la ventana terminaba con el ancho de
   la barra de cinco botones. El 10/09/2026 el usuario lo vio contra una
   pantalla ancha: «ese print deberia poder expandirse porque tiene espacio
   de sobra como para ampliarlo».

   El tope son 2.400 px y no un numero redondo: el Formato 8.1 mide 339
   caracteres a 7,031 px de paso --el medido con `measureText`, ver la nota
   de `.papel-vista-previa`-- o sea 2.384 px, mas los 12 de relleno. Pasado
   ese punto la ventana crece sin ensenar nada, que es el defecto que 138 ya
   corrigio por el otro lado.

   Y no es un apartamiento: en CONCAR esta ventana es un hijo MDI que se
   maximiza, y las dos capturas de `docs/CTLIBR81-VISTA-PREVIA.md` son
   justamente una restaurada y otra maximizada. Ver DIFERENCIAS 262. */
#pantalla-vista-previa {
  width: min(2400px, calc(100vw - 32px));
  /* `.ventana` de `estilos.css` pone `max-width: 1080px` para TODAS las
     ventanas, y sin levantarlo aca el `width` de arriba no se nota: medido
     en el navegador el 10/09/2026, la ventana salia de 1.080 px con 1.440
     de viewport y el papel pidiendo 2.396. */
  max-width: none;
}

/* El menu del padre, que aca vive DENTRO de la ventana porque la replica
   no tiene barra de menu de Windows. Apartamiento de forma, anotado. */
.menu-vista-previa {
  display: flex; gap: var(--oly-space-1);
  padding: 2px var(--oly-space-2);
  border-bottom: 1px solid var(--oly-border-subtle);
  background: var(--oly-surface);
  flex: none;
}
.menu-vp {
  background: transparent; border: none; cursor: default;
  padding: 2px var(--oly-space-2);
  font-size: var(--oly-font-size-xs);
  color: var(--oly-text-primary);
}
.menu-vp:hover { background: var(--oly-surface-subtle); }

/* 🔴 LA BARRA ARRIBA. Es el unico sitio del modulo donde la barra de
   botones no va abajo, y no es un descuido de la regla de la casa: en
   CONCAR esta MEDIDA arriba, entre el titulo y el papel, en las dos
   capturas. `padding-left: 10px` y `gap: 0` no son estetica: el grupo de
   los cinco arranca a 10 px del borde y el paso entre botones es 24, que
   es exactamente el ancho de cada uno. */
.barra-vista-previa {
  display: flex; gap: 0;
  padding: 3px 0 3px 10px;
  border-bottom: 1px solid var(--oly-border-subtle);
  background: var(--oly-surface);
  flex: none;
}
/* 24 x 22, medido. `min-width: 0` porque cualquier `min-width` heredado
   ensancharia el boton y romperia el paso de 24 -- es el empate que ya
   costo la vuelta 43 con `.boton-gs`. */
.boton-vp {
  width: 24px; height: 22px; min-width: 0;
  display: grid; place-items: center;
  padding: 0;
  border: 1px solid var(--oly-border);
  background: var(--oly-surface);
  color: var(--oly-icon-muted);
  cursor: pointer;
}
.boton-vp:hover { background: var(--oly-surface-subtle); }

/* El papel. `line-height: 14px` es el renglon MEDIDO en la captura --el
   `.papel-reporte` usa 1.45, o sea 17,4 px, y por eso el mismo papel
   ocupaba un tercio mas de alto que en CONCAR--. Y los 12 px del tipo no
   se cambian porque ya dan el paso de caracter medido: 7,031 px contra
   los 7,000 de CONCAR, comprobado con `measureText` en el navegador. */
.papel-vista-previa {
  flex: 1 1 auto;
  overflow: auto;
  padding: 4px 6px;
  background: var(--oly-surface);
  font-family: ui-monospace, "Cascadia Mono", Consolas, "Liberation Mono", monospace;
  font-size: 12px;
  line-height: 14px;
  white-space: pre;
}

/* ==================================================================== */
/* IMPRIMIR: SOLO EL PAPEL                                              */
/* -------------------------------------------------------------------- */
/* El primero de los cinco botones de `PrintPreview` es `Imprimir`,      */
/* medido el 07/09/2026 leyendo su tooltip en CONCAR. Llama a            */
/* `window.print()`, que abre el dialogo de impresora DEL SISTEMA -- el  */
/* mismo que CONCAR abre, porque CONCAR usa el `CommonDialog` de VB6 y   */
/* no una pantalla suya (ver DIFERENCIAS 147).                           */
/*                                                                       */
/* Lo que si es decision de la replica es QUE se imprime. Sin estas       */
/* reglas `print()` manda a la impresora la aplicacion entera: el menu,   */
/* la barra de los cinco iconos, las otras 23 ventanas ocultas y el      */
/* papel recortado a la altura de su caja con desplazamiento. Con ellas   */
/* sale el papel y nada mas, a su ancho completo.                         */
/* ==================================================================== */
@media print {
  /* Todo fuera menos la rama que lleva al papel. `visibility` y no
     `display: none`: quitar la caja del flujo desmonta tambien el papel,
     que es hijo de una de las que habria que quitar. */
  body.imprimiendo-vista-previa * { visibility: hidden; }

  /* ------------------------------------------------------------------ */
  /* 🔴 Y EL MISMO TRATO PARA `#reporte-papel`, QUE NO LO TENIA.         */
  /* ------------------------------------------------------------------ */
  /* El 10/09/2026 el usuario pulso `Imprimir` en `CTLIBR81` y el         */
  /* navegador le saco el MENU y el DIALOGO de la replica en una hoja     */
  /* vertical: «tu si te pasaste como vas a imprimir el html enves del    */
  /* reporte??». Tenia razon y la causa era literal -- `libr81Imprimir`,  */
  /* `libr51Imprimir` y `libr61Imprimir` llamaban a `window.print()` a    */
  /* secas, sin poner ninguna clase, mientras que la unica regla          */
  /* `@media print` que existia estaba acotada a `#pantalla-vista-previa`.*/
  /* Habia dos caminos para imprimir el mismo papel y tres botones usaban */
  /* el que no estaba cableado.                                          */
  /*                                                                      */
  /* 🔴 Y LA CAUSA DE FONDO ES OTRA, DICHA POR EL USUARIO EL MISMO DIA:   */
  /* «una de las reglas era que tenias que probar los botones para        */
  /* replicar las acciones no alucinar». Estos tres nunca se pulsaron.    */
  /* Ver DIFERENCIAS 261. */
  body.imprimiendo-el-papel * { visibility: hidden; }
  body.imprimiendo-el-papel #reporte-papel,
  body.imprimiendo-el-papel #reporte-papel * { visibility: visible; }
  body.imprimiendo-el-papel #reporte-papel {
    /* `display` explicito: el papel de las pantallas de reporte nace oculto y
       `visibility` sola no lo trae de vuelta -- una caja en `display: none` no
       genera caja que hacer visible. Es la otra mitad del defecto que se midio
       pulsando el boton. */
    display: block;
    position: absolute; inset: 0;
    overflow: visible; height: auto; max-height: none;
    border: none; box-shadow: none; padding: 0;
  }
  /* Y la vista previa, cuando imprime desde el pie de un reporte, tambien va
     apaisada: el 8.1 mide 339 caracteres. La regla de `@page` de mas abajo es
     una sola para las dos clases. */
  /* Apaisado y sin margenes: el 8.1 mide 339 caracteres y en vertical se
     parte cada renglon en dos. CONCAR lo imprime asi -- su
     `Pre-Configuracion en Modo Grafico`, medida en el aparejo el
     10/09/2026, nace con `Orientacion: Horizontal` y `Tipo de Hoja: A3`. */
  @page { size: A3 landscape; margin: 8mm; }
  body.imprimiendo-vista-previa #pantalla-vista-previa,
  body.imprimiendo-vista-previa #pantalla-vista-previa .papel-vista-previa,
  body.imprimiendo-vista-previa #pantalla-vista-previa .papel-vista-previa * {
    visibility: visible;
  }
  /* El papel deja de ser una caja con desplazamiento y pasa a ser papel:
     sin `overflow` no imprime lo que no cabe en la pantalla, que en el 8.1
     es casi todo (196 lineas). */
  body.imprimiendo-vista-previa #pantalla-vista-previa {
    position: absolute; inset: 0;
    width: auto; height: auto; max-height: none;
    border: none; box-shadow: none;
  }
  body.imprimiendo-vista-previa #pantalla-vista-previa .papel-vista-previa {
    position: absolute; inset: 0;
    overflow: visible; height: auto; max-height: none;
    padding: 0;
    /* El zoom NO viaja al papel impreso. Ampliar en pantalla es para leer;
       imprimir al 200 % partiria cada renglon del Formato 8.1 en dos, y ese
       papel esta medido a 7 px de paso de caracter. */
    font-size: 12px; line-height: 14px;
  }
  /* La barra, el menu y la ayuda de la replica no son papel. */
  body.imprimiendo-vista-previa .barra-vista-previa,
  body.imprimiendo-vista-previa .menu-vista-previa,
  body.imprimiendo-vista-previa .titulo-ventana,
  body.imprimiendo-vista-previa #vp-ayuda { display: none; }
}

/* ===================================================================== */
/* LA GEOMETRIA DE `CTMOVI70`, MEDIDA                                    */
/* ===================================================================== */
/* Misma forma y misma razon que el bloque de `CTMOVI09` de mas arriba, y por
   el mismo pedido del usuario del 07/09/2026: «la idea es que concar web se
   vea igual exactamente igual solo cambiando el .css». La primera version de
   esta pantalla se subio SIN una sola regla: se veia pasable porque
   `.fila-libr81` hacia el trabajo, y las cinco clases del marcado
   --`cuerpo-movi70`, `grupo-movi70`, `columna-movi70`, `botones-movi70` y una
   quinta con un nombre inventado-- no casaban con NADA. Medido en el
   navegador el 07/09/2026: cero reglas con `movi70` en su selector. Es la
   trampa 7 en el CSS --una promesa sin consumidor-- y se caza contando
   reglas, no leyendo el marcado.

   TODO NUMERO DE ESTE BLOQUE SALE DEL VOLCADO, no de la captura:
   `artifacts/rig/share/form.ctmovi70.json` y `.2.json`, reunidos control por
   control en `docs/CTMOVI70-MEDIDA.md` §4. Las dos tomas dan geometria
   IDENTICA y difieren en tres controles (dos combos con texto y la caja
   `Comprobante` habilitada/deshabilitada), que son dos estados de la misma
   pantalla; si hubieran discrepado en la geometria, no seria una medicion.

   POR QUE VA ACOTADO POR `id`: `estilos.css` viste las cajas con
   `input:not([type="radio"]):not([type="checkbox"])`, que pesa (0,2,1). Dos
   clases EMPATAN y el empate lo decide el orden de las hojas, que es el
   defecto de §128. `#pantalla-movi70` pesa (1,x,y) y gana sin depender de
   nada.

   LO QUE **NO** ESTA MEDIDO Y POR ESO NO SE ESCRIBE: la `x` de los rotulos.
   Un `Label` de VB6 no tiene ventana y no sale en el volcado -- de las
   etiquetas se sabe el TEXTO (de la captura) y nada mas. Asi que se
   posicionan las CAJAS por su numero y el rotulo se deja a la derecha de su
   banda, terminando donde la caja empieza. La banda mide 128 porque las cajas
   arrancan en x=141 y el marco en x=13: derivado de dos numeros medidos. */

/* La ventana hugea su contenido en vez de estirarse al hueco entero.
   🔴 CORRECCION DEL 09/09/2026 sobre el comentario que estaba aca: la
   causa NO era un `max-width: 1080px` --ese tope es de `.ventana` estatica,
   y esta es `.ventana-apilada`-- sino el `inset` de las cuatro esquinas
   (`cascaron.css`, bloque de `.ventana-apilada`): con las cuatro fijadas, un
   `width` en `auto` se ESTIRA al hueco completo aunque el marco mida 606. Es
   el mismo defecto que el usuario señaló en `CTANEX03` --«hay espacio de
   sobra a los costados... adaptalos al tamaño de la card»-- medido tambien
   aca: en CONCAR la ventana mide 639 de ancho (el frame del pie, el unico
   control que cruza entera) y la replica la estiraba a 1280 o mas.

   La solucion completa es la misma que se le da a `#pantalla-anex03` mas
   abajo: `width`/`height` en `max-content` --ciñe al contenido-- con
   `max-width`/`max-height` de TOPE para que nunca se salga de la pantalla ni
   pierda el desplazamiento con contenido grande. Los dos numeros del tope
   salen del `inset` BASE de `.ventana-apilada` (60px 40px 40px, sin
   sobreescribir aca) mas el `margin-top: 20px` de `.ventana`: 60+20=80
   arriba, 40 abajo --de ahi `100vh - 120px`-- y 40+40 a los lados --de ahi
   `100vw - 80px`--. Son los MISMOS bordes a los que la ventana ya llegaba
   estirada: el tope no encoge nada que hoy se vea, solo dejar de FORZAR el
   estiramiento cuando el contenido pide menos.

   Medido en el navegador a 1400x900, ANTES -> DESPUES: 1280 -> 634 de ancho
   (sobraba 661), 780 -> 634 de alto con el contenido de hoy (cabe entero sin
   desplazar; con mas datos el `.cuerpo-movi70` de abajo desplaza, como ya
   hacia). */
#pantalla-movi70 {
  width: max-content;
  max-width: calc(100vw - 80px);
  height: max-content;
  max-height: calc(100vh - 120px);
}

.cuerpo-movi70 {
  /* El ancho que se escribe es el MEDIDO --606, el del marco-- y el relleno
     de 13 sale de la `x` del marco. La suma da los 632 de la ventana, y no se
     escribe al reves: poner 632 y deducir el marco fue el primer intento y
     dejaba el cuerpo en 658, medido en el navegador. */
  width: 606px;
  padding: 4px 13px;
  box-sizing: content-box;
}

/* Los dos marcos: 606 medido los dos (`13,125 606x165` y `13,290 606x118`).
   Se tocan como en CONCAR --290 - (125 + 165) = 0-- asi que no llevan hueco
   entre ellos. */
.grupo-movi70 {
  width: 606px;
  box-sizing: border-box;
  margin: 0;
  padding: 4px 0;
  border: 1px solid var(--oly-border-subtle);
  border-radius: 0;
}
.grupo-movi70 + .grupo-movi70 { border-top: none; }

/* El grupo 1 pone la columna de campos y el marco de los dos botones LADO A
   LADO, porque en el volcado ese marco esta en `433,213`: dentro del grupo,
   a la derecha y a la altura del tercer renglon. */
.banda-movi70 { display: flex; align-items: flex-start; gap: 3px; }
/* `flex: none` y NO `1 1 auto`: estirada, la columna se comia el sobrante y
   empujaba el marco de los botones a x=550 en vez de 433 -- medido en el
   navegador antes de creerlo. Sin estirar mide su contenido, 416
   (14 del borde + 125 de banda + 2 de separacion + 289 de la caja mas ancha),
   y con los 3 de hueco el marco cae en 433 EXACTO, que es el numero del
   volcado. Los 3 no son un apaño: son 433 - 430. */
.columna-movi70 { flex: none; min-width: 0; }

#pantalla-movi70 .fila-libr81 {
  gap: 2px;
  margin-bottom: 2px;
  flex-wrap: nowrap;
}
#pantalla-movi70 .fila-libr81 > label {
  /* 128 - 1 del borde del marco - 2 de la separacion rotulo/caja = 125. La
     misma cuenta que `.marco-medido` (§110) y el bloque del 09 ya hacian. */
  width: 125px;
  min-width: 0;
  box-sizing: border-box;
  padding-right: 6px;
  text-align: left;
}

/* Ninguna caja se estira: cada una lleva su ancho medido. La altura es 21 en
   los TRECE controles de entrada visibles --contados uno por uno en las dos
   tablas de §4, no a ojo-- salvo la casilla `Conversion`, que es 17, y los
   cuatro botones, que son 35 y 41. Las que se apartan van mas abajo. */
#pantalla-movi70 .fila-libr81 input:not([type="checkbox"]),
#pantalla-movi70 .fila-libr81 select {
  flex: none;
  box-sizing: border-box;
  height: 21px;
  min-width: 0;
  padding: 1px 4px;
  font: inherit;
  font-size: 11px;
  line-height: 17px;
}

/* --- grupo 1, identificacion (`13,125 606x165`) ---------------------- */
#movi70-subdiario    { width: 289px; }   /* ComboBox      141,141 289x21 */
#movi70-comprobante  { width: 73px;  }   /* TextBox       141,165  73x21 */
#movi70-fecha        { width: 73px;  }   /* MaskedTextBox 141,189  73x21 */
#movi70-moneda       { width: 289px; }   /* ComboBox      141,213 289x21 */
#movi70-glosa        { width: 289px; }   /* TextBox       141,237 289x21 */

/* La casilla `Conversion` NO esta en la banda de rotulos: su control mide
   `27,262 127x17`, o sea que arranca 14 px a la derecha del marco (27 - 13) y
   no en la columna de 141 donde caen las seis cajas. Por eso este renglon no
   reserva banda, y el texto va antes de la casilla como en la captura. */
/* 13 y no 14: el marco ya se lleva 1 px de borde, asi que con 14 la casilla
   caia en 28 -- medido en el navegador, no calculado. El control arranca en
   27 (13 del marco + 1 del borde + 13). */
.fila-casilla-libr81 { padding-left: 13px; }
#pantalla-movi70 .fila-casilla-libr81 > label {
  /* 127x17 es el tamaño del CONTROL en el volcado, texto y casilla juntos:
     un `CheckBox` de VB6 es una sola ventana. Se escribe el numero medido en
     vez de dejarlo al largo del texto, que depende de la tipografia. */
  width: 127px;
  /* `height` y no `min-height`: con el minimo el renglon medía 20 porque la
     casilla nativa trae 3 px de margen propio. Medido en el navegador. */
  height: 17px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  overflow: hidden;
}
/* 🟡 El TAMAÑO DE LA CASILLA en si no está medido: el volcado da el control
   entero --127x17, texto y casilla juntos, porque un `CheckBox` de VB6 es una
   sola ventana-- y no la caja por separado. Así que acá sólo se le quita el
   margen propio del navegador, para que el control quepa en sus 17 medidos, y
   su tamaño se deja el nativo. Poner un 13x13 «medido» sería inventar. */
#movi70-conversion { margin: 0; }

/* El marco de los dos botones: `433,213 71x45`, con los botones de 31x35 y
   35x35. Va a la altura del tercer renglon --el de `Fecha Comprobante`
   termina en 189 + 21 = 210, y el marco arranca en 213--, asi que se empuja
   con el margen de arriba en vez de posicionarlo absoluto: 213 - 125 - 4 del
   relleno del marco = 84 desde el borde de arriba del grupo. */
.botones-movi70 {
  flex: none;
  display: flex;
  gap: 2px;
  width: 71px;
  box-sizing: border-box;
  margin-top: 84px;   /* 213 - 125 - 4 del relleno del marco */
  padding: 4px 2px;
  border: 1px solid var(--oly-border-subtle);
}
/* 🟡 LOS DOS BOTONES NO SON `boton-gs`, Y SE DICE. `boton-gs` es la caja de
   25x41 del pie, que esta medida (§79). Estos dos miden 31x35 y 35x35 en el
   volcado -- distintos entre si y distintos del pie. Se escriben sus numeros
   y se deja la clase por el icono, que es lo unico que comparten. */
#movi70-icono-1 { width: 31px; height: 35px; }
#movi70-icono-2 { width: 35px; height: 35px; }

/* --- grupo 2, estado (`13,290 606x118`) ------------------------------ */
#movi70-situacion    { width: 97px; }   /* 141,306  97x21 */
#movi70-total        { width: 97px; }   /* 141,330  97x21 */
#movi70-tasa-igv     { width: 97px; }   /* 413,330  97x21 -- el UNICO habilitado */
#movi70-fecha-control{ width: 57px; }   /* 141,354  57x21 */
#movi70-hora-control { width: 37px; }   /* 200,354  37x21 */
#movi70-usuario      { width: 97px; }   /* 141,378  97x21 */

/* La banda del rotulo `Tasa IGV`: la caja de `Total Comprobante` acaba en
   141 + 97 = 238 y la de `Tasa IGV` arranca en 413, o sea 175 de banda menos
   los 2 de separacion del renglon. Derivado de tres numeros medidos. */
/* 171 y no 173: la caja de `Total Comprobante` acaba en 238, y de ahi al 413
   de `Tasa IGV` hay 175 -- pero DOS de esos 175 se los lleva la separacion
   del renglon en cada lado del rotulo (2 + 171 + 2 = 175). Con 173 la caja
   caia en 415, medido en el navegador. La cuenta a mano se equivoco por el
   hueco que ya estaba puesto. */
#pantalla-movi70 label[for="movi70-tasa-igv"] { width: 171px; }

/* Y las dos cajas de `Fecha/Hora Control` se PISAN un pixel en CONCAR: la
   primera acaba en 141 + 57 = 198 y la segunda arranca en 200, o sea 2 de
   hueco, que es exactamente el `gap` del renglon. No hay correccion que
   hacer; se anota porque el 09 si necesito una (-3) y la diferencia entre
   «no hace falta» y «se olvido» tiene que estar escrita. */

/* ==================================================================== */
/* LA VENTANA CABE EN LA PANTALLA, Y EL PIE SIEMPRE SE ALCANZA          */
/* ==================================================================== */
/* POR QUE EXISTE. El 07/09/2026, el usuario:

       «escuchame los forms que tenemos tienen que tener un max de tamaño de
        lo que alcance en la web porque si no los cientos de registros vamos
        a tener que bajar el scroll hasta el último para poder hacer alguna
        acción del footer»

   Medido en el navegador --no deducido-- inyectando 400 renglones de 18 px en
   el cuerpo de cada seccion, a 1440x900. Cuanto habia que BAJAR para que el
   pie entrara en la vista:

       pantalla-inicio ............ 6810 px
       pantalla-pagp .............. 6834 px
       pantalla-situacion ......... 6550 px
       pantalla-situacion-detalle . 6867 px
       pantalla-reporte ........... 6632 px
       pantalla-comp .............. 6513 px
       pantalla-pendiente ......... 6743 px
       ventana-padre .............. 7016 px

   OCHO de las DIECISIETE ventanas estaticas --24 secciones menos las siete
   apiladas--. Las otras nueve se salvaban, y no
   por disciplina: por CUATRO topes escritos a mano con cuatro numeros
   distintos --`.scroll-maestro` 260, `.cuerpo-honp` 265, `.cuerpo-regc22`
   300, `.caja-grilla-comp` 470--, cada uno medido contra SU pantalla. O sea
   que la regla estaba cuatro veces escrita y nueve veces sin escribir: la
   misma forma de 73, un dibujo por sitio y nadie comparandolos.

   ------------------------------------------------------------------
   HAY DOS CLASES DE VENTANA Y NO SE ARREGLAN IGUAL. TAMBIEN MEDIDO.
   ------------------------------------------------------------------
   La `.ventana` estatica es una tarjeta en el flujo del documento: crece
   hacia abajo sin tope y el pie se va con ella. Acota + desplaza la SECCION,
   y el pie se pega con `sticky`. No hace falta tocar el marcado, que es lo
   que el usuario eligio cuando se le pregunto por `ventana-hijo` --cuatro
   hermanos y un pie-- y por `pantalla-reporte`, que tiene los dos dialogos
   entre los parametros y el papel.

   ⚠️ `ventana-hijo` YA NO ES DE ESTA CLASE, desde la vuelta 75, y la frase
   de arriba se deja escrita porque la eleccion del usuario sigue en pie: lo
   que eligio fue QUE EL PIE SE ALCANCE sin tocar el marcado, y el marcado se
   toco por OTRA razon medida --la ventana tenia que salir ENCIMA de la padre,
   modal, y una `.ventana` estatica no puede--. Al pasar a apilada su pie se
   alcanza por el otro mecanismo, el de esta misma seccion: cuerpo que se
   reparte y rejilla que desplaza. Ver `#ventana-hijo` mas arriba.

   La `.ventana-apilada` es otra cosa: `position: fixed` con `inset`, o sea YA
   acotada al viewport, columna flex y `overflow: hidden`. Ahi el `sticky` no
   sirve --no hay nada que desplace-- y lo que sobra NO SE ALCANZA DE NINGUNA
   MANERA. Su cuerpo tiene que ser el que se desplaza.

   🔴 Y una de las siete lo tenia mal, medido SIN inyectar nada, a 1280x420 y
   con el contenido propio de la pantalla: en `#pantalla-movi70` la seccion va
   de y=80 a y=380 y su `#movi70-pie` --el que lleva `Grabar` y `Salir`-- iba
   de 400 a 461, o sea que sobresalia 81 px POR DEBAJO del borde de la
   ventana, recortado y sin forma de llegar. `.cuerpo-movi70` no declaraba
   `flex` --y el valor por omision es `0 1 auto`-- ni `overflow`: ni se
   encogia ni desplazaba.

   🔴 Y ese numero estuvo mal escrito primero, en SEIS sitios: decia 162 px,
   que es 462 menos 300. Restarle a la `y` del pie la ALTURA de la seccion en
   vez de su BORDE INFERIOR es un error de resta, y lo cazo el auditor. La
   medicion era buena --y=462, catorce descendientes fuera-- y la cuenta no.

   Las otras seis estan bien, y dos lo estan A PROPOSITO de una manera que
   parece el defecto: `#movi90-detalle .cuerpo-detalle` y
   `#pantalla-movi60 .cuerpo-detalle` llevan `overflow: hidden` porque la que
   se desplaza es la GRILLA de dentro --en `movi90-nivel2.png` la grilla tiene
   su propia barra y la ficha se ve al mismo tiempo, ver 136--. Inyectarles un
   bloque al final del cuerpo las pinta como recortadas; es artefacto de la
   inyeccion, no un defecto suyo. Medido con su contenido real a 420 px de
   alto: cero descendientes fuera de la seccion.

   ------------------------------------------------------------------
   EL 117
   ------------------------------------------------------------------
   77 + 20 + 20, los tres medidos a 1280x420 y a 1440x900: `#barra-menu` mide
   77 px y es `sticky`, `.ventana` trae 20 px de `margin-top` --la primera
   arranca en `top: 97`-- y quedan otros 20 de aire abajo. */
/* 🔴 `width: max-content`, EL PEDIDO DEL 09/09/2026: «ese crear proveedor
   parece hecho a la que me importa porque hay espacio de sobra a los
   costados, asegurate que ningun form se vea asi y adaptalos al tamaño de
   la card». `.ventana` (`estilos.css`) sólo pone un TOPE --`max-width:
   1080px`-- y sin ancho propio un bloque ocupa TODO lo que el tope permite,
   asi que toda ventana estatica se estiraba a 1080 aunque su contenido
   pidiera la mitad. `max-content` la ciñe al MAS ANCHO de sus hijos --el
   fieldset, la fila de campos o la tabla, lo que sea mas ancho-- y el
   `max-width` de `.ventana` se queda de tope por si algun contenido pidiera
   mas de 1080.

   Medido en el navegador a 1400x900, ANTES -> DESPUES de esta linea (ancho
   de la ventana; ver tambien la cita de `.titulo-ventana > span` mas abajo,
   que evita que el TITULO sea el que decida el ancho):
     CTREGC27 (`pantalla-regc27`) ....... 1080 -> 424  (sobraba 822)
     CTREGC25 (`pantalla-regc25`) ....... 1080 -> 435  (sobraba 811)
     CTPLE551 (`pantalla-ple551`) ....... 1080 -> 781  (sobraba 493)
   Las demas estaticas (`pantalla-inicio`, `pantalla-pagp`, etc.) bajan igual,
   todas por debajo de su contenido real; no se listan una por una porque
   ninguna llevaba un numero citado antes de hoy. */
.ventana:not(.ventana-apilada) {
  width: max-content;
  max-height: calc(100vh - 117px);
  /* `overflow-x: hidden` y no `auto`: el recorte horizontal es el que ya
     hacia el `overflow: hidden` de `estilos.css` --redondea las esquinas-- y
     ninguna ventana debe sacar barra horizontal. La que tiene contenido mas
     ancho que la caja se la saca ADENTRO (`.papel-reporte`, `.cuerpo-regc22`). */
  overflow-y: auto;
  overflow-x: hidden;
}

/* 🔴 Y EL TITULO NO PUEDE SER EL QUE DECIDA EL ANCHO.
   `width: max-content` de arriba ciñe la ventana al hijo MAS ancho, y en
   `CTREGC27` ese hijo no era el formulario: era el `<span>` del titulo,
   "Genera Archivo Mensual Compras IGV 18%, 10.5% y 10% 2023 2026 CTREGC27",
   que sin envolver mide 533 px --medido clonando el nodo con
   `width: max-content` y sin restricciones--, mas ancho que el CUERPO del
   formulario (422 px, `.cuerpo-regc27` medido igual). Sin este tope la
   ventana quedaba con 111 px de mas SOLO por el rotulo del titulo, exactos
   los que sobran entre 533 y 422 -- el mismo defecto que el usuario señalo,
   solo que aca lo causaba el titulo y no el cuerpo.

   Esto es un DEFECTO y no una regla de CONCAR: alla el titulo vive en la
   barra de titulo NATIVA de Windows, que no tiene ancho propio que darle al
   formulario --es al reves, la ventana decide y Windows recorta el rotulo
   con `...` si no entra--. Aca el titulo es una fila mas del documento, asi
   que si no se limita SI empuja.

   🔴 300 Y NO 400: el primer numero escrito aca (400) SEGUIA sin alcanzar,
   medido en el navegador. La fila del titulo entera --el punto de sesion,
   el `<span>`, el boton `✕`, el `gap` y el `padding` de `.titulo-ventana`--
   pesa unos 96px MAS que el `<span>` solo, asi que un tope de 400 en el
   span deja la FILA en ~496 y esa fila seguia siendo mas ancha que el
   cuerpo de `CTREGC27` (422 medido, `.cuerpo-regc27` clonado igual). Bajado
   a 300 --por debajo de 422 y de 433 (`CTREGC25`) incluso sumando esos 96--
   el cuerpo vuelve a ser quien decide el ancho, que es el punto: que
   NINGUN titulo le gane al formulario que esta anunciando.

   Medido en los 27 titulos de la casa (`querySelectorAll('.titulo-ventana >
   span')`, clonados y medidos sin restriccion, los nueve mas anchos):
   `CTREGC27` 533, `CTPLEC5xx` 507, `CTPLEC581` 416, `CTREGC22` 402,
   `CPPAGP01` 401, `CTREGC25` 374, `CTMOVI60` 361, `CTMOVI90` 352 y
   `CTHONP01` 341 -- los nueve por encima de 300, y por eso los nueve
   envuelven a una segunda linea con esta regla. De esos, `CTREGC27` y
   `CTREGC25` son dos de los TRES que este mismo cambio de sesion arregla
   (ver la tabla de `.ventana:not(.ventana-apilada)` mas arriba) y quedaron
   verificados con el cuerpo real cargado. Los otros siete NO se
   contrastaron con su cuerpo real -- `CTREGC22`, `CPPAGP01` y `CTMOVI90`
   pintan su grilla con JavaScript recien al abrirlos, y no se cargo esa
   grilla para esta medicion --, asi que de ellos solo se sabe que el
   TITULO ya no puede ser el que decida el ancho; no se afirma que su
   ventana haya bajado de tamaño, que es lo que pide la regla de no
   escribir una ausencia sin haber buscado. */
.titulo-ventana > span {
  max-width: 300px;
  min-width: 0;
  overflow-wrap: break-word;
  /* 🔴 `pre-wrap` PORQUE CONCAR TITULA CON DOS ESPACIOS Y EL NAVEGADOR LOS
     COLAPSA. `Mantenimiento Tipo de Cambio··CTCAMB01` --dos espacios y ningún
     guion-- es el hallazgo entero de DIFERENCIAS §293, y sin esta línea era
     invisible en pantalla: el fuente decía dos y el contador veía uno, que es
     justo el defecto que §293 fue a arreglar.

     Medido el 11/09/2026 en el navegador, contra estas mismas hojas, con un
     `Range` sobre el texto para saltarse el `max-width` de aquí arriba:

       white-space: normal (como estaba)   dos espacios 332,61 px
                                           un espacio   332,61 px   <- iguales
       white-space: pre-wrap               dos espacios 336,64 px
                                           un espacio   332,61 px   <- distintos

     Va `pre-wrap` y no `pre`: `pre` prohíbe el salto de línea y arriba hay un
     `max-width: 300px` con `overflow-wrap: break-word` que cuenta con poder
     partir. `pre-wrap` conserva los espacios y deja envolver.

     Lo cazó el auditor, y es la forma de siempre: la medición estaba en el
     fuente y no llegaba a la pantalla. */
  white-space: pre-wrap;
}

/* EL PIE SE PEGA ABAJO. `:last-child` no es adorno: `pantalla-maestro` tiene
   DOS pies hermanos --`#maestro-botones` y luego `.barra-inferior`-- y dos
   `sticky` en `bottom: 0` se taparian entre si. Se pega el ULTIMO, y esa
   ventana no necesita mas porque su `.scroll-maestro` ya acota la grilla a
   640 px y el pie se alcanza sin bajar nada (medido: 0 px).

   🟡 Si aparece una ventana con dos pies hermanos donde el PRIMERO lleve
   acciones que haya que alcanzar, esto no basta y hay que decidirlo ahi. */
.ventana:not(.ventana-apilada) > .barra-inferior:last-child,
.ventana:not(.ventana-apilada) > .barra-botones:last-child,
.ventana:not(.ventana-apilada) > .barra-pagp:last-child,
.ventana:not(.ventana-apilada) > .barra-comp:last-child,
.ventana:not(.ventana-apilada) > .barra-pie-concar:last-child,
.ventana:not(.ventana-apilada) > .pie-regc22:last-child {
  position: sticky;
  bottom: 0;
  z-index: 2;
}
/* Y los TRES que no traen fondo propio necesitan uno, porque un pie pegado
   sin fondo deja ver el contenido pasando por debajo. Medido el
   `backgroundColor` calculado de los nueve pies: `rgba(0, 0, 0, 0)` en
   `.barra-pagp`, `.barra-pie-concar` y `.pie-regc22`; los otros seis ya
   traen el suyo y NO se les toca --`.barra-inferior`, `#maestro-botones` y
   `.barra-firme` son `rgb(249,249,249)`, que es `--oly-surface-subtle`, y
   pintarlos de `--oly-surface` les cambiaria el color--. */
.ventana:not(.ventana-apilada) > .barra-pagp:last-child,
.ventana:not(.ventana-apilada) > .barra-pie-concar:last-child,
.ventana:not(.ventana-apilada) > .pie-regc22:last-child {
  background: var(--oly-surface);
}

/* 🔴 Y `pantalla-maestro` NECESITA OTRA COSA, PORQUE TIENE DOS PIES.
   La primera version de este bloque dijo que no le hacia falta nada porque
   `.scroll-maestro` acota la grilla a 640 px «y el pie se alcanza sin bajar
   nada (medido: 0 px)». ESA MEDICION ERA DE LA PANTALLA VACIA. Con la
   grilla llena --`CTPLAN01`, 100 filas-- la seccion desplaza 50 px, y como
   el que se pega es el ULTIMO pie, `.barra-inferior` aterriza ENCIMA de
   `#maestro-botones`: medido a 1440x900, los botones en 844..890 con la
   barra pegada en 840..879, y `document.elementFromPoint` sobre el primer
   boton devuelve `barra-inferior`. O sea que Crear, Modificar y Eliminar
   quedaron INCLICABLES en los dieciocho maestros. Peor que el defecto que
   esta vuelta venia a arreglar, y el 🟡 que lo declaraba «hoy no hace falta»
   describia justo lo que si pasaba.

   La aritmetica dice que no era cuestion de afinar un numero: `.scroll-maestro`
   se acota en `100vh - 260` y la seccion en `100vh - 117`, o sea 143 px de
   diferencia, y el cromo de la pantalla mide 191 --titulo 53, filtros 53,
   botones 46, barra 39--. Sobran ~48 px SIEMPRE.

   Asi que esta seccion no se desplaza: se reparte. Columna flex, la grilla se
   come el alto que sobra y los dos pies quedan FUERA del reparto. Con eso la
   seccion nunca saca barra propia --se va tambien la doble barra de
   desplazamiento-- y los dos pies estan siempre a la vista, sea el cromo el
   que sea. Es la unica seccion con dos pies hermanos, y el arnes lo vigila:
   si aparece otra, hay que traerla aca. */
/* `> *` y no la lista de los nueve hijos: cuatro de ellos nacen ocultos
   --subtitulo, pie de grilla, panel de parametros y franja de edicion-- y
   aparecen segun el maestro y el modo, asi que enumerarlos deja fuera al que
   se agregue manana. Medido el peor caso, los CUATRO visibles a 1280x620: la
   grilla baja a 153 px, la seccion NO desplaza y los dos pies siguen a la
   vista. */
#pantalla-maestro { display: flex; flex-direction: column; }
#pantalla-maestro > * { flex: none; }
#pantalla-maestro > .scroll-maestro { flex: 1 1 auto; min-height: 0; }

/* EL CUERPO DE LA APILADA SE COME EL ALTO QUE SOBRA Y SE DESPLAZA. Es lo
   mismo que ya hace `.cuerpo-detalle` --y por lo mismo: sin `min-height: 0`
   un hijo flexible no baja de su `min-content` y el `overflow` no entra en
   juego--; a `.cuerpo-movi70` le faltaba. */
.cuerpo-movi70 {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

/* ===================================================================== */
/* EL COMBO CON BUSCADOR                                                 */
/* ===================================================================== */
/* Tercera regla transversal del 07/09/2026: todo desplegable lleva
   buscador. El `<select>` sigue en el DOM --es el que guarda el valor y el
   que leen todos los lectores que ya existen-- y se esconde; encima va una
   caja de texto y una lista. Ver `frontend/combo-buscable.js` y §149.

   `position: relative` en el envoltorio y `absolute` en la lista: la lista
   flota SOBRE lo que sigue en vez de empujarlo. Es el unico `absolute`
   nuevo de pantalla desde §142, y por eso se declara en el censo de
   `la-barra-que-no-flota.mjs` con esta razon. */
.combo-buscador { position: relative; display: inline-block; }

/* 🔴 EL `<select>` SE QUEDA EN EL FLUJO, Y OCUPANDO SU CAJA MEDIDA. Se le
   quita la tinta (`opacity`) y el raton (`pointer-events`), no el sitio.

   La primera version lo sacaba con `position: absolute; width: 1px`, y con eso
   el envoltorio se quedaba SIN ANCHO: los anchos medidos de esta pantalla
   estan escritos contra el `<select>` --`#f-codigo-compra { width: 289px }`,
   que es el z48 de CONCAR-- y un `inline-block` vacio se encoge al ancho por
   omision de un `<input>`. El usuario lo vio el 07/09/2026 y lo dijo con las
   dos pantallas al lado: «eso esta comprimido en un espacio pequeño cuando
   puedes aprovechar mas», con `91625102 A` y `10 REGISTRO C` cortados donde
   CONCAR ensena la fila entera.

   Dejandolo en flujo, el envoltorio mide lo que mide el `<select>` y CADA
   pantalla conserva su ancho medido sin escribir una regla mas. El comentario
   que habia aca decia «la caja hereda el ancho de la que reemplaza» y era
   falso: no habia nada que se lo pasara. */
.combo-buscador-oculto { opacity: 0; pointer-events: none; }

/* Y la caja de texto se pone ENCIMA, tapandolo exactamente.

   🔴 EL `> ` DEL SEGUNDO SELECTOR ES LA PROTECCION, no una preferencia de
   estilo. Esta caja tapa al `<select>` que lleva el ancho medido de la
   pantalla, asi que cualquier regla de pantalla que apunte a `<input>` --y
   hay varias, porque casi toda franja tiene cajas de dos o tres digitos-- se
   la lleva puesta y el combo queda ancho por fuera y estrecho por dentro. Le
   paso a `.campo-regc27 input` el 10/09/2026 (ver alli). Con dos clases pesa
   (0,2,0) y le gana a `.clase input`, que pesa (0,1,1). */
.combo-buscador-caja {
  position: absolute;
  inset: 0;
  width: 100%;
}
.combo-buscador > .combo-buscador-caja { width: 100%; text-align: left; }

/* 🔴 `absolute` ACA, Y EL JS LA PROMUEVE A `fixed` CUANDO HAY RECORTE.
   ---------------------------------------------------------------------
   El comentario que habia aca decia que esta lista «FLOTA sobre lo que hay
   debajo, como la de un `<select>` nativo». Era falso: toda `.ventana` de la
   replica es un contexto de recorte --`overflow-y: auto` mas el
   `overflow: hidden` de `estilos.css`-- y un `absolute` no flota fuera de
   el. La de un `<select>` nativo si flota, pero porque la dibuja el sistema
   operativo, no el documento.

   Lo trajo el usuario el 11/09/2026 con `CTLIBR52`, que es el caso peor
   porque `Moneda` es su ULTIMA fila: «sale cortado, como que por debajo del
   borde». Medido a 1024x768: 27 px de lista fuera, y el `scrollHeight` de la
   ventana subiendo de 271 a 299 -- la lista no se salia, ENSANCHABA el
   scroll.

   El arreglo NO es `position: fixed` aca. Es el mismo que §172 §1 ya le hizo
   a `.sugerencias` el 08/09/2026, cuando midio que «esto valia para las 25»:
   `colocarListaFlotante` de `app.js` la promueve a `fixed` EN LINEA, y solo
   si `laRecortaUnAncestro` dice que hace falta. Fijarlo aca seria decidir
   por CSS lo que depende del sitio, y dejaria dos sitios calculando lo mismo.

   Por eso el bloque se queda como estaba --`absolute`, con su `top`/`left`
   y su `max-height` de tope--: ese es el estado del que parte el JS, y el que
   queda si el JS no llega a correr. Ver DIFERENCIAS §172 §1 y §295. */
.combo-buscador-lista {
  position: absolute; z-index: 60;
  top: 100%; left: 0; min-width: 100%;
  max-height: 260px; overflow-y: auto;
  margin: 0; padding: 2px 0;
  list-style: none;
  background: #fff;
  border: 1px solid #7a7a7a;
  box-shadow: 0 4px 10px rgba(0, 0, 0, .18);
  white-space: pre;
}
.combo-buscador-lista li {
  padding: 2px 8px;
  font: inherit;
  cursor: default;
}
.combo-buscador-lista li.marcada,
.combo-buscador-lista li:hover { background: #0a246a; color: #fff; }
.combo-buscador-lista li.elegida { font-weight: 600; }
/* El aviso de «no hay ninguna» no se puede elegir y no se pinta como fila. */
.combo-buscador-lista li.combo-buscador-vacio {
  color: #7a4a00; font-style: italic; cursor: default;
}
.combo-buscador-lista li.combo-buscador-vacio:hover { background: #fff; color: #7a4a00; }

/* =====================================================================
   LA NOTA AZUL DEL PADRON (`CTANEX03`)
   ---------------------------------------------------------------------
   CONCAR escribe `*Datos Obtenidos de la SUNAT`, `NATURAL`, `HABIDO` y
   `ACTIVO` en azul, junto al campo, no en la franja de avisos. Se copia el
   sitio y el color porque es lo que el contador busca con la vista.
   🔴 Y se copia SOLO cuando hay respuesta: la mitad del arreglo de §149
   es que estas palabras no aparezcan cuando nadie contestó.
   ===================================================================== */
.nota-sunat {
  color: #0000c0;
  font-size: 11px;
  line-height: 13px;
  margin-left: 8px;
  white-space: pre-line;
}

/* --- el rebote del `Cálculo Compra` -----------------------------------
   Este bloque NO copia nada de CONCAR: es el apartamiento de §159 --CONCAR
   informa y sigue-- así que no hay medida que respetar y se pinta con los
   tokens del cascarón. Rojo de aviso, y la casilla debajo del texto para que
   el orden de lectura sea «esto está mal» y sólo después «forzarlo». */
.aviso-rebote {
  margin: 6px 8px 0;
  padding: 6px 8px;
  border: 1px solid var(--rojo-borde, #b00020);
  background: var(--rojo-fondo, #fdecee);
  font-size: 12px;
  line-height: 15px;
}
.aviso-rebote p { margin: 0 0 4px; color: var(--rojo-texto, #8a0018); }
.aviso-rebote label { display: flex; align-items: center; gap: 6px; }

/* =====================================================================
   `Creación` de `Detalle de Comprobante` -- las DOS COLUMNAS (B2, §168)
   =====================================================================
   CONCAR reparte los 19 campos en dos columnas dentro del mismo groupbox:
   ocho filas a la izquierda y ocho a la derecha, medido en
   `docs/capturas-concar/ctmovi09-0002-detalle-creacion-ceco.png`. La
   replica los tenia en UNA fila con dos campos.

   `flex-wrap: wrap` y un `min-width` por columna a proposito: si la ventana
   se angosta, la derecha baja debajo de la izquierda en vez de comprimir
   las cajas hasta que el rotulo `Nro.Dcmto.Refer.` se corte. La regla de la
   casa dice que el pie siempre se alcanza (§144), y una columna que baja es
   scroll vertical, que si se alcanza; una caja recortada no se arregla
   sola. */
#bloque-creacion .creacion-columnas {
  display: flex; flex-wrap: wrap; gap: 0 24px; align-items: flex-start;
}
#bloque-creacion .creacion-columna { flex: 1 1 420px; min-width: 0; }

/* El rotulo mas largo de la seccion es `Nro.Dcmto.Refer.`. Con los 128 px
   de `.fila label` se corta, asi que la banda de rotulo de ESTE bloque va a
   116 --el mismo ancho que ya usa `.bloque-detraccion` por la misma razon--
   y el tamaño de letra de la etiqueta corta cede un punto. Medido en el
   navegador a 1440x900: ningun rotulo de los 19 se corta. */
#bloque-creacion .fila > label:not(.etiqueta-corta) { width: 116px; }
#bloque-creacion .fila > label.etiqueta-corta { min-width: 0; }

/* La caja ancha de `Tipo Tasa`: la descripcion que resuelve el codigo. En la
   captura ocupa el resto de la fila. */
#bloque-creacion input.campo-descripcion { flex: 1 1 160px; }

/* 🔴 LAS TRES CAJAS CORTAS DE `Creación`, POR ID Y EN `ch`.
   Los 128 px de `.campo-corto` son el campo corto de la casa; estas tres
   piden menos, y lo que se sabe de ellas no es un ancho en pixeles del
   navegador sino CUANTOS CARACTERES ENSENAN, que es un dato que si viaja
   entre las dos metricas:

     `Secuencia` ... cuatro digitos. La columna `Sec.` de la rejilla dice
                     `0001`, `0002`, `0003` --misma captura-- y el volcado le
                     da una caja gris de 33 px en un marco de 625.
     `Debe-Haber` .. UN caracter. En la captura la caja lleva una `D` sola y
                     en el volcado mide 25 px, la mas estrecha del marco.
                     `spec/reglas-registro-comprobantes.md` §12c la declara
                     de un caracter (`D`/`H`).
     `Tipo Tasa` ... DOS, el codigo `28` o `29` de `TAGP TCOD`
                     (`spec/reglas-documentos-compras-ventas.md` §3e y §3f).
                     Volcado `controlId: 8`, 49 px.

   En `ch` --no en px-- por lo mismo que las siete cajas de la cabecera: si
   quien mira cambia el tamano de letra del navegador, una caja de cuatro
   digitos sigue cabiendo cuatro digitos. Y `flex: 0 0 auto` para que el
   reparto de la fila no se las lleve por delante.

   ⚠️ Y AL LADO DE LA CAJA NO HAY NADA MAS, que es lo que dice la captura: la
   fila de `Secuencia` y la de `Debe-Haber` acaban ahi, con el hueco a la
   derecha. Rellenarlo seria dibujar un campo que CONCAR no tiene. */
#f-cr-secuencia { flex: 0 0 auto; width: 7ch; }
#f-cr-debe-haber { flex: 0 0 auto; width: 4ch; }
#f-cr-tipo-tasa { flex: 0 0 auto; width: 5ch; }

/* 🔴 LAS CUATRO FILAS DE DOS PAREJAS SE PARTIAN EN DOS RENGLONES, MEDIDO.
   En CONCAR cada una de estas cuatro es UN renglon con sus dos parejas al
   lado --`Fec.Dcmto.`/`Fec.Vmto.`, `Nro.Dcmto.Refer.`/`Fec.Doc.Ref.`,
   `Tipo Tasa` con sus dos cajas y `Tasa`/`Monto Base`, las cuatro en
   `ctmovi09-0002-detalle-creacion-ceco.png`--. La replica bajaba la segunda
   caja a un renglon propio y a lo ancho de la columna entera: medido en el
   navegador a 1440x900, las cuatro filas con 64 px de alto en vez de 40 y el
   `input` de la derecha en `x=724` --el borde izquierdo de la columna-- en
   vez de al lado de su rotulo.

   La cuenta dice por que, y no era el ancho de la columna: `.fila` trae
   `flex-wrap: wrap` y la regla global da a cada `input` un `flex-basis` de
   190 px. Rotulo 116 + caja 190 + rotulo corto 62 + caja 190 + tres huecos de
   8 = 582 px pedidos en una columna de 471. Con `wrap`, lo que no cabe baja;
   los 190 son de la regla global de `estilos.css`, escrita para una fila de
   una sola pareja.

   Asi que en ESTE bloque las cajas dejan de pedir un ancho de partida y se
   reparten lo que sobra (`flex: 1 1 0`), y la fila no se parte. La columna
   entera SI sigue pudiendo bajar debajo de la otra --`.creacion-columnas`
   conserva su `wrap` y su `min-width` de 420--, que es lo que la regla de
   arriba protege: lo que no se quiere es que se parta UNA fila, no que la
   pantalla deje de responder al ancho. */
#bloque-creacion .fila { flex-wrap: nowrap; }
/* 🔴 Y LAS CAJAS CON ANCHO DECLARADO SE QUEDAN FUERA, que es un defecto que
   esta misma regla cometio antes de llevar los dos `:not` de clase. Con
   `#bloque-creacion .fila > input` --un id, una clase y dos `:not` de
   atributo-- le gana en especificidad a `input.campo-corto` y a
   `#bloque-creacion input.campo-descripcion`, asi que se llevo por delante
   TRES anchos declarados: medido en el navegador, `Secuencia`,
   `Debe-Haber` y `Tipo Tasa` pasaron de 128 px a 347 y 169, y las dos cajas
   de `Tipo Tasa` --la del codigo y la de la descripcion-- quedaron IGUALES
   cuando la captura las tiene una chica y una ancha.

   Un arreglo de reparto no tiene por que pisar un ancho que alguien midio:
   la regla reparte lo que sobra SOLO entre las cajas que no piden nada. */
#bloque-creacion .fila > input:not([type="radio"]):not([type="checkbox"]):not(.campo-corto):not(.campo-descripcion),
#bloque-creacion .fila > select { flex: 1 1 0; min-width: 0; }


/* ===== EL PIE DEL `Detalle de Comprobante`: SIETE CONTROLES MEDIDOS =====
   `docs/capturas-concar/detalle-comprobante-boton-finaliza.png`, ampliada el
   08/09/2026: hoja · carpeta · aspa · disquete · prismáticos · `F` · (hueco)
   · puerta roja. Están PEGADOS a la derecha del pie, que es la forma que el
   censo de `barras-pie.mjs` llama «franja hundida a la izquierda, botones de
   icono pegados a la derecha, al ras del pie» y que ya está medida en nueve
   sitios de CONCAR. Acá se cumple con un empuje, no con un `float`, porque
   la franja de la izquierda tiene contenido propio --la situación del
   comprobante-- y tiene que poder crecer.

   Ver DIFERENCIAS §173. */
#detalle-iconos-pie {
  display: flex;
  align-items: center;
  gap: var(--oly-space-1);
  flex: 0 0 auto;
}

/* Lo que separa la franja de la izquierda del grupo de iconos. Un `margin-
   left: auto` en el grupo haría lo mismo, pero deja de funcionar en cuanto
   alguien añade algo a su derecha -- y este pie ya lleva un botón nuestro
   fuera del grupo medido. */
.empuje-pie { flex: 1 1 auto; min-width: var(--oly-space-2); }

/* `Anular` es NUESTRO. Se marca en el CSS además de en el marcado para que
   no se confunda con los siete de CONCAR cuando alguien mire la pantalla en
   vez del HTML: va con texto y no con icono, que es lo que distingue en toda
   la réplica un botón propio de uno medido. */
.boton-nuestro { flex: 0 0 auto; }

/* Mientras se arrastra: sin transiciones y con la sombra un poco más marcada,
   para que se vea que la ventana está en la mano. Lo segundo es cosmético;
   lo primero no -- una `transition` sobre `left`/`top` hace que la ventana
   PERSIGA al cursor con retraso, y el arrastre se siente roto. */
.ventana-en-movimiento {
  transition: none !important;
  box-shadow: 0 18px 48px rgba(0, 0, 0, .28);
}
.ventana-apilada > .titulo-ventana { cursor: move; }

/* =====================================================================
   🔴 LOS DIECINUEVE CONTROLES DE `Creacion`, CON SU ANCHO MEDIDO
   =====================================================================
   Lo cazo el usuario el 09/09/2026: «corrige los inputs esos importes tienen
   espacio de sobra y no se ven». Tenia razon y el volcado lo zanja: `Importe`
   media 307 px en la replica y mide 113 en CONCAR, y no era el unico -- los
   DIECINUEVE estaban mal, casi todos de sobra, porque ninguno traia ancho
   propio y se los repartia el `flex: 1 1 0` generico de mas arriba.

   FUENTE: `artifacts/ui/forms/2026-08-09T0009/form.detalle-de-comprobante.2.json`
   --el volcado en estado DESCUADRADO, el mismo de la cabecera-- y la tabla de
   `docs/CTMOVI09-DETALLE-MEDIDO.md` §7.4, que ya traia los diecinueve tamanos.
   O sea que esto NO es una medicion nueva: es una medicion que estaba escrita
   y que el CSS no seguia, que es la version silenciosa del mismo defecto que
   este proyecto caza a cada rato.

   🔴 Y EL EMPAREJADO ROTULO->CAJA, QUE §7.4 DEJABA COMO 🟡, QUEDA CERRADO
   POR UN TERCER DATO. Ese documento dice, textual, que «emparejarlas una por
   una necesita las dos cosas a la vez» --la lista de 19 rotulos es de la
   captura y la de 19 cajas es del volcado-- y que no se empareja por parecido.
   No se emparejo por parecido: coinciden TRES senales independientes.

     1. EL ORDEN DE FILA. Ocho filas de 21 px de paso en cada columna, y la
        replica tiene las mismas ocho en el mismo orden.
     2. EL TIPO DE CONTROL. Cuatro desplegables en el volcado (201, 213, 211,
        201) y cuatro combos en la replica, en esas cuatro filas. Y la caja de
        `25x21` admite UN caracter: es el `Debe-Haber`, que es de un caracter.
     3. LAS SEIS GRISES. El volcado trae seis `enabled: false` dentro de
        `Creacion`; la replica trae seis `disabled` -- y son las MISMAS SEIS
        filas: `Secuencia`, `Nro.Dcmto.Refer.`, su fecha, `Tipo Tasa`, `Tasa` y
        `Monto Base`. Que dos listas de seis salgan iguales por casualidad
        despues de que ya coincidieran el orden y el tipo no es un parecido.

   Las TRES cajas de descripcion son NUESTRAS y no llevan numero de CONCAR
   --`f-cuenta-gasto-nombre`, `f-cr-anexo-nombre` y `f-cr-tipo-tasa-desc`--,
   asi que siguen con su `flex` y se declaran aparte, igual que la descripcion
   del `Anexo Ref.` de la ventana padre (§186 punto 5).

   🔴 Y EL SELECTOR LLEVA `input#id` A PROPOSITO. La regla generica de mas
   arriba es `#bloque-creacion .fila > input:not(...):not(...):not(...):not(...)`,
   que pesa (1,5,1): un `#f-cr-importe` a secas pesa (1,0,0) y PERDERIA en
   silencio. Es la tercera vez que la especificidad muerde en este fichero
   --ver `.cuerpo-detalle .campo-detalle input` y `.marco-medido`-- asi que va
   escrito: `#bloque-creacion .fila > input#f-cr-importe` pesa (2,1,1) y gana.
   ===================================================================== */

/* 🔴 Y EL RELLENO, QUE ES LO QUE HACE QUE UN ANCHO MEDIDO SIRVA DE ALGO.
   `estilos.css` gobierna las cajas con
   `input:not([type="radio"]):not([type="checkbox"])` --(0,2,1)-- y les pone
   `14px` de letra y `padding: 0 12px`. Con 24 px de relleno horizontal, la
   caja de `25x21` del `Debe-Haber` se queda con CERO de hueco util y su unica
   letra no entra: medido, `scrollWidth` 34 contra `clientWidth` 24. O sea que
   copiar los anchos de CONCAR sin copiar el relleno no copia nada -- es
   exactamente el defecto que `.cuerpo-detalle .campo-detalle input` ya
   documenta unas lineas mas arriba, y por eso se usa el MISMO remedio y los
   MISMOS numeros: `11px` y `1px 4px`, que es la letra y el relleno con los
   que estos anchos se midieron. */
#bloque-creacion .fila > input,
#bloque-creacion .fila > select,
#bloque-creacion .fila > .combo-buscable > input,
#bloque-creacion .fila > .combo-buscador > select {
  padding: 1px 4px;
  font-size: 11px;
}

/* --- columna izquierda: x rel 80, ocho filas de 21 --- */
/* 🔴 EL RELLENO BAJA A 2 EN LA MAS ESTRECHA, Y EL ANCHO MEDIDO NO SE
   TOCA. `Secuencia` mide 33 en CONCAR y guarda cuatro cifras (`0001`); con
   `1px 4px` quedaban 31 de hueco y las cuatro cifras piden 33 --medido en
   el navegador--. El ancho es de CONCAR y el relleno es nuestro, asi que se
   cede el nuestro: al reves seria ensanchar una caja medida para que quepa
   un relleno que CONCAR no tiene. */
#bloque-creacion .fila > input#f-cr-secuencia        { flex: none; width: 33px; padding: 1px 2px; }   /* 33x21 GRIS */
/* 🔴 LOS DOS COMBOS BUSCABLES NO SON HIJOS DE LA FILA: el ancho va al
   ENVOLTORIO (`.combo-buscable`, que es quien lleva el `flex`) y la caja de
   dentro lo llena. Con el ancho puesto solo en el `input` estos dos se
   quedaron en 241 px --lo comprobo el navegador antes de escribir esto-- y
   eran los dos unicos de los diecinueve que seguian de sobra. */
#bloque-creacion .fila > .combo-buscable:has(> input#f-cuenta-gasto-buscar)
                                                     { flex: none; width: 97px; }   /* 97x21 */
#bloque-creacion .fila > .combo-buscable:has(> input#f-cr-anexo-buscar)
                                                     { flex: none; width: 108px; }  /* 108x21 */
#bloque-creacion .fila > .combo-buscable > input     { width: 100%; min-width: 0; }
#bloque-creacion .fila > select#f-cr-centro-costo,
#bloque-creacion .fila > .combo-buscador:has(> select#f-cr-centro-costo)
                                                     { flex: none; width: 201px; }  /* 201x21 combo */
#bloque-creacion .fila > input#f-cr-debe-haber       { flex: none; width: 25px; }   /* 25x21, un caracter */
#bloque-creacion .fila > input#f-cr-importe          { flex: none; width: 113px; }  /* 113x21 */
#bloque-creacion .fila > select#f-cr-tipo-documento,
#bloque-creacion .fila > .combo-buscador:has(> select#f-cr-tipo-documento)
                                                     { flex: none; width: 201px; }  /* 201x21 combo */
#bloque-creacion .fila > input#f-cr-num-documento    { flex: none; width: 201px; }  /* 201x21 */

/* --- columna derecha: x rel 414, y las tres de remate en 551..569 --- */
#bloque-creacion .fila > input#f-cr-fecha-documento  { flex: none; width: 57px; }   /* 57x21 mascara */
#bloque-creacion .fila > input#f-cr-fecha-vencimiento { flex: none; width: 57px; }  /* 57x21 mascara, x rel 568 */
#bloque-creacion .fila > select#f-area-gasto,
#bloque-creacion .fila > .combo-buscador:has(> select#f-area-gasto)
                                                     { flex: none; width: 213px; }  /* 213x21 combo */
#bloque-creacion .fila > input#f-cr-anexo-refer      { flex: none; width: 100px; }  /* 100x21 */
#bloque-creacion .fila > select#f-cr-dcmto-refer,
#bloque-creacion .fila > .combo-buscador:has(> select#f-cr-dcmto-refer)
                                                     { flex: none; width: 211px; }  /* 211x21 combo */
#bloque-creacion .fila > input#f-cr-nro-dcmto-refer  { flex: none; width: 77px; }   /* 77x21 GRIS */
#bloque-creacion .fila > input#f-cr-fecha-doc-ref    { flex: none; width: 56px; }   /* 56x21 GRIS, x rel 569 */
#bloque-creacion .fila > input#f-cr-tipo-tasa        { flex: none; width: 49px; }   /* 49x21 GRIS */
#bloque-creacion .fila > input#f-cr-tasa             { flex: none; width: 61px; }   /* 61x21 GRIS */
#bloque-creacion .fila > input#f-cr-monto-base       { flex: none; width: 74px; }   /* 74x21 GRIS, x rel 551 */
#bloque-creacion .fila > input#f-cr-glosa            { flex: none; width: 211px; }  /* 211x21 */

/* Y las tres NUESTRAS, que no tienen numero que copiar: se quedan con el
   hueco que sobra de su fila en vez de un ancho inventado. `min-width: 0`
   para que puedan encogerse en vez de estirar la fila. */
#bloque-creacion .fila > input#f-cuenta-gasto-nombre,
#bloque-creacion .fila > input#f-cr-anexo-nombre,
#bloque-creacion .fila > input#f-cr-tipo-tasa-desc   { flex: 1 1 0; min-width: 0; }

/* ============ LA ESPERA DIBUJADA, `campo-cargando.js` ================
   El usuario, 10/09/2026: «se quedó en stop y después de varios segundos
   apareció el nombre de las cuentas». La marca va como FONDO del propio
   `<input>` y no como elemento aparte, para poder encenderla en cualquier
   caja sin tocar el HTML de su pantalla -- un `::after` no serviría, porque
   un `<input>` es un elemento vacío y no tiene pseudoelementos.

   El SVG va incrustado (`data:`) y no en un fichero: es un arco de 10 px y
   pedirlo por la red para avisar de que se está esperando por la red sería
   exactamente al revés. */
.campo-cargando {
  background-image: url('data:image/svg+xml;utf8,\
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">\
<circle cx="10" cy="10" r="7" fill="none" stroke="%23c8ccd4" stroke-width="2.5"/>\
<path d="M10 3a7 7 0 0 1 7 7" fill="none" stroke="%233b6ea5" stroke-width="2.5" stroke-linecap="round"/>\
</svg>');
  background-repeat: no-repeat;
  background-position: right 6px center;
  background-size: 14px 14px;
  /* Que el texto no se meta debajo del arco. `padding-right` y no `width`:
     la caja conserva el ancho medido de su pantalla. */
  padding-right: 24px;
  animation: campo-cargando-gira .7s linear infinite;
}

/* La animación gira el FONDO, no la caja: `transform` sobre el `<input>`
   arrastraría el borde y el texto con él. */
@keyframes campo-cargando-gira {
  from { background-position-x: right 6px; }
  to   { background-position-x: right 6px; }
}

/* 🔴 EL GIRO DE VERDAD. `background-image` no se puede rotar con CSS, así que
   el arco se mueve alternando su posición no -- se sustituye por un elemento
   girado sólo cuando la caja tiene envoltorio. Para las que no lo tienen,
   que son casi todas, el arco se queda quieto y lo que anima es su OPACIDAD:
   se ve igual de claro que «está pasando algo» y no miente sobre el
   progreso, que es lo que un giro de velocidad fija hace. */
.campo-cargando { animation: campo-cargando-late 1s ease-in-out infinite; }
@keyframes campo-cargando-late {
  0%, 100% { opacity: 1; }
  50%      { opacity: .55; }
}

/* Quien no quiera movimiento no lo tiene, y sigue viendo el arco. */
@media (prefers-reduced-motion: reduce) {
  .campo-cargando { animation: none; }
}

/* ============ LA CABECERA DE PÁGINA DE LOS PAPELES DE GESTIÓN =========
   `CTMAYO01`, `CTMAYO02`, `CTDIAR02` y `CTCOST32`. Razón social (o R.U.C.,
   o el código de programa) a la izquierda y `Pag. N` --o la fecha de
   emisión-- pegados al borde derecho del papel.

   `justify-content: space-between` y no `margin-left: auto` en la segunda
   celda: las cifras del cuerpo ya usan `margin-left: auto` para su
   alineación de columna, y mezclar los dos mecanismos en el mismo `.linea-
   papel` es lo que dejó las bandas de moneda sobre columnas que no eran las
   suyas cuando se pintó `CTMAYO01` la primera vez.

   Va sin `border` ni `font-weight`: en las capturas de CONCAR la cabecera
   es del mismo cuerpo de letra que el resto del papel. */
.linea-papel.cabecera-papel {
  display: flex;
  justify-content: space-between;
  gap: var(--oly-space-4);
}
.cabecera-papel .cabecera-izquierda { white-space: pre; }
.cabecera-papel .cabecera-derecha { white-space: pre; text-align: right; }

/* La casilla `Todos` del marco `Filtro` de CTPBIS01. Medida en
   `form.ctpbis01.json`: `ThunderRT6CheckBox` con texto `Todos`, a la derecha
   del desplegable, y con ella marcada el desplegable va deshabilitado. */
.casilla-banda {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: var(--oly-font-size-xs);
  color: var(--oly-text-secondary);
}

/* Una cuenta con el Tipo de Bien o Servicio cambiado y SIN GRABAR. No se
   inventa un color nuevo: es el mismo aviso de «esto todavia no esta en la
   base» que usa el resto de la aplicacion. */
.grilla-maestro tbody tr.fila-pendiente {
  background: var(--oly-status-warning-surface, #fff4e0);
}
.grilla-maestro tbody tr.fila-pendiente td:last-child {
  font-style: italic;
}

/* Los dos radios de `Glosa a Imprimir` APILADOS: `Principal` encima de
   `Movimientos`, con el mismo borde izquierdo. El `.grupo-glosa` de
   `CTLIBR51` los pone en fila porque ahi van en la franja de parametros;
   aca es un marco propio dentro del cuerpo, como en CONCAR.

   🔴 ERA SOLO DE `CTPLE561`, Y AHORA SON TRES. La clase se llamaba
   `glosa-apilada-ple561` porque cuando se escribio era la unica pantalla de
   esta familia con medicion propia -- DIFERENCIAS 10 del bloque de
   `los-controles-que-no-son-cajas.mjs` lo dice con todas las letras: apilar
   `.grupo-glosa` entera habria «torcido las otras dos pantallas que la
   comparten y que no tienen medicion propia».

   Ya la tienen. Cotejadas en vivo sobre la `0002` el 11/09/2026, las tres
   traen los radios apilados:

     `docs/capturas-concar/ctmayo01-0002-ventana.png`
     `docs/capturas-concar/ctlibr61-0002-ventana.png`
     `docs/capturas-concar/ctple561-0002-ventana.png`

   Sigue SIN aplicarse a `CTLIBR51`, que va en fila y esta medido asi. */
.grupo-glosa.glosa-apilada {
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  padding-bottom: var(--oly-space-2);
}
#ple561-moneda { width: max-content; min-width: 265px; }
