/*!
 * BeplyTheme - Mobile forms
 * Reorganiza EditView y formularios densos para móvil:
 * inputs 16px+, secciones colapsables, sticky save, agrupación por bloques.
 */

@media (max-width: 767.98px) {

    /* === Inputs y labels — ya hay reglas en mobile-base.css, aquí refuerzos === */
    .form-group { margin-bottom: var(--beply-mb-gap-lg); }
    label, .form-label {
        font-size: var(--beply-mb-fs-sm);
        font-weight: 600;
        margin-bottom: 4px;
        color: var(--beply-mb-fg-mute) !important;
        text-transform: uppercase;
        letter-spacing: 0.4px;
    }

    /* WAVE 2 — labels en EditController salen en `text-info` (azul Bootstrap)
       cuando son campos required. Sobreescribimos para mantener el tono gris
       uppercase coherente con el resto. Excepción: link/anchor labels. */
    .form-label.text-info,
    label.text-info,
    .col-form-label.text-info,
    fieldset .form-label.text-info {
        color: var(--beply-mb-fg-mute) !important;
    }
    /* El "*" indicador de required: rojo brand */
    .form-label.text-info::after,
    label.text-info::after {
        content: " *";
        color: var(--beply-mb-accent);
        font-weight: 700;
    }

    /* Labels dentro de fieldset uppercase — mantenemos legibilidad sin demasiado peso */
    .form-control:focus,
    .form-select:focus {
        border-color: var(--beply-mb-accent);
        box-shadow: 0 0 0 0.2rem rgba(var(--beply-mb-accent-rgb), 0.18);
    }

    .form-text {
        font-size: var(--beply-mb-fs-xs);
    }

    /* WAVE 2 — campos required salen con FONDO AMARILLO en FacturaScripts.
       custom.css (Dinamic/Assets/CSS/custom.css) aplica:
         input[required].form-control:not(:read-only) {
             background-image: linear-gradient(rgba(253,253,150,0.5), ...);
         }
       En mobile lo neutralizamos: fondo blanco limpio + border-left rojo
       3px como indicador de required (coherente con las cards y el dot
       brand). Override del background-image (que es lo que pinta amarillo). */
    input[required].form-control:not(:read-only),
    textarea[required].form-control:not(:read-only),
    select[required].form-control:not(:disabled),
    .form-control.bg-warning,
    .form-control.bg-warning-subtle,
    .form-select.bg-warning,
    .form-select.bg-warning-subtle,
    input.bg-warning,
    input.bg-warning-subtle,
    select.bg-warning,
    textarea.bg-warning {
        background-image: none !important;
        background-color: var(--beply-mb-surface, #fff) !important;
        background: var(--beply-mb-surface, #fff) !important;
        border-left: 3px solid var(--beply-mb-accent, #d20000) !important;
    }
    /* Select2 required: el shadow amarillo del wrapper Select2 */
    select[required].form-select.select2 + .select2-container--bootstrap-5 .select2-selection,
    .select2-container--bootstrap-5 .select2-selection {
        box-shadow: none !important;
        border-left: 3px solid var(--beply-mb-accent, #d20000) !important;
        border-radius: 0 !important;
    }
    /* Select sin required: sin border-left rojo */
    select:not([required]) + .select2-container--bootstrap-5 .select2-selection {
        border-left: 1px solid var(--beply-mb-border, #e5e5e5) !important;
    }
    /* Variante: input dentro de div.bg-warning wrapper */
    div.bg-warning > .form-control,
    div.bg-warning-subtle > .form-control,
    .mb-3.bg-warning,
    .mb-3.bg-warning-subtle {
        background-color: transparent !important;
        background: transparent !important;
    }
    /* Card-header bg-warning en EditController (banner del fieldset) — neutro */
    .card-header.bg-warning,
    .card-header.bg-warning-subtle {
        background: var(--beply-mb-surface-2, #f5f5f5) !important;
        color: var(--beply-mb-fg-strong, #000) !important;
        border-left: 3px solid var(--beply-mb-accent, #d20000);
    }

    /* AUTOFILL amarillo de Chrome — neutralizar.
       Chrome colorea inputs con autofill en amarillo claro vía pseudo-class
       `:-webkit-autofill`. La única manera de overrides es con box-shadow
       interna que cubra el fondo. */
    input:-webkit-autofill,
    input:-webkit-autofill:hover,
    input:-webkit-autofill:focus,
    input:-webkit-autofill:active,
    select:-webkit-autofill,
    textarea:-webkit-autofill {
        -webkit-box-shadow: 0 0 0 1000px var(--beply-mb-surface, #fff) inset !important;
        -webkit-text-fill-color: var(--beply-mb-fg-strong, #000) !important;
        box-shadow: 0 0 0 1000px var(--beply-mb-surface, #fff) inset !important;
        background-color: var(--beply-mb-surface, #fff) !important;
        transition: background-color 9999s ease-in-out 0s;
        caret-color: var(--beply-mb-fg-strong);
    }

    /* Link dentro de labels (Id. Fiscal, etc.) — gris uppercase, no azul */
    label > a,
    .form-label > a,
    .col-form-label > a,
    label.mb-0 > a {
        color: var(--beply-mb-fg-mute, #666) !important;
        text-decoration: none !important;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.4px;
    }
    label > a:hover,
    .form-label > a:hover {
        color: var(--beply-mb-fg-strong, #000) !important;
        text-decoration: underline !important;
    }

    /* `<legend class="text-info">` en EditController (sub-sección
       "Información de contacto"). Lo hacemos negro uppercase como un
       group header sin "info azul". */
    legend.text-info {
        color: var(--beply-mb-fg-strong, #000) !important;
        font-family: var(--beply-mb-font-text);
        font-weight: 700 !important;
        font-size: 12px !important;
        letter-spacing: 0.6px;
        text-transform: uppercase;
        margin: 16px 0 8px !important;
        padding-bottom: 4px;
        border-bottom: 1px solid var(--beply-mb-border, #e5e5e5);
    }

    /* WAVE 2 — KPI lateral en EditCliente (Ped/Alb/Fact Ptes).
       En desktop salen como botones .btn.btn-light en columna derecha
       (.text-end). En mobile los pasamos a STRIP HORIZONTAL bajo el
       header negro, con scroll-x oculto + chips compactos. */
    form[id^="formEdit"] .row > .col-12.text-end:has(> a.btn.btn-light),
    form[id^="form"] .row > .col-12.text-end {
        text-align: left !important;
        display: flex;
        flex-wrap: nowrap;
        overflow-x: auto;
        scrollbar-width: none;
        gap: 8px;
        padding: 0 var(--beply-mb-pad, 16px);
        margin: 0 calc(-1 * var(--beply-mb-pad, 16px)) var(--beply-mb-gap-md, 12px);
    }
    form[id^="form"] .row > .col-12.text-end::-webkit-scrollbar { display: none; }
    form[id^="form"] .row > .col-12.text-end > a.btn.btn-light {
        flex: 0 0 auto;
        display: inline-flex;
        align-items: center;
        gap: 6px;
        padding: 8px 12px !important;
        height: auto !important;
        min-height: 36px !important;
        margin: 0 !important;
        background: var(--beply-mb-surface, #fff) !important;
        border: 1px solid var(--beply-mb-border, #e5e5e5) !important;
        border-radius: 0 !important;
        font-family: var(--beply-mb-font-text);
        font-size: 13px;
        color: var(--beply-mb-fg-strong, #000) !important;
        white-space: nowrap;
    }
    form[id^="form"] .row > .col-12.text-end > a.btn.btn-light svg,
    form[id^="form"] .row > .col-12.text-end > a.btn.btn-light i {
        color: var(--beply-mb-fg-mute, #666);
        font-size: 12px;
    }

    /* WAVE 2 — PAGINACIÓN en mobile (.btn-group con .btn.btn-outline-dark).
       Se renderiza al final del listado cuando hay más de N items. */
    form[id^="formList"] .text-center > .btn-group,
    form[id^="form"] .card-footer.text-center > .btn-group,
    form[id^="form"] .pt-3.text-center > .btn-group {
        display: inline-flex;
        flex-wrap: wrap;
        justify-content: center;
        gap: 4px;
        background: transparent;
    }
    form[id^="form"] .text-center > .btn-group > .btn.btn-outline-dark,
    form[id^="form"] .text-center > .btn-group > .btn-outline-dark {
        height: 38px !important;
        min-width: 38px !important;
        padding: 0 10px !important;
        font-family: var(--beply-mb-font-num) !important;
        font-weight: 600 !important;
        font-size: 13px !important;
        border-radius: 0 !important;
        border-color: var(--beply-mb-border, #e5e5e5) !important;
        color: var(--beply-mb-fg-strong, #000) !important;
        background: var(--beply-mb-surface, #fff) !important;
    }
    form[id^="form"] .text-center > .btn-group > .btn.btn-outline-dark.active,
    form[id^="form"] .text-center > .btn-group > .btn-outline-dark.active {
        background: var(--beply-mb-fg-strong, #000) !important;
        color: #ffffff !important;
        border-color: var(--beply-mb-fg-strong, #000) !important;
    }

    /* WAVE 2 — FILTROS (#listViewModalFilters / el panel filterview).
       Cuando el usuario pulsa el bote de pintura/filter, FS muestra un
       panel con N selects/inputs. En mobile esto se desbordaba: cada
       filtro en col-sm-6/md-4/lg-3 → 2 cols laterales se solapan. */
    form[id^="form"] .filterview,
    form[id^="form"] [id$="filterview"],
    form[id^="form"] [id*="-filterview"] {
        padding: var(--beply-mb-gap-md) var(--beply-mb-pad) !important;
        background: var(--beply-mb-surface, #fff) !important;
        border: 1px solid var(--beply-mb-border, #e5e5e5) !important;
        margin: 0 0 var(--beply-mb-gap-md) !important;
    }
    /* Cada filtro = full width en mobile */
    form[id^="form"] .filterview > .row > [class*="col-"],
    form[id^="form"] [id*="filterview"] > .row > [class*="col-"] {
        flex: 0 0 100% !important;
        max-width: 100% !important;
        padding: 0 !important;
    }
    /* Los selects/inputs del filterview heredan el styling del form */
    form[id^="form"] .filterview select,
    form[id^="form"] .filterview .form-select,
    form[id^="form"] .filterview .form-control {
        height: 40px;
        font-size: 14px;
    }
    /* form-check (checkboxes Recargo/Retención/Suplidos) */
    form[id^="form"] .filterview .form-check {
        margin: 6px 0;
        padding-left: 28px;
    }
    form[id^="form"] .filterview .form-check-input {
        margin-left: -28px;
        width: 18px;
        height: 18px;
    }

    /* Tabs y pills: estilo "underline" tipo desktop.
       El JS mueve las pestañas que no caben a un dropdown "..." al final, así que
       overflow se queda VISIBLE para que el dropdown-menu del "..." flote libremente. */
    .nav-tabs,
    .nav-pills,
    .nav.nav-pills {
        flex-wrap: nowrap;
        overflow: visible;
        max-width: 100%;
        position: relative;
        white-space: nowrap;
        border-bottom: 0;
        gap: 0;
        padding-left: 0;
        padding-right: 0;
        padding-bottom: 0;
        margin-bottom: 0;
    }
    /* Estilo IDÉNTICO al desktop FacturaScripts/BeplyTheme:
         - Inactivas: fondo transparente, sin borde, texto azul link.
         - Activa: fondo blanco, texto negro, bordes superior+laterales sutiles
                   (estilo "lengüeta" pegada al panel inferior). */
    .nav-tabs .nav-link,
    .nav-pills .nav-link {
        flex: 0 0 auto;
        border-radius: 0 !important;
        border: 1px solid transparent;
        border-bottom: 0;
        background: transparent !important;
        padding: 8px 14px;
        font-size: var(--beply-mb-fs-base);
        font-weight: 600;
        /* Edit usa nav-pills sobre fondo CLARO → inactivas en gris oscuro
           (no azul, no blanco). Las de listado van sobre header negro y tienen
           su propia regla (.nav-tabs-scroll) en blanco, que gana por specificity. */
        color: var(--beply-mb-fg-mute, #6b7280) !important;
    }
    .nav-tabs .nav-link:hover,
    .nav-pills .nav-link:hover {
        color: var(--beply-mb-fg-strong, #000) !important;
    }
    .nav-tabs .nav-link.active,
    .nav-pills .nav-link.active,
    .nav-pills .show > .nav-link {
        background: var(--beply-mb-surface) !important;
        color: var(--beply-mb-fg) !important;
        border: none !important;
        border-bottom: 1px solid var(--beply-mb-surface) !important;
        margin-bottom: -1px;
        position: relative;
        z-index: 1;
        font-weight: 400;
    }
    /* Badges en tabs — gris oscuro con texto blanco (idéntico al desktop). */
    .nav-tabs .nav-link .badge,
    .nav-pills .nav-link .badge,
    .nav-link .badge.bg-secondary,
    .nav-link .badge.bg-light {
        margin-left: 4px;
        background: #6c757d !important;
        color: #ffffff !important;
        font-weight: 600;
        border-radius: 0;
        padding: 2px 7px;
    }

    /* Overflow tab "..." — pegado a la última pestaña visible (sin margin-left auto) */
    .beply-mb-tab-overflow {
        flex: 0 0 auto;
    }
    /* Las pestañas de ficha (`.nav-pills.overflow-x-auto`) las pinta el core
       con scroll horizontal. Cuando el menú "⋯" recoge las que no caben ya no
       hay nada que arrastrar, y ese scroll recortaría el desplegable. */
    .nav.beply-mb-tabs-fit {
        overflow: visible !important;
        flex-wrap: nowrap;
        /* El menú se alinea contra la BARRA, no contra su botón: si el botón
           queda a mitad de la fila (pocas pestañas visibles), un menú anclado a
           él se salía por la izquierda de la pantalla. */
        position: relative;
    }
    .beply-mb-tabs-fit .beply-mb-tab-overflow {
        position: static;
    }
    .beply-mb-tab-overflow .dropdown-menu {
        max-width: calc(100vw - 24px);
    }
    .beply-mb-tab-overflow > .nav-link,
    .beply-mb-tab-overflow > button.nav-link {
        background: transparent !important;
        border: 0 !important;
        color: var(--beply-mb-fg-mute);
        padding: 8px 12px !important;
        min-width: 40px;
        text-align: center;
        font-size: var(--beply-mb-fs-base);
        cursor: pointer;
        line-height: 1;
    }
    .beply-mb-tab-overflow > button.nav-link::after {
        display: none;
    }
    .beply-mb-tab-overflow.show > .nav-link,
    .beply-mb-tab-overflow.show > button.nav-link {
        color: var(--beply-mb-fg);
    }
    .beply-mb-tab-overflow > .nav-link::after {
        display: none;
    }
    .beply-mb-tab-overflow .dropdown-menu {
        max-height: 60vh;
        overflow-y: auto;
        min-width: 180px;
    }
    .beply-mb-tab-overflow .dropdown-item {
        display: flex;
        align-items: center;
        gap: 8px;
        padding: 10px 14px;
        min-height: var(--beply-mb-tap);
    }
    .beply-mb-tab-overflow .dropdown-item.active {
        background: var(--beply-mb-primary);
        color: var(--beply-mb-on-primary);
    }
    /* Una pestaña deshabilitada (sin permiso, sin datos) tiene que parecerlo
       también dentro del menú: el color fuerte del tema la hacía pasar por
       una opción normal que al tocarla no hacía nada. */
    .beply-mb-tab-overflow .dropdown-item.disabled {
        color: var(--beply-mb-fg-mute) !important;
        opacity: .55;
        pointer-events: none;
    }
    .beply-mb-tab-overflow .dropdown-item .badge {
        margin-left: auto;
    }

    /* === Secciones colapsables vía <details> (progressive) ===
       Los EditView del core usan tarjetas Bootstrap; el override Twig
       puede envolver bloques en <details class="beply-mb-section"> */
    .beply-mb-section {
        background: var(--beply-mb-surface);
        border: 1px solid var(--beply-mb-border);
        margin-bottom: var(--beply-mb-gap-md);
        overflow: hidden;
    }
    .beply-mb-section > summary {
        display: flex;
        align-items: center;
        justify-content: space-between;
        list-style: none;
        cursor: pointer;
        padding: 14px var(--beply-mb-pad);
        font-weight: 600;
        font-size: var(--beply-mb-fs-base);
        min-height: var(--beply-mb-tap);
        background: var(--beply-mb-surface);
    }
    .beply-mb-section > summary::-webkit-details-marker { display: none; }
    .beply-mb-section > summary::after {
        content: '\f078'; /* chevron-down FA */
        font-family: 'Font Awesome 6 Free', 'FontAwesome', sans-serif;
        font-weight: 900;
        margin-left: 12px;
        font-size: 12px;
        color: var(--beply-mb-fg-mute);
        transition: transform 0.2s ease;
    }
    .beply-mb-section[open] > summary::after {
        transform: rotate(180deg);
    }
    .beply-mb-section > .beply-mb-section__body {
        padding: var(--beply-mb-pad);
        border-top: 1px solid var(--beply-mb-border);
    }

    /* === Cards Bootstrap dentro de EditView: hacerlas más compactas === */
    .card .card-header {
        padding: var(--beply-mb-gap-md) var(--beply-mb-pad);
        font-weight: 600;
    }
    .card .card-body {
        padding: var(--beply-mb-pad);
    }

    /* === Sticky footer con acciones (Guardar / Eliminar) ===
       Aplica solo en formularios marcados con .beply-mb-form.
       Cuando esta barra existe, ocultamos el bottom nav para no duplicar UI. */
    .beply-mb-form-actions {
        /* Mismo anclaje que la barra de pestañas, que no se mueve: `!important`
           para que nada la desplace y capa propia, que es lo que evita el salto
           mientras el navegador del móvil esconde o muestra su barra de URL. */
        position: fixed !important;
        left: 0 !important;
        right: 0 !important;
        bottom: 0 !important;
        transform: translateZ(0);
        will-change: transform;
        /* El hueco lateral lo pone la barra, NO el primer/último hijo.
           Con `:first-child` el margen se lo llevaba `.beply-mb-mas`, que
           está `display:none` casi siempre, así que el botón visible salía
           pegado a la pared (o desbordando por la izquierda cuando la ficha
           traía más botones). */
        padding: 6px var(--beply-mb-pad) calc(6px + var(--beply-mb-safe-bottom));
        background: var(--beply-mb-surface);
        border-top: 1px solid var(--beply-mb-border);
        display: flex;
        align-items: center;
        gap: var(--beply-mb-gap);
        z-index: var(--beply-mb-z-bottomnav);
        box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.06);
    }
    .beply-mb-form-actions > * {
        margin: 0;
        /* Sin esto un botón con texto largo no encoge y empuja al resto
           fuera de la pantalla. */
        min-width: 0;
    }
    .beply-mb-form-actions .btn {
        flex: 1 1 0;
        min-width: 0;
        /* 44px (el objetivo táctil) en vez de 52: la barra ocupaba casi 72px
           de pantalla, demasiado en una ficha larga. */
        min-height: var(--beply-mb-tap);
        font-weight: 600;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .beply-mb-form-actions .btn-primary,
    .beply-mb-form-actions .btn-success {
        background: var(--beply-mb-accent);
        border-color: var(--beply-mb-accent);
        color: var(--beply-mb-on-accent);
    }
    .beply-mb-form-actions .btn-primary:hover,
    .beply-mb-form-actions .btn-success:hover {
        background: var(--beply-mb-accent-dark, #b00000);
        border-color: var(--beply-mb-accent-dark, #b00000);
    }

    /* Cuando la action bar existe, oculta el bottom nav y reajusta el padding del body */
    body:has(.beply-mb-form-actions[data-beply-bar]) .beply-mb-bottomnav {
        display: none !important;
    }
    /* Y en una ficha se queda oculto SIEMPRE. La barra es de cada pestaña, así
       que en las que no la tienen (direcciones, variantes, listados de la
       ficha) el bottom-nav volvía a asomar: la barra inferior cambiaba sola al
       saltar de pestaña. Dentro de una ficha se sale por el botón atrás. */
    body.beply-mb-ficha .beply-mb-bottomnav {
        display: none !important;
    }
    /* Sin barra abajo tampoco hace falta reservarle sitio. */
    body.beply-mb-ficha:not(:has(.beply-mb-form-actions[data-beply-bar])) {
        padding-bottom: calc(var(--beply-mb-safe-bottom) + 16px) !important;
    }
    body:has(.beply-mb-form-actions[data-beply-bar]) {
        padding-bottom: calc(var(--beply-mb-tap-lg) + 24px + var(--beply-mb-safe-bottom));
    }

    /* Ocultar los botones Guardar / Eliminar nativos: el sticky bar los reemplaza en móvil. */
    [data-beply-mb-hide] {
        display: none !important;
    }

    /* Date / number inputs nativos: aspecto cuidado */
    input[type="date"],
    input[type="time"],
    input[type="datetime-local"],
    input[type="number"],
    input[type="tel"],
    input[type="email"] {
        appearance: none;
        -webkit-appearance: none;
    }

    /* Switch / checkbox más grandes */
    .form-check {
        min-height: var(--beply-mb-tap);
        padding-left: 2.2em;
        display: flex;
        align-items: center;
    }
    .form-check-input {
        width: 1.4em;
        height: 1.4em;
        margin-left: -2.2em;
        margin-top: 0;
    }
    .form-switch .form-check-input {
        width: 2.4em;
        height: 1.4em;
    }

    /* Select2 / autocompletes — si el plugin los usa */
    .select2-container .select2-selection {
        min-height: var(--beply-mb-tap);
        font-size: var(--beply-mb-fs-input);
    }
    .select2-container--default .select2-selection--single .select2-selection__rendered {
        line-height: var(--beply-mb-tap);
        padding-left: 12px;
    }
    .select2-container--default .select2-selection--single .select2-selection__arrow {
        height: var(--beply-mb-tap);
    }
}

/* ============================================================
   EDIT (mobile): consistencia con el tema — sin azules, checks
   tematizados y checkboxes en 2 columnas.
   ============================================================ */
@media (max-width: 767.98px) {
    /* Checks/radios en negro del tema (no azul Bootstrap) — global móvil */
    input[type="checkbox"],
    input[type="radio"] {
        accent-color: var(--beply-mb-fg-strong, #000);
    }
    /* Enlaces de campo del Edit (subcuentas, selectores…) en negro, no azul */
    form[id^="formEdit"] a:not(.btn):not(.nav-link):not(.dropdown-item):not(.page-link) {
        color: var(--beply-mb-fg-strong, #000);
        text-decoration: none;
    }
    /* Checkboxes del Edit → 2 por fila (no desperdiciar alto) */
    form[id^="formEdit"] .row > .col-sm-auto:has(.form-check),
    form[id^="formEdit"] .row > .col-auto:has(.form-check) {
        flex: 0 0 50% !important;
        max-width: 50% !important;
        align-self: flex-start;
    }
    /* form-check a flex limpio: el input de FS lleva float:left + margin-left
       negativo de Bootstrap y se pegaba/descolocaba. Lo alineamos como en los
       filtros: check + texto con separación, sin floats. */
    form[id^="formEdit"] .form-check {
        display: flex !important;
        align-items: flex-start;
        gap: 9px;
        padding: 8px 8px 8px 0 !important;
        margin: 0 !important;
        min-height: 0;
    }
    form[id^="formEdit"] .form-check > .form-check-input,
    form[id^="formEdit"] .form-check > input[type="checkbox"] {
        margin: 1px 0 0 !important;
        float: none !important;
        flex: 0 0 auto;
        width: 18px;
        height: 18px;
    }
    form[id^="formEdit"] .form-check > label {
        margin: 0 !important;
        line-height: 1.25;
        text-transform: none;          /* el texto del check NO en mayúsculas */
        letter-spacing: 0;
        font-weight: 500;
        color: var(--beply-mb-fg-strong, #000) !important;
    }
}

/* Checkboxes/radios de Bootstrap (.form-check-input) marcados → negro del
   tema (no azul). accent-color no les afecta (usan background propio).
   Global móvil: aplica a Edit, filtros y menú Campos por igual. */
@media (max-width: 767.98px) {
    .form-check-input:checked {
        background-color: var(--beply-mb-fg-strong, #000) !important;
        border-color: var(--beply-mb-fg-strong, #000) !important;
    }
    .form-check-input:focus {
        border-color: var(--beply-mb-fg-strong, #000);
        box-shadow: 0 0 0 .2rem rgba(0, 0, 0, .12);
    }
}

/* Quitar el "card" del Edit en móvil: form plano, sin borde ni recuadro. */
@media (max-width: 767.98px) {
    form[id^="formEdit"]:not([id^="formModal"]) {
        border: 0 !important;
        box-shadow: none !important;
        background: var(--beply-mb-surface, #fff) !important;
    }
}

/* ============================================================
   PESTAÑAS del Edit = idénticas a las del listado (barra negra,
    inactivas blanco-tenue,
    activa caja blanca,
    scroll horizontal).
   Los PanelController de FS usan DOS marcados según `setTabsPosition`:
     · `left` (por defecto) → `.nav.nav-pills.flex-row`
     · `bottom` → `.nav.nav-pills.nav-pills-scroll` (EditRole, EditSerie,
       EditImpuesto… 28 vistas del core)
   El segundo se quedaba fuera de esta barra: sus pestañas heredaban el
   blanco pensado para el fondo negro y salían BLANCAS SOBRE BLANCO, o sea
   invisibles. Las dos formas se tratan igual: subpáginas en barra negra.
   ============================================================ */
@media (max-width: 767.98px),
    scroll horizontal).
   Los PanelController de FS usan `.nav.nav-pills.nav-pills-scroll`.
   ============================================================ */
@media (max-width: 767.98px) {.nav-pills.flex-row,
    .nav-pills.nav-pills-scroll {
        /* full-bleed a todo el ancho del viewport (como el header negro) */
        width: 100vw;
        max-width: 100vw;
        margin-left: calc(-50vw + 50%) !important;
        margin-right: calc(-50vw + 50%) !important;
        margin-bottom: 0 !important;
        background: var(--beply-mb-primary) !important;
        display: flex !important;
        flex-direction: row !important;
        flex-wrap: nowrap !important;
        overflow-x: auto;
        scrollbar-width: none;
        gap: 2px;
    }.nav-pills.flex-row::-webkit-scrollbar,
    .nav-pills.nav-pills-scroll::-webkit-scrollbar { display: none; }.nav-pills.flex-row > .nav-item,
    .nav-pills.nav-pills-scroll > .nav-item { flex: 0 0 auto; }.nav-pills.flex-row .nav-link,
    .nav-pills.nav-pills-scroll .nav-link {
        flex: 0 0 auto;
        border: 0 !important;
        border-radius: 0 !important;
        background: transparent !important;
        color: rgba(255, 255, 255, 0.62) !important;
        padding: 12px 14px !important;
        font-weight: 600;
        white-space: nowrap;
    }.nav-pills.flex-row .nav-link:hover,
    .nav-pills.nav-pills-scroll .nav-link:hover { color: #fff !important; }.nav-pills.flex-row .nav-link.active,
    .nav-pills.nav-pills-scroll .nav-link.active {
        background: var(--beply-mb-surface, #fff) !important;
        color: var(--beply-mb-fg-strong, #000) !important;
        font-weight: 700;
    }/* badge contador dentro de la pestaña */
    .nav-pills.flex-row .nav-link .badge,
    /* badge contador dentro de la pestaña */
    .nav-pills.nav-pills-scroll .nav-link .badge {
        background: rgba(255, 255, 255, 0.18) !important;
        color: #fff !important;
        border-radius: 2px;
        margin-left: 6px;
        font-weight: 600;
    }.nav-pills.flex-row .nav-link.active .badge,
    .nav-pills.nav-pills-scroll .nav-link.active .badge {
        background: var(--beply-mb-fg-strong, #000) !important;
        color: #fff !important;
    }

    /* === Editor de documentos (Factura/Albarán/Pedido/Presupuesto) ===
       Normaliza la paleta: el documento trae botones Bootstrap de colores
       (info cian, success verde, secondary gris) que rompen el blanco/negro/
       rojo. Paleta Beply: acción primaria = NEGRO, peligro = ROJO. */

    /* Picker de producto (icono libro, btn-info) y "Firmar factura" → negro */
    .btn.btn-info {
        background: var(--beply-mb-primary) !important;
        border-color: var(--beply-mb-primary) !important;
        color: var(--beply-mb-on-primary) !important;
    }

    /* "+ Línea", "Nuevo" y demás btn-success de los documentos → negro
       (el "Nuevo" del listado ya se oculta vía FAB; aquí cubrimos el editor) */
    .btn.btn-success {
        background: var(--beply-mb-primary) !important;
        border-color: var(--beply-mb-primary) !important;
        color: var(--beply-mb-on-primary) !important;
    }

    /* Guardar del documento (btn-primary, onclick salesFormSave/purchasesFormSave)
       → negro, primaria. El Eliminar (btn-danger) se queda rojo para diferenciar. */
    .btn.btn-primary {
        background: var(--beply-mb-primary) !important;
        border-color: var(--beply-mb-primary) !important;
        color: var(--beply-mb-on-primary) !important;
    }
    .btn.btn-danger {
        background: var(--beply-mb-danger) !important;
        border-color: var(--beply-mb-danger) !important;
        color: var(--beply-mb-on-accent) !important;
    }

    /* Barra de estado del documento ("Boceto"/"Emitida"…, btn-secondary full
       width) → negra con texto blanco, como las pestañas. */
    .dropdown > .btn.w-100.btn-secondary.dropdown-toggle,
    .dropdown > .btn.btn-secondary.dropdown-toggle.btn-spin-action {
        background: var(--beply-mb-primary) !important;
        border-color: var(--beply-mb-primary) !important;
        color: var(--beply-mb-on-primary) !important;
    }

    /* La barra sticky de acciones: Guardar primaria NEGRA (no roja) y, si hay
       Eliminar, queda en rojo de contorno (ya definido como btn-outline-danger). */
    .beply-mb-form-actions .btn-primary,
    .beply-mb-form-actions .btn-success {
        background: var(--beply-mb-primary) !important;
        border-color: var(--beply-mb-primary) !important;
        color: var(--beply-mb-on-primary) !important;
    }
    .beply-mb-form-actions .btn-primary:hover,
    .beply-mb-form-actions .btn-success:hover {
        background: #1a1a1a !important;
        border-color: #1a1a1a !important;
    }

    /* Labels-enlace azules de los campos del documento (Cliente, Serie, Forma
       de pago…): FS los pinta como <a> azul (rgb 13,110,253). Los pasamos a
       texto oscuro tipo label; siguen siendo clicables. Excluimos enlaces de
       cabeceras de tabla (th) y dropdowns. */
    .mb-2 > a:not(.btn):not(.dropdown-item):not(.badge):not(.nav-link),
    .mb-3 > a:not(.btn):not(.dropdown-item):not(.badge):not(.nav-link),
    [id$="-methods"] > a:not(.btn):not(.dropdown-item) {
        color: var(--beply-mb-fg-strong) !important;
        font-weight: 600;
        text-decoration: none;
    }

    /* Cabecera de documento compactada: los campos intermedios en 2 columnas
       (Serie/Fecha, Número 2/Forma de pago) y Cliente + Total a ancho completo
       — así se reduce el scroll hasta las líneas. (marcada por compactDocHeader) */
    .beply-mb-dochead > [class*="col-"] {
        flex: 0 0 50% !important;
        max-width: 50% !important;
    }
    .beply-mb-dochead > [class*="col-"]:first-child,
    .beply-mb-dochead > [class*="col-"]:last-child {
        flex: 0 0 100% !important;
        max-width: 100% !important;
    }
}

/* ============================================================
   LÍNEAS DE DOCUMENTO PLEGADAS (factura, albarán, pedido…)
   ============================================================
   Medido antes de tocar nada: cada línea ocupaba 559 px, así que una
   factura de dos líneas eran 3,1 pantallas de scroll y una de seis
   rondaba las siete. Revisar un documento en el móvil era inviable.

   Ahora cada línea se pliega a una fila de 64 px con lo que de verdad
   se consulta —descripción, cantidad × precio y subtotal— y se abre al
   tocarla. Es un acordeón: sólo una abierta a la vez.

   Sólo se oculta el bloque de detalle; los inputs siguen en el DOM y se
   envían igual, así que FacturaScripts no se entera.
   ============================================================ */
@media (max-width: 767.98px) {
    .beply-mb-line {
        padding: 0 !important;
    }
    .beply-mb-line__resumen {
        display: flex;
        align-items: center;
        gap: 10px;
        width: 100%;
        min-height: 64px;
        padding: 10px var(--beply-mb-pad);
        background: var(--beply-mb-surface, #fff);
        border: 0;
        border-bottom: 1px solid var(--beply-mb-border);
        border-radius: 0;
        text-align: left;
        cursor: pointer;
    }
    .beply-mb-line__txt {
        flex: 1 1 auto;
        min-width: 0;
        display: flex;
        flex-direction: column;
        gap: 2px;
    }
    .beply-mb-line__desc {
        font-weight: 600;
        font-size: 15px;
        color: var(--beply-mb-fg-strong);
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    .beply-mb-line__calc {
        font-size: 12.5px;
        color: var(--beply-mb-fg-mute);
    }
    .beply-mb-line__total {
        flex: 0 0 auto;
        font-weight: 700;
        font-size: 15px;
        color: var(--beply-mb-fg-strong);
        font-variant-numeric: tabular-nums;
    }
    .beply-mb-line__chev {
        flex: 0 0 auto;
        font-size: 12px;
        color: var(--beply-mb-fg-soft);
    }

    /* El formulario de la línea sólo se ve dentro de la hoja (más abajo). */
    .beply-mb-line > .row {
        display: none !important;
    }

    /* Mientras se arrastra para reordenar. */
    .beply-mb-line.is-dragging {
        position: relative;
        z-index: 5;
        box-shadow: 0 10px 24px rgba(0, 0, 0, 0.18);
    }
    .beply-mb-line.is-dragging .beply-mb-line__resumen {
        background: var(--beply-mb-surface-2, #f4f5f7);
    }
    body.beply-mb-arrastrando {
        touch-action: none;
        user-select: none;
    }

    /* El campo de cantidad venía a 14px y Safari hace zoom al enfocar
       cualquier campo por debajo de 16px, descolocando la página. */
    .doc-line-qty,
    .doc-line-desc {
        font-size: 16px !important;
    }
}

/* ============================================================
   FICHA DE LÍNEA A PANTALLA COMPLETA
   ============================================================
   El formulario de una línea son ocho columnas pensadas para una tabla de
   escritorio (referencia, descripción, cantidad, precio, dto, impuesto,
   neto, subtotal). Desplegado dentro del documento ocupaba ~560px y dejaba
   la factura ilegible.

   Ahora la fila resumen abre una hoja: primero la ficha en lectura y, con
   Editar, los campos de verdad. Son dos capas `position: fixed` colgando de
   la propia `.fs-line`, así que los inputs nunca salen del <form> y
   FacturaScripts sigue enviándolos igual. Las alturas de cabecera y pie son
   fijas porque el bloque de edición se posiciona entre ellas.
   ============================================================ */
@media (max-width: 767.98px) {
    :root {
        --beply-mb-lsheet-head: 56px;
        /* 10 + 52 + 10 de relleno más 1 de borde: el bloque de edición se
           apoya justo encima del pie, medido, no a ojo. */
        --beply-mb-lsheet-foot: calc(73px + var(--beply-mb-safe-bottom));
    }

    body.beply-mb-lsheet-abierta {
        overflow: hidden;
    }

    .beply-mb-lsheet {
        display: none;
        position: fixed;
        inset: 0;
        z-index: var(--beply-mb-z-sheet);
        flex-direction: column;
        background: var(--beply-mb-surface, #fff);
    }
    .beply-mb-line.is-open > .beply-mb-lsheet {
        display: flex;
    }

    .beply-mb-lsheet__head {
        flex: 0 0 var(--beply-mb-lsheet-head);
        display: flex;
        align-items: center;
        gap: 10px;
        padding-inline: 6px var(--beply-mb-pad);
        background: var(--beply-mb-primary);
        color: #fff;
    }
    .beply-mb-lsheet__cerrar {
        flex: 0 0 auto;
        width: 44px;
        height: 44px;
        border: 0;
        background: none;
        color: #fff;
        font-size: 18px;
    }
    .beply-mb-lsheet__titulo {
        flex: 1 1 auto;
        min-width: 0;
        font-size: 16px;
        font-weight: 600;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    .beply-mb-lsheet__tot {
        flex: 0 0 auto;
        font-size: 16px;
        font-weight: 700;
        font-variant-numeric: tabular-nums;
    }

    .beply-mb-lsheet__body {
        flex: 1 1 auto;
        /* sin esto el bloque no encoge por debajo de su contenido y empuja el
           pie fuera de la pantalla */
        min-height: 0;
        overflow-y: auto;
        padding: 0 var(--beply-mb-pad);
        -webkit-overflow-scrolling: touch;
    }
    .beply-mb-line.is-editing .beply-mb-lsheet__body {
        visibility: hidden;
    }
    .beply-mb-lsheet__campo {
        display: flex;
        align-items: baseline;
        gap: 12px;
        padding: 13px 0;
        border-bottom: 1px solid var(--beply-mb-border);
    }
    .beply-mb-lsheet__et {
        flex: 0 0 40%;
        font-size: 12px;
        font-weight: 700;
        letter-spacing: 0.05em;
        text-transform: uppercase;
        color: var(--beply-mb-fg-mute);
    }
    .beply-mb-lsheet__vl {
        flex: 1 1 auto;
        min-width: 0;
        font-size: 16px;
        color: var(--beply-mb-fg-strong);
        overflow-wrap: anywhere;
    }

    .beply-mb-lsheet__foot {
        flex: 0 0 auto;
        display: flex;
        gap: 10px;
        padding: 10px var(--beply-mb-pad);
        padding-bottom: calc(10px + var(--beply-mb-safe-bottom));
        border-top: 1px solid var(--beply-mb-border);
        background: var(--beply-mb-surface, #fff);
    }
    .beply-mb-lsheet__foot > .btn {
        flex: 1 1 0;
        min-height: var(--beply-mb-tap-lg);
        border-radius: 0;
        font-weight: 600;
    }
    /* Se pintan con las variables de Bootstrap en vez de con `background` y
       `color` sueltos: `.btn:hover` tiene más peso que una clase y, en cuanto
       el dedo o el ratón se quedan encima, devolvía el botón a su gris. */
    .beply-mb-lsheet__borrar {
        flex: 0 0 auto !important;
        min-width: 52px;
        --bs-btn-bg: var(--beply-mb-surface, #fff);
        --bs-btn-color: var(--beply-mb-danger);
        --bs-btn-border-color: var(--beply-mb-danger);
        --bs-btn-hover-bg: var(--beply-mb-danger-soft, #fef0f0);
        --bs-btn-hover-color: var(--beply-mb-danger);
        --bs-btn-hover-border-color: var(--beply-mb-danger);
        --bs-btn-active-bg: var(--beply-mb-danger-soft, #fef0f0);
        --bs-btn-active-color: var(--beply-mb-danger);
        --bs-btn-active-border-color: var(--beply-mb-danger);
    }
    .beply-mb-lsheet__editar,
    .beply-mb-lsheet__hecho {
        --bs-btn-bg: var(--beply-mb-primary);
        --bs-btn-color: #fff;
        --bs-btn-border-color: var(--beply-mb-primary);
        --bs-btn-hover-bg: var(--beply-mb-primary);
        --bs-btn-hover-color: #fff;
        --bs-btn-hover-border-color: var(--beply-mb-primary);
        --bs-btn-active-bg: var(--beply-mb-primary);
        --bs-btn-active-color: #fff;
        --bs-btn-active-border-color: var(--beply-mb-primary);
    }

    /* --- modo edición: el .row real de la línea, entre cabecera y pie --- */
    .beply-mb-line.is-editing > .row {
        display: flex !important;
        position: fixed;
        left: 0;
        right: 0;
        top: var(--beply-mb-lsheet-head);
        bottom: var(--beply-mb-lsheet-foot);
        z-index: calc(var(--beply-mb-z-sheet) + 1);
        align-content: flex-start;
        overflow-y: auto;
        margin: 0;
        padding: 0 var(--beply-mb-pad) 20px;
        background: var(--beply-mb-surface, #fff);
        border: 0 !important;
    }
    .beply-mb-line.is-editing > .row > [class*="col-"] {
        width: 100%;
        max-width: none;
        flex: 0 0 auto;
        padding-inline: 0;
    }
    /* Los rótulos que el core sólo enseña fuera de escritorio hacen de label. */
    .beply-mb-line.is-editing > .row .d-lg-none {
        margin-top: 14px !important;
        font-size: 12px;
        font-weight: 700;
        letter-spacing: 0.05em;
        text-transform: uppercase;
        color: var(--beply-mb-fg-mute);
    }
    /* La referencia no es un campo: es el producto de la línea. */
    .beply-mb-line.is-editing > .row > .order-1 > .small {
        font-size: 16px !important;
    }
    .beply-mb-line.is-editing > .row > .order-1 a {
        color: var(--beply-mb-fg-strong);
        font-weight: 600;
        text-decoration: none;
    }
    .beply-mb-line.is-editing > .row .form-control,
    .beply-mb-line.is-editing > .row .form-select {
        border: 1px solid var(--beply-mb-border) !important;
        min-height: var(--beply-mb-tap);
    }
    /* Neto y subtotal por línea sobran: el total sale en la cabecera de la
       hoja y se actualiza con cada recálculo. */
    .beply-mb-line.is-editing > .row > .columNeto,
    .beply-mb-line.is-editing > .row > .columSubtotal {
        display: none !important;
    }
    /* Eliminar ya está en el pie de la hoja. */
    .beply-mb-line.is-editing > .row > .col-auto > .btn-danger {
        display: none !important;
    }
    .beply-mb-line.is-editing > .row > .col-auto {
        margin-top: 18px;
    }
    .beply-mb-line.is-editing > .row > .col-auto > .btn-light {
        width: 100%;
        min-height: var(--beply-mb-tap);
        margin-right: 0 !important;
        border: 1px solid var(--beply-mb-border);
    }
    /* La referencia de una línea sin producto es sólo el número de orden. */
    .beply-mb-line.is-editing > .row > .order-1:not(:has([name^="referencia_"])) {
        display: none !important;
    }
}

/* ============================================================
   ZOOM DE iOS AL ENFOCAR UN CAMPO
   ============================================================
   Safari en iPhone hace zoom automático sobre cualquier campo de texto
   con fuente por debajo de 16px: la página salta, se descoloca y hay
   que volver a alejarla con los dedos. Quedaban algunos campos a 13-14px.
   Subirlos a 16px lo evita; es la única forma sin desactivar el zoom
   general de la página, que sí haría falta para accesibilidad.
   ============================================================ */
@media (max-width: 767.98px) {
    input[type="text"],
    input[type="search"],
    input[type="email"],
    input[type="tel"],
    input[type="url"],
    input[type="password"],
    input[type="number"],
    input[type="date"],
    input[type="datetime-local"],
    input[type="time"],
    textarea,
    select {
        font-size: max(16px, 1rem);
    }
}

/* ============================================================
   ZONA DE AÑADIR LÍNEA
   ============================================================
   Antes: cinco controles al mismo nivel justo debajo de las líneas
   (buscar referencia, "+ Línea", "Mover líneas", código de barras y el
   conmutador Neto/Subtotal). Tres formas distintas de añadir una línea
   compitiendo entre sí, más dos ajustes que en un teléfono no sirven.

   Queda UNA: "Añadir línea", con el mismo aspecto que el alta de los
   EditListView (tarjeta de borde discontinuo, no botón sólido), y el
   producto se busca dentro de la ficha de la línea. Mover líneas lo
   sustituye la pulsación larga sobre la fila; el buscador suelto, el
   lector de códigos de barras y el conmutador neto/subtotal se van.
   ============================================================ */
@media (max-width: 767.98px) {
    .beply-mb-docactions {
        display: flex !important;
        flex-wrap: wrap !important;
        align-items: flex-start;
    }
    /* Se ocultan desde el pie, no desde `.beply-mb-docactions`: esa marca la
       pone el JS a partir del buscador de referencia, que en un documento ya
       cerrado no existe — y entonces el conmutador Neto/Subtotal reaparecía. */
    #salesFormFooter .container-fluid > .row > div:has(#sortableBtn),
    #salesFormFooter .container-fluid > .row > div:has(#columnView),
    #salesFormFooter .container-fluid > .row > div:has(#findProductInput),
    #salesFormFooter .container-fluid > .row > div:has([name="fastli"]),
    #purchasesFormFooter .container-fluid > .row > div:has(#sortableBtn),
    #purchasesFormFooter .container-fluid > .row > div:has(#columnView),
    #purchasesFormFooter .container-fluid > .row > div:has(#findProductInput),
    #purchasesFormFooter .container-fluid > .row > div:has([name="fastli"]) {
        display: none !important;
    }
    .beply-mb-docactions > div:has(a[onclick*="new-line"]) {
        flex: 1 1 100%;
        width: 100% !important;
        max-width: none !important;
        /* 8 del form + 8 de la fila = el mismo canal de 16px que el resto de
           la página. Con `--beply-mb-pad` aquí encima el botón se metía hacia
           dentro y quedaba más estrecho que todo lo demás. */
        padding: 12px 0 !important;
    }
    /* Mismo lenguaje que el alta de un EditListView. El botón del core es
       `btn-success` y la regla general lo pinta de negro con `!important`, así
       que hay que fijar el aspecto en todos los estados o al pulsarlo vuelve. */
    .beply-mb-docactions a[onclick*="new-line"],
    .beply-mb-docactions a[onclick*="new-line"]:hover,
    .beply-mb-docactions a[onclick*="new-line"]:focus,
    .beply-mb-docactions a[onclick*="new-line"]:focus-visible,
    .beply-mb-docactions a[onclick*="new-line"]:active {
        display: flex !important;
        align-items: center;
        justify-content: center;
        gap: 8px;
        width: 100%;
        min-height: var(--beply-mb-tap);
        margin: 0 !important;
        border-radius: 0;
        background: var(--beply-mb-surface) !important;
        border: 1px dashed var(--beply-mb-accent) !important;
        color: var(--beply-mb-accent) !important;
        box-shadow: none !important;
        font-weight: 600;
    }
    .beply-mb-docactions a[onclick*="new-line"] i,
    .beply-mb-docactions a[onclick*="new-line"] svg {
        color: currentColor !important;
        fill: currentColor !important;
    }
}

/* ============================================================
   DOCUMENTO SIN LÍNEAS
   ============================================================
   El core pinta una banda amarilla (`table-warning`) explicando que se
   añade producto "con el botón producto, el campo código de barras o el
   botón línea" — tres controles que en móvil ya no existen. El texto se
   cambió en `Translation/` por uno que vale también en escritorio; aquí
   se le quita el amarillo: es un estado vacío, no un aviso.
   ============================================================ */
@media (max-width: 767.98px) {
    #salesFormLines .table-warning,
    #purchasesFormLines .table-warning {
        background: transparent !important;
        --bs-table-bg: transparent !important;
        --bs-table-accent-bg: transparent !important;
        color: var(--beply-mb-fg-mute) !important;
        padding: 22px var(--beply-mb-pad) 6px !important;
        font-size: 14px;
    }
}

/* ============================================================
   BUSCAR PRODUCTO DENTRO DE LA FICHA DE LA LÍNEA
   ============================================================
   El concepto y la referencia van juntos: se busca el producto justo
   encima de la descripción, no en un campo suelto en otra parte de la
   página. Sólo sale en líneas que aún no tienen producto — el core no
   sabe cambiarle el producto a una línea que ya existe.
   ============================================================ */
@media (max-width: 767.98px) {
    .beply-mb-lref {
        order: -1;
        width: 100%;
        position: relative;
    }
    .beply-mb-lref__et {
        margin-top: 14px;
        font-size: 12px;
        font-weight: 700;
        letter-spacing: 0.05em;
        text-transform: uppercase;
        color: var(--beply-mb-fg-mute);
    }
    .beply-mb-lref__input {
        min-height: var(--beply-mb-tap);
        border: 1px solid var(--beply-mb-border) !important;
        border-radius: 0;
    }
    .beply-mb-lref__lista {
        position: absolute;
        z-index: 3;
        left: 0;
        right: 0;
        max-height: 42vh;
        overflow-y: auto;
        background: var(--beply-mb-surface, #fff);
        border: 1px solid var(--beply-mb-border);
        box-shadow: 0 8px 28px rgba(0, 0, 0, 0.14);
    }
    .beply-mb-lref__op {
        display: flex;
        flex-direction: column;
        gap: 2px;
        width: 100%;
        min-height: 52px;
        padding: 8px var(--beply-mb-pad);
        border: 0;
        border-bottom: 1px solid var(--beply-mb-border);
        background: var(--beply-mb-surface, #fff);
        text-align: left;
    }
    .beply-mb-lref__op:disabled {
        color: var(--beply-mb-fg-mute);
        justify-content: center;
    }
    .beply-mb-lref__ref {
        font-size: 15px;
        font-weight: 700;
        color: var(--beply-mb-fg-strong);
    }
    .beply-mb-lref__desc {
        font-size: 13px;
        color: var(--beply-mb-fg-mute);
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
}

/* ============================================================
   PIE DE TOTALES DEL DOCUMENTO
   ============================================================
   Cada importe (neto, impuestos, retenciones, coste, total) venía como
   campo a ancho completo con la etiqueta encima: ~75px por línea, cerca
   de 400px sólo para el pie. En un móvil eso es media pantalla de
   números que sólo se consultan.

   Se ponen a dos columnas y el último —el total, que es el que se mira—
   ocupa el ancho entero y va destacado.
   ============================================================ */
@media (max-width: 767.98px) {
    /* Igual que la cabecera: la fila se disuelve y sus columnas se colocan
       sueltas. Así observaciones puede bajar con los datos del documento
       mientras los importes se quedan aquí. */
    .beply-mb-doctotales {
        display: contents !important;
    }
    .beply-mb-doctotales > [class*="col-"] {
        order: 5;
        width: 50%;
        max-width: none !important;
        flex: 0 0 auto !important;
        padding: 0 8px !important;
        margin-top: 6px;
    }
    .beply-mb-doctotales > [class*="col-"] > .mb-2 {
        margin: 0 !important;
        font-size: 11px;
        font-weight: 700;
        letter-spacing: 0.05em;
        text-transform: uppercase;
        color: var(--beply-mb-fg-mute);
    }
    .beply-mb-doctotales .form-control {
        min-height: 40px;
        padding: 6px 10px;
        text-align: right;
        font-weight: 600;
        font-variant-numeric: tabular-nums;
        background: var(--beply-mb-surface-2, #f6f6f7) !important;
    }
    /* El total va en su casilla, como los demás importes: a lo ancho pesaba
       más que el propio documento. */
    .beply-mb-doctotales > [class*="col-"]:last-child > .mb-2 {
        color: var(--beply-mb-fg-strong);
    }
    .beply-mb-doctotales > [class*="col-"]:last-child > .mb-2 {
        color: var(--beply-mb-fg-strong);
    }
    .beply-mb-doctotales > [class*="col-"]:last-child .form-control {
        min-height: 48px;
        font-size: 18px;
        font-weight: 700;
        color: #fff;
        background: var(--beply-mb-primary) !important;
        border-color: var(--beply-mb-primary);
    }

    /* Observaciones no es un importe: no pinta nada en medio de los totales.
       Baja con serie, número 2 y forma de pago, que es donde se rellena. */
    .beply-mb-doctotales > [class*="col-"]:has(textarea) {
        order: 8;
        width: 100%;
        margin-top: 0;
    }
    .beply-mb-doctotales > [class*="col-"]:has(textarea) > .mb-2 {
        font-size: var(--beply-mb-fs-sm);
        letter-spacing: 0;
        text-transform: none;
        color: var(--beply-mb-fg-strong);
    }
    .beply-mb-doctotales > [class*="col-"]:has(textarea) .form-control {
        text-align: left;
        font-weight: 400;
        background: var(--beply-mb-surface, #fff) !important;
    }
}

/* ============================================================
   FICHAS LARGAS A DOS COLUMNAS
   ============================================================
   Una ficha de cliente son 25 campos apilados a ancho completo:
   3,3 pantallas de scroll. beply-mobile.js marca como "media" los
   campos cortos (fechas, selects, importes, códigos) y aquí se
   colocan de dos en dos. Lo que necesita sitio —nombre, dirección,
   correo, observaciones— se queda entero.
   ============================================================ */
@media (max-width: 767.98px) {
    .beply-mb-form .row:has(> .beply-mb-col-media),
    form[id^="formEdit"] .row:has(> .beply-mb-col-media) {
        display: flex;
        flex-wrap: wrap;
    }
    .beply-mb-col-media {
        flex: 0 0 calc(50% - 5px) !important;
        width: calc(50% - 5px) !important;
        max-width: calc(50% - 5px) !important;
    }
    /* etiqueta más discreta para que quepa en media columna */
    .beply-mb-col-media label,
    .beply-mb-col-media .form-label {
        font-size: 10.5px;
        letter-spacing: 0.3px;
    }
}

/* En media columna el texto largo debe recortarse, no crear scroll dentro
   del control (se vio en el select2 de "Estado del documento", con 71px
   de desbordamiento interno). */
@media (max-width: 767.98px) {
    .beply-mb-col-media .form-control,
    .beply-mb-col-media .form-select,
    .beply-mb-col-media .select2-selection,
    .beply-mb-col-media .select2-selection__rendered {
        min-width: 0;
        max-width: 100%;
        overflow: hidden;
        text-overflow: ellipsis;
    }
}

/* ============================================================
   DESPLEGABLES COMO HOJA INFERIOR
   ============================================================
   El <select> nativo abre la rueda del sistema: tapa media pantalla,
   no deja buscar y obliga a leer el valor dentro de una caja estrecha
   (la empresa se veía "BeplyThem…"). Es donde más se notaba que esto
   era una web y no una app.

   El campo pasa a ser un botón a ancho completo y las opciones salen
   en una hoja desde abajo, con filas de 52px y buscador si hay muchas.
   El <select> original sigue en el DOM: se actualiza y dispara `change`,
   así que FacturaScripts recalcula igual.
   ============================================================ */
@media (max-width: 767.98px) {
    /* select2 se inicializa DESPUÉS que el shell, así que ocultar su
       contenedor desde JS no basta: al crearse volvía a aparecer y el campo
       salía duplicado (el botón nuevo y el select2 debajo). Por CSS no
       depende del orden de arranque. */
    select.beply-mb-sel-oculto + .select2-container,
    select.beply-mb-sel-oculto ~ .select2-container {
        display: none !important;
    }

    .beply-mb-sel-oculto {
        position: absolute !important;
        width: 1px !important;
        height: 1px !important;
        /* hay un min-height global de 44px para los campos táctiles y le gana
           a height, dejando una tira de 1x44 px visible */
        min-height: 0 !important;
        padding: 0 !important;
        border: 0 !important;
        opacity: 0 !important;
        overflow: hidden !important;
        clip: rect(0 0 0 0) !important;
        white-space: nowrap !important;
    }

    .beply-mb-selbtn {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 8px;
        width: 100%;
        min-height: var(--beply-mb-tap);
        padding: 8px 12px;
        background: var(--beply-mb-surface, #fff);
        border: 1px solid var(--beply-mb-border);
        border-radius: 0;
        font-size: 16px;
        color: var(--beply-mb-fg-strong);
        text-align: left;
    }
    .beply-mb-selbtn__val {
        flex: 1 1 auto;
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    .beply-mb-selbtn > i {
        flex: 0 0 auto;
        font-size: 12px;
        color: var(--beply-mb-fg-soft);
    }
    .beply-mb-selbtn:focus-visible {
        outline: 3px solid rgba(var(--beply-mb-accent-rgb), 0.4);
        outline-offset: 1px;
    }
    /* campo obligatorio: misma marca roja que el resto de la ficha */
    select[required].beply-mb-sel-oculto + .select2-container + .beply-mb-selbtn,
    select[required].beply-mb-sel-oculto ~ .beply-mb-selbtn {
        border-left: 3px solid var(--beply-mb-accent);
    }

    body.beply-mb-sheet-lock {
        overflow: hidden;
    }
    .beply-mb-sheet {
        position: fixed;
        inset: 0;
        z-index: 2000;
        display: flex;
        align-items: flex-end;
        background: rgba(0, 0, 0, 0.45);
        opacity: 0;
        transition: opacity 0.18s ease;
    }
    .beply-mb-sheet.is-open { opacity: 1; }
    .beply-mb-sheet__panel {
        width: 100%;
        max-height: 78vh;
        display: flex;
        flex-direction: column;
        background: var(--beply-mb-surface, #fff);
        border-top: 3px solid var(--beply-mb-primary);
        transform: translateY(14px);
        transition: transform 0.18s ease;
        padding-bottom: var(--beply-mb-safe-bottom);
    }
    .beply-mb-sheet.is-open .beply-mb-sheet__panel { transform: translateY(0); }

    .beply-mb-sheet__head {
        display: flex;
        align-items: center;
        gap: 10px;
        padding: 14px var(--beply-mb-pad);
        background: var(--beply-mb-primary);
        color: #fff;
    }
    .beply-mb-sheet__title {
        flex: 1 1 auto;
        font-family: var(--beply-mb-font-text);
        font-size: 17px;
        font-weight: 700;
    }
    .beply-mb-sheet__close {
        flex: 0 0 auto;
        width: var(--beply-mb-tap);
        height: var(--beply-mb-tap);
        background: transparent;
        border: 0;
        color: #fff;
        font-size: 18px;
    }
    .beply-mb-sheet__search {
        padding: 10px var(--beply-mb-pad);
        border-bottom: 1px solid var(--beply-mb-border);
    }
    .beply-mb-sheet__input {
        width: 100%;
        min-height: var(--beply-mb-tap);
        padding: 8px 12px;
        font-size: 16px;
        border: 1px solid var(--beply-mb-border);
        border-radius: 0;
    }
    .beply-mb-sheet__list {
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
    }
    .beply-mb-sheet__opt {
        display: block;
        width: 100%;
        min-height: 52px;
        padding: 14px var(--beply-mb-pad);
        background: transparent;
        border: 0;
        border-bottom: 1px solid var(--beply-mb-border);
        border-radius: 0;
        text-align: left;
        font-size: 16px;
        color: var(--beply-mb-fg);
    }
    .beply-mb-sheet__opt.is-sel {
        font-weight: 700;
        color: var(--beply-mb-fg-strong);
        box-shadow: inset 3px 0 0 var(--beply-mb-accent);
    }
    .beply-mb-sheet__opt:focus-visible {
        outline: 3px solid rgba(var(--beply-mb-accent-rgb), 0.4);
        outline-offset: -3px;
    }

    @media (prefers-reduced-motion: reduce) {
        .beply-mb-sheet,
        .beply-mb-sheet__panel { transition: none; }
    }
}

/* Casillas: 18px es demasiado poco para el dedo y quedaban fuera de las
   reglas anteriores, que sólo cubrían el formulario principal y los
   listados. En móvil, todas. */
@media (max-width: 767.98px) {
    input[type="checkbox"].form-check-input,
    input[type="radio"].form-check-input {
        width: 22px;
        height: 22px;
        margin-top: 0.1em;
    }
    .form-check {
        min-height: var(--beply-mb-tap);
        display: flex;
        align-items: center;
        gap: 8px;
    }
    .form-check .form-check-label {
        font-size: 15px;
    }
}

/* ============================================================
   MODALES DE SELECCIÓN COMO HOJA INFERIOR
   ============================================================
   Los buscadores de cliente, proveedor, producto o subcuenta salían
   como tarjeta flotante en el centro: el pulgar tiene que subir a
   media pantalla y la lista queda encajonada. Se comportan igual que
   la hoja de los desplegables — suben desde abajo, cabecera negra y
   filas grandes — para que toda la selección use el mismo gesto.

   Es sólo presentación: sigue siendo el modal de Bootstrap, así que
   conserva su foco atrapado, su Escape y su accesibilidad.
   ============================================================ */
@media (max-width: 767.98px) {
    .modal:not(.beply-mb-trial-modal) .modal-dialog {
        /* mobile-base ya trae reglas para .modal-dialog en móvil y ganaban por
           orden: por eso la hoja salía con 16px de margen a cada lado */
        position: fixed !important;
        left: 0 !important;
        right: 0 !important;
        bottom: 0 !important;
        top: auto !important;
        width: 100% !important;
        max-width: none !important;
        min-height: 0 !important;
        margin: 0 !important;
        padding: 0 !important;
    }
    .modal:not(.beply-mb-trial-modal) .modal-content {
        max-height: 82vh;
        border: 0;
        border-top: 3px solid var(--beply-mb-primary);
        border-radius: 0;
        padding-bottom: var(--beply-mb-safe-bottom);
        box-shadow: 0 -10px 34px rgba(0, 0, 0, 0.22);
    }
    .modal:not(.beply-mb-trial-modal) .modal-header {
        background: var(--beply-mb-primary);
        color: #fff;
        border-bottom: 0;
        border-radius: 0;
        padding: 14px var(--beply-mb-pad);
    }
    .modal:not(.beply-mb-trial-modal) .modal-header .modal-title {
        font-family: var(--beply-mb-font-text);
        font-size: 17px;
        font-weight: 700;
    }
    .modal:not(.beply-mb-trial-modal) .modal-header .btn-close {
        filter: invert(1) grayscale(1) brightness(2);
        opacity: 0.9;
        width: var(--beply-mb-tap);
        height: var(--beply-mb-tap);
    }
    /* OJO: el buscador de productos deja la tabla de resultados FUERA de
       .modal-body, como hermana. Si el body scrolla por su cuenta salen dos
       zonas de scroll y un control queda partido por la mitad (se vio con
       "Ordenar"). Scrolla la hoja entera y el body fluye. */
    .modal:not(.beply-mb-trial-modal) .modal-content {
        display: flex;
        flex-direction: column;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
    }
    /* Un hijo de flex no encoge por debajo de su contenido salvo que se le
       diga: sin esto la tabla de resultados del buscador de productos se
       salía de lado de la hoja. */
    .modal:not(.beply-mb-trial-modal) .modal-content > * {
        min-width: 0;
        max-width: 100%;
    }
    .modal:not(.beply-mb-trial-modal) .modal-body {
        flex: 0 0 auto;
        overflow: visible;
        /* `!important` porque el core pinta varios cuerpos de modal con las
           utilidades de padding de Bootstrap (`p-3`, `p-2`), que llevan su
           propio !important y volvían a meter el canal. */
        padding: 0 !important;
    }
    /* El envoltorio .table-responsive lleva overflow-x:auto, y CSS obliga
       entonces al eje vertical a 'auto': eso creaba un SEGUNDO scroll dentro
       de la hoja y la lista de resultados quedaba encajonada en una franja.
       En móvil la tabla ya cabe a lo ancho, así que el envoltorio no aporta:
       se deja fluir y scrolla la hoja entera. */
    .modal:not(.beply-mb-trial-modal) .table-responsive {
        overflow: visible;
        max-width: 100%;
    }
    .modal:not(.beply-mb-trial-modal) .table-responsive > table {
        width: 100%;
        max-width: 100%;
    }
    /* filas de resultado: mismo tamaño que en la hoja de desplegables */
    .modal:not(.beply-mb-trial-modal) .modal-body .list-group-item,
    .modal:not(.beply-mb-trial-modal) .modal-body a.list-group-item-action {
        min-height: 52px;
        display: flex;
        align-items: center;
        padding: 14px var(--beply-mb-pad);
        border-left: 0;
        border-right: 0;
        border-radius: 0;
        font-size: 16px;
    }
    /* el buscador del modal, separado y a 16px para que iOS no haga zoom */
    .modal:not(.beply-mb-trial-modal) .modal-body .input-group,
    .modal:not(.beply-mb-trial-modal) .modal-body > form {
        padding: 10px var(--beply-mb-pad);
    }
    .modal:not(.beply-mb-trial-modal) .modal-body input.form-control {
        font-size: 16px;
        min-height: var(--beply-mb-tap);
    }
    .modal:not(.beply-mb-trial-modal) .modal-footer {
        border-top: 1px solid var(--beply-mb-border);
        padding: 10px var(--beply-mb-pad);
    }

    /* ------------------------------------------------------------
       MODALES DE FORMULARIO (Detalle del documento, línea…)
       ------------------------------------------------------------
       Todo lo de arriba está pensado para las hojas de selección, donde
       scrolla la hoja entera y el cuerpo va a sangre. Un formulario
       necesita lo contrario: canal lateral y un pie que no se vaya con el
       scroll — el de Detalle son 19 campos, 1500px de alto, y
       Cerrar/Aceptar quedaban fuera de la pantalla.

       Se reconocen por tener campos en columnas y NO tener una lista de
       resultados: el buscador de productos también trae `.row` en el
       cuerpo (sus filtros), así que con eso solo se colaba y le partíamos
       la tabla de resultados, que además cuelga fuera de `.modal-body`.
       ------------------------------------------------------------ */
    .modal:not(.beply-mb-trial-modal):has(.modal-body > .row):not(:has(table.table)):not(:has(.list-group)) .modal-content {
        max-height: calc(100dvh - 48px);
        overflow-y: hidden;
    }
    .modal:not(.beply-mb-trial-modal):has(.modal-body > .row):not(:has(table.table)):not(:has(.list-group)) .modal-body {
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
        /* 4 aquí + 4 de la fila + 8 de cada columna = el canal de 16px de
           toda la app */
        padding: 4px 4px 12px !important;
    }
    .modal:not(.beply-mb-trial-modal):has(.modal-body > .row):not(:has(table.table)):not(:has(.list-group)) .modal-body > .row > [class*="col-"] {
        padding-inline: 8px;
    }
    /* Una `.row` de Bootstrap tira de márgenes negativos para compensar el
       canal de sus columnas; con `.modal-body` a padding 0 eso la sacaba 4px
       por cada lado en TODOS los modales con campos en fila. */
    .modal .modal-body > .row {
        margin-inline: 0;
        padding-inline: 4px;
    }
    .modal:not(.beply-mb-trial-modal):has(.modal-body > .row):not(:has(table.table)):not(:has(.list-group)) .modal-body > .row > [class*="col-"] {
        width: 100%;
        max-width: none;
        flex: 0 0 auto;
    }

    /* Los cortos van de dos en dos: 19 campos apilados eran 1500px de
       scroll para consultar una dirección.

       El criterio lo pone el propio core con el ancho que le da a cada
       campo en escritorio (`col-sm-4`, `col-sm-3`, `col-6` = campo corto).
       Ir por `name` no vale: en un documento con contacto de facturación
       elegido, dirección, apartado, código postal, ciudad y provincia
       salen `disabled` y SIN atributo `name`, así que no los alcanzaba
       ningún selector y se quedaban todos a lo ancho. */
    .modal:has(.modal-body > .row):not(:has(table.table)):not(:has(.list-group)) .modal-body > .row > .col-sm-4,
    .modal:has(.modal-body > .row):not(:has(table.table)):not(:has(.list-group)) .modal-body > .row > .col-sm-3,
    .modal:has(.modal-body > .row):not(:has(table.table)):not(:has(.list-group)) .modal-body > .row > .col-6 {
        width: 50%;
    }

    /* Unos rótulos son texto y otros son enlaces al registro relacionado
       (País, Divisa, Dirección de facturación): salían en negrita y negro
       entre los demás en gris, como si fueran más importantes. Aquí son
       todos etiquetas. */
    .modal:has(.modal-body > .row):not(:has(table.table)):not(:has(.list-group)) .modal-body .mb-2 > a:not(.btn) {
        font-weight: 400;
        color: inherit !important;
        text-decoration: none;
    }

    /* Rótulos de sección: 19 campos seguidos no se leen, y el core no trae
       ninguna marca para agruparlos. */
    .modal .modal-body > .row > [class*="col-"]:has(select[name="idcontactoenv"], select[id$="idcontactoenv"])::before,
    .modal .modal-body > .row > [class*="col-"]:has([name="coddivisa"])::before {
        display: block;
        margin: 14px 0 2px;
        font-size: 11px;
        font-weight: 700;
        letter-spacing: 0.06em;
        text-transform: uppercase;
        color: var(--beply-mb-fg-mute);
    }
    .modal .modal-body > .row > [class*="col-"]:has(select[name="idcontactoenv"], select[id$="idcontactoenv"])::before {
        content: "Envío";
    }
    .modal .modal-body > .row > [class*="col-"]:has([name="coddivisa"])::before {
        content: "Otros datos";
    }
    /* El campo que lleva el rótulo va a lo ancho: si no, el título de la
       sección ocupa media línea y el campo de al lado se le sube al lado. */
    .modal .modal-body > .row > [class*="col-"]:has(select[name="idcontactoenv"], select[id$="idcontactoenv"]),
    .modal .modal-body > .row > [class*="col-"]:has([name="coddivisa"]) {
        width: 100%;
    }

    /* El pie se queda a la vista y con los botones de siempre. */
    .modal:not(.beply-mb-trial-modal):has(.modal-body > .row):not(:has(table.table)):not(:has(.list-group)) .modal-footer {
        flex: 0 0 auto;
        flex-wrap: nowrap;
        gap: 10px;
        background: var(--beply-mb-surface, #fff);
    }
    .modal:not(.beply-mb-trial-modal):has(.modal-body > .row):not(:has(table.table)):not(:has(.list-group)) .modal-footer > .btn {
        flex: 1 1 0;
        min-height: var(--beply-mb-tap-lg);
        margin: 0;
        border-radius: 0;
        font-weight: 600;
    }

    @media (prefers-reduced-motion: no-preference) {
        .modal.fade:not(.beply-mb-trial-modal) .modal-dialog {
            transition: transform 0.2s ease-out;
            transform: translateY(16px);
        }
        .modal.fade.show:not(.beply-mb-trial-modal) .modal-dialog {
            transform: translateY(0);
        }
    }
}

/* El botón que sustituye a un <select> tiene que comportarse como un miembro
   más del .input-group cuando el campo lleva icono delante. Si no, se va a la
   línea siguiente y el icono queda suelto encima (pasaba en cualquier
   desplegable con icono: idioma, país, régimen…). */
@media (max-width: 767.98px) {
    .input-group > .beply-mb-selbtn {
        flex: 1 1 auto;
        width: 1%;
        min-width: 0;
        margin-left: -1px;
        border-top-left-radius: 0;
        border-bottom-left-radius: 0;
    }
}

/* ============================================================
   MISMA ALTURA PARA TODOS LOS CAMPOS
   ============================================================
   Los inputs de texto salían a 46px (padding 10px arriba y abajo) y los
   desplegables a 44px (padding 8px): dos alturas distintas en la misma
   ficha, y se notaba al mirar una columna de campos.

   Se igualan a 44px, que además es el objetivo táctil de la app
   (--beply-mb-tap). El textarea conserva su altura de varias líneas.
   ============================================================ */
@media (max-width: 767.98px) {
    .form-control,
    .form-select,
    .input-group-text,
    .beply-mb-selbtn {
        min-height: var(--beply-mb-tap);
        padding-top: 8px;
        padding-bottom: 8px;
    }
    textarea.form-control {
        min-height: calc(var(--beply-mb-tap) * 2);
    }
}

/* ============================================================
   LA FICHA NO ES UNA TARJETA FLOTANTE EN EL MÓVIL
   ============================================================
   En escritorio la ficha es un card blanco sobre fondo gris, que ahí
   tiene sentido porque hay espacio alrededor. En un móvil el card ocupa
   todo el ancho, así que el marco y el fondo gris sólo restan sitio y
   añaden ruido: el contenido va a sangre.

   El pie del card, además, repetía acciones que ya viven en la barra
   fija (borrar) o que no aportan (recargar); las propias del modelo
   pasan al menú "⋯" de esa barra.
   ============================================================ */
@media (max-width: 767.98px) {
    .beply-mb-form .card,
    form[id^="formEdit"] > .card,
    form[id^="formSettings"] > .card {
        background: transparent;
        border: 0;
        box-shadow: none !important;
        margin: 0;
    }
    .beply-mb-form .card > .card-body,
    form[id^="formEdit"] > .card > .card-body,
    form[id^="formSettings"] > .card > .card-body {
        background: var(--beply-mb-surface, #fff);
        padding: var(--beply-mb-pad);
    }

    /* menú "⋯" dentro de la barra fija de acciones */
    .beply-mb-mas {
        position: relative;
        flex: 0 0 auto;
    }
    /* `display:flex` en la barra gana al `display:none` del atributo. */
    .beply-mb-mas[hidden] {
        display: none !important;
    }
    .beply-mb-mas__btn {
        width: var(--beply-mb-tap);
        height: var(--beply-mb-tap);
        display: inline-flex;
        align-items: center;
        justify-content: center;
        background: var(--beply-mb-surface, #fff);
        color: var(--beply-mb-fg-strong);
        border: 1px solid var(--beply-mb-border);
        border-radius: 0;
        font-size: 18px;
    }
    .beply-mb-mas.is-open .beply-mb-mas__btn {
        background: var(--beply-mb-primary);
        color: #fff;
        border-color: var(--beply-mb-primary);
    }
    .beply-mb-mas__panel {
        display: none;
        position: absolute;
        bottom: calc(100% + 8px);
        left: 0;
        min-width: 220px;
        background: var(--beply-mb-surface, #fff);
        border: 1px solid var(--beply-mb-border);
        box-shadow: 0 -8px 28px rgba(0, 0, 0, 0.16);
        z-index: 5;
    }
    .beply-mb-mas.is-open .beply-mb-mas__panel {
        display: block;
    }
    .beply-mb-mas__item {
        display: block;
        width: 100%;
        min-height: var(--beply-mb-tap);
        padding: 12px var(--beply-mb-pad);
        background: transparent;
        border: 0;
        border-bottom: 1px solid var(--beply-mb-border);
        border-radius: 0;
        text-align: left;
        font-size: 15px;
        color: var(--beply-mb-fg-strong);
    }
    .beply-mb-mas__item:last-child { border-bottom: 0; }
    /* Rótulo del grupo: en un documento el menú junta dos desplegables
       (cobro y estado) y sin encabezado no se sabe qué cambia cada opción. */
    .beply-mb-mas__label {
        display: block;
        padding: 10px var(--beply-mb-pad) 4px;
        font-size: 11px;
        font-weight: 700;
        letter-spacing: 0.06em;
        text-transform: uppercase;
        color: var(--beply-mb-fg-mute);
    }
    .beply-mb-mas__label + .beply-mb-mas__item {
        border-top: 0;
    }
}

/* ============================================================
   LAS FILAS ANIDADAS NO SE VUELVEN A PARTIR EN EL MÓVIL
   ============================================================
   FacturaScripts anida filas dentro de columnas. En una pantalla ancha
   se ve bien, pero en el móvil la fila interior hereda un ancho ya
   reducido y se subdivide otra vez: se midieron columnas de 153px con
   la etiqueta en 89px y textos como "Permitir la venta sin stock en
   nuevos productos" cayendo en cinco líneas.

   Dentro de un formulario, una columna anidada ocupa el ancho entero.
   ============================================================ */
@media (max-width: 767.98px) {
    form [class*="col-"] .row > [class*="col-"]:not(.beply-mb-col-media) {
        flex: 0 0 100%;
        max-width: 100%;
        width: 100%;
    }
}

/* Las clases col-1…col-5 sin breakpoint se aplican TAMBIÉN en el teléfono:
   una col-3 son 87px, donde no cabe ni un icono con su campo (se vio en
   Opciones de página, con el grupo partido en dos líneas). En formularios,
   a ancho completo. */
@media (max-width: 767.98px) {
    form .row > .col-1,
    form .row > .col-2,
    form .row > .col-3,
    form .row > .col-4,
    form .row > .col-5 {
        flex: 0 0 100%;
        max-width: 100%;
        width: 100%;
    }
}

/* La ficha ocupa todo el ancho: sin el canal lateral del contenedor no queda
   gris a los lados y deja de parecer una tarjeta flotante. El respiro del
   texto lo pone el propio .card-body, que conserva su padding. */
@media (max-width: 767.98px) {
    .beply-mb-ficha-sangre {
        padding-left: 0 !important;
        padding-right: 0 !important;
        /* El gris asomaba también por arriba y por abajo: la fila interior
           lleva 8px de margen superior y el panel de pestañas 21px por debajo
           del card. En vez de perseguir cada margen, la superficie de la ficha
           es blanca de principio a fin. */
        background: var(--beply-mb-surface, #fff);
    }
    /* Al quitarle el canal lateral, los gutters negativos de la fila interior
       (`.row.g-2` = -4px por lado) se salían del documento y dejaban la página
       con 4px de scroll horizontal en TODAS las fichas. Sin canal que
       compensar, la fila no necesita margen negativo. */
    .beply-mb-ficha-sangre > .row {
        margin-left: 0 !important;
        margin-right: 0 !important;
    }
    /* Y la columna que envuelve el contenido tampoco: sus 4px de canal metían
       hacia dentro TODO el panel, así que un listado dentro de una pestaña
       (Albaranes de un cliente) se veía como una tarjeta flotante con su borde
       a la vista, en vez de a sangre como en su pantalla propia. */
    .beply-mb-ficha-sangre > .row > * {
        padding-left: 0 !important;
        padding-right: 0 !important;
    }
}

/* Huecos verticales sobrantes alrededor de la cabecera: la columna del
   breadcrumb arrastra `pb-2` y la de las pestañas el canal vertical de
   Bootstrap. En el móvil la barra negra, las pestañas y el contenido van
   pegados. */
@media (max-width: 767.98px) {
    .col.pb-2 {
        padding-bottom: 0 !important;
    }
    .beply-mb-tabs-col {
        margin-top: 0 !important;
    }
}

/* Y el respiro que el formulario deja bajo las pestañas: en móvil el contenido
   arranca pegado a ellas (el aire lo pone ya el padding del card-body). */
@media (max-width: 767.98px) {
    .beply-mb-form {
        padding-top: 0 !important;
    }
}

/* ============================================================
   EDITLISTVIEW: SUB-TABLAS DE UNA FICHA
   ============================================================
   Direcciones y contactos, cuentas bancarias, contactos de un proveedor…
   El core encadena un formulario completo por registro: una sola dirección
   ocupa 1.150px. En el móvil eso es scroll a ciegas — no sabes cuántos
   registros hay ni dónde acaba uno.

   Cada registro pasa a ser una tarjeta plegada con su resumen; el formulario
   es el mismo del core, solo cambia cuándo se ve.
   ============================================================ */
@media (max-width: 767.98px) {
    /* El panel de pestañas trae su propio canal lateral y dejaba los registros
       12px hacia dentro respecto al resto de la ficha. Alineamos todo al mismo
       margen de pantalla. */
    .tab-content > .tab-pane {
        padding-left: 0 !important;
        padding-right: 0 !important;
    }
    /* Aire entre la barra de pestañas y el contenido. Sin él, el editor de
       documentos arrancaba a 6px de la barra negra —la fila del core lleva
       `margin-top: -8px`— y los datos parecían parte de la propia barra. */
    #mainTabsContent,
    .tab-content {
        padding-top: 12px;
    }
    /* La cabecera del editor de documentos (cliente, serie, fecha, forma de
       pago) es una `.row.g-2.align-items-end` con el margen negativo de los
       gutters de Bootstrap: quedaba a 6px de la barra de pestañas, como si los
       datos fueran parte de la propia barra negra. */
    .row.g-2.align-items-end:first-child {
        margin-top: 12px !important;
    }

    .beply-mb-elrec {
        border: 0 !important;
        border-top: 1px solid var(--beply-mb-border) !important;
        border-radius: 0 !important;
        box-shadow: none !important;
        margin: 0 !important;
    }
    .beply-mb-elrec__cab {
        display: flex;
        align-items: center;
        gap: 12px;
        width: 100%;
        min-height: var(--beply-mb-tap-lg);
        padding: 10px var(--beply-mb-pad);
        background: transparent;
        border: 0;
        text-align: left;
        font-family: var(--beply-mb-font-text);
        color: var(--beply-mb-fg-strong);
    }
    .beply-mb-elrec__txt {
        flex: 1 1 auto;
        min-width: 0;
    }
    .beply-mb-elrec__t,
    .beply-mb-elrec__s {
        display: block;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    .beply-mb-elrec__t {
        font-weight: 700;
        font-size: 15px;
        line-height: 1.25;
    }
    .beply-mb-elrec__s {
        font-size: 13px;
        color: var(--beply-mb-fg-mute);
    }
    .beply-mb-elrec__s:empty {
        display: none;
    }
    .beply-mb-elrec__ic {
        flex: 0 0 auto;
        color: var(--beply-mb-fg-mute);
        font-size: 13px;
        transition: transform 0.15s ease-out;
    }
    .beply-mb-elrec.is-open .beply-mb-elrec__ic {
        transform: rotate(180deg);
    }
    /* Plegado: el formulario sigue en el DOM (y se envía entero al guardar),
       simplemente no ocupa pantalla. */
    .beply-mb-elrec:not(.is-open) > .card-body,
    .beply-mb-elrec:not(.is-open) > .card-footer {
        display: none !important;
    }
    .beply-mb-elrec > .card-body {
        padding: 4px var(--beply-mb-pad) 8px !important;
    }

    /* Pie de un registro o de un alta. El core lo pinta como una fila de
       columnas —borrar, acciones del modelo, restablecer, guardar— con fondo
       gris propio de Bootstrap, y en el alta además alineado a la derecha. En
       un teléfono no cabe en una línea y salía todo apretado a 36px sobre una
       banda gris. Aquí: [borrar] [guardar] a lo ancho y las acciones del
       modelo debajo. Se cuelga de la clase que pone el JS —y no de "hijo del
       card"— porque en el alta el pie vive dentro del desplegable. */
    .card .beply-mb-elrec__pie {
        display: flex;
        flex-wrap: wrap;
        gap: 8px;
        margin: 0 !important;
        padding: 8px var(--beply-mb-pad) 12px !important;
        background: transparent !important;
        border-top: 0 !important;
        text-align: left !important;
    }
    .card .beply-mb-elrec__pie > * {
        padding: 0 !important;
        flex: 0 0 auto;
        width: auto;
    }
    .card .beply-mb-elrec__pie > .beply-mb-elrec__guardar {
        flex: 1 1 auto;
    }
    .card .beply-mb-elrec__pie > .beply-mb-elrec__extra {
        flex: 1 0 100%;
        order: 9;
    }
    /* Restablecer no pinta nada en un teléfono: deshacer es salir sin guardar.
       Se oculta el botón, no su columna: el core la comparte con Guardar. */
    .card .beply-mb-elrec__pie .btn[type="reset"] {
        display: none !important;
    }
    .card .beply-mb-elrec__pie .btn:not(.fs-5) {
        /* Las reglas de listado fijan los botones de cualquier form a 36px con
           `height` y `min-height` !important, y la del borrar lleva
           `:not(.fs-5)` —más específica—: por eso este selector la iguala. En
           el pie de un registro son las acciones de verdad y se tocan con el
           dedo. */
        height: auto !important;
        min-height: var(--beply-mb-tap) !important;
        min-width: var(--beply-mb-tap) !important;
        width: 100%;
        margin: 0 !important;
        border-radius: 0;
    }
    .card .beply-mb-elrec__pie .btn[type="submit"] {
        background: var(--beply-mb-accent);
        border-color: var(--beply-mb-accent);
        color: var(--beply-mb-on-accent);
        font-weight: 600;
    }
    /* El core esconde las etiquetas por debajo de `sm` y deja los botones como
       iconos sueltos: "guardar" es la acción principal y tiene que decir lo que
       hace. El borrar se queda como icono, a propósito. */
    .card .beply-mb-elrec__pie .btn[type="submit"] .d-none {
        display: inline-block !important;
    }
    /* Borrar: mismo lenguaje que la barra fija —contorno rojo, no un bloque
       macizo junto al guardar, que invita a tocarlo sin querer. */
    .card .beply-mb-elrec__pie .btn.btn-danger:not(.fs-5) {
        background: var(--beply-mb-surface) !important;
        border: 1px solid var(--beply-mb-danger, var(--beply-mb-accent, #d20000)) !important;
        color: var(--beply-mb-danger, var(--beply-mb-accent, #d20000)) !important;
        /* La regla de listado del borrar lleva `.btn-danger:not(.fs-5)`, así
           que el tamaño hay que repetirlo aquí para llegar a los 44px. */
        height: auto !important;
        min-height: var(--beply-mb-tap) !important;
        min-width: var(--beply-mb-tap) !important;
    }
    /* Acciones del modelo (actualizar documentos, etc.): son secundarias, no
       un semáforo en ámbar a pantalla completa. */
    .beply-mb-elrec__extra .btn {
        background: var(--beply-mb-surface) !important;
        border: 1px solid var(--beply-mb-border) !important;
        color: var(--beply-mb-fg-strong) !important;
        font-weight: 500;
    }

    /* Tarjeta de alta ("+ Añadir"): es la acción principal del panel, no un
       botoncito perdido arriba a la izquierda. El texto suelto que el core
       deja al lado del botón repite el nombre de la pestaña. */
    .beply-mb-elrec-nuevo {
        border: 0 !important;
        border-radius: 0 !important;
        box-shadow: none !important;
        margin: 0 !important;
    }
    .card.beply-mb-elrec-nuevo > .card-body {
        padding: 12px var(--beply-mb-pad) !important;
        font-size: 0;
    }
    .card.beply-mb-elrec-nuevo > .card-body > * {
        font-size: var(--beply-mb-fs-base);
    }
    .card.beply-mb-elrec-nuevo > .card-body > .btn,
    .card.beply-mb-elrec-nuevo > .card-body > .btn:hover,
    .card.beply-mb-elrec-nuevo > .card-body > .btn:focus,
    .card.beply-mb-elrec-nuevo > .card-body > .btn:focus-visible,
    .card.beply-mb-elrec-nuevo > .card-body > .btn:active,
    .card.beply-mb-elrec-nuevo > .card-body > .btn.show,
    .card.beply-mb-elrec-nuevo > .card-body > .btn[aria-expanded="true"] {
        display: flex !important;
        align-items: center;
        justify-content: center;
        gap: 8px;
        width: 100%;
        /* Los botones de listado se fijan a 36px con `height` y `min-height`
           !important: aquí es la acción principal del panel. */
        height: auto !important;
        min-height: var(--beply-mb-tap);
        margin: 0 !important;
        border-radius: 0;
        /* El botón del core es `btn-outline-success`: al pulsarlo Bootstrap lo
           rellenaba de verde y quedaba verde con el borde y el texto rojos del
           tema. Se fija el aspecto en TODOS los estados, incluido el de
           desplegado, para que no reaparezca el verde. */
        background: var(--beply-mb-surface) !important;
        border: 1px dashed var(--beply-mb-accent) !important;
        color: var(--beply-mb-accent) !important;
        box-shadow: none !important;
        font-weight: 600;
    }
    /* El icono del core viene con su propio color de marca: que siga al texto. */
    .card.beply-mb-elrec-nuevo > .card-body > .btn svg,
    .card.beply-mb-elrec-nuevo > .card-body > .btn i {
        color: currentColor !important;
        fill: currentColor !important;
    }
    /* Desplegado: mismo botón, apenas un fondo para saber que está abierto. */
    .card.beply-mb-elrec-nuevo > .card-body > .btn[aria-expanded="true"] {
        background: var(--beply-mb-surface-2, #f5f5f5) !important;
    }
    /* Mientras se despliega, Bootstrap cambia `.collapse` por `.collapsing`:
       si la regla solo mira `.collapse`, durante la animación el contenido
       recupera el padding por defecto de Bootstrap (16px) y lo pierde al
       acabar — un salto feo justo al abrir. Se listan los dos estados. */
    .beply-mb-elrec-nuevo > .collapse .card-body,
    .beply-mb-elrec-nuevo > .collapse > .card-body,
    .beply-mb-elrec-nuevo > .collapsing .card-body,
    .beply-mb-elrec-nuevo > .collapsing > .card-body {
        padding: 4px var(--beply-mb-pad) 8px !important;
    }
}

/* ============================================================
   ETIQUETAS DE CASILLA
   ============================================================
   La etiqueta de un campo es un nombre corto y va en mayúsculas; la de una
   casilla es una FRASE ("Las respuestas a este email irán a…"). En
   mayúsculas se lee peor, ocupa el doble y se salía de la pantalla.
   ============================================================ */
@media (max-width: 767.98px) {
    .form-check label,
    label.form-check-label,
    .form-check .form-label {
        text-transform: none !important;
        letter-spacing: 0 !important;
        font-size: 14px;
        font-weight: 500;
        line-height: 1.35;
        overflow-wrap: anywhere;
    }
}

/* ============================================================
   PESTAÑAS DE FICHA = PESTAÑAS DE LISTADO
   ============================================================
   El core usa `.nav-tabs` en los listados y `.nav-pills` en las fichas. Las
   primeras ya respiraban dentro de la barra negra (16px de canal, 10px de
   alto interior) y las segundas salían pegadas al borde izquierdo y un poco
   más altas. Son la misma barra: se igualan.
   ============================================================ */
@media (max-width: 767.98px) {
    /* Qué se puede tocar y qué no. El core marca la pestaña deshabilitada solo
       con `cursor: default` y `pointer-events: none`, que en una pantalla
       táctil no se ve: quedaba idéntica a una activable. Ahora la que SE PUEDE
       usar va en blanco y la que no, apagada. Vale para los dos marcados de
       pestañas del core. */
    #mainTabs .nav-link:not(.active):not(.disabled) {
        color: #ffffff !important;
    }
    #mainTabs .nav-link.disabled {
        /* El gris de siempre de las pestañas, atenuado: el mismo tono que
           tenían antes de que las activables pasaran a blanco. */
        color: rgba(255, 255, 255, 0.62) !important;
        opacity: .45;
        pointer-events: none;
    }

    #mainTabs.nav-pills {
        padding-left: var(--beply-mb-pad) !important;
        /* Sin canal a la derecha: en 360px esos 16px eran justo los que hacían
           que "Direcciones y contactos" se fuera al menú. El "⋯" cerrando la
           fila contra el borde se lee igual de bien. */
        padding-right: 0 !important;
        gap: 2px;
    }
    #mainTabs.nav-pills > .nav-link,
    #mainTabs.nav-pills > .nav-item > .nav-link {
        padding: 10px 14px !important;
    }
    /* El "⋯" también: en la ficha salía 8px más bajo que las pestañas y en
       blanco puro, mientras que en un listado va a la altura de la barra y en
       blanco al 70% como las pestañas inactivas —que es lo que es—. */
    #mainTabs.nav-pills > .beply-mb-tab-overflow {
        display: flex;
        align-items: stretch;
    }
    #mainTabs.nav-pills > .beply-mb-tab-overflow > .nav-link.dropdown-toggle {
        color: rgba(255, 255, 255, 0.7) !important;
        padding: 10px 12px !important;
        display: flex;
        align-items: center;
        justify-content: center;
        height: 100%;
    }
}

/* ============================================================
   ARCHIVOS ADJUNTOS
   ============================================================
   El core pinta por archivo: un botón gigante gris con el nombre, un área de
   observaciones siempre abierta, una línea de datos y un pie con dos botones
   más. Cuatro bloques por archivo, y con tres adjuntos la pestaña era un
   muro. Se pliega como cualquier otro registro (nombre + datos) y al abrir
   aparecen descarga, observaciones y acciones.
   ============================================================ */
@media (max-width: 767.98px) {
    .beply-mb-elrec--archivo > .beply-mb-elrec__cab .beply-mb-elrec__arch {
        flex: 0 0 auto;
        font-size: 16px;
        color: var(--beply-mb-fg-mute);
    }
    /* Miniatura del adjunto: la imagen de verdad cuando la hay, y si no el
       icono del tipo que ya elige el core. Antes salía siempre el mismo icono
       genérico y la vista previa se perdía. */
    .beply-mb-elrec--archivo > .beply-mb-elrec__cab .beply-mb-elrec__mini {
        flex: 0 0 auto;
        display: flex;
        align-items: center;
        justify-content: center;
        width: 44px;
        height: 44px;
        overflow: hidden;
        background: var(--beply-mb-surface-2, #f4f5f7);
        color: var(--beply-mb-fg-mute);
        font-size: 16px;
    }
    .beply-mb-elrec--archivo > .beply-mb-elrec__cab .beply-mb-elrec__mini img {
        width: 100%;
        height: 100%;
        object-fit: cover;
    }
    /* Vista previa dentro de la tarjeta abierta: tocarla abre el archivo. */
    .beply-mb-elrec--archivo .beply-mb-elrec__preview {
        display: block;
        padding: 0 var(--beply-mb-pad) 12px;
    }
    .beply-mb-elrec--archivo .beply-mb-elrec__preview img {
        display: block;
        width: 100%;
        height: auto;
        max-height: 46vh;
        object-fit: contain;
        background: var(--beply-mb-surface-2, #f4f5f7);
    }
    /* Los bloques que el core deja fuera del card-body también se pliegan. */
    /* Plegada sólo se ve la fila. Iba por `div` y la vista previa de las
       imágenes es un `<a>`: se quedaba a la vista con la tarjeta cerrada. */
    .beply-mb-elrec--archivo:not(.is-open) > *:not(.beply-mb-elrec__cab) {
        display: none !important;
    }
    /* Descarga: dentro de la tarjeta el nombre ya está arriba, así que el
       botón dice lo que hace y deja de ser un bloque gris a pantalla completa. */
    .card.beply-mb-elrec--archivo .beply-mb-elrec__descarga {
        display: flex !important;
        align-items: center;
        justify-content: center;
        gap: 8px;
        width: 100%;
        height: auto !important;
        min-height: var(--beply-mb-tap) !important;
        margin: 0 !important;
        padding: 10px 14px !important;
        border-radius: 0;
        background: var(--beply-mb-surface) !important;
        border: 1px solid var(--beply-mb-border) !important;
        color: var(--beply-mb-fg-strong) !important;
        font-size: 15px !important;
        font-weight: 600;
    }
    /* Autor, fecha y tamaño ya se leen en el resumen de la tarjeta: repetirlos
       dentro solo alarga. Se esconde por CSS y no por JS, porque el core
       repinta esta pestaña por AJAX y una marca puesta a mano se perdía. */
    .beply-mb-elrec--archivo .card-text {
        display: none !important;
    }
    .beply-mb-elrec--archivo > .p-3 {
        padding: 8px var(--beply-mb-pad) 0 !important;
    }
    .beply-mb-elrec--archivo > .card-body {
        padding: 8px var(--beply-mb-pad) !important;
    }
}

/* ============================================================
   BUSCADORES DE CLIENTE / PROVEEDOR / PRODUCTO (documentos)
   ============================================================
   El core los pinta como una tabla dentro del modal: cada opción es un <td>
   con el padding de tabla de Bootstrap, y encima el buscador va en un `p-3`.
   Resultado en un teléfono: filas de ~36px con mucho aire alrededor donde
   acertar cuesta, y media pantalla gastada en márgenes.

   Se les da la misma pinta que a las hojas de selección que ya usa la app
   (`.beply-mb-sheet__opt`): fila a ancho completo, 52px, separador y el texto
   alineado con el resto de la pantalla.
   ============================================================ */
@media (max-width: 767.98px) {
    .modal .modal-body > .p-3 {
        padding: 0 !important;
    }
    .modal .modal-body table.table > tbody > tr.clickableRow > td,
    .modal .modal-body table.table > tbody > tr[onclick] > td {
        display: flex;
        align-items: center;
        gap: 10px;
        min-height: 52px;
        padding: 12px var(--beply-mb-pad) !important;
        font-size: 16px;
        line-height: 1.3;
        border: 0;
        border-bottom: 1px solid var(--beply-mb-border);
    }
    .modal .modal-body table.table > tbody > tr.clickableRow:last-child > td,
    .modal .modal-body table.table > tbody > tr[onclick]:last-child > td {
        border-bottom: 0;
    }
    .modal .modal-body table.table > tbody > tr.clickableRow > td svg,
    .modal .modal-body table.table > tbody > tr[onclick] > td svg {
        flex: 0 0 auto;
        color: var(--beply-mb-fg-mute);
    }
    /* El pie con "Nuevo" no necesita banda gris ni botón verde: es la misma
       acción de alta que en el resto de la app. */
    .modal .modal-footer.bg-light {
        background: var(--beply-mb-surface) !important;
        border-top: 1px solid var(--beply-mb-border);
        padding: 10px var(--beply-mb-pad) !important;
    }
    .modal .modal-footer .btn.btn-success {
        min-height: var(--beply-mb-tap) !important;
        height: auto !important;
        background: var(--beply-mb-surface) !important;
        border: 1px dashed var(--beply-mb-accent) !important;
        color: var(--beply-mb-accent) !important;
        font-weight: 600;
    }
}

/* ============================================================
   EDITOR DE DOCUMENTOS — ORDEN DE LA PÁGINA
   ============================================================
   Encargo: al entrar a una factura/albarán/pedido/presupuesto lo primero
   tiene que ser el cliente y las líneas. Medido antes: cabecera de 770px
   (seis campos + tres botones) antes de la primera línea, o sea una
   pantalla entera de scroll para llegar a lo que se viene a mirar.

   El core repinta cabecera, líneas y pie por AJAX (`innerHTML = data.…`) en
   cada recálculo, así que MOVER nodos no vale: el repintado los devuelve a
   su sitio y duplica los campos. Ya se intentó y acabó en bucle.

   La solución es no tocar el DOM en absoluto: `display: contents` disuelve
   los tres contenedores, sus filas pasan a ser hijas directas del <form> y
   se colocan con `order`. Sobrevive a cualquier repintado porque no hay
   nada que rehacer.

       1  cliente
       2  fecha
       3  líneas
       4  añadir línea               (fila 1 del pie)
       5  descuento, neto, impuestos, beneficios, total (fila 2 del pie)
       6  "Datos del documento"      (encabezado que inserta el JS)
       7  serie, número 2, forma de pago
       8  observaciones              (viene de la fila 2 del pie)
       9  Detalle, Impagado, estado
      10  deshacer / guardar         (fila 3 del pie; lo tapa la barra fija)
   ============================================================ */
@media (max-width: 767.98px) {

    form[name="salesForm"],
    form[name="purchasesForm"] {
        display: flex;
        flex-wrap: wrap;
        align-items: flex-start;
        /* La mitad del canal la pone el form y la otra mitad cada columna: así
           el margen del borde (8+8) y el hueco entre dos columnas (8+8) miden
           lo mismo. Con los 16px enteros en la columna, entre campo y campo
           quedaba el doble de aire que en los bordes. */
        padding-inline: 8px;
    }

    /* Los contenedores desaparecen como caja; sus hijos suben al form. */
    form[name="salesForm"] > #salesFormHeader,
    form[name="salesForm"] > #salesFormHeader > .container-fluid,
    form[name="salesForm"] > #salesFormHeader > .container-fluid > .row,
    form[name="salesForm"] > #salesFormFooter,
    form[name="salesForm"] > #salesFormFooter > .container-fluid,
    form[name="purchasesForm"] > #purchasesFormHeader,
    form[name="purchasesForm"] > #purchasesFormHeader > .container-fluid,
    form[name="purchasesForm"] > #purchasesFormHeader > .container-fluid > .row,
    form[name="purchasesForm"] > #purchasesFormFooter,
    form[name="purchasesForm"] > #purchasesFormFooter > .container-fluid {
        display: contents;
    }

    /* Columnas de la cabecera: por defecto al final, en pares de media
       pantalla (serie · número 2 / forma de pago). */
    #salesFormHeader > .container-fluid > .row > *,
    #purchasesFormHeader > .container-fluid > .row > * {
        order: 7;
        width: 50%;
        padding-inline: 8px;
        /* `compactDocHeader()` marcaba esta fila para ponerla a dos columnas
           cuando aún era una fila de verdad; ahora manda el ancho de aquí. */
        flex: 0 0 auto !important;
        max-width: none !important;
    }
    /* Los botones (Detalle, Impagado, estado) van a ancho completo y después
       de los campos: son acciones, no datos, y a media pantalla el texto se
       parte. */
    #salesFormHeader > .container-fluid > .row > .col-sm,
    #salesFormHeader > .container-fluid > .row > .col-sm-auto,
    #purchasesFormHeader > .container-fluid > .row > .col-sm,
    #purchasesFormHeader > .container-fluid > .row > .col-sm-auto {
        order: 9;
        width: 100%;
    }

    #salesFormHeader > .container-fluid > .row > div:has(input[name="codcliente"]),
    #purchasesFormHeader > .container-fluid > .row > div:has(input[name="codproveedor"]) {
        order: 1;
        width: 100%;
    }
    /* Fecha y Detalle comparten línea: la fecha no necesita más de media
       pantalla y Detalle —donde vive el resto de datos del documento— gana
       estando arriba, no perdido al final. */
    #salesFormHeader > .container-fluid > .row > div:has(> #document-date),
    #purchasesFormHeader > .container-fluid > .row > div:has(> #document-date) {
        order: 2;
        width: 50%;
    }
    #salesFormHeader > .container-fluid > .row > div:has([data-bs-target="#headerModal"]),
    #purchasesFormHeader > .container-fluid > .row > div:has([data-bs-target="#headerModal"]) {
        order: 2;
        width: 50%;
        /* La fecha lleva etiqueta encima y Detalle no: sin esto el botón queda
           montado sobre el rótulo en vez de a la altura del campo. */
        align-self: flex-end;
    }
    #salesFormHeader > .container-fluid > .row > div:has([data-bs-target="#headerModal"]) .btn,
    #purchasesFormHeader > .container-fluid > .row > div:has([data-bs-target="#headerModal"]) .btn {
        width: 100%;
        min-height: var(--beply-mb-tap);
    }

    /* "Al contado", "Transferencia bancaria"… no caben en media pantalla. */
    #salesFormHeader > .container-fluid > .row > div:has(> #payment-methods),
    #purchasesFormHeader > .container-fluid > .row > div:has(> #payment-methods) {
        width: 100%;
    }

    /* El Total de la cabecera es el mismo número que el TOTAL del pie, que
       además sale destacado; y su botón de guardar lo duplica la barra fija.
       Duplicado puro: fuera en móvil. (El input va `disabled`, no se envía.) */
    #salesFormHeader > .container-fluid > .row > div:has(> .mb-2 > .input-group > button[onclick*="save-doc"]),
    #purchasesFormHeader > .container-fluid > .row > div:has(> .mb-2 > .input-group > button[onclick*="save-doc"]) {
        display: none !important;
    }

    form[name="salesForm"] > #salesFormLines,
    form[name="purchasesForm"] > #purchasesFormLines {
        order: 3;
        width: 100%;
        /* las líneas van a sangre, sin el canal del form */
        margin-inline: -8px;
        /* aire para separar la cabecera del documento de su contenido: pegadas
           parecían un campo más de la ficha */
        margin-top: 16px;
    }
    #salesFormFooter > .container-fluid > .row,
    #purchasesFormFooter > .container-fluid > .row {
        width: 100%;
        margin-inline: 0;
        padding-inline: 8px;
    }
    #salesFormFooter > .container-fluid > .row:nth-child(1),
    #purchasesFormFooter > .container-fluid > .row:nth-child(1) {
        order: 4;
    }
    #salesFormFooter > .container-fluid > .row:nth-child(2),
    #purchasesFormFooter > .container-fluid > .row:nth-child(2) {
        order: 5;
    }
    #salesFormFooter > .container-fluid > .row:nth-child(3),
    #purchasesFormFooter > .container-fluid > .row:nth-child(3) {
        order: 10;
    }

    /* Encabezado de la zona de datos, insertado por el JS como hijo directo
       del form (ahí no llega ningún repintado del core). */
    .beply-mb-docdatos {
        order: 6;
        width: 100%;
        margin: 20px 0 2px;
        padding: 0 8px;
        font-size: 11px;
        font-weight: 700;
        letter-spacing: 0.06em;
        text-transform: uppercase;
        color: var(--beply-mb-fg-mute);
    }

}

/* ============================================================
   PESTAÑAS HTML DEL DOCUMENTO (Devoluciones y compañía)
   ============================================================
   El core pinta estas pestañas como HTML suelto, sin pasar por el
   ListView, así que no las alcanzaba nada de la capa móvil: tarjeta con
   borde y cabecera amarillos, botón amarillo y una tabla de cuatro
   columnas que se salía 127px de la pantalla — la casilla "A devolver",
   que es justo para lo que se entra aquí, quedaba fuera y no se podía
   ni tocar.

   Las tablas pasan a filas apiladas con el rótulo de cada dato (lo copia
   el JS del `thead`, así sale en el idioma del core) y la tarjeta pierde
   el amarillo para hablar el mismo idioma que el resto del documento.
   ============================================================ */
@media (max-width: 767.98px) {
    .beply-mb-tablahtml,
    .beply-mb-tablahtml > tbody,
    .beply-mb-tablahtml > tbody > tr,
    .beply-mb-tablahtml > tbody > tr > td {
        display: block;
        width: 100%;
        max-width: 100%;
    }
    .beply-mb-tablahtml > thead {
        display: none;
    }
    .beply-mb-tablahtml {
        margin-bottom: 0 !important;
    }
    .beply-mb-tablahtml > tbody > tr {
        padding: 12px var(--beply-mb-pad);
        border-bottom: 1px solid var(--beply-mb-border);
        /* las filas del core vienen tintadas (`table-danger`, `table-warning`) */
        --bs-table-bg: transparent;
        --bs-table-accent-bg: transparent;
        background: var(--beply-mb-surface, #fff);
    }
    .beply-mb-tablahtml > tbody > tr > td {
        border: 0 !important;
        padding: 0 !important;
        text-align: left !important;
        --bs-table-bg: transparent;
        --bs-table-accent-bg: transparent;
        background: transparent !important;
    }
    /* La primera celda es el nombre de la fila; las demás, dato con rótulo. */
    .beply-mb-tablahtml > tbody > tr > td:first-child {
        margin-bottom: 6px;
        font-size: 15px;
        font-weight: 600;
        color: var(--beply-mb-fg-strong);
    }
    .beply-mb-tablahtml > tbody > tr > td:first-child a {
        color: var(--beply-mb-fg-mute);
        text-decoration: none;
    }
    .beply-mb-tablahtml > tbody > tr > td:not(:first-child) {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
        min-height: 34px;
    }
    .beply-mb-tablahtml > tbody > tr > td[data-mb-et]:not(:first-child)::before {
        content: attr(data-mb-et);
        flex: 0 0 auto;
        font-size: 12px;
        font-weight: 700;
        letter-spacing: 0.05em;
        text-transform: uppercase;
        color: var(--beply-mb-fg-mute);
    }
    .beply-mb-tablahtml > tbody > tr > td .form-control {
        max-width: 140px;
        min-height: var(--beply-mb-tap);
        text-align: right;
    }
    /* Filas pulsables (las devoluciones ya emitidas llevan `data-href`). */
    .beply-mb-tablahtml > tbody > tr[data-href] {
        cursor: pointer;
    }

    /* --- la tarjeta "Nueva devolución" --- */
    #refunds .card,
    #refunds .card.border-warning {
        border: 0 !important;
        border-radius: 0 !important;
        box-shadow: none !important;
        margin-bottom: 0 !important;
    }
    #refunds .card > .card-header {
        padding: 18px var(--beply-mb-pad) 6px;
        background: transparent !important;
        border: 0;
        font-size: 11px;
        font-weight: 700;
        letter-spacing: 0.06em;
        text-transform: uppercase;
        color: var(--beply-mb-fg-mute);
    }
    /* 12 del cuerpo + 4 de cada columna = los 16px de siempre, y de paso
       quedan 8 de separación entre dos botones contiguos. */
    #refunds .card > .card-body {
        padding: 0 12px 12px;
    }
    #refunds .container-fluid {
        padding-inline: 0;
    }
    #refunds .row > [class*="col-"] {
        padding-inline: 4px;
    }
    #refunds .row {
        margin-inline: 0;
    }
    /* El botón de guardar viene en amarillo; aquí manda el negro de marca. */
    #refunds .btn-warning,
    #refunds .btn-warning:hover,
    #refunds .btn-warning:focus,
    #refunds .btn-warning:active {
        background: var(--beply-mb-primary) !important;
        border-color: var(--beply-mb-primary) !important;
        color: #fff !important;
    }
    #refunds .btn-group,
    #refunds .btn-group > .dropdown,
    #refunds .btn-group > .btn,
    #refunds .dropdown > .btn {
        width: 100%;
    }
    #refunds .col-auto {
        width: 50%;
        flex: 0 0 auto;
    }
    #refunds .col-auto .btn-group {
        margin-bottom: 0 !important;
    }
}

/* ============================================================
   ARCHIVOS ADJUNTOS CON EL MISMO LENGUAJE QUE UN EDITLISTVIEW
   ============================================================
   Medido contra "Direcciones y contactos", que es el patrón bueno:

     · el alta era una fila normal alineada a la izquierda (52px) en vez
       del botón de borde discontinuo centrado (36px);
     · las filas de archivo salían metidas 16px a cada lado (358 de ancho)
       porque el panel del core las envuelve en un `.container-fluid`,
       mientras que las de un EditListView van a sangre (390).

   Dos listas de la misma ficha con dos aspectos distintos es justo lo que
   despista al cliente.
   ============================================================ */
@media (max-width: 767.98px) {
    /* La rejilla de adjuntos cuelga más adentro que el `.row` del panel, y
       arrastra los márgenes negativos de los gutters de Bootstrap: por eso la
       pestaña se iba 8px de lado. Se neutraliza el canal en todo el panel. */
    #docfiles .container-fluid,
    #docfiles .row,
    #docfiles [class*="col-"],
    #docfiles .col {
        padding-inline: 0 !important;
        margin-inline: 0 !important;
    }

    .beply-mb-elrec--alta > .beply-mb-elrec__cab {
        justify-content: center;
        gap: 8px;
        width: auto;
        min-height: var(--beply-mb-tap);
        margin: 12px var(--beply-mb-pad);
        padding: 6px 12px;
        border: 1px dashed var(--beply-mb-accent);
        background: var(--beply-mb-surface, #fff);
        color: var(--beply-mb-accent);
        font-weight: 600;
    }
    .beply-mb-elrec--alta > .beply-mb-elrec__cab .beply-mb-elrec__arch,
    .beply-mb-elrec--alta > .beply-mb-elrec__cab .beply-mb-elrec__t {
        color: inherit;
    }
    .beply-mb-elrec--alta > .beply-mb-elrec__cab .beply-mb-elrec__txt {
        flex: 0 0 auto;
    }
    /* El alta de un EditListView no lleva flecha: o está plegada o abierta. */
    .beply-mb-elrec--alta > .beply-mb-elrec__cab .beply-mb-elrec__ic {
        display: none;
    }
    .beply-mb-elrec--alta {
        border-top: 0 !important;
    }
    /* Con el alta ya separada, la primera fila de archivo no necesita raya. */
    .beply-mb-elrec--alta + .beply-mb-elrec--archivo {
        border-top: 1px solid var(--beply-mb-border) !important;
    }
}

/* ============================================================
   Permisos del grupo (EditRole) en móvil
   ============================================================
   El core pinta una matriz de menús × 6 permisos. Con el reflow
   genérico de tablas salían ~60 filas iguales, con la casilla
   diminuta pegada a la derecha, el rótulo en mayúsculas a dos
   líneas y contadores en cian de Bootstrap.

   Aquí cada menú es una tarjeta con su cabecera, y cada permiso
   una fila de 44px pulsable ENTERA: la `<label>` del control (que
   el core deja vacía) se estira sobre la celda, así que tocar en
   cualquier punto marca la casilla. Sin JS.
   ============================================================ */
@media (max-width: 767.98px) {
    /* Tarjeta por menú */
    .beply-mb-permisos > tbody > tr {
        padding: 0 !important;
        margin-bottom: var(--beply-mb-gap-md, 12px);
        border: 1px solid var(--beply-mb-border, #e5e7eb);
        border-bottom: 1px solid var(--beply-mb-border, #e5e7eb);
    }

    /* Cabecera: nombre del menú + desplegable de páginas */
    .beply-mb-permisos > tbody > tr > td:first-child {
        display: flex !important;
        align-items: center;
        gap: var(--beply-mb-gap, 8px);
        margin: 0 !important;
        padding: 10px var(--beply-mb-pad, 16px) !important;
        min-height: var(--beply-mb-tap, 44px);
        background: var(--beply-mb-surface-2, #f4f5f7) !important;
        border-bottom: 1px solid var(--beply-mb-border, #e5e7eb);
        font-size: var(--beply-mb-fs-sm, 13px);
        font-weight: 800;
        text-transform: uppercase;
        letter-spacing: 0.6px;
    }
    /* El ⊞ que despliega las páginas del menú, con área de toque. Sin
       margen negativo a la izquierda: se comía la primera letra del
       nombre del menú. El hueco se recorta en el padding de la cabecera. */
    /* OJO: el nombre del menú va DENTRO de este span, no suelto en la
       celda. Forzarle un ancho de 44px cortaba el texto; se le da altura
       de toque y que crezca con su contenido, así se despliega tocando
       el icono o el nombre. */
    .beply-mb-permisos > tbody > tr > td:first-child > span[onclick] {
        display: inline-flex;
        align-items: center;
        gap: var(--beply-mb-gap, 8px);
        min-height: var(--beply-mb-tap, 44px);
        margin: -10px 0;
        color: inherit;
    }

    /* "Todos": es el interruptor maestro, se distingue */
    .beply-mb-permisos > tbody > tr#trTodosMenus > td:first-child {
        background: var(--beply-mb-fg-strong, #000) !important;
        color: #fff;
    }

    /* Cada permiso: fila de 44px, rótulo a la izquierda en frase */
    .beply-mb-permisos > tbody > tr > td:not(:first-child) {
        position: relative;
        display: flex !important;
        align-items: center;
        gap: var(--beply-mb-gap, 8px);
        min-height: var(--beply-mb-tap, 44px);
        padding: 0 var(--beply-mb-pad, 16px) !important;
        border-bottom: 1px solid var(--beply-mb-border-soft, #f1f3f5);
    }
    .beply-mb-permisos > tbody > tr > td:last-child {
        border-bottom: 0;
    }
    .beply-mb-permisos > tbody > tr > td[data-mb-et]:not(:first-child)::before {
        flex: 1;
        /* En frase, no en mayúsculas: son etiquetas largas
           ("Mostrar solamente registros del usuario") y en caja alta
           ocupaban dos líneas y costaban de leer. */
        text-transform: none;
        letter-spacing: 0;
        font-size: var(--beply-mb-fs-base, 14px);
        font-weight: 500;
        color: var(--beply-mb-fg, #111418);
    }

    /* Contador y casilla, a la derecha y con tamaño de dedo. El contador
       vive DENTRO de la etiqueta (así lo pinta el core), por eso la
       etiqueta no puede ser el overlay: se llevaría el contador a la
       esquina. El overlay es su `::after`, que igualmente hace pulsable
       la fila entera porque pertenece a la etiqueta. */
    .beply-mb-permisos .custom-control {
        position: static;
        display: flex;
        align-items: center;
        gap: var(--beply-mb-gap, 8px);
        flex: none;
        margin: 0;
        padding: 0;
    }
    .beply-mb-permisos .custom-control-input {
        position: relative;
        z-index: 1;
        width: 22px;
        height: 22px;
        margin: 0;
        flex: none;
        accent-color: var(--beply-mb-fg-strong, #000);
    }
    /* La etiqueta (vacía salvo el contador) se estira sobre la celda: así
       toda la fila queda pulsable sin JS. El contador, que cuelga de ella,
       se ancla a la derecha dejando sitio a la casilla. */
    .beply-mb-permisos .custom-control-label {
        position: absolute;
        inset: 0;
        margin: 0;
        cursor: pointer;
    }
    /* Todo lo que el core cuelga de la etiqueta (el contador y el candado
       de "solo sus registros") se ancla a la derecha; si no, al ser la
       etiqueta un overlay, se amontonaba sobre el rótulo. */
    .beply-mb-permisos .custom-control-label > .badge,
    .beply-mb-permisos .custom-control-label > svg,
    .beply-mb-permisos .custom-control-label > i {
        position: absolute;
        top: 50%;
        right: 46px;
        transform: translateY(-50%);
        color: var(--beply-mb-fg-mute, #6b7280);
    }
    /* El indicador de Bootstrap (`custom-control-lg`) dibujaba un cuadro
       fantasma dentro de la etiqueta: la casilla real ya está a la vista. */
    .beply-mb-permisos .custom-control-label::before,
    .beply-mb-permisos .custom-control-label::after {
        display: none !important;
    }

    /* Las filas del core vienen tintadas (table-secondary, table-warning):
       en tarjeta esos colores no significan nada y ensucian. */
    .beply-mb-permisos > tbody > tr,
    .beply-mb-permisos > tbody > tr > td {
        --bs-table-bg: transparent !important;
        --bs-table-accent-bg: transparent !important;
        --bs-table-bg-state: transparent !important;
    }
    .beply-mb-permisos > tbody > tr {
        background: var(--beply-mb-surface, #fff) !important;
    }

    /* Contadores (34/34, 3/4): del cian de Bootstrap al gris de la casa.
       Completo = negro, para que se lea de un vistazo qué está entero. */
    .beply-mb-permisos .badge {
        flex: none;
        border-radius: var(--beply-mb-radius-chip, 0);
        background: var(--beply-mb-surface-2, #f4f5f7) !important;
        color: var(--beply-mb-fg-mute, #6b7280) !important;
        font-family: var(--beply-mb-font-numbers, sans-serif);
        font-size: var(--beply-mb-fs-xs, 11px);
        font-weight: 700;
        padding: 4px 8px;
    }

    /* Aviso del pie: que respire y no compita con la barra de guardar */
    .beply-mb-permisos ~ .alert,
    .beply-mb-permisos ~ .text-muted.small {
        margin: var(--beply-mb-gap-md, 12px) var(--beply-mb-pad, 16px);
        font-size: var(--beply-mb-fs-sm, 13px);
        line-height: 1.4;
    }
}
