/* =====================================================================
   CTMOVI09 — Comprobante de Compras
   Réplica web de CONCAR · Grupo HNG

   LA REGLA QUE ORDENA ESTE ARCHIVO
   --------------------------------
   El esqueleto es de CONCAR y no se toca: los mismos bloques, en el mismo
   orden, con la misma densidad, los mismos rótulos y el mismo recorrido de
   teclado. `CTMOVI09` mete 38 campos en una pantalla y eso NO es un defecto
   de diseño — es una pantalla de captura y el digitador la quiere así.

   Este archivo no toca `index.html` ni `app.js`: viste exactamente el mismo
   árbol de nodos que ya existía.

   DE DÓNDE SALE LA PIEL
   ---------------------
   De `olympium-tokens.css`, el sistema de diseño de Ratio. Y con él viene
   su regla, que aquí se respeta al pie de la letra:

       ni un hex en este archivo, ni uno.

   Todo color, radio, espacio, sombra y duración sale de un token semántico
   (`--oly-surface`, `--oly-text-primary`, `--oly-radius-sm`), nunca de un
   primitivo (`--oly-color-grey-200`) y nunca de un valor suelto. El día que
   Ratio cambie su paleta, esta pantalla cambia con ella y nadie tiene que
   acordarse de venir a tocarla.

   Hubo un intento anterior de piel oscura, tipo Spotify/Steam. Se descartó:
   se veía peor, no mejor. Queda anotado para no repetirlo.

   TRES DECISIONES QUE NO SON COSMÉTICAS
   -------------------------------------
   1. Toda cifra de dinero lleva `font-variant-numeric: tabular-nums` y va
      alineada a la derecha. Sin eso las columnas de importes no alinean sus
      unidades y un decimal fuera de lugar deja de verse. Es la misma regla
      que Ratio aplica a `input[type=number]` en su `index.css`, y por el
      mismo motivo.

   2. `.bloque` conserva `min-inline-size: 0`. Un <fieldset> arranca en
      `min-content` y NO se encoge por debajo de su contenido: sin esa línea
      la fila de detracción empuja el bloque a 863px dentro de una ventana
      de 698 y el `overflow` lo recorta EN SILENCIO — se llegó a ver
      "o. Detracción" en pantalla.

   3. El foco de teclado se ve siempre y se ve fuerte. Esta pantalla se
      opera tabulando, no con el mouse; un foco tenue aquí es un defecto de
      uso, no un detalle de estilo.
   ===================================================================== */

* { box-sizing: border-box; }

body {
  margin: 0;
  padding: 0 0 var(--oly-space-7);
  min-height: 100vh;
  font-family: var(--oly-font-family);
  font-size: var(--oly-font-size-xs);
  line-height: var(--oly-line-height-sm);
  color: var(--oly-text-primary);
  background: var(--oly-surface-subtle);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* ============================ BARRA DE MENÚ ========================== */
/* El menú de CONCAR, con sus diez módulos en el mismo orden. Aquí hace
   además de barra de título de la aplicación. */

.barra-menu {
  position: sticky; top: 0; z-index: 60;
  display: flex; align-items: center; gap: var(--oly-space-1);
  padding: var(--oly-space-2) var(--oly-space-4);
  background: var(--oly-surface);
  border-bottom: 1px solid var(--oly-border);
  box-shadow: var(--oly-shadow-sm);
}

/* La marca, sin meter un logo que habría exigido tocar el HTML. */
.barra-menu::before {
  content: "";
  width: var(--oly-space-1); height: var(--oly-space-5);
  margin-right: var(--oly-space-3); flex: none;
  border-radius: var(--oly-radius-full);
  background: var(--oly-action-primary);
}

.barra-menu span {
  padding: var(--oly-space-1) var(--oly-space-3);
  border-radius: var(--oly-radius-sm);
  font-size: var(--oly-font-size-xs);
  font-weight: var(--oly-font-weight-medium);
  color: var(--oly-text-secondary);
  cursor: default; 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);
}
.barra-menu span:hover { background: var(--oly-surface-hover); color: var(--oly-text-primary); }

.barra-menu .empresa-actual {
  margin-left: auto;
  padding: var(--oly-space-1) var(--oly-space-3);
  font-size: var(--oly-font-size-2xs);
  font-weight: var(--oly-font-weight-semibold);
  color: var(--oly-text-on-primary-subtle);
  background: var(--oly-action-primary-subtle);
  border-radius: var(--oly-radius-full);
}
.barra-menu .empresa-actual:hover {
  background: var(--oly-action-primary-subtle);
  color: var(--oly-text-on-primary-subtle);
}

/* =============================== UTILIDAD ============================ */
.oculto { display: none !important; }

/* El atributo `hidden` tiene que esconder de verdad.
   `[hidden] { display: none }` viene del navegador con la especificidad más
   baja que existe, así que CUALQUIER regla propia que ponga un display se lo
   come. Pasó con las dos pantallas que se ocultan así:

       .pantalla-login { display: grid }   -> el login tapaba la aplicación
       .barra-menu     { display: flex }   -> la barra se veía sin haber entrado

   El síntoma del primero era «entro, me dice todo ok y me deja en el login»:
   la sesión se creaba bien, el menú se armaba detrás, y el login quedaba
   encima con z-index 100. No había ningún error en consola, y comprobarlo
   con `elemento.hidden` daba que sí estaba oculto -- el atributo estaba
   puesto; lo que no obedecía era el estilo. Hay que mirar el display
   calculado, no el atributo.

   Con `!important` gana siempre, que es lo que uno espera de `hidden`. */
[hidden] { display: none !important; }

/* ============================ BARRA DE ERROR ========================= */
/* Muestra el mensaje CRUDO del motor con su HINT. Nunca se reemplaza por
   un texto genérico: el contador tiene que ver el error real, con código. */

