/* ============================================================================
   MODALES — Gestión Gama
   ----------------------------------------------------------------------------
   Ventanas que se superponen a la pantalla, difuminando lo que hay detrás.
   Se usan en el flujo de modificación de la fórmula de cálculo (CU-09) y
   quedan disponibles para cualquier confirmación posterior.

   No declara colores literales: todos vienen de temas.css, de modo que los
   modales acompañan el cambio de tema.
   ============================================================================ */

/* ---------------------------------------------------------------------------
   FONDO

   Cubre la ventana entera y difumina el contenido. El desenfoque no es solo
   estético: separa visualmente el modal del fondo y deja claro que la pantalla
   de atrás está inactiva, sin necesidad de oscurecerla tanto que se vuelva
   ilegible.

   z-index por debajo de la pantalla de carga (9000): si el usuario confirma la
   fórmula, la carga debe verse por encima del modal.
   --------------------------------------------------------------------------- */
.modal-fondo {
    position: fixed;
    inset: 0;
    z-index: 8000;

    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;

    background: var(--modal-fondo);
    backdrop-filter: blur(4px);

    /* La aparición es breve: un modal que tarda en llegar se percibe como
       lentitud del sistema, no como elegancia. */
    animation: modal-aparecer 0.18s ease;
}

@keyframes modal-aparecer {
    from {
        opacity: 0;
    }
    to {
        opacity: 1;
    }
}

/* ---------------------------------------------------------------------------
   CAJA

   Reutiliza el contenedor del login y de los paneles de inventario: mismo
   fondo, mismo borde, misma franja dorada superior.
   --------------------------------------------------------------------------- */
.modal-caja {
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    box-shadow: var(--card-sombra);
    width: 100%;
    max-width: 420px;
    position: relative;

    /* Sube desde abajo al aparecer, reforzando la sensación de que emerge
       sobre la pantalla y no de que estaba oculta ahí. */
    animation: modal-subir 0.2s ease;
}

/* Variante para diálogos de confirmación, que llevan menos contenido. */
.modal-caja-angosta {
    max-width: 380px;
}

@keyframes modal-subir {
    from {
        transform: translateY(12px);
    }
    to {
        transform: translateY(0);
    }
}

.modal-caja::before {
    content: "";
    display: block;
    height: 2px;
    background: linear-gradient(
        90deg,
        transparent 0%,
        var(--acento-oscuro) 20%,
        var(--acento) 50%,
        var(--acento-oscuro) 80%,
        transparent 100%
    );
}

.modal-contenido {
    padding: 22px 26px 24px;
}

/* ---------------------------------------------------------------------------
   TÍTULO
   --------------------------------------------------------------------------- */
.modal-titulo {
    font-size: 0.85rem;
    font-weight: 500;
    letter-spacing: 1.4px;
    text-transform: uppercase;
    color: var(--input-texto);
    margin: 0 0 18px;
}

/* ---------------------------------------------------------------------------
   VISTA PREVIA DE LA FÓRMULA

   Refleja lo que el usuario está escribiendo, con el factor resultante. Va en
   monoespaciada porque los operadores y los números se alinean mejor y la
   expresión se lee de un vistazo.
   --------------------------------------------------------------------------- */
.formula-previa {
    background: var(--input-bg);
    border: 1px solid var(--input-border);
    padding: 12px 14px;
    margin-bottom: 20px;
    text-align: center;
}

.formula-previa code {
    font-family: "Consolas", "Courier New", monospace;
    font-size: 0.82rem;
    color: var(--texto-secundario);
    letter-spacing: 0.5px;
}

/* El factor es el dato que importa: se destaca en color de acento para que se
   distinga de los porcentajes que lo componen. */
.formula-previa code strong {
    color: var(--acento);
    font-weight: 500;
}

/* ---------------------------------------------------------------------------
   CAMPOS

   Etiqueta a la izquierda, campo a la derecha: con solo dos campos cortos,
   esta disposición ocupa menos alto que apilarlos y mantiene el modal compacto.
   --------------------------------------------------------------------------- */
.modal-campo {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 14px;
}

.modal-campo label {
    font-size: 0.75rem;
    color: var(--input-texto);
    min-width: 78px;
}

.modal-campo input {
    width: 90px;
    padding: 7px 10px;
    background: var(--input-bg);
    border: 1px solid var(--input-border);
    color: var(--input-texto);
    font-size: 0.78rem;
    font-family: inherit;
    text-align: right;
    transition: border-color 0.2s ease;
    box-sizing: border-box;
}

.modal-campo input:hover {
    border-color: var(--input-border-hover);
}

.modal-campo input:focus {
    outline: none;
    border-color: var(--acento);
}

.modal-campo input::placeholder {
    color: var(--input-placeholder);
}

/* Las flechas que Chrome agrega a los campos numéricos se ocultan: ocupan
   espacio, invitan a un uso poco práctico con decimales y desalinean el texto
   respecto de los demás campos. */
.modal-campo input::-webkit-outer-spin-button,
.modal-campo input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.modal-campo input[type="number"] {
    -moz-appearance: textfield;
    appearance: textfield;
}

.modal-sufijo {
    font-size: 0.78rem;
    color: var(--texto-secundario);
}

/* ---------------------------------------------------------------------------
   DIÁLOGO DE ADVERTENCIA
   --------------------------------------------------------------------------- */
.modal-icono-alerta {
    width: 40px;
    height: 40px;
    color: var(--acento);
    display: block;
    margin: 0 auto 16px;
}

.modal-advertencia {
    font-size: 0.78rem;
    line-height: 1.55;
    color: var(--input-texto);
    text-align: center;
    margin: 0 0 20px;
}

/* ---- Campo de contraseña ---- */
.modal-campo-password {
    margin-bottom: 20px;
}

.modal-campo-password label {
    display: block;
    font-size: 0.7rem;
    font-weight: 500;
    color: var(--input-texto);
    margin-bottom: 7px;
}

.password-envoltorio {
    display: flex;
    gap: 8px;
}

.password-envoltorio input {
    flex: 1;
    padding: 8px 11px;
    background: var(--input-bg);
    border: 1px solid var(--input-border);
    color: var(--input-texto);
    font-size: 0.8rem;
    font-family: inherit;
    transition: border-color 0.2s ease;
    box-sizing: border-box;
    min-width: 0;
}

.password-envoltorio input:focus {
    outline: none;
    border-color: var(--acento);
}

.btn-ver-password {
    width: 38px;
    background: var(--input-bg);
    border: 1px solid var(--input-border);
    color: var(--texto-secundario);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: all 0.2s ease;
    padding: 0;
}

.btn-ver-password:hover {
    border-color: var(--acento);
    color: var(--acento);
}

.btn-ver-password svg {
    width: 16px;
    height: 16px;
}

/* Los dos iconos —ojo abierto y tachado— están siempre en el DOM y el CSS
   decide cuál mostrar, igual que en el indicador de fraccionable del
   inventario. Así el marcado no cambia y la lógica queda en la hoja de
   estilos. */
.btn-ver-password .icono-ojo-tachado {
    display: none;
}

.btn-ver-password.visible .icono-ojo {
    display: none;
}

.btn-ver-password.visible .icono-ojo-tachado {
    display: block;
}

/* ---------------------------------------------------------------------------
   ERRORES
   --------------------------------------------------------------------------- */
.modal-error {
    padding: 9px 12px;
    margin-bottom: 16px;
    font-size: 0.72rem;
    color: var(--error-texto);
    background: var(--error-bg);
    border: 1px solid var(--error-border);
}

.modal-error p {
    margin: 0;
}

.modal-error p + p {
    margin-top: 4px;
}

/* ---------------------------------------------------------------------------
   CONFIRMACIONES

   Mensaje de que la operación se realizó con éxito. Es el mismo en todas las
   pantallas: verde, con una franja a la izquierda y una tilde antes del
   texto. La tilde la agrega el CSS, así las plantillas solo escriben el
   mensaje.
   --------------------------------------------------------------------------- */
.modal-exito {
    padding: 9px 12px;
    margin-bottom: 16px;
    font-size: 0.72rem;
    color: var(--exito-texto);
    background: var(--exito-bg);
    border: 1px solid var(--exito-border);
    border-left: 3px solid var(--exito-texto);
}

.modal-exito p {
    margin: 0;
}

