/* ============================================================
   NP — Hoja de estilos base
   REFERENCIA DE ESTILO: prototipos/04-carga-cotizacion.html (D39,
   uniformado a pedido de Leo el 27/07/2026). Los valores de acá
   NO se cambian por pantalla: toda pantalla nueva los hereda.
   Letra escalable = zoom nativo del navegador: todo en rem.
   ============================================================ */
:root {
  --azul: #217fb7;          /* acento principal — azul del logo ALAS */
  --azul-naval: #0d2438;    /* azul oscuro naval — encabezado, títulos de caja, botón principal */
  --azul-oscuro: #164569;
  --fondo: #f4f5f7;         /* grisado de fondo general */
  --blanco: #ffffff;
  --borde: #cdd3d9;
  /* Negro puro (D79 regla 12). Venía en #24292e desde el primer prototipo y
     Leo lo encontró flojo «en condiciones óptimas de luz» (31/08/2026). */
  --texto: #000000;
  --texto-suave: #6a737d;
  --verde: #1a7f37;
  --rojo: #b42318;
  --amarillo-suave: #fff8e1;
  /* Movimientos esperados: lo que el banco todavía no procesó (D72). */
  --esperado-fondo: #f2f7fb;
  --esperado-borde: #7fb0d4;
  font-size: 16px;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: "Segoe UI", system-ui, sans-serif; background: var(--fondo); color: var(--texto); }

/* ====== El tamaño de la letra (D124) ======
   Todo el sistema está dimensionado en `rem`, o sea relativo a la raíz: los 130
   valores en `px` que quedan son bordes, radios y sombras, que NO tienen que
   crecer (un borde de 1px sigue siendo un borde). Por eso alcanza con mover el
   `font-size` del `html` y escala la pantalla entera sin tocar una regla más.
   El JavaScript de `base.html` lo escribe; acá sólo vive el default. */
html { font-size: 100%; }

/* ===== Todo campo hereda la letra del sistema (U9, Leo 19/09/2026) =====
   «Los cuadros de diálogo no respetan el texto normal.» Medido: los campos de una
   grilla sin clase propia —la ventana de certificar, por ejemplo— salían con el
   tamaño que el navegador le da por defecto a un `<input>`, **13,3 px cuando todo
   lo demás está en 16**, y lo peor: con A+ el resto de la pantalla crecía y ellos
   se quedaban en 13,3. O sea que justo donde la persona escribe, la letra no se
   podía agrandar — que es lo contrario de para qué existe el control (D124).
   Se arregla en el mecanismo y no en la pantalla: un campo nunca elige su cuerpo
   de letra por omisión. Lo que quiera otro tamaño lo declara (los `.btn`, el
   control A− A A+) y sigue mandando, porque esta regla no lleva `!important`. */
input, select, textarea { font-family: inherit; font-size: inherit; }

.tamano-letra { display: flex; gap: 2px; }
.btn-letra {
  background: rgba(255, 255, 255, .12); color: #fff;
  border: 1px solid rgba(255, 255, 255, .25); border-radius: 5px;
  padding: .15rem .45rem; cursor: pointer; line-height: 1.2;
  font-family: inherit; font-weight: 600;
}
/* Los tres en el MISMO cuerpo, sin escalar con la preferencia: si el «A−»
   creciera junto con el resto, achicar desde la letra más grande sería apuntarle
   a un botón que se mueve. El control tiene que quedarse quieto. */
.btn-letra { font-size: 13px; }
.btn-letra:hover { background: rgba(255, 255, 255, .22); }
.btn-letra[disabled] { opacity: .4; cursor: default; }
/* El control vive DENTRO del bloque `.derecha`, que ya tiene su
   `margin-left:auto`: no hace falta empujar nada. */

