/* Estilo simple y responsivo para las pantallas de personal (no-admin).
   No usa ningún framework externo, para no depender de internet en cada
   carga de página: todo el CSS vive en este único archivo. */

:root {
    --color-primario: #1d4ed8;
    --color-primario-oscuro: #1e3a8a;
    --color-fondo: #f3f4f6;
    --color-tarjeta: #ffffff;
    --color-texto: #111827;
    --color-texto-ayuda: #6b7280;
    --color-borde: #d1d5db;
    --color-error: #b91c1c;
    --color-exito: #15803d;
    /* Altura fija de .barra-superior, para que cualquier elemento que
       necesite "pegarse" justo debajo de ella (ej. .pv-ticket) sepa
       exactamente cuánto restarle al viewport, en vez de adivinar. */
    --altura-barra-superior: 64px;
}

* {
    box-sizing: border-box;
}

body {
    margin: 0;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
    background: var(--color-fondo);
    color: var(--color-texto);
}

/* --- Estructura general: rail de iconos a la izquierda (inspirado en la
   referencia de Siigo que mandó Gabriel el 16 de julio de 2026) + barra
   superior clara + contenido. --- */

.app-shell {
    display: flex;
    min-height: 100vh;
}

.app-shell__main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    /* Deja el espacio que antes ocupaba el sidebar dentro del flujo
       normal — ahora que .sidebar es "fixed" (ver abajo) y ya no empuja
       a sus hermanos, hay que dejarle el mismo margen a mano para que el
       contenido no quede debajo de él. */
    margin-left: 76px;
}

.sidebar {
    /* Antes el sidebar era un simple hijo del flex de .app-shell, así
       que se desplazaba hacia arriba junto con el resto de la página al
       hacer scroll (Gabriel, 17 de julio de 2026: "estos encabezados se
       mueven y se tapan cuando muevo el scroll"). "fixed" lo saca del
       flujo normal y lo deja pegado al viewport, siempre visible sin
       importar cuánto se baje la página — igual que la barra superior
       (.barra-superior, con "sticky" un poco más abajo). */
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    z-index: 50;
    flex-shrink: 0;
    width: 76px;
    background: var(--color-primario-oscuro);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.35rem;
    padding: 0.85rem 0.5rem;
    overflow-y: auto;
    /* Recortes de los pictogramas. El fondo real del riel se pisa más
       abajo a #0f172a; el activo usa --color-primario. */
    --icono-hueco: #0f172a;
}

.sidebar__marca {
    width: 34px;
    height: 34px;
    border-radius: 8px;
    /* Fondo casi blanco (no rgba translúcido como antes) a propósito: si
       el día de mañana Gabriel sube un logo con fondo blanco sólido (ej.
       la foto de una tarjeta impresa), se ve como una insignia prolija
       sobre este fondo claro en vez de un cuadro blanco raro flotando
       sobre el azul oscuro del menú. */
    background: rgba(255, 255, 255, 0.92);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 0.8rem;
    text-decoration: none;
    margin-bottom: 0.6rem;
    padding: 3px;
    box-sizing: border-box;
}

.sidebar__marca img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.sidebar__enlace {
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.2rem;
    padding: 0.5rem 0.25rem;
    border-radius: 10px;
    color: #bfdbfe;
    text-decoration: none;
    font-size: 0.68rem;
    font-weight: 600;
    text-align: center;
    line-height: 1.1;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.sidebar__enlace svg,
.icono-sello {
    flex-shrink: 0;
    display: block;
}

.sidebar__enlace:hover {
    background: rgba(255, 255, 255, 0.1);
    color: #fff;
}

.sidebar__enlace--activo {
    background: #fff;
    color: var(--color-primario-oscuro);
    --icono-hueco: var(--color-primario);
}

.sidebar__enlace--activo:hover {
    background: #fff;
    color: var(--color-primario-oscuro);
}

/* Divisores con etiqueta entre grupos de enlaces del menú lateral (ej.
   "Ventas", "Inventario", "Análisis"...) — agregado el 18 de julio de
   2026 porque el menú había crecido a más de 15 enlaces en una sola
   columna vertical sin ninguna separación, y Gabriel lo notó: "el menú
   lateral se ve como muy saturado". No cambia ningún comportamiento,
   solo agrupa visualmente los enlaces que ya existían (más el nuevo de
   "Gastos") en bloques más chicos y fáciles de escanear. */
.sidebar__grupo-titulo {
    width: 100%;
    text-align: center;
    font-size: 0.55rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.45);
    margin-top: 0.35rem;
    padding-top: 0.5rem;
    border-top: 1px solid rgba(255, 255, 255, 0.14);
}

/* Grupo "Sistema" colapsable — agregado el 18 de julio de 2026 a pedido de
   Gabriel ("no es posible que esos 'grupos' que creaste fueran agrupados y
   se desplegaran a voluntad con un clic"). El botón reutiliza el mismo
   look de .sidebar__grupo-titulo (solo le quitamos los estilos por
   defecto de <button>) y le agregamos una flechita que gira al
   colapsar/expandir (ver core/sidebar.js). */
.sidebar__grupo-titulo--colapsable {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.2rem;
    background: none;
    border: none;
    border-top: 1px solid rgba(255, 255, 255, 0.14);
    font: inherit;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
}

.sidebar__grupo-titulo--colapsable:hover {
    color: rgba(255, 255, 255, 0.7);
}

.sidebar__grupo-flecha {
    flex-shrink: 0;
    transition: transform 0.15s ease;
}

.sidebar__grupo-titulo--colapsado .sidebar__grupo-flecha {
    transform: rotate(-90deg);
}

/* El <div id="sidebar-grupo-sistema"> envuelve los enlaces de "Sistema"
   solo para que el JS tenga un contenedor a quien ocultar — no debe
   comportarse como una caja aparte dentro del layout de columna del
   sidebar, por eso "display: contents" (los enlaces de adentro siguen
   siendo hijos directos, en flex, del <nav>). Cuando el JS lo colapsa
   (atributo "hidden"), ahí sí se oculta de verdad. */
.sidebar__grupo-contenido {
    display: contents;
}

.sidebar__grupo-contenido[hidden] {
    display: none;
}

/* Elementos marcados con el atributo hidden: el navegador les pone
   display:none, pero cualquier regla nuestra con display:flex/grid en una
   clase gana por especificidad y los deja visibles. Pasaba con el recuadro
   verde vacio del cliente, el paginador del catalogo y las lineas de
   descuento en $0 del punto de venta. Esta regla global lo cierra. */
[hidden] {
    display: none !important;
}

.barra-superior {
    /* "sticky" en vez del flujo normal, por la misma razón que .sidebar
       de arriba: se queda pegada arriba del área de contenido mientras
       se hace scroll, en vez de desaparecer hacia arriba con el resto de
       la página. */
    position: sticky;
    top: 0;
    z-index: 40;
    min-height: var(--altura-barra-superior);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.85rem 1.5rem;
    background: var(--color-tarjeta);
    border-bottom: 1px solid var(--color-borde);
    color: var(--color-texto);
    box-sizing: border-box;
}

.barra-superior__marca {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    font-weight: 700;
    font-size: 1.05rem;
    color: var(--color-texto);
}

.barra-superior__marca img {
    height: 34px;
    width: auto;
    max-width: 120px;
    object-fit: contain;
}

.barra-superior__sede {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    font-size: 0.9rem;
}

.barra-superior__sede-menu a {
    color: var(--color-primario);
    margin-right: 0.75rem;
    text-decoration: none;
}

.barra-superior__sede-menu a.activo,
.barra-superior__sede-menu a:hover {
    text-decoration: underline;
    color: var(--color-primario-oscuro);
}

.barra-superior__usuario {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    font-size: 0.9rem;
    color: var(--color-texto-ayuda);
}

.form-en-linea {
    display: inline;
}

.enlace-boton {
    background: none;
    border: none;
    color: var(--color-primario);
    text-decoration: underline;
    cursor: pointer;
    font-size: 0.9rem;
    padding: 0;
}

.enlace-boton:hover {
    color: var(--color-primario-oscuro);
}

.enlace-boton--oscuro {
    color: var(--color-primario);
}

.enlace-boton--oscuro:hover {
    color: var(--color-primario-oscuro);
}

.contenido {
    /* Antes 960px: en monitores anchos dejaba franjas grises grandes a
       los lados incluso en pantallas de trabajo densas como el punto de
       venta (Gabriel, 17 de julio de 2026: "a los lados se ve un
       espacio generoso que está quedando subutilizado"). 1280px sigue
       centrando el contenido y dejando aire en los formularios angostos
       (que ya tienen su propio max-width más chico, como
       .tarjeta--formulario), pero le da mucho más espacio real a las
       pantallas de dos columnas como el punto de venta. */
    max-width: 1280px;
    margin: 0 auto;
    padding: 1.5rem 1.25rem 3rem;
    width: 100%;
}

@media (max-width: 720px) {
    .sidebar {
        width: 60px;
    }

    .app-shell__main {
        margin-left: 60px;
    }

    .sidebar__enlace {
        font-size: 0;
    }

    .sidebar__enlace svg {
        width: 20px;
        height: 20px;
    }
}

.caja-centrada {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 70vh;
}

.tarjeta {
    background: var(--color-tarjeta);
    border: 1px solid var(--color-borde);
    border-radius: 10px;
    padding: 1.5rem;
    margin-bottom: 1.25rem;
}

.detalles-plegable {
    margin-top: 1rem;
    border-top: 1px solid var(--color-borde);
    padding-top: 1rem;
}

.detalles-plegable summary {
    cursor: pointer;
    font-weight: 600;
    color: var(--color-primario-oscuro);
}

.detalles-plegable summary:hover {
    color: var(--color-primario);
}

.detalles-plegable .tabla {
    margin-top: 0.75rem;
}

.detalles-plegable pre {
    background: var(--color-fondo);
    border: 1px solid var(--color-borde);
    border-radius: 6px;
    padding: 0.5rem;
    font-size: 0.75rem;
    white-space: pre-wrap;
    word-break: break-word;
    max-width: 420px;
}

.tarjeta--login {
    width: 100%;
    max-width: 380px;
}

.logo-login {
    display: block;
    margin: 0 auto 1rem auto;
    width: 150px;
    max-width: 100%;
    height: auto;
}

.tarjeta--aviso {
    border-left: 4px solid var(--color-primario);
}

h1 {
    margin-top: 0;
}

.texto-ayuda {
    color: var(--color-texto-ayuda);
    font-size: 0.9rem;
}