.modal-exito p::before {
    content: "\2713";
    margin-right: 8px;
    font-weight: 700;
}

/* ---------------------------------------------------------------------------
   ACCIONES

   Alineadas a la derecha, con la acción principal primero. Es la disposición
   habitual en Windows, que es el sistema donde va a operar el negocio.
   --------------------------------------------------------------------------- */
.modal-acciones {
    display: flex;
    justify-content: flex-end;
    gap: 9px;
    margin-top: 4px;
}

.modal-acciones .btn {
    min-width: 96px;
}

/* ---------------------------------------------------------------------------
   ACCESIBILIDAD
   --------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .modal-fondo,
    .modal-caja {
        animation: none;
    }
}

/* Variante del modal para listados: más alto que los diálogos de confirmación,
   porque el contenido crece con la cantidad de categorías. */
.modal-caja-lista {
    max-width: 400px;
}

/* ---------------------------------------------------------------------------
   ENCABEZADO CON CIERRE
   --------------------------------------------------------------------------- */
.modal-encabezado {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 18px;
}

.modal-encabezado .modal-titulo {
    margin: 0;
}

.modal-cerrar {
    width: 28px;
    height: 28px;
    background: transparent;
    border: 1px solid var(--input-border);
    color: var(--texto-secundario);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: all 0.2s ease;
    padding: 0;
}

.modal-cerrar:hover {
    border-color: var(--acento);
    color: var(--acento);
}

.modal-cerrar svg {
    width: 14px;
    height: 14px;
}

/* ---------------------------------------------------------------------------
   ALTA DE CLASIFICACIÓN

   Comparte un único fragmento entre las cuatro clasificaciones de producto
   -categoría, marca, modelo y tamaño-, porque son estructuralmente idénticas:
   una lista de nombres únicos que se agregan y se quitan.

   El botón va a la izquierda del campo, siguiendo el diseño acordado. Es una
   disposición menos habitual que a la derecha, pero funciona bien acá porque
   el botón es cuadrado y actúa como un icono que precede al campo.
   --------------------------------------------------------------------------- */
.clasificacion-alta {
    display: flex;
    flex-wrap: wrap;
    gap: 9px;
    margin-bottom: 16px;
}

.btn-agregar-clasificacion {
    width: 38px;
    height: 38px;
    background: var(--input-bg);
    border: 1px solid var(--input-border);
    color: var(--texto-secundario);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: all 0.2s ease;
    padding: 0;
}

.btn-agregar-clasificacion:hover:not(:disabled) {
    border-color: var(--acento);
    color: var(--acento);
    background: var(--input-bg);
}

/* Estado deshabilitado: mientras el nombre no sea válido, el botón se atenúa y
   el cursor indica que no está disponible. Mostrarlo así, en lugar de
   ocultarlo, deja claro que la acción existe pero requiere completar el campo. */
.btn-agregar-clasificacion:disabled {
    opacity: 0.35;
    cursor: not-allowed;
}

.btn-agregar-clasificacion svg {
    width: 16px;
    height: 16px;
}

.clasificacion-alta input {
    flex: 1;
    min-width: 0;
    padding: 8px 12px;
    background: var(--input-bg);
    border: 1px solid var(--input-border);
    color: var(--input-texto);
    font-size: 0.78rem;
    font-family: inherit;
    transition: border-color 0.2s ease;
    box-sizing: border-box;
}

.clasificacion-alta input:hover {
    border-color: var(--input-border-hover);
}

.clasificacion-alta input:focus {
    outline: none;
    border-color: var(--acento);
}

.clasificacion-alta input::placeholder {
    color: var(--input-placeholder);
}

/* ---- Categoría padre (solo en el alta de categorías) ----
   Va en un renglón propio, debajo del nombre, con la etiqueta en mayúsculas
   chicas como las de los filtros. Las reglas cuelgan de .clasificacion-padre
   para no cruzarse con las del campo del nombre (que es un input). */
.clasificacion-alta .clasificacion-padre {
    flex: 1 1 100%;
    display: flex;
    flex-direction: column;
    gap: 5px;
    font-size: 0.52rem;
    font-weight: 500;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    color: var(--texto-secundario);
}

.clasificacion-alta .clasificacion-padre select {
    width: 100%;
    padding: 8px 12px;
    background: var(--input-bg);
    border: 1px solid var(--input-border);
    color: var(--input-texto);
    font-size: 0.78rem;
    font-family: inherit;
    letter-spacing: normal;
    text-transform: none;
    transition: border-color 0.2s ease;
    box-sizing: border-box;
}

.clasificacion-alta .clasificacion-padre select:hover {
    border-color: var(--input-border-hover);
}

.clasificacion-alta .clasificacion-padre select:focus {
    outline: none;
    border-color: var(--acento);
}

/* Las opciones no heredan el fondo del desplegable: se les da color plano. */
.clasificacion-alta .clasificacion-padre select option {
    background-color: #0f1522;
    color: var(--input-texto);
}

[data-tema="claro"] .clasificacion-alta .clasificacion-padre select option {
    background-color: #ffffff;
}

.clasificacion-error {
    margin-bottom: 14px;
}

/* ---------------------------------------------------------------------------
   LISTADO

   Alto máximo con scroll propio: con veinte registros el modal crecería más
   allá de la ventana y el botón de cierre quedaría fuera de alcance.
   --------------------------------------------------------------------------- */
.clasificacion-lista {
    list-style: none;
    padding: 0;
    margin: 0;
    max-height: 280px;
    overflow-y: auto;
    border: 1px solid var(--input-border);
}

.clasificacion-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 12px;
    border-bottom: 1px solid var(--linea);
    transition: background 0.15s ease;
}

.clasificacion-item:last-child {
    border-bottom: none;
}

.clasificacion-item:hover {
    background: var(--input-bg);
}