/* ====== Barra del encabezado (idéntica en TODAS las pantallas) ====== */
.barra-superior {
  background: var(--azul-naval); color: #fff;
  display: flex; align-items: center; gap: 1.25rem; flex-wrap: wrap;
  padding: .8rem 1.25rem;
  position: sticky; top: 0;
  /* Por ENCIMA del velo de la ficha flotante (z-index 30) y por debajo de la
     ventana de confirmación (50). Antes la barra quedaba tapada por el velo:
     con una ficha abierta no se podía apretar ni el logo ni —desde el
     04/08/2026— el botón de salir, que es justo cuando más se necesitan.
     Encaja con D39, que ya pedía que las flotantes empiecen DEBAJO de la
     barra. La confirmación sí la tapa: mientras se pregunta algo, la barra no
     tiene que responder. */
  z-index: 40;
}
.barra-superior .logo img { height: 2.8rem; display: block; }
.barra-superior h1 { font-size: 1.45rem; font-weight: 600; color: #fff; }
/* Los datos que van al lado del título (bloque barra_cabecera): listas y textos
   sobre el azul naval, como en el prototipo 07. */
.barra-superior .en-barra { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.barra-superior .en-barra select { font-family: inherit; font-size: 1rem; padding: .2rem .45rem; border-radius: 5px;
  border: 1px solid rgba(255,255,255,.35); background: rgba(255,255,255,.12); color: #fff; font-weight: 600; }
.barra-superior .en-barra select option { color: #000; }
.barra-superior .en-barra select:disabled { opacity: .75; }
.barra-superior .en-barra .contexto { color: #9fc3de; font-size: .95rem; }
.barra-superior .en-barra .contexto b { color: #fff; }
/* La salida de la pantalla con el mouse (Leo, 04/08/2026): mismo molde que
   cualquier botón del sistema (esquinas redondeadas, sin emojis, D41), pero
   sobre la franja navy — de ahí el contorno claro en vez del fondo blanco.
   `nowrap` para que el cartel no se parta al medio: si no entra, la barra lo
   baja de línea entera (ya es flex-wrap), que es lo que hace falta en el
   celular y con el zoom grande. */
.barra-superior .btn-volver {
  display: inline-flex; align-items: center; gap: .35rem;
  background: rgba(255, 255, 255, .12); color: #fff; text-decoration: none;
  border: 1px solid rgba(255, 255, 255, .4); border-radius: 6px;
  padding: .35rem .8rem; font-size: .95rem; font-family: inherit;
  white-space: nowrap; cursor: pointer;
}
.barra-superior .btn-volver:hover { background: rgba(255, 255, 255, .28); }
.barra-superior .derecha { margin-left: auto; display: flex; align-items: center; gap: .75rem; }
.usuario { display: flex; align-items: center; gap: .4rem; font-size: .9rem; color: #fff; text-decoration: none; }
.circulo {
  background: var(--azul); color: #fff; border-radius: 50%; width: 1.9rem; height: 1.9rem;
  display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: .8rem;
}
/* Menú desplegable del círculo de iniciales (todas las opciones del usuario) */
.menu-usuario { position: relative; }
.circulo-boton { background: none; border: none; cursor: pointer; padding: 0; display: block; }
.circulo-boton:hover .circulo { background: var(--azul-oscuro); outline: 2px solid var(--azul); }
.circulo-ub { outline: 2px solid #e0b400; }  /* en modo UB, el círculo se marca en amarillo */
.menu-desplegable {
  display: none; position: absolute; right: 0; top: calc(100% + .5rem);
  background: var(--blanco); border: 1px solid var(--borde); border-radius: 8px;
  box-shadow: 0 6px 18px rgba(13,36,56,.25);
  min-width: 17rem; z-index: 40; overflow: hidden; padding: .3rem 0;
}
.menu-desplegable.abierto { display: block; }
/* El menú del círculo entra en la pantalla y se desplaza (hallazgo AZ-C4): con la letra
   grande en un celular medía 940 px, no se podía bajar y se cortaba por la izquierda. */
#menuUsuario {
  max-height: calc(100vh - var(--alto-barra, 4.2rem) - .5rem); overflow-y: auto;
  max-width: calc(100vw - 16px);
}
@media (max-width: 640px) {
  #menuUsuario { position: fixed; left: 8px; right: 8px; top: calc(var(--alto-barra, 4.2rem) + 4px);
                 min-width: 0; max-width: none; }
}
/* Con el menú abierto, la barra pasa por encima de la ventana de mensajes (AZ-C51). */
.barra-superior.con-menu { z-index: 90; }
.menu-encabezado {
  padding: .5rem .9rem; font-size: .85rem; font-weight: 700; color: var(--texto-suave);
  border-bottom: 1px solid #e6eaee; margin-bottom: .3rem;
}
.item-menu {
  display: block; width: 100%; text-align: left;
  padding: .5rem .9rem; font-size: .95rem; color: var(--texto);
  background: none; border: none; cursor: pointer; text-decoration: none;
  font-family: inherit;
}
.item-menu:hover { background: #f0f6fb; color: var(--azul-oscuro); }
.menu-separador { border-top: 1px solid #e6eaee; margin: .3rem 0; }

/* ====== Contenido ====== */
/* Los anchos máximos van en PÍXELES, no en rem (pedido de Leo, 28/07/2026):
   al achicar la letra con el zoom, la ventana/tabla NO se achica con ella —
   mantiene su lugar en pantalla y entra MÁS información en el mismo espacio. */
.contenido { padding: 1.25rem; max-width: 1088px; margin: 0 auto; }
.barra-acciones { display: flex; gap: .5rem; flex-wrap: wrap; margin-bottom: 1rem; justify-content: flex-end; }

/* ====== Botones (esquinas redondeadas, SIN emojis) ====== */
.btn {
  border: 1px solid var(--borde); background: var(--blanco); color: var(--texto);
  padding: .45rem .9rem; border-radius: 6px; cursor: pointer; font-size: .95rem;
  text-decoration: none; display: inline-block;
}
/* `hidden` tiene que esconder, siempre. Cualquier regla nuestra que declare un
   `display` —`.btn` es `inline-block`— le gana a la del navegador, que es de la
   hoja del propio navegador y por lo tanto la más débil de todas. Resultado: un
   botón marcado `hidden` se seguía viendo. Lo encontró la prueba del botón
   «Grabar» de F19, y valía para todo el sistema, no solo para él. */
[hidden] { display: none !important; }
.btn:hover { background: #eef1f4; }
/* Submit invisible que fija qué hace Enter en un formulario con varios
   botones (el navegador dispara siempre el primero). No se ve ni se tabula. */
.submit-por-defecto { position: absolute; width: 0; height: 0; padding: 0; border: 0; opacity: 0; }
.btn-primario { background: var(--azul-naval); border-color: var(--azul-naval); color: #fff; font-weight: 600; }
.btn-primario:hover { background: var(--azul-oscuro); }
/* Un botón apagado tiene que VERSE apagado (docs/28 BG25). Hasta acá ningún
   `.btn` deshabilitado tenía estilo propio: «Confirmar la planilla y seguir»,
   apagado, parecía apretable, y quien lo apretaba creía que la pantalla no
   andaba. Va una sola vez para todo el sistema; el hover no lo despierta. */
.btn:disabled, .btn[disabled] { opacity: .45; cursor: not-allowed; }
.btn:disabled:hover, .btn[disabled]:hover { background: var(--blanco); }
.btn-primario:disabled:hover, .btn-primario[disabled]:hover { background: var(--azul-naval); }
/* Misma tipografía que cualquier botón: solo cambia el color (D41). */
.btn-excel { color: var(--verde); }
.btn-peligro { color: var(--rojo); }

/* ====== Cajas: separación mínima 2px; título de caja navy redondeado ====== */
.tarjeta { background: var(--blanco); border: 1px solid var(--borde); border-radius: 8px; overflow: hidden; margin-bottom: 2px; }
.tarjeta h3 {
  font-size: .85rem; text-transform: uppercase; letter-spacing: .4px; color: var(--texto-suave);
  background: #eef1f4; border-bottom: 1px solid var(--borde); padding: .5rem .8rem; font-weight: 600;
}
.cuerpo-tarjeta { padding: 1rem; }
.descripcion { color: var(--texto-suave); margin-bottom: 1rem; max-width: 46rem; font-size: .95rem; }

/* Título de caja: navy redondeado — estándar para TODAS las cajas/ventanas */
.titulo-caja {
  background: var(--azul-naval); color: #fff;
  border-radius: 8px; padding: .55rem .9rem;
  font-size: 1.05rem; font-weight: 600; margin: .9rem 0 2px;
  display: flex; align-items: center; gap: .6rem;
}
.titulo-caja:first-of-type { margin-top: 0; }
.titulo-caja { scroll-margin-top: 5.5rem; }  /* los anclajes no quedan tapados por la barra fija */
.titulo-caja a { color: #dcecf7; text-decoration: none; }
.titulo-caja .acciones-titulo { margin-left: auto; display: flex; gap: .45rem; align-items: center; flex: 0 0 auto; }
/* Lo mismo para `.derecha`, que varias pantallas usan con el mismo fin (Leo,
   21/09/2026: en la agenda el contador y el botón «Marcar todo visto» se montaban
   encima del título). Estaba definido SÓLO para la barra de arriba, así que adentro
   de un título de caja era un `<span>` común: sin `margin-left: auto` no se iba a la
   derecha, y sin `display: flex` sus hijos se apilaban uno sobre otro. */
.titulo-caja .derecha { margin-left: auto; display: flex; gap: .45rem; align-items: center; flex: 0 0 auto; }
/* Un nombre larguísimo sin espacios no puede empujar ‹ › × fuera de la
   pantalla (N58): el título corta donde haga falta y los botones quedan. */
.titulo-caja { overflow-wrap: anywhere; min-width: 0; }
.titulo-caja .cerrar {
  margin-left: auto; background: none; border: none;
  font-size: 1.2rem; cursor: pointer; color: #cfe3f5; line-height: 1;
}
.titulo-caja .cerrar:hover { color: #fff; }
/* Flechas para recorrer el listado desde adentro de la ficha (D41). */
.nav-ficha {
  background: none; border: 1px solid rgba(255,255,255,.4); border-radius: 6px;
  color: #dcecf7; font-size: 1rem; line-height: 1; padding: .1rem .5rem;
  cursor: pointer; text-decoration: none;
}
.nav-ficha:hover { background: var(--azul-oscuro); color: #fff; }
.nav-ficha.inactiva { opacity: .35; pointer-events: none; }

/* ====== Formularios ====== */
.fila-campos { display: flex; gap: 1rem; flex-wrap: wrap; margin-bottom: .9rem; align-items: center; }
.fila-campos:last-child { margin-bottom: 0; }
.campo { flex: 1; min-width: 11rem; }
.campo label { display: block; font-size: .8rem; font-weight: 600; color: var(--texto-suave); margin-bottom: .25rem; }
.campo input, .campo select, .campo textarea {
  width: 100%; padding: .4rem .55rem; border: 1px solid var(--borde); border-radius: 6px;
  font-size: .95rem; font-family: inherit; background: #fff;
}
.campo input:focus, .campo select:focus, .campo textarea:focus { outline: 2px solid var(--azul); border-color: var(--azul); }
.campo textarea { resize: vertical; min-height: 4rem; }
/* Una casilla no se estira al ancho del campo: quedaba lejos de su «Sí» (N61). */
.campo input[type="checkbox"], .campo input[type="radio"] { width: auto; }
/* Observaciones internas (prototipo 01). Con `.campo .obs` también: `.campo textarea`
   (fondo blanco) le ganaba por especificidad y nunca se veían amarillas (hallazgo AZ-C7). */
.obs, .campo .obs { background: var(--amarillo-suave); }
/* Los botones de acción de una ventana (Guardar/Aceptar/Cancelar) van
   abajo a la DERECHA (Leo, 28/07/2026). */
.acciones-formulario { display: flex; gap: .6rem; margin-top: 1rem; justify-content: flex-end; }
.check-activo { display: flex; align-items: center; gap: .4rem; font-size: .95rem; }

/* Una caja en rojo se permite y SE MUESTRA (docs/18 §6, docs/15 §8): la marca
   es lo que hace que se vea. No se bloquea nada: si pasó, pasó. */
.saldo-negativo { color: var(--rojo); font-weight: 700; }
/* El resumen de cuenta (D81) usa este otro nombre para lo mismo: el saldo en
   rojo cuando la cuenta queda negativa. Faltaba la regla (relevamiento del
   06/10/2026): la clase se escribía en el HTML pero no hacía nada. */
.en-rojo { color: var(--rojo); font-weight: 700; }

/* La banda del bloqueo de edición (D35/D68) tiene que verse SIEMPRE, y eso no
   sale gratis: la mitad de las pantallas del sistema abren la ficha en un velo
   flotante (z-index 30) que le pasaba por encima. O sea que el aviso más
   importante —«esto lo está editando otro», «perdiste el control»— quedaba
   tapado justo en las pantallas donde hace falta. Es el mismo bug que el velo
   ya había provocado con la barra de arriba (D65), y por eso va fija arriba de
   todo y por encima del velo. */
#bandaBloqueo {
  position: sticky;
  top: 0;
  z-index: 45;          /* sobre el velo (30/40), bajo la ventana de confirmar (50) */
  margin-bottom: .8rem;
  box-shadow: 0 2px 10px rgba(20,30,40,.25);
}

/* Cuando alguien PIERDE el control de una ficha que estaba editando (D68), la
   pantalla tiene que mostrarle exactamente qué se pierde. Los campos que había
   cambiado quedan en amarillo; los que están como llegaron, en gris. Es la
   diferencia entre «perdiste la ficha» y «perdiste ESTOS tres datos». */
.campo-perdido:disabled,
.campo-perdido[disabled] {
  background: #fff6d8;
  border-color: #e0b700;
  color: var(--texto);
  font-weight: 600;
}
.campo-sin-tocar:disabled,
.campo-sin-tocar[disabled] { background: #f4f4f4; color: var(--texto-suave); }

/* Una cotización que NO coincide con lo que informa el banco (Leo, 28/08/2026).
   El sistema no la pisó —lo cargado no se modifica solo— así que la pinta para
   que alguien la mire y decida. */
.fila-divergente { background: #fff6d8; }

/* Un movimiento anulado NO se esconde (criterio de D61: para eso se anula en
   vez de borrar). Se atenúa y se tacha el importe: se lee que estuvo, y se ve
   que ya no cuenta. */
.fila-anulada { opacity: .55; }
.fila-anulada .col { text-decoration: line-through; }

/* Lo que todavía no procesó el banco (D72): cuenta para el saldo proyectado y
   no para el real. Se marca con una banda a la izquierda y un fondo apenas
   distinto — tiene que leerse distinto de un vistazo sin gritar, porque en una
   cuenta activa la mitad de las filas pueden estar así. */
.fila-esperada { background: var(--esperado-fondo); }
.fila-esperada td:first-child { box-shadow: inset 3px 0 0 var(--esperado-borde); }

/* La fila del listado que se está editando abajo (molde de D66: listado
   primero, ficha después). Sin esta marca, corregir un renglón se hace a
   ciegas: el formulario muestra unos datos y no se sabe de cuál fila salieron. */
.fila-elegida { background: #e8f1fa; }
.fila-elegida td:first-child { box-shadow: inset 3px 0 0 var(--azul); }

/* ====== Grillas ====== */
.desliza { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; }
th, td { padding: .32rem .5rem; font-size: .95rem; white-space: nowrap; }
/* El encabezado sube de contraste junto con el negro puro (D79 regla 12): el
   gris suave sobre gris claro era lo primero que se perdía con luz de frente. */
thead th {
  background: #dde5ec; color: var(--azul-naval); font-weight: 700; font-size: .78rem;
  text-transform: uppercase; letter-spacing: .3px; border-bottom: 2px solid #9fb0bf;
  text-align: left;
}
tbody tr { border-bottom: 1px solid #e6eaee; }
tbody tr:last-child { border-bottom: none; }
tbody tr[onclick] { cursor: pointer; }
tbody tr[onclick]:hover { background: #f0f6fb; }
.link { color: var(--azul); font-weight: 600; text-decoration: none; }
/* Un botón que se ve como enlace: sale como Esc en vez de navegar (N48). */
button.boton-enlace { background: none; border: none; padding: 0; cursor: pointer; font: inherit; }
.texto-problema { color: var(--rojo); font-weight: 600; }
/* Importes y cantidades: siempre a la derecha, con dígitos de ancho parejo
   para que las columnas se lean de un vistazo (D39). */
td.col, th.col { text-align: right; font-variant-numeric: tabular-nums; }
.linea-azul td { border-top: 2px solid var(--azul); }
.fila-total td { background: #f0f6fb; font-weight: 700; border-top: 2px solid var(--azul); font-size: 1rem; }
.pie-tabla {
  padding: .5rem .8rem; font-size: .85rem; color: var(--texto-suave);
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: .5rem;
  border-top: 1px solid #e6eaee;
}

/* ====== Chips de estado ====== */
.estado {
  display: inline-block; padding: .05rem .5rem; border-radius: 10px;
  font-size: .78rem; font-weight: 600;
}
.estado.activo { background: #e2f5e9; color: var(--verde); }
.estado.inactivo { background: #f1f1f1; color: var(--texto-suave); }
.estado.pendiente { background: var(--amarillo-suave); color: #7a6414; }
.estado.problema { background: #fde8e6; color: var(--rojo); }
.estado.sa { background: #e8f1fa; color: var(--azul-oscuro); }
.estado.negado { background: #fde8e6; color: var(--rojo); }  /* el "No" bien distinto del "Sí" */
.tabla-estado td:first-child { font-weight: 600; width: 40%; }

/* ====== Árboles en grillas (D39): +/− por rama, grisado por nivel ====== */
.alternar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.15rem; height: 1.15rem; margin-right: .35rem;
  border: 1px solid var(--borde); border-radius: 4px; background: var(--blanco);
  font-size: .8rem; font-weight: 700; color: var(--texto-suave); cursor: pointer;
  line-height: 1;
}
.alternar:hover { background: #eef1f4; color: var(--texto); }
.alternar-hueco { display: inline-block; width: 1.5rem; }
.fila-nivel-1 td { background: #f7f8f9; }
.fila-nivel-2 td { background: #eff1f4; }
.fila-nivel-3 td { background: #e7eaee; }

/* Permisos: TODA la línea en grisado verde (Sí) o rojo (No), más notorio
   cuanto más profundo el nivel — igual criterio que el grisado gris (D39). */
.fila-si-0 td { background: #f1faf4; }
.fila-si-1 td { background: #e6f6ec; }
.fila-si-2 td { background: #daf1e3; }
.fila-si-3 td { background: #cdecd9; }
.fila-no-0 td { background: #fdf3f2; }
.fila-no-1 td { background: #fceae8; }
.fila-no-2 td { background: #fae0dd; }
.fila-no-3 td { background: #f8d6d2; }
/* El tercer estado de una rama (U7, Leo 19/09/2026): algunos hijos sí y otros no.
   Hasta hoy la madre se pintaba a mano y su color NO significaba nada —no lleva
   permiso adentro—, así que una madre en rojo con hijos en verde era una pantalla
   que la persona SÍ veía, y se leía al revés. Ahora el color de la madre se
   calcula de sus hijos, y este es el caso del medio. */
.fila-algo-0 td { background: #fdf8ec; }
.fila-algo-1 td { background: #fbf2dc; }
.fila-algo-2 td { background: #f8ebcb; }
.fila-algo-3 td { background: #f5e4ba; }
.estado.parcial { background: #f5e4ba; color: #7a6414; }
.descripcion-celda { color: var(--texto-suave); white-space: normal; }
.celda-vacia { color: var(--texto-suave); white-space: normal; padding: 1rem; }
.tabla-estado td { padding: .55rem .8rem; white-space: normal; }

/* ====== Avisos y errores ====== */
.caja-aviso {
  background: #e2f5e9; border: 1px solid #b5e3c4; color: var(--verde);
  border-radius: 6px; padding: .6rem .9rem; margin-bottom: 1rem; font-size: .95rem;
}
/* El aviso de la cortina (D82) se ve igual que un error, pero no es uno: no
   comparte la clase para que en una pantalla siga habiendo un solo
   «caja-error», que es el de la ficha. */
.caja-error, .aviso-clave {
  background: #fde8e6; border: 1px solid #f2c1bc; color: var(--rojo);
  border-radius: 6px; padding: .6rem .9rem; margin-bottom: 1rem; font-size: .95rem;
}
/* El error, sin correr la pantalla de lugar (F20).
   Leo: «el mensaje debería aparecer como una ventana emergente, sin cambiar de
   ubicación la pantalla». Un cartel metido en el flujo empuja todo hacia abajo
   y encima hay que ir a buscar qué campo estaba mal. Flotando, la ficha queda
   donde estaba y el foco puede ir derecho al campo. */
/* Arranca DEBAJO del título de la ficha, no encima: con la letra grande tapaba
   el nombre de lo que se estaba cargando (N63). La barra y la banda se miden
   (M2, J3); los 3,4rem son el título. */
.caja-error.flotante {
  position: fixed; top: calc(var(--alto-barra, 4.2rem) + var(--alto-banda, 0px) + 3.4rem);
  left: 50%; transform: translateX(-50%);
  z-index: 120; max-width: 42rem; width: calc(100% - 2rem); margin: 0;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .22);
  display: flex; align-items: flex-start; gap: .7rem;
}
.caja-error.flotante .cerrar {
  border: none; background: none; color: inherit; cursor: pointer;
  font-size: 1.1rem; line-height: 1; padding: 0 .15rem; margin-left: auto;
}
/* Y el campo que causó el error queda marcado: sin la marca, el mensaje dice
   qué pasa pero no dónde. */
.campo-con-error input, .campo-con-error select, .campo-con-error textarea,
input.campo-con-error, select.campo-con-error, textarea.campo-con-error {
  border-color: var(--rojo); box-shadow: 0 0 0 3px rgba(198, 40, 40, .18);
}
/* ====== Los avisos que INTERRUMPEN ======
   Lo que el sistema tiene que decir sí o sí —«te están esperando esta ficha»,
   «te la sacaron», «este navegador ahora es de otro»— no puede quedar detrás
   de nada. Va fijo arriba y por encima de cualquier velo.

   Es la tercera vez que el velo de la ficha flotante tapa algo importante: la
   barra de salir (D65), la banda del bloqueo (D68) y ahora el aviso de que te
   van a sacar la ficha (G8). Las dos primeras se arreglaron caso por caso; esta
   regla arregla **la clase de error**: un aviso que interrumpe se declara así y
   deja de depender de qué haya abierto encima. */
.aviso-interrumpe {
  position: fixed; top: 4.2rem; left: 50%; transform: translateX(-50%);
  z-index: 150; max-width: 46rem; width: calc(100% - 2rem); margin: 0;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .25);
}

/* ====== La cortina por inactividad (D82) ======
   Tapa TODO y no deja leer nada de lo que había debajo — que es para lo que
   existe. Va por encima de cualquier otra cosa de la pantalla, incluida la
   ventana de confirmación: si algo quedó preguntando, tampoco se tiene que
   poder leer. */
.velo-inactividad {
  position: fixed; inset: 0; z-index: 200;
  background: var(--azul-naval);
  display: flex; align-items: center; justify-content: center; padding: 1rem;
}
.velo-inactividad .ventana-chica { margin: 0; }

/* De dónde arranca lo que se está viendo (G3): no es un movimiento, es el
   punto de partida. Se distingue con un fondo apenas gris para que nadie la
   confunda con una fila de datos. */
.fila-arrastre > td { background: #f2f5f7; border-bottom: 2px solid #cdd3d9; }

/* Un vencimiento pasado que todavía se debe (D81 §3). Es lo que hace que la
   cuenta corriente sirva para decidir qué pagar: lo vencido se ve de lejos. */
.vencido { color: var(--rojo); font-weight: 600; }

/* Alerta que AVISA pero no frena (D50: precios raros). Ni verde ni roja:
   amarilla, para que se note que es una advertencia y no un error. */
.caja-alerta {
  background: var(--amarillo-suave); border: 1px solid #e8d48a; color: #7a6414;
  border-radius: 6px; padding: .6rem .9rem; margin-bottom: 1rem; font-size: .95rem;
}
.caja-alerta ul { margin: 0; padding-left: 1.1rem; }

/* El reloj de los 2 minutos del bloqueo (Leo, 07/09/2026). Va adentro de la
   banda, en la misma línea: lo que se está contando ahí es tiempo de una
   persona esperando a otra, así que tiene que leerse de un vistazo sin que la
   banda crezca ni empuje la ficha para abajo. */
.reloj-espera {
  display: inline-block;
  margin-left: .5rem;
  padding: .05rem .45rem;
  border-radius: .25rem;
  background: #1c3d5a;
  color: #fff;
  font-variant-numeric: tabular-nums;   /* no baila al cambiar el segundo */
  font-weight: 600;
  white-space: nowrap;
}

/* ====== Pantallas de acceso (login y ventanas de clave/PIN) ======
   Fondo grisado con el logo ALAS ocupando toda la pantalla, y una
   ventana chica centrada con su título navy. */
.fondo-acceso::before {
  content: ""; position: fixed; inset: 4.4rem 0 0 0;
  background: url("/estaticos/logo-alas.svg") center / 70% no-repeat;
  opacity: .07; pointer-events: none;
}
.ventana-chica { position: relative; width: 100%; max-width: 24rem; margin: 3rem auto 0; }
.ventana-chica .tarjeta { margin-bottom: 0; }

/* ====== Ficha como ventana flotante sobre el listado (D39) ======
   La ventana comienza DEBAJO de la barra de encabezado: dos títulos navy
   pegados se confunden (Leo, 28/07/2026). */
.velo {
  display: none; position: fixed; inset: 0;
  background: rgba(20,30,40,.45); z-index: 30;
  overflow-y: auto;
  /* Los 6rem son el alto de la barra de arriba. Y lo que sume la banda del
     bloqueo, si la hay: la banda vive en el contenido y la ficha flota FIJA
     sobre la ventana, así que no se corren una a la otra — la banda le tapaba
     el encabezado a la ficha cada vez que crecía un renglón (pasó con el botón
     «Necesito esta ficha» y otra vez con el reloj, 07/09/2026).
     Es la CUARTA vez que la ficha flotante y un aviso se pelean el mismo lugar,
     después de la barra de salir (D65), la banda del bloqueo (D68) y el aviso
     de «te esperan» (G8). Acá se arregla el mecanismo y no el caso: la mide el
     JavaScript y la deja en `--alto-banda`, así vale para cualquier aviso, del
     alto que sea.
     Y desde el 12/09/2026 (M2) la barra de arriba también se MIDE
     (`--alto-barra`): en el celular se parte en dos renglones y los 6rem fijos
     dejaban el título de la ficha debajo de ella. Los 6rem quedan solo como
     valor de arranque, hasta que el JavaScript mida. */
  padding: calc(var(--alto-barra, 6rem) + var(--alto-banda, 0px)) 1rem 2rem;
}
.velo.abierto { display: block; }

/* ====== Ventana de confirmación propia (norma D41, centrada) ====== */
.velo-centrado {
  display: none; position: fixed; inset: 0;
  background: rgba(20,30,40,.45); z-index: 50;
  align-items: center; justify-content: center; padding: 1rem;
}
.velo-centrado.abierto { display: flex; }
.ventana-confirmar { width: 100%; max-width: 26rem; }
.ventana-confirmar .tarjeta { margin-bottom: 0; }
/* Un aviso con una TABLA adentro necesita otro ancho (Leo, 20/09/2026: el cartel
   de «Lo que sale al emitir» mostraba «IMPO…» y «400,0…», con los datos cortados
   contra el borde). Con 26rem la tabla no entraba, y como la tarjeta recorta, lo
   que sobraba no se podía ni ver ni desplazar: desaparecía.
   Se ensancha en `rem` para que acompañe a la letra (misma razón que U9). */
.ventana-confirmar.ancha { max-width: 58rem; }
.ventana-confirmar.ancha #textoConfirmar { max-height: 60vh; overflow: auto; }
.ventana-confirmar.ancha table { width: 100%; border-collapse: collapse; }
.ventana-confirmar.ancha th, .ventana-confirmar.ancha td { padding: .25rem .45rem; }
/* El ancho de una ficha flotante, en `rem` (U9, 19/09/2026).
   Eran 736px fijos «para que con menos zoom entrara más» (regla del 28/07). Con el
   zoom del navegador da igual —el zoom escala todo, también los px—, pero desde
   que existe el control A− A A+ (D124) no: con la letra agrandada el texto crecía
   y la ventana no, así que el contenido se apretaba y aparecía scroll de costado.
   En `rem` la ventana acompaña a la letra, y el zoom sigue funcionando igual. */
.ficha { max-width: 46rem; margin: 0 auto; }
.ficha .tarjeta { margin-bottom: 0; }
/* La ficha ancha: la del legajo (D106) tiene solapas y grillas de documentos
   que no entran en 736px sin cortar. */
.ficha.ficha-ancha { max-width: 65rem; }

/* ====== Las solapas de una ficha (legajo, D106) ======
   Una sola sección a la vista por vez; lo escondido viaja igual al guardar. */
.solapas {
  display: flex; border-bottom: 1px solid var(--borde); background: #f7f9fb;
  overflow-x: auto; margin: 0 0 1rem; gap: 0;
}
.solapas button {
  font: inherit; font-size: .95rem; padding: .55rem .9rem; border: none; background: none;
  cursor: pointer; color: var(--texto-suave); border-bottom: 3px solid transparent; white-space: nowrap;
}
.solapas button.activa {
  color: var(--azul-naval); font-weight: 700; border-bottom-color: var(--azul-naval); background: #fff;
}
.solapas button:focus-visible { outline: 3px solid #f0a500; outline-offset: -3px; }
/* La franja fija de la persona: lo que hay que ver, esté en la solapa que esté. */
.resumen-legajo {
  display: flex; gap: .6rem; align-items: center; flex-wrap: wrap;
  padding: .5rem .8rem; margin-bottom: .6rem; background: #f7f9fb;
  border: 1px solid var(--borde); border-radius: 6px; font-size: .92rem;
}
.aviso-faltan {
  margin-left: auto; display: inline-flex; align-items: center; gap: .4rem;
  background: var(--amarillo-suave); border: 1px solid #e0c86a; border-radius: 20px;
  padding: .15rem .7rem; font: inherit; font-size: .85rem; color: #7a6414; cursor: pointer;
}
.aviso-faltan.ok { background: #eef5e9; border-color: #b9dcc4; color: #3f6b22; cursor: default; }
tr.fila-vencida td { color: var(--rojo); }
tr.fila-vigente td { background: #f2f8f3; font-weight: 600; }

/* ====== Cargar algo nuevo sin salir de acá (Leo, 04/08/2026) ======
   Ctrl+Ins (o el botón derecho) sobre un campo que elige de una lista abre la
   ficha de alta de esa entidad adentro de esta ventana. La ficha es LA MISMA
   pantalla del ABM, traída en un iframe: no hay una segunda versión que
   mantener (ver app/ventana.py). Por encima de la ficha flotante (30) y por
   debajo de la confirmación (50), que puede abrirse sobre ella. */
.velo-ventana {
  display: none; position: fixed; inset: 0;
  background: rgba(20,30,40,.45); z-index: 40;
  align-items: center; justify-content: center; padding: 1rem;
}
.velo-ventana.abierto { display: flex; }
.ventana-alta {
  width: 100%; max-width: 780px; height: 100%; max-height: 90vh;
  display: flex; flex-direction: column;
}
.ventana-alta .titulo-caja { flex: 0 0 auto; }
/* El marco de la ficha: el iframe ocupa todo lo que queda y hace su propio
   scroll, así la pantalla de atrás nunca se mueve. */
.ventana-alta iframe {
  flex: 1 1 auto; width: 100%; border: none; background: var(--fondo, #fff);
  border-radius: 0 0 8px 8px; min-height: 12rem;
}

/* El MISMO ABM, visto adentro de la ventana (ampliación de D67, Leo
   04/08/2026): se le esconde la barra de arriba y poco más. El listado se ve,
   porque ahora la ventana también es el buscador grande (D66) y el lugar donde
   se entra a corregir. Se resuelve acá, con cuatro reglas, en vez de con un
   `{% if %}` en cada plantilla de ABM. */
.en-ventana .barra-superior { display: none; }
/* Una pantalla incrustada como sección de otra (BE108: el cómputo adentro del presupuesto): sin
   la barra de arriba —la tiene la de afuera— y con el margen justo para ver su borde. */
.incrustado .barra-superior { display: none; }
.incrustado .contenido { padding: .25rem .3rem; }
.en-ventana .contenido { padding-top: 0; }
/* Con una ficha abierta, el listado de atrás se esconde: la ficha es la
   pantalla entera (adentro de la ventana no flota). Sin ficha, el listado ES
   lo que se vino a ver. El `:has()` evita tener que avisarle a la pantalla
   desde el JavaScript —y el parpadeo de mostrar el listado y esconderlo. */
.en-ventana:has(.contenido .velo) .contenido > *:not(.velo):not(.barra-ventana) {
  display: none;
}
/* Exportar a Excel desde una ventana que se abrió para elegir algo es ruido
   (y una descarga adentro de un marco). */
.en-ventana .btn-excel { display: none; }
/* Lo que llega a la ventana y NO es una pantalla del sistema —«no tenés
   permiso», «algo salió mal»— se muestra igual: una ventana en blanco no le
   dice nada a nadie. La clase la pone base.html. */
.en-ventana.sin-ficha .contenido > * { display: block; }
/* La salida del ABM adentro de la ventana, con el mouse (D65): la barra de
   arriba no está, así que el «← Volver a …» va acá. */
.barra-ventana { margin-bottom: .8rem; }
/* Adentro de la ventana, la fila del listado ES el botón de elegir. */
.en-ventana .fila-elegible { cursor: pointer; }
.en-ventana .col-elegir { width: 2.2rem; text-align: center; }
/* Adentro de la ventana la ficha ya NO flota: es la pantalla entera. Queda
   `relative` con `inset: auto` (y no `static`) solo para no pisar la regla de
   la barra con mucho zoom, que se apoya en el orden de este archivo. */
.en-ventana .velo {
  display: block; position: relative; inset: auto;
  background: none; padding: 0; overflow: visible;
}
.en-ventana .ficha { max-width: none; }
/* El título de la ficha lo pone la ventana de afuera: adentro sería el
   segundo navy pegado al otro (la misma razón de la regla del 28/07). */
.en-ventana .ficha > .titulo-caja { display: none; }

/* Menú del botón derecho, propio del sistema (nunca el del navegador). */
.menu-contextual {
  display: none; position: absolute; z-index: 60;
  background: #fff; border: 1px solid var(--borde);
  border-radius: 6px; box-shadow: 0 4px 14px rgba(20,30,40,.22);
  padding: .25rem; min-width: 15rem;
}
.menu-contextual.abierto { display: block; }
.menu-contextual button {
  display: block; width: 100%; text-align: left; background: none; border: none;
  padding: .5rem .7rem; font: inherit; font-size: .95rem; cursor: pointer;
  border-radius: 4px; color: var(--texto, inherit);
}
.menu-contextual button:hover, .menu-contextual button:focus {
  background: var(--azul-suave, #eef3f8); outline: none;
}
.menu-contextual .atajo { color: #667; font-size: .85rem; margin-left: .6rem; }
.subtitulo {
  font-size: .95rem; font-weight: 600; margin: 1.2rem 0 .5rem;
  border-top: 2px solid var(--azul); padding-top: 1rem;  /* línea azul divisoria (D41) */
  display: flex; align-items: center; justify-content: space-between; gap: .6rem;
}
/* Botón chico pegado al subtítulo (ej. "+ Agregar" de contactos, prototipo 01). */
.subtitulo .btn { padding: .2rem .6rem; font-size: .85rem; font-weight: 400; }

/* Grillas de carga (contactos, estados, socios): las cajas de texto adentro
   de la grilla llevan el MISMO formato que cualquier campo (D41: borde
   redondeado, foco azul) — señalado por Leo, 28/07/2026. */
.tabla-carga td { padding: .32rem .3rem; }
.tabla-carga td input, .tabla-carga td select {
  width: 100%; min-width: 7rem; padding: .4rem .55rem; border: 1px solid var(--borde);
  border-radius: 6px; font-size: .95rem; font-family: inherit; background: #fff;
}
.tabla-carga td input:focus, .tabla-carga td select:focus {
  outline: 2px solid var(--azul); border-color: var(--azul);
}
/* Una grilla de carga que además es lista estándar (los documentos y los
   beneficiarios del legajo, D108 §4): el ancho lo manda la columna, que se
   arrastra. Con el piso de 7rem de la grilla común, cinco campos empujaban la
   tabla más allá de la ficha y aparecía un scroll de costado sin motivo (P1). */
.tabla-listado.tabla-carga td input:not([type="checkbox"]),
.tabla-listado.tabla-carga td select { min-width: 0; }
.tabla-carga td input[type="checkbox"] { width: auto; min-width: 0; }
.tabla-carga td.acciones-documento { white-space: nowrap; }
.tabla-carga td.acciones-documento .btn { margin-right: .25rem; }
.barra-documentos { align-items: center; gap: .5rem; margin-bottom: .4rem; }
/* D113: la franja de arriba de los feriados (dónde está la empresa, cuántos a
   confirmar). No se achica: es parte de la cabecera fija de la lista (D79). */
.tarjeta.lista > .barra-feriados { flex: 0 0 auto; }
.barra-feriados { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; padding: .35rem .75rem; }
.barra-feriados .lugar-empresa { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; margin: 0; }
.barra-feriados select, .barra-feriados .caja-buscable { width: auto; min-width: 11rem; }
.valor-solo-lectura { padding: .45rem 0; }

/* ---- D115 §7: la lista que se despliega y se achica al escribir ----
   Flota sobre todo (también sobre las fichas flotantes) y se ubica debajo de
   la caja que la abrió, o arriba si abajo no hay lugar. La flechita dice que
   es una lista: se toca y se despliega. */
input.caja-buscable {
  padding-right: 1.6rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23555'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right .55rem center;
}
.lista-desplegable {
  position: fixed; z-index: 5000; background: #fff; color: #000;
  border: 1px solid var(--borde); border-radius: 6px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .18);
  max-height: 16rem; max-width: min(34rem, 96vw); overflow-y: auto; font-size: .95rem;
}
.lista-desplegable-opcion {
  padding: .35rem .65rem; cursor: pointer;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lista-desplegable-opcion.elegida { font-weight: 600; }
.lista-desplegable-opcion.resaltada, .lista-desplegable-opcion:hover { background: #e3eefa; }
.lista-desplegable-vacia { padding: .35rem .65rem; color: #555; font-style: italic; }
/* Quitar una fila: la cruz roja compacta del prototipo 01, no un botonazo. */
.quitar {
  color: var(--rojo); background: none; border: none; cursor: pointer;
  font-size: .9rem; padding: .2rem .4rem;
}
.quitar:hover { font-weight: 700; }
/* ====== Grillas de importes (prototipo 04: carga de cotización) ======
   Números a la derecha con ancho de dígito parejo, y las filas de la cuenta
   (subtotal, descuentos, flete, total) pegadas al pie de los renglones. */
input.campo-num {
  width: 100%; min-width: 5rem; text-align: right; padding: .4rem .55rem;
  border: 1px solid var(--borde); border-radius: 6px;
  font-size: .95rem; font-family: inherit; font-variant-numeric: tabular-nums;
}
input.campo-num:focus { outline: 2px solid var(--azul); border-color: var(--azul); }
input.campo-num.chica { width: 6rem; min-width: 0; }
td.centro, th.centro { text-align: center; }
.etiq { font-size: .78rem; color: var(--texto-suave); }
/* La marca de color de un comprobante o de una forma de pago (D212; Leo, BH25): el nombre del
   tipo sobre su color, el número sin color. Los colores los da la parametrización. */
.marca-comprobante { display: inline-block; padding: 0 .4rem; border-radius: 4px; font-weight: 600;
  font-size: .92em; line-height: 1.4; white-space: nowrap; }
td.etiq-der { text-align: right; font-weight: 600; color: var(--texto-suave); }
/* El ítem que el proveedor no cotizó: queda gris, adentro pero afuera. */
tr.no-cotiza td { color: var(--texto-suave); background: #fafbfc; }
/* Filas de la cuenta: más oscuras que un renglón no cotizado, para que se
   lean como "esto ya no son ítems". */
.fila-ajuste td { background: #e9edf1; }
/* «Lo que ofrece el proveedor por su cuenta» (Leo, 04/08/2026): una sección
   dentro de la misma grilla, para que se lea como parte de la misma oferta
   —suma en el mismo subtotal— pero se vea que no contesta el pedido. */
tr.fila-seccion td { background: #eef3f7; padding-top: .5rem; padding-bottom: .5rem; }
tr.fila-agregar-extra td { background: #f7f9fb; }
/* Código, descripción y unidad de un ítem agregado, en una sola celda. */
.fila-material { display: flex; gap: .35rem; align-items: center; }
.fila-material input { min-width: 0; }
select.sel-flete {
  padding: .2rem .35rem; border: 1px solid var(--borde); border-radius: 5px;
  font-size: .93rem; font-family: inherit; width: 7rem; background: #fff;
}
/* Tilde alineada con la altura de los campos de al lado. */
.check-inline { display: flex; align-items: center; gap: .4rem; font-size: .95rem; height: 2.35rem; }
.check-inline label { font-weight: 400; color: var(--texto); margin: 0; }

/* ====== Comparación de cotizaciones (prototipo 03) ======
   Una columna por cotización; cada celda es precio · cantidad asignada ·
   total del ítem, apilados a la derecha. */
.prov-cab { line-height: 1.35; }
.prov-cab .nombre { color: var(--texto); font-size: .85rem; text-transform: none; letter-spacing: 0; }
.prov-cab .cond { font-weight: 400; text-transform: none; letter-spacing: 0; font-size: .78rem; }
.celda-cotiz { display: flex; flex-direction: column; align-items: flex-end; gap: .15rem; }
.celda-cotiz .precio { font-variant-numeric: tabular-nums; }
.celda-cotiz .total-item {
  font-variant-numeric: tabular-nums; font-weight: 600; font-size: .9rem; color: var(--texto-suave);
}
/* El mejor precio del ítem, en celeste: se ve de un vistazo cuál conviene. */
td.mejor { background: #e3f1fa; }
td.mejor .precio { color: var(--azul-oscuro); font-weight: 700; }
td.nocotiza { color: var(--texto-suave); text-align: center; }
input.cant {
  width: 6.2rem; text-align: right; padding: .18rem .35rem;
  border: 1px solid var(--borde); border-radius: 5px;
  font-size: .92rem; font-variant-numeric: tabular-nums; font-family: inherit;
}
input.cant:focus { outline: 2px solid var(--azul); border-color: var(--azul); }
input.cant.con-valor { border-color: var(--azul); background: #eaf4fb; font-weight: 600; }
/* Lo que falta asignar del pedido: verde si está completo, rojo si se pasó. */
.pendiente-ok { color: var(--verde); font-weight: 600; }
.pendiente-falta { color: var(--texto-suave); }
.pendiente-exceso { color: var(--rojo); font-weight: 700; }

.fila-botones { display: flex; gap: .6rem; flex-wrap: wrap; }
/* Par de botones pegados: el principal y su "abrir en ventana aparte" (D6) */
.grupo-boton { display: inline-flex; }
.grupo-boton .btn:first-child { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.btn-aparte {
  border-top-left-radius: 0; border-bottom-left-radius: 0; border-left: none;
  padding: .45rem .55rem; color: var(--texto-suave);
}
.btn-aparte:hover { color: var(--azul-oscuro); }

/* Con mucho zoom la barra fija ocuparía demasiado: cuando pasa del ~20 %
   del alto de la pantalla, deja de estar fija y scrollea con el contenido
   (pedido de Leo, 27/07/2026). La barra mide ~4.4rem → umbral: 22rem. */
@media (max-height: 22rem) {
  .barra-superior { position: static; }
  .fondo-acceso::before { inset: 0; }
}

/* ====== Responsive ====== */
@media (max-width: 640px) {
  .contenido { padding: .75rem; }
  .col-opcional { display: none; }
  .tabla-estado td:first-child { width: auto; }
  .campo { min-width: 100%; }
}

/* ====== Solo lectura (ver sin editar, D42) ====== */
/* Un fieldset "plano" agrupa los campos de una ficha sin cambiar su aspecto;
   deshabilitado, deja todo en solo lectura (los botones de acción se ocultan
   aparte: sin permiso no se ven, pedido de Leo 28/07/2026). */
fieldset.plano { border: 0; padding: 0; margin: 0; min-width: 0; }
fieldset.plano:disabled input,
fieldset.plano:disabled select,
fieldset.plano:disabled textarea { background: #f3f4f6; color: #374151; }

/* ====== Dónde está parado el teclado (va ÚLTIMO: le tiene que ganar a
   cualquier regla de foco anterior) ======
   Pedido de Leo (01/08/2026): "hay veces que un botón está pintado de azul
   pero el Enter no lo aprieta". El azul del botón principal es su COLOR, no
   su foco. El foco es este anillo amarillo con halo: no se parece a nada más
   de la pantalla, así que lo que está marcado así es lo que responde a Enter.
   Se usa :focus-visible — con el mouse no aparece, solo al navegar con
   teclado, que es cuando hace falta saberlo. */
.btn:focus-visible,
button:focus-visible,
.campo input:focus-visible, .campo select:focus-visible, .campo textarea:focus-visible,
input.campo-num:focus-visible, input.cant:focus-visible,
.tabla-carga td input:focus-visible, .tabla-carga td select:focus-visible,
a.link:focus-visible, .nav-ficha:focus-visible, .item-menu:focus-visible,
.barra-superior .btn-volver:focus-visible,
.alternar:focus-visible, .quitar:focus-visible,
.barra-lista input[type="search"]:focus-visible, input[type="search"]:focus-visible {
  outline: 3px solid #e0b400;
  outline-offset: 1px;
  box-shadow: 0 0 0 4px rgba(224, 180, 0, .25);
}

/* ====== Elegir qué se está cargando (material o agrupador) ======
   Va arriba de todo en la ficha de material: de esta elección depende el
   resto de la pantalla, así que tiene que leerse como una decisión, no como
   un campo más (Leo, 01/08/2026). */
.elegir-tipo { display: flex; gap: .5rem; flex-wrap: wrap; }
.opcion-tipo {
  flex: 1; min-width: 15rem; display: flex; align-items: center; gap: .5rem;
  border: 1px solid var(--borde); border-radius: 6px; padding: .5rem .7rem;
  font-size: .9rem; color: var(--texto-suave); cursor: pointer; background: #fff;
}
.opcion-tipo b { color: var(--texto); }
.opcion-tipo:hover { background: #f0f6fb; }
.opcion-tipo.elegida { border-color: var(--azul); background: #eaf4fb; }
.opcion-tipo input { width: auto; margin: 0; }
/* En el árbol, la carpeta se distingue del material sin tener que leer. */
.fila-agrupador { font-weight: 600; }

/* ====== Grilla de dos líneas por ítem (solicitud de materiales) ======
   Un renglón por material no entraba a lo ancho y obligaba a scrollear para
   cargar (Leo, 01/08/2026): ahora cada ítem usa dos líneas y toda su
   información se ve junta mientras se carga. En el LISTADO sigue yendo un
   ítem por renglón, que ahí sí entra. */
.grilla-renglones tbody.renglon-pedido { border-bottom: 2px solid var(--borde); }
.grilla-renglones tbody.renglon-pedido tr { border-bottom: none; }
.grilla-renglones .renglon-segunda-linea td { padding-top: 0; padding-bottom: .5rem; }
.grilla-renglones .renglon-segunda-linea .etiq { white-space: nowrap; padding-right: .3rem; }

/* ====== Ayudas de pantalla, que se pueden apagar (Leo, 01/08/2026) ======
   Los carteles que explican cómo funciona cada pantalla sirven al principio
   y estorban cuando ya te sabés el sistema. Cada usuario los prende o los
   apaga desde el menú de su círculo de iniciales; la preferencia se guarda
   en su ficha, así lo acompaña en cualquier máquina.
   Ojo al escribir pantallas nuevas: la clase «ayuda» es para lo que EXPLICA.
   Un mensaje de "todavía no hay nada cargado" o un aviso de estado NO lleva
   esta clase — si se esconde, la pantalla queda muda. */
body.sin-ayudas .ayuda { display: none; }

/* ====== Factura de compra: dos hojas (D53) ======
   La carga se parte en dos hojas que se alternan con el botón segmentado de
   la barra de título y con F2. La barra de la factura, los controles
   automáticos y la barra de acciones quedan visibles en las dos. */
.barra-factura { position: sticky; top: 4.2rem; z-index: 3; }
.hojas { display: inline-flex; background: #1b3d5c; border-radius: 8px; padding: 2px; gap: 2px; }
.hoja-boton {
  border: none; border-radius: 6px; cursor: pointer; font: inherit;
  font-size: .85rem; font-weight: 600; padding: .2rem .7rem;
  background: transparent; color: #b6cee0;
}
.hoja-boton.activa { background: #fff; color: var(--azul-naval); }
/* El origen de la compra va solo en su renglón, con el rótulo al lado. */
.fila-origen { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; margin-bottom: .6rem; }
.fila-origen label { font-size: .78rem; font-weight: 600; color: var(--texto-suave); }
.fila-origen select { max-width: 28rem; padding: .35rem .5rem; border: 1px solid var(--borde); border-radius: 6px; }
.linea-divisoria { border-top: 1px solid var(--borde); margin: .2rem 0 .8rem; }
/* La fila del renglón activo: se marca con el fondo, sin barras de color. */
.fila-activa td { background: #eaf4fb; }
.barra-avance { height: 8px; background: #e3e7eb; border-radius: 4px; overflow: hidden; }

/* ====== La factura entra en una pantalla (Leo, 02/08/2026) ======
   Es la pantalla más cargada del sistema y se usa todo el día: con el zoom al
   100 % tiene que verse de una sola vez hasta el total. Se aprieta el aire,
   no la letra. */
.pantalla-densa .cuerpo-tarjeta { padding: .6rem .8rem; }
.pantalla-densa .fila-campos { gap: .6rem; margin-bottom: .5rem; }
.pantalla-densa .titulo-caja { margin: .5rem 0 2px; padding: .35rem .9rem; font-size: 1rem; }
.pantalla-densa .campo label { margin-bottom: .1rem; }
.pantalla-densa .campo input, .pantalla-densa .campo select { padding: .3rem .5rem; }
.pantalla-densa table td { padding: .25rem .4rem; }
.pantalla-densa .descripcion { margin-bottom: .4rem; }
.pantalla-densa .pie-tabla { padding: .3rem .8rem; }

/* La tabla de renglones se edita en la propia fila (Leo, 02/08/2026): los
   campos ocupan la celda entera y no se ven como cajas sueltas. */
#tablaRenglones td input, #tablaRenglones td select {
  width: 100%; border: 1px solid transparent; background: transparent;
  padding: .25rem .35rem; border-radius: 5px; font-size: .95rem; font-family: inherit;
}
#tablaRenglones td input:hover, #tablaRenglones td select:hover { border-color: var(--borde); }
#tablaRenglones td input:focus, #tablaRenglones td select:focus {
  background: #fff; border-color: var(--azul); outline: none;
}
#tablaRenglones .acciones-fila { white-space: nowrap; text-align: right; }
/* Material en UNA columna (Leo, 03/08/2026): se lee y se escribe
   «código - descripción» todo junto, y se busca por cualquiera de los dos. Es
   la columna más larga de la tabla: se lleva todo el ancho que sobra (y tiene un mínimo,
   más abajo, desde el prototipo 31). */
#tablaRenglones .chipFalta:empty { display: none; }
#tablaRenglones .celdaRubro { white-space: nowrap; }
.btn-chico { padding: .1rem .5rem; font-size: .85rem; }
/* La línea del precio que se guarda en la lista del proveedor, al pie. */
.fila-precio td { background: #f7f8f9; font-size: .9rem; color: var(--texto-suave); padding: .35rem .6rem; }
.barra-avance div { height: 100%; width: 0; transition: width .15s; }

/* ====== Factura de compra: obra, rubro y alícuota únicos (BH22, prototipo 31) ======
   Todo con el prefijo `fc-`: un modificador local nunca se llama como una clase del sistema
   (V13 — ya mordió cinco veces). */
/* BH27 (Leo, 20/10/2026: «me parece más lógico dejarla ancha y listo»): la factura es SIEMPRE
   ancha. En el prototipo pasaba de 1088 a 1440 px recién al destildar «Obra única» o «Alícuota
   única», y la pantalla entera saltaba. Ancha de entrada, el material (lo que identifica el
   renglón, guía D133) no se achica cuando aparecen las columnas Obra e IVA. */
body.factura-de-compra .contenido { max-width: 1440px; }
/* El rótulo del campo con su tilde al lado. */
.fc-rotulo { display: flex; justify-content: space-between; align-items: baseline; gap: .6rem; }
.campo .fc-rotulo > label { margin-bottom: .1rem; }
.fc-tilde { display: inline-flex; align-items: center; gap: .3rem; white-space: nowrap; font-size: .88rem; }
.campo .fc-tilde input[type="checkbox"] { margin: 0; width: auto; }
.campo .fc-tilde label { display: inline; margin: 0; font-size: .88rem; font-weight: 400; color: var(--texto); }
/* Las columnas que se ven solo con su tilde destildado (7.2). */
#tablaRenglones.fc-sin-obra .fc-obra,
#tablaRenglones.fc-sin-rubro .fc-rubro { display: none; }
.fc-alic { display: block; text-align: right; padding-right: .55rem; font-variant-numeric: tabular-nums; }
/* BK3: el «Grabar» de arriba, en la barra del título de la factura. Claro sobre el azul de la
   barra, como «Ir a …»: el azul del botón principal ahí se perdía y parecía un texto. */
.barra-factura .fc-grabar-arriba {
  padding: .2rem .9rem; font-size: .9rem; background: #fff; color: var(--azul-naval);
  border-color: #fff; font-weight: 700;
}
.barra-factura .fc-grabar-arriba:hover { background: #e8eef4; }

/* ---- D203 §2: el pie por alícuota. Cada alícuota con su neto y su IVA. ---- */
#cuerpoAlicuotas .fc-cabeza-alic td {
  padding-top: .7rem; border-top: 1px solid var(--borde);
  font-size: .78rem; color: var(--texto-suave); text-transform: uppercase; letter-spacing: .02em;
}
#cuerpoAlicuotas .fc-cabeza-alic td b { color: var(--texto); }
#cuerpoAlicuotas .fc-cabeza-alic .etiq { text-transform: none; letter-spacing: 0; }
/* La primera columna se parte en renglones antes que ensanchar la tabla: en un celular la tabla
   de importes ya se corre de costado adentro de su tarjeta, y no tiene que crecer. */
#cuerpoAlicuotas tr > td:first-child { white-space: normal; }
#cuerpoAlicuotas td.col { text-align: right; padding-right: .7rem; }
.fc-nombre-alic { font-weight: 600; }
.fc-celda-neto input { display: block; max-width: 11rem; margin-left: auto; }
.fc-papel { display: block; font-size: .82rem; color: #9a6700; }
.fc-papel:empty { display: none; }
.fc-sin { color: var(--texto-suave); }
#cuadreNetos .estado { white-space: normal; }

/* ---- D203 §1: los renglones, una sección por alícuota, cada una con su ajuste ---- */
#tablaRenglones tr.fc-banda > td {
  background: var(--azul-naval); color: #fff; padding: .3rem .5rem; font-size: .9rem;
  border-top: 2px solid #fff;
}
#tablaRenglones tr.fc-banda.fc-mal > td { background: #8a1c14; }
#tablaRenglones tr.fc-banda.fc-destino > td { background: #217fb7; }
#tablaRenglones tr.fc-destino:not(.fc-banda) > td { background: #e3f0fb; }
.fc-banda-in {
  position: sticky; left: .5rem; display: flex; flex-wrap: wrap; align-items: center;
  gap: .25rem .9rem;
}
.fc-banda-nombre { font-weight: 700; font-size: .95rem; }
.fc-banda-dato { white-space: nowrap; font-variant-numeric: tabular-nums; opacity: .92; }
.fc-banda-in .estado { margin: 0; }
.fc-banda-in .fc-b-mas { padding: .05rem .55rem; font-size: .82rem; }
#tablaRenglones tr.fc-vacia td { font-size: .88rem; padding: .5rem .8rem; }
/* La manija para pasar un renglón de sección: se agarra por acá, no por la fila entera. */
.fc-asa {
  display: inline-block; width: 1rem; margin-right: .15rem; text-align: center;
  color: #8a94a3; cursor: grab; user-select: none; touch-action: none; vertical-align: middle;
}
.fc-asa:hover { color: var(--azul); }
.fc-asa-quieta { cursor: default; }
#tablaRenglones.fc-seccionada .celdaMaterial { white-space: nowrap; }
#tablaRenglones.fc-seccionada .celdaMaterial input { width: calc(100% - 1.15rem); vertical-align: middle; }
#tablaRenglones tr.fc-recien > td { animation: fc-brillo 1.8s ease-out; }
@keyframes fc-brillo { from { background: #fff1b8; } to { background: transparent; } }
.fc-fantasma {
  position: fixed; z-index: 80; pointer-events: none; background: #fff;
  border: 1px solid var(--borde); border-radius: 6px; box-shadow: 0 4px 14px rgba(20,30,40,.22);
  padding: .3rem .6rem; font-size: .9rem; white-space: nowrap;
}
.fc-fantasma-a { color: var(--azul); margin-left: .3rem; }
body.fc-arrastrando, body.fc-arrastrando * { cursor: grabbing !important; user-select: none; }
/* El menú del renglón y de los botones del pie (la caja es la del sistema: .menu-contextual). */
#fcMenu .fc-menu-tit {
  padding: .3rem .7rem .35rem; font-size: .8rem; color: var(--texto-suave);
  border-bottom: 1px solid var(--borde); margin-bottom: .2rem; max-width: 22rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#fcMenu button.fc-apagado { color: var(--texto-suave); cursor: default; white-space: normal; max-width: 22rem; }
/* La ventana de grabar: los problemas numerados, cada uno con su arreglo. */
.fc-problemas { margin: .5rem 0 .4rem 1.2rem; padding: 0; }
.fc-problemas li { margin-bottom: .7rem; }
.fc-arreglos { margin-top: .35rem; display: flex; flex-wrap: wrap; gap: .4rem; }
.fc-nota { margin: .4rem 0 0; color: var(--texto-suave); font-size: .9rem; }
.fc-m { white-space: nowrap; }

/* ---- BK2: la sección de pago ---- */
#tablaPagos .fc-pago-hecho td { color: var(--texto-suave); }
#tablaPagos .fc-pago-a-favor td { background: #f4f8fb; }
.fc-a-favor { margin-top: .6rem; padding: .45rem .7rem; background: #f4f8fb; border-radius: 6px; }
/* BH28: el renglón de ajuste, alineado con los demás. La cantidad y el precio los calcula el
   sistema y van como texto, con el mismo aire que el número de un campo; el texto ocupa el
   ancho entero, como el material de los demás, y la marca «ajuste» pasó a la cantidad, a la
   izquierda del 1 (antes iba adelante del texto y lo corría). */
#tablaRenglones .fc-fijo {
  display: block; text-align: right; padding: .25rem calc(.35rem + 1px);
  font-size: .95rem; font-variant-numeric: tabular-nums; white-space: nowrap;
}
#tablaRenglones .fc-marca-ajuste { float: left; font-size: .78rem; }
/* El material es lo que identifica el renglón y no se achica nunca (guía D133): con las tres
   columnas a la vista en una pantalla angosta, o con la letra grande (D124), la tabla desliza
   de costado ADENTRO de su tarjeta antes que dejar el material en «Cement». La página no. */
#tablaRenglones .celdaMaterial input { min-width: 12rem; }
/* BH26: en un celular el título de la factura quedaba escrito letra por letra, porque los
   carteles («Parcialmente cargada», «Imputada») y el botón «Ir a 2» se comían el ancho. Bajan
   a otro renglón. */
@media (max-width: 700px) {
  .barra-factura { flex-wrap: wrap; }
  .barra-factura .acciones-titulo { flex: 1 1 100%; flex-wrap: wrap; margin-left: 0; }
  /* Lo mismo en «Importes y conceptos fiscales»: los dos botones (BK49) se comían el ancho y el
     título quedaba escrito letra por letra. */
  .fc-titulo-importes { flex-wrap: wrap; }
  .fc-titulo-importes .acciones-titulo { flex: 1 1 100%; flex-wrap: wrap; margin-left: 0; }
}

/* ====== Documento imprimible (orden de compra) ======
   Es lo que ve el proveedor: se imprime o se guarda en PDF desde el navegador
   y se manda "vía compartir" por WhatsApp o mail (D45). Mismo lenguaje visual
   del sistema, pero con aire de papel: hoja blanca, encabezado con el logo y
   pie de firmas. Al imprimir desaparece todo lo que es pantalla. */
.hoja-documento {
  background: var(--blanco); border: 1px solid var(--borde); border-radius: 8px;
  padding: 1.6rem; max-width: 900px; margin: 0 auto;
}
.encabezado-documento {
  display: flex; align-items: center; gap: 1.5rem;
  border-bottom: 2px solid var(--azul); padding-bottom: 1rem; margin-bottom: 1rem;
}
.logo-documento { height: 3.4rem; }
.datos-documento { margin-left: auto; text-align: right; }
.datos-documento h2 { font-size: 1.3rem; color: var(--azul-naval); }
.marca-estado { color: var(--rojo); font-weight: 700; letter-spacing: .08em; }
.datos-cabecera { width: 100%; margin-bottom: 1rem; }
.datos-cabecera th {
  text-align: left; font-size: .78rem; text-transform: uppercase;
  color: var(--texto-suave); padding: .25rem .6rem .25rem 0; white-space: nowrap;
}
.datos-cabecera td { padding: .25rem 1.2rem .25rem 0; white-space: normal; }
.detalle-documento { width: 100%; }
.detalle-documento th { background: var(--azul-naval); color: #fff; }
.nota-documento { font-size: .9rem; color: var(--texto-suave); margin-top: 1rem; }
.firma-documento {
  display: flex; justify-content: space-between; gap: 2rem;
  margin-top: 3.5rem; text-align: center; font-size: .9rem;
}

@media print {
  .barra-superior, .barra-acciones, .sin-imprimir, .velo-centrado { display: none !important; }
  body { background: #fff; }
  .contenido { padding: 0; max-width: none; }
  .hoja-documento { border: none; padding: 0; max-width: none; }
}

/* ============================================================
   EL LISTADO ESTÁNDAR (D79) — prototipo 05-listado-estandar.html
   ------------------------------------------------------------
   El sistema es, en su mayoría, listados, y nunca se había prototipado
   ninguno: TODOS los hallazgos de la validación de Caja y Bancos fueron
   sobre listados. Esto se escribe UNA vez acá y lo hereda toda pantalla de
   lista, igual que el «← Volver» (D65) y el bloqueo de edición (D35).

   Una pantalla se declara listado con el bloque `clases_body` en
   «pantalla-lista» y marcando su tabla con `class="tabla-listado"`. El resto
   —ordenar, anchos, cartelitos, totales— lo arma solo el JavaScript de
   base.html.
   ============================================================ */

/* ---- Regla 1: una sola zona de scroll, la tabla. La página no scrollea ----
   Era el problema de fondo: dos scrolls peleándose hacían que al bajar por la
   lista se fueran de pantalla los encabezados y los botones (C1). Con la
   página quieta, lo de arriba y lo de abajo no se puede ir a ningún lado. */
body.pantalla-lista { height: 100vh; overflow: hidden; display: flex; flex-direction: column; }
body.pantalla-lista .barra-superior { flex: 0 0 auto; }
/* El listado usa TODO el ancho: el tope de 1088px es para una ficha, que se
   lee mejor angosta; una tabla angosta esconde columnas detrás de un scroll
   horizontal, que es lo que dejaba invisible el botón «Anular» (C7). */
body.pantalla-lista .contenido {
  flex: 1 1 auto; min-height: 0; max-width: none;
  /* El `margin: 0 auto` que el contenido trae de las fichas (donde centrar SÍ
     corresponde) hay que apagarlo a mano: en un contenedor flexible, un margen
     `auto` en el eje transversal **anula el estirado** y centra el bloque en su
     tamaño natural. Con él puesto, medido en una ventana de 1280 px, la lista
     se dibujaba de 947 px con 166 px de aire a cada lado — o sea, cuantas menos
     columnas tenía un listado, más angosto se dibujaba (hallazgo F3). */
  margin: 0; width: 100%;
  display: flex; flex-direction: column; overflow: hidden; padding: .8rem 1rem;
}
/* Lo que va arriba de la tabla (avisos, ayuda, cajas de contexto) no se
   estira, pero SÍ se encoge: hay pantallas con bastante preámbulo —la del
   dólar tiene cuatro cajas antes de la lista— y con la página quieta eso
   empujaba el listado abajo del borde, o sea lo hacía desaparecer. Encogiendo,
   cada caja scrollea adentro suyo y la lista nunca se pierde de vista. */
body.pantalla-lista .contenido > * { flex: 0 1 auto; min-height: 0; overflow: auto; }
/* La lista se come todo lo que sobra y tiene piso: por apretada que quede la
   pantalla, siempre se ven unas cuantas filas. */
body.pantalla-lista .contenido > .tarjeta.lista {
  flex: 1 1 auto; min-height: 14rem; margin-bottom: 0; overflow: hidden;
}
body.pantalla-lista .caja-aviso,
body.pantalla-lista .caja-error,
body.pantalla-lista .caja-alerta { margin-bottom: .6rem; }
/* Un aviso no se achica nunca para dejarle lugar a la lista (hallazgo BA4). La regla de arriba
   deja que todo lo que está sobre la tabla ceda alto, con su scroll; con dos avisos en las
   cotizaciones del dólar, la caja verde quedaba aplastada en una franja que no se leía. */
body.pantalla-lista .contenido > .caja-aviso,
body.pantalla-lista .contenido > .caja-error,
body.pantalla-lista .contenido > .caja-alerta { flex: 0 0 auto; overflow: visible; }
/* La ayuda de la pantalla no puede comerse la lista: se le pone techo propio
   y scrollea adentro suyo. */
body.pantalla-lista .tarjeta.ayuda { max-height: 9rem; overflow: auto; margin-bottom: .6rem; }
/* …pero tampoco puede quedar aplastada (M1, Leo 12/09/2026: «la ventana de las
   ayudas es muy fina en vertical y no se puede leer»). La regla de arriba la
   dejaba con `flex: 0 1 auto`, o sea ENCOGIBLE: con una pantalla baja o con
   zoom, la lista —que tiene piso de 14rem— la comprimía hasta dejar una franja
   de un renglón. Con `flex: 0 0 auto` ocupa lo que necesita, hasta su techo de
   9rem, y adentro scrollea. */
body.pantalla-lista .contenido > .tarjeta.ayuda { flex: 0 0 auto; }
/* El cuadro de «buscar mientras se escribe» (D105) que vive en la barra de la
   lista: mismo formato que cualquier campo, no el crudo del navegador. */
.barra-lista input[type="search"], .lq-ventana input[type="search"], .lq .buscador input[type="search"], .lq .pop input[type="search"] {
  font-family: inherit; font-size: .95rem; padding: .45rem .6rem;
  border: 1px solid var(--borde); border-radius: 6px; background: #fff;
  flex: 1 1 14rem; min-width: 9rem; max-width: 26rem;
}
/* Con el mouse, azul; con el teclado manda la marca ámbar de D51 (N62): sin el
   :not, esta regla va después y le ganaba. */
.barra-lista input[type="search"]:focus:not(:focus-visible) { outline: 2px solid var(--azul); border-color: var(--azul); }
/* La ficha flotante SÍ scrollea (es `position: fixed` con su propio overflow),
   así que la página quieta no le hace nada. */

/* La tarjeta que contiene la lista: botones, filtros, tabla y pie, apilados;
   solo la tabla scrollea. */
.tarjeta.lista { display: flex; flex-direction: column; overflow: hidden; }
.tarjeta.lista > .desliza { flex: 1 1 auto; min-height: 0; overflow: auto; }
.tarjeta.lista > .pie-tabla { flex: 0 0 auto; }
.tarjeta.lista > .barra-lista, .tarjeta.lista > .panel-filtros { flex: 0 0 auto; }

/* ---- Regla 2: la barra de botones, siempre a la vista ----
   Vive DENTRO de la tarjeta de la lista, arriba de la tabla: así no se va con
   el scroll y además queda pegada a lo que opera. */
.barra-lista {
  display: flex; gap: .5rem; align-items: center; flex-wrap: wrap;
  padding: .5rem .7rem; margin: 0;
  background: var(--blanco); border-bottom: 1px solid var(--borde);
  justify-content: flex-start;
}
.barra-lista .empuja { margin-left: auto; }
.barra-lista .interruptor {
  display: inline-flex; align-items: center; gap: .4rem;
  font-size: .9rem; color: var(--texto-suave); cursor: pointer;
}
.barra-lista .interruptor input { cursor: pointer; }

/* ---- Regla 3: filtros plegados, y los puestos a la vista en cartelitos ----
   Leo: «la parte superior de la pantalla no debería aparecer por defecto»
   (C2). Con el detalle que hace la diferencia: un filtro activo tiene que
   notarse PLEGADO, si no alguien mira una lista filtrada creyendo que la ve
   entera. Para eso están los cartelitos amarillos. */
.panel-filtros { display: none; }
.panel-filtros.abierto { display: block; }
.tarjeta.lista > .panel-filtros {
  background: #fafbfc; border-bottom: 1px solid var(--borde); padding: .7rem;
}
.tarjeta.lista > .panel-filtros .tarjeta { margin: 0; border: none; background: none; }
.tarjeta.lista > .panel-filtros .cuerpo-tarjeta { padding: 0; }
.tarjeta.lista > .panel-filtros .fila-campos { margin-bottom: 0; }
.btn.activo { background: var(--azul); color: #fff; border-color: var(--azul); }
.chips-filtro { display: inline-flex; gap: .35rem; flex-wrap: wrap; align-items: center; }
.chip-filtro {
  background: var(--amarillo-suave); border: 1px solid #e0c86a; border-radius: 20px;
  padding: .1rem .3rem .1rem .6rem; font-size: .82rem;
  display: inline-flex; align-items: center; gap: .3rem; max-width: 22rem;
}
.chip-filtro .texto { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chip-filtro button {
  border: none; background: none; cursor: pointer; font-weight: 700;
  color: var(--texto-suave); font-size: 1rem; line-height: 1; padding: 0 .25rem;
}
.chip-filtro button:hover { color: var(--rojo); }

/* ---- La tabla ---- */
/* `fixed` es lo que permite las dos cosas que pidió Leo: que una referencia
   larga NO rompa la tabla (regla 8) y que el ancho de cada columna se pueda
   arrastrar (regla 5). Sin ancho fijo, el navegador reparte según el
   contenido y lo que uno arrastra se le vuelve a escapar. */
table.tabla-listado { width: 100%; border-collapse: separate; border-spacing: 0; }
/* El ancho fijo lo prende el JavaScript DESPUÉS de medir cuánto ocupa de
   verdad cada columna: si se declarara acá, el navegador repartiría todo en
   partes iguales y la fecha ocuparía lo mismo que el concepto. Sin
   JavaScript la tabla se comporta como siempre (scroll horizontal), que es
   peor pero no rompe nada. */
table.tabla-listado.anchos-fijos { table-layout: fixed; min-width: 100%; }
/* ---- Regla 2: los encabezados, siempre a la vista ---- */
table.tabla-listado thead th {
  position: sticky; top: 0; z-index: 10;
  background: #dde5ec; color: var(--azul-naval); font-weight: 700;
  font-size: .8rem; text-transform: none; letter-spacing: 0;
  border-bottom: 2px solid #9fb0bf; text-align: left;
  padding: .45rem .55rem; white-space: nowrap;
}
table.tabla-listado thead th.col { text-align: right; }
/* ---- Regla 4: ordenar con clic en el título; otro clic invierte ---- */
table.tabla-listado thead th.ordenable { cursor: pointer; user-select: none; }
table.tabla-listado thead th.ordenable:hover { background: #cfdae4; }
table.tabla-listado thead th .envuelto { position: relative; display: block; overflow: hidden; text-overflow: ellipsis; }
table.tabla-listado thead th .flecha { color: var(--azul); font-size: .75rem; margin-left: .25rem; opacity: 0; }
table.tabla-listado thead th.ordenada .flecha { opacity: 1; }
/* ---- Regla 5: el ancho se arrastra, como en Excel ----
   La franja agarrable vive ADENTRO de la celda, pegada a su borde derecho, y
   es hermana del `.envuelto` — no hija (F2). Adentro la recortaba el
   `overflow: hidden` de los títulos largos y quedaba inagarrable; y afuera del
   `th` la taparía la celda siguiente, que también es `sticky`. Los últimos
   11 px de cada columna, que es justo donde uno apunta. */
/* (No hace falta `position: relative` en el `th`: ya es `sticky` por la regla 2
   —y declararle `relative` acá lo desclavaría—, y `sticky` alcanza de sobra
   para ubicar un hijo absoluto.) */
table.tabla-listado thead th .tirador {
  position: absolute; right: 0; top: 0; height: 100%; width: .7rem;
  cursor: col-resize; z-index: 3;
}
/* Se nota al pasar el mouse: sin una marca visible, nadie descubre que la
   columna se puede ensanchar. */
table.tabla-listado thead th .tirador:hover { background: var(--azul); opacity: .35; }
/* Y la línea divisoria dice dónde termina cada columna, que es donde hay que
   apuntar. */
table.tabla-listado thead th + th { border-left: 1px solid #b9c7d3; }
body.arrastrando-columna { cursor: col-resize; user-select: none; }
/* ---- Regla 8: contenido largo, cortado con puntos y legible al pasar el mouse ----
   Hoy una referencia larga «se va toda la info de la pantalla» (C4). */
table.tabla-listado tbody td, table.tabla-listado tfoot td {
  padding: .38rem .55rem; border-bottom: 1px solid #e8ecef;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
table.tabla-listado tbody tr { border-bottom: none; }
table.tabla-listado tbody tr:hover > td { background: #f6f9fb; }
/* ---- Regla 9: los totales, abajo de sus propias columnas ----
   No en un pie de texto: debajo de la columna que suman, y pegados al fondo
   del marco para que se lean aunque la lista sea larga (regla 2). */
table.tabla-listado tfoot td {
  position: sticky; bottom: 0; z-index: 10;
  background: #dde5ec; color: var(--azul-naval); font-weight: 700;
  border-top: 2px solid #9fb0bf; border-bottom: none;
}
table.tabla-listado tfoot td.col { text-align: right; font-variant-numeric: tabular-nums; }
/* ---- Regla 13: los datos derivados van en itálica ----
   Los que calcula el sistema y nadie carga a mano (la obra de un movimiento,
   D77). La itálica dice «esto se ve, no se edita». El color baja apenas, lo
   justo para distinguirse sin volverse ilegible (el gris de antes no se
   distinguía). */
table.tabla-listado td.derivada { color: #48535e; font-style: italic; }
/* Lo derivado va en itálica también fuera de los listados: las horas que el
   horario de la obra calcula de sus tramos (N70). */
.tabla-carga td.derivada, .derivada { font-style: italic; }
table.tabla-listado th.derivada { font-style: italic; }
/* ---- Regla 16: lo que agrupa no es una fila de datos ----
   Cuando un listado agrupa (los movimientos de una orden de pago), el
   agrupador se dibuja como BANDA corrida, sin columnas alineadas, para que
   nunca se lea como un registro de esa tabla. Distinto del cheque con sus
   gastos colgando: ahí el padre sí es un movimiento y va como fila. */
table.tabla-listado tr.banda > td {
  background: var(--azul-naval); color: #fff; font-weight: 600;
  padding: .35rem .6rem; font-size: .9rem; white-space: normal;
}
table.tabla-listado tr.banda .total { float: right; font-weight: 400; opacity: .85; }
table.tabla-listado tr.banda a { color: #8fc7ea; }
/* Una fila que cuelga de otra (el impuesto al cheque, la otra pata del
   traspaso): se corre a la derecha y viaja pegada a su padre al ordenar. */
table.tabla-listado tr.fila-hija > td:first-child { padding-left: 1.9rem; }
table.tabla-listado tr.fila-hija > td { font-size: .9rem; color: var(--texto-suave); }

/* ---- Regla 7: lo inactivo o anulado no se muestra por defecto ----
   Leo: «las cuentas que no están activas no deberían aparecer por defecto»
   (B6). Vale para cajas, materiales, proveedores, clientes, usuarios y
   chequeras. El interruptor lo pone solo el JavaScript cuando encuentra
   alguna fila marcada; sin filas inactivas no aparece ningún control que
   explicar. */
tr.fila-inactiva { display: none; }
body.ver-inactivos tr.fila-inactiva { display: table-row; }

/* La fila a la que se vuelve al salir de la ficha (regla 6) usa la marca que
   ya existía, `.fila-elegida`. */

/* Adentro de la ventana de «elegir, corregir o cargar» (D67) el listado NO
   toma la pantalla entera: es un marco chico dentro de otra pantalla. Se le
   saca la altura completa para que el iframe crezca con su contenido. */
.en-ventana.pantalla-lista, body.en-ventana.pantalla-lista { height: auto; overflow: visible; display: block; }
.en-ventana.pantalla-lista .contenido { overflow: visible; display: block; }
.en-ventana.pantalla-lista .tarjeta.lista { overflow: visible; }
.en-ventana.pantalla-lista .tarjeta.lista > .desliza { overflow: auto; max-height: 60vh; }

/* Adentro de la ventana de «elegir, corregir o cargar» (D67) el buscador NO se
   pliega: la ventana se abre justamente para buscar (es también el buscador
   grande de D66). Plegar el filtro ahí sería esconder la herramienta principal
   detrás de un botón. */
.en-ventana .panel-filtros { display: block; }
.en-ventana [data-abre-filtros] { display: none; }

/* Las listas hermanas de Mano de obra (siete botones): en la computadora se
   acomodan como siempre; en el celular van en UN renglón que se desliza de
   costado, para que la tabla conserve su alto (D79 reglas 1 y 2). */
.listas-hermanas { display: contents; }
@media (max-width: 700px) {
  .listas-hermanas { display: flex; flex: 1 1 100%; gap: .3rem; overflow-x: auto; flex-wrap: nowrap; }
  .listas-hermanas .btn { flex: 0 0 auto; }
}

/* El número de mensajes sin leer, sobre el círculo de las iniciales (D101 §5.1). */
.circulo-boton { position: relative; }
.num-circulo { position: absolute; top: -.25rem; right: -.35rem; background: #c0392b; color: #fff;
  border-radius: 999px; font-size: .68rem; line-height: 1.05rem; min-width: 1.05rem; padding: 0 .25rem;
  font-weight: 700; pointer-events: none; }
/* Y en el menú del círculo, CUÁLES (prototipo 09, `pintarPopAvisos`). */
.menu-desplegable .titulo-seccion { padding: .3rem .9rem .15rem; font-size: .8rem; font-weight: 700; color: var(--texto-suave); }
.menu-desplegable .vacio-menu { padding: .35rem .9rem; font-size: .9rem; color: var(--texto-suave); }
.menu-desplegable .aviso-item b { display: flex; justify-content: space-between; gap: .5rem; align-items: center; font-weight: 600; }
.menu-desplegable .aviso-item small { display: block; color: var(--texto-suave); font-size: .84rem; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; max-width: 22rem; }
.num-rojo { display: inline-block; min-width: 1.2rem; border-radius: 9px; background: #c0392b; color: #fff; font-size: .72rem;
  text-align: center; padding: 0 .3rem; }
.menu-desplegable .pie-pop { padding: .4rem .9rem .2rem; border-top: 1px solid #e6eaee; margin-top: .3rem; }

/* ---------- Parametrización: el índice a un lado, la lista al otro ----------
   Leo, 21/09/2026: «la pantalla de Parametrización de Mano de obra es muy
   confusa; se mezclan los distintos botones con el buscar dentro de una lista de
   uno de ellos».

   Tenía razón y el problema era de jerarquía, no de estilo: las diez listas, el
   «Exportar», el «Nuevo» y el cuadro de buscar vivían en la MISMA barra, todos
   con forma de botón. Nada decía cuál era el índice y cuál la acción — y el
   buscar, que filtra UNA lista, parecía un botón más al lado de las otras nueve.

   Ahora son dos cosas separadas: de un lado se elige QUÉ se parametriza, del otro
   se trabaja con eso. */
.param { display: flex; gap: .8rem; align-items: stretch; min-height: 0; }
body.pantalla-lista .contenido > .param { flex: 1 1 auto; min-height: 14rem; overflow: hidden; }
.param > .tarjeta.lista { flex: 1 1 auto; min-width: 0; margin-bottom: 0; }

.param-indice {
  flex: 0 0 15rem; display: flex; flex-direction: column; gap: 2px;
  background: #fff; border: 1px solid var(--borde); border-radius: var(--radio);
  padding: .5rem; overflow: auto; min-height: 0;
}
.param-rotulo {
  font-size: .78rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--texto-suave); padding: .1rem .4rem .35rem;
}
.param-item {
  display: block; padding: .4rem .55rem; border-radius: 4px; text-decoration: none;
  color: var(--texto); font-size: .95rem; line-height: 1.25; border: 1px solid transparent;
}
.param-item:hover { background: #eef4f9; }
.param-item.elegida { background: var(--azul); color: #fff; font-weight: 600; }
.param-item:focus-visible { outline: 2px solid var(--foco); outline-offset: 1px; }
/* El nombre de la lista abierta, ahí donde antes estaba su botón: sin esto, del
   lado derecho no quedaba escrito en ningún lado qué se está mirando. */
.titulo-de-la-lista { font-weight: 700; font-size: 1.02rem; }

/* En una pantalla angosta el índice va arriba, en una sola línea que se desliza:
   una columna de quince rem al costado de un celular no deja lugar para la lista.
   Y lo mismo, en cualquier pantalla, para las listas de MUCHAS columnas (`.arriba`):
   con seis datos propios —los feriados— el índice al costado dejaba la tabla sin
   lugar y la lista se corría de lado, que es justo lo que esto vino a arreglar. */
.param.arriba { flex-direction: column; }
.param.arriba > .param-indice {
  flex: 0 0 auto; flex-direction: row; gap: .3rem; overflow-x: auto; overflow-y: hidden;
  padding: .35rem; align-items: center;
}
.param.arriba .param-rotulo { padding: 0 .5rem 0 .2rem; }
.param.arriba .param-item { white-space: nowrap; }
@media (max-width: 820px) {
  .param { flex-direction: column; }
  .param-indice {
    flex: 0 0 auto; flex-direction: row; gap: .3rem; overflow-x: auto; overflow-y: hidden;
    padding: .35rem;
  }
  .param-rotulo { display: none; }
  .param-item { white-space: nowrap; }
}

/* ---------- La ventana flotante de mensajes y avisos (D129, prototipo 17) ----------
   Leo, 21/09/2026: «imagino la ventana de mensajes como una ventana emergente,
   flotante sobre cualquier pantalla que estamos usando en el momento; que se pueda
   desplazar, para ver lo que hay abajo, por si necesitamos mirar datos para escribir
   el mensaje».

   SIN VELO, a propósito: el velo es lo que taparía justamente lo que hay que mirar, y
   en este proyecto ya tapó cuatro veces algo importante (D65, D68, G8, J3). */
/* `:not(.caja-error)` NO es un adorno (hallazgo AI1, 26/09/2026). El cartel de error que
   flota sobre la ficha se llama `.caja-error.flotante` desde el 02/09 (F20), y esta
   ventana nació el 21/09 usando la misma palabra. Como esta regla viene después en la
   hoja, **le ganaba**: todo cartel de error del sistema salía blanco con borde azul —sin
   su color de error— y con 14rem de alto mínimo, o sea 224 px para decir «El nombre es
   obligatorio», tapando el botón Guardar de cualquier ficha baja. Es la regla de V13
   —un nombre local nunca se llama como una clase del sistema— mordiendo por cuarta vez. */
.flotante:not(.caja-error) {
  position: fixed; background: #fff; border: 1px solid var(--azul-naval); border-radius: 10px;
  box-shadow: 0 12px 40px rgba(13,36,56,.28); display: flex; flex-direction: column;
  min-width: 19rem; min-height: 14rem; z-index: 80; overflow: hidden;
}
.flotante[hidden] { display: none; }
.flotante .cabecera {
  background: var(--azul-naval); color: #fff; padding: .45rem .7rem; display: flex;
  align-items: center; gap: .5rem; cursor: move; user-select: none; flex: 0 0 auto;
}
/* La agarradera: una zona clara de donde tomar la ventana. Sin esto, con las dos
   solapas ocupando la barra quedaban unos pocos píxeles agarrables — el mismo
   problema que F2, el tirador del ancho de columna con 5,6 px útiles. */
.flotante .cabecera .agarradera {
  cursor: move; opacity: .75; font-size: 1.1rem; line-height: 1; padding: 0 .15rem;
  letter-spacing: -.1em;
}
/* Y el hueco entre las solapas y los botones también agarra. */
.flotante .cabecera .hueco { flex: 1; min-width: 1.5rem; align-self: stretch; cursor: move; }
.flotante .cabecera .solapas { display: flex; gap: .25rem; }
.flotante .cabecera .sol {
  background: rgba(255,255,255,.1); color: #cfe2f0; border: 1px solid rgba(255,255,255,.22);
  border-radius: 6px; padding: .15rem .6rem; font: inherit; font-size: .9rem; cursor: pointer;
  width: auto; height: auto; display: inline-flex; align-items: center; gap: .35rem;
}
.flotante .cabecera .sol.elegida { background: #fff; color: var(--azul-naval); border-color: #fff; font-weight: 600; }
.flotante .cabecera .sol i {
  background: var(--rojo); color: #fff; border-radius: 10px; font-size: .68rem;
  padding: 0 .3rem; font-weight: 700; font-style: normal;
}
.flotante .cabecera .sol.elegida i { background: var(--azul); }
.flotante .cabecera .sol i:empty { display: none; }
.flotante .cabecera .acc { display: flex; gap: .3rem; }
.flotante .cabecera button {
  background: rgba(255,255,255,.15); color: #fff; border: 1px solid rgba(255,255,255,.35);
  border-radius: 5px; width: 1.5rem; height: 1.5rem; font: inherit; font-size: .85rem;
  cursor: pointer; display: flex; align-items: center; justify-content: center; padding: 0;
}
.flotante .cabecera button:hover { background: rgba(255,255,255,.3); }
.flotante .adentro { flex: 1; min-height: 0; display: flex; overflow: hidden; }
.flotante .adentro[hidden] { display: none; }
.flotante.minimizada .adentro { display: none; }
.flotante.minimizada { height: auto !important; min-height: 0; }
/* La esquina, más grande y por encima de todo lo de adentro (la lista y el campo de
   escribir tienen su propio scroll y le robaban el clic). */
.flotante .tirador {
  position: absolute; right: 0; bottom: 0; width: 22px; height: 22px; cursor: nwse-resize;
  z-index: 6;
  background: linear-gradient(135deg, transparent 45%, var(--borde) 45%, var(--borde) 55%,
    transparent 55%, transparent 70%, var(--borde) 70%, var(--borde) 80%, transparent 80%);
}
.flotante .tirador:hover { background-color: rgba(33, 127, 183, .18); }
/* Y los dos BORDES, que es lo que una persona intenta primero: agarrar el costado o el
   pie de la ventana. Son franjas de 8 px, invisibles, que agrandan sólo en su eje. */
.flotante .tirador-lado {
  position: absolute; z-index: 5; background: transparent;
}
/* Van ADENTRO, no sobresaliendo: la ventana tiene `overflow: hidden`, así que lo que
   sale del borde queda recortado y **no recibe el clic** — parecía andar y no agarraba
   nada (medido con `elementFromPoint`). Y la franja derecha arranca en la mitad de abajo
   a propósito: más arriba está la barra de scroll del hilo de mensajes, y taparla sería
   cambiar un problema por otro. */
.flotante .tirador-lado.derecha { top: 55%; right: 0; width: 7px; bottom: 22px; cursor: ew-resize; }
.flotante .tirador-lado.abajo { left: 0; bottom: 0; height: 7px; right: 22px; cursor: ns-resize; }
.flotante .tirador-lado:hover { background: rgba(33, 127, 183, .25); }

/* La columna de la lista: el buscador arriba, las conversaciones en el medio (con su
   propio scroll) y abajo «Nuevo mensaje…» y las archivadas (hallazgos AZ-C55 y C56).
   El ancho de 12rem es el de arranque: el separador lo cambia y queda guardado (C53). */
.flotante .lista-conv {
  width: 12rem; flex: 0 0 auto; border-right: 1px solid var(--borde); background: #fafbfc;
  display: flex; flex-direction: column; min-height: 0; min-width: 0;
}
.flotante .lista-conv .filas-conv { flex: 1; min-height: 0; overflow: auto; }
.flotante .buscar-conv { padding: .35rem .4rem; border-bottom: 1px solid var(--borde); flex: 0 0 auto; }
.flotante .buscar-conv[hidden] { display: none; }
/* Un campo no se queda chico (D125 §5): crece con A+ como todo lo demás. */
.flotante .buscar-conv input { width: 100%; font: inherit; font-size: .92rem; padding: .25rem .4rem; }
.flotante .pie-conv {
  display: flex; flex-wrap: wrap; gap: .3rem; padding: .35rem .4rem; border-top: 1px solid var(--borde);
  flex: 0 0 auto;
}
.flotante .pie-conv[hidden] { display: none; }
/* El separador entre la lista y la conversación (C53): una franja de 6 px que se
   agarra para ensanchar la lista. Se marca al pasar el mouse para que se vea que se
   puede agarrar. */
.flotante .separador-conv { flex: 0 0 6px; cursor: col-resize; background: transparent; margin-left: -1px; }
.flotante .separador-conv:hover, .flotante .separador-conv:focus,
.flotante .separador-conv.arrastrando { background: rgba(33, 127, 183, .25); outline: none; }
.flotante .conv.volver { color: var(--azul-naval); font-weight: 600; font-size: .85rem; background: #f3f6f8; }
.flotante .conv .marca { font-weight: 400; color: var(--texto-suave); font-size: .76rem; }
.flotante .conv .txt small.pedacito { color: #21507a; font-style: italic; }
/* La cabecera de la conversación abierta: el nombre, quiénes participan con su rol
   (C57) y los botones de archivar y salir del grupo (C55). */
.flotante .cab-hilo {
  display: flex; align-items: center; gap: .4rem; padding: .35rem .55rem; flex-wrap: wrap;
  border-bottom: 1px solid var(--borde); background: #f7f9fb; flex: 0 0 auto;
}
.flotante .cab-hilo[hidden] { display: none; }
.flotante .cab-hilo .que { flex: 1 1 8rem; min-width: 0; }
.flotante .cab-hilo .que b { display: block; font-size: .9rem; word-break: break-word; }
.flotante .cab-hilo .que small { display: block; font-size: .76rem; color: var(--texto-suave); word-break: break-word; }
.flotante .cab-hilo .acc-hilo { display: flex; gap: .3rem; flex-wrap: wrap; }
/* Mientras está abierta la ventana de confirmar (la de «¿Salir del grupo?», por
   ejemplo), la flotante baja ABAJO de su velo: si no, la pregunta del sistema (D41)
   quedaba tapada por la ventana que la pidió. */
body:has(#veloConfirmar.abierto) .flotante:not(.caja-error) { z-index: 45; }
.flotante .conv {
  display: flex; gap: .4rem; padding: .45rem .5rem; border-bottom: 1px solid #eef2f5;
  cursor: pointer; align-items: center; width: 100%; text-align: left; background: none;
  border-left: 0; border-right: 0; border-top: 0; font: inherit;
}
.flotante .conv:hover { background: #f2f8fd; }
.flotante .conv.elegida { background: #e7f1f8; border-left: 3px solid var(--azul); }
.flotante .conv .ic {
  background: var(--azul); color: #fff; border-radius: 50%; width: 1.6rem; height: 1.6rem;
  flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
  font-size: .7rem; font-weight: 700;
}
.flotante .conv.sistema .ic { background: var(--azul-naval); }
/* El grupo de una obra, cuadrado y naval, como en la pantalla de mensajes (C57). */
.flotante .conv.grupo .ic { background: var(--azul-naval); border-radius: 6px; }
.flotante .conv .txt { min-width: 0; flex: 1; }
.flotante .conv .txt b { display: block; font-size: .86rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.flotante .conv .txt small {
  display: block; color: var(--texto-suave); font-size: .76rem; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.flotante .conv .n { background: var(--rojo); color: #fff; border-radius: 10px; font-size: .68rem; padding: 0 .3rem; font-weight: 700; }

.flotante .hilo { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.flotante .mensajes {
  flex: 1; min-height: 0; overflow: auto; padding: .5rem .6rem; display: flex;
  flex-direction: column; gap: .4rem; background: #f7fafc;
}
.flotante .msj {
  background: #fff; border: 1px solid var(--borde); border-radius: 8px; padding: .35rem .55rem;
  font-size: .9rem; max-width: 85%; line-height: 1.4;
}
.flotante .msj.mio { align-self: flex-end; background: #e7f1f8; border-color: #bcd9ed; }
.flotante .msj.del-sistema { align-self: stretch; max-width: none; background: #fff6e0; border-color: #e8d49a; }
.flotante .msj.sistema { background: #fff6e0; border-color: #e8d49a; }
.flotante .msj.buscado { outline: 2px solid var(--azul); outline-offset: 2px; }
/* «Fulano salió del grupo» (D168 §10): noticia del grupo, al medio y en gris. */
.flotante .msj.aviso-grupo { align-self: center; background: transparent; border: 0; color: var(--texto-suave); font-size: .78rem; text-align: center; }
/* Los tildes de lo que uno manda (D114 §5), en la pantalla de mensajes y en la
   ventana de Alt+M (hallazgo AZ-C57: las dos muestran lo mismo que mostraba la
   oficina): ✓ enviado · ✓✓ gris le llegó · ✓✓ azul lo leyeron. */
.msj .tildes {
  margin-left: .35rem; font-size: .8rem; letter-spacing: -.15rem; color: #8b949c;
  font-style: normal; cursor: default; white-space: nowrap;
}
.msj .tildes.leido { color: #1d8fe0; }
.flotante .msj.urgente { border-left: 3px solid var(--rojo); }
.flotante .msj .quien { display: block; font-size: .74rem; color: var(--texto-suave); margin-bottom: .1rem; }
.flotante .msj .acciones { display: flex; gap: .3rem; margin-top: .35rem; flex-wrap: wrap; }
.flotante .escribir {
  border-top: 1px solid var(--borde); padding: .45rem .55rem; display: flex; gap: .4rem;
  align-items: flex-end; flex: 0 0 auto; background: #fff;
}
.flotante .escribir[hidden] { display: none; }
.flotante .escribir textarea {
  flex: 1; font: inherit; font-size: .92rem; padding: .35rem .5rem; border: 1px solid var(--borde);
  border-radius: 6px; resize: none; min-height: 2.3rem; max-height: 6rem;
}
.flotante .vacio-ventana { color: var(--texto-suave); font-size: .88rem; padding: .8rem; text-align: center; }

@media (max-width: 700px) {
  /* En el celular no hay «al lado»: la ventana ocupa casi todo y no se arrastra. */
  .flotante {
    left: .5rem !important; right: .5rem !important; top: auto !important; bottom: .5rem !important;
    width: auto !important; height: 70vh !important; box-shadow: 0 4px 16px rgba(13,36,56,.25);
  }
  .flotante .cabecera { cursor: default; }
  /* En el celular la columna no se ensancha: el ancho guardado en la computadora
     no sirve acá (por eso el !important le gana al que dejó el separador). */
  .flotante .lista-conv { width: 8.5rem !important; }
  .flotante .separador-conv { display: none; }
  .flotante .tirador, .flotante .tirador-lado { display: none; }
}

/* ===========================================================================
   EL PANEL DEL PIE (D135 §11, Leo el 23/09/2026)
   ===========================================================================
   Idea suya, y vale para TODAS las pantallas de novedades: *«podríamos tener la
   sección de abajo colapsada en el fondo de la pantalla, en 2 (máximo 3) líneas, y
   que la misma crezca hacia arriba cuando pasamos el mouse por arriba […] hacer clic
   en la barra la deja crecida y otro clic la vuelve a bajar»*. Y después:
   *«el formato de novedades colapsado lo imagino igual en todas las pantallas:
   Resumen, detalle, personal y obras»* — más la precisión que lo define:
   *«siempre en el pie de la pantalla, no necesariamente pegado a la ventana superior»*.

   Por eso vive acá y no en cada plantilla: si cada pantalla lo escribiera por su
   cuenta, tres de las cuatro terminarían distintas, que es exactamente lo que Leo
   viene marcando desde D117 (uniformidad visual).

   Tres cosas que sostienen el diseño:
   · **Va al pie, siempre**. El `margin-top:auto` lo empuja al fondo del área de
     trabajo, aunque lo de arriba sea corto: el hueco queda en el medio y el panel no
     cambia de lugar. Lo que se busca con el mouse está siempre donde mismo.
   · **Colapsado se ve el título y los botones.** Lo que hay que apretar nunca se
     esconde; lo que se esconde es el detalle.
   · **El retardo es sólo al abrir** (no al cerrar): pasar por encima de casualidad
     camino a otra cosa no tiene que desplegar nada.
   =========================================================================== */
.panel-pie { flex: 0 0 auto; display: flex; flex-direction: column; margin-top: auto; }
/* Las dos convenciones que usan las pantallas para el cuerpo del panel. */
.panel-pie > .cuerpo, .panel-pie > .panel-cuerpo {
  flex: 0 1 auto; max-height: 0; min-height: 0; overflow: hidden; padding: 0 .8rem;
  transition: max-height .18s ease .35s, padding .18s ease .35s;
}
.panel-pie:hover > .cuerpo, .panel-pie.fijo > .cuerpo, .panel-pie:focus-within > .cuerpo,
.panel-pie:hover > .panel-cuerpo, .panel-pie.fijo > .panel-cuerpo,
.panel-pie:focus-within > .panel-cuerpo {
  /* Hasta la MITAD de la pantalla si hay contenido que lo justifique (Leo,
     23/09/2026). El clamp hace las dos cosas: nunca pasa de la mitad, y si adentro
     hay poco, el panel crece sólo lo que ocupa lo que tiene. */
  max-height: clamp(8rem, 50vh, 30rem); overflow: auto; padding: .5rem .8rem;
  transition-delay: 0s;
}
/* La barra que se agarra: el título de la caja, cualquiera de las dos formas. */
.panel-pie > .titulo-caja, .panel-pie > h2 { cursor: pointer; }
.panel-pie .fijar { margin-left: .4rem; font-size: .8rem; opacity: .75; }

/* Qué quiere decir cada color (AY7): la tabla que abre un botón con data-colores. */
.tabla-colores { width: 100%; border-collapse: collapse; margin-top: .5rem; font-size: .92rem; text-align: left; }
.tabla-colores td { padding: .3rem .45rem; border-bottom: 1px solid #eef1f4; vertical-align: top; }
.tabla-colores td:first-child { width: 11rem; white-space: nowrap; }
.muestra-color { display: inline-block; padding: .1rem .45rem; border-radius: 4px; }
.boton-colores { min-width: 2rem; justify-content: center; font-weight: 700; }

/* El cartelito del guardado automático (D181): «Guardado hace 3 s», «Guardando…», o en rojo
   «Sin guardar: …» con el motivo. Va en la barra de cada pantalla de presupuestación.
   ANCHO FIJO (BE102, Leo 13/10/2026: «el cartel hace que el botón se caiga a la fila de abajo»):
   el texto cambia cada pocos segundos, y si el cartel cambiara de ancho empujaría todo lo que
   tiene al lado. Un motivo largo se corta con «…» y se lee entero al pasar el mouse. */
.autoguardado {
  font-size: .9rem; color: var(--texto-suave); white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; flex: 0 0 auto; width: 13rem; align-self: center; padding: 0 .35rem;
}
.autoguardado.guardando { color: var(--texto-suave); font-style: italic; }
.autoguardado.sin-guardar { color: #b42318; font-weight: 600; }

/* ====== Lo que sale del NP como archivo (BK5, BK18, BK44) ======
   Las clases llevan el prefijo `np-arch-` (V13: un nombre local nunca se llama como una
   clase del sistema). */

/* La nota al pie: «Preparando el Excel…», «No se guardó». No interrumpe —para eso está
   la ventana del sistema (D84)—: avisa y se va sola. Por encima de las ventanas del
   sistema (50) y por debajo de la cortina por inactividad (200). */
.np-arch-nota {
  position: fixed; right: 1rem; bottom: 1rem; z-index: 70;
  display: flex; align-items: center; gap: .6rem; max-width: min(34rem, calc(100% - 2rem));
  background: var(--blanco); color: var(--texto); border: 1px solid var(--borde);
  border-left: 4px solid var(--azul); border-radius: 8px; padding: .55rem .7rem;
  box-shadow: 0 6px 22px rgba(13,36,56,.18); font-size: .95rem; line-height: 1.35;
}
.np-arch-nota-texto { flex: 1 1 auto; min-width: 0; }
.np-arch-nota-cerrar {
  flex: 0 0 auto; border: 0; background: none; color: var(--texto-suave); cursor: pointer;
  font-size: 1.2rem; line-height: 1; padding: 0 .2rem;
}
.np-arch-nota-cerrar:hover { color: var(--texto); }

/* El marco donde se carga lo que se imprime: invisible y sin ocupar lugar, pero NO
   `display: none` (con eso el navegador no carga el PDF y no hay nada que imprimir). */
.np-arch-imprimir {
  position: absolute; left: 0; top: 0; width: 0; height: 0; border: 0;
  visibility: hidden; pointer-events: none;
}

/* La ventana de compartir: las dos vías, una debajo de la otra. */
.np-arch-compartir { text-align: left; }
.np-arch-archivos {
  display: flex; align-items: center; justify-content: space-between; gap: .6rem; flex-wrap: wrap;
  margin-bottom: .55rem; word-break: break-word;
}
.np-arch-estado { color: var(--texto-suave); font-size: .92rem; }
.np-arch-fila { display: flex; align-items: center; gap: .8rem; }
.np-arch-fila > p { flex: 1 1 auto; margin-bottom: 0 !important; }
.np-arch-fila > .btn { flex: 0 0 auto; }
@media (max-width: 600px) { .np-arch-fila { flex-direction: column; align-items: flex-start; } }
.np-arch-texto { margin-bottom: .6rem; font-size: .95rem; white-space: pre-wrap; }
.np-arch-paso {
  border: 1px solid var(--borde); border-radius: 8px; padding: .6rem .75rem; margin-bottom: .6rem;
  background: #fbfcfd;
}
.np-arch-paso > b { display: block; color: var(--azul-naval); margin-bottom: .25rem; }
.np-arch-paso p { margin-bottom: .45rem; font-size: .95rem; }
.np-arch-no { color: var(--texto-suave); }
.np-arch-chats { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
.np-arch-tarjeta {
  display: inline-flex; align-items: center; gap: .55rem; margin: 0;
  padding: .45rem .7rem; border: 1px dashed var(--azul); border-radius: 8px; background: #eef6fc;
  cursor: grab; user-select: none; max-width: 100%;
}
.np-arch-tarjeta:active, .np-arch-tarjeta.arrastrando { cursor: grabbing; opacity: .7; }
.np-arch-tarjeta small { display: block; color: var(--texto-suave); font-size: .82rem; }
.np-arch-tarjeta b { word-break: break-word; }
.np-arch-icono { font-size: 1.5rem; line-height: 1; }

@media print {
  .np-arch-nota { display: none !important; }
}