.acciones-secundarias {
    color: var(--color-texto-ayuda);
    font-size: 0.9rem;
    margin-top: -0.5rem;
}

.lista-errores-importacion {
    margin: 0.5rem 0 0;
    padding-left: 1.25rem;
}

.lista-errores-importacion li {
    margin-bottom: 0.35rem;
}

.campo {
    margin-bottom: 1rem;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.campo label {
    font-weight: 600;
    font-size: 0.9rem;
}

input[type="text"],
input[type="password"],
input[type="email"] {
    padding: 0.6rem 0.7rem;
    border: 1px solid var(--color-borde);
    border-radius: 6px;
    font-size: 1rem;
    width: 100%;
}

.boton {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    padding: 0.6rem 1.1rem;
    border-radius: 8px;
    border: 1px solid transparent;
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
    text-decoration: none;
    text-align: center;
    transition: background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, transform 0.05s ease;
}

.boton:active {
    transform: translateY(1px);
}

.boton:disabled,
.boton[aria-disabled="true"] {
    opacity: 0.55;
    cursor: not-allowed;
    transform: none;
}

.boton--primario {
    background: var(--color-primario);
    color: #fff;
    width: 100%;
    box-shadow: 0 1px 2px rgba(17, 24, 39, 0.05), 0 4px 10px rgba(29, 78, 216, 0.25);
}

.boton--primario:hover {
    background: var(--color-primario-oscuro);
    box-shadow: 0 2px 4px rgba(17, 24, 39, 0.08), 0 6px 16px rgba(29, 78, 216, 0.3);
}

.boton--secundario {
    background: #fff;
    color: var(--color-texto);
    border-color: var(--color-borde);
}

.boton--secundario:hover {
    background: #f9fafb;
    border-color: #9ca3af;
}

.boton--peligro {
    /* Solo para el reinicio de datos (core/servicios_mantenimiento.py,
       18 de julio de 2026): la única acción de todo el sistema que borra
       información de verdad, sin poder deshacerla — se marca en rojo a
       propósito, distinto de boton--primario, para que nunca se confunda
       con un botón de guardar normal. */
    background: var(--color-error);
    color: #fff;
}

.boton--peligro:hover {
    background: #991b1b;
}

.boton--fantasma {
    background: transparent;
    color: var(--color-primario);
    border-color: transparent;
    padding-left: 0.6rem;
    padding-right: 0.6rem;
}

.boton--fantasma:hover {
    background: #eff6ff;
}

.lista-sedes {
    list-style: none;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
}

.tabla {
    width: 100%;
    border-collapse: collapse;
}

.tabla th,
.tabla td {
    text-align: left;
    padding: 0.5rem 0.6rem;
    border-bottom: 1px solid var(--color-borde);
}

.mensajes {
    list-style: none;
    padding: 0;
    margin: 0 0 1rem;
}

/* En el POS el aviso de "turno abierto" no puede comerse el carrito. */
.contenido:has(.pv) .mensajes {
    margin-bottom: 0.45rem;
}

.contenido:has(.pv) .mensaje {
    padding: 0.4rem 0.75rem;
    margin-bottom: 0;
    font-size: 0.85rem;
}

.mensaje {
    padding: 0.65rem 0.9rem;
    border-radius: 6px;
    margin-bottom: 0.5rem;
    font-size: 0.9rem;
}

.mensaje--compacto {
    padding: 0.4rem 0.7rem;
    margin: 0 0 0.7rem;
    font-size: 0.85rem;
    line-height: 1.4;
}

.mensaje--error {
    background: #fee2e2;
    color: var(--color-error);
}

.mensaje--success {
    background: #dcfce7;
    color: var(--color-exito);
}

.mensaje--warning {
    /* Primer uso: aviso NO bloqueante de que una promoción quedó con
       precio por debajo del costo (promociones/views.py::crear_promocion,
       17 de julio de 2026) — ni error (rojo) ni éxito (verde), un tono
       ámbar intermedio para "revisa esto, pero se guardó igual". */
    background: #fef3c7;
    color: #92400e;
}

.mensaje--vista-previa {
    /* Primer uso: vista previa "antes -> después" al ajustar inventario
       (inventario/templates/inventario/ajuste.html, 19 de julio de 2026,
       a pedido de Gabriel) — mismo tono neutro/informativo que
       .mensaje--nota-interna, solo con nombre propio porque el propósito
       es distinto (mostrar un cálculo en vivo, no un dato guardado). */
    background: #f0f9ff;
    color: #0369a1;
    border-left: 4px solid #38bdf8;
}

.mensaje--alerta-cambio {
    /* 20 de julio de 2026, a pedido de Gabriel ("los mensajes deben ser
       llamativos cuando son alertas, por ejemplo cuanto devolver"): el
       aviso de "debes devolver $X de cambio" en el modal de confirmación
       de venta (punto_venta.js::abrirModal) reusaba el tono neutro/celeste
       de .mensaje--vista-previa, que se perdía entre el resto de texto
       informativo. Este es un tono ámbar fuerte y en negrita, a propósito
       más llamativo que .mensaje--warning normal, porque es dinero físico
       que el vendedor no se puede olvidar de entregar. */
    background: #fef3c7;
    color: #92400e;
    border-left: 4px solid #f59e0b;
    font-weight: 700;
    font-size: 1rem;
}

.mensaje--nota-interna {
    /* Primer uso: el comentario interno de una venta (ventas/models.py,
       Venta.nota_interna, 19 de julio de 2026) — un tono neutro (ni error
       ni éxito ni advertencia), pensado solo para recordar visualmente que
       esto es de uso interno y nunca sale en la factura impresa. */
    background: #f1f5f9;
    color: #334155;
    border-left: 4px solid #94a3b8;
    white-space: pre-line;
}

@media (max-width: 600px) {
    .barra-superior {
        flex-direction: column;
        align-items: flex-start;
    }
}

/* --- Fase 4: catálogo de productos --- */

.encabezado-seccion {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
}

/* Menú de informes. Sustituye el párrafo de "Ver X · Ver Y · Ver Z"
   que Gabriel no podía leer (16 de agosto de 2026): mismo listado en
   todas las pantallas, agrupado, con la opción actual marcada. */
.menu-informes {
    background: var(--color-tarjeta);
    border: 1px solid var(--color-borde);
    border-radius: 12px;
    padding: 0.75rem 1rem 0.9rem;
    margin: 0 0 1rem;
}

.menu-informes__volver {
    display: inline-block;
    margin: 0 0 0.7rem;
    font-size: 0.9rem;
    font-weight: 600;
    text-decoration: none;
}

.menu-informes__grupo {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem 0.65rem;
    padding: 0.45rem 0;
    border-top: 1px solid var(--color-borde);
}

.menu-informes__grupo:first-of-type {
    border-top: 0;
    padding-top: 0;
}

.menu-informes__titulo {
    flex: 0 0 8.5rem;
    margin: 0;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--color-texto-ayuda);
    line-height: 1.3;
}

.menu-informes__opciones {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    flex: 1 1 16rem;
}

.menu-informes__opcion {
    display: inline-flex;
    align-items: center;
    padding: 0.4rem 0.75rem;
    border: 1px solid var(--color-borde);
    border-radius: 999px;
    background: #f9fafb;
    color: var(--color-texto);
    text-decoration: none;
    font-size: 0.88rem;
    font-weight: 600;
    line-height: 1.25;
}

.menu-informes__opcion:hover {
    border-color: var(--color-primario);
    color: var(--color-primario);
    background: #eff6ff;
}

.menu-informes__opcion--activa {
    background: var(--color-primario);
    border-color: var(--color-primario);
    color: #fff;
}

.menu-informes__opcion--activa:hover {
    background: var(--color-primario-oscuro);
    border-color: var(--color-primario-oscuro);
    color: #fff;
}

/* Notas de informes y pantallas: cerradas. Un clic las abre. */
.nota-informe {
    margin: 0.2rem 0 0.55rem;
    max-width: 40rem;
}

.nota-informe:not([open]) > .nota-informe__cuerpo {
    display: none !important;
}

.nota-informe summary {
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--color-texto-ayuda);
    list-style: none;
}

.nota-informe summary:hover {
    color: var(--color-texto);
}

.nota-informe summary::-webkit-details-marker {
    display: none;
}

.nota-informe summary::before {
    content: "";
    width: 0;
    height: 0;
    border-left: 5px solid currentColor;
    border-top: 4px solid transparent;
    border-bottom: 4px solid transparent;
}

.nota-informe[open] summary::before {
    transform: rotate(90deg);
}

.nota-informe__cuerpo {
    margin-top: 0.55rem;
    padding: 0.7rem 0.85rem;
    background: var(--color-tarjeta);
    border: 1px solid var(--color-borde);
    border-radius: 8px;
    font-size: 0.88rem;
    line-height: 1.45;
    color: var(--color-texto-ayuda);
}

.nota-informe__cuerpo p {
    margin: 0 0 0.6rem;
}

.nota-informe__cuerpo p:last-child {
    margin-bottom: 0;
}

.boton--auto {
    width: auto;
}

.barra-filtros {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
    margin: 1rem 0;
}

.barra-filtros input[type="text"] {
    flex: 1;
    min-width: 260px;
    padding: 0.55rem 0.7rem;
    border: 1px solid var(--color-borde);
    border-radius: 6px;
    font-size: 1rem;
}

.filtro-checkbox {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.9rem;
    color: var(--color-texto-ayuda);
}

.campo-filtro {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    font-size: 0.85rem;
    color: var(--color-texto-ayuda);
}

.campo-filtro select,
.campo-filtro input[type="date"] {
    width: auto;
    min-width: 150px;
}

.texto-alerta {
    color: var(--color-error);
    font-weight: 600;
}

.texto-exito {
    color: var(--color-exito);
    font-weight: 600;
}

.texto-tachado {
    color: var(--color-texto-ayuda);
    text-decoration: line-through;
}

.etiqueta-alerta {
    display: inline-block;
    margin-left: 0.4rem;
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    background: #fee2e2;
    color: var(--color-error);
    font-size: 0.75rem;
    font-weight: 600;
}

.etiqueta-exito {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    background: #dcfce7;
    color: var(--color-exito);
    font-size: 0.75rem;
    font-weight: 600;
}

.etiqueta-info {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    background: #dbeafe;
    color: var(--color-primario-oscuro);
    font-size: 0.75rem;
    font-weight: 600;
}