.barra-error {
  position: sticky; top: 56px; z-index: 55;
  display: flex; align-items: flex-start; flex-wrap: wrap; gap: var(--oly-space-2);
  margin: var(--oly-space-4) auto 0; max-width: 1080px;
  padding: var(--oly-space-3) var(--oly-space-4);
  background: var(--oly-status-danger-subtle);
  border: 1px solid var(--oly-status-danger);
  border-left: var(--oly-space-1) solid var(--oly-status-danger);
  border-radius: var(--oly-radius-sm);
  color: var(--oly-status-danger-strong);
  font-size: var(--oly-font-size-xs);
  line-height: var(--oly-line-height-sm);
}

.barra-error strong {
  flex: none;
  padding: 0 var(--oly-space-2);
  font-size: var(--oly-font-size-3xs);
  font-weight: var(--oly-font-weight-bold);
  color: var(--oly-text-on-status);
  background: var(--oly-status-danger-filled);
  border-radius: var(--oly-radius-xs);
  line-height: var(--oly-line-height-xs);
  margin-top: 2px;
}

.error-ayuda {
  display: block; width: 100%;
  margin-top: var(--oly-space-1);
  font-size: var(--oly-font-size-2xs);
  font-style: italic;
  color: var(--oly-text-secondary);
}

#cerrar-error {
  flex: none; margin-left: auto;
  width: var(--oly-control-height-sm); height: var(--oly-control-height-sm);
  display: grid; place-items: center;
  background: transparent;
  color: var(--oly-status-danger-strong);
  border: none; border-radius: var(--oly-radius-xs);
  font-size: var(--oly-font-size-2xs); cursor: pointer;
  transition: background var(--oly-motion-duration-fast) var(--oly-motion-ease-productive);
}
#cerrar-error:hover { background: var(--oly-status-danger-subtle-pressed); }

/* =============================== VENTANA ============================= */
/* Lo que en CONCAR es una ventana MDI, aquí es una tarjeta. */

.ventana {
  /* 🔴 EL TOPE ERA 1080px A SECAS Y DEJABA EL PIE FUERA DE LA PANTALLA.
     Cotejando `CTLIB581` contra CONCAR el 11/09/2026 a 1024x768 --que es la
     resolucion de CONCAR, no una pantalla rara-- el boton `Salir` quedaba
     cortado y la pagina sacaba barra horizontal: el viewport util es 1009 y
     la ventana medía los 1080 del tope, porque `width: max-content` la ciñe
     al hijo mas ancho y en esta pantalla ese hijo es el parrafo de ayuda, de
     una sola linea de 1078px.

     Eso rompe la primera de las TRES reglas de todas las pantallas --el pie
     tiene que ser alcanzable-- y lo rompia en la resolucion del cliente.

     `min()` no cambia NADA por encima de 1112px de viewport: ahi sigue
     mandando el 1080 de siempre y las anchuras medidas en el navegador a
     1400x900 (ver `cascaron.css`, la tabla ANTES -> DESPUES) no se mueven.
     Por debajo, la ventana se ciñe a la pantalla en vez de salirse. Los
     32px son los dos margenes del cuerpo. */
  max-width: min(1080px, 100vw - 32px);
  margin: var(--oly-space-5) auto 0;
  background: var(--oly-surface);
  border: 1px solid var(--oly-border);
  border-radius: var(--oly-radius-md);
  box-shadow: var(--oly-shadow-sm);
  overflow: hidden;
}

/* 🔴 `#ventana-hijo` YA NO LLEVA MARGEN PROPIO, y el de `.ventana` se le
   ANULA en `cascaron.css` con `margin: 0`: es `.ventana-apilada` --`position:
   fixed` con `inset` en los cuatro lados-- y ahi el margen le corre la caja
   sin decirlo. Medido: con `inset-top: 80px` y los 20 px de `.ventana` la
   ventana nacia en `y=100`, o sea que el numero del `inset` no era el de la
   pantalla. Su regla, su `z-index` 44 y las razones medidas estan en
   `cascaron.css`, junto a la pila de ventanas apiladas. */

.titulo-ventana {
  display: flex; align-items: center; gap: var(--oly-space-2);
  padding: var(--oly-space-3) var(--oly-space-5);
  background: var(--oly-surface);
  border-bottom: 1px solid var(--oly-border);
  font-size: var(--oly-font-size-sm);
  font-weight: var(--oly-font-weight-semibold);
  color: var(--oly-text-heading);
}
/* Punto de sesión activa. */
.titulo-ventana::before {
  content: "";
  width: var(--oly-space-2); height: var(--oly-space-2); flex: none;
  border-radius: var(--oly-radius-full);
  background: var(--oly-status-success);
}

.titulo-ventana button {
  margin-left: auto;
  width: var(--oly-control-height-sm); height: var(--oly-control-height-sm);
  display: grid; place-items: center;
  background: transparent;
  color: var(--oly-icon-muted);
  border: none; border-radius: var(--oly-radius-xs);
  font-size: var(--oly-font-size-2xs); 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);
}
.titulo-ventana button:hover {
  background: var(--oly-status-danger-subtle);
  color: var(--oly-status-danger);
}

/* =========================== BLOQUES Y FILAS ========================= */
/* CONCAR agrupa los 38 campos en cuatro bloques y ese agrupamiento es
   información: identificación, documento y proveedor, detracción, y
   conversión con glosas. Cada uno es su propia tarjeta interna. Es un
   cambio puramente visual: no se movió ni un campo ni un tabindex. */

#form-padre {
  display: flex; flex-direction: column; gap: var(--oly-space-3);
  padding: var(--oly-space-4);
}

.bloque {
  margin: 0; padding: var(--oly-space-4);
  background: var(--oly-surface);
  border: 1px solid var(--oly-border-subtle);
  border-radius: var(--oly-radius-sm);
  /* Ver decisión 2 de la cabecera. No quitar: el recorte es silencioso. */
  min-inline-size: 0;
}

