/* ------------------------------------------------------------------
   ERP Óptica — estilos propios sobre Bootstrap 5.3

   Dos exigencias que tiran en direcciones distintas y hay que sostener
   a la vez: se usa en mostrador con el cliente delante —texto legible a
   un metro, botones que no se fallan con el dedo— y lo mira el dueño
   para decidir, así que tiene que parecer una herramienta seria.

   La solución es la de siempre: poco color, mucha jerarquía. El marino
   de la marca para el texto y lo primario, el turquesa solo como acento,
   el rojo solo para lo que urge, y el resto en acero diluido.
   ------------------------------------------------------------------ */

:root {
    --erp-sidebar: 252px;

    /*
       Los colores de la marca, tal cual.

       Azul marino para el texto y lo primario, turquesa para el acento, acero
       para bordes y superficies suaves, blanco para el fondo. El azul oscuro y
       el claro no son colores nuevos: son el mismo marino un paso más abajo y
       un paso más arriba, para el degradado de la barra y los estados hover.
    */
    --erp-azul: #033D5D;
    --erp-azul-900: #02293D;
    --erp-azul-claro: #14577C;
    --erp-acento: #38B7C3;
    --erp-acero: #8AA6B5;

    /*
       El acero puro sobre blanco da 2,6:1 de contraste. Sirve para un borde o
       un icono, pero como texto no se lee a un metro del mostrador, que es la
       distancia real de uso. Para texto secundario va el mismo tono llevado a
       5,2:1; se sigue viendo acero, pero se lee.
    */
    --erp-tenue: #52717F;

    --erp-fondo: #FFFFFF;
    --erp-superficie: #FFFFFF;
    /* Acero muy diluido: cabeceras de tabla, filas alternas, zonas apagadas.
       Sobre blanco puro, sin esto no habría forma de separar nada sin dibujar
       una línea en cada sitio. */
    --erp-superficie-suave: #F1F6F8;
    --erp-borde: #DCE7EC;

    /* Alto de la barra de arriba: la usan los bloques que se pegan al
       desplazarse, para no quedar por debajo de ella. */
    --erp-header: 3.4rem;
    --erp-borde-fuerte: #B7CBD6;
    --erp-texto: #033D5D;


    /*
       Bootstrap trae su propio azul (#0d6efd) y lo usa en insignias, enlaces y
       estados. Al lado del marino de la marca se ve como un color prestado de
       otro sistema. Aquí se reapunta a la paleta: se cambia el valor, no el
       componente, así cualquier `text-bg-primary` de cualquier vista ya sale
       en el color correcto sin tocarla.
    */
    --bs-primary: #033D5D;
    --bs-primary-rgb: 3, 61, 93;
    --bs-primary-text-emphasis: #022A40;
    --bs-primary-bg-subtle: #E6EEF3;
    --bs-primary-border-subtle: #B7CBD6;
    --bs-link-color: #14577C;
    --bs-link-color-rgb: 20, 87, 124;
    --bs-link-hover-color: #033D5D;
    --bs-border-color: #DCE7EC;
    --erp-radio: 10px;
    --erp-sombra: 0 1px 2px rgba(3, 61, 93, .06), 0 1px 3px rgba(3, 61, 93, .05);
    --erp-sombra-alta: 0 4px 12px rgba(3, 61, 93, .10);
}

body {
    background-color: var(--erp-fondo);
    color: var(--erp-texto);
    font-size: 0.9375rem;
    /* La pila del sistema: sin descargar nada, en Windows sale Segoe y
       en el celular San Francisco o Roboto. Cualquiera de las tres se
       lee mejor que una webfont que llega tarde. */
    font-family: "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5, h6 {
    letter-spacing: -0.011em;
    color: var(--erp-texto);
}

a { text-decoration-thickness: 1px; text-underline-offset: 2px; }

/* ------------------------------------------------------------- Iconos */

/* Alineados con la línea base del texto: un icono centrado a la caja
   siempre parece flotar medio píxel por encima de la palabra. */
.erp-icono {
    flex: 0 0 auto;
    vertical-align: -0.18em;
}

/* ------------------------------------------------------------ Sidebar */

.erp-sidebar {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    width: var(--erp-sidebar);
    background: linear-gradient(180deg, var(--erp-azul) 0%, var(--erp-azul-900) 100%);
    color: #b9c7d6;
    overflow-y: auto;
    z-index: 1030;
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, .18) transparent;
}

.erp-sidebar::-webkit-scrollbar { width: 6px; }
.erp-sidebar::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, .18);
    border-radius: 3px;
}

.erp-sidebar .erp-marca {
    display: block;
    padding: 1.1rem 1.15rem;
    border-bottom: 1px solid rgba(255, 255, 255, .09);
}

/* El logotipo, no un icono con el nombre al lado: el nombre ya está dentro
   del logo, y escribirlo otra vez lo repetía.

   `aspect-ratio` con la proporción real del archivo (2000×600) reserva su
   altura desde el primer pintado. Sin eso el navegador no sabe cuánto mide
   hasta que el SVG llega, deja el hueco en cero y empuja el menú hacia abajo
   cuando aparece: ese es el salto de un segundo al cargar cada pantalla. */
.erp-sidebar .erp-marca img {
    display: block;
    width: 178px;
    max-width: 100%;
    height: auto;
    aspect-ratio: 2000 / 600;
}

.erp-sidebar .erp-marca small {
    display: block;
    margin-top: .5rem;
    font-size: .72rem;
    font-weight: 400;
    color: #8ba5bf;
    letter-spacing: .02em;
}

.erp-sidebar .nav-link {
    color: #b9c7d6;
    padding: .58rem 1.15rem;
    border-left: 3px solid transparent;
    display: flex;
    align-items: center;
    gap: .7rem;
    font-size: .885rem;
    transition: background .12s ease, color .12s ease;
}

.erp-sidebar .nav-link:hover {
    background: rgba(255, 255, 255, .06);
    color: #fff;
}

.erp-sidebar .nav-link.active {
    background: rgba(255, 255, 255, .1);
    border-left-color: var(--erp-acento);
    color: #fff;
    font-weight: 600;
}

/* Los iconos apagados hasta que la fila importa: así el ojo encuentra
   la sección activa sin leer, que es de lo que se trata. */
.erp-sidebar .nav-link .erp-icono { opacity: .72; }
.erp-sidebar .nav-link:hover .erp-icono,
.erp-sidebar .nav-link.active .erp-icono { opacity: 1; }

/* Submenús: un escalón menos de peso, no una lista aparte. */
.erp-sidebar .nav .nav-link {
    padding-left: 1rem;
    font-size: .845rem;
    border-left-width: 2px;
}

.erp-sidebar .erp-seccion {
    padding: 1.1rem 1.15rem .3rem;
    font-size: .68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .085em;
    color: #6f8aa6;
}

/* --------------------------------------------------------- Contenido */

.erp-contenido {
    margin-left: var(--erp-sidebar);
    min-height: 100vh;
}

.erp-header {
    background: rgba(255, 255, 255, .92);
    backdrop-filter: saturate(180%) blur(8px);
    border-bottom: 1px solid var(--erp-borde);
    padding: .6rem 1.35rem;
    position: sticky;
    top: 0;
    z-index: 1020;
    min-height: var(--erp-header);
}

.erp-buscador {
    max-width: 460px;
    position: relative;
}

.erp-buscador .form-control {
    border-radius: 999px;
    padding-left: 2.35rem;
    background-color: var(--erp-superficie-suave);
    border-color: transparent;
}

.erp-buscador .form-control:focus {
    background-color: #fff;
    border-color: var(--erp-azul-claro);
}

/* La lupa dentro de la caja, no al lado: ocupa cero ancho. */
.erp-buscador .erp-lupa {
    position: absolute;
    left: .8rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--erp-tenue);
    pointer-events: none;
}

@media (max-width: 991.98px) {
    .erp-sidebar {
        transform: translateX(-100%);
        transition: transform .2s ease;
    }
    .erp-sidebar.abierta { transform: translateX(0); }
    .erp-contenido { margin-left: 0; }
}

/* ---------------------------------------------------- Semáforo fechas */