.etiqueta-advertencia {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    background: #fef3c7;
    color: #92400e;
    font-size: 0.75rem;
    font-weight: 600;
}

.etiqueta-neutra {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    background: #e5e7eb;
    color: var(--color-texto-ayuda);
    font-size: 0.75rem;
    font-weight: 600;
}

.tabla--datos th {
    width: 220px;
    color: var(--color-texto-ayuda);
    font-weight: 600;
}

.tarjeta--formulario {
    max-width: 520px;
}

.fila-campos {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
}

.fila-campos .campo {
    flex: 1;
    /* Sin esto, en una tablet angosta dos campos lado a lado se
       aplastan hasta quedar ilegibles en vez de bajar uno debajo del
       otro. Con "flex-wrap: wrap" arriba y este ancho mínimo, cuando ya
       no caben cómodos se acomodan solos en dos renglones. */
    min-width: 11rem;
}

/* Un campo de texto con un botón pegado al lado (ej. el código del
   producto y su botón "Generar código"). El campo se lleva todo el
   espacio sobrante y el botón se queda del tamaño de su texto. */
.campo-con-boton {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

.campo-con-boton input {
    flex: 1 1 12rem;
}

.campo--checkbox label {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-weight: normal;
}

.campo--checkbox input[type="checkbox"] {
    width: auto;
}

.texto-error-campo {
    color: var(--color-error);
    font-size: 0.85rem;
    margin: 0;
}

/* 20 de julio de 2026, reporte de arqueos: resalta en rojo la diferencia
   de un turno que no cuadró (sobró o faltó), en la tabla de detalle —
   distinta de .texto-error-campo (esa es para mensajes de validación de
   formularios, con su propio tamaño de letra que no encaja bien dentro
   de una celda de tabla). */
.valor-descuadre {
    color: var(--color-error);
    font-weight: 700;
}

.acciones-formulario {
    display: flex;
    gap: 0.75rem;
    margin-top: 1.25rem;
}

.paginacion {
    display: flex;
    align-items: center;
    gap: 1rem;
    margin-top: 1.25rem;
}

.paginacion__info {
    color: var(--color-texto-ayuda);
    font-size: 0.9rem;
}

/* --- Rediseño inspirado en Siigo: home con accesos directos --- */

.tarjeta--bienvenida {
    background: linear-gradient(135deg, var(--color-primario) 0%, var(--color-primario-oscuro) 100%);
    border: none;
    color: #fff;
}

.tarjeta--bienvenida p {
    margin: 0;
    font-size: 1.05rem;
}

.tarjeta--bienvenida strong {
    color: #fff;
}

.accesos-directos {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: 1rem;
    margin-bottom: 1.25rem;
}

.acceso-directo {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 0.6rem;
    background: var(--color-tarjeta);
    border: 1px solid var(--color-borde);
    border-radius: 12px;
    padding: 1.25rem 0.75rem;
    text-decoration: none;
    color: var(--color-texto);
    font-weight: 600;
    font-size: 0.9rem;
    transition: box-shadow 0.15s ease, border-color 0.15s ease, transform 0.05s ease;
}

.acceso-directo:hover {
    border-color: var(--color-primario);
    box-shadow: 0 6px 16px rgba(29, 78, 216, 0.12);
}

.acceso-directo:active {
    transform: scale(0.98);
}

.acceso-directo__icono {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 52px;
    height: 52px;
    border-radius: 50%;
    background: #eff6ff;
    color: var(--color-primario);
    --icono-hueco: #eff6ff;
}

.acceso-directo__texto {
    line-height: 1.3;
}

input[type="number"],
input[type="date"],
select,
textarea {
    padding: 0.6rem 0.7rem;
    border: 1px solid var(--color-borde);
    border-radius: 6px;
    font-size: 1rem;
    width: 100%;
    background: #fff;
    font-family: inherit;
}

/* --- Fase 5: ajustes de inventario y traslados --- */

.campo ul {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    gap: 1.25rem;
}

.campo ul li label {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-weight: normal;
}

.campo ul input[type="radio"] {
    width: auto;
}

.tabla--formset select,
.tabla--formset input {
    margin: 0;
}

.tabla--formset td {
    vertical-align: top;
}

/* --- Buscador de producto por texto (BuscadorProductoWidget, Fase 10):
   reemplaza el <select> plano de producto en traslados, compras y
   recetas — mismo patrón visual que .pv-buscador/.pv-resultados del
   punto de venta, pero de tamaño compacto para caber en una celda de
   tabla de formset. --- */

.buscador-producto {
    position: relative;
    min-width: 220px;
}

.buscador-producto__texto {
    width: 100%;
    padding: 0.45rem 0.6rem;
    border: 1px solid var(--color-borde);
    border-radius: 8px;
    font-size: 0.9rem;
    background: var(--color-fondo);
}

.buscador-producto__texto:focus {
    outline: none;
    border-color: var(--color-primario);
    background: #fff;
    box-shadow: 0 0 0 3px rgba(29, 78, 216, 0.12);
}

.buscador-producto__resultados {
    display: none;
    position: absolute;
    z-index: 30;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    max-height: 260px;
    overflow-y: auto;
    background: var(--color-tarjeta);
    border: 1px solid var(--color-borde);
    border-radius: 8px;
    box-shadow: 0 12px 28px rgba(17, 24, 39, 0.16);
}

.buscador-producto__resultados--visible {
    display: block;
}

.buscador-producto__item {
    padding: 0.5rem 0.65rem;
    font-size: 0.85rem;
    cursor: pointer;
    border-bottom: 1px solid var(--color-fondo);
}

.buscador-producto__item:last-child {
    border-bottom: none;
}

.buscador-producto__item:hover,
.buscador-producto__item:focus {
    background: #eff6ff;
    outline: none;
}

/* =========================================================================
   Fase 7 (segundo rediseño): punto de venta estilo "app de caja" — catálogo
   de productos a la izquierda (buscador + categorías + tarjetas) y ticket
   de venta fijo a la derecha, siguiendo el mismo patrón de Square/Shopify
   POS/Loyverse: la lista de la venta actual siempre visible mientras se
   sigue agregando productos.
   ========================================================================= */

.pv {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.pv__topbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem 0.75rem;
    background: var(--color-tarjeta);
    border: 1px solid var(--color-borde);
    border-radius: 10px;
    padding: 0.5rem 0.9rem;
    box-shadow: 0 1px 2px rgba(17, 24, 39, 0.04);
}

.pv__titulo {
    margin: 0;
    font-size: 1.1rem;
}

.pv__subtitulo {
    margin: 0.2rem 0 0;
    color: var(--color-texto-ayuda);
    font-size: 0.88rem;
}

.pv__topbar-acciones {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: center;
}

.pv__cuerpo {
    display: grid;
    /* La columna del carrito ("Venta actual") pasó de 380px a 460px el
       17 de julio de 2026 — Gabriel marcó con flechas que justo esa
       columna es la que queda apretada (la tabla del carrito), mientras
       sobraba espacio a los costados de toda la pantalla. Ese espacio
       extra ahora se lo lleva principalmente esta columna.

       20 de julio de 2026: subió otra vez, de 460px a 560px, a pedido de
       Gabriel ("de ser posible darle mas espacio al modulo de ventas") —
       ahora que el catálogo pasó de tarjetas grandes a una lista compacta
       paginada (ver .pv-lista-compacta más abajo), ya no necesita tanto
       ancho, así que ese espacio libre se lo lleva "Venta actual". */
    grid-template-columns: 1fr 560px;
    gap: 1.25rem;
    align-items: start;
}

@media (max-width: 960px) {
    .pv__cuerpo {
        grid-template-columns: 1fr;
    }

    .pv-ticket {
        position: static;
        max-height: none;
    }
}

/* --- Catálogo (izquierda) --- */

.pv-catalogo {
    background: var(--color-tarjeta);
    border: 1px solid var(--color-borde);
    border-radius: 12px;
    padding: 0.85rem 1rem;
    box-shadow: 0 1px 2px rgba(17, 24, 39, 0.04);
}

.pv-buscador {
    position: relative;
    display: flex;
    align-items: center;
}

.pv-buscador__icono {
    position: absolute;
    left: 0.85rem;
    color: var(--color-texto-ayuda);
    pointer-events: none;
    display: flex;
}

.pv-buscador input[type="text"] {
    padding: 0.75rem 0.9rem 0.75rem 2.5rem;
    border: 1px solid var(--color-borde);
    border-radius: 10px;
    font-size: 1.05rem;
    width: 100%;
    background: var(--color-fondo);
}

.pv-buscador input[type="text"]:focus {
    outline: none;
    border-color: var(--color-primario);
    background: #fff;
    box-shadow: 0 0 0 3px rgba(29, 78, 216, 0.12);
}

.pv-resultados {
    display: none;
    position: absolute;
    z-index: 30;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    max-height: 340px;
    overflow-y: auto;
    background: var(--color-tarjeta);
    border: 1px solid var(--color-borde);
    border-radius: 10px;
    box-shadow: 0 12px 28px rgba(17, 24, 39, 0.16);
}

.pv-resultados--visible {
    display: block;
}

.pv-resultado-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    padding: 0.65rem 0.9rem;
    cursor: pointer;
    border-bottom: 1px solid var(--color-fondo);
}

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

.pv-resultado-item:hover,
.pv-resultado-item:focus {
    background: #eff6ff;
    outline: none;
}

.pv-resultado-item__izquierda {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    min-width: 0;
}

.pv-resultado-item__nombre {
    font-weight: 600;
}

.pv-resultado-item__detalle {
    color: var(--color-texto-ayuda);
    font-size: 0.85rem;
    white-space: nowrap;
}

.pv-categorias {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin: 0.5rem 0;
}

.pv-categoria-chip {
    border: 1px solid var(--color-borde);
    background: #fff;
    color: var(--color-texto-ayuda);
    padding: 0.4rem 0.95rem;
    border-radius: 999px;
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.15s ease;
}

.pv-categoria-chip:hover {
    border-color: var(--color-primario);
    color: var(--color-primario);
}

.pv-categoria-chip.pv-activo {
    background: var(--color-primario);
    border-color: var(--color-primario);
    color: #fff;
}

/* 20 de julio de 2026, a pedido de Gabriel ("el listado de productos le
   quita mucho espacio a la vista de ventas... mejor que sean hojas para
   ir mirando"): reemplaza la cuadrícula de tarjetas grandes (que crecía
   sin límite hacia abajo) por una lista de filas angostas, paginada de a
   PAGINA_TAMANO en vez de scroll infinito — ver ventas/static/ventas/
   punto_venta.js::renderGrid. Sin límite de alto propio: como la
   cantidad de filas ya está acotada por la paginación, no hace falta un
   max-height/overflow aparte aquí. */