/* 🔴 SIN `uppercase`: el rotulo del `groupbox` tambien es de CONCAR. El
   marco de la ventana hija dice `Creación`, con tilde y en minusculas
   --`ctmovi09-0002-detalle-creacion-ceco.png`-- y la pantalla ensenaba
   `CREACIÓN`. Misma razon que las cabeceras de rejilla. */
.bloque legend {
  padding: 0 0 var(--oly-space-2);
  font-size: var(--oly-font-size-3xs);
  font-weight: var(--oly-font-weight-semibold);
  letter-spacing: .09em;
  color: var(--oly-text-tertiary);
}

.fila {
  display: flex; align-items: center;
  flex-wrap: wrap; gap: var(--oly-space-2);
  margin-bottom: var(--oly-space-2);
}
.fila:last-child { margin-bottom: 0; }

.fila label {
  flex: none; width: 128px;
  text-align: right;
  font-size: var(--oly-font-size-2xs);
  font-weight: var(--oly-font-weight-medium);
  color: var(--oly-field-label);
  white-space: nowrap;
}
/* Etiqueta intercalada a media fila: se ciñe a su texto en vez de reservar
   los 128px de la etiqueta principal. */
.fila label.etiqueta-corta {
  width: auto; min-width: 78px;
  padding-left: var(--oly-space-1);
  color: var(--oly-text-secondary);
  white-space: nowrap;
}

/* ============================== CONTROLES ============================ */

/* 🔴 LOS RADIOS Y LAS CASILLAS NO SON CAJAS DE TEXTO, Y ESTA EXCLUSIÓN ES UN
   ARREGLO DE ORIGEN.
   ---------------------------------------------------------------------
   La regla de abajo daba a TODO `input` un `flex: 1 1 190px`, una altura de
   control y un `padding`. Sobre un radio nativo eso lo estira: el marcado sale
   como un círculo azul grande y el sin marcar como uno pequeño, en el mismo
   grupo. Lo vio el usuario el 07/09/2026 mirando `CTREGC27`, y la captura de
   CONCAR (`docs/capturas-demo/demo15-15-ctregc27-generar-archivo-mensual.png`)
   confirma que allá los dos miden lo mismo.

   No es la primera vez: había **OCHO** parches a mano del mismo problema
   --`.grupo-glosa`, `.columna-orden` y `.radios-situacion` para los radios;
   `.casilla-medio`, `.fila-casilla-libr81`, `.casillas-consulta`,
   `.casilla-comp` y `.campo-comp` para las casillas--, cada uno escrito el día
   que alguien vio la pantalla torcida. Tres pantallas más se construyeron sin
   parche (`CTREGC27`, `CTREGC25` y el grupo `mayo01-glosa`), y a mano habría
   habido una novena.

   Se excluyen acá y no se parchea allá: un tipo de control que no es una caja
   de texto no tiene que heredar el tamaño de una caja de texto. `input.mjs`
   --`herramientas/los-controles-que-no-son-cajas.mjs`-- cuenta los sitios y se
   pone rojo si vuelve a aparecer un parche, que es lo que impide la novena. */
input:not([type="radio"]):not([type="checkbox"]), select {
  flex: 1 1 190px; min-width: 0;
  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);
  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);
}
input:not([type="radio"]):not([type="checkbox"]):hover:not(:disabled):not([readonly]),
select:hover:not(:disabled) { border-color: var(--oly-field-border-hover); }

select {
  cursor: pointer;
  /* La flecha nativa se pinta en el color del sistema y no acompaña al
     tema; se dibuja aquí en SVG embebido. Es el único sitio del archivo
     donde aparece un color literal, y es porque un `data:` URI no puede
     leer una variable CSS. */
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  padding-right: var(--oly-space-7);
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' stroke='%23646867' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--oly-space-3) center;
}

/* Ver decisión 3 de la cabecera: esta pantalla se opera tabulando. */
input:not([type="radio"]):not([type="checkbox"]):focus, select:focus,
button:focus-visible {
  border-color: var(--oly-field-border-focus);
  box-shadow: 0 0 0 3px var(--oly-selection-ring);
}

/* Un campo inerte tiene que leerse como inerte de un vistazo. En esta
   pantalla hay siete —Comprobante, R.U.C., I.S.C., Tasa IGV, Importe
   Total, Tipo Conversión y Glosa Movimiento— y cada uno lo es por un
   motivo distinto, anotado en el `title` del HTML. */
input:not([type="radio"]):not([type="checkbox"]):disabled,
input:not([type="radio"]):not([type="checkbox"])[readonly], select:disabled {
  color: var(--oly-text-disabled);
  background: var(--oly-field-surface-filled);
  border-color: var(--oly-border);
  border-style: dashed;
  cursor: not-allowed;
}

input::placeholder { color: var(--oly-field-placeholder); }

/* 🔴 ESTA CLASE NO HACIA NADA, Y LO PARECIA TODO. Medido el 08/09/2026 con
   `getComputedStyle` sobre los OCHO `input.campo-corto` del arbol: ninguno
   tenia `flex: 0 1 128px`. Cinco salian en `0 0 auto` --los de
   `Parametro Detraccion` y `Anexo Ref.`, que tienen regla POR ID con su ancho
   medido, y esa si gana-- y los otros tres en `1 1 190px`, que es la regla
   global de mas arriba.

   La causa es especificidad, no orden: la global es
   `input:not([type="radio"]):not([type="checkbox"])`, o sea un elemento y DOS
   selectores de atributo --(0,2,1)--, y `input.campo-corto` es una clase y un
   elemento --(0,1,1)--. Pierde aunque este escrita despues.

   Y el efecto se veia en pantalla: `Secuencia` y `Debe-Haber` de la ventana
   hija salian de 347 px --el ancho entero de su columna, para cuatro digitos
   y para UNA letra-- y en `Tipo Tasa` la caja del CODIGO salia de 184 y la de
   la DESCRIPCION de 155, o sea la chica mas ancha que la ancha, justo del
   reves que la captura.

   Una declaracion que dice `128px` y no pone 128 px es de la misma familia
   que un comentario que afirma un comportamiento sin medirlo: se lee como una
   decision tomada. Se le dan los dos `:not` de la global para que empate en
   especificidad y gane por orden. Lo vigila la seccion 6 de
   `los-arneses/la-barra-que-no-flota.mjs`, que es donde ya viven las DOS
   trampas anteriores de la misma forma --`.campo-detalle input` y
   `.grupo-cuadre input`, las dos vencidas por esta misma global--.
   Ver DIFERENCIAS §171. */