/*
   El color no es decoración: es la única forma de que veinte tarjetas en una
   columna se lean sin leerlas. Rojo se acabó el tiempo, amarillo se está
   acabando, verde va sobrado, gris no hay contra qué medir.

   La franja va a la izquierda y no en el fondo de la tarjeta: pintar la
   tarjeta entera de rojo obliga a bajar el contraste del texto, y esto se lee
   a un metro desde el mostrador.
*/
.erp-rojo { box-shadow: inset 4px 0 0 #dc3545; }
.erp-amarillo { box-shadow: inset 4px 0 0 #f59e0b; }
.erp-verde { box-shadow: inset 4px 0 0 #16a34a; }
.erp-gris { box-shadow: inset 4px 0 0 var(--erp-acero); }

/* El rojo además tiñe apenas el fondo: con la columna llena, la franja sola
   se pierde entre tarjeta y tarjeta. */
.erp-rojo { background: rgba(220, 53, 69, .045); }

/* Cuánto del tramo se lleva gastado, para el trabajo que se mide así. */
.erp-consumo {
    display: inline-block;
    width: 2.5rem;
    height: 4px;
    border-radius: 999px;
    background: var(--erp-borde);
    overflow: hidden;
    vertical-align: middle;
}

.erp-consumo > span { display: block; height: 100%; background: currentColor; }

.erp-vencido { box-shadow: inset 3px 0 0 #dc3545; }
.erp-hoy { box-shadow: inset 3px 0 0 #f59e0b; }
.erp-proximo { box-shadow: inset 3px 0 0 #16a34a; }
.erp-derivado { box-shadow: inset 3px 0 0 #2563eb; }

/* ------------------------------------------------------- Superficies */

.erp-tarjeta {
    background: var(--erp-superficie);
    border: 1px solid var(--erp-borde);
    border-radius: var(--erp-radio);
    box-shadow: var(--erp-sombra);
}

/* Una tarjeta en la que se puede hacer clic tiene que parecerlo antes
   de que el mouse llegue. */
.erp-tarjeta[role="button"],
a > .erp-tarjeta { transition: box-shadow .14s ease, border-color .14s ease; }

.erp-tarjeta[role="button"]:hover,
a:hover > .erp-tarjeta {
    box-shadow: var(--erp-sombra-alta);
    border-color: var(--erp-borde-fuerte);
}

/* Rótulo de dato: pequeño, en versalitas, gris. El número manda. */
.erp-rotulo {
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--erp-tenue);
}

/* Cifras: tabulares para que las columnas cuadren al mirarlas. */
.erp-dato { font-variant-numeric: tabular-nums; }

/* Y las cifras grandes, además, más apretadas: los números por defecto
   dejan un aire que hace parecer que sobra espacio. */
.erp-cifra {
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.02em;
    font-weight: 600;
}

.erp-vacio {
    color: var(--erp-tenue);
    text-align: center;
    padding: 2.25rem 1rem;
    font-size: .875rem;
}

/* ------------------------------------------------------------ Tablas */

.table { --bs-table-color: var(--erp-texto); }

.table > thead > tr > th {
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .045em;
    text-transform: uppercase;
    color: var(--erp-tenue);
    background: var(--erp-superficie-suave);
    border-bottom-color: var(--erp-borde);
    white-space: nowrap;
}

.table > tbody > tr > td { border-color: var(--erp-borde); }
.erp-tarjeta > .table-responsive > .table > tbody > tr:last-child > td { border-bottom: 0; }

/* ---------------------------------------------------------- Detalles */

.progress {
    background-color: var(--erp-superficie-suave);
    border-radius: 999px;
}

.progress-bar { border-radius: 999px; }

.badge {
    font-weight: 600;
    letter-spacing: .01em;
    padding: .34em .6em;
}

.form-label { font-weight: 500; color: #33475b; }
.form-text { color: var(--erp-tenue); }

.form-control:focus, .form-select:focus {
    border-color: var(--erp-azul-claro);
    box-shadow: 0 0 0 .2rem rgba(2, 62, 94, .14);
}

.btn { font-weight: 500; }
.btn-primary { --bs-btn-bg: var(--erp-azul); --bs-btn-border-color: var(--erp-azul); }
.btn-primary:hover { --bs-btn-hover-bg: var(--erp-azul-claro); --bs-btn-hover-border-color: var(--erp-azul-claro); }

/* Botones de mostrador: cómodos con mouse y con pantalla táctil. */
.btn-mostrador {
    padding: .58rem 1.05rem;
    font-size: .95rem;
}

.nav-pills .nav-link {
    color: var(--erp-tenue);
    font-weight: 500;
    font-size: .875rem;
    padding: .4rem .85rem;
    display: inline-flex;
    align-items: center;
    gap: .4rem;
}

.nav-pills .nav-link:hover { color: var(--erp-texto); background: #e8edf3; }
.nav-pills .nav-link.active { background: var(--erp-azul); color: #fff; }

.modal-content { border: 0; border-radius: var(--erp-radio); }
.modal-header, .modal-footer { border-color: var(--erp-borde); }

/* --------------------------------------------------------- Impresión */

@media print {
    .erp-sidebar, .erp-header, .btn, .nav-pills { display: none !important; }
    .erp-contenido { margin-left: 0; }
    .erp-tarjeta { box-shadow: none; border-color: #ccc; }
    body { background: #fff; font-size: 11pt; }
}

/* ------------------------------------------------------- Acceso */

/* El fondo del ingreso es el azul de la marca, con un halo del turquesa
   arriba para que no sea un rectángulo plano. */
.erp-acceso {
    min-height: 100vh;
    padding: 2rem 1rem;
    background:
        radial-gradient(900px 420px at 50% -10%, rgba(56, 184, 196, .22), transparent 70%),
        linear-gradient(180deg, var(--erp-azul) 0%, var(--erp-azul-900) 100%);
}

.erp-acceso-logo {
    width: 300px;
    max-width: 100%;
    height: auto;
    aspect-ratio: 2000 / 600;
}

/* ------------------------------------------- Tablero: tira de resumen */

/* ------------------------------------------------------------------
   Los dos carruseles del tablero

   Misma mecánica para la tira de resumen y para las bandejas: mientras las
   cuatro no quepan, se deslizan en horizontal y la siguiente asoma cortada
   por el borde derecho.

   Ese trozo visible es todo el aviso que hace falta. Un carrusel que corta
   justo en el límite parece una lista completa, y nadie desliza lo que no
   sabe que sigue.
   ------------------------------------------------------------------ */

.erp-resumen,
.erp-bandejas {
    display: grid;
    grid-auto-flow: column;
    gap: .75rem;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
    /* Aire a los lados para que la sombra de la tarjeta no se recorte. */
    padding: .25rem .25rem .75rem;
    margin: -.25rem -.25rem 0;
    -webkit-overflow-scrolling: touch;
}

.erp-resumen > *,
.erp-bandeja { scroll-snap-align: start; }

/* Las cuatro bandejas terminan a la misma altura: el pie de «Ver todas»
   alineado es lo que hace que la fila se lea como una fila y no como
   cuatro tarjetas sueltas de distinto largo. */
.erp-bandeja { display: flex; min-width: 0; }
.erp-bandeja > .erp-tarjeta { width: 100%; }

/* La barra de desplazamiento, discreta pero presente: en un escritorio sin
   pantalla táctil es la otra señal de que hay más a la derecha. */
.erp-resumen::-webkit-scrollbar,
.erp-bandejas::-webkit-scrollbar { height: 6px; }

.erp-resumen::-webkit-scrollbar-thumb,
.erp-bandejas::-webkit-scrollbar-thumb {
    background: var(--erp-borde-fuerte);
    border-radius: 3px;
}

.erp-resumen, .erp-bandejas {
    scrollbar-width: thin;
    scrollbar-color: var(--erp-borde-fuerte) transparent;
}

/* --- Resumen: cuánto se ve de cada tarjeta en cada ancho --- */

/*
   El ancho va a secas y no como `minmax(0, X%)`: con un mínimo de cero, el
   grid encoge las cuatro pistas hasta que caben dentro del contenedor —que
   es exactamente lo contrario de lo que se busca— y en vez de un carrusel
   sale una fila apretada. Con el porcentaje solo, la pista mide eso y la
   fila se desborda, que es lo que hace aparecer el desplazamiento.
*/

/* Celular: una y media. */
.erp-resumen { grid-auto-columns: 62%; }

/* Tablet: tres y media, que es la proporción que deja claro que falta una. */
@media (min-width: 768px) {
    .erp-resumen { grid-auto-columns: 28%; }
}

/* Escritorio: las cuatro, sin nada que deslizar. */
@media (min-width: 1400px) {
    .erp-resumen {
        grid-auto-flow: row;
        grid-template-columns: repeat(4, 1fr);
        overflow: visible;
    }
}

/* --- Bandejas: lo mismo, con columnas más anchas --- */

/* Celular: una entera y el filo de la siguiente. */
.erp-bandejas { grid-auto-columns: 88%; }

/* Tablet: dos y un pedazo de la tercera. */
@media (min-width: 768px) {
    .erp-bandejas { grid-auto-columns: 43%; }
}

@media (min-width: 1400px) {
    .erp-bandejas {
        grid-auto-flow: row;
        grid-template-columns: repeat(4, 1fr);
        overflow: visible;
    }
}

.erp-resumen-tarjeta {
    display: flex;
    align-items: center;
    gap: .85rem;
    padding: .9rem 1rem;
    background: var(--erp-superficie);
    border: 1px solid var(--erp-borde);
    border-radius: var(--erp-radio);
    box-shadow: var(--erp-sombra);
    color: inherit;
    scroll-snap-align: start;
    transition: box-shadow .14s ease, border-color .14s ease;
}

.erp-resumen-tarjeta:hover {
    box-shadow: var(--erp-sombra-alta);
    border-color: var(--erp-borde-fuerte);
    color: inherit;
}

/* El icono en un disco del mismo color que la cifra, muy rebajado: marca
   de qué va la tarjeta sin competir con el número. */
.erp-resumen-icono {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 46px;
    height: 46px;
    border-radius: 50%;
    background: currentColor;
}

.erp-resumen-icono > svg { color: #fff; }
.erp-resumen-icono.text-primary { background: #e7effa; }
.erp-resumen-icono.text-primary > svg { color: var(--erp-azul-claro); }
.erp-resumen-icono.text-success { background: #e4f4ec; }
.erp-resumen-icono.text-success > svg { color: #15803d; }
.erp-resumen-icono.text-warning { background: #fdf1dd; }
.erp-resumen-icono.text-warning > svg { color: #b45309; }
.erp-resumen-icono.text-danger { background: #fbe9e9; }
.erp-resumen-icono.text-danger > svg { color: #b91c1c; }

.erp-resumen-texto { min-width: 0; }

.erp-resumen-valor {
    display: block;
    font-size: 1.5rem;
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
}

.erp-resumen-titulo {
    display: block;
    font-weight: 600;
    font-size: .9rem;
    color: var(--erp-texto);
}

.erp-resumen-nota {
    display: block;
    font-size: .78rem;
    color: var(--erp-tenue);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ------------------------------------------------ Tablero: bandejas */

/* Las columnas no crecen con la más larga: cada una se desplaza por dentro
   y la fila conserva una altura que cabe en pantalla. Con cuarenta órdenes
   por llevar, sin esto la fila mide tres pantallas y las otras tres
   bandejas quedan como una tira de aire. */
@media (min-width: 1400px) {
    .erp-bandeja-lista {
        max-height: 26rem;
        overflow-y: auto;
    }
}

/* --------------------------------------------- Tablero: tarjeta de orden */

/* La tarjeta entera abre el popup, así que tiene que parecer pulsable antes
   de que el mouse llegue. En táctil no hay hover: por eso además el bloque
   es grande y las acciones van separadas en su esquina. */
.erp-orden[role="button"] { cursor: pointer; transition: background .12s ease; }
.erp-orden[role="button"]:hover { background: var(--erp-superficie-suave); }

.erp-orden[role="button"]:focus-visible {
    outline: 2px solid var(--erp-azul-claro);
    outline-offset: -2px;
}

/* Los formularios de las acciones no deben separar nada: son dos botones
   pegados en la esquina, no dos bloques. */
.erp-orden form { display: inline; margin: 0; }

/* ------------------------------------------------ Avisos que se van solos */

/* Abajo a la derecha: fuera del recorrido de la vista —que va de arriba a la
   izquierda hacia el contenido— y sin empujar nada. Una franja encima del
   contenido movía la pantalla entera cada vez que se guardaba algo. */
.erp-avisos {
    position: fixed;
    right: 1rem;
    bottom: 1rem;
    z-index: 1080;
    display: flex;
    flex-direction: column;
    gap: .5rem;
    max-width: min(380px, calc(100vw - 2rem));
    pointer-events: none;
}

.erp-aviso {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: .6rem;
    padding: .8rem 2.2rem .8rem .9rem;
    background: var(--erp-superficie);
    border: 1px solid var(--erp-borde);
    border-radius: var(--erp-radio);
    box-shadow: 0 8px 24px rgba(16, 35, 55, .14);
    font-size: .9rem;
    overflow: hidden;
    pointer-events: auto;
    transition: opacity .25s ease, transform .25s ease;
}

.erp-aviso-saliendo { opacity: 0; transform: translateY(.5rem); }

.erp-aviso-icono { flex: 0 0 auto; margin-top: .1rem; }
.erp-aviso-exito .erp-aviso-icono { color: #15803d; }
.erp-aviso-error .erp-aviso-icono { color: #b91c1c; }

.erp-aviso-error { border-color: #f0c2c2; }

/* Ni verde ni rojo: se guardó, pero queda algo por hacer. */
.erp-aviso-aviso .erp-aviso-icono { color: #B45309; }

.erp-aviso-aviso { border-color: #f5d9a8; }

.erp-aviso-texto { min-width: 0; }

.erp-aviso-cerrar {
    position: absolute;
    top: .35rem;
    right: .5rem;
    border: 0;
    background: none;
    font-size: 1.15rem;
    line-height: 1;
    color: var(--erp-tenue);
    cursor: pointer;
    padding: .15rem .3rem;
}

.erp-aviso-cerrar:hover { color: var(--erp-texto); }

/* La barrita del tiempo que queda: dice cuánto falta sin decirlo. */
.erp-aviso-barra {
    position: absolute;
    left: 0;
    bottom: 0;
    height: 3px;
    width: 100%;
    background: #15803d;
    transition-property: width;
    transition-timing-function: linear;
}

.erp-aviso-barra.corriendo { width: 0; }

/* En celular ocupa el ancho y va arriba: abajo lo tapa el teclado y los
   botones del sistema. */
@media (max-width: 575.98px) {
    .erp-avisos {
        right: .75rem;
        left: .75rem;
        bottom: auto;
        top: .75rem;
        max-width: none;
    }
    .erp-aviso-saliendo { transform: translateY(-.5rem); }
}

@media (prefers-reduced-motion: reduce) {
    .erp-aviso, .erp-aviso-barra { transition: none; }
}

/* ------------------------------------------------------------------
   La línea de etapas de un trabajo

   Cuatro puntos con la fecha en que se cumplió cada uno. Responde de un
   vistazo la única pregunta que se hace al abrir un trabajo: ¿dónde va?

   La línea coloreada llega hasta donde llegó el trabajo. Se lee la
   distancia, no el texto: media línea pintada es «va por la mitad» sin
   que nadie tenga que leer un estado.
   ------------------------------------------------------------------ */
.erp-pasos {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    gap: 0;
    margin: 0;
    padding: 0;
    list-style: none;
}

.erp-paso {
    position: relative;
    text-align: center;
    padding-top: .25rem;
}

/* La barra que une un punto con el anterior. Va detrás del círculo. */
.erp-paso::before {
    content: "";
    position: absolute;
    top: 1.45rem;
    right: 50%;
    left: -50%;
    height: 2px;
    background: var(--erp-borde);
}

.erp-paso:first-child::before { display: none; }
.erp-paso-hecho::before { background: var(--erp-acento); }

.erp-paso-icono {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 50%;
    background: var(--erp-superficie-suave);
    border: 2px solid var(--erp-borde);
    color: var(--erp-acero);
}

.erp-paso-hecho .erp-paso-icono {
    background: var(--erp-acento);
    border-color: var(--erp-acento);
    color: #fff;
}

/* El punto donde está AHORA el trabajo, que es distinto de «ya pasó por
   aquí»: un aro alrededor, para encontrarlo sin contar círculos. */
.erp-paso-actual .erp-paso-icono {
    box-shadow: 0 0 0 4px rgba(56, 183, 195, .22);
}

.erp-paso-texto {
    display: block;
    margin-top: .35rem;
    font-size: .8125rem;
    font-weight: 600;
    color: var(--erp-tenue);
    line-height: 1.2;
}

.erp-paso-hecho .erp-paso-texto { color: var(--erp-texto); }

.erp-paso-fecha {
    display: block;
    font-size: .75rem;
    color: var(--erp-tenue);
    font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------------
   Los tres botones de avance

   Se ven los tres siempre, y el aspecto dice en cuál va el trabajo: los
   cumplidos apagados, el siguiente encendido, los que aún no tocan
   deshabilitados. Esconder los pasados haría que el botón cambiara de
   sitio en cada avance, y el dedo ya aprendió dónde estaba.
   ------------------------------------------------------------------ */
.erp-avance { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; }

.erp-avance .btn { flex: 1 1 auto; }

/* Un paso ya dado: sigue visible, pero no invita a pulsarlo. */
.erp-avance .btn.erp-hecho {
    background: var(--erp-superficie-suave);
    border-color: var(--erp-borde);
    color: var(--erp-tenue);
    pointer-events: none;
}

/* Un paso que todavía no toca: no se puede saltar la fila. */
.erp-avance .btn.erp-bloqueado {
    background: transparent;
    border-color: var(--erp-borde);
    color: var(--erp-acero);
    pointer-events: none;
}

.erp-avance .erp-deshacer { flex: 0 0 auto; }

/* ------------------------------------------------------------------
   Tablet y celular

   El sistema se usa de pie, con el cliente delante y a menudo con una
   sola mano. Lo que cambia en pantalla chica no es solo el ancho: es
   dónde llega el pulgar y qué se puede fallar al tocar.
   ------------------------------------------------------------------ */

/* La barra de acciones del celular, fija al pie.

   Los mismos dos botones que en escritorio viven en el encabezado. Aquí
   abajo porque es la zona a la que el pulgar llega sin recolocar la mano. */
.erp-barra-movil {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    /* Justo por debajo de la barra lateral: con el menú abierto, el menú
       manda. Y por debajo de los diálogos, que están en 1055. */
    z-index: 1025;
    display: flex;
    gap: .6rem;
    padding: .65rem .75rem;
    /* Con el teclado o la barra del navegador, el área segura del iPhone
       se come el último centímetro: sin esto los botones quedan debajo. */
    padding-bottom: calc(.65rem + env(safe-area-inset-bottom, 0px));
    background: var(--erp-superficie);
    border-top: 1px solid var(--erp-borde);
    box-shadow: 0 -2px 10px rgba(3, 61, 93, .07);
}

.erp-barra-movil .btn {
    flex: 1 1 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .4rem;
    /* 44 px es el mínimo para acertar con el dedo sin mirar. */
    min-height: 44px;
    font-weight: 600;
    white-space: nowrap;
}

/* El contenido termina antes de la barra: si no, la última fila de
   cualquier tabla queda tapada y parece que falta información. */
@media (max-width: 767.98px) {
    body { padding-bottom: 4.5rem; }
}

@media (max-width: 767.98px) {
    /* El encabezado en dos líneas: el buscador necesita el ancho entero
       y los controles no caben a su lado sin encogerse a la mitad. */
    .erp-header {
        flex-wrap: wrap;
        padding: .55rem .75rem;
        gap: .5rem !important;
    }

    .erp-buscador { max-width: none; flex: 1 1 100%; order: 3; }

    /* Los desplegables del encabezado no pueden ser más anchos que la
       pantalla: en un teléfono de 360 px se salían por el borde. */
    .dropdown-menu { max-width: calc(100vw - 1.5rem); }

    /* Los tres avances de un trabajo, uno por línea. Apretados en fila se
       leen «Ya lo…», «Ya lo…», y no se distingue cuál es cuál. */
    .erp-avance .btn,
    .erp-avance form { flex: 1 1 100%; }
    .erp-avance .erp-deshacer { flex: 0 0 auto; }

    /* La línea de etapas cabe, pero justa: se le quita peso al texto y se
       deja que la fecha baje de línea antes que desbordar. */
    .erp-paso-texto { font-size: .72rem; }
    .erp-paso-fecha { font-size: .68rem; }
    .erp-paso-icono { width: 2.1rem; height: 2.1rem; }
    .erp-paso::before { top: 1.25rem; }

    /* Los diálogos ocupan el ancho útil: un modal centrado con márgenes de
       escritorio deja el formulario en una columna de dedo y medio. */
    .modal-dialog { margin: .5rem; }

    /* Botones y campos algo más altos: se tocan, no se apuntan con el ratón. */
    .btn { min-height: 38px; }
    .form-control, .form-select { min-height: 38px; }
}

/* En tablet la barra lateral ya se pliega (arriba, en 991.98px). Lo que
   falta aquí es que las rejillas de dos columnas no queden en dos
   columnas de nada: por debajo de 992 px casi todo pasa a una. */
@media (max-width: 991.98px) {
    .erp-header .erp-buscador { max-width: 100%; }
}

/* Red de seguridad contra el desbordamiento lateral.

   El caso real: un correo largo, un modelo de montura sin espacios o el
   nombre completo de un cliente con cuatro apellidos. Dentro de una fila
   flex, ese texto no se parte y empuja la fila hasta que la página entera
   se va de ancho — y en un teléfono eso se nota en todas las pantallas a
   la vez, porque el ancho lo fija el contenido más largo de la página.

   Dos reglas lo cubren: que las palabras largas puedan partirse, y que un
   hijo de flex pueda encogerse por debajo de su contenido (que es lo que
   `min-width: auto` le impide por defecto). */
.erp-tarjeta { overflow-wrap: break-word; }

@media (max-width: 767.98px) {
    .erp-tarjeta .text-truncate { min-width: 0; }
    .erp-tarjeta .flex-grow-1 { min-width: 0; }
}

/* El fondo oscuro que acompaña al menú desplegado.

   Es lo que permite cerrarlo tocando fuera —lo primero que intenta
   cualquiera— y de paso dice sin palabras que lo de detrás no responde
   mientras el menú esté encima. */
.erp-fondo-menu {
    position: fixed;
    inset: 0;
    z-index: 1029;
    background: rgba(2, 41, 61, .45);
    /* Que el menú se abra por encima de un fondo ya oscurecido y no de un
       salto de blanco a negro. */
    animation: erp-aparece .16s ease;
}

@keyframes erp-aparece { from { opacity: 0; } to { opacity: 1; } }

/* Con el menú abierto, la página de detrás no se mueve: al cerrarlo, uno
   aparecía en un sitio distinto del que había dejado. */
body.erp-sin-scroll { overflow: hidden; }

@media (prefers-reduced-motion: reduce) {
    .erp-fondo-menu { animation: none; }
}

/* El número de cada paso de la cotización.

   No es decoración: dice el orden en que se pregunta —montura, tipo de luna,
   protecciones—, que es el orden de la conversación real en el mostrador. */
.erp-paso-numero {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.35rem;
    height: 1.35rem;
    margin-right: .25rem;
    border-radius: 50%;
    background: var(--erp-acento);
    color: #fff;
    font-size: .72rem;
    font-weight: 700;
}

/* Red de seguridad para la paginación.

   Un SVG sin ancho ni alto no se queda pequeño: se estira hasta llenar lo que
   le den. Con la plantilla de Tailwind puesta por error, las flechas de
   «anterior» y «siguiente» ocupaban la pantalla entera y tapaban la lista.

   La plantilla ya es la de Bootstrap, así que esto no debería hacer falta
   nunca. Está por si alguien vuelve a publicar las vistas de paginación con
   clases de otro framework: un icono grande de más se nota, uno que ocupa la
   pantalla deja la pantalla inservible. */
.pagination svg,
.page-link svg {
    width: 1rem;
    height: 1rem;
    vertical-align: -.15em;
}

/* ------------------------------------------------------------------
   El signo de interrogación

   Reemplaza a los recuadros de explicación que había encima de cada
   sección. En escritorio estorbaban; en un celular ocupaban media
   pantalla y empujaban el trabajo hacia abajo, así que había que
   deslizar para llegar a lo que se venía a hacer.

   Va apagado y solo se enciende al pasar por encima o al enfocarlo:
   está para quien lo busca, no para llamar la atención de quien ya
   sabe lo que hace.
   ------------------------------------------------------------------ */
.erp-ayuda-caja { display: inline-flex; vertical-align: middle; }

.erp-ayuda {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* Botón chico a la vista, área de toque de 32 px: en un celular hay
       que poder acertarle sin apuntar. */
    width: 32px;
    height: 32px;
    /*
       Y ese área de toque NO puede crecer la línea donde vive.

       Dentro de una etiqueta —«Costo ?»— los 32 px hacían esa etiqueta más
       alta que la de al lado, y los dos campos del formulario dejaban de
       alinearse: parecía que el signo hubiera empujado medio bloque hacia
       abajo. El margen negativo devuelve la altura sobrante sin quitar ni un
       píxel de zona tocable.
    */
    margin: -8px 0;
    padding: 0;
    border: 0;
    background: none;
    color: var(--erp-acero);
    cursor: pointer;
    transition: color .12s ease;
}

/* La caja alinea el signo con la línea base del texto al que acompaña, no
   con la caja entera: centrado a la caja siempre parece flotar. */
.erp-ayuda-caja { vertical-align: middle; }

.erp-ayuda svg { width: 15px; height: 15px; }
.erp-ayuda:hover { color: var(--erp-azul-claro); }

.erp-ayuda:focus-visible {
    outline: 2px solid var(--erp-azul-claro);
    outline-offset: 2px;
    border-radius: 50%;
}

/* Dentro de una cabecera oscura o de color, hereda el color de al lado. */
.erp-ayuda.heredado { color: inherit; opacity: .65; }
.erp-ayuda.heredado:hover { opacity: 1; }

/* ------------------------------------------------------------------
   Pestañas que se deslizan

   Siete pestañas no caben en un celular. Envueltas en dos o tres filas
   se ven amontonadas y se pierde cuál está activa; en una sola línea
   que se desliza, se recorta la siguiente por el borde derecho y eso
   dice «hay más» sin ningún cartel.

   Es la misma mecánica de las bandejas del tablero, a propósito: una
   cosa que se desliza se aprende una vez.
   ------------------------------------------------------------------ */
/* `.nav` de Bootstrap trae `flex-wrap: wrap`. Aquí se pisa con la misma
   fuerza y ganando por orden —esta hoja se carga después—, pero se repite
   con !important porque es la regla de la que depende todo lo demás: si un
   día vuelve a envolver, las pestañas se apilan y no se ve cuál está activa. */
.erp-pestanas {
    display: flex !important;
    flex-wrap: nowrap !important;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
    gap: .15rem;
    border-bottom: 1px solid var(--erp-borde);
    /* Sin barra de desplazamiento visible: en táctil no hace falta y en
       escritorio robaría altura a una fila que ya es baja. */
    scrollbar-width: none;
}

.erp-pestanas::-webkit-scrollbar { display: none; }

/* Los hijos que se estiran son los <li>, no los enlaces. Sin fijarlos,
   el navegador los encoge para que quepan y la fila se parte igual
   aunque el contenedor diga que no envuelva. */
.erp-pestanas > .nav-item {
    flex: 0 0 auto;
    scroll-snap-align: start;
}

.erp-pestanas .nav-link {
    flex: 0 0 auto;
    scroll-snap-align: start;
    white-space: nowrap;
    border: 0;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    color: var(--erp-tenue);
    padding: .6rem .85rem;
    font-size: .9rem;
}

.erp-pestanas .nav-link:hover { color: var(--erp-azul-claro); }

.erp-pestanas .nav-link.active {
    color: var(--erp-azul);
    border-bottom-color: var(--erp-acento);
    background: transparent;
    font-weight: 600;
}

/* ------------------------------------------------------------------
   El acordeón del catálogo

   Antes, entrar a una pestaña desplegaba todas sus listas a la vez.
   En «Monturas» son cinco listas abiertas de golpe: en un celular eso
   son varias pantallas de desplazamiento antes de encontrar la que se
   venía a tocar.

   Cerrado, la pestaña es un índice de una pantalla. Se abre lo que se
   necesita y se sabe siempre en qué sección se está.
   ------------------------------------------------------------------ */
.erp-listas .accordion-button {
    font-weight: 600;
    padding: .85rem 1rem;
}

.erp-listas .accordion-button:not(.collapsed) {
    background: var(--erp-superficie-suave);
    color: var(--erp-azul);
    box-shadow: none;
}

.erp-listas .accordion-button:focus {
    box-shadow: none;
    border-color: var(--erp-borde);
}

/* El contador va DELANTE del nombre. Al final de la fila quedaba a
   mil pixeles del texto al que pertenece, y eso deja de leerse como
   una fila: son dos cosas sueltas en los dos extremos. */
.erp-listas .cuantas {
    min-width: 1.9rem;
    text-align: center;
    margin-right: .55rem;
    font-weight: 400;
}

/* ------------------------------------------------------------------
   Las pantallas de configuración

   Siete listas cortas estiradas a 1600 px no se leen mejor: separan lo
   que va junto. El nombre quedaba pegado al borde izquierdo y su número
   a mil pixeles de distancia, y eso deja de leerse como una fila.

   Pegado a la izquierda y no centrado: el ojo ya viene de la barra
   lateral, y centrar el contenido lo obligaría a saltar al medio cada
   vez que cambia de pantalla.
   ------------------------------------------------------------------ */
.erp-config { max-width: 62rem; }

/* ------------------------------------------------------------------
   Un diálogo encima de otro

   La ayuda se abre desde dentro del diálogo de editar, y los dos son
   dos hojas blancas: al aparecer la segunda no se distinguía cuál
   estaba encima ni cuál cerraba la equis.

   Dos señales, las dos necesarias. El fondo se oscurece más —el
   segundo velo se suma al primero— y el diálogo de arriba lleva su
   propia sombra, más profunda. Con una sola no basta: en una pantalla
   con brillo, el oscurecido extra apenas se nota.
   ------------------------------------------------------------------ */
.modal-backdrop ~ .modal-backdrop.show { opacity: .62; }

#modalAyuda .modal-content {
    border: 1px solid var(--erp-borde-fuerte);
    box-shadow: 0 24px 60px rgba(2, 41, 61, .42);
}

/* Y el título en el color de acento, para que se lea como «esto es otra
   cosa» y no como una continuación del formulario de debajo. */
#modalAyuda .modal-title { color: var(--erp-azul-claro); }

/* ── Fichas de selección múltiple ────────────────────────────────────────
   Características y etiquetas. En celular un <select multiple> obliga a
   mantener presionado para marcar varias y nadie lo descubre solo; esto es
   una casilla normal con un área de toque de 38 px.

   La lista completa vive dentro del desplegable (.erp-multi): aquí abajo
   solo quedan las elegidas, que son las que importan. Seis opciones se
   veían bien sueltas, pero la lista crece y entonces ocupa media pantalla
   antes de que el vendedor haya escrito nada. */
.erp-fichas {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
}

.erp-ficha {
    display: inline-flex;
    align-items: center;
    min-height: 38px;
    padding: .35rem .75rem;
    border: 1px solid var(--bs-border-color);
    border-radius: 999px;
    background: #fff;
    font-size: .875rem;
    line-height: 1.2;
    cursor: pointer;
    user-select: none;
    transition: background-color .12s, border-color .12s, color .12s;
}

/* La casilla se oculta pero sigue existiendo: es la que se envía y la que
   recibe el foco del teclado. */
.erp-ficha input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.erp-ficha:has(input:checked) {
    background: var(--erp-azul);
    border-color: var(--erp-azul);
    color: #fff;
}

.erp-ficha:has(input:focus-visible) {
    outline: 2px solid var(--erp-acento);
    outline-offset: 2px;
}

/* En la ficha del producto las características y las etiquetas se leen
   como texto separado por puntos, no como pastillas: cinco pastillas
   ocupaban más que toda la ficha y competían con el precio, que es lo
   que de verdad se viene a mirar. Por eso aquí ya no hay estilo de
   pastilla de solo lectura. */

/* ------------------------------------------------------------------
   El desplegable de selección múltiple

   Se ve como un desplegable normal porque hace lo mismo que uno; lo
   único distinto es que se pueden marcar varias.
   ------------------------------------------------------------------ */
.erp-multi-barra {
    /* Sin .dropdown-toggle a propósito: la flecha ya la pone form-select
       y dos flechas seguidas se leen como un error de dibujo. */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.erp-multi-barra:focus {
    box-shadow: 0 0 0 .2rem rgba(56, 183, 195, .25);
    border-color: var(--erp-acento);
}

.erp-multi-panel {
    width: 100%;
    min-width: 15rem;
    padding: 0;
    overflow: hidden;
}

/* Alto máximo con desplazamiento propio: con treinta opciones el panel
   taparía la pantalla entera y no se llegaría al botón de guardar. */
.erp-multi-lista {
    max-height: 45vh;
    overflow-y: auto;
    padding: .25rem 0;
}

.erp-multi-opcion {
    display: flex;
    align-items: center;
    gap: .6rem;
    min-height: 42px;
    padding: .3rem 1rem;
    cursor: pointer;
    font-size: .9rem;
}

.erp-multi-opcion:hover {
    background: var(--erp-superficie-suave);
}

.erp-multi-opcion input {
    width: 1.05rem;
    height: 1.05rem;
    flex: 0 0 auto;
    accent-color: var(--erp-azul);
}

/* Las elegidas, debajo de la barra. Se quitan de una sin volver a abrir
   el panel: quitar es lo que más se repite al corregir una ficha.

   Más pequeñas que las de tocar: estas no se marcan, se leen. Con cinco o
   seis al tamaño de un botón ocupaban más que el propio desplegable. La
   equis sí conserva su área de toque, porque esa sí se toca. */
.erp-ficha-elegida {
    gap: .15rem;
    min-height: 0;
    padding: .1rem .15rem .1rem .55rem;
    font-size: .78rem;
    background: var(--erp-azul);
    border-color: var(--erp-azul);
    color: #fff;
    cursor: default;
}

.erp-fichas:has(.erp-ficha-elegida) { gap: .3rem; }

.erp-ficha-elegida button {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.35rem;
    height: 1.35rem;
    border: 0;
    background: none;
    color: inherit;
    opacity: .7;
    padding: 0;
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
}

.erp-ficha-elegida button:hover { opacity: 1; }

/* ------------------------------------------------------------------
   Las secciones plegables de una ficha

   Mismo acordeón que el catálogo, para no obligar a aprender dos cosas
   distintas. La ficha de producto son veinte campos: en el celular son
   cinco pantallas de desplazamiento y no se sabe nunca por dónde se va.
   ------------------------------------------------------------------ */
.erp-secciones .accordion-button {
    font-weight: 600;
    padding: .85rem 1rem;
}

.erp-secciones .accordion-button:not(.collapsed) {
    background: var(--erp-superficie-suave);
    color: var(--erp-azul);
    box-shadow: none;
}

.erp-secciones .accordion-button:focus {
    box-shadow: none;
    border-color: var(--erp-borde);
}

/* ------------------------------------------------------------------
   El texto de ejemplo dentro de un campo

   Con el gris de Bootstrap parecía escrito: el vendedor daba por
   rellenado un campo vacío. Va en el gris azulado de la marca, más
   claro que el texto real y todavía legible.
   ------------------------------------------------------------------ */
.form-control::placeholder,
.form-select::placeholder {
    color: var(--erp-acero);
    opacity: 1;
}

/* El campo del SKU escribe en mayúsculas, pero su ejemplo no: en
   mayúsculas «SE GENERA SOLO» parece un dato ya cargado. */
.text-uppercase::placeholder {
    text-transform: none;
}

/* ------------------------------------------------------------------
   Una fila de campos que alinean de verdad

   Las etiquetas no miden lo mismo: unas llevan el signo de
   interrogación, otras el asterisco de obligatorio y otras nada. Con
   alturas distintas, los campos de una misma fila arrancaban a
   distinta altura y la fila dejaba de leerse como una fila.

   La etiqueta ocupa siempre lo mismo, así que todos los campos
   empiezan en la misma línea sin depender de lo que diga encima.
   ------------------------------------------------------------------ */
.erp-campos > [class*="col-"] > .form-label {
    display: flex;
    align-items: center;
    gap: .3rem;
    min-height: 1.6rem;
    margin-bottom: .3rem;
}

/* Los atajos de porcentaje.

   Cuatro botones de ancho fijo no caben en la columna de un diálogo
   en celular: el último se salía de la caja y el texto de ayuda se le
   montaba encima. Reparten el ancho disponible y bajan de línea si
   hace falta. */
.erp-atajos {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem;
    margin-top: .35rem;
}

.erp-atajos .btn {
    flex: 1 1 auto;
    min-width: 2.7rem;
    padding: .1rem .25rem;
    font-size: .78rem;
}

/* ------------------------------------------------------------------
   Una ficha sin publicar

   Apagada y no en amarillo: no es una alerta, es algo que todavía no
   está terminado. El amarillo la ponía al nivel del stock descuadrado,
   que sí hay que atender hoy, y con veinte copias recién duplicadas la
   lista entera parecía un incendio.
   ------------------------------------------------------------------ */
.erp-apagado > td {
    opacity: .55;
}

.erp-apagado:hover > td {
    opacity: 1;
}

/* El mismo botón, pero avisando. El signo de interrogación se ignora
   —quien ya sabe no lo mira— y esto hay que verlo: dice que la ficha
   tiene algo sin resolver. */
.erp-ayuda-aviso {
    color: #B45309;
}

.erp-ayuda-aviso:hover {
    color: #92400E;
}

/* ------------------------------------------------------------------
   Una lista de datos que se sigue con la vista

   En una pantalla ancha la etiqueta queda a un palmo de su valor y el
   ojo se pierde de renglón: se lee «Material» y se acaba mirando el
   dato de la línea de abajo. La rayita no decora, sirve de riel.

   Muy tenue a propósito: catorce líneas marcadas se convierten en una
   reja y compiten con lo que hay dentro.
   ------------------------------------------------------------------ */
.erp-datos dt,
.erp-datos dd {
    padding: .4rem 0;
    border-bottom: 1px solid var(--erp-borde);
    margin-bottom: 0;
}

/* La última no lleva raya: cerraría la lista dos veces, con el borde
   de la propia tarjeta. */
.erp-datos > :nth-last-child(-n + 2) {
    border-bottom: 0;
}

/* ------------------------------------------------------------------
   La cabecera en un celular

   Con el menú, el volver, la campana, el buscador y el nombre entero
   del usuario, la fila medía más que la pantalla y el buscador quedaba
   aplastado a la mitad de su ancho.

   Menos aire entre botones y el buscador cediendo primero: es el único
   que se puede encoger sin perderse, porque su sitio se entiende por
   la lupa aunque no quepa el texto de dentro.
   ------------------------------------------------------------------ */
@media (max-width: 575.98px) {
    .erp-header {
        padding: .5rem .65rem;
        gap: .4rem !important;
    }

    .erp-header .btn {
        padding: .35rem .5rem;
    }

    .erp-buscador { min-width: 0; }
}

/* ------------------------------------------------------------------
   El aviso contado, al lado de un título

   Tres avisos apilados ocupaban media pantalla de celular antes de que
   se viera un solo producto, y de los tres solo uno es urgente: el
   resto es trabajo pendiente, que no es lo mismo. Contados detrás del
   triángulo se ven igual y no desplazan nada.
   ------------------------------------------------------------------ */
.erp-aguja {
    display: inline-flex;
    align-items: center;
    gap: .25rem;
    padding: .1rem .5rem .1rem .35rem;
    border: 1px solid #f5d9a8;
    border-radius: 999px;
    background: #fffaf0;
    color: #B45309;
    font-size: .8rem;
    font-weight: 600;
    line-height: 1.4;
}

/* Rojo cuando hay stock negativo: eso no es trabajo pendiente, es que
   el estante y la lista dicen cosas distintas hoy. */
.erp-aguja-roja {
    border-color: #f0c2c2;
    background: #fff5f5;
    color: #b91c1c;
}

/* ------------------------------------------------------------------
   Las acciones de una pantalla, en rejilla

   Apretados en una fila de celular salían de anchos distintos y en dos
   líneas descuadradas, que se lee como si estuvieran puestos al azar.
   En dos columnas iguales se lee como un bloque.
   ------------------------------------------------------------------ */
.erp-acciones {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
}

@media (max-width: 575.98px) {
    .erp-acciones {
        display: grid;
        grid-template-columns: 1fr 1fr;
        width: 100%;
    }

    /* Las cuatro del mismo tamaño. Una a lo ancho y las otras a medias se
       lee como si el ancho lo hubiera decidido el azar; en un cuadrado de
       dos por dos se lee como un bloque de cuatro opciones. */
}

/* ------------------------------------------------------------------
   Una tabla que se desliza sin aplastarse

   Sin ancho mínimo, el navegador estrecha las columnas hasta que
   quepan todas: «S/ 142.86» se parte en tres líneas y deja de leerse
   como un precio. Con mínimo, la tabla se sale y se desliza, que es lo
   que ya hace el contenedor.
   ------------------------------------------------------------------ */
.erp-tabla th,
.erp-tabla td {
    white-space: nowrap;
}

/* El nombre sí puede partirse: es lo único largo de verdad. */
.erp-tabla td:nth-child(2),
.erp-tabla th:nth-child(2) {
    white-space: normal;
    min-width: 11rem;
}

/* La fila entera abre la ficha. */
.erp-fila { cursor: pointer; }

/* ------------------------------------------------------------------
   El resumen de la vitrina

   «2 monturas en vitrina» en una línea se come el ancho entero de un
   celular y deja el desglose —que es la respuesta a la pregunta— fuera
   de la pantalla. La cifra encima de su rótulo ocupa dos renglones
   cortos en vez de uno larguísimo, y el desglose entra al lado.
   ------------------------------------------------------------------ */
.erp-vitrina {
    display: flex;
    align-items: center;
    gap: 1rem;
}

.erp-vitrina-cifra {
    flex: 0 0 auto;
    line-height: 1.15;
    text-align: center;
    min-width: 4.5rem;
}

/* La rayita separa la cifra de su desglose: sin ella, los números de
   los dos lados se leen como una sola lista y «2» y «2 Hombre»
   parecen dos datos del mismo tipo. */
.erp-vitrina-detalle {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .4rem;
    padding-left: 1rem;
    border-left: 1px solid var(--erp-borde);
    min-height: 2.6rem;
}

/* ------------------------------------------------------------------
   Los filtros puestos

   Debajo de la caja de buscar y no dentro: son el resultado de una
   decisión anterior, no un campo que se rellena.
   ------------------------------------------------------------------ */
.erp-filtro {
    display: inline-flex;
    align-items: center;
    padding: .3rem .8rem;
    border: 1px solid var(--erp-borde);
    border-radius: 999px;
    background: #fff;
    font-size: .82rem;
    line-height: 1.3;
    white-space: nowrap;
}

/* ------------------------------------------------------------------
   El semáforo del mínimo

   El cliente está mirando esta misma pantalla. Un renglón que diga
   «Mínimo S/ 430» se lee desde la otra silla, y una banda roja de
   «estás tocando margen» todavía más.

   Aquí no hay nada que leer: un signo de interrogación que cambia de
   color. Los tres son apagados a propósito —no son los rojos y ámbares
   de una alerta— porque tienen que decírselo a quien los busca sin
   llamar la atención de quien no.
   ------------------------------------------------------------------ */
.erp-semaforo-caja {
    position: relative;
    display: inline-flex;
}

.erp-semaforo {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* Área de toque de 28 px sin crecer la línea, como el signo de
       ayuda: dentro de una etiqueta, un botón alto descuadra la fila. */
    width: 28px;
    height: 28px;
    margin: -6px 0;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
    transition: color .15s;
}

.erp-semaforo.es-gris  { color: var(--erp-acero); }
.erp-semaforo.es-ambar { color: #C99A2E; }
.erp-semaforo.es-rojo  { color: #C0554C; }

.erp-semaforo:focus-visible {
    outline: 2px solid var(--erp-azul-claro);
    outline-offset: 2px;
    border-radius: 50%;
}

/* La burbuja. Solo aparece al tocar el signo, y se cierra al tocar
   fuera: en un celular no hay «quitar el dedo de encima». */
.erp-burbuja {
    position: absolute;
    bottom: calc(100% + .4rem);
    left: 50%;
    transform: translateX(-50%);
    z-index: 20;
    min-width: 12rem;
    max-width: 16rem;
    padding: .5rem .7rem;
    border-radius: .5rem;
    background: var(--erp-azul);
    color: #fff;
    font-size: .78rem;
    font-weight: 400;
    line-height: 1.35;
    white-space: pre-line;
    box-shadow: 0 6px 18px rgba(3, 61, 93, .28);
}

/* El pico, para que se lea como que sale del signo y no flotando. */
.erp-burbuja::after {
    content: '';
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    border: .35rem solid transparent;
    border-top-color: var(--erp-azul);
}

/* ------------------------------------------------------------------
   Una venta cerrada bajo el mínimo

   El número teñido y nada más. Una insignia roja al lado del título se
   lee desde la otra silla de la mesa, y que la venta fuera floja es
   cosa nuestra. Donde de verdad se mira esto es en el reporte de fin
   de mes.
   ------------------------------------------------------------------ */
.erp-bajo-piso { color: #BE7A73; }

/* ------------------------------------------------------------------
   Los tres finales de una consulta

   Apilados a lo largo ocupaban cuatro renglones, y el más raro —solo
   guardar— quedaba igual de gordo que los otros dos. En dos filas se
   leen como lo que son: lo que pasa casi siempre arriba, y lo que
   ocurre de vez en cuando debajo, que además queda más cerca del dedo
   de quien sostiene el teléfono.
   ------------------------------------------------------------------ */
.erp-finales {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: .5rem;
}

.erp-final-ancho {
    grid-column: 1 / -1;
}

@media (min-width: 768px) {
    .erp-finales {
        display: flex;
        flex-wrap: wrap;
    }
}

/* ------------------------------------------------------------------
   La tabla de refracción

   Partida en dos mitades de tres columnas, cada una cabe entera en un
   celular. Lo que hace falta es que los desplegables no se estrechen
   hasta que «-1.25» deje de leerse.
   ------------------------------------------------------------------ */
/* Ancho fijo: sin esto el navegador reparte las columnas según lo que
   mida el texto de dentro, y una opción larga como «Ninguno» hincha su
   celda hasta sacar el desplegable fuera de la tarjeta. Aquí se están
   anotando datos de salud: no puede quedar medio número tapado. */
.erp-refraccion {
    table-layout: fixed;
    width: 100%;
}

.erp-refraccion th,
.erp-refraccion td {
    padding: .3rem .2rem;
}

.erp-refraccion thead th {
    font-size: .72rem;
    font-weight: 600;
    line-height: 1.15;
}

/* El desplegable ocupa su celda y ni un pixel más. */
.erp-refraccion .form-select,
.erp-refraccion .form-control {
    width: 100%;
    min-width: 0;
    padding-left: .3rem;
    padding-right: 1.1rem;
    background-position: right .25rem center;
}

/* La barra del celular cuando la ocupa una tarea: tres botones en dos
   filas, como los del pie del formulario. */
.erp-barra-movil:has(.erp-enviar-medida) {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: .5rem;
}

/* ------------------------------------------------------------------
   El selector de graduación

   La esfera tiene ciento trece valores. En un desplegable normal eso
   es una lista ciega que hay que recorrer entera, y el sistema la abre
   siempre por el principio: para poner -1.25 hay que deslizar sesenta
   y siete renglones.

   Partida por signo se recorre la mitad, y esa mitad se sabe antes de
   mirar —una miopía es negativa y punto—.
   ------------------------------------------------------------------ */
.erp-grad {
    position: relative;
}

/* Se ve como el desplegable de al lado porque hace lo mismo: quien lo
   usa no tiene por qué notar que por dentro es otra cosa. */
.erp-grad-boton {
    text-align: center;
    padding-right: 1.1rem;
    background-position: right .25rem center;
}

.erp-grad-panel {
    position: absolute;
    top: calc(100% + .2rem);
    left: 50%;
    transform: translateX(-50%);
    z-index: 30;
    min-width: 11rem;
    padding: .3rem;
    border: 1px solid var(--erp-borde);
    border-radius: .5rem;
    background: #fff;
    box-shadow: 0 8px 24px rgba(3, 61, 93, .18);
}

/* Hacia arriba cuando abajo no cabe: en un celular la fila OI queda en
   la mitad inferior y el panel se salía por debajo de la pantalla. */
.erp-grad.esta-arriba .erp-grad-panel {
    top: auto;
    bottom: calc(100% + .2rem);
}

.erp-grad-cols {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: .15rem;
}

.erp-grad-cols.erp-grad-una {
    grid-template-columns: 1fr;
}

.erp-grad-titulo {
    text-align: center;
    font-size: .8rem;
    font-weight: 600;
    color: var(--erp-acero);
    padding-bottom: .15rem;
    border-bottom: 1px solid var(--erp-borde);
}

/* Alto fijo con su propio desplazamiento: sin esto el panel mide lo que
   midan sus ciento trece opciones y tapa la pantalla entera. */
.erp-grad-col {
    max-height: 13rem;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: .1rem;
}

.erp-grad-opcion {
    display: block;
    width: 100%;
    padding: .3rem .2rem;
    border: 0;
    border-radius: .3rem;
    background: none;
    font-family: var(--erp-mono, inherit);
    font-size: .85rem;
    line-height: 1.2;
    color: inherit;
    cursor: pointer;
}

.erp-grad-opcion:hover { background: var(--erp-superficie-suave); }

.erp-grad-opcion.esta-elegida {
    background: var(--erp-azul);
    color: #fff;
    font-weight: 600;
}

/* El cero, a lo ancho: no es negativo ni positivo, y en una escala de
   graduación es «sin corrección», que se elige tanto como cualquiera. */
.erp-grad-cero,
.erp-grad-limpiar {
    margin-bottom: .15rem;
    background: var(--erp-superficie-suave);
}

.erp-grad-libre {
    margin-top: .3rem;
    padding-top: .3rem;
    border-top: 1px solid var(--erp-borde);
}

/* Sin esto, un nombre largo estira su columna y empuja el botón de al
   lado fuera de la pantalla en vez de partirse. */
.min-w-0 { min-width: 0; }

/* Las medidas anteriores del diálogo: alto tope y desplazamiento propio.
   Con seis en el historial el diálogo medía tres pantallas y el botón de
   cerrar quedaba a un viaje de distancia. */
.erp-anteriores {
    max-height: 65vh;
    overflow-y: auto;
}

/* ------------------------------------------------------------------
   El asistente de la venta

   Una venta es un recorrido —quién compra, qué se lleva, cuánto paga y
   cuándo lo recoge— y era una pantalla con cinco tarjetas donde no se
   sabía por dónde se iba ni qué faltaba. En un celular, cuatro
   pantallas de desplazamiento y ningún sitio donde comprobarlo.
   ------------------------------------------------------------------ */
.erp-pasos-venta {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .25rem;
    list-style: none;
    margin: 0;
    padding: 0;
    overflow-x: auto;
    scrollbar-width: none;
}

/* Los cuatro pasos, centrados y sin estirarse de borde a borde. Cruzando la
   pantalla entera, las rayitas separaban tanto los circulos que dejaban de
   leerse como un recorrido y parecian cuatro botones sueltos. */
.erp-pasos-venta {
    max-width: 46rem;
    margin: 0 auto;
}

.erp-pasos-venta::-webkit-scrollbar { display: none; }

/* La rayita que une un paso con el siguiente: sin ella son cuatro
   botones sueltos y no un recorrido. */
.erp-paso-venta {
    display: flex;
    align-items: center;
    flex: 1 1 0;
    min-width: max-content;
}

.erp-paso-venta:not(:last-child)::after {
    content: '';
    flex: 1 1 1rem;
    height: 1px;
    min-width: .75rem;
    margin: 0 .35rem;
    background: var(--erp-borde);
}

.erp-paso-boton {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: .25rem .35rem;
    border: 0;
    background: none;
    color: var(--erp-acero);
    font-size: .82rem;
    white-space: nowrap;
    cursor: pointer;
}

/* El mismo circulo que la cabecera de cada paso, para que se lean como lo
   mismo: el dibujo en linea mientras falta, pintado cuando esta. El gris de
   antes era tan claro que el icono no se distinguia del fondo y los pasos
   pendientes parecian circulos vacios. */
.erp-paso-numero {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    border: 1.5px solid var(--erp-borde);
    border-radius: 50%;
    background: #fff;
    color: var(--erp-azul-claro);
    flex: 0 0 auto;
    transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}

/* Hecho: relleno, no un color de texto. Un paso completado tiene que
   distinguirse de un vistazo desde el otro lado del mostrador. */
.erp-paso-venta.esta-hecho .erp-paso-boton { color: var(--erp-azul); }

.erp-paso-venta.esta-hecho .erp-paso-numero {
    background: var(--erp-azul);
    border-color: var(--erp-azul);
    color: #fff;
}

/* En un celular no caben cuatro rótulos: quedan los números, que con la
   rayita y el relleno ya cuentan la misma historia. */
@media (max-width: 575.98px) {
    .erp-paso-nombre { display: none; }
}

/* El mismo número dentro de cada sección, para saber en cuál se está
   sin volver arriba a mirar. */
.erp-venta .accordion-button {
    font-weight: 600;
    padding: .75rem 1rem;
    gap: .6rem;
}

.erp-venta .accordion-button:not(.collapsed) {
    background: var(--erp-superficie-suave);
    color: var(--erp-azul);
    box-shadow: none;
}

.erp-venta .accordion-button:focus { box-shadow: none; }

/* El icono del paso, dentro de su circulo.

   En linea mientras falta algo, pintado cuando esta hecho. Antes era un
   numero que no dice nada, y en cuanto el paso se daba por hecho un check
   que a veces mentia: el del cliente salia marcado desde que la venta se
   abria, con la ficha a medias y sin telefono al que avisar. */
.erp-venta-icono {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.9rem;
    height: 1.9rem;
    border: 1.5px solid var(--erp-borde);
    border-radius: 50%;
    background: #fff;
    color: var(--erp-acero);
    flex: 0 0 auto;
    transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}

.erp-venta-icono.esta-hecho {
    background: var(--erp-azul);
    border-color: var(--erp-azul);
    color: #fff;
}

/* El triangulo de lo que falta, y la burbuja que lo cuenta.

   Vive dentro del boton del acordeon, asi que se posiciona respecto a si
   mismo: la burbuja cuelga por debajo sin empujar la cabecera. */
.erp-aviso-paso {
    position: relative;
    display: inline-flex;
    align-items: center;
    margin-left: .1rem;
    color: var(--bs-warning-text-emphasis, #997404);
    cursor: pointer;
}

.erp-burbuja-aviso {
    position: absolute;
    top: calc(100% + .5rem);
    left: 50%;
    z-index: 20;
    display: none;
    width: max-content;
    max-width: 16rem;
    padding: .45rem .7rem;
    transform: translateX(-50%);
    border: 1px solid var(--bs-warning-border-subtle, #ffe69c);
    border-radius: .4rem;
    background: var(--bs-warning-bg-subtle, #fff3cd);
    box-shadow: 0 .35rem .8rem rgba(0, 0, 0, .12);
    color: var(--bs-warning-text-emphasis, #997404);
    font-size: .78rem;
    font-weight: 400;
    white-space: normal;
}

.erp-burbuja-aviso.abierta { display: block; }

/* Las tarjetas de dentro pierden su borde: el de la sección ya está, y
   dos marcos concéntricos hacen que el contenido parezca hundido. */
.erp-venta .accordion-body > .erp-tarjeta,
.erp-venta .accordion-body > .erp-tarjeta.mt-3 {
    border: 0;
    box-shadow: none;
    border-radius: 0;
    margin-top: 0 !important;
}

/* ------------------------------------------------------------------
   Un paso a la vez, también en escritorio

   Tenerlos los tres abiertos parecía aprovechar el sitio, pero deja una
   tira de campos donde no se sabe por dónde se va: justo lo que el
   asistente venía a resolver. El que toca se abre solo y los demás
   esperan cerrados; el dinero se queda a la derecha, siempre a la vista.

   El de al lado, cuando aún no le toca, se ve apagado: sigue pudiéndose
   abrir —a veces hace falta mirar—, pero no compite con el que toca.
   ------------------------------------------------------------------ */
.erp-venta .accordion-button.collapsed { color: var(--erp-acero); }

.erp-venta .accordion-button.collapsed .erp-venta-icono:not(.esta-hecho) {
    opacity: .55;
}

/* En escritorio el dinero acompaña: se queda arriba mientras se recorre el
   pedido, que es lo que se mira al decidir qué se lleva.

   La columna entera, no su primera tarjeta. Pegando solo el total, los cobros
   seguian el scroll y acababan pasando por debajo de el: dos bloques que se
   montaban uno sobre otro con las cifras encima.

   align-self hace falta porque una columna de Bootstrap se estira a lo alto
   de la fila, y algo tan alto como su contenedor nunca llega a pegarse.

   El tope deja libre la barra de arriba, que tambien esta pegada; y si el
   panel no cabe entero, se desplaza por dentro en vez de tapar nada. */
@media (min-width: 992px) {
    .erp-venta-dinero {
        position: sticky;
        top: calc(var(--erp-header) + 1rem);
        z-index: 1;
        align-self: flex-start;
        max-height: calc(100vh - var(--erp-header) - 2rem);
        overflow-y: auto;
        scrollbar-width: thin;
    }
}

/* ---------------------------------------------------------------- Detalle del cliente
   La pregunta de a nombre de quién sale la boleta, y los grupos que ordenan
   el formulario. Antes eran dos filas de radios con su párrafo cada una y
   veinte campos seguidos sin ningún corte: ocupaba más la pregunta que la
   respuesta. */
.erp-quien {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .75rem;
    padding: .6rem 1rem;
    background: var(--bs-tertiary-bg, #f8f9fa);
    border-bottom: 1px solid var(--bs-border-color);
}

.erp-quien-titulo {
    font-size: .8125rem;
    color: var(--bs-secondary-color, #6c757d);
}

/* El nombre del paciente puede ser largo y no tiene por qué caber: se corta
   antes que romper la línea en dos. */
.erp-quien .btn {
    max-width: 14rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Rótulo de grupo: dice de qué son los campos que vienen debajo. La línea lo
   separa de lo anterior sin gastar el espacio de un título. */
.erp-grupo {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: .5rem;
    margin: 1.1rem 0 .5rem;
    padding-bottom: .3rem;
    border-bottom: 1px solid var(--bs-border-color-translucent, rgba(0, 0, 0, .1));
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--bs-secondary-color, #6c757d);
}

/* El primero no necesita separarse de nada: está pegado al borde de arriba. */
.erp-grupo:first-of-type { margin-top: 0; }

.erp-grupo .btn-link {
    font-size: .75rem;
    letter-spacing: 0;
    text-transform: none;
}

/* Un campo bloqueado tiene que parecerlo. Bootstrap deja el readonly con el
   mismo fondo que uno editable, así que se teclea encima creyendo que no pasa
   nada —y lo que pasa es que se renombra al paciente en todo su historial. */
.erp-tarjeta [readonly],
.erp-tarjeta select:disabled {
    background-color: var(--bs-secondary-bg, #e9ecef);
    color: var(--bs-secondary-color, #6c757d);
    cursor: default;
}

/* ------------------------------------------------- Piezas en el popup de línea
   El mismo renglón en los resultados de la búsqueda y en lo elegido: la
   etiqueta arriba —que es lo que se tiene en la mano—, qué es en medio, y
   cómo se reconoce en la vitrina debajo. */
.erp-elegidos {
    border: 1px solid var(--bs-border-color);
    border-radius: .5rem;
    overflow: hidden;
}

.erp-elegidos:empty { display: none; }

.erp-pieza {
    display: flex;
    align-items: flex-start;
    gap: .5rem;
    width: 100%;
    padding: .5rem .75rem;
    text-align: left;
}

.erp-pieza + .erp-pieza {
    border-top: 1px solid var(--bs-border-color-translucent, rgba(0, 0, 0, .1));
}

.erp-pieza-datos { flex: 1 1 auto; }

/* El código, en pequeño y encima: se lee de la etiqueta antes que nada. */
.erp-pieza-codigo {
    font-size: .72rem;
    color: var(--bs-secondary-color, #6c757d);
    line-height: 1.3;
}

.erp-pieza-boton {
    border: 0;
    background: none;
    color: inherit;
    cursor: pointer;
}

.erp-pieza-boton:hover { background: var(--erp-superficie-suave, #f1f5f9); }

/* Agregar otra pieza. De trazo discontinuo porque no es el final del camino:
   es un hueco donde cabe la siguiente. */
.erp-agregar-mas {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .4rem;
    width: 100%;
    padding: .6rem;
    border: 1.5px dashed var(--bs-border-color);
    border-radius: .5rem;
    background: none;
    color: var(--erp-azul);
    font-size: .875rem;
    font-weight: 500;
    cursor: pointer;
}

.erp-agregar-mas:hover {
    border-color: var(--erp-azul);
    background: var(--erp-superficie-suave, #f1f5f9);
}

/* -------------------------------------------------- Resumen del paso cerrado
   Un acordeón que al cerrarse no deja nada obliga a abrirlo para comprobar qué
   se puso, y entonces ya no sirve de nada haberlo cerrado. Aquí queda lo justo
   para saber que ese paso está bien sin tocarlo. */
.erp-resumen-paso { display: none; }

.erp-venta .accordion-item:has(.accordion-button.collapsed) .erp-resumen-paso {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    padding: .75rem 1rem 1rem;
    border-top: 1px solid var(--bs-border-color-translucent, rgba(0, 0, 0, .08));
}

.erp-resumen-datos {
    display: flex;
    flex-direction: column;
    gap: .3rem;
    min-width: 0;
}

.erp-resumen-linea {
    display: flex;
    align-items: center;
    gap: .5rem;
    font-size: .875rem;
    color: var(--bs-body-color);
}

/* El icono acompaña, no compite: gris incluso en la línea en negrita. */
.erp-resumen-linea .erp-icono {
    flex: 0 0 auto;
    color: var(--erp-acero);
}

.erp-resumen-paso .btn { flex: 0 0 auto; }

/* ------------------------------------------------------------- El dinero
   La cifra que se dice en voz alta va sobre fondo oscuro y en grande. Estaba
   del mismo tamaño que el precio de catálogo y el IGV, que no se dicen nunca. */
.erp-dinero { overflow: hidden; }

.erp-dinero-cabecera {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: .9rem 1rem;
    background: var(--erp-azul);
    color: #fff;
    font-weight: 600;
}

.erp-dinero-cifra {
    font-size: 1.45rem;
    line-height: 1.1;
    letter-spacing: -.01em;
}

/* El importe que se teclea manda sobre el resto del formulario: sin recuadro
   que compita, con el símbolo apagado al lado. */
.erp-monto {
    display: flex;
    align-items: baseline;
    gap: .35rem;
    padding: .3rem .7rem;
    border: 1px solid var(--bs-border-color);
    border-radius: .5rem;
    background: var(--erp-superficie-suave, #f8fafc);
}

.erp-monto > span {
    color: var(--bs-secondary-color, #6c757d);
    font-size: .95rem;
}

/* Grande para que destaque sobre lo demas, no para leerse desde la calle:
   a 1.6rem el importe pesaba mas que el total de la venta, que es el numero
   que de verdad manda en la pantalla. */
.erp-monto input {
    flex: 1 1 auto;
    width: 100%;
    min-width: 0;
    padding: 0;
    border: 0;
    background: none;
    color: var(--erp-azul);
    font-size: 1.2rem;
    font-weight: 700;
    line-height: 1.7;
}

.erp-monto input:focus { outline: none; }

/* Con que paga, en una linea.

   Eran seis botones en rejilla y ocupaban mas que el importe, que es lo que de
   verdad se mira. El icono va dentro del recuadro y cambia con la opcion, para
   reconocerla sin leerla. */
.erp-metodo {
    position: relative;
    display: flex;
    align-items: center;
}

.erp-metodo-icono {
    position: absolute;
    left: .65rem;
    display: inline-flex;
    align-items: center;
    color: var(--erp-azul-claro);
    pointer-events: none;
    z-index: 2;
}

.erp-metodo .form-select { padding-left: 2.4rem; }

/* ------------------------------------------------------------------ Cobros
   Arriba lo ya cobrado, en un renglón por pago; abajo el que toca ahora,
   abierto y listo. Era un formulario suelto con una lista encima: no se leía
   como un recorrido —anticipo hoy, el resto al recoger— sino como un cajón
   donde se van metiendo cobros. */
.erp-saldo-pendiente {
    padding: .3rem .7rem;
    border-radius: 999px;
    background: var(--bs-warning-bg-subtle, #fff3cd);
    color: var(--bs-warning-text-emphasis, #997404);
    font-size: .8rem;
    font-weight: 600;
}

.erp-cobro {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .6rem .75rem;
    margin-bottom: .5rem;
    border: 1px solid var(--bs-border-color);
    border-radius: .6rem;
    font-size: .82rem;
}

/* La marca de cada cobro: verde el que ya entró, azul el que se está
   registrando. Se distinguen sin leer. */
.erp-cobro-marca {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.7rem;
    height: 1.7rem;
    border-radius: 50%;
    flex: 0 0 auto;
}

.erp-cobro-hecho .erp-cobro-marca {
    background: var(--bs-success-bg-subtle, #d1e7dd);
    color: var(--bs-success-text-emphasis, #0a3622);
}

.erp-cobro-activo {
    border: 1px solid var(--erp-azul-claro);
    border-radius: .6rem;
    overflow: hidden;
    background: var(--erp-superficie-suave, #f8fafc);
}

.erp-cobro-activo-titulo {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .6rem .75rem;
    border-bottom: 1px solid var(--bs-border-color);
    background: #fff;
    font-size: .9rem;
}

.erp-cobro-activo-titulo .erp-cobro-marca {
    background: var(--bs-primary-bg-subtle, #cfe2ff);
    color: var(--erp-azul);
}

/* Lo que va a quedar debiendo, dicho antes de pulsar: es la pregunta que hace
   el cliente justo después. */
.erp-cobro-queda {
    display: flex;
    align-items: center;
    gap: .45rem;
    padding: .5rem .7rem;
    border-radius: .5rem;
    background: var(--bs-warning-bg-subtle, #fff3cd);
    color: var(--bs-warning-text-emphasis, #997404);
    font-size: .82rem;
}

.erp-cobro-queda.esta-al-dia {
    background: var(--bs-success-bg-subtle, #d1e7dd);
    color: var(--bs-success-text-emphasis, #0a3622);
}

/* Adjuntar la captura: un recuadro de trazo discontinuo y no un «Elegir
   archivo» del navegador, que en un celular no se entiende que abra la
   cámara. */
.erp-captura {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    width: 100%;
    padding: .7rem;
    border: 1.5px dashed var(--bs-border-color);
    border-radius: .5rem;
    background: #fff;
    color: var(--erp-azul);
    font-size: .82rem;
    cursor: pointer;
}

.erp-captura:hover { border-color: var(--erp-azul); }

.erp-comprobantes-abrir {
    display: flex;
    align-items: center;
    gap: .5rem;
    width: 100%;
    margin-top: .75rem;
    padding: .65rem .75rem;
    border: 1px solid var(--bs-border-color);
    border-radius: .6rem;
    background: #fff;
    color: var(--erp-azul);
    font-size: .85rem;
    font-weight: 500;
    cursor: pointer;
}

.erp-comprobantes-abrir:hover { background: var(--erp-superficie-suave, #f1f5f9); }

/* ------------------------------------------------ El total, abajo y a mano
   En vertical, mientras se baja de los productos a la entrega, lo único que
   hace falta llevar encima es cuánto suma lo que se está armando. Los accesos
   rápidos de siempre no pintan nada a media venta. */
.erp-total-movil {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    width: 100%;
    padding: .35rem .25rem;
}

.erp-total-movil span {
    color: var(--bs-secondary-color, #6c757d);
    font-size: .85rem;
}

.erp-total-movil strong {
    color: var(--erp-azul);
    font-size: 1.35rem;
    line-height: 1.1;
}

/* Sin nada que decir no se dibuja: una franja vacía al pie de la pantalla se
   lee como algo que no cargó, y ocupa el centímetro que el pulgar necesita
   para llegar al formulario. */
.erp-barra-movil:has(.esta-vacia) { display: none; }

/* Con el panel del dinero a la vista, el total ya está en pantalla con su
   desglose: repetirlo abajo es tapar contenido para no decir nada nuevo. */
.erp-barra-movil.esta-de-mas {
    transform: translateY(120%);
    pointer-events: none;
    transition: transform .18s ease;
}

/* --------------------------------------------- El paso que toca, señalado
   Se sabe cuál está abierto porque es el único desplegado, pero en una
   pantalla llena de tarjetas iguales eso hay que deducirlo. Un filo azul a la
   izquierda lo dice sin gritar: quien ya sabe dónde está ni lo nota, y quien
   se acaba de sentar sabe dónde escribir. */
.erp-venta .accordion-item {
    border-left: 3px solid transparent;
    transition: border-color .15s ease;
}

.erp-venta .accordion-item:has(.accordion-collapse.show) {
    border-left-color: var(--erp-azul);
}

.erp-venta .accordion-item:has(.accordion-collapse.show) > .accordion-header .accordion-button {
    background: var(--erp-superficie-suave, #f1f5f9);
}

/* ------------------------------------------------- Atajos de fecha y hora
   Al cliente no se le dice «el 4 de septiembre»: se le dice «el viernes» o
   «en cinco días». Buscar esa fecha en un calendario es traducir dos veces. */
.erp-atajos-fecha {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem;
}

.erp-atajo {
    padding: .3rem .6rem;
    border: 1px solid var(--bs-border-color);
    border-radius: 999px;
    background: #fff;
    color: var(--erp-azul);
    font-size: .78rem;
    line-height: 1.3;
    cursor: pointer;
}

.erp-atajo:hover { border-color: var(--erp-azul); }

.erp-atajo.esta-puesto {
    background: var(--erp-azul);
    border-color: var(--erp-azul);
    color: #fff;
}

.erp-atajo.esta-puesto .text-muted { color: rgba(255, 255, 255, .75) !important; }

/* ------------------------------------------------- El prefijo del teléfono
   Bootstrap le pone «width: 1%» a un select dentro de un input-group para que
   se reparta el ancho con el resto; con el crecimiento apagado, ese 1% manda y
   el desplegable se queda en blanco. Aquí mide lo suyo y no compite. */
.erp-telefono-pais {
    flex: 0 0 auto !important;
    width: 6.5rem !important;
    min-width: 6.5rem !important;
    padding-right: 1.6rem;
}

/* El número tiene todo el sitio que sobra: es lo que se teclea. */
.erp-telefono .erp-telefono-numero { flex: 1 1 auto; }

/* ------------------------------------------- Qué clase de línea se agrega
   En diálogo y no en desplegable: el menú se abría pegado al botón, tapando
   justo la tabla que se está mirando, y en un celular quedaba a ras del borde
   con cuatro opciones de un renglón cada una. */
.erp-clases-linea {
    display: flex;
    flex-direction: column;
    gap: .35rem;
}

.erp-clase-linea {
    display: flex;
    align-items: center;
    gap: .75rem;
    width: 100%;
    padding: .7rem .8rem;
    border: 1px solid var(--bs-border-color);
    border-radius: .6rem;
    background: #fff;
    color: var(--erp-azul);
    text-align: left;
    cursor: pointer;
}

.erp-clase-linea:hover {
    border-color: var(--erp-azul);
    background: var(--erp-superficie-suave, #f1f5f9);
}

.erp-clase-linea span { display: flex; flex-direction: column; line-height: 1.25; }
.erp-clase-linea small { color: var(--bs-secondary-color, #6c757d); }

/* ------------------------------------------ La fecha de nacimiento, en tres
   El calendario del navegador se abre en el mes de hoy: para llegar a 1978 hay
   que retroceder quinientas veces, o saber que se puede teclear encima —que no
   lo sabe nadie—. Una fecha de nacimiento no se busca, se sabe. */
.erp-fecha3 { position: relative; }

.erp-fecha3-boton { cursor: pointer; }
.erp-fecha3-boton:disabled { background-color: var(--bs-secondary-bg, #e9ecef); cursor: default; }

.erp-fecha3-panel {
    position: absolute;
    z-index: 30;
    left: 0;
    right: 0;
    min-width: 17rem;
    margin-top: .25rem;
    padding: .5rem;
    border: 1px solid var(--bs-border-color);
    border-radius: .5rem;
    background: #fff;
    box-shadow: 0 .5rem 1.2rem rgba(3, 61, 93, .16);
}

.erp-fecha3-columnas { display: flex; gap: .35rem; }
.erp-fecha3-columna { flex: 1 1 0; min-width: 0; }

.erp-fecha3-titulo {
    display: block;
    padding-bottom: .25rem;
    font-size: .7rem;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--bs-secondary-color, #6c757d);
}

.erp-fecha3-lista {
    max-height: 11rem;
    overflow-y: auto;
    scrollbar-width: thin;
}

.erp-fecha3-opcion {
    display: block;
    width: 100%;
    padding: .3rem .4rem;
    border: 0;
    border-radius: .3rem;
    background: none;
    color: var(--bs-body-color);
    font-size: .85rem;
    text-align: center;
    cursor: pointer;
}

.erp-fecha3-opcion:hover:not(:disabled) { background: var(--erp-superficie-suave, #f1f5f9); }
.erp-fecha3-opcion:disabled { color: var(--bs-border-color); cursor: default; }

.erp-fecha3-opcion.esta-puesto {
    background: var(--erp-azul);
    color: #fff;
    font-weight: 600;
}

.erp-fecha3-pie {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    margin-top: .5rem;
    padding-top: .5rem;
    border-top: 1px solid var(--bs-border-color-translucent, rgba(0, 0, 0, .08));
}

.erp-fecha3-edad { font-size: .8rem; color: var(--bs-secondary-color, #6c757d); }

/* -------------------------------------------- Cuántas personas se parecen
   La lista vivía en una columna a la derecha, que en vertical caía debajo del
   botón de guardar: para cuando se veía, ya se había creado la ficha repetida.
   Un número al lado del nombre se ve mientras se escribe. */
.erp-coincidencias {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    padding: .2rem .55rem;
    border: 1px solid var(--bs-warning-border-subtle, #ffe69c);
    border-radius: 999px;
    background: var(--bs-warning-bg-subtle, #fff3cd);
    color: var(--bs-warning-text-emphasis, #997404);
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
    cursor: pointer;
}

.erp-coincidencias:hover { border-color: var(--bs-warning, #ffc107); }

/* ------------------------------------------------- Las cifras del tablero
   Alineadas a la derecha y una detrás de otra, en un celular se amontonaban
   contra el borde y el último número caía a media línea. En rejilla cada una
   tiene su celda: dos por fila en el teléfono, seguidas en pantalla ancha. */
.erp-cifras {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: .75rem;
    width: 100%;
}

/* En pantallas estrechas los rótulos no caben del todo: se cortan antes que
   partirse en dos líneas y descuadrar la fila. */
.erp-cifras > div { min-width: 0; }
.erp-cifras .small { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.erp-cifras .h5 { line-height: 1.2; }

/* En pantalla ancha no se estiran de borde a borde: tres cifras separadas
   medio metro dejan de leerse como un conjunto. */
@media (min-width: 768px) {
    .erp-cifras {
        max-width: 34rem;
        gap: 2rem;
    }
}

/* ------------------------------------------- Los trabajos, en el teléfono
   Siete columnas en una pantalla de cinco centímetros dejaban «En el taller ·
   falta recogerlo» partido en cuatro renglones y el nombre del cliente en
   tres. Se leía peor que un papel. En vertical cada trabajo es un bloque:
   quién, qué, en qué va y para cuándo. */
.erp-trabajos {
    display: flex;
    flex-direction: column;
    gap: .6rem;
}

.erp-trabajo {
    display: block;
    padding: .75rem .85rem;
    border: 1px solid var(--erp-borde);
    border-radius: .6rem;
    background: var(--erp-superficie, #fff);
    color: var(--bs-body-color);
    text-decoration: none;
}

.erp-trabajo:hover { border-color: var(--erp-azul-claro); }
.erp-trabajo.esta-cerrada { opacity: .6; }

/* La etapa, a la derecha y sin partirse: es lo que decide qué toca hacer. */
.erp-trabajo-etapa {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    padding: .2rem .55rem;
    border-radius: 999px;
    background: var(--erp-superficie-suave, #f1f5f9);
    color: var(--erp-azul);
    font-size: .72rem;
    font-weight: 600;
    text-align: center;
    max-width: 8.5rem;
}

.erp-trabajo-fechas {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem .75rem;
    font-size: .78rem;
    font-variant-numeric: tabular-nums;
    color: var(--bs-secondary-color, #6c757d);
}

.erp-trabajo-pie {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .25rem .6rem;
    margin-top: .5rem;
    padding-top: .5rem;
    border-top: 1px solid var(--bs-border-color-translucent, rgba(0, 0, 0, .08));
    font-size: .75rem;
    color: var(--bs-secondary-color, #6c757d);
}

/* El filo del semáforo, también en la tarjeta de un trabajo: rojo lo vencido,
   ámbar lo de hoy, verde lo que va a tiempo. Sin él, una lista de veinte
   trabajos hay que leerla entera para saber cuál corre prisa. */
.erp-trabajo.erp-vencido,
.erp-trabajo.erp-hoy,
.erp-trabajo.erp-proximo { border-left-width: 3px; }

.erp-trabajo.erp-vencido { border-left-color: #dc3545; }
.erp-trabajo.erp-hoy { border-left-color: #f59e0b; }
.erp-trabajo.erp-proximo { border-left-color: #16a34a; }

/* La leyenda del semáforo. Un código de color sin leyenda se aprende por
   prueba y error, y hasta entonces no sirve de nada. */
.erp-leyenda {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem 1rem;
    font-size: .75rem;
    color: var(--bs-secondary-color, #6c757d);
}

.erp-leyenda span { display: inline-flex; align-items: center; gap: .35rem; }

.erp-punto {
    width: .55rem;
    height: .55rem;
    border-radius: 50%;
    box-shadow: none !important;
}

.erp-punto.erp-vencido { background: #dc3545; }
.erp-punto.erp-hoy { background: #f59e0b; }
.erp-punto.erp-proximo { background: #16a34a; }

/* ------------------------------------------- Cerrar la venta, al pie del dinero
   Va dentro de la tarjeta de cobros, debajo de los comprobantes: el último
   cobro y la entrega ocurren en el mismo momento del mostrador. El filo de
   arriba lo separa de la lista sin sacarlo de la tarjeta. */
.erp-cerrar-venta {
    margin-top: .75rem;
    padding-top: .75rem;
    border-top: 1px solid var(--bs-border-color);
}

/* ------------------------------------- El semáforo también en la tabla
   En las tarjetas del celular el color va en el filo izquierdo. En la tabla
   un borde puesto en el <tr> no se dibuja —las celdas están colapsadas—, así
   que se pinta el filo de la primera celda. Sin esto, la lista de escritorio
   se quedaba sin la única señal que se lee de lejos. */
.erp-tabla-semaforo > tbody > tr > td:first-child { border-left: 4px solid transparent; }

.erp-tabla-semaforo > tbody > tr.erp-vencido > td:first-child { border-left-color: #dc3545; }
.erp-tabla-semaforo > tbody > tr.erp-hoy > td:first-child { border-left-color: #f59e0b; }
.erp-tabla-semaforo > tbody > tr.erp-proximo > td:first-child { border-left-color: #16a34a; }

/* Y el punto de color, junto a la fecha que manda: dice cuál de las tres es
   la que decide el color, que es lo que no se adivina mirando el filo. */
.erp-punto {
    display: inline-block;
    vertical-align: baseline;
    flex-shrink: 0;
}

/* ------------------------------- Lo que hay que cobrarle si paga con tarjeta
   Pegado al importe y no al pie del formulario: se teclea el monto, se lee al
   lado cuánto pedir, y se le dice al cliente antes de pasar la tarjeta. La
   cifra a cobrar manda sobre el recargo —es la que se dice en voz alta— y el
   desglose queda debajo para cuando el cliente pregunta por qué. */
.erp-aviso-tarjeta {
    display: flex;
    flex-direction: column;
    gap: .1rem;
    margin-bottom: .75rem;
    padding: .6rem .75rem;
    border: 1px solid #f59e0b;
    border-left-width: 4px;
    border-radius: .5rem;
    background: #fffbeb;
}

.erp-aviso-tarjeta .rotulo {
    font-size: .75rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: #92400e;
}

.erp-aviso-tarjeta .cifra {
    font-size: 1.35rem;
    font-weight: 700;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
    color: #7c2d12;
}

.erp-aviso-tarjeta .detalle { font-size: .75rem; color: #92400e; }

/* ------------------------------- La lista de pacientes, plegada en el celular
   El botón que la despliega se lee como una fila más, con la flecha al fondo
   que gira cuando está abierta: dice sin palabras que debajo hay algo. */
.erp-desplegar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    text-align: start;
}

.erp-desplegar .erp-giro { transition: transform .2s ease; }
.erp-desplegar[aria-expanded="true"] .erp-giro { transform: rotate(180deg); }

@media (prefers-reduced-motion: reduce) {
    .erp-desplegar .erp-giro { transition: none; }
}

/* ------------------------------------------ Los pasos de la medida, resumidos
   La misma regla que la venta: el resumen aparece solo cuando su paso está
   cerrado, y con el mismo aspecto, para que las dos pantallas se lean igual. */
.erp-pasos-medida .accordion-item:has(.accordion-button.collapsed) .erp-resumen-paso {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    padding: .75rem 1rem 1rem;
    border-top: 1px solid var(--bs-border-color-translucent, rgba(0, 0, 0, .08));
}

/* OD y OI, como una etiqueta fija delante de la graduación. */
.erp-resumen-ojo {
    flex: 0 0 auto;
    min-width: 1.9rem;
    color: var(--erp-acero);
    font-size: .75rem;
    font-weight: 700;
}

/* Al bajar hasta el paso siguiente, que no quede debajo de la barra de arriba. */
.erp-pasos-medida .accordion-item { scroll-margin-top: 4.5rem; }