.pv-lista-compacta {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--color-borde);
    border-radius: 10px 10px 0 0;
    background: var(--color-tarjeta);
    border-bottom: none;
}

.pv-fila-producto {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    width: 100%;
    text-align: left;
    padding: 0.6rem 0.85rem;
    border: none;
    border-bottom: 1px solid var(--color-borde);
    background: none;
    font-family: inherit;
    font-size: inherit;
    color: inherit;
    cursor: pointer;
}

.pv-lista-compacta .pv-fila-producto:last-child {
    border-bottom: none;
}

.pv-fila-producto:hover {
    background: var(--color-fondo);
}

.pv-fila-producto:active {
    background: #e5e7eb;
}

.pv-fila-producto__cat {
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.72rem;
    font-weight: 700;
    color: #fff;
}

.pv-fila-producto__info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.05rem;
}

.pv-fila-producto__nombre {
    font-weight: 600;
    font-size: 0.92rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.pv-fila-producto__codigo {
    font-size: 0.76rem;
    color: var(--color-texto-ayuda);
}

.pv-fila-producto__genero {
    display: inline-block;
    width: fit-content;
    font-size: 0.65rem;
    font-weight: 700;
    padding: 0.05rem 0.4rem;
    border-radius: 999px;
    white-space: nowrap;
}

.pv-fila-producto__genero--hombre {
    background: #dbeafe;
    color: #1d4ed8;
}

.pv-fila-producto__genero--mujer {
    background: #fce7f3;
    color: #be185d;
}

.pv-fila-producto__genero--unisex {
    background: #ede9fe;
    color: #5b21b6;
}

.pv-fila-producto__badge {
    flex-shrink: 0;
}

.pv-fila-producto__precio-caja {
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.05rem;
    min-width: 70px;
}

.pv-fila-producto__precio {
    font-weight: 700;
    color: var(--color-primario-oscuro);
    font-size: 0.92rem;
    white-space: nowrap;
}

.pv-fila-producto__precio-original {
    font-size: 0.72rem;
    color: var(--color-texto-ayuda);
    text-decoration: line-through;
    white-space: nowrap;
}

.pv-fila-producto__precio--promo {
    color: var(--color-exito);
}

/* --- Paginador ("hojas") del catálogo --- */

.pv-paginador {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0.55rem 0.85rem;
    border: 1px solid var(--color-borde);
    border-top: none;
    border-radius: 0 0 10px 10px;
    background: var(--color-fondo);
}

.pv-paginador__boton {
    padding: 0.4rem 0.85rem;
    border-radius: 8px;
    border: 1px solid var(--color-borde);
    background: #fff;
    font-weight: 600;
    font-size: 0.85rem;
    cursor: pointer;
    font-family: inherit;
}

.pv-paginador__boton:hover:not(:disabled) {
    border-color: var(--color-primario);
    color: var(--color-primario);
}

.pv-paginador__boton:disabled {
    opacity: 0.4;
    cursor: default;
}

.pv-paginador__estado {
    font-size: 0.85rem;
    color: var(--color-texto-ayuda);
    font-weight: 600;
}

.pv-badge {
    font-size: 0.7rem;
    font-weight: 700;
    padding: 0.15rem 0.5rem;
    border-radius: 999px;
    white-space: nowrap;
}

.pv-badge--ok {
    background: #dcfce7;
    color: var(--color-exito);
}

.pv-badge--bajo {
    background: #fef3c7;
    color: #92400e;
}

.pv-badge--agotado {
    background: #fee2e2;
    color: var(--color-error);
}

.pv-badge--kit {
    background: #ede9fe;
    color: #5b21b6;
}

.pv-grid-vacio {
    text-align: center;
    color: var(--color-texto-ayuda);
    padding: 2.5rem 1rem;
}

/* --- Ticket de venta (derecha, fijo) --- */

.pv-ticket {
    /* "top" y "max-height" restan --altura-barra-superior porque la
       barra superior ahora es "sticky" y se queda ocupando ese espacio
       arriba del viewport (ver .barra-superior) — sin este ajuste, el
       ticket quedaría escondido debajo de la barra al hacer scroll. */
    position: sticky;
    top: calc(var(--altura-barra-superior) + 1rem);
    background: var(--color-tarjeta);
    border: 1px solid var(--color-borde);
    border-radius: 12px;
    box-shadow: 0 1px 2px rgba(17, 24, 39, 0.04);
    padding: 0.85rem 1rem;
    display: flex;
    flex-direction: column;
    max-height: calc(100vh - var(--altura-barra-superior) - 1.25rem);
    /* 20 de julio de 2026, a pedido de Gabriel ("toca desplazarme con el
       scroll para poder cobrar o confirmar la venta"): el scroll ya NO
       vive aquí — vive en .pv-ticket__scroll, adentro. Así el total y el
       botón Cobrar (en .pv-ticket__pie) quedan siempre visibles, fuera
       de la zona que se desplaza, sin importar cuánto crezca el carrito
       o la forma de pago. */
    overflow: hidden;
}

.pv-ticket__form {
    display: flex;
    flex-direction: column;
    min-height: 0;
    flex: 1;
}

.pv-ticket__scroll {
    /* Zona que se desplaza: todo lo de arriba del total (cliente,
       carrito, forma de pago, descuento, nota, puntos). flex:1 +
       min-height:0 es lo que le permite encogerse dentro del alto
       máximo de .pv-ticket y ceder el espacio fijo que necesita
       .pv-ticket__pie (ver más abajo). */
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    /* Mismo criterio que antes tenía .pv-ticket__lista con su
       min-height de 240px (17 de julio de 2026: "la altura no permite
       ver nada casi") — ahora ese mínimo lo respeta el propio contenido
       de la tabla del carrito, sin cambios ahí. */
}

.pv-ticket__pie {
    /* Pago + total + Cobrar: siempre visibles. El carrito es el que
       se desplaza (Gabriel, 23 ago 2026: el pago quedaba saturado
       arriba, escondido detrás de descuento, nota y puntos). */
    flex-shrink: 0;
    padding-top: 0.65rem;
    border-top: 1px solid var(--color-borde);
}

.pv-ticket__seccion--pago {
    margin-bottom: 0.65rem;
}

.pv-ajustes {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 0.65rem;
    margin: 0 0 0.7rem;
}

.pv-ajustes__campo {
    margin: 0;
}

.pv-ajustes__campo label {
    display: block;
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--color-texto-ayuda);
    margin-bottom: 0.25rem;
}

.pv-ajustes__campo input {
    width: 100%;
    min-height: 40px;
    padding: 0.4rem 0.55rem;
    font-size: 1rem;
    font-weight: 600;
}

.pv-ajustes__campo .texto-ayuda {
    margin: 0.25rem 0 0;
    font-size: 0.75rem;
}


.pv-extras {
    margin: 0 0 0.75rem;
}

.pv-extras summary {
    cursor: pointer;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--color-texto-ayuda);
    list-style: none;
}

.pv-extras summary::-webkit-details-marker {
    display: none;
}

.pv-extras summary::before {
    content: "";
    display: inline-block;
    width: 0;
    height: 0;
    margin-right: 0.35rem;
    border-left: 5px solid currentColor;
    border-top: 4px solid transparent;
    border-bottom: 4px solid transparent;
}

.pv-extras[open] summary::before {
    transform: rotate(90deg);
}

.pv-extras summary:hover {
    color: var(--color-texto);
}

.pv-ticket h2 {
    margin: 0 0 0.6rem;
    font-size: 1.05rem;
}

.pv-ticket__seccion {
    margin-bottom: 0.9rem;
}

.pv-ticket__seccion label,
.pv-ticket__etiqueta {
    display: block;
    font-weight: 600;
    font-size: 0.85rem;
    margin-bottom: 0.35rem;
}

.pv-enlace-discreto {
    display: inline-block;
    margin-top: 0.3rem;
    font-size: 0.82rem;
}

.pv-ticket__lista {
    /* El pago vive en el pie (siempre visible). El carrito ya no pelea
       por altura con Addi, Sistecrédito, descuento y nota: ese scroll
       es uno solo, el de .pv-ticket__scroll. */
    min-height: 8rem;
    margin-bottom: 0.75rem;
}

.pv-ticket__vacio {
    text-align: center;
    color: var(--color-texto-ayuda);
    padding: 1.75rem 0.5rem;
    font-size: 0.9rem;
    border: 1px dashed var(--color-borde);
    border-radius: 10px;
    margin-bottom: 0.75rem;
}

/* Venta cruzada ("También suelen llevar...") — a pedido de Gabriel el
   22 de julio de 2026. Aparece justo debajo del carrito apenas se
   agrega un producto con sugerencias disponibles. */
.pv-sugerencias {
    margin-bottom: 0.75rem;
    padding: 0.6rem 0.7rem;
    border: 1px solid var(--color-borde);
    border-radius: 10px;
    background: #f8fafc;
}

.pv-sugerencias__titulo {
    display: block;
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--color-texto-ayuda);
    text-transform: uppercase;
    letter-spacing: 0.02em;
    margin-bottom: 0.4rem;
}

.pv-sugerencias__lista {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}

.pv-sugerencias__item {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.3rem 0.55rem;
    border: 1px solid var(--color-primario);
    border-radius: 999px;
    background: #fff;
    color: var(--color-primario-oscuro);
    font-size: 0.8rem;
    cursor: pointer;
}

.pv-sugerencias__item:hover {
    background: var(--color-primario);
    color: #fff;
}