input.campo-corto:not([type="radio"]):not([type="checkbox"]) { flex: 0 1 128px; }
input.campo-largo { flex: 1 1 100%; }

/* Los tres calendarios caben en una fila sin empujar el bloque. */
input[type="date"] { flex: 0 1 132px; min-width: 118px; }
input[type="date"]::-webkit-calendar-picker-indicator { cursor: pointer; opacity: .55; }
input[type="date"]::-webkit-calendar-picker-indicator:hover { opacity: 1; }

/* Ver decisión 1 de la cabecera. Se listan los id reales del HTML y sus
   variantes con prefijo `f-`. */
#isc, #igv, #importe-total, #tasa-igv, #tipo-cambio, #imp-detraccion,
#f-isc, #f-igv, #f-importe-total, #f-tasa-igv, #f-tipo-cambio,
#f-detraccion-importe,
input[type="number"] {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
#f-ruc, #f-comprobante, #f-documento {
  font-variant-numeric: tabular-nums;
}

/* ========================= COMBO CON BÚSQUEDA ======================== */

.combo-buscable { position: relative; flex: 1 1 210px; min-width: 0; display: flex; }
.combo-buscable input { width: 100%; }

.sugerencias {
  position: absolute; top: calc(100% + var(--oly-space-1)); left: 0; right: 0; z-index: 40;
  margin: 0; padding: var(--oly-space-1);
  max-height: 232px; overflow-y: auto;
  list-style: none;
  background: var(--oly-surface);
  border: 1px solid var(--oly-border);
  border-radius: var(--oly-radius-sm);
  box-shadow: var(--oly-shadow-md);
}

.sugerencias li {
  padding: var(--oly-space-2) var(--oly-space-3);
  border-radius: var(--oly-radius-xs);
  font-size: var(--oly-font-size-2xs);
  color: var(--oly-text-primary);
  cursor: pointer;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: background var(--oly-motion-duration-fast) var(--oly-motion-ease-productive);
}
.sugerencias li:hover, .sugerencias li.activa {
  background: var(--oly-selection-hover-surface);
  color: var(--oly-text-on-primary-subtle);
}

/* ============================= DETRACCIÓN ============================ */
/* CONCAR SÍ tiene estos tres campos, vacíos en 6.155.901 líneas medidas.
   Se muestran por fidelidad de pantalla; el motor todavía no los recibe.
   El filo ámbar lo dice sin obligar a leer la nota. */

.bloque-detraccion {
  background: var(--oly-status-warning-subtle);
  border-color: var(--oly-status-warning);
}

/* ============================== BOTONERA ============================= */

.barra-botones {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--oly-space-2);
  padding: var(--oly-space-3) var(--oly-space-4);
  background: var(--oly-surface-subtle);
  border: 1px solid var(--oly-border-subtle);
  border-radius: var(--oly-radius-sm);
}
.bloque .barra-botones {
  margin: var(--oly-space-3) calc(var(--oly-space-4) * -1) calc(var(--oly-space-4) * -1);
  border: none;
  border-top: 1px solid var(--oly-border-subtle);
  border-radius: 0 0 var(--oly-radius-sm) var(--oly-radius-sm);
}

/* 🔴 `:not(.boton-gs)` ES UN ARREGLO DE ORIGEN, NO UN CAPRICHO.
   Este selector pesa (0,1,1) --una clase y un tipo-- y por eso le GANA a
   `.boton-gs` (0,1,0) aunque `.boton-gs` este mucho mas abajo en la otra hoja.
   Resultado medido en el navegador: los dos botones del pie de `CTMOVI09`,
   que CONCAR tiene en 25x41, se dibujaban en 34x28 -- la altura de aca y el
   ancho de aca mas su relleno de 16.

   Es el MISMO defecto de especificidad que §128 y que la exclusion de los
   radios de mas arriba: una regla general que viste por tipo y una clase
   medida que no puede desvestirla. Se arregla igual, excluyendo en el origen
   en vez de subir la especificidad de la clase pantalla por pantalla. */
.barra-botones button:not(.boton-gs) {
  height: var(--oly-control-height-sm);
  padding: 0 var(--oly-space-4);
  font-family: var(--oly-font-family);
  font-size: var(--oly-font-size-xs);
  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),
              border-color var(--oly-motion-duration-fast) var(--oly-motion-ease-productive);
}
.barra-botones button:hover {
  background: var(--oly-surface-hover);
  border-color: var(--oly-field-border-hover);
}

/* La acción principal de cada barra va en el primario del sistema. */
.barra-botones button:first-child {
  color: var(--oly-text-on-action);
  background: var(--oly-action-primary);
  border-color: var(--oly-action-primary);
}
.barra-botones button:first-child:hover {
  background: var(--oly-action-primary-hover);
  border-color: var(--oly-action-primary-hover);
}
.barra-botones button:active { background: var(--oly-action-primary-active); }
.barra-botones button:not(:first-child):active { background: var(--oly-surface-hover); }

.estado-texto {
  margin-left: auto;
  font-size: var(--oly-font-size-2xs);
  color: var(--oly-text-secondary);
  font-variant-numeric: tabular-nums;
}

/* =========================== BARRA INFERIOR ========================== */