.clasificacion-nombre {
    font-size: 0.78rem;
    font-weight: 500;
    color: var(--input-texto);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* El formulario de baja no debe introducir espaciado propio: el botón que
   contiene ya trae el suyo. */
.clasificacion-item form {
    margin: 0;
    padding: 0;
    display: flex;
    flex-shrink: 0;
}

.btn-eliminar-clasificacion {
    width: 26px;
    height: 26px;
    background: transparent;
    border: 1px solid var(--accion-eliminar-borde);
    color: var(--accion-eliminar);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s ease;
    padding: 0;
}

.btn-eliminar-clasificacion:hover {
    background: var(--accion-eliminar-fondo);
    border-color: var(--accion-eliminar);
}

.btn-eliminar-clasificacion svg {
    width: 13px;
    height: 13px;
}

.clasificacion-vacio {
    padding: 24px 12px;
    text-align: center;
    font-size: 0.72rem;
    color: var(--texto-secundario);
}

/* ---------------------------------------------------------------------------
   AVISO DE CLASIFICACIÓN EN USO
   --------------------------------------------------------------------------- */
.clasificacion-bloqueo {
    text-align: center;
}

.clasificacion-bloqueo .modal-advertencia {
    font-size: 0.75rem;
    margin-bottom: 16px;
}

/* Listado de productos que bloquean la eliminación. Tiene scroll propio porque
   pueden ser muchos: mostrar los primeros y dejar el resto accesible es más
   útil que un modal que se extiende fuera de la pantalla. */
.clasificacion-productos {
    list-style: none;
    padding: 0;
    margin: 0 0 20px;
    max-height: 190px;
    overflow-y: auto;
    border: 1px solid var(--input-border);
    text-align: left;
}

.clasificacion-productos li {
    display: flex;
    align-items: baseline;
    gap: 7px;
    padding: 9px 12px;
    border-bottom: 1px solid var(--linea);
    font-size: 0.73rem;
}

.clasificacion-productos li:last-child {
    border-bottom: none;
}

.clasificacion-productos .producto-nombre {
    font-weight: 500;
    color: var(--input-texto);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.clasificacion-productos .producto-separador {
    color: var(--texto-secundario);
    flex-shrink: 0;
}

/* El código va monoespaciado para que todos tengan el mismo ancho de carácter
   y la columna se lea alineada, igual que en la tabla del inventario. */
.clasificacion-productos .producto-codigo {
    font-family: "Consolas", "Courier New", monospace;
    font-size: 0.68rem;
    color: var(--texto-secundario);
    flex-shrink: 0;
    margin-left: auto;
}

.clasificacion-bloqueo .modal-acciones {
    justify-content: center;
}

/* ---------------------------------------------------------------------------
   CAMPOS DE ANCHO COMPLETO

   El modal de la fórmula usa campos angostos porque son porcentajes de dos o
   tres dígitos. Los de producto llevan nombres y marcas, así que necesitan
   todo el ancho disponible.

   La etiqueta conserva un ancho fijo para que todos los campos queden
   alineados en la misma vertical, sin importar cuánto mida cada texto.
   --------------------------------------------------------------------------- */
.modal-campo-ancho {
    align-items: center;
}

.modal-campo-ancho label {
    min-width: 88px;
    flex-shrink: 0;
}

.modal-campo-ancho input,
.modal-campo-ancho select {
    flex: 1;
    width: auto;
    min-width: 0;
    text-align: left;
    padding: 8px 11px;
    background: var(--input-bg);
    border: 1px solid var(--input-border);
    color: var(--input-texto);
    font-size: 0.78rem;
    font-family: inherit;
    transition: border-color 0.2s ease;
    box-sizing: border-box;
}

.modal-campo-ancho input:hover,
.modal-campo-ancho select:hover {
    border-color: var(--input-border-hover);
}

.modal-campo-ancho input:focus,
.modal-campo-ancho select:focus {
    outline: none;
    border-color: var(--acento);
}

.modal-campo-ancho input::placeholder {
    color: var(--input-placeholder);
}

/* Los <option> se renderizan fuera del flujo del documento y no heredan los
   colores del <select>. Sin declararlos, el navegador usa fondo blanco
   mientras el texto puede quedar en blanco, volviéndolos ilegibles.

   El fondo va en color literal porque las variables de input son degradados, y
   los <option> no los soportan: necesitan un color plano. */
.modal-campo-ancho select option {
    background-color: #0f1522;
    color: var(--input-texto);
}

[data-tema="claro"] .modal-campo-ancho select option {
    background-color: #ffffff;
}

/* ---------------------------------------------------------------------------
   DETALLE DE LA CONFIRMACIÓN

   Segunda línea del diálogo, usada por ejemplo para avisar que al dar de baja
   un paquete también se dará de baja su fraccionado. Va más chica y atenuada
   que el mensaje principal: es información complementaria, no la pregunta.
   --------------------------------------------------------------------------- */
.modal-detalle {
    font-size: 0.72rem;
    line-height: 1.5;
    color: var(--texto-secundario);
    text-align: center;
    margin: -8px 0 18px;
    padding: 10px 12px;
    background: var(--input-bg);
    border-left: 2px solid var(--acento);
}

/* ---------------------------------------------------------------------------
   LISTA DEBAJO DEL DETALLE

   Renglones que acompañan al detalle, por ejemplo los usuarios que pierden un
   rol al darlo de baja. Tiene una altura máxima y se desplaza, para que los
   botones queden siempre a la vista.
   --------------------------------------------------------------------------- */
.modal-lista {
    list-style: none;
    max-height: 200px;
    overflow-y: auto;
    margin: -8px 0 18px;
    padding: 8px 12px;
    font-size: 0.72rem;
    line-height: 1.6;
    color: var(--texto-secundario);
    border: 1px solid var(--input-border);
}

/* ---------------------------------------------------------------------------
   NOTA ACLARATORIA

   Se usa en el modal del fraccionado para explicar por qué faltan campos que
   el usuario podría estar buscando.
   --------------------------------------------------------------------------- */
.modal-nota {
    font-size: 0.68rem;
    line-height: 1.5;
    color: var(--texto-secundario);
    margin: 4px 0 18px;
    padding: 10px 12px;
    background: var(--input-bg);
    border-left: 2px solid var(--input-border-hover);
}

.modal-nota strong {
    color: var(--acento);
    font-weight: 500;
}

/* ---------------------------------------------------------------------------
   MODAL CON SCROLL

   El formulario de alta tiene doce campos y puede exceder el alto de la ventana
   en pantallas chicas. El scroll va en la caja y no en el fondo para que la
   superposición difuminada permanezca fija mientras el contenido se desplaza.
   --------------------------------------------------------------------------- */
.modal-caja {
    max-height: calc(100vh - 3rem);
    overflow-y: auto;
}

/* ---------------------------------------------------------------------------
   RESUMEN DEL PAQUETE DE ORIGEN

   Recuadro con el paquete que se va a fraccionar, sus paquetes disponibles y
   el contenido de cada paquete. Las cantidades van en el color de acento y el
   nombre del producto resaltado, para leer los datos de un vistazo.
   --------------------------------------------------------------------------- */
.fraccionar-resumen {
    font-size: 0.8rem;
    line-height: 1.7;
    color: var(--texto-secundario);
    padding: 16px 20px;
    margin: 0 0 22px;
    background: var(--input-bg);
    border: 1px solid var(--input-border);
    border-left: 3px solid var(--acento);
}

.fraccionar-resumen strong {
    color: var(--acento);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------------
   CUENTA DE LO QUE SE VA A FRACCIONAR

   Debajo del campo: cuántos paquetes se fraccionan y cuánto se suma al
   fraccionado. Se actualiza mientras el usuario escribe. El borde punteado la
   distingue del resumen (dato fijo) y el verde marca lo que va a cambiar.
   --------------------------------------------------------------------------- */
.fraccionar-previa {
    font-size: 0.8rem;
    line-height: 1.7;
    color: var(--texto-secundario);
    padding: 14px 20px;
    margin: 6px 0 22px;
    border: 1px dashed var(--input-border-hover);
}

.fraccionar-previa strong {
    color: var(--exito-texto);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* El nombre de los productos, en el color del texto principal en los dos bloques */
.fraccionar-resumen strong.nombre,
.fraccionar-previa strong.nombre {
    color: var(--input-texto);
}

/* ---------------------------------------------------------------------------
   BOTÓN DE FRACCIONAR EN LA TABLA

   Va en las filas de los empaquetados fraccionables, después del de baja.
   Lleva el color de acento del sistema y no el azul de editar
   ni en el rojo de eliminar: no es ninguna de esas dos cosas, sino una
   operación sobre el stock.
   --------------------------------------------------------------------------- */
.btn-icono.fraccionar {
    border-color: var(--accion-fraccionar-borde);
    color: var(--accion-fraccionar);
}

.btn-icono.fraccionar:hover {
    background: var(--accion-fraccionar-fondo);
    border-color: var(--accion-fraccionar);
}

/* ---------------------------------------------------------------------------
   CAJA ANCHA

   El formulario de alta tiene trece campos. Apilados en una sola columna
   obligan a hacer scroll dentro del modal, y los botones de confirmación
   quedan fuera de vista mientras se completa.
   --------------------------------------------------------------------------- */
.modal-caja-ancha {
    max-width: 760px;
}

/* ---------------------------------------------------------------------------
   COLUMNAS

   La división no es arbitraria: a la izquierda va la identificación del
   producto —qué es y cómo se lo reconoce— y a la derecha los datos operativos
   —cuánto hay, cuánto cuesta y cómo se maneja.

   Agrupar por afinidad y no por orden de carga permite completar una columna
   entera sin cambiar de contexto mental.
   --------------------------------------------------------------------------- */
.formulario-columnas {
    display: flex;
    gap: 26px;
    margin-bottom: 18px;
}

.formulario-columna {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 13px;
}

/* Los campos ya no necesitan margen propio: el gap de la columna lo resuelve
   de forma uniforme. */
.formulario-columna .modal-campo {
    margin-bottom: 0;
}

/* Con dos columnas hay menos ancho disponible, así que las etiquetas se
   acortan para que el campo conserve espacio suficiente. */
.formulario-columna .modal-campo-ancho label {
    min-width: 82px;
    font-size: 0.72rem;
}

/* ---------------------------------------------------------------------------
   CASILLAS CON ACLARACIÓN

   El texto al lado de la casilla explica qué implica marcarla. Sin él, la
   etiqueta sola —"Expira", "Fraccionable"— deja al usuario adivinando si se
   refiere al producto o al paquete.
   --------------------------------------------------------------------------- */
.campo-casilla {
    display: flex;
    align-items: center;
    gap: 9px;
    flex: 1;
    min-width: 0;
}

.modal-checkbox {
    width: 17px;
    height: 17px;
    flex: none;
    accent-color: var(--acento);
    cursor: pointer;
    margin: 0;
}

/* ---------------------------------------------------------------------------
   CÓDIGO DEL FRACCIONADO

   Se bloquea mientras la casilla de fraccionable está sin marcar: sin ella no
   se va a crear ningún producto derivado al que asignar ese código.

   Se muestra atenuado en lugar de ocultarse, para que el formulario no cambie
   de alto al marcar la casilla, desplazando los botones justo cuando el
   usuario está por pulsarlos.
   --------------------------------------------------------------------------- */
.formulario-columna input:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

/* ---------------------------------------------------------------------------
   RESPONSIVE (RNF-08)

   Por debajo de 700px las columnas se apilan: a 760px de ancho, dos columnas
   no entran en una pantalla angosta.
   --------------------------------------------------------------------------- */
@media (max-width: 700px) {
    .formulario-columnas {
        flex-direction: column;
        gap: 13px;
    }
}

.formulario-columna .modal-campo-ancho label {
    display: flex;
    align-items: center;
}

/* ---------------------------------------------------------------------------
   INDICADOR DE AYUDA

   Marca los campos cuyo significado no es evidente por su nombre. Al pasar el
   mouse, tooltip.js muestra la aclaración.

   La regla vive acá y no en descuentos.css porque los modales la necesitan
   igual, y esa hoja no se carga en las pantallas de inventario.
   --------------------------------------------------------------------------- */
.ayuda {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 14px;
    height: 14px;
    margin-left: 6px;
    border: 1px solid var(--input-border-hover);
    border-radius: 50%;
    font-size: 0.55rem;
    color: var(--texto-secundario);
    cursor: help;
    flex-shrink: 0;
    transition: all 0.2s ease;
    /* La etiqueta puede venir en mayúsculas o con espaciado propio: el signo
       no debe heredarlo. */
    text-transform: none;
    letter-spacing: 0;
}

.ayuda:hover {
    border-color: var(--acento);
    color: var(--acento);
}

/* ---------------------------------------------------------------------------
   GLOBO DEL TOOLTIP

   Se dibuja como un único elemento reutilizable al final del body, y no como
   pseudo-elemento de cada indicador.

   La razón es el recorte: la tabla lleva overflow para su scroll horizontal, y
   eso corta cualquier elemento que se dibuje fuera de sus límites. Un tooltip
   posicionado dentro de la celda aparecería mutilado. Con position: fixed y un
   solo elemento en el body, el globo queda por encima de todo.
   --------------------------------------------------------------------------- */
.tooltip-globo {
    position: fixed;
    z-index: 9500;
    max-width: 300px;
    padding: 11px 13px;

    background: var(--card-bg-solido);
    border: 1px solid var(--acento);
    box-shadow: var(--card-sombra);

    font-size: 0.7rem;
    line-height: 1.5;
    color: var(--input-texto);
    text-align: left;
    text-transform: none;
    letter-spacing: 0;
    font-weight: 400;

    /* Oculto por defecto. visibility evita que intercepte el mouse mientras no
       se ve, algo que opacity por sí sola no impide. */
    opacity: 0;
    visibility: hidden;
    transform: translateY(4px);
    transition: opacity 0.15s ease, transform 0.15s ease, visibility 0.15s ease;
    pointer-events: none;
}

.tooltip-globo.visible {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

/* Franja de acento superior, igual que en los modales y la sidebar. */
.tooltip-globo::before {
    content: "";
    position: absolute;
    top: -1px;
    left: -1px;
    right: -1px;
    height: 2px;
    background: linear-gradient(
        90deg,
        transparent 0%,
        var(--acento-oscuro) 20%,
        var(--acento) 50%,
        var(--acento-oscuro) 80%,
        transparent 100%
    );
}

/* ---------------------------------------------------------------------------
   BLOQUE DEL SELECTOR

   Agrupa el buscador, sus resultados y la selección en un recuadro propio:
   son tres piezas de una misma decisión, y separarlas visualmente del resto
   del formulario deja claro que funcionan juntas.
   --------------------------------------------------------------------------- */
.selector-producto {
    padding: 14px;
    margin: 16px 0;
    border: 1px solid var(--input-border);
    background: rgba(0, 0, 0, 0.12);
}

.selector-producto .modal-campo {
    margin-bottom: 0;
}

/* ---------------------------------------------------------------------------
   BUSCADOR
   --------------------------------------------------------------------------- */
.buscador-envoltorio {
    position: relative;
    flex: 1;
    min-width: 0;
}

.buscador-icono {
    position: absolute;
    left: 10px;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    color: var(--texto-secundario);
    pointer-events: none;
}

.buscador-icono svg {
    width: 13px;
    height: 13px;
}

.buscador-envoltorio input {
    width: 100%;
    /* El padding izquierdo deja lugar para la lupa. */
    padding: 8px 11px 8px 31px;
    background: var(--input-bg);
    border: 1px solid var(--input-border);
    color: var(--input-texto);
    font-size: 0.76rem;
    font-family: inherit;
    transition: all 0.2s ease;
    box-sizing: border-box;
}

.buscador-envoltorio input:focus {
    outline: none;
    border-color: var(--acento);
}

.buscador-envoltorio input::placeholder {
    color: var(--input-placeholder);
}

/* Con un producto ya elegido el buscador se bloquea: un descuento normal recae
   sobre un único producto, así que permitir elegir otro sin quitar el anterior
   generaría confusión sobre cuál quedó asignado. */
.buscador-envoltorio input:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

/* ---------------------------------------------------------------------------
   RESULTADOS

   A diferencia de otros buscadores del sistema, esta lista va en el flujo del
   documento y no superpuesta: el bloque de selección está justo abajo, y un
   desplegable flotante lo taparía en el momento en que el usuario necesita
   verlo.
   --------------------------------------------------------------------------- */
.resultados-producto {
    margin-top: 10px;
    display: flex;
    flex-direction: column;
    gap: 5px;
}

/* Vacío no debe ocupar espacio: se colapsa solo cuando no tiene contenido. */
.resultados-producto:empty {
    display: none;
}

.resultado-item,
.seleccionado-item {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 8px 10px;
    background: var(--input-bg);
    border: 1px solid var(--input-border);
    font-size: 0.7rem;
    transition: border-color 0.2s ease;
}

.resultado-item:hover {
    border-color: var(--input-border-hover);
}

.item-nombre {
    font-weight: 500;
    color: var(--input-texto);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.item-separador {
    color: var(--texto-secundario);
    flex-shrink: 0;
}

/* El código va monoespaciado para que todos tengan el mismo ancho de carácter,
   igual que en la tabla del inventario. */
.item-codigo {
    font-family: "Consolas", "Courier New", monospace;
    font-size: 0.64rem;
    color: var(--texto-secundario);
    flex-shrink: 0;
}

.item-precio {
    color: var(--acento);
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
}

.resultado-vacio {
    padding: 12px 10px;
    font-size: 0.68rem;
    color: var(--texto-secundario);
    text-align: center;
}

/* ---------------------------------------------------------------------------
   BOTONES DE ACCIÓN DE CADA ÍTEM
   --------------------------------------------------------------------------- */
.btn-elegir,
.btn-quitar {
    width: 24px;
    height: 24px;
    background: transparent;
    border: 1px solid transparent;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    padding: 0;
    margin-left: 4px;
    transition: all 0.2s ease;
}

.btn-elegir {
    border-color: var(--input-border-hover);
    color: var(--texto-secundario);
}

.btn-elegir:hover {
    border-color: var(--acento);
    color: var(--acento);
}

.btn-quitar {
    border-color: var(--accion-eliminar-borde);
    color: var(--accion-eliminar);
}

.btn-quitar:hover {
    background: var(--accion-eliminar-fondo);
    border-color: var(--accion-eliminar);
}

.btn-elegir svg,
.btn-quitar svg {
    width: 12px;
    height: 12px;
}

/* ---------------------------------------------------------------------------
   PRODUCTO SELECCIONADO
   --------------------------------------------------------------------------- */
.seleccionado-bloque {
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid var(--linea);
}

.seleccionado-titulo {
    display: block;
    font-size: 0.55rem;
    font-weight: 500;
    letter-spacing: 1.1px;
    text-transform: uppercase;
    color: var(--texto-secundario);
    margin-bottom: 8px;
}

/* El seleccionado lleva la barra de acento que lo distingue de los resultados
   de búsqueda: es una decisión ya tomada, no una opción disponible. */
.seleccionado-item {
    border-left: 2px solid var(--acento);
}

.seleccionado-vacio {
    font-size: 0.68rem;
    color: var(--texto-secundario);
    font-style: italic;
    margin: 0;
    padding: 8px 10px;
}

/* ---------------------------------------------------------------------------
   RESUMEN DE LA CONFIRMACIÓN

   Muestra el efecto concreto del descuento antes de crearlo. Ver el precio
   final es lo que permite advertir un porcentaje mal tipeado antes de que el
   descuento entre en vigencia, y no después de la primera venta.
   --------------------------------------------------------------------------- */
.resumen-descuento {
    margin: 0 0 20px;
    border: 1px solid var(--input-border);
    background: var(--input-bg);
}

.resumen-linea {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 14px;
    padding: 9px 13px;
    border-bottom: 1px solid var(--linea);
    font-size: 0.72rem;
}

.resumen-linea:last-child {
    border-bottom: none;
}

.resumen-etiqueta {
    color: var(--texto-secundario);
    flex-shrink: 0;
}

.resumen-valor {
    color: var(--input-texto);
    text-align: right;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.resumen-valor.acento {
    color: var(--acento);
    font-weight: 500;
}

.resumen-valor.tachado {
    color: var(--texto-secundario);
    text-decoration: line-through;
    text-decoration-color: var(--input-border-hover);
}

.resumen-final {
    background: rgba(0, 0, 0, 0.15);
    border-left: 2px solid var(--acento);
    font-size: 0.78rem;
}

/* ---------------------------------------------------------------------------
   MODAL DE ALTA DE DESCUENTO

   Más ancho que un diálogo común porque los resultados de búsqueda llevan
   nombre, código y precio en una sola línea. A 380px los nombres se cortaban
   con puntos suspensivos casi siempre, dejando al usuario eligiendo entre
   "Arandelas planas ..." y "Arandelas plana...".
   --------------------------------------------------------------------------- */
.modal-caja-descuento {
    max-width: 560px;
}

/* Con más ancho disponible, los resultados pueden mostrar el nombre completo.
   El mínimo evita que un nombre corto deje el código y el precio pegados a la
   izquierda, desalineados respecto del resto de la lista. */
.modal-caja-descuento .item-nombre {
    min-width: 180px;
}

/* ---------------------------------------------------------------------------
   CAJA

   Más ancha que un diálogo común: la tabla lleva cuatro columnas, dos de ellas
   con importes que no deben romperse en varias líneas.
   --------------------------------------------------------------------------- */
.modal-caja-productos {
    max-width: 560px;
}

/* ---------------------------------------------------------------------------
   ENCABEZADO

   El porcentaje va a la izquierda y el cierre a la derecha. No hay título
   visible: el contenido se explica solo, y agregarlo restaría espacio a la
   tabla, que es lo que el usuario vino a ver.

   El título existe igual en el marcado, oculto, para que un lector de pantalla
   anuncie de qué descuento se trata.
   --------------------------------------------------------------------------- */
.productos-encabezado {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    margin-bottom: 16px;
}

/* ---- Porcentaje ----
   Se muestra como campo deshabilitado y no como texto plano: conserva la forma
   de un campo, lo que deja claro que es el mismo dato que se edita en otro
   lado, pero su estado atenuado indica que acá no se toca. */
.porcentaje-vista {
    display: flex;
    align-items: center;
    gap: 11px;
    flex: 1;
    padding: 11px 14px;
    border: 1px solid var(--input-border);
    background: rgba(0, 0, 0, 0.12);
}

.porcentaje-etiqueta {
    font-size: 0.72rem;
    font-weight: 500;
    color: var(--input-texto);
    flex-shrink: 0;
}

.porcentaje-campo {
    width: 78px;
    padding: 7px 10px;
    background: var(--input-bg);
    border: 1px solid var(--input-border);
    color: var(--acento);
    font-family: "Consolas", "Courier New", monospace;
    font-size: 0.78rem;
    font-weight: 500;
    text-align: center;
    box-sizing: border-box;
    /* Deshabilitado pero legible: el navegador lo atenúa por defecto hasta
       volverlo difícil de leer, y acá el valor es justamente lo que interesa. */
    opacity: 1;
    cursor: default;
}

.porcentaje-simbolo {
    font-size: 0.78rem;
    color: var(--texto-secundario);
}

/* ---------------------------------------------------------------------------
   TABLA

   Alto fijo con scroll propio. Se prefiere a dejarla crecer porque la cantidad
   de productos varía mucho entre descuentos: sin un alto estable, el modal
   saltaría de tamaño al pasar de uno con tres productos a otro con veinte.
   --------------------------------------------------------------------------- */
.productos-tabla {
    border: 1px solid var(--input-border);
    max-height: 320px;
    min-height: 220px;
    overflow-y: auto;
}

.tabla-productos-desc {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.72rem;
}

.tabla-productos-desc thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--card-bg-solido);
    padding: 9px 12px;
    font-size: 0.55rem;
    font-weight: 500;
    letter-spacing: 1.1px;
    text-transform: uppercase;
    color: var(--texto-secundario);
    text-align: left;
    border-bottom: 1px solid var(--linea);
}

.tabla-productos-desc th.num,
.tabla-productos-desc td.num {
    text-align: right;
}

.tabla-productos-desc tbody td {
    padding: 10px 12px;
    border-bottom: 1px solid var(--linea);
}

.tabla-productos-desc tbody tr:last-child td {
    border-bottom: none;
}

.tabla-productos-desc .col-nombre {
    color: var(--input-texto);
    font-weight: 500;
    max-width: 200px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* El código va monoespaciado para que todos tengan el mismo ancho de carácter
   y la columna se lea alineada, igual que en la tabla del inventario. */
.tabla-productos-desc .col-codigo {
    font-family: "Consolas", "Courier New", monospace;
    font-size: 0.66rem;
    color: var(--texto-secundario);
    white-space: nowrap;
}

.tabla-productos-desc .precio-original {
    color: var(--texto-secundario);
    text-decoration: line-through;
    /* El tachado sobre un color atenuado puede volverse ilegible: se aclara un
       poco la línea para que el número siga leyéndose debajo. */
    text-decoration-color: var(--input-border-hover);
    font-variant-numeric: tabular-nums;
}

.tabla-productos-desc .precio-rebajado {
    color: var(--acento);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------------
   ESTADO VACÍO
   --------------------------------------------------------------------------- */
.productos-vacio {
    padding: 40px 20px;
    text-align: center;
    color: var(--texto-secundario);
}

.productos-vacio svg {
    width: 30px;
    height: 30px;
    opacity: 0.3;
    margin-bottom: 10px;
}

.productos-vacio p {
    font-size: 0.72rem;
    margin: 0;
}

.productos-vacio .sugerencia {
    font-size: 0.65rem;
    opacity: 0.7;
    margin-top: 5px;
}

/* ---------------------------------------------------------------------------
   BOTÓN DE AGREGAR

   Arranca deshabilitado y solo se habilita cuando hay una sugerencia elegida:
   sin eso, pulsarlo no haría nada y el usuario no sabría por qué.
   --------------------------------------------------------------------------- */
.btn-agregar-producto {
    width: 34px;
    height: 34px;
    background: var(--input-bg);
    border: 1px solid var(--input-border);
    color: var(--texto-secundario);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    padding: 0;
    margin-left: 8px;
    transition: all 0.2s ease;
}

.btn-agregar-producto:hover:not(:disabled) {
    border-color: var(--acento);
    color: var(--acento);
}

/* Se muestra atenuado en lugar de ocultarse: así el usuario ve de antemano que
   la acción existe pero requiere elegir un producto primero. */
.btn-agregar-producto:disabled {
    opacity: 0.3;
    cursor: not-allowed;
}

.btn-agregar-producto svg {
    width: 15px;
    height: 15px;
}

/* ---------------------------------------------------------------------------
   SUGERENCIAS

   Van superpuestas y no en el flujo del documento: debajo está la lista de
   productos ya agregados, y empujarla hacia abajo en cada tecla escrita haría
   que el modal cambiara de alto constantemente.
   --------------------------------------------------------------------------- */
.sugerencias-producto {
    position: absolute;
    top: calc(100% + 3px);
    left: 0;
    right: 0;
    z-index: 30;
    display: flex;
    flex-direction: column;
    max-height: 180px;
    overflow-y: auto;
    box-shadow: var(--card-sombra);
}

/* Vacío no debe ocupar espacio ni mostrar borde: se colapsa solo cuando no
   tiene contenido. */
.sugerencias-producto:empty {
    display: none;
}

.sugerencia-item {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    padding: 8px 11px;
    background: var(--card-bg-solido);
    border: 1px solid var(--input-border);
    border-bottom: none;
    cursor: pointer;
    text-align: left;
    font-family: inherit;
    font-size: 0.7rem;
    transition: background 0.15s ease;
}

.sugerencia-item:last-child {
    border-bottom: 1px solid var(--input-border);
}

.sugerencia-item:hover {
    background: var(--input-bg);
}

.sugerencia-vacia {
    padding: 12px 11px;
    background: var(--card-bg-solido);
    border: 1px solid var(--input-border);
    font-size: 0.68rem;
    color: var(--texto-secundario);
    text-align: center;
}

/* ---------------------------------------------------------------------------
   LISTA DE PRODUCTOS AGREGADOS

   Alto fijo con scroll propio. Sin él, agregar quince productos empujaría los
   botones de confirmación fuera de la pantalla.
   --------------------------------------------------------------------------- */
.elegidos-lista {
    margin-top: 12px;
    max-height: 200px;
    min-height: 90px;
    overflow-y: auto;
    border: 1px solid var(--input-border);
    background: var(--input-bg);
    display: flex;
    flex-direction: column;
}

.elegido-item {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 9px 11px;
    border-bottom: 1px solid var(--linea);
    font-size: 0.7rem;
    flex-shrink: 0;
}

.elegido-item:last-child {
    border-bottom: none;
}

.elegido-item .item-nombre {
    font-weight: 500;
    color: var(--input-texto);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* margin-left: auto empuja el botón hacia la derecha, manteniendo la columna
   alineada aunque los nombres varíen de largo. */
.elegido-item .btn-quitar {
    margin-left: auto;
}

.elegidos-vacio {
    margin: auto;
    padding: 16px;
    font-size: 0.68rem;
    color: var(--texto-secundario);
    font-style: italic;
    text-align: center;
}

/* ---------------------------------------------------------------------------
   ETIQUETA DE TIPO DE PRODUCTO

   Distingue el paquete cerrado de las unidades sueltas en los resultados de
   búsqueda. Usa los mismos colores que las etiquetas del inventario, para que
   el usuario no tenga que aprender dos códigos distintos.
   --------------------------------------------------------------------------- */
.tipo-etiqueta {
    font-size: 0.52rem;
    letter-spacing: 0.7px;
    text-transform: uppercase;
    padding: 2px 6px;
    border: 1px solid;
    flex-shrink: 0;
    /* margin-left: auto empuja este y todo lo que sigue hacia la derecha,
       manteniendo las columnas alineadas aunque los nombres varíen de largo. */
    margin-left: auto;
}

.tipo-empaquetado {
    color: var(--tag-empaquetado);
    border-color: var(--tag-empaquetado);
}

.tipo-fraccionado {
    color: var(--tag-fraccionado);
    border-color: var(--tag-fraccionado);
}

/* ---------------------------------------------------------------------------
   CAJA

   Es el modal más grande del sistema: contiene la carga por un lado y el
   comprobante por el otro. A menos ancho, la tabla de productos quedaría con
   siete columnas apretadas y los nombres cortados casi siempre.
   --------------------------------------------------------------------------- */
.modal-caja-venta-registro {
    max-width: 1000px;
}

/* ---------------------------------------------------------------------------
   COLUMNAS

   A la izquierda los datos de la operación —qué se vende, cómo se paga—; a la
   derecha el comprobante que se va armando.

   Esa división sigue el orden real del mostrador: el cajero carga por un lado
   y verifica por el otro, sin cambiar de contexto.
   --------------------------------------------------------------------------- */
.venta-registro-columnas {
    display: flex;
    align-items: stretch;
}

.venta-registro-carga {
    /* Ancho fijo y ajustado: los campos de carga son cortos y estables,
       mientras que el comprobante crece con la cantidad de productos. Darle más
       espacio del necesario deja la tabla de siete columnas con scroll
       horizontal, que es donde el cajero verifica lo que está por cobrar. */
    flex: 0 0 220px;
    padding: 20px 18px;
    display: flex;
    flex-direction: column;
    gap: 14px;
    /* La línea divisoria es lo que une visualmente las dos columnas: sin ella
       parecerían dos tarjetas sueltas. */
    border-right: 1px solid var(--linea);
}

.venta-registro-detalle {
    flex: 1;
    min-width: 0;
    padding: 22px 24px;
    display: flex;
    flex-direction: column;
}

/* ---------------------------------------------------------------------------
   CAMPOS APILADOS

   El método de pago y los comentarios llevan la etiqueta encima y no al lado:
   uno es un desplegable largo y el otro un área de texto de varias líneas, y
   con la etiqueta en línea quedarían desalineados entre sí.
   --------------------------------------------------------------------------- */
.venta-campo-bloque {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.venta-campo-bloque label {
    font-size: 0.72rem;
    color: var(--input-texto);
}

.venta-campo-bloque select,
.venta-campo-bloque textarea {
    width: 100%;
    padding: 8px 11px;
    background: var(--input-bg);
    border: 1px solid var(--input-border);
    color: var(--input-texto);
    font-size: 0.78rem;
    font-family: inherit;
    transition: border-color 0.2s ease;
    box-sizing: border-box;
}

.venta-campo-bloque select:hover,
.venta-campo-bloque textarea:hover {
    border-color: var(--input-border-hover);
}

.venta-campo-bloque select:focus,
.venta-campo-bloque textarea:focus {
    outline: none;
    border-color: var(--acento);
}

.venta-campo-bloque textarea {
    resize: vertical;
    line-height: 1.5;
    /* Un mínimo evita que el usuario lo achique tanto que deje de verse el
       texto que escribió. */
    min-height: 90px;
}

.venta-campo-bloque textarea::placeholder {
    color: var(--input-placeholder);
}

/* Los <option> se renderizan fuera del flujo del documento y no heredan los
   colores del <select>. Sin declararlos, el navegador usa fondo blanco
   mientras el texto puede quedar en blanco, volviéndolos ilegibles. */
.venta-campo-bloque select option {
    background-color: #0f1522;
    color: var(--input-texto);
}

[data-tema="claro"] .venta-campo-bloque select option {
    background-color: #ffffff;
}

/* ---------------------------------------------------------------------------
   ETIQUETAS DE LA COLUMNA DE CARGA

   Con menos ancho disponible, la etiqueta se achica para que los campos
   conserven espacio suficiente.
   --------------------------------------------------------------------------- */
.venta-registro-carga .modal-campo-ancho label {
    min-width: 70px;
    font-size: 0.68rem;
}

/* ---------------------------------------------------------------------------
   TABLA DE PRODUCTOS

   Alto fijo con scroll propio. Sin él, una venta de veinte productos empujaría
   los totales y los botones fuera de la pantalla, que es justo lo que el
   cajero necesita ver antes de confirmar.
   --------------------------------------------------------------------------- */
.venta-items-envoltorio {
    max-height: 240px;
    min-height: 150px;
    overflow-y: auto;
}

.tabla-venta-items {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.7rem;
}

.tabla-venta-items thead th {
    /* Encabezados fijos al hacer scroll: con quince productos cargados, saber
       qué columna es cuál sin volver arriba. */
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--card-bg-solido);
    padding: 8px 9px;
    font-size: 0.53rem;
    font-weight: 500;
    letter-spacing: 1px;
    text-transform: uppercase;
    color: var(--texto-secundario);
    text-align: left;
    border-bottom: 1px solid var(--linea);
    white-space: nowrap;
}

.tabla-venta-items th.num,
.tabla-venta-items td.num {
    text-align: right;
}

.tabla-venta-items tbody td {
    padding: 9px;
    border-bottom: 1px solid var(--linea);
    color: var(--input-texto);
}

.tabla-venta-items tbody tr:last-child td {
    border-bottom: none;
}

.tabla-venta-items .col-nombre {
    max-width: 150px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tabla-venta-items .col-codigo {
    font-family: "Consolas", "Courier New", monospace;
    font-size: 0.64rem;
    color: var(--texto-secundario);
    white-space: nowrap;
}

.venta-items-vacio {
    padding: 40px 12px !important;
    text-align: center;
    font-size: 0.7rem;
    color: var(--texto-secundario);
    font-style: italic;
    border-bottom: none !important;
}

/* ---------------------------------------------------------------------------
   TOTALES

   margin-top: auto los empuja al fondo de la columna, de modo que queden
   alineados con el borde inferior aunque la lista de productos sea corta.
   --------------------------------------------------------------------------- */
.venta-registro-totales {
    margin-top: auto;
    padding-top: 16px;
    border-top: 1px solid var(--linea);
}

.venta-registro-totales .total-linea {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    padding: 6px 12px;
    font-size: 0.74rem;
    color: var(--texto-secundario);
}

.venta-registro-totales .numero {
    font-family: "Consolas", "Courier New", monospace;
    font-variant-numeric: tabular-nums;
}

/* El total es el dato que el cliente va a pagar: se destaca del resto. */
.venta-registro-totales .total-final {
    margin-top: 6px;
    padding: 12px;
    background: var(--input-bg);
    border-left: 2px solid var(--acento);
    font-size: 0.84rem;
    font-weight: 500;
    color: var(--input-texto);
}

.venta-registro-totales .total-final .numero {
    color: var(--acento);
}

.venta-registro-detalle .modal-acciones {
    margin-top: 16px;
}

/* ---------------------------------------------------------------------------
   RESPONSIVE (RNF-08)

   Por debajo de 900px las columnas se apilan: a 290px la de carga más la tabla
   de siete columnas no entran una al lado de la otra.
   --------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
   LÍNEA DE CARGA DE PRODUCTO

   Cantidad, multiplicador, código y botón en una sola fila. Se lee como una
   expresión —"3 × FIJ-0014"— que es la forma en que una venta se dicta en el
   mostrador.
   --------------------------------------------------------------------------- */
.campo-carga-item {
    gap: 7px;
}

/* La cantidad ocupa lo justo para tres dígitos: más ancho le daría un peso
   visual que no corresponde, ya que casi siempre vale 1.

   Se declara con !important porque .modal-campo-ancho input estira todos sus
   campos con flex: 1, y acá ese comportamiento es exactamente lo que no
   queremos. Es una excepción puntual a una regla general del sistema, no un
   parche para ordenar la cascada. */
.campo-carga-item .campo-cantidad {
    flex: 0 0 48px !important;
    width: 48px !important;
    min-width: 48px;
    text-align: center;
    padding-left: 4px;
    padding-right: 4px;
}

/* Las flechas del campo numérico se ocultan: a 48px de ancho ocupan casi la
   mitad del espacio y desplazan el número fuera del centro. */
.campo-carga-item .campo-cantidad::-webkit-outer-spin-button,
.campo-carga-item .campo-cantidad::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.campo-carga-item .campo-cantidad {
    -moz-appearance: textfield;
    appearance: textfield;
}

.separador-por {
    font-size: 0.78rem;
    color: var(--texto-secundario);
    flex-shrink: 0;
}

.campo-carga-item .campo-codigo {
    flex: 1;
    min-width: 0;
}

.campo-carga-item .btn-agregar-producto {
    margin-left: 0;
}

/* ---------------------------------------------------------------------------
   RESPONSIVE (RNF-08)

   Por debajo de 900px las columnas se apilan: a 250px la de carga más la tabla
   de siete columnas no entran una al lado de la otra.
   --------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .venta-registro-columnas {
        flex-direction: column;
    }

    .venta-registro-carga {
        flex: none;
        border-right: none;
        border-bottom: 1px solid var(--linea);
    }
}

/* ---------------------------------------------------------------------------
   AVISO DE CARGA

   Confirma lo que se acaba de agregar o explica por qué no se pudo. Aparece
   junto al campo de carga y no como diálogo: el cajero está escaneando en
   secuencia y un modal por cada aviso interrumpiría el ritmo.
   --------------------------------------------------------------------------- */
.venta-aviso {
    font-size: 0.65rem;
    line-height: 1.4;
    color: var(--estado-exitosa);
    margin: -6px 0 0;
    /* El alto mínimo reserva el espacio: sin él, los campos de abajo saltarían
       cada vez que aparece o desaparece un aviso. */
    min-height: 2.4em;
}

.venta-aviso.error {
    color: var(--accion-eliminar);
}

/* ---------------------------------------------------------------------------
   COLUMNA DE TIPO EN LA TABLA
   --------------------------------------------------------------------------- */
.tabla-venta-items .col-tipo {
    font-size: 0.62rem;
    color: var(--texto-secundario);
    white-space: nowrap;
}

.tabla-venta-items .vacio {
    color: var(--texto-secundario);
}

/* El botón de quitar renglón es más chico que los de las otras tablas: la fila
   ya tiene ocho columnas y no hay espacio para uno del tamaño habitual. */
.tabla-venta-items .btn-quitar {
    width: 20px;
    height: 20px;
    margin-left: 0;
}

.tabla-venta-items .btn-quitar svg {
    width: 10px;
    height: 10px;
}

/* ---------------------------------------------------------------------------
   COMPROBANTE DE LA CONFIRMACIÓN

   Los importes vuelven a mostrarse recalculados por el servidor. Es la última
   oportunidad de advertir una diferencia —por ejemplo, si otro usuario
   modificó un precio mientras tanto— antes de cobrarle al cliente.
   --------------------------------------------------------------------------- */
.confirmar-items {
    max-height: 220px;
    overflow-y: auto;
    border: 1px solid var(--input-border);
    margin-bottom: 4px;
}

.confirmar-items .tabla-venta-items thead th {
    background: var(--card-bg-solido);
}

/* ---------------------------------------------------------------------------
   CASILLA DE COBRO

   Bloquea el registro hasta que el cajero confirme que recibió el dinero.
   Registrar la venta descuenta el stock, y hacerlo antes de cobrar deja
   mercadería salida del sistema sin contrapartida en la caja.

   Va destacada con el borde de acento porque es un paso deliberado, no un
   campo más del formulario.
   --------------------------------------------------------------------------- */
.confirmar-cobro {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    margin: 16px 0;
    background: var(--input-bg);
    border-left: 2px solid var(--acento);
}

.confirmar-cobro label {
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--input-texto);
    cursor: pointer;
    user-select: none;
}

/* Cobro con Mercado Pago: en lugar de la casilla, el QR (simulado: un
   recuadro con el total) y el vencimiento de la orden. */
.cobro-qr {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 12px 14px;
    margin: 16px 0;
    background: var(--input-bg);
    border-left: 2px solid var(--acento);
}

.qr-simulado {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 160px;
    height: 160px;
    border: 2px dashed var(--input-border);
    color: var(--input-texto);
}

.qr-simulado-titulo {
    font-size: 0.75rem;
    font-weight: 500;
}

.qr-simulado-total {
    font-size: 1.1rem;
    font-weight: 600;
}

.cobro-vence,
.cobro-esperando {
    margin: 0;
    font-size: 0.75rem;
    color: var(--texto-secundario);
}

/* Stock restante en los diálogos de baja. Va en línea aparte y en color de
   acento porque es el dato que puede hacer que el usuario reconsidere. */
.modal-stock {
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--acento);
    text-align: center;
    margin: -10px 0 18px;
}

/* ---------------------------------------------------------------------------
   VENTANAS DE LOS LOTES DE UN DESCUENTO

   Van acá y no en descuentos.css porque estas ventanas también se abren sobre
   otras pantallas (la del inventario, al crear un descuento o al fraccionar),
   que no cargan esa hoja.
   --------------------------------------------------------------------------- */

/* Botones de texto para acciones que no entran en un icono: "Ver lotes" o
   "Desactivar" no tienen un símbolo evidente, y uno inventado obligaría al
   usuario a pasar el mouse para descubrir qué hace.
   Los usan también las tablas de la pantalla de descuentos. */
.btn-tabla {
    padding: 4px 10px;
    background: transparent;
    border: 1px solid var(--input-border);
    color: var(--texto-secundario);
    font-family: inherit;
    font-size: 0.55rem;
    letter-spacing: 0.8px;
    text-transform: uppercase;
    cursor: pointer;
    transition: all 0.2s ease;
    white-space: nowrap;
}

.btn-tabla:hover:not(:disabled) {
    border-color: var(--acento);
    color: var(--acento);
}

/* Un descuento ya activo no puede volver a activarse. Se muestra atenuado en
   lugar de ocultarlo, para que la columna no cambie de alto entre filas. */
.btn-tabla:disabled {
    opacity: 0.25;
    cursor: not-allowed;
}

/* Aviso de unidades por cargar, a la izquierda del botón de los lotes ("Ver
   (N)" en descuentos, "Ver lotes" en inventario). Va fuera del ancho del botón para que "Ver (N)" quede centrado y
   alineado en todas las filas, tengan aviso o no. */
.celda-lotes {
    position: relative;
    display: inline-block;
}

.aviso-lotes {
    position: absolute;
    right: 100%;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    margin-right: 6px;
    color: var(--accion-eliminar);
    cursor: help;
}

.aviso-lotes svg {
    width: 16px;
    height: 16px;
}

/* En la parte desplegable de un producto de inventario, el botón de los lotes
   va a la derecha del todo. */
.detalle-cuerpo .celda-lotes {
    margin-left: auto;
}

/* El calendario de la fecha del lote necesita más ancho que los demás campos
   de la ventana para mostrar la fecha completa y su ícono. */
.lote-nuevo input[type="date"] {
    width: 140px;
}

/* En el tema oscuro, el calendario se dibuja con colores oscuros; si no, su
   ícono queda negro sobre el fondo oscuro. */
[data-tema="oscuro"] .lote-nuevo input[type="date"] {
    color-scheme: dark;
}

/* ---------------------------------------------------------------------------
   HISTORIAL DE CAMBIOS DE UN PRODUCTO

   La tabla tiene doce columnas: la ventana es más ancha que las demás y, si
   igual no entra, la tabla se desplaza a lo ancho dentro de la ventana.
   --------------------------------------------------------------------------- */
.modal-caja-historial {
    max-width: 1100px;
}

.tabla-historial-envoltorio {
    overflow-x: auto;
    margin-bottom: 12px;
}

.tabla-historial th,
.tabla-historial td {
    white-space: nowrap;
}

.paginacion-historial {
    justify-content: center;
    align-items: center;
    margin-bottom: 12px;
}

.paginacion-historial .pagina-actual {
    font-size: 0.7rem;
    color: var(--texto-secundario);
    padding: 0 8px;
}

/* ---------------------------------------------------------------------------
   MI CUENTA

   La ventana de la cuenta propia (se abre desde el menú, en cualquier
   pantalla: por eso sus reglas están acá). A la izquierda, las pestañas; a la derecha,
   el panel de la pestaña abierta. En el de "Mi cuenta", la cabecera (el
   círculo con el ícono, el nombre y el botón de Google, con la línea dorada
   debajo), los datos en dos columnas, cada uno en un recuadro con el borde
   izquierdo dorado, y los roles, uno por fila.
   --------------------------------------------------------------------------- */
.mi-cuenta-cuerpo {
    display: grid;
    grid-template-columns: 170px 1fr;
    gap: 24px;
}

.mi-cuenta-pestanas {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding-right: 18px;
    border-right: 1px solid var(--input-border);
}

.mi-cuenta-pestana {
    padding: 10px 14px;
    background: transparent;
    border: 1px solid var(--input-border);
    color: var(--texto-secundario);
    font-family: inherit;
    font-size: 0.7rem;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    text-align: left;
    cursor: pointer;
    transition: all 0.2s ease;
}

.mi-cuenta-pestana:hover,
.mi-cuenta-pestana.activa {
    border-color: var(--acento);
    color: var(--acento);
}

.mi-cuenta-panel {
    min-width: 0;
}

.mi-cuenta-cabecera {
    display: flex;
    align-items: center;
    gap: 16px;
    padding-bottom: 18px;
    margin-bottom: 20px;
    border-bottom: 2px solid transparent;
    border-image: linear-gradient(90deg, var(--acento), transparent) 1;
}

.mi-cuenta-avatar {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    flex-shrink: 0;
    border: 2px solid var(--acento);
    border-radius: 50%;
    color: var(--acento);
}

.mi-cuenta-avatar svg {
    width: 26px;
    height: 26px;
}

.mi-cuenta-nombre {
    margin: 0;
    color: var(--input-texto);
    font-size: 1.1rem;
    font-weight: 500;
}

.mi-cuenta-google {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-left: auto;
    padding: 10px 16px;
    background: var(--input-bg);
    border: 1px solid var(--input-border);
    color: var(--texto-secundario);
    font-family: inherit;
    font-size: 0.65rem;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    cursor: pointer;
    transition: all 0.2s ease;
}

.mi-cuenta-google:hover {
    border-color: var(--acento);
    color: var(--acento);
}

/* Es un enlace: sin el subrayado. */
a.mi-cuenta-google {
    text-decoration: none;
}

/* La cuenta ya vinculada: el mismo recuadro, en dorado, sin acción. */
.mi-cuenta-google.vinculada {
    border-color: var(--acento);
    color: var(--acento);
    cursor: default;
}

.mi-cuenta-google svg {
    width: 16px;
    height: 16px;
    fill: currentColor;
    flex-shrink: 0;
}

.mi-cuenta-datos {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px 20px;
    margin-bottom: 16px;
}

.mi-cuenta-dato {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 16px;
}

.mi-cuenta-datos .mi-cuenta-dato {
    margin-bottom: 0;
}

.mi-cuenta-dato > span {
    color: var(--texto-secundario);
    font-size: 0.65rem;
    letter-spacing: 1.5px;
    text-transform: uppercase;
}

.mi-cuenta-valor {
    margin: 0;
    padding: 10px 14px;
    background: var(--input-bg);
    border: 1px solid var(--input-border);
    border-left: 2px solid var(--acento);
    color: var(--input-texto);
    font-size: 0.9rem;
    overflow-wrap: anywhere;
}

.mi-cuenta-roles {
    margin: 0;
    padding: 0;
    list-style: none;
    border: 1px solid var(--input-border);
}

.mi-cuenta-roles li {
    padding: 10px 14px;
    color: var(--input-texto);
    font-size: 0.9rem;
}

.mi-cuenta-roles li + li {
    border-top: 1px solid var(--input-border);
}

@media (max-width: 700px) {
    .mi-cuenta-cuerpo {
        grid-template-columns: 1fr;
    }

    .mi-cuenta-pestanas {
        flex-direction: row;
        padding-right: 0;
        padding-bottom: 12px;
        border-right: none;
        border-bottom: 1px solid var(--input-border);
    }

    .mi-cuenta-cabecera {
        flex-wrap: wrap;
    }

    .mi-cuenta-google {
        margin-left: 0;
    }

    .mi-cuenta-datos {
        grid-template-columns: 1fr;
    }
}

/* ---------------------------------------------------------------------------
   CAMPOS AUTOCOMPLETADOS

   Cuando el navegador completa un campo con una sugerencia guardada (un correo,
   una contraseña), le pone su propio fondo y su color de texto, que no
   acompañan el tema. La transición, que tarda días en empezar, deja el fondo
   que el campo ya tenía, y el texto toma el color de los campos del tema.
   Vale para todos los campos del sistema.
   --------------------------------------------------------------------------- */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus {
    -webkit-text-fill-color: var(--input-texto);
    caret-color: var(--input-texto);
    transition: background-color 600000s 0s, color 600000s 0s;
}

/* ---------------------------------------------------------------------------
   BOTÓN REACTIVAR

   Va en la fila de un cliente o de un usuario inactivo, donde están los
   botones de acción. Dorado y con el ícono de un rayo, para que se distinga
   de las acciones sobre los activos.
   --------------------------------------------------------------------------- */
.btn-reactivar {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 4px 10px;
    background: rgba(var(--acento-rgb), 0.12);
    border: 1px solid var(--acento);
    color: var(--acento);
    font-family: inherit;
    font-size: 0.6rem;
    letter-spacing: 0.8px;
    text-transform: uppercase;
    cursor: pointer;
    transition: all 0.2s ease;
    white-space: nowrap;
}

.btn-reactivar svg {
    width: 13px;
    height: 13px;
    flex-shrink: 0;
}

.btn-reactivar:hover {
    background: var(--acento);
    color: var(--btn-texto);
}