.pv-sugerencias__nombre {
    max-width: 160px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pv-sugerencias__precio {
    font-weight: 700;
    white-space: nowrap;
}

/* El carrito es una tabla (Producto / Cant. / Subtotal / quitar), no
   tarjetas apiladas — a pedido de Gabriel el 17 de julio de 2026, que
   mandó de ejemplo un listado tipo tabla como el de otros sistemas de
   punto de venta que conoce. El intento anterior (nombre arriba,
   controles abajo en una fila propia) todavía forzaba de más el ancho
   de esa fila y terminaba generando scroll horizontal dentro de cada
   producto; una tabla de verdad reparte las columnas sola, sin ese
   problema. */
.pv-carrito-tabla {
    font-size: 0.85rem;
}

.pv-carrito-tabla th,
.pv-carrito-tabla td {
    padding: 0.4rem 0.4rem;
}

.pv-carrito-tabla thead th {
    position: sticky;
    top: 0;
    background: var(--color-tarjeta);
    font-size: 0.78rem;
    color: var(--color-texto-ayuda);
    font-weight: 600;
    z-index: 1;
}

.pv-item--sin-stock {
    background: #fef2f2;
}

.pv-item__nombre {
    font-weight: 600;
    line-height: 1.3;
    overflow-wrap: break-word;
}

.pv-item__aviso {
    font-size: 0.75rem;
    margin-top: 0.1rem;
}

.pv-item__promo {
    font-size: 0.75rem;
    margin-top: 0.1rem;
    color: var(--color-exito);
    font-weight: 600;
}

.pv-item__cantidad {
    display: flex;
    align-items: center;
    gap: 0.25rem;
}

/* Corrección de la auditoría (Frontend/UX #8): estos botones (+/-) y el
   de quitar (más abajo, .pv-item__quitar) son los controles que más se
   tocan de todo el punto de venta, y eran los más pequeños de toda la
   pantalla (24×24px y ~19×22px) — en una tablet, tocar el de al lado por
   error es cuestión de tiempo. 36px se acerca al tamaño mínimo de
   objetivo táctil recomendado (44px) sin desbordar la columna angosta
   del carrito. */
.pv-stepper-boton {
    width: 36px;
    height: 36px;
    border-radius: 6px;
    border: 1px solid var(--color-borde);
    background: #fff;
    cursor: pointer;
    font-weight: 700;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    font-size: 1.1rem;
    color: var(--color-primario-oscuro);
}

.pv-stepper-boton:hover {
    background: #eff6ff;
    border-color: var(--color-primario);
}

.pv-stepper-input {
    width: 48px;
    text-align: center;
    border: 1px solid var(--color-borde);
    border-radius: 6px;
    padding: 0.25rem 0.15rem;
    font-size: 0.85rem;
}

.pv-item__subtotal {
    font-weight: 700;
    text-align: right;
    white-space: nowrap;
}

/* 20 de julio de 2026, descuentos con tope por Rol: input de descuento
   manual por producto, columna "Descuento" del carrito (ver
   ventas/static/ventas/punto_venta.js::renderCarrito). Se ve apagado
   cuando está deshabilitado (producto con promoción vigente — las dos
   cosas no se pueden combinar). */
.pv-item__descuento {
    width: 64px;
    text-align: right;
    border: 1px solid var(--color-borde);
    border-radius: 6px;
    padding: 0.25rem 0.3rem;
    font-size: 0.85rem;
}

.pv-item__descuento:disabled {
    background: #f3f4f6;
    color: var(--color-texto-ayuda);
    cursor: not-allowed;
}

.pv-item__quitar {
    background: none;
    border: none;
    color: var(--color-error);
    cursor: pointer;
    font-size: 1.2rem;
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border-radius: 6px;
    line-height: 1;
}

.pv-item__quitar:hover {
    background: #fee2e2;
}

/* --- Pagos (posiblemente combinados: efectivo + tarjeta, etc.) --- */

.pv-pagos__encabezado {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-bottom: 0.4rem;
}

.pv-pagos-estado {
    font-size: 0.82rem;
    font-weight: 700;
    padding: 0.25rem 0.55rem;
    border-radius: 8px;
    margin: 0.15rem 0 0;
    text-align: right;
}

.pv-pagos-estado--ok {
    background: #dcfce7;
    color: var(--color-exito);
}

.pv-pagos-estado--falta {
    background: #fef3c7;
    color: #92400e;
}

.pv-pagos-estado--sobra {
    background: #fee2e2;
    color: var(--color-error);
}

.pv-pagos-estado--cambio {
    /* 20 de julio de 2026, a pedido de Gabriel ("los mensajes deben ser
       llamativos cuando son alertas, por ejemplo cuanto devolver"): antes
       "Vas a devolver $X de cambio" usaba el mismo verde de
       --ok ("Pagos completos"), y se podía confundir con un simple visto
       bueno. Mismo tono ámbar que .mensaje--alerta-cambio (ver ese
       comentario), con borde para que resalte más que la píldora normal. */
    background: #fef3c7;
    color: #92400e;
    border: 1px solid #f59e0b;
}

.pv-pagos-lineas {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    margin-bottom: 0.5rem;
}

.pv-pago-linea {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.pv-pago-linea select {
    flex: 1.1;
    min-height: 44px;
    padding: 0.55rem 0.6rem;
    font-size: 1rem;
}

.pv-pago-linea input[type="number"] {
    flex: 1;
    min-height: 44px;
    padding: 0.55rem 0.6rem;
    font-size: 1.05rem;
    font-weight: 600;
}

.pv-pago-linea__quitar {
    background: none;
    border: none;
    color: var(--color-error);
    cursor: pointer;
    font-size: 1.15rem;
    width: 36px;
    height: 36px;
    padding: 0;
    border-radius: 6px;
    line-height: 1;
}

.pv-pago-linea__quitar:hover {
    background: #fee2e2;
}

.pv-pagos-agregar {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}

.pv-pagos-agregar__boton {
    border: 1px dashed var(--color-borde);
    background: #fff;
    color: var(--color-primario);
    padding: 0.45rem 0.8rem;
    border-radius: 999px;
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.15s ease;
}

.pv-pagos-agregar__boton:hover {
    background: #eff6ff;
    border-style: solid;
}

.pv-pagos-agregar__boton:disabled {
    /* No se puede agregar dos veces la misma forma de pago (19 de julio
       de 2026, a pedido de Gabriel) — se ve apagado en vez de activo. */
    color: var(--color-texto-ayuda);
    border-style: solid;
    border-color: var(--color-borde);
    background: #f8fafc;
    cursor: not-allowed;
}

.pv-campo-descuento {
    max-width: 220px;
}

/* Buscador de cliente (19 de julio de 2026, a pedido de Gabriel: "y
   deberia tener una forma de buscar un cliente con el id para ser mas
   rapido?") — reutiliza .pv-buscador/.pv-resultados del buscador de
   productos, pero sin el ícono de lupa (no hace falta el padding extra
   a la izquierda). */
.pv-buscador--cliente input[type="text"] {
    padding-left: 0.9rem;
}

.pv-oculto {
    display: none;
}

.pv-cliente-seleccionado {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    margin-top: 0.4rem;
    padding: 0.5rem 0.65rem;
    border-radius: 6px;
    background: #f0fdf4;
    border: 1px solid #bbf7d0;
    font-size: 0.85rem;
}

.pv-resultado-item__etiqueta {
    display: inline-block;
    margin-left: 0.4rem;
    padding: 0.1rem 0.45rem;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 600;
    background: #fef3c7;
    color: #92400e;
}

.pv-campo-descuento--apagado {
    opacity: 0.55;
    pointer-events: none;
}

.pv-fidelizacion-info {
    margin-top: 0.4rem;
    padding: 0.5rem 0.65rem;
    border-radius: 6px;
    background: #eff6ff;
    border: 1px solid #bfdbfe;
    color: var(--color-texto);
    font-size: 0.8rem;
    line-height: 1.35;
}

.pv-ticket__totales {
    margin-top: 0.15rem;
    padding-top: 0.45rem;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.pv-ticket__linea {
    display: flex;
    justify-content: space-between;
    font-size: 0.95rem;
}

.pv-ticket__linea--total {
    font-size: 1.35rem;
    font-weight: 700;
    color: var(--color-primario-oscuro);
}

.pv-boton-cobrar {
    margin-top: 0.9rem;
    padding: 0.9rem;
    font-size: 1.1rem;
}

/* --- Modal de confirmación (reemplaza el confirm() del navegador) --- */

.pv-modal {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
}

.pv-modal[hidden] {
    display: none;
}

.pv-modal__fondo {
    position: absolute;
    inset: 0;
    background: rgba(17, 24, 39, 0.55);
}

.pv-modal__caja {
    position: relative;
    background: #fff;
    border-radius: 14px;
    padding: 1.5rem;
    width: 100%;
    max-width: 420px;
    max-height: 85vh;
    overflow-y: auto;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.3);
}

.pv-modal__caja h2 {
    margin-top: 0;
}

.pv-modal__lineas {
    list-style: none;
    padding: 0;
    margin: 0.9rem 0;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    max-height: 220px;
    overflow-y: auto;
}

.pv-modal__lineas li {
    display: flex;
    justify-content: space-between;
    gap: 0.75rem;
    font-size: 0.88rem;
}

.pv-modal__subtitulo {
    margin: 0.75rem 0 0.15rem;
    font-weight: 600;
    font-size: 0.85rem;
    color: var(--color-texto-ayuda);
}

/* Fecha del día que se está resumiendo, justo bajo el título del modal
   "Resumen del día" (Gabriel, 11 de agosto de 2026). Va pegada al título
   —de ahí el margen negativo arriba— para que se lea como parte de él y
   no como un dato suelto más. */
.pv-modal__fecha {
    margin: -0.4rem 0 0.5rem;
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--color-texto-ayuda);
}

.pv-modal__total {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    font-size: 1.25rem;
    font-weight: 700;
    padding-top: 0.6rem;
    margin-top: 0.4rem;
    border-top: 1px solid var(--color-borde);
    color: var(--color-primario-oscuro);
}

/* --- Notificaciones tipo "toast" (errores del carrito en el navegador) --- */

.pv-toasts {
    position: fixed;
    bottom: 1.25rem;
    right: 1.25rem;
    z-index: 200;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    max-width: 320px;
}

.pv-toast {
    background: #111827;
    color: #fff;
    padding: 0.75rem 1rem;
    border-radius: 8px;
    font-size: 0.88rem;
    box-shadow: 0 10px 24px rgba(0, 0, 0, 0.25);
    animation: pv-toast-in 0.18s ease;
}

.pv-toast--error {
    background: #7f1d1d;
}

@keyframes pv-toast-in {
    from {
        opacity: 0;
        transform: translateY(6px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@media (max-width: 600px) {
    /* 20 de julio de 2026: la regla que vivía aquí para .pv-grid (cuadrícula
       de tarjetas) quedó sin uso — el catálogo ahora es .pv-lista-compacta,
       una lista de filas de un solo ancho que ya se ve bien en celular sin
       ajustes aparte (ver más arriba). */

    .pv__topbar-acciones {
        width: 100%;
    }

    .pv__topbar-acciones .boton {
        flex: 1;
    }
}

/* --- Fase 9: reportes de ventas e inventario --- */

.tarjeta--ancha {
    max-width: none;
    /* Dentro de .reporte-secciones (una grilla), ocupa las columnas
       completas en vez de una sola celda — para la tabla de "productos
       que más vendieron"/"mayor valor en inventario", que necesita más
       ancho que las tarjetas de al lado. grid-column no hace nada fuera
       de un contenedor grid, así que no afecta a los demás usos de esta
       clase (ej. recetas/formulario.html). */
    grid-column: 1 / -1;
}

.tarjetas-resumen {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 1rem;
    margin: 1.25rem 0;
}

.tarjeta-resumen {
    background: var(--color-tarjeta);
    border: 1px solid var(--color-borde);
    border-radius: 10px;
    padding: 1rem 1.1rem;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.tarjeta-resumen__etiqueta {
    font-size: 0.82rem;
    color: var(--color-texto-ayuda);
    font-weight: 600;
}

.tarjeta-resumen__valor {
    font-size: 1.6rem;
    font-weight: 700;
    color: var(--color-primario-oscuro);
}

.tarjeta-resumen--hero .tarjeta-resumen__valor {
    font-size: 2rem;
}

.tarjeta-resumen--hero {
    border-color: #93c5fd;
}

.reporte-secciones {
    display: grid;
    /* Corrección de la auditoría interna (7.1, segunda parte) — REGRESIÓN QUE
       INTRODUJO EL PROPIO 7.1, reportada por Gabriel el 8 de agosto de 2026
       con una captura del reporte de compras.

       El mínimo era 340px. Con una ventana de entre ~961 y ~1100 píxeles esta
       grilla arma dos columnas de ~450px, y la tabla "Por proveedor" (cuatro
       columnas, con nombres largos tipo "G&L LABORATORIO") no cabe en ese
       ancho: su ancho mínimo de contenido es ~507px. Como el track está
       limitado a "1fr" y no crece hasta el min-content del contenido, la tabla
       se dibujaba POR FUERA del borde de la tarjeta.

       Antes de 7.1 esto no se veía porque .tabla tenía display:block +
       overflow-x:auto en todos los tamaños y la tabla se desplazaba adentro.
       Al encerrar esa regla en @media (max-width: 960px), la franja de 961 a
       1100 quedó sin ninguna de las dos protecciones. Justo esa franja es la
       que ve Gabriel con el navegador al 150% de zoom (1528 px reales / 1,5 =
       ~1019 px de CSS).

       560px es el ancho mínimo con el que esa tabla cabe entera. Por debajo de
       eso la grilla pasa a una sola columna, que es lo correcto: mejor una
       tabla completa y legible que dos apretadas. Medido en 14 anchos de
       ventana, de 700 a 1600 px: cero desbordes. */
    grid-template-columns: repeat(auto-fit, minmax(560px, 1fr));
    gap: 1.25rem;
    align-items: start;
}

/* Red de seguridad del arreglo de arriba: si algún día un dato hace que una
   tabla de reporte no quepa igual (un nombre de proveedor larguísimo, una
   columna nueva), la tarjeta se desplaza de lado en vez de dejar que la tabla
   se salga por el borde. Va limitado a .reporte-secciones a propósito: poner
   overflow en TODAS las .tarjeta convertiría cada tarjeta en contenedor de
   desplazamiento y recortaría los desplegables del buscador de productos, que
   están posicionados en absoluto dentro de tarjetas de formulario. */
.reporte-secciones .tarjeta {
    overflow-x: auto;
}

/* La misma red de seguridad, para las tablas anchas que NO viven dentro de
   .reporte-secciones (rotación, inventario envejecido, fechas especiales y
   alertas tienen su tabla suelta). Sin esto, por encima de 960px —donde la
   regla de @media más abajo no aplica— una tabla de diez columnas se dibuja
   POR FUERA del borde de su tarjeta: es exactamente el fallo 7.1/R12 de la
   auditoría, que se arregló solo para la rejilla de secciones y dejó estas
   cuatro pantallas sin cubrir.

   Va como clase propia y no sobre .tarjeta--ancha a secas porque esa clase
   también la usan tarjetas de FORMULARIO (recetas/formulario.html), y
   "overflow" convierte la tarjeta en contenedor de recorte: le cortaría el
   desplegable del buscador de productos, que está posicionado en absoluto. */
.tarjeta--tabla {
    overflow-x: auto;
}

/* Distintivo de clase A/B/C del Pareto de ventas. El color hace el trabajo
   que en una tabla de 400 filas no puede hacer el orden: A y B se
   reconocen de un vistazo aunque se haya perdido de vista el encabezado. */
.etiqueta-clase {
    display: inline-block;
    min-width: 1.5rem;
    padding: 0.1rem 0.45rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 700;
    text-align: center;
}

.etiqueta-clase--a { background: #dcfce7; color: #15803d; }
.etiqueta-clase--b { background: #fef3c7; color: #a16207; }
.etiqueta-clase--c { background: #e5e7eb; color: var(--color-texto-ayuda); }

/* Marcas de decisión en sugeridos de compra: una acción por fila +
   filtro por chip. No toca el POS. */
.resumen-decision {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    margin: 0 0 1rem;
}
.resumen-decision__chip {
    display: inline-block;
    padding: 0.25rem 0.7rem;
    border-radius: 999px;
    background: #e5e7eb;
    color: var(--color-texto);
    font-size: 0.85rem;
    font-weight: 600;
    text-decoration: none;
}
.resumen-decision__chip:hover { text-decoration: none; filter: brightness(0.97); }
.resumen-decision__chip--pedir { background: #dcfce7; color: #15803d; }
.resumen-decision__chip--trasladar { background: #dbeafe; color: var(--color-primario-oscuro); }
.resumen-decision__chip--revisar { background: #fef3c7; color: #92400e; }
.resumen-decision__chip--activo {
    outline: 2px solid var(--color-primario-oscuro);
    outline-offset: 1px;
}
.resumen-decision__plata {
    margin-left: 0.25rem;
    font-weight: 700;
}
.marcas-celda {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    align-items: center;
}
.campo--buscar-decision {
    max-width: 36rem;
    margin: 0 0 1rem;
}
.campo--buscar-decision input {
    width: 100%;
}

/* --- Fase 9: gráficas simples de los reportes (sin librerías externas,
   igual que el resto del sistema — ver la nota al inicio de este
   archivo) --- */

.grafica-tendencia {
    display: flex;
    align-items: flex-end;
    gap: 3px;
    height: 160px;
    padding: 0.5rem 0.25rem 0;
    overflow-x: auto;
}

.grafica-tendencia__columna {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    flex: 1 0 auto;
    min-width: 10px;
    height: 100%;
}

.grafica-tendencia__barra {
    width: 100%;
    max-width: 28px;
    background: var(--color-primario);
    border-radius: 3px 3px 0 0;
    min-height: 2px;
}

.grafica-tendencia__barra:hover {
    background: var(--color-primario-oscuro);
}

.grafica-tendencia__etiqueta {
    margin-top: 0.3rem;
    font-size: 0.68rem;
    color: var(--color-texto-ayuda);
    white-space: nowrap;
    height: 1rem;
}

/* Contenedor de las gráficas hechas con Chart.js. La altura tiene que
   estar fija acá porque el lienzo corre con maintainAspectRatio en
   false: sin un alto definido por CSS, Chart.js no tiene contra qué
   medirse y la gráfica crece sin parar en cada redibujado. */
.grafica-lienzo {
    position: relative;
    height: 260px;
}

/* Las donas van dentro de una tarjeta que también lleva su tabla, así que
   necesitan menos alto que una gráfica que ocupa la tarjeta entera. */
.grafica-lienzo--dona {
    height: 200px;
    margin-bottom: 1rem;
}

/* Para las barras HORIZONTALES de los "top 15": con la altura normal, quince
   barras apiladas quedan de 3px y los nombres de producto se solapan hasta
   volverse ilegibles. */
.grafica-lienzo--alta {
    height: 420px;
    margin-bottom: 1rem;
}

.mini-barra {
    background: var(--color-fondo);
    border-radius: 999px;
    height: 8px;
    min-width: 60px;
    overflow: hidden;
}

.mini-barra__relleno {
    height: 100%;
    background: var(--color-primario);
    border-radius: 999px;
}

/* --- Impresión (corrección de la auditoría, Frontend/UX #9) -----------

   "style.css no tiene ni un @media print: imprimir un arqueo o un cierre
   de turno sale con sidebar azul y barra superior incluidos." Las
   pantallas de factura ya tienen su propia plantilla de impresión aparte
   (factura_imprimir_ticket.html / factura_imprimir_media_carta.html, sin
   sidebar para empezar) — este bloque es para el resto de las pantallas
   normales del sistema, que alguien puede querer imprimir directo con
   Ctrl+P (un arqueo, un cierre de turno, un reporte) sin pasar por
   ninguna plantilla especial. */
@media print {
    .sidebar,
    .barra-superior,
    .acciones-formulario,
    .encabezado-seccion .boton,
    .mensajes,
    .sidebar__grupo-titulo--colapsable,
    .no-imprimir {
        display: none !important;
    }

    .app-shell {
        display: block;
    }

    .app-shell__main,
    .contenido {
        margin: 0;
        padding: 0;
        width: 100%;
    }

    body {
        background: #fff;
    }

    .tarjeta {
        box-shadow: none;
        border: 1px solid #ccc;
        break-inside: avoid;
    }

    a[href]::after {
        /* Los enlaces de "volver"/navegación no aportan nada en papel —
           en vez de escondernos el texto del enlace (que a veces sí
           importa, ej. un link a WhatsApp), simplemente no se subraya
           como si fuera clickeable. */
        content: "";
    }
}

/* Corrección de la auditoría (Frontend/UX #7): "Ninguna tabla tiene
   scroll horizontal y varias tienen 7–9 columnas: en tablet vertical
   desbordan y empujan el layout." display:block + overflow-x:auto en el
   propio <table> (sin tener que envolverlo en un <div> en cada una de
   las decenas de plantillas que usan .tabla) vuelve la tabla misma su
   propio contenedor de scroll: si el contenido cabe, se ve exactamente
   igual que antes; si no cabe (muchas columnas en pantalla angosta), se
   puede desplazar horizontalmente en vez de romper el layout de toda la
   página.

   Corrección de la auditoría interna (7.1 / R12) — LO IMPORTANTE ES EL
   @media, no las tres propiedades de adentro. Antes esta regla estaba
   suelta, fuera de toda consulta de medios, así que también se aplicaba
   en escritorio, y ahí hace daño: "display:block" sobre un <table> deja
   de ser una tabla y pasa a ser una caja normal, con la tabla de verdad
   metida adentro encogiéndose a su contenido. El "width:100%" de la
   regla de más arriba (línea ~534) se lo queda la CAJA, no la tabla, así
   que la caja ocupa todo el ancho y la tabla se dibuja angosta y pegada
   a la izquierda.

   Medido con Chromium el 8 de agosto de 2026, contenedor de 1200 px:
   la caja medía 1200 px pero la fila dibujada solo 345 px. Eso en las
   ~60 tablas del sistema.

   El segundo daño era menos visible y más molesto: "overflow-x:auto"
   convierte la tabla en su propio contenedor de desplazamiento, y un
   encabezado "position:sticky" se pega al contenedor que lo contiene.
   El del carrito del punto de venta estaba pensado para pegarse a
   .pv-ticket__scroll (ver más arriba), pero pasó a pegarse a la tabla
   misma — que crece con el contenido y nunca se desplaza. Medido igual:
   al bajar 400 px dentro del carrito, el encabezado se iba a -399 px, o
   sea se perdía de vista, en vez de quedarse arriba.

   Por eso el arreglo son dos cosas: encerrar la regla en el mismo corte
   de 960 px que ya usa el punto de venta para apilarse (ver línea 1060),
   y dejar al carrito FUERA de ella incluso en pantalla angosta, para que
   su encabezado sticky funcione siempre. Por debajo de 960 px la
   protección original sigue intacta: es ahí donde de verdad hacía falta
   ("en tablet vertical desbordan"), no en un monitor. */
@media (max-width: 960px) {
    .tabla {
        display: block;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }

    /* Va DESPUÉS de .tabla a propósito: misma especificidad (una clase
       cada uno), así que gana la última. El carrito prefiere que su
       encabezado se quede fijo mientras se desplaza la lista de
       productos antes que poder correrse de lado — con el punto de venta
       ya apilado a una sola columna en este tamaño, la tabla tiene todo
       el ancho de la pantalla y no lo necesita. */
    .pv-carrito-tabla {
        display: table;
        overflow-x: visible;
    }
}

/* --- Opciones con su consecuencia a la vista (Corrección de la auditoría 2,
   R3): la pregunta "¿salió dinero del cajón?" de ventas/anular.html decide
   si el cierre de caja descuenta esa plata o no. Cada opción muestra debajo
   lo que va a pasar, en pesos, dentro de una caja pulsable grande — para que
   nadie la conteste sin leerla y para que sea difícil marcar la equivocada
   por error. --- */
.opcion-consecuencia {
    display: block;
    padding: 0.8rem 0.9rem;
    margin-bottom: 0.6rem;
    border: 1px solid var(--color-borde);
    border-radius: 6px;
    cursor: pointer;
    font-weight: normal;
}

.opcion-consecuencia:hover {
    border-color: var(--color-primario);
    background: var(--color-fondo);
}

.opcion-consecuencia__titulo {
    display: block;
    font-weight: 600;
}

.opcion-consecuencia__detalle {
    display: block;
    margin-top: 0.3rem;
    margin-left: 1.6rem;
}

.opcion-consecuencia input[type="radio"] {
    width: auto;
    margin-right: 0.4rem;
}

/* =====================================================================
   REDISEÑO VISUAL "CONTRASTE ALTO"  (Gabriel, 8 de agosto de 2026)

   Gabriel pidió "un toque diferente, bonito, que resalte, intuitivo" y
   eligió esta dirección entre cuatro maquetas que se compararon en vivo
   antes de tocar nada.

   Va TODO al final del archivo y sin tocar ninguna regla anterior, a
   propósito: si algo se ve mal, se borra este bloque completo y el
   sistema vuelve exactamente a como estaba. Ningún cambio de aquí toca
   plantillas ni lógica — es solo apariencia.

   Las decisiones que NO son de gusto, sino de seguridad, están marcadas
   con "OJO" más abajo. Vale la pena leerlas antes de mover algo.
   ===================================================================== */

/* --- Encabezado oscuro de cada tarjeta ---------------------------------

   OJO 1: los márgenes negativos son -1.5rem porque ese es el padding de
   .tarjeta (ver la regla original, línea ~348). Si algún día se cambia
   ese padding, hay que cambiar estos dos números o el encabezado dejará
   de llegar a los bordes.

   OJO 2: NO se usa "overflow:hidden" en .tarjeta para redondear la
   esquina, aunque sería lo obvio. Convertiría cada tarjeta en contenedor
   de recorte y cortaría el desplegable del buscador de productos, que
   está posicionado en absoluto dentro de tarjetas de formulario (ver
   .buscador-producto__resultados, línea ~961). El redondeo se hace en el
   propio h2, que no tiene ese efecto secundario.

   OJO 3: se aplica a TODO h2 hijo directo de .tarjeta, no solo al
   primero. Hay tarjetas que agrupan varias secciones con un h2 cada una
   (12 plantillas), y darle barra solo a la primera dejaba la pantalla
   despareja. El :first-child recibe el margen superior negativo para
   quedar al ras; los demás llevan separación arriba para leerse como
   divisores de sección. */
.tarjeta > h2 {
    margin-left: -1.5rem;
    margin-right: -1.5rem;
    margin-bottom: 1.1rem;
    padding: 0.85rem 1.5rem;
    background: #0f172a;
    color: #fff;
    font-size: 0.95rem;
    font-weight: 600;
    letter-spacing: 0.01em;
}

.tarjeta > h2:first-child {
    margin-top: -1.5rem;
    /* 9px y no 10px: el radio de .tarjeta es 10px por fuera del borde de
       1px, así que por dentro son 9. Con 10 se asoma una uña del borde
       gris en cada esquina. */
    border-radius: 9px 9px 0 0;
}

.tarjeta > h2:not(:first-child) {
    margin-top: 1.75rem;
}

/* --- Tablas: el dato pesa más que el título de la columna ------------- */
.tabla th {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 700;
    color: var(--color-texto-ayuda);
    border-bottom: 2px solid var(--color-borde);
    white-space: nowrap;
}

.tabla tbody tr:nth-child(even) {
    background: #f8fafc;
}

.tabla tbody tr:hover {
    background: #e0f2fe;
}

/* Cifras de ancho fijo: sin esto, un "1" ocupa menos que un "8" y las
   columnas de pesos quedan dentadas aunque estén alineadas. */
.tabla,
.tarjeta-resumen__valor {
    font-variant-numeric: tabular-nums;
}

/* Alineación a la derecha de columnas numéricas. La clase se marca en las
   plantillas, celda por celda (fase 2 del rediseño) — mientras tanto esta
   regla simplemente no aplica a nada y no estorba. */
.tabla th.num,
.tabla td.num {
    text-align: right;
}

/* --- Barras de comparación de los reportes --- */
.mini-barra__relleno {
    background: linear-gradient(90deg, #38bdf8, var(--color-primario));
}

/* --- Indicadores de arriba (las tarjetas de resumen) --- */
.tarjeta-resumen {
    position: relative;
    overflow: hidden;
}

.tarjeta-resumen::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    height: 3px;
    background: linear-gradient(90deg, #38bdf8, var(--color-primario));
}

.tarjeta-resumen__etiqueta {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 700;
}

/* --- Menú lateral: más oscuro, y el activo en azul en vez de blanco --- */
.sidebar {
    background: #0f172a;
    --icono-hueco: #0f172a;
}

.sidebar__enlace--activo,
.sidebar__enlace--activo:hover {
    background: var(--color-primario);
    color: #fff;
    --icono-hueco: var(--color-primario);
}

/* --- Impresión: sin barras negras -------------------------------------

   Este bloque va DESPUÉS del @media print original a propósito: a igual
   especificidad gana el último, así que deshace el encabezado oscuro solo
   en papel. Un arqueo o un cierre de turno impreso con una franja negra
   de lado a lado gasta tinta y se ve peor que el original. */
@media print {
    .tarjeta > h2 {
        background: transparent;
        color: var(--color-texto);
        border-bottom: 1px solid #ccc;
        margin-left: 0;
        margin-right: 0;
        padding-left: 0;
        padding-right: 0;
    }

    .tarjeta > h2:first-child {
        margin-top: 0;
    }

    .tabla tbody tr:nth-child(even) {
        background: transparent;
    }

    .mini-barra__relleno {
        background: #666;
    }

    .tarjeta-resumen::before {
        display: none;
    }
}

/* --- Campos de dinero: el "$" pegado al campo y el eco de lo escrito ----

   Gabriel, 8 de agosto de 2026, al abrir un turno: "me muestra el campo en
   número normal y no en pesos, ¿no debería ser en $ para minimizar
   errores?". Tenía razón, y al buscar gemelos resultó que NINGÚN campo de
   dinero del sistema traía el símbolo.

   Es puramente visual: el <input> sigue siendo el mismo type="number" que
   arma Django y se envía igual. Ver el comentario en
   ventas/templates/ventas/turno_abrir.html sobre por qué NO se ponen
   separadores de miles mientras se escribe. */
.campo-dinero {
    position: relative;
}

.campo-dinero__simbolo {
    position: absolute;
    left: 0.7rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--color-texto-ayuda);
    font-weight: 600;
    /* Sin esto, hacer clic justo encima del "$" no enfoca el campo que hay
       debajo — el símbolo se comería el clic y parecería que el campo no
       responde. */
    pointer-events: none;
}

/* 1.5rem = el 0.7rem del padding original del input + el ancho del "$" y su
   respiro. Si se cambia el padding de input[type="number"] (línea ~891),
   hay que revisar este número. */
.campo-dinero input[type="number"] {
    padding-left: 1.5rem;
}

.campo-dinero__eco {
    margin: 0;
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--color-exito);
}

/* --- Calculadora de billetes y monedas del arqueo de caja ---------------
   (Gabriel, 11 de agosto de 2026). Se usa al abrir y al cerrar turno, desde
   ventas/templates/ventas/_conteo_caja.html. Las casillas son grandes y
   centradas a propósito: esto se llena de pie, contando dinero con una mano,
   a veces en una tablet. */
.conteo-tabla { width: 100%; border-collapse: collapse; margin: .5rem 0 1rem; }
.conteo-tabla thead th {
    font-size: .72rem; text-transform: uppercase; letter-spacing: .04em;
    color: var(--color-texto-ayuda); text-align: left;
    padding: .35rem .5rem; border-bottom: 1px solid #dcdfe6;
}
.conteo-cant { text-align: center; width: 6.5rem; }
.conteo-sub { text-align: right; width: 8rem; }
.conteo-grupo td {
    font-size: .72rem; text-transform: uppercase; letter-spacing: .05em;
    font-weight: 700; color: var(--color-texto-ayuda); padding: .7rem .5rem .25rem;
}
.conteo-den { padding: .28rem .5rem; font-variant-numeric: tabular-nums; font-weight: 600; }
.conteo-tabla input {
    width: 100%; text-align: center; font-size: 1.05rem; font-weight: 700;
    padding: .45rem .3rem; border: 1px solid #cfd4dc; border-radius: 8px;
    background: #fff; font-variant-numeric: tabular-nums;
}
.conteo-tabla input:focus { outline: 3px solid rgba(37, 99, 235, .35); border-color: #2563eb; }
/* Las flechitas del input numérico estorban cuando se cuenta rápido: se
   escriben cantidades, no se sube de uno en uno. */
.conteo-tabla input::-webkit-outer-spin-button,
.conteo-tabla input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.conteo-tabla input[type="number"] { -moz-appearance: textfield; }
.conteo-subtotal {
    display: block; text-align: right; padding: .28rem .5rem;
    color: #98a2b3; font-variant-numeric: tabular-nums;
}
.conteo-subtotal--activo { color: inherit; font-weight: 600; }
.conteo-total {
    display: flex; justify-content: space-between; align-items: baseline; gap: 1rem;
    padding: .9rem 1rem; border-radius: 12px; background: #eef4ff;
    border: 1px solid #cddcff; margin-top: .5rem;
}
.conteo-total span:first-child { font-weight: 700; color: #1e40af; }
.conteo-total span:last-child {
    font-size: 1.6rem; font-weight: 800; color: #1e40af; font-variant-numeric: tabular-nums;
}

/* Casilla + botón pegados al total, no arriba de la tabla. */
.conteo-acciones {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: 0.75rem;
    margin-top: 0.85rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--color-borde);
    position: sticky;
    bottom: 0;
    background: var(--color-tarjeta);
    z-index: 2;
}

.conteo-confirmar {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    flex: 1 1 16rem;
    margin: 0;
    padding: 0.5rem 0.65rem;
    background: #fef3c7;
    border: 1px solid #f59e0b;
    border-radius: 8px;
    font-size: 0.85rem;
    font-weight: 600;
    color: #92400e;
    line-height: 1.35;
}

.conteo-confirmar input {
    margin-top: 0.15rem;
    width: 1.15rem;
    height: 1.15rem;
    flex-shrink: 0;
}
@media (max-width: 520px) {
    .conteo-cant { width: 5rem; }
    .conteo-sub { width: 6.5rem; }
    .conteo-tabla input { font-size: 1rem; }
}

/* Desglose de billetes y monedas dentro del reporte de arqueos
   (corrección de la auditoría del arqueo, A3). Va plegado dentro de una
   fila de la tabla: son once denominaciones posibles y desplegarlas
   siempre haría ilegible la vista que se usa todos los días. */
.arqueo-desglose > td { background: #f7f9fc; padding: 0 .75rem .75rem; }
.arqueo-desglose summary {
    cursor: pointer; padding: .55rem 0; font-size: .82rem; font-weight: 600;
    color: var(--color-texto-ayuda);
}
.arqueo-desglose summary:hover { color: inherit; }
.tabla--interior { width: auto; min-width: 30rem; margin: .25rem 0 .5rem; }
.tabla--interior td, .tabla--interior th { font-size: .82rem; padding: .25rem .75rem; }
.tabla--interior td { font-variant-numeric: tabular-nums; }

/* Aviso de venta rechazada y freno por falta de stock, dentro del punto de
   venta (13 de agosto de 2026). La vendedora reportó, a través de Gabriel,
   que cuando una venta se rechaza "no sale ninguna alerta grande visible
   que le diga qué pasó". El mensaje existía, pero era la franja de 0,9rem
   de base.html, arriba de toda la barra del punto de venta — en una tablet,
   fuera de la vista. Estos dos van DENTRO de la pantalla, donde ella mira. */
.pv-rechazo {
    background: #fee2e2;
    border: 2px solid var(--color-error);
    border-radius: 10px;
    padding: 1rem 1.15rem;
    margin-bottom: 1rem;
}
.pv-rechazo__titulo {
    margin: 0 0 .35rem;
    font-size: 1.35rem;
    font-weight: 800;
    color: var(--color-error);
    text-transform: uppercase;
    letter-spacing: .01em;
}
/* Esta línea es la que de verdad importa: quita la duda de "¿quedó cobrado
   o no?", que es peligrosa en las dos direcciones (volver a cobrar y cobrar
   doble, o creer que se cobró y dejar ir al cliente sin pagar). */
.pv-rechazo__calma { margin: 0 0 .5rem; font-weight: 700; color: #7f1d1d; }
.pv-rechazo__motivo { margin: 0; color: #7f1d1d; }

.pv-bloqueo {
    background: #fef3c7;
    border: 2px solid #f59e0b;
    border-radius: 10px;
    padding: .8rem .9rem;
    margin-bottom: .75rem;
}
.pv-bloqueo__titulo {
    margin: 0 0 .5rem;
    font-weight: 800;
    color: #92400e;
}
.pv-bloqueo__fila {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    padding: .35rem 0;
    border-top: 1px solid #fde68a;
}
.pv-bloqueo__fila:first-of-type { border-top: none; }
.pv-bloqueo__texto { color: #92400e; font-size: .9rem; }
.pv-bloqueo__acciones { display: flex; gap: .4rem; flex-wrap: wrap; }
/* Botones pequeños: el arreglo tiene que costar un clic, no una lectura. */
.pv-bloqueo__acciones .boton { padding: .3rem .7rem; font-size: .85rem; }

/* --- Tablero del inicio (23 ago 2026): el panel deja de ser solo un
   menú de atajos. La cifra del día y la curva de la semana van primero;
   los accesos, abajo. El punto de venta no se toca. --- */

.tablero {
    display: flex;
    flex-direction: column;
    gap: 1.35rem;
}

.tablero__saludo {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}

.tablero__saludo h1 {
    margin: 0;
}

.tablero__meta {
    margin: 0.25rem 0 0;
    color: var(--color-texto-ayuda);
    font-size: 0.95rem;
}

.tablero__cobrar {
    display: inline-flex;
    align-items: center;
    gap: 0.55rem;
    background: var(--color-primario);
    color: #fff;
    --icono-hueco: var(--color-primario);
    text-decoration: none;
    font-weight: 700;
    padding: 0.7rem 1.15rem;
    border-radius: 10px;
}

.tablero__cobrar:hover {
    background: var(--color-primario-oscuro);
    --icono-hueco: var(--color-primario-oscuro);
    color: #fff;
}

.tablero__hero {
    display: grid;
    grid-template-columns: minmax(220px, 0.9fr) minmax(0, 1.3fr);
    gap: 1.25rem;
    background: var(--color-tarjeta);
    border: 1px solid var(--color-borde);
    border-radius: 14px;
    padding: 1.25rem 1.4rem 1.1rem;
}

.tablero__etiqueta {
    display: block;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--color-texto-ayuda);
}

.tablero__valor {
    display: block;
    margin-top: 0.2rem;
    font-size: 2.15rem;
    font-weight: 800;
    letter-spacing: -0.03em;
    color: var(--color-primario-oscuro);
    font-variant-numeric: tabular-nums;
    line-height: 1.15;
}

.tablero__valor--suave {
    color: var(--color-texto-ayuda);
    font-weight: 600;
}

.tablero__ayuda {
    display: block;
    margin-top: 0.35rem;
    color: var(--color-texto-ayuda);
    font-size: 0.9rem;
}

.tablero__secundarias {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 1rem;
}

.tablero__chip {
    display: inline-flex;
    align-items: baseline;
    gap: 0.35rem;
    padding: 0.35rem 0.65rem;
    border-radius: 999px;
    background: #eff6ff;
    color: var(--color-primario-oscuro);
    text-decoration: none;
    font-size: 0.82rem;
}

.tablero__chip strong {
    font-variant-numeric: tabular-nums;
}

.tablero__chip--alerta {
    background: #fef3c7;
    color: #92400e;
}

.tablero__curva {
    min-width: 0;
}

.tablero-spark {
    display: block;
    width: 100%;
    height: 88px;
    margin-top: 0.55rem;
    color: var(--color-primario);
}

.tablero-spark__area {
    fill: currentColor;
    opacity: 0.16;
}

.tablero-spark__linea {
    fill: none;
    stroke: currentColor;
    stroke-width: 2.4;
    stroke-linejoin: round;
    stroke-linecap: round;
}

.tablero-spark__dias {
    display: flex;
    justify-content: space-between;
    margin-top: 0.35rem;
    color: var(--color-texto-ayuda);
    font-size: 0.7rem;
    font-variant-numeric: tabular-nums;
}

.tablero__columnas {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 1rem;
}

.tablero__bloque {
    background: var(--color-tarjeta);
    border: 1px solid var(--color-borde);
    border-radius: 12px;
    padding: 1rem 1.1rem 0.85rem;
    overflow-x: auto;
}

.tablero__bloque h2 {
    margin: 0;
    font-size: 1rem;
}

.tablero__bloque-cabeza {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 0.7rem;
}

.tablero__bloque-cabeza a {
    font-size: 0.85rem;
    font-weight: 600;
}

.tablero__atajos-titulo {
    margin: 0.4rem 0 0;
    font-size: 1.05rem;
}

.tablero .accesos-directos {
    grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
    margin-bottom: 0;
}

.tablero .acceso-directo {
    padding: 1rem 0.65rem 0.9rem;
}

.tablero .acceso-directo__icono {
    width: 48px;
    height: 48px;
}

.tablero__accesos {
    background: var(--color-tarjeta);
    border: 1px solid var(--color-borde);
    border-radius: 10px;
    padding: 0.65rem 1rem;
}

.tablero__accesos summary {
    cursor: pointer;
    font-weight: 600;
    color: var(--color-texto-ayuda);
}

.tablero__accesos .tabla {
    margin-top: 0.7rem;
}

@media (max-width: 720px) {
    .tablero__hero {
        grid-template-columns: 1fr;
    }

    .tablero__valor {
        font-size: 1.8rem;
    }
}

@media print {
    .tablero__cobrar,
    .tablero__atajos-titulo,
    .tablero .accesos-directos,
    .tablero__accesos {
        display: none;
    }
}