.barra-inferior {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--oly-space-5);
  padding: var(--oly-space-2) var(--oly-space-5);
  background: var(--oly-surface-subtle);
  border-top: 1px solid var(--oly-border-subtle);
  font-size: var(--oly-font-size-3xs);
  color: var(--oly-text-tertiary);
  font-variant-numeric: tabular-nums;
}
.barra-inferior span:last-child { margin-left: auto; }

/* =============================== DIÁLOGO ============================= */
/* 🔴 AL CENTRO, y esto es una MARCHA ATRAS.
   Estaba fijado arriba a la derecha, y el comentario que lo justificaba
   decía que era deliberado «porque en CONCAR este diálogo tapa los campos
   de detracción». Eso no es una razón para apartarse: que un modal tape lo
   que hay debajo es lo que hace un modal, y taparlo es parte de lo que
   contabilidad va a fotografiar.

   Lo corrigió el usuario el 03/09/2026 -- «siempre es al centro» -- y el
   fotograma de la demo lo confirma: `Cálculo Compra` sale centrado sobre
   la ventana de CTMOVI09, que es lo que hace Windows con un modal respecto
   de su ventana dueña. La tarjeta de CTMOVI09 está centrada en la página,
   así que centrar contra el viewport da el mismo sitio.

   La entrada de DIFERENCIAS que amparaba la esquina se retiró: era una
   diferencia que nadie había pedido. */

.dialogo {
  position: fixed; inset: 0; z-index: 90;
  margin: auto; height: max-content;
  width: 310px;
  background: var(--oly-surface);
  border: 1px solid var(--oly-border);
  border-radius: var(--oly-radius-md);
  box-shadow: var(--oly-shadow-lg);
  overflow: hidden;
}

.titulo-dialogo {
  padding: var(--oly-space-3) var(--oly-space-4);
  border-bottom: 1px solid var(--oly-border-subtle);
  font-size: var(--oly-font-size-xs);
  font-weight: var(--oly-font-weight-semibold);
  color: var(--oly-modal-title);
}

/* El velo. Un modal que deja clicar lo de atrás no es un modal, y en
   CONCAR no se puede tocar la ventana de abajo mientras el cuadro está. */
.velo-dialogo {
  position: fixed; inset: 0; z-index: 89;
  background: color-mix(in srgb, var(--oly-text-primary) 22%, transparent);
}

.cuerpo-dialogo { padding: var(--oly-space-4); }

/* ---------------- El cuadro de confirmacion (`confirmar.js`) ---------
   Reusa `.dialogo`, `.velo-dialogo` y `.titulo-dialogo`: es el MISMO
   cuadro que los otros modales de la replica, y tenerlo en un solo sitio
   es lo que evita que dentro de un mes haya dos dibujos del mismo cuadro
   --el defecto que este repositorio comete una y otra vez--.

   Estrecho porque la pregunta es una linea: `Desea Eliminar la Clave :
   CTA03`. Si el texto crece, el cuadro crece con el. */
.dialogo-confirmar { width: min(380px, calc(100vw - 32px)); }

/* El cuadro que PIDE un dato --`Buscar` de CTMOVI90--, medido en vivo el
   05/09/2026: la etiqueta arriba a la izquierda, los dos botones apilados
   arriba a la derecha, y la caja de texto ancha debajo de los dos. Reutiliza
   `.dialogo`, `.titulo-dialogo` y `.boton-confirmar` para que no haya dos
   dibujos del mismo cuadro. */
.dialogo-pedir { width: min(420px, calc(100vw - 32px)); }
.cuerpo-pedir {
  display: grid; grid-template-columns: 1fr auto; gap: var(--oly-space-3);
  align-items: start;
}
.texto-pedir { font-size: var(--oly-font-size-xs); color: var(--oly-text-primary); }
.botones-pedir { display: grid; gap: var(--oly-space-2); }
.caja-pedir {
  grid-column: 1 / -1; width: 100%; box-sizing: border-box;
  padding: 3px var(--oly-space-2);
  border: 1px solid var(--oly-border);
  border-radius: var(--oly-radius-sm);
  background: var(--oly-surface);
  color: var(--oly-text-primary);
  font-size: var(--oly-font-size-xs);
}

.cuerpo-confirmar { display: flex; gap: var(--oly-space-3); align-items: flex-start; }

/* Hermano del `.icono-informacion` de `Calculo Compra`: mismo tamano y
   misma posicion, con el interrogante que Windows pone en un cuadro de
   pregunta en vez de la `i`. */
.icono-pregunta {
  flex: none; width: 32px; height: 32px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--oly-status-info-filled, #1668c1);
  color: #fff; font: 700 18px/1 var(--oly-font-family, system-ui), sans-serif;
}

.texto-confirmar {
  margin: 0; padding-top: 6px;
  font-size: var(--oly-font-size-sm);
  color: var(--oly-text-primary);
}

/* El cuadro que solo AVISA no lleva icono --lo que ensena la captura del
   07/09/2026-- asi que su texto arranca pegado al borde izquierdo y no
   detras de un hueco de 32 px que ya no hay. Y respeta los saltos: el aviso
   de CTREGC27 son dos frases en dos lineas. */
.texto-avisado { white-space: pre-line; padding-top: 0; }

/* Los dos botones abajo a la derecha, que es donde los pone Windows. */
.botones-confirmar {
  display: flex; justify-content: flex-end; gap: var(--oly-space-2);
  padding: 0 var(--oly-space-4) var(--oly-space-4);
}
.boton-confirmar {
  min-width: 76px; padding: 5px var(--oly-space-4);
  border: 1px solid var(--oly-border);
  border-radius: var(--oly-radius-sm);
  background: var(--oly-surface);
  color: var(--oly-text-primary);
  font-size: var(--oly-font-size-xs);
  cursor: pointer;
}
.boton-confirmar:hover { background: var(--oly-surface-subtle); }
/* El foco se ve, y se ve como en Windows: un reborde en el boton por
   defecto. Sin esto, un cuadro que se maneja con el teclado no dice cual
   de los dos responde al Enter. */
.boton-confirmar:focus-visible,
.boton-confirmar-si:focus {
  outline: 2px solid var(--oly-focus-ring, #1668c1);
  outline-offset: 1px;
}

/* ------------------- `Cálculo Compra` (CTMOVI09) --------------------
   MEDIDO en un fotograma de la demo del 01/09/2026 (Fathom 805526550,
   min 36:10): un icono de información redondo a la izquierda y tres
   renglones etiquetados a su derecha, con los números alineados en la
   misma columna. Un solo botón, `Aceptar`, centrado abajo. */
.cuerpo-calculo { display: flex; gap: var(--oly-space-3); align-items: flex-start; }

.icono-informacion {
  flex: none; width: 32px; height: 32px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--oly-status-info-filled, #1668c1);
  color: #fff; font: italic 700 18px/1 Georgia, "Times New Roman", serif;
}

.renglones-calculo {
  display: grid; grid-template-columns: max-content max-content;
  gap: 2px var(--oly-space-2);
  font-size: var(--oly-font-size-xs);
  color: var(--oly-modal-body);
}
.renglones-calculo b { font-weight: var(--oly-font-weight-regular); }
.renglones-calculo span { text-align: right; font-variant-numeric: tabular-nums; }

.botones-dialogo.centrado { justify-content: center; }
.botones-dialogo.centrado button { flex: 0 0 auto; min-width: 90px; }
.cuerpo-dialogo p {
  margin: 0 0 var(--oly-space-4);
  font-size: var(--oly-font-size-xs);
  color: var(--oly-modal-body);
}

.botones-dialogo { display: flex; gap: var(--oly-space-2); }

.botones-dialogo button,
.botones-regc27 button {
  flex: 1;
  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-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-dialogo button:first-child,
.botones-regc27 button:first-child {
  color: var(--oly-text-on-action);
  background: var(--oly-action-primary);
  border-color: var(--oly-action-primary);
}
.botones-dialogo button:hover,
.botones-regc27 button:hover { background: var(--oly-surface-hover); }
.botones-dialogo button:first-child:hover,
.botones-regc27 button:first-child:hover {
  background: var(--oly-action-primary-hover);
  border-color: var(--oly-action-primary-hover);
}

.numeracion-manual {
  margin-top: var(--oly-space-4); padding-top: var(--oly-space-4);
  border-top: 1px solid var(--oly-border-subtle);
}
/* 🔴 SIN `uppercase`, aunque este rotulo sea NUESTRO: el cuadro de
   `Numeración Comprobantes` de CONCAR escribe en minusculas todo lo que
   ensena --`Numeración Comprobantes`, `¿Desea numeración automática?`,
   medido en `ctmovi09-0002-abre-numeracion.png`-- y un rotulo anadido que
   grita al lado de los suyos se nota mas que si no estuviera. */
.numeracion-manual label {
  display: block; margin-bottom: var(--oly-space-1);
  font-size: var(--oly-font-size-3xs);
  font-weight: var(--oly-font-weight-semibold);
  letter-spacing: .08em;
  color: var(--oly-text-tertiary);
}
.numeracion-manual input {
  width: 100%; margin-bottom: var(--oly-space-3);
  font-variant-numeric: tabular-nums;
  letter-spacing: .1em; text-align: center;
  font-size: var(--oly-font-size-sm);
}

/* ============================ VENTANA HIJA =========================== */

/* ---------------------------------------------------------------------
   LA CABECERA DE LA VENTANA HIJA: SIETE CAJAS GRISES EN DOS COLUMNAS
   ---------------------------------------------------------------------
   Los anchos NO son de gusto: son los del volcado de formulario
   `artifacts/ui/forms/2026-08-09T0009/form.detalle-de-comprobante.2.json`,
   que es el unico de los quince de esta ventana que esta en el estado
   descuadrado. Medicion entera en `docs/CTMOVI09-DETALLE-MEDIDO.md` §7.2:

     subdiario   41 x 19      moneda  121 x 19      Debe/Haber/Dif.  137 x 19
     numero      73 x 19      fecha   121 x 21

   El marco entero va `enabled: false` en el volcado, o sea que las siete son
   de solo lectura. Aca son `input` grises y no celdas de tabla porque es lo
   que son alli --`ThunderRT6TextBox` y un `MSMaskWndClass`--, y porque una
   celda no se puede enfocar ni recorrer con el tabulador, que es como el
   contador lee una ficha de CONCAR.

   🔴 Y SE FUE LA BARRA DE «CHIPS» que habia aca. Cuatro pastillas redondeadas
   con textos que no son de CONCAR --`11 COMPRAS PARA VTAS GRAVADAS 1`,
   `N° (automático al grabar)`, `2026-09-01`, `PEN — Soles`--. La forma de
   pastilla tampoco: CONCAR dibuja cajas hundidas de VB6. Ver §170.

   Los `ch` salen de dividir el ancho medido por el de un digito de la fuente
   monoespaciada de las cajas, para que la caja siga cuadrando si el usuario
   cambia el tamano de letra del navegador: un `px` clavado se rompe ahi, y la
   regla de la casa es que el pie siempre se alcance. */
.cabecera-hijo {
  display: flex; flex-wrap: wrap; gap: var(--oly-space-8);
  padding: var(--oly-space-3) var(--oly-space-5);
  border-bottom: 1px solid var(--oly-border-subtle);
}
.cabecera-hijo-columna { display: flex; flex-direction: column; gap: 2px; }
.cabecera-hijo .campo-hijo {
  display: flex; align-items: center; gap: var(--oly-space-2);
  /* 21 px de paso entre filas, medido. */
  min-height: 21px;
}
.cabecera-hijo .campo-hijo label {
  /* El rotulo no empuja la caja: ancho fijo y a la izquierda, como en la
     ficha de CONCAR. `Sub-Comprobante` es el mas largo de los seis. */
  flex: 0 0 auto; width: 15ch; text-align: left;
  font-size: var(--oly-font-size-3xs);
  color: var(--oly-text-tertiary);
}
.cabecera-hijo .par-subcomprobante { display: flex; gap: 4px; }

.caja-gris {
  background: var(--oly-surface-subtle);
  border: 1px solid var(--oly-border);
  border-radius: 2px;
  padding: 1px 4px;
  font-family: var(--oly-font-mono, ui-monospace, monospace);
  font-size: var(--oly-font-size-2xs);
  font-variant-numeric: tabular-nums;
  color: var(--oly-text-secondary);
  height: 19px; box-sizing: border-box;
}
/* 🔴 Y LA FUENTE DE `.caja-gris` NUNCA LLEGABA A ESTAS CAJAS.
   -------------------------------------------------------------------
   `.caja-gris` pide `font-family: var(--oly-font-mono, ui-monospace,
   monospace)` y `font-size: var(--oly-font-size-2xs)` --12 px--, y los anchos
   de abajo estan calculados en `ch` CONTRA ESA FUENTE: `8ch` para que
   `090006` entre en los 73 px que mide CONCAR.

   Pero estas cajas son `<input>`, y unas lineas mas arriba hay
   `input:not([type="radio"]):not([type="checkbox"])` con `font-family:
   var(--oly-font-family)`. Los dos `:not()` cuentan, asi que ese selector
   pesa (0,2,1) y `.caja-gris` (0,1,0): **gana el generico**. Resultado
   medido en el navegador el 10/09/2026: `fontFamily: Inter`, `fontSize:
   14px`, o sea 14 px proporcional donde el ancho suponia 12 px monoespaciado.

   Y con eso `8ch` da 57 px, `090006` necesita 78, y el `text-overflow:
   ellipsis` de `.caja-gris` de `cascaron.css` lo remata: la ventana enseñaba
   **`09...`** donde tiene que decir `090006`, y `SOLES ...` donde dice
   `SOLES`. El usuario: «si tienes espacio de sobra ¿por que muestras 3
   puntos suspensivos en vez del dato real???».

   No era un ancho mal medido: era una fuente que no llegaba. Se arregla con
   el id de la ventana, que gana sin discusion, en vez de subirle la
   especificidad a `.caja-gris` --que se usa en media aplicacion y no todas
   sus cajas son de esta ventana--. Ver DIFERENCIAS 253. */
#cabecera-hijo input.caja-gris {
  font-family: var(--oly-font-mono, ui-monospace, "Cascadia Mono", "Consolas", monospace);
  font-size: var(--oly-font-size-2xs);
  /* Y `flex: none`: el generico pone `flex: 1 1 190px`, que estira o encoge
     la caja segun lo que le quede a la fila y borra el ancho medido. */
  flex: none;
  /* Y EL RELLENO PERDIA POR LO MISMO, que es la mitad que faltaba. Arreglada
     la fuente, `090006` seguia cortado: medido, la caja daba 66 px y el texto
     pedia 66. El motivo es que el generico pone `padding: 0 12px` --24 px de
     los dos lados-- donde `.caja-gris` pide `4px 8px` --16--, y como todo va
     `box-sizing: border-box` esos 8 px de mas se los come el texto. Devolver
     el relleno de `.caja-gris` es lo que hace que los `ch` medidos vuelvan a
     cuadrar, sin tocar ni uno de los numeros de abajo. */
  padding: 4px var(--oly-space-2);
}

/* Y LOS ANCHOS VAN EN PIXELES, QUE ES COMO ESTAN MEDIDOS.
   -------------------------------------------------------------------
   Los `ch` que habia aca --`5ch`, `8ch`, `22ch`, `15ch`-- no salian de
   ninguna medicion: eran el numero de caracteres que a alguien le parecio
   que cabia, con el ancho de CONCAR anotado al lado en un comentario como
   si fuera lo mismo. No lo era, y por dos motivos a la vez: `ch` depende de
   la fuente que ACABE aplicandose --y la de esta ventana no aplicaba--, y
   ninguno de los cinco daba el pixel de al lado. Medido el 10/09/2026:
   `22ch` daba 155 px donde CONCAR mide 121, y `15ch` daba 105 donde mide
   137. O sea que dos cajas salian mas anchas que CONCAR y tres mas
   estrechas, y la del comprobante ademas cortaba el dato.

   Los cinco numeros de abajo son los del volcado de formulario, control por
   control (`docs/CTMOVI09-DETALLE-MEDIDO.md` seccion 7): `41x19` el
   subdiario, `73x19` el comprobante, `121x19` la moneda, `121x21` la fecha
   --que en CONCAR es un `MSMaskWndClass`-- y `137x19` cada uno de los tres
   del cuadre.

   Y con el relleno restaurado arriba entran los siete valores: la caja mas
   justa es la del comprobante, 73 menos 2 de borde y 16 de relleno dejan 55
   px para un `090006` que mide 42. Comprobado en el navegador con
   `scrollWidth <= clientWidth` en las siete. */
.caja-subdiario   { width: 41px; }
.caja-comprobante { width: 73px; }
.caja-moneda      { width: 121px; }
.caja-fecha       { width: 121px; height: 21px; }
.caja-cuadre      { width: 137px; text-align: right; }

/* =============================== TABLAS ============================== */

/* 🔴 `.tabla-cuadre` SE FUE DE ESTOS SEIS SELECTORES, Y NO SOLO DE UNO.
   La clase desaparecio del marcado en §170 --sus tres numeros son cajas
   grises de la cabecera de la ventana hija, no celdas de una tabla, y la
   tabla ademas tenia una columna `Dólares` que no sale de ninguna medicion--.
   El comentario que habia aca decia que sus reglas «se quedan compartidas
   porque el selector doble es el que da la forma a la grilla», y eso era
   verdad de la primera regla y falso de las otras cinco: `.tabla-cuadre
   { width: auto; min-width: 340px }` no compartia nada con nadie. Media
   limpieza deja el peor de los dos estados --parece que hay dos sujetos y
   solo hay uno-- asi que se van los seis. Ver §170 y §171. */
.grilla-lineas {
  width: calc(100% - var(--oly-space-8) - var(--oly-space-2));
  margin: var(--oly-space-4) var(--oly-space-5);
  border-collapse: separate; border-spacing: 0;
  background: var(--oly-surface);
  border: 1px solid var(--oly-border);
  border-radius: var(--oly-radius-sm);
  overflow: hidden;
  font-size: var(--oly-font-size-2xs);
}

.grilla-lineas th, .grilla-lineas td {
  padding: var(--oly-space-2) var(--oly-space-3);
  border-bottom: 1px solid var(--oly-border-subtle);
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.grilla-lineas tr:last-child td { border-bottom: none; }

/* Cuenta y descripción son texto, no cifras: se alinean a la izquierda. */
.grilla-lineas td:nth-child(2), .grilla-lineas td:nth-child(3),
.grilla-lineas th:nth-child(2), .grilla-lineas th:nth-child(3) {
  text-align: left;
}
.grilla-lineas td:nth-child(3) { white-space: normal; color: var(--oly-text-secondary); }

/* 🔴 SIN `uppercase` --misma razon que `.grilla-maestro th` en
   `cascaron.css`, medida en las dos capturas que alli se citan-- y SIN
   `.tabla-cuadre`, que ya no existe (ver el bloque de arriba). */
.grilla-lineas th {
  position: sticky; top: 0; z-index: 2;
  background: var(--oly-surface-subtle);
  font-size: var(--oly-font-size-3xs);
  font-weight: var(--oly-font-weight-semibold);
  letter-spacing: .06em;
  color: var(--oly-text-tertiary);
  border-bottom: 1px solid var(--oly-border);
}

.grilla-lineas tbody tr {
  transition: background var(--oly-motion-duration-fast) var(--oly-motion-ease-productive);
}
.grilla-lineas tbody tr:nth-child(even) { background: var(--oly-surface-subtle); }
.grilla-lineas tbody tr:hover { background: var(--oly-selection-hover-surface); }

/* El cuadre: es lo primero que mira un contador al abrir el asiento. */
.cuadre-diferencia { font-weight: var(--oly-font-weight-bold); }
.cuadre-diferencia.cuadra {
  color: var(--oly-status-success-strong);
  background: var(--oly-status-success-subtle);
}
.cuadre-diferencia.descuadra {
  color: var(--oly-status-danger-strong);
  background: var(--oly-status-danger-subtle);
}

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

/* ====================== BLOQUE DE CREACIÓN Y FIRME ==================== */

.creacion {
  margin: 0 var(--oly-space-5) var(--oly-space-4);
  padding: var(--oly-space-4);
  background: var(--oly-surface-subtle);
  border: 1px solid var(--oly-border-subtle);
  border-radius: var(--oly-radius-sm);
}
.creacion .barra-botones {
  margin: var(--oly-space-3) calc(var(--oly-space-4) * -1) calc(var(--oly-space-4) * -1);
  background: transparent;
  border: none;
  border-top: 1px solid var(--oly-border-subtle);
  border-radius: 0;
}

.barra-firme {
  background: var(--oly-surface-subtle);
  border: none;
  border-top: 1px solid var(--oly-border);
  border-radius: 0;
}

/* ============================= RESPONSIVO ============================ */

@media (max-width: 780px) {
  /* Sin `#ventana-hijo`: es apilada y su `inset` ya la acota. */
  .ventana { margin: var(--oly-space-3) var(--oly-space-3) 0; }
  .fila { align-items: stretch; flex-direction: column; gap: var(--oly-space-1); }
  .fila label, .fila label.etiqueta-corta {
    width: auto; min-width: 0; text-align: left; padding-left: 0;
  }
  input[type="date"], input.campo-corto { flex: 1 1 auto; }
  .dialogo {
    top: auto; bottom: var(--oly-space-4);
    right: var(--oly-space-3); left: var(--oly-space-3); width: auto;
  }
  .barra-menu { overflow-x: auto; }
}

/* Quien pidió menos movimiento, no lo recibe. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
}


/* La columna «Contenido» de la tabla general va en ancho fijo.
   No es estética: ahí el espaciado ES el dato. La categoría 53 guarda
   "MN42     421201        FACTURAS EMITIDAS..." -- moneda, cuenta y glosa
   separadas por relleno a posiciones fijas. En tipografía proporcional las
   columnas se desalinean y el registro deja de poder leerse. */
.col-crudo {
  font-family: ui-monospace, "Cascadia Mono", Consolas, "Liberation Mono", monospace;
  font-size: 0.86em;
  white-space: pre;
}

/* Los dos combos de la cabecera de CTMOVI09 van en tipografía de ancho fijo.
   No es estética: sus etiquetas son COLUMNAS -- `MN42   421201   FACTURAS
   EMITIDAS POR PAGAR M.N. T` --, y con tipografía proporcional los espacios
   no alinean nada y el renglón se lee como una frase. En CONCAR el combo es
   de ancho fijo y las tres columnas caen una debajo de la otra. */
#f-codigo-compra,
#f-subdiario {
  font-family: ui-monospace, "Cascadia Mono", Consolas, "Liberation Mono", monospace;
}

/* La descripción que CONCAR pone al lado de la caja de cuenta en el diálogo
   de `CTMAYO01`: no es un campo, es el eco del maestro mientras se teclea. */
.descripcion-cuenta {
  font-family: var(--oly-font-mono, monospace);
  font-size: 12px;
  color: var(--oly-text-secondary, #555);
  padding-left: var(--oly-space-2, 8px);
  white-space: nowrap;
}
