/* ============================================================================
   ds/movil.css — EL MARCO EN EL TELÉFONO (doc 66, M1)

   Por debajo de 768 px el producto deja de ser «el dashboard en pequeño» y pasa
   a ser una app: la barra lateral se va, arriba queda una cabecera oscura de la
   marca y abajo una barra de pestañas con «Más», que abre todo el menú como hoja.

   TODO VA DETRÁS DE DOS CONDICIONES, y las dos importan:

   · `@media (max-width: 767.98px)` — el corte que ya usan la rejilla y la caja.
     El escritorio y la tableta no reciben NI UNA regla de este archivo.
   · `body.con-pestanas` — la clase la pone la barra de pestañas del front al
     montarse. Las pantallas que todavía pinta PHP (Facturas) no la llevan, así
     que conservan su barra lateral: esconderla sin poner nada en su lugar las
     dejaría sin forma de navegar.

   Va ÚLTIMO en el orden de carga (bootstrap.php y sync-ds.mjs del front): pisa
   a `sidebar.css`, `header.css` y a la caja con la misma especificidad, sin
   `!important` (salvo los que pelean con una utilidad que ya es `!important`
   —`.d-flex`, `.flex-column`, `.mt-3`—, explicados donde están).
   ============================================================================ */

/* La barra de pestañas no existe fuera del teléfono. */
.barra-pestanas {
  display: none;
}

/* El logo de la cabecera móvil, tampoco. */
.cabecera-movil__logo {
  display: none;
}

@media (max-width: 767.98px) {
  body.con-pestanas {
    /* La barra lateral ya no reserva nada: el contenido ocupa el ancho entero. */
    --sidebar-rail: 0px;
    --sidebar-reserved: 0px;
    --lightbox-inset-start: 0px;

    /* Lo que miden las dos barras, CON las zonas seguras del teléfono: el notch
       arriba y la barra de gestos abajo. Sin `viewport-fit=cover` (lo pone el
       `<meta viewport>`) `env()` vale 0 y queda igual que antes. */
    --cabecera-movil: calc(56px + env(safe-area-inset-top, 0px));
    --pestanas-alto: calc(60px + env(safe-area-inset-bottom, 0px));

    /* Que se sienta app: sin el destello azul al tocar y sin que la página
       entera rebote al llegar al final de una lista. */
    -webkit-tap-highlight-color: transparent;
    overscroll-behavior-y: none;
  }

  /* Un `!important`, y es por otro: la barra lateral es `<aside class="d-flex">`
     y `.d-flex` es `display: flex !important` (`ds/utilities.css`). Sin él se quedaba a 0 px de
     ancho —no se veía— pero sus enlaces seguían recibiendo el foco del teclado, invisibles. */
  body.con-pestanas #dashboard_sidebar {
    display: none !important;
  }

  /* ---- La cabecera ------------------------------------------------------- */

  /* Pegada arriba y a sangre, del color de la marca. Pasa POR DEBAJO de la
     barra de estado del iPhone (`black-translucent`): por eso su alto suma el
     notch y su contenido arranca después de él. */
  body.con-pestanas #dashboard_header {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: var(--cabecera-movil);
    margin: 0;
    padding: env(safe-area-inset-top, 0px) 6px 0 14px;
    border-radius: 0;
    background: var(--brand-charcoal, #22333B);
    box-shadow: none;
    z-index: 97;
  }

  body.con-pestanas.float_active #dashboard_header,
  body.con-pestanas .float_active #dashboard_header {
    box-shadow: none;
  }

  body.con-pestanas #dashboard_title_wrapper {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
  }

  /* El logo lleva a Inicio: 44 px de alto tocable, con la imagen de 26 centrada. */
  body.con-pestanas .cabecera-movil__logo {
    display: flex;
    align-items: center;
    flex-shrink: 0;
    height: 44px;
    line-height: 0;
  }

  body.con-pestanas .cabecera-movil__logo img {
    height: 26px;
    width: auto;
  }

  /* Los iconos de la cabecera, en blanco sobre la marca, y con 44 px de blanco
     táctil aunque el glifo mida 20. */
  body.con-pestanas #dashboard_header .notifications_bell {
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--neutral-white, #fff);
  }

  body.con-pestanas #dashboard_header .notifications_bell i {
    color: var(--neutral-white, #fff);
  }

  body.con-pestanas #header_account .header_account_image {
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  /* ---- El contenido ------------------------------------------------------ */

  /* `clip` y no el `hidden` de `ds/sidebar.css`: los dos recortan, pero `hidden`
     vuelve a esta caja el marco de cualquier `sticky` de dentro, y como ella no
     desplaza (desplaza la página) nada se pegaba nunca —ni la tira de pestañas
     del formulario ni la cuenta de marcadas del archive—. `clip` no crea ese
     marco. Un navegador sin `clip` se queda con `hidden`: recorta igual y sólo
     pierde el pegado. */
  body.con-pestanas #dashboard_page_content {
    padding: calc(var(--cabecera-movil) + 12px) 12px calc(var(--pestanas-alto) + 16px);
    overflow: clip;
  }

  /* Los avisos que flotan abajo suben por encima de las pestañas: debajo de
     ellas no se verían. */
  body.con-pestanas .toast-stack {
    bottom: calc(var(--pestanas-alto) + 12px);
  }

  body.con-pestanas .update-card {
    left: 12px;
    right: 12px;
    width: auto;
    max-width: none;
    bottom: calc(var(--pestanas-alto) + 12px);
  }

  /* ---- La barra de pestañas ---------------------------------------------- */

  body.con-pestanas .barra-pestanas {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 97;
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    min-height: var(--pestanas-alto);
    padding: 0 4px env(safe-area-inset-bottom, 0px);
    box-sizing: border-box;
    background: var(--brand-charcoal, #22333B);
  }

  .barra-pestanas__boton {
    position: relative;
    min-height: 60px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    padding: 0;
    border: 0;
    background: transparent;
    color: #A9B4C0;
    font-family: var(--font-sans);
    font-size: 11px;
    font-weight: 500;
    line-height: 1.2;
    text-decoration: none;
    cursor: pointer;
  }

  .barra-pestanas__boton i {
    font-size: 22px;
    line-height: 1;
  }

  /* Sin hover en un dedo: lo que confirma el toque es este instante. */
  .barra-pestanas__boton:active {
    background: rgba(255, 255, 255, 0.08);
  }

  .barra-pestanas__boton:focus-visible {
    outline: 2px solid var(--neutral-white, #fff);
    outline-offset: -4px;
  }

  .barra-pestanas__boton[aria-current="page"] {
    color: var(--neutral-white, #fff);
    font-weight: 700;
  }

  /* La marca de la pestaña activa: una raya del acento de la marca, arriba. */
  .barra-pestanas__boton[aria-current="page"]::before {
    content: '';
    position: absolute;
    top: 0;
    left: 50%;
    width: 28px;
    height: 3px;
    margin-left: -14px;
    border-radius: 0 0 2px 2px;
    background: var(--brand-accent, #D62A49);
  }

  /* ---- La caja con pestañas ---------------------------------------------- */

  /* La caja mide su carrito contra el alto de la pantalla (`ds/pos.css`). Con la
     cabecera pegada arriba y las pestañas abajo, los dos altos cambian: el
     carrito se acorta lo que miden las pestañas para que su botón de cobrar no
     quede debajo de ellas. La caja de verdad en el teléfono es M2. */
  body.con-pestanas .cart {
    height: calc(100dvh - 280px - var(--pestanas-alto));
  }
}

/* ---- La hoja «Más» --------------------------------------------------------
   Un `<dialog>` nativo abierto con `showModal()`: atrapa el foco, cierra con
   Escape y —en Android— con el botón Atrás, sin tocar el historial (que es del
   router). Vive fuera del `@media` porque sólo la abre la barra de pestañas,
   que sólo existe en el teléfono. */

.hoja {
  position: fixed;
  inset: auto 0 0 0;
  margin: 0;
  width: 100%;
  max-width: 100%;
  max-height: 88dvh;
  padding: 8px 16px calc(16px + env(safe-area-inset-bottom, 0px));
  box-sizing: border-box;
  border: 0;
  border-radius: 20px 20px 0 0;
  background: var(--surface-page);
  color: var(--text-primary);
  font-family: var(--font-sans);
  overflow-y: auto;
  overscroll-behavior: contain;
  touch-action: pan-y;
}

.hoja::backdrop {
  background: rgba(34, 51, 59, 0.55);
}

.hoja[open] {
  animation: hoja-sube 0.22s ease-out;
}

@keyframes hoja-sube {
  from { transform: translateY(100%); }
}

@media (prefers-reduced-motion: reduce) {
  .hoja[open] { animation: none; }
}

/* El asa: también es lo que se arrastra hacia abajo para cerrarla. */
.hoja__asa {
  display: block;
  width: 100%;
  height: 24px;
  margin: -8px 0 4px;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: grab;
  touch-action: none;
}

.hoja__asa::before {
  content: '';
  display: block;
  width: 40px;
  height: 5px;
  margin: 10px auto 0;
  border-radius: 3px;
  background: var(--border-strong);
}

.hoja__cuenta {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 4px 0 12px;
  border-bottom: 1px solid var(--border-light);
}

.hoja__avatar {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--brand-charcoal, #22333B);
  color: var(--neutral-white, #fff);
  font-size: 18px;
  overflow: hidden;
}

.hoja__avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.hoja__quien {
  flex-grow: 1;
  min-width: 0;
}

.hoja__nombre {
  display: block;
  font-size: 15px;
  font-weight: 700;
}

.hoja__rol {
  display: block;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-secondary);
}

.hoja__cerrar {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: 50%;
  background: var(--surface-sunken-light);
  color: var(--text-primary);
  font-size: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.hoja__rejilla {
  list-style: none;
  margin: 14px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}

.hoja__destino {
  width: 100%;
  min-height: 88px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 8px 4px;
  box-sizing: border-box;
  border: 0;
  border-radius: 12px;
  background: var(--surface-sunken-light);
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.25;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}

.hoja__destino i {
  font-size: 24px;
  line-height: 1;
  color: var(--brand-charcoal, #22333B);
}

.hoja__destino:active {
  background: var(--surface-sunken);
}

.hoja__destino[aria-current="page"],
.hoja__destino[aria-expanded="true"] {
  box-shadow: inset 0 0 0 2px var(--brand-charcoal, #22333B);
}

/* Los hijos de un destino con submenú se despliegan debajo de la rejilla, a
   lo ancho: dentro de una baldosa de 110 px no caben nueve ajustes. */
.hoja__hijos {
  list-style: none;
  margin: 12px 0 0;
  padding: 4px 0;
  border-radius: 12px;
  background: var(--surface-sunken-light);
}

.hoja__titulo-hijos {
  margin: 14px 4px 0;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.hoja__hijo {
  display: flex;
  align-items: center;
  min-height: 48px;
  padding: 0 16px;
  color: var(--text-primary);
  font-size: 15px;
  font-weight: 600;
  text-decoration: none;
}

.hoja__hijo[aria-current="page"] {
  color: var(--brand-accent, #D62A49);
}

.hoja__pie {
  display: flex;
  gap: 10px;
  margin-top: 16px;
}

.hoja__pie a {
  flex: 1 1 0;
  min-height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 1px solid var(--border-default);
  border-radius: 8px;
  color: var(--text-primary);
  font-size: 14px;
  font-weight: 700;
  text-decoration: none;
}

/* ============================================================================
   LA CAJA EN EL TELÉFONO (doc 66, M2)

   El catálogo vuelve —en lista, con las categorías en fila deslizable— y el
   carrito se pliega en una barra sobre las pestañas que se despliega como hoja.
   El cobro, a pantalla completa.

   Todo cuelga de dos clases que SÓLO pinta el front nuevo:
   `.pos_product_archive--telefono` (la `Rejilla`, cuando el ancho es de
   teléfono) y `.hoja-carrito` (la envoltura del carrito). Por eso este bloque
   no le cambia nada al front que esté desplegado antes que él: la regla de
   `ds/pos.css` que esconde el catálogo sigue ahí para quien no lleve la clase.
   ============================================================================ */

/* En escritorio la hoja no existe: las dos envolturas no generan caja, así que
   el carrito sigue siendo la columna derecha, hijo flex de la misma fila, y la
   barra y la cabecera de la hoja no se pintan. */
.hoja-carrito,
.hoja-carrito__panel {
  display: contents;
}

.hoja-carrito__fondo,
.hoja-carrito__cabecera,
.hoja-carrito__barra {
  display: none;
}

@media (max-width: 767.98px) {
  body.con-pestanas.page-pos {
    /* Lo que mide la barra del carrito plegado. */
    --barra-carrito: 76px;
  }

  /* ---- El marco de la caja ------------------------------------------------
     La caja no desplaza la PÁGINA: el buscador y las categorías se quedan
     arriba y sólo corre la lista. Por eso la columna del catálogo mide
     exactamente lo que queda entre la cabecera y la barra del carrito. */
  body.con-pestanas.page-pos #dashboard_page_content {
    padding: calc(var(--cabecera-movil) + 8px) 8px calc(var(--pestanas-alto) + var(--barra-carrito) + 8px);
  }

  body.con-pestanas.page-pos .toast-stack {
    bottom: calc(var(--pestanas-alto) + var(--barra-carrito) + 12px);
  }

  body.con-pestanas .pos_page_main_wrapper .pos_page_main {
    display: flex;
    flex-direction: column;
    gap: 8px;
    height: calc(100dvh - var(--cabecera-movil) - var(--pestanas-alto) - var(--barra-carrito) - 16px);
  }

  body.con-pestanas .pos_page_main .pos_search_header {
    flex-shrink: 0;
    margin: 0;
    padding: 8px;
  }

  /* El botón de alta rápida, al tamaño del dedo. */
  body.con-pestanas .pos_search_header_inner {
    gap: 8px;
  }

  body.con-pestanas .pos_search_header_inner > .icon-chip {
    width: 44px;
    height: 44px;
    flex-shrink: 0;
  }

  body.con-pestanas .pos_search_header .input__el {
    height: 44px;
  }

  /* ---- El catálogo --------------------------------------------------------
     Gana a la regla de `ds/pos.css` que lo esconde por debajo de 768 px: esa
     regla es de cuando la caja no tenía dónde ponerlo. */
  body.con-pestanas .pos_product_archive.pos_product_archive--telefono {
    display: flex;
    flex-direction: column;
    gap: 8px;
    flex: 1;
    min-height: 0;
    height: auto;
    margin: 0;
    padding: 8px;
  }

  /* Las categorías: arriba y en fila, no en la columna de 270 px del listado
     de escritorio, que en un teléfono se comería la pantalla. */
  body.con-pestanas .pos_product_archive--telefono .pos_products_nav {
    flex-direction: row;
    align-items: center;
    flex-shrink: 0;
    width: 100%;
    height: auto;
    border-width: 3px;
  }

  body.con-pestanas .pos_product_archive--telefono .pos_categories_tabs {
    flex-direction: row;
    flex: 1;
    width: auto;
    min-width: 0;
    overflow-x: auto;
    overflow-y: hidden;
  }

  body.con-pestanas .pos_product_archive--telefono .pos_tab {
    display: flex;
    align-items: center;
    min-height: 44px;
    padding: 0 14px;
    white-space: nowrap;
  }

  body.con-pestanas .pos_product_archive--telefono .pos_products_nav_actions {
    width: 44px;
  }

  body.con-pestanas .pos_product_archive--telefono .pos_sort_trigger {
    width: 44px;
    height: 44px;
  }

  body.con-pestanas .pos_product_archive--telefono .pos_product_archives {
    flex: 1;
    min-height: 0;
    height: auto;
    overflow-y: auto;
    overscroll-behavior: contain;
  }

  body.con-pestanas .pos_product_archive--telefono .pos_product_archive_grid {
    gap: 8px;
    padding: 0 0 8px;
  }

  /* La fila: nombre entero, precio y un botón del tamaño de un dedo. */
  body.con-pestanas .pos_product_archive--telefono .pos_product_row {
    min-height: 64px;
    padding: 10px 12px;
    gap: 12px;
  }

  body.con-pestanas .pos_product_archive--telefono .pos_product_row:active {
    background: var(--neutral-150);
  }

  body.con-pestanas .pos_product_archive--telefono .pos_product_row__title {
    font-size: 14px;
    line-height: 1.3;
  }

  body.con-pestanas .pos_product_archive--telefono .pos_product_row__price {
    font-size: 15px;
  }

  body.con-pestanas .pos_product_archive--telefono .pos_product_row__action .icon-chip {
    position: relative;
    width: 44px;
    height: 44px;
  }

  body.con-pestanas .pos_product_archive--telefono .pos_product_row__action .icon-chip i {
    font-size: 20px;
  }

  /* Cuántas van ya en el carrito: con el carrito plegado es la prueba de que el
     toque entró. El aro blanco la despega del botón. */
  .pos_product_row__llevados {
    position: absolute;
    top: -6px;
    right: -6px;
    min-width: 22px;
    height: 22px;
    padding: 0 6px;
    box-sizing: border-box;
    border-radius: 11px;
    background: var(--brand-accent, #D62A49);
    box-shadow: 0 0 0 2px var(--surface-page, #fff);
    color: var(--neutral-white, #fff);
    font-size: 12px;
    font-weight: 800;
    line-height: 22px;
    text-align: center;
    font-style: normal;
  }

  /* ---- La barra del carrito plegado --------------------------------------- */

  body.con-pestanas .hoja-carrito__barra {
    position: fixed;
    left: 0;
    right: 0;
    bottom: var(--pestanas-alto);
    z-index: 96;
    display: flex;
    align-items: center;
    gap: 12px;
    min-height: var(--barra-carrito);
    padding: 10px 12px;
    box-sizing: border-box;
    border-radius: 18px 18px 0 0;
    background: var(--surface-page);
    box-shadow: 0 -6px 24px rgba(34, 51, 59, 0.16);
  }

  .hoja-carrito__resumen {
    flex: 1;
    min-width: 0;
    min-height: 52px;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--text-primary);
    font-family: var(--font-sans);
    text-align: left;
    cursor: pointer;
  }

  .hoja-carrito__resumen > i {
    font-size: 22px;
    line-height: 1;
    color: var(--text-secondary);
  }

  .hoja-carrito__cuenta {
    display: block;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-secondary);
  }

  .hoja-carrito__total {
    display: block;
    font-size: 20px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
  }

  body.con-pestanas .hoja-carrito__cobrar {
    flex-shrink: 0;
    min-width: 150px;
    height: 52px;
  }

  /* ---- La hoja ------------------------------------------------------------
     Una capa fija normal, no un `<dialog>` modal: ver `HojaDelCarrito.tsx`. Va
     en 98, encima de las pestañas (97) y debajo de los lightbox (99), que se
     abren desde dentro y tienen que quedar encima.

     Plegada se oculta con `visibility` y NO con `display: none`: un lightbox
     activo de dentro declara `visibility: visible` y así se ve aunque la hoja
     esté plegada. Y no lleva `transform` fuera de la animación, porque un
     `transform` convierte a la hoja en el marco de sus hijos `fixed`: esos
     lightbox quedarían metidos en ella en vez de cubrir la pantalla. */
  body.con-pestanas .hoja-carrito--abierta .hoja-carrito__fondo {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 98;
    background: rgba(34, 51, 59, 0.55);
  }

  body.con-pestanas .hoja-carrito__panel {
    position: fixed;
    top: calc(env(safe-area-inset-top, 0px) + 40px);
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 98;
    display: flex;
    flex-direction: column;
    padding: 0 12px env(safe-area-inset-bottom, 0px);
    box-sizing: border-box;
    border-radius: 20px 20px 0 0;
    background: var(--surface-page);
    visibility: hidden;
    overscroll-behavior: contain;
  }

  body.con-pestanas .hoja-carrito--abierta .hoja-carrito__panel {
    visibility: visible;
    animation: hoja-sube 0.22s ease-out;
  }

  body.con-pestanas .hoja-carrito__cabecera {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-shrink: 0;
    min-height: 60px;
    padding-top: 8px;
  }

  /* El asa: la raya que dice «esto se baja». Es un botón de 44 px de alto
     aunque la raya mida 5. */
  .hoja-carrito__asa {
    position: absolute;
    top: 0;
    left: 50%;
    width: 64px;
    height: 44px;
    margin-left: -32px;
    padding: 0;
    border: 0;
    background: transparent;
    cursor: pointer;
  }

  .hoja-carrito__asa::before {
    content: '';
    position: absolute;
    top: 8px;
    left: 12px;
    width: 40px;
    height: 5px;
    border-radius: 3px;
    background: var(--border-default, #E5EAEF);
  }

  .hoja-carrito__titulo {
    margin: 0;
    font-size: 16px;
    font-weight: 800;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-primary);
  }

  .hoja-carrito__cerrar {
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    border-radius: 22px;
    background: var(--surface-sunken-light, #F4F7F9);
    color: var(--text-primary);
    cursor: pointer;
  }

  .hoja-carrito__cerrar i {
    font-size: 20px;
    line-height: 1;
  }

  /* El carrito, dentro: ocupa lo que queda y desplaza por dentro, con el pie de
     cobrar pegado abajo (eso ya lo hace `ds/cart.css` en el teléfono). */
  body.con-pestanas .hoja-carrito__panel .pos_page_cart {
    flex: 1;
    min-height: 0;
    width: 100%;
    margin: 0;
    display: flex;
    flex-direction: column;
  }

  body.con-pestanas .hoja-carrito__panel .cart {
    flex: 1;
    min-height: 0;
    height: auto;
    padding-bottom: 0;
  }

  /* La cantidad del renglón: de 25 px a 44, que es lo que pide un dedo. Se
     toca muchas veces por venta y es donde más se fallaba. */
  body.con-pestanas .hoja-carrito__panel .cart_quantity > span {
    width: 44px;
    height: 44px;
    font-size: 18px;
  }

  body.con-pestanas .hoja-carrito__panel .cart_quantity input {
    width: 48px;
    height: 44px;
  }

  /* ---- El cobro, a pantalla completa ---------------------------------------
     Es el momento de la venta: nada de la caja asoma por los lados. El botón de
     cobrar queda pegado abajo, al alcance del pulgar, aunque los métodos y las
     denominaciones desplacen.

     ⚠ SÓLO EL COBRO SOLO, por eso el `>`. Cuando un vertical reparte el cobro en
     dos cajas (`.lightbox__group`: el panel de la cuenta de una mesa, la atención
     de Bookings) el panel se apila ENCIMA del modal; con el modal a 100dvh el
     conjunto medía más que la pantalla, la capa no desplaza, y el botón de cobrar
     quedaba en y=1002 de una pantalla de 844, sin poder tocarse. Ese reparto
     tiene sus propias reglas, más abajo («el cobro repartido en dos cajas»). */
  body.con-pestanas.page-pos .lightbox.checkout > .lightbox__content {
    display: flex;
    flex-direction: column;
    width: 100%;
    max-width: none;
    height: 100dvh;
    border-radius: 0;
  }

  body.con-pestanas.page-pos .lightbox.checkout > .lightbox__content > .lightbox__header {
    flex-shrink: 0;
    height: calc(56px + env(safe-area-inset-top, 0px));
    padding-top: env(safe-area-inset-top, 0px);
    padding-left: 16px;
    border-radius: 0;
  }

  body.con-pestanas.page-pos .lightbox.checkout > .lightbox__content .lightbox__close {
    width: 56px;
    height: 56px;
    border-radius: 0;
  }

  /* Con el id porque el front topa ESTE cuerpo por id (`#createOrderLightbox`, en
     `panel-de-cobro.css`): sin él, esa regla gana y el cuerpo se queda en 483 px
     de una pantalla de 844. */
  body.con-pestanas.page-pos .lightbox.checkout > .lightbox__content > .lightbox__body,
  body.con-pestanas.page-pos #createOrderLightbox.checkout > .lightbox__content > .lightbox__body {
    flex: 1;
    min-height: 0;
    max-height: none;
    padding: 16px 16px 0;
    overscroll-behavior: contain;
    /* En columna para que el botón de cobrar baje al fondo cuando sobra
       pantalla (su `margin-top: auto`), y se pegue abajo cuando falta. */
    display: flex;
    flex-direction: column;
  }

  body.con-pestanas.page-pos .lightbox.checkout > .lightbox__content > .lightbox__body > * {
    flex-shrink: 0;
  }

  /* Pegado abajo, pero POR ENCIMA de la barra de gestos del iPhone: el `bottom`
     del sticky lleva la zona segura (el margen no cuenta mientras está pegado). */
  body.con-pestanas.page-pos .lightbox.checkout > .lightbox__content .checkout__cta {
    margin-top: auto;
    position: sticky;
    bottom: calc(12px + env(safe-area-inset-bottom, 0px));
    z-index: 2;
    height: 56px;
    margin-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
    box-shadow: 0 0 0 12px var(--surface-page, #fff);
  }

  /* EL COBRO REPARTIDO EN DOS CAJAS, también a pantalla completa (doc 66,
     después de M5). Es el de una mesa de Restaurant (el panel de propina y
     comensales al lado del modal) y el de Bookings. En M2 se dejó flotando
     porque a 100dvh el botón de cobrar se iba de la pantalla; apiladas en una
     ventana, las dos cajas dejaban el botón en y = 902 de 844, dentro de un
     scroll interior.

     Ahora el grupo ocupa la pantalla y se lee de arriba abajo: la cabecera con
     su ✕, el panel (propina, por persona) y el cuerpo, que es lo único que
     desplaza, con el botón anclado abajo. Para poder poner el panel ENTRE la
     cabecera y el cuerpo, la columna de la caja y la caja misma se vuelven
     `display: contents`: sus hijos pasan a ser renglones de la fila. */
  body.con-pestanas.page-pos .lightbox.checkout > .lightbox__group {
    display: flex;
    flex-direction: column;
    width: 100%;
    max-width: none;
    height: 100dvh;
    margin: 0;
    background: var(--surface-page, #fff);
  }

  /* UN SOLO SCROLL, el de la fila. Con el panel topado (25dvh, `panel-de-cobro.css`) y el cuerpo
     desplazando aparte eran dos scrolls apilados: a 360×640 el «Total a cobrar» quedaba partido
     dentro del panel. Ahora panel y cuerpo van a su alto natural y desplaza la fila entera; la
     cabecera se pega arriba y el botón abajo. */
  body.con-pestanas.page-pos .lightbox.checkout > .lightbox__group > .row {
    flex: 1;
    min-height: 0;
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: stretch;
    margin: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
  }

  body.con-pestanas.page-pos .lightbox.checkout > .lightbox__group > .row > [class*='col-'] {
    width: 100%;
    max-width: none;
    margin: 0;
    padding: 0;
  }

  body.con-pestanas.page-pos .lightbox.checkout > .lightbox__group > .row > [class*='col-']:has(> .lightbox__content),
  body.con-pestanas.page-pos .lightbox.checkout > .lightbox__group .lightbox__content {
    display: contents;
  }

  body.con-pestanas.page-pos .lightbox.checkout > .lightbox__group .lightbox__header {
    order: -2;
    position: sticky;
    top: 0;
    z-index: 3;
    flex-shrink: 0;
    height: calc(56px + env(safe-area-inset-top, 0px));
    padding-top: env(safe-area-inset-top, 0px);
    padding-left: 16px;
    border-radius: 0;
  }

  body.con-pestanas.page-pos .lightbox.checkout > .lightbox__group .lightbox__close {
    width: 56px;
    height: 56px;
    border-radius: 0;
  }

  /* El panel, entre la cabecera y el cuerpo, entero: sin el tope de 25dvh
     del front ni su scroll propio. */
  body.con-pestanas.page-pos .lightbox.checkout > .lightbox__group > .row > [class*='col-']:not(:has(> .lightbox__content)) {
    order: -1;
    flex-shrink: 0;
    padding: 12px 16px 0;
  }

  body.con-pestanas.page-pos .lightbox.checkout > .lightbox__group .cobro_panel {
    max-height: none;
    overflow: visible;
  }

  /* Con el id: el front topa este cuerpo por id (`panel-de-cobro.css`). */
  body.con-pestanas.page-pos .lightbox.checkout > .lightbox__group .lightbox__body,
  body.con-pestanas.page-pos #createOrderLightbox.checkout > .lightbox__group .lightbox__body {
    flex: 1 0 auto;
    max-height: none;
    overflow: visible;
    padding: 16px 16px 0;
    display: flex;
    flex-direction: column;
  }

  body.con-pestanas.page-pos .lightbox.checkout > .lightbox__group .lightbox__body > * {
    flex-shrink: 0;
  }

  body.con-pestanas.page-pos .lightbox.checkout > .lightbox__group .checkout__cta {
    margin-top: auto;
    position: sticky;
    bottom: calc(12px + env(safe-area-inset-bottom, 0px));
    z-index: 2;
    height: 56px;
    margin-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
    box-shadow: 0 0 0 12px var(--surface-page, #fff);
  }

  /* Anclado, el botón apagado NO puede ser translúcido (`checkout.css` lo baja
     a .5): el cuerpo pasa por debajo y se leían los botones de cupón y de
     dividir a través de «Crear orden». Opaco, con el tono inerte del DS que ya
     le da `.btn:disabled`. Vale para los dos cobros, el solo y el repartido. */
  body.con-pestanas.page-pos .lightbox.checkout .checkout__cta:disabled {
    opacity: 1;
  }

  /* La tarjeta de «hay versión nueva» también sube sobre la barra del carrito,
     como los avisos: si no, tapaba el botón de cobrar. */
  body.con-pestanas.page-pos .update-card {
    bottom: calc(var(--pestanas-alto) + var(--barra-carrito) + 12px);
  }
}

/* EL TELÉFONO EN HORIZONTAL. Con 360–375 px de alto, repartir la pantalla entre
   cabecera, pestañas y barra dejaba unos 25 px a la lista. Ahí la caja deja de
   medir su columna y desplaza la página entera, como cualquier otra pantalla. */
@media (max-width: 767.98px) and (max-height: 500px) {
  body.con-pestanas .pos_page_main_wrapper .pos_page_main {
    height: auto;
  }

  body.con-pestanas .pos_product_archive.pos_product_archive--telefono {
    flex: none;
  }

  body.con-pestanas .pos_product_archive--telefono .pos_product_archives {
    overflow: visible;
  }
}

@media (prefers-reduced-motion: reduce) {
  .hoja-carrito--abierta .hoja-carrito__panel { animation: none; }
}

/* ============================================================================
   EL ARCHIVE EN EL TELÉFONO (doc 66, M3)

   Órdenes, Productos, Inventarios, Clientes, Cupones, Usuarios… comparten el
   mismo marco (`PantallaArchive`) y la misma tabla. En el teléfono la tabla se
   pinta como TARJETAS (`.archive-tarjetas`, sólo la pinta el front nuevo) y el
   marco se reacomoda: las pestañas de estatus pasan a chips deslizables, la
   paginación de arriba se va (queda la de abajo, al alcance del pulgar) y la
   barra de acciones en lote se parte en renglones.
   ============================================================================ */

/* Fuera del teléfono las tarjetas no se pintan nunca (las pinta el front sólo
   por debajo de 768 px), así que no hace falta apagarlas aquí. */

@media (max-width: 767.98px) {
  /* ---- Las pestañas de estatus, como chips ------------------------------- */
  body.con-pestanas .archive-nav > [class*="col"] {
    flex: 0 0 100%;
    max-width: 100%;
  }

  /* La paginación de arriba se va: la de abajo hace lo mismo y queda donde
     termina el pulgar, después de la última tarjeta. */
  /* `!important` por lo mismo que la barra lateral: la paginación es
     `.d-flex`, y `.d-flex` es `display: flex !important` (`ds/utilities.css`). */
  body.con-pestanas .archive-nav .archive-pagination {
    display: none !important;
  }

  body.con-pestanas .archive-status {
    gap: 8px;
    margin: 0 -12px;
    padding: 0 12px 2px;
    overflow-x: auto;
    scrollbar-width: none;
    overscroll-behavior-x: contain;
  }

  body.con-pestanas .archive-status::-webkit-scrollbar {
    display: none;
  }

  body.con-pestanas .archive-status > * {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 44px;
    padding: 0 14px;
    border: 1px solid var(--border-default, #E5EAEF);
    border-radius: 20px;
    background: var(--surface-page, #fff);
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
    text-decoration: none;
  }

  body.con-pestanas .archive-status > *:not(:last-child)::after {
    content: none;
  }

  body.con-pestanas .archive-status .is-current {
    border-color: var(--brand-charcoal, #22333B);
    background: var(--brand-charcoal, #22333B);
    color: var(--neutral-white, #fff);
    text-decoration: none;
  }

  body.con-pestanas .archive-status .is-current .archive-status__count {
    color: inherit;
    opacity: 0.8;
  }

  /* ---- La barra de acciones en lote y filtros ----------------------------- */
  body.con-pestanas .archive-toolbar {
    flex-wrap: wrap;
    gap: 10px;
    padding: 10px;
  }

  /* SÓLO el grupo de las acciones en lote, hijo DIRECTO de la barra: el de las
     burbujas (filtros, columnas) también se llama `.archive-toolbar__group` y,
     estirado a un renglón entero, dejaba su caja de 400 px abriéndose en x=−334. */
  body.con-pestanas .archive-toolbar > .archive-toolbar__group {
    flex: 1 1 100%;
    min-width: 0;
  }

  /* `!important` porque el grupo es `.d-flex`, que lo es: sin él, el grupo vacío
     (en el teléfono el lote va abajo) seguía siendo un renglón y dejaba su hueco. */
  body.con-pestanas .archive-toolbar > .archive-toolbar__group:empty {
    display: none !important;
  }

  body.con-pestanas .archive-toolbar > .archive-toolbar__group select,
  body.con-pestanas .archive-toolbar > .archive-toolbar__group .field {
    flex: 1;
    min-width: 0;
  }

  /* LAS CAJAS DE LAS BURBUJAS (filtros, columnas) se anclan a la BARRA y no a su
     botón: con 400 px de ancho y el botón a la izquierda, colgadas de él se
     salían de la pantalla. Así ocupan el ancho de la barra, justo debajo. El
     pico deja de apuntar al botón, y se quita. */
  body.con-pestanas .archive-toolbar {
    position: relative;
  }

  body.con-pestanas .archive-toolbar__filters .bubble_wrapper {
    position: static;
  }

  body.con-pestanas .archive-toolbar__filters .bubble--box {
    left: 0;
    right: 0;
    width: auto;
  }

  body.con-pestanas .archive-toolbar__filters .bubble--box::before {
    content: none;
  }

  /* Y ninguna caja de burbuja más ancha que la pantalla: la de descargar cuelga
     de la cabecera de la página, pegada a la derecha. */
  body.con-pestanas .bubble--box {
    max-width: calc(100vw - 24px);
  }

  body.con-pestanas .archive-toolbar__filters {
    flex: 1 1 100%;
    flex-wrap: wrap;
    gap: 8px;
  }

  /* El separador vertical sólo tiene sentido en fila. */
  body.con-pestanas .archive-toolbar__divider {
    display: none;
  }

  /* Los controles de la BARRA, no los de dentro de las burbujas (que viven en su
     DOM): por eso los hijos directos y los disparadores, no `.archive-toolbar .btn`. */
  body.con-pestanas .archive-toolbar > .archive-toolbar__group .btn {
    min-height: 44px;
  }

  /* Selectores y buscador a 16 px: por debajo, el iPhone hace zoom a la página
     al enfocarlos y no la devuelve. */
  body.con-pestanas .archive-toolbar select,
  body.con-pestanas .archive-toolbar input:not([type="checkbox"]):not([type="radio"]) {
    min-height: 44px;
    font-size: 16px;
  }

  /* El selector de «buscar por» (Nombre, SKU…) cedía todo al campo y se leía
     «Nomb». Ancho propio y el resto para lo que se teclea. */
  body.con-pestanas .archive-toolbar__search select {
    flex: 0 0 116px;
    width: 116px;
  }

  /* Los atajos de fecha («Hoy», «Ayer», «Esta semana») son badges de 25 px. */
  body.con-pestanas .archive-atajos__opcion {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 14px;
    font-size: 13px;
  }

  body.con-pestanas .archive-toolbar .bubble_trigger.icon-chip {
    width: 44px;
    height: 44px;
  }

  /* ---- El lote, abajo ----------------------------------------------------- */
  /* Con algo marcado, el selector de la acción y «Ejecutar» van fijos sobre las
     pestañas (`BulkActions` los saca de la barra de arriba y los pinta aquí sólo
     en el teléfono). Arriba quedaban a treinta tarjetas de la que se acaba de
     marcar. Es el patrón de «Guardar» del formulario: misma altura y sombra. */
  body.con-pestanas .archive-lote {
    position: fixed;
    left: 0;
    right: 0;
    bottom: var(--pestanas-alto);
    z-index: 96;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    background: var(--surface-page, #fff);
    box-shadow: 0 -6px 24px rgba(34, 51, 59, 0.12);
    animation: archive-lote-entra 160ms ease-out;
  }

  body.con-pestanas .archive-lote select {
    flex: 1 1 auto;
    min-width: 0;
    min-height: 44px;
    font-size: 16px;
  }

  body.con-pestanas .archive-lote .btn {
    flex: 0 0 auto;
    min-height: 44px;
  }

  /* La última tarjeta no queda debajo de la barra. */
  body.con-pestanas #dashboard_page_content:has(.archive-lote) {
    padding-bottom: calc(var(--pestanas-alto) + 64px + 16px);
  }

  /* Los avisos («Seleccione una acción…») salen encima de la barra, no tapándola. */
  body.con-pestanas:has(.archive-lote) .toast-stack,
  body.con-pestanas:has(.archive-lote) .update-card {
    bottom: calc(var(--pestanas-alto) + 64px + 12px);
  }

  @keyframes archive-lote-entra {
    from {
      transform: translateY(100%);
    }
  }

  @media (prefers-reduced-motion: reduce) {
    body.con-pestanas .archive-lote {
      animation: none;
    }
  }

  /* ---- La paginación de abajo -------------------------------------------- */
  body.con-pestanas .archive_footer .archive-pagination {
    justify-content: center;
    gap: 8px;
    font-size: 14px;
  }

  body.con-pestanas .archive_footer .archive-pagination .icon-chip {
    width: 44px;
    height: 44px;
  }

  body.con-pestanas .archive_footer .archive-pagination > .archive-pagination__page {
    width: 60px;
    height: 44px;
    font-size: 16px;
  }

  /* ---- Las tarjetas ------------------------------------------------------- */
  .archive-tarjetas {
    margin: 8px 0;
  }

  /* Pegada bajo la cabecera mientras se baja: con 30 tarjetas, la cuenta de
     marcadas se perdía de vista. */
  .archive-tarjetas__barra {
    position: sticky;
    top: var(--cabecera-movil, 56px);
    z-index: 3;
    background: var(--surface-sunken-light, #F4F7F9);
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 12px;
    min-height: 44px;
  }

  .archive-tarjetas__cuenta {
    flex: 1;
    font-size: 13px;
    font-weight: 600;
    color: var(--text-secondary);
    text-align: center;
  }

  .archive-tarjetas__enlace {
    min-height: 44px;
    padding: 0 4px;
    border: 0;
    background: transparent;
    color: var(--text-link, #008A91);
    font-family: var(--font-sans);
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
  }

  .archive-tarjetas__lista {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
  }

  .archive-tarjeta {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 12px 4px 12px 14px;
    border: 2px solid transparent;
    border-radius: var(--radius-md, 10px);
    background: var(--surface-page, #fff);
    color: var(--text-primary);
  }

  .archive-tarjeta--pulsable {
    cursor: pointer;
  }

  .archive-tarjeta--pulsable:active {
    background: var(--surface-sunken-light, #F4F7F9);
  }

  .archive-tarjeta--marcada {
    border-color: var(--action-primary-default, #00B4BD);
  }

  .archive-tarjeta__casilla {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    min-height: 44px;
    margin: -8px 0 -8px -6px;
    cursor: pointer;
  }

  .archive-tarjeta__imagen {
    flex-shrink: 0;
    width: 56px;
    height: 56px;
    border-radius: var(--radius-md, 8px);
    overflow: hidden;
    background: var(--surface-sunken-light, #F4F7F9);
  }

  .archive-tarjeta__imagen a,
  .archive-tarjeta__imagen img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  .archive-tarjeta__cuerpo {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding-top: 2px;
  }

  .archive-tarjeta__cabeza {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
  }

  .archive-tarjeta__titulo {
    min-width: 0;
    font-size: 15px;
    font-weight: 800;
    line-height: 1.3;
    overflow-wrap: anywhere;
  }

  .archive-tarjeta__titulo a {
    color: inherit;
    text-decoration: none;
  }

  .archive-tarjeta__importe {
    flex-shrink: 0;
    font-size: 16px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    text-align: right;
  }

  /* Los datos, en dos columnas de etiqueta sobre valor: en una tarjeta no hay
     cabecera de columna que diga qué es cada cosa. */
  .archive-tarjeta__datos {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px 12px;
    margin: 0;
  }

  .archive-tarjeta__dato {
    min-width: 0;
  }

  .archive-tarjeta__dato dt {
    margin: 0 0 1px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-muted);
  }

  /* Lo que la celda trae centrado para la tabla (la pastilla del método de
     pago, el inventario) aquí va a la izquierda, bajo su etiqueta. */
  .archive-tarjeta__dato dd,
  .archive-tarjeta__dato dd > * {
    justify-content: flex-start;
    text-align: left;
  }

  .archive-tarjeta__dato dd {
    margin: 0;
    font-size: 13px;
    font-weight: 500;
    line-height: 1.35;
    overflow-wrap: anywhere;
  }

  .archive-tarjeta__estado {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
  }

  /* Refrescando se atenúan los DATOS, no la tarjeta: una opacidad en la tarjeta
     o en la lista crea un contexto de apilamiento y el menú ⋯ abierto quedaba
     atrapado debajo de la barra de pestañas. */
  .archive-tarjetas--refrescando .archive-tarjeta__cuerpo,
  .archive-tarjetas--refrescando .archive-tarjeta__imagen {
    opacity: 0.6;
  }

  /* El ⋯ de la fila, a 44 px: es lo que se toca. Sin acciones no deja hueco. */
  .archive-tarjeta__acciones:empty {
    display: none;
  }

  .archive-tarjeta__acciones {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
    margin: -8px 0;
  }

  .archive-tarjeta__acciones .icon-chip {
    width: 44px;
    height: 44px;
  }
}

/* ============================================================================
   EL FORMULARIO EN EL TELÉFONO (doc 66, M4)

   Agregar o editar producto, cliente, cupón, usuario, movimiento de
   inventario… comparten el «form panel»: una columna principal (`col-9`) con
   campos en `col-N` que no colapsan —el grid sólo tiene puntos de corte desde
   768— y una barra lateral (`col-3`) con las pestañas y el botón de guardar.
   A 390 px eso eran tres campos por renglón de 60 px y la barra a la derecha.

   Aquí: una columna, las pestañas ARRIBA como chips deslizables pegados bajo la
   cabecera, y el botón de guardar FIJO abajo, sobre las pestañas de la app.
   Todo CSS: el marcado es el mismo en las dos pantallas.
   ============================================================================ */

@media (max-width: 767.98px) {
  /* ---- Una columna -------------------------------------------------------- */
  body.con-pestanas .ajax_form .row > [class*="col-"] {
    flex: 0 0 100%;
    width: 100%;
    max-width: 100%;
  }

  /* Salvo los renglones que llevan un menú ⋯ o un botón chico al lado de su
     campo (el estatus del producto; el engrane de cada opción de variación): el
     botón se queda junto a su campo y no baja a un renglón propio. */
  body.con-pestanas .ajax_form .row:has(> .gwfield_bubble_menu, > .gwfield_button.col-1, > .gwfield_button.col-2) > [class*="col-"] {
    flex: 1 1 0;
    width: auto;
  }

  body.con-pestanas .ajax_form .row:has(> .gwfield_bubble_menu, > .gwfield_button.col-1, > .gwfield_button.col-2) > :is(.gwfield_bubble_menu, .gwfield_button) {
    flex: 0 0 44px;
  }

  /* La cabecera del panel (nombre + estatus) con menos aire: 25 px por lado se
     comían el ancho del nombre. */
  body.con-pestanas .form_panel_header {
    padding: 12px;
  }

  /* ---- Las pestañas, arriba ---------------------------------------------- */
  /* Pegadas bajo la cabecera mientras se baja por el formulario: con cinco
     pestañas y treinta campos, cambiar de pestaña no debe pedir volver arriba.

     Un `sticky` sólo se pega dentro de su PADRE, y la columna de la barra mide
     lo mismo que la barra: no se pegaba nunca. Con la columna en `contents` la
     tira pasa a ser hija del renglón del panel, que mide todo el formulario. */
  body.con-pestanas .form_panel_sidebar_wrapper {
    display: contents;
  }

  body.con-pestanas .form_panel_sidebar {
    order: -1;
    flex: 0 0 calc(100% - 24px);
    min-width: 0;
    max-width: calc(100% - 24px);
    align-self: flex-start;
    margin: 0 12px 12px;
    top: var(--cabecera-movil);
    z-index: 5;
    padding: 8px;
  }

  /* El cuerpo del widget trae 30 px de relleno: la tira de pestañas medía 120 px
     de alto para 44 de chips. */
  body.con-pestanas .form_panel_sidebar .widget_body {
    padding: 0;
  }

  /* `!important` porque el marcado trae `.flex-column`, que es
     `flex-direction: column !important` (`ds/utilities.css`). */
  body.con-pestanas .form_panel_tabs {
    flex-direction: row !important;
    gap: 8px;
    overflow-x: auto;
    scrollbar-width: none;
    overscroll-behavior-x: contain;
  }

  body.con-pestanas .form_panel_tabs::-webkit-scrollbar {
    display: none;
  }

  body.con-pestanas .sidebar_tab {
    flex-shrink: 0;
    min-height: 44px;
    padding: 4px 14px 4px 4px;
    white-space: nowrap;
  }

  /* ---- Las listas que se repiten (productos de un movimiento, ingredientes) --
     Cada renglón reservaba 50 px a la DERECHA para el botón de borrar, por fuera
     de su caja: a 390 px los campos quedaban en 175. El borrar sube a la esquina
     de dentro y el renglón usa el ancho entero.

     ⚠ La agarradera de la izquierda SE QUEDA: es lo único que reordena (el
     arrastre y las flechas del teclado viven en ella, `ListaRepetible.tsx`), y
     sin ella no se podían ordenar categorías, zonas de mesas ni ingredientes. */
  body.con-pestanas .field_blocks_list {
    padding: 8px 8px 28px;
  }

  body.con-pestanas .list_item .list_item_wrapper {
    width: auto;
  }

  body.con-pestanas .list_item .list_item_header {
    padding: 12px;
  }

  /* El hueco de arriba sólo cuando HAY botón de borrar: las listas de sólo
     edición (el stock por sucursal) no lo llevan. */
  body.con-pestanas .list_item .list_item_header:has(> .delete_list_item) {
    padding-top: 52px;
  }

  body.con-pestanas .list_item .delete_list_item {
    top: 8px;
    right: 8px;
    left: auto;
    width: 44px;
    height: 44px;
  }

  /* Formularios SIN pestañas (almacén, movimiento de inventario, atributo): su
     barra sólo lleva el botón, que sale del flujo al fijarse abajo; sin esto
     quedaba una tira blanca vacía pegada bajo la cabecera. */
  body.con-pestanas .form_panel_sidebar:not(:has(.form_panel_tabs)) {
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
    box-shadow: none;
  }

  /* ---- Guardar, fijo abajo ------------------------------------------------ */
  body.con-pestanas .form_panel_sidebar .form_footer {
    position: fixed;
    left: 0;
    right: 0;
    bottom: var(--pestanas-alto);
    z-index: 96;
    margin: 0 !important; /* `.mt-3` es `!important` */
    padding: 10px 12px;
    background: var(--surface-page, #fff);
    box-shadow: 0 -6px 24px rgba(34, 51, 59, 0.12);
  }

  body.con-pestanas .form_panel_sidebar .form_footer .btn {
    min-height: 52px;
  }

  /* El contenido deja sitio al botón fijo, para que el último campo no quede
     debajo de él. */
  body.con-pestanas #dashboard_page_content:has(.form_panel_sidebar .form_footer) {
    padding-bottom: calc(var(--pestanas-alto) + 72px + 16px);
  }

  /* Los avisos y la tarjeta de «hay versión nueva» suben por encima del botón:
     encima de él taparían justo lo que hay que pulsar. */
  body.con-pestanas:has(.form_panel_sidebar .form_footer) .toast-stack,
  body.con-pestanas:has(.form_panel_sidebar .form_footer) .update-card {
    bottom: calc(var(--pestanas-alto) + 72px + 12px);
  }
}

/* CUANDO EL NAVEGADOR LLEVA LA VISTA A UN CAMPO —el obligatorio que faltó, el
   siguiente con Tab— lo pone pegado al borde, y en el teléfono ahí están la
   cabecera (y la tira de pestañas del formulario) arriba y las pestañas de la
   app (y el botón de guardar) abajo. `scroll-padding` le dice cuánto apartarse.
   Va en `html`, que es quien desplaza, y por eso con `:has()`. */
@media (max-width: 767.98px) {
  html:has(body.con-pestanas) {
    scroll-padding-top: calc(56px + env(safe-area-inset-top, 0px) + 16px);
    scroll-padding-bottom: calc(60px + env(safe-area-inset-bottom, 0px) + 16px);
  }

  html:has(body.con-pestanas .form_panel_tabs) {
    scroll-padding-top: calc(56px + env(safe-area-inset-top, 0px) + 60px + 16px);
  }

  html:has(body.con-pestanas .form_panel_sidebar .form_footer) {
    scroll-padding-bottom: calc(60px + env(safe-area-inset-bottom, 0px) + 72px + 16px);
  }

  /* Y la barra del lote: al pasar con Tab o TalkBack por las casillas, la tarjeta
     enfocada no queda debajo de ella. */
  html:has(body.con-pestanas .archive-lote) {
    scroll-padding-bottom: calc(60px + env(safe-area-inset-bottom, 0px) + 64px + 16px);
  }
}

/* ============================================================================
   M5 — EL RESUMEN, EL TURNO Y LO PEQUEÑO (doc 66)
   ============================================================================ */
@media (max-width: 767.98px) {
  /* ---- Todo lo tocable, a 44 ---------------------------------------------
     Un solo token: `--control-md` es el alto de los campos, los botones, los
     selects y los chips del DS (40 en escritorio). En el teléfono el dedo pide
     44 —la regla de la puerta del doc 66— y así lo cumplen todos a la vez, en
     vez de perseguirlos pantalla por pantalla. */
  body.con-pestanas {
    --control-md: 44px;
  }

  /* Los chips CHICOS que viven dentro de un campo (generar el SKU, el ⋯ de una
     lista) o junto a él (añadir renglón) se quedan de 30 a la vista —agrandarlos
     descuadraría el campo— pero su zona de toque crece a 44 por fuera. */
  body.con-pestanas .input > .icon-chip--sm,
  body.con-pestanas .list_field_actions > .icon-chip--sm {
    position: relative;
  }

  body.con-pestanas .input > .icon-chip--sm::after,
  body.con-pestanas .list_field_actions > .icon-chip--sm::after {
    content: '';
    position: absolute;
    inset: -7px;
  }

  /* Las opciones de los desplegables (sucursal, categoría, cliente…) medían 28:
     elegir «Sucursal Principal» entre «Este» y «Reforma» era atinarle a una
     franja de 13 px por renglón en pantalla. Con relleno y NO con flex: al
     buscar, selectize parte el texto en `<span class="highlight">`, y como
     piezas de un flex los espacios de las orillas se pierden («SucursalPr…»). */
  body.con-pestanas .selectize-dropdown .option,
  body.con-pestanas .selectize-dropdown .create {
    min-height: 44px;
    padding-block: 12px;
    line-height: 20px;
  }

  /* Casillas e interruptores: el renglón entero (la casilla y su texto) es lo
     que se toca, y medía 18. En la lista de categorías del producto eran quince
     renglones de 18 px pegados. */
  body.con-pestanas .choice {
    min-height: 44px;
  }

  /* Dentro de una tarjeta del archive: el título (abre la ficha) y los enlaces
     de los datos (el teléfono de un cliente) medían 16–19 de alto. El relleno
     con margen negativo les da 44 al dedo sin mover un píxel de la tarjeta. */
  body.con-pestanas .archive-tarjeta__titulo a,
  body.con-pestanas .archive-tarjeta__dato a {
    display: inline-block;
    padding-block: 14px;
    margin-block: -14px;
  }

  /* La estrella de «destacado» se queda de 30 a la vista; 44 al dedo. */
  body.con-pestanas .archive_item_featured_toggle {
    position: relative;
  }

  body.con-pestanas .archive_item_featured_toggle::after {
    content: '';
    position: absolute;
    inset: -7px;
  }

  /* En la hoja del carrito, los precios de cada renglón abren su edición
     (descuento, nota) y medían 37. */
  body.con-pestanas .pos_cart_item_prices[role='button'] {
    min-height: 44px;
  }

  /* La caja de categorías del producto topa en 200 px con su propio scroll:
     con renglones de 44 se veían cuatro de veinte, en una caja que desplaza
     dentro de una página que también desplaza. En el teléfono crece entera. */
  body.con-pestanas .catogories_box {
    max-height: none;
  }

  /* El deslizador del radio de entrega, a la altura de los campos de al lado. */
  body.con-pestanas .juicy-range {
    height: 44px;
  }

  /* El spinner del catálogo de la caja se dibuja con `--control-md` y se
     centra restando 25 a mano: con el token a 44 caía 3 px fuera de centro.
     Se queda en los 40 de siempre. */
  body.con-pestanas .pos_product_archive::after {
    width: 40px;
    height: 40px;
  }

  /* ---- Los widgets del resumen y de Analytics ----------------------------- */

  /* Los títulos se parten en dos renglones en vez de cortarse: «VENTAS DE H…»,
     «PRÓXIMOS A C…» no decían qué medían. */
  body.con-pestanas .widget__title {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    letter-spacing: 1px;
  }

  body.con-pestanas .widget--kpi .widget__title {
    font-size: 12px;
  }

  /* De dos en dos, una cifra de 32 px no cabe cuando la venta pasa de los
     cinco dígitos («$12,345.00» medía 190 en una tarjeta de 165). Menos
     relleno y una cifra que encoge con la pantalla, SIN partirse: partida a
     media cifra se lee como dos números. */
  body.con-pestanas .widget--kpi {
    padding: 14px;
  }

  body.con-pestanas .widget--kpi .widget__number {
    font-size: clamp(18px, 5.6vw, 24px);
    white-space: nowrap;
  }

  /* Y la pareja mide lo mismo aunque un título se parta en dos renglones. */
  body.con-pestanas .dash_kpis {
    align-items: stretch;
  }

  /* «Ver todo» medía 15 px de alto. El margen negativo le da los 44 sin
     engordar la cabecera del widget. */
  body.con-pestanas .widget__link {
    min-height: 44px;
    margin-block: -14px;
  }

  /* Las tablas de los widgets: más apretadas, y si aun así no caben, se
     deslizan DENTRO de su caja. Antes la tabla se salía y la cortaba el
     contenido (`overflow: clip`): «Se te acaba pronto» y «Por persona», de
     Analytics, perdían su última columna sin forma de verla. */
  body.con-pestanas .widget__body--flush {
    overflow-x: auto;
    overscroll-behavior-x: contain;
  }

  body.con-pestanas .table .table__head,
  body.con-pestanas .table th,
  body.con-pestanas .table .table__cell,
  body.con-pestanas .table tbody td {
    padding-inline: 10px;
  }

  /* Las orillas, a los 20 de la cabecera del widget: el texto de la primera
     columna arranca alineado con el título. */
  body.con-pestanas .table tr > :first-child {
    padding-left: 20px;
  }

  body.con-pestanas .table tr > :last-child {
    padding-right: 20px;
  }

  /* La tabla como LISTA (`WidgetTabla enTelefono="lista"`: las órdenes
     recientes). A la derecha, el total sobre su estatus. */
  body.con-pestanas .widget__list--tabla .widget__row-title {
    font-size: 14px;
  }

  body.con-pestanas .widget__row-fin {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 4px;
    flex-shrink: 0;
  }

  body.con-pestanas .widget__row-importe {
    font-size: 14px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
  }

  /* ---- La cabecera de la caja: ⋯, bloquear y cerrar -----------------------
     Son las dos puertas del turno y medían 30. A 36 a la vista y 44 al dedo:
     a 44 los tres no caben junto al logo, la campana y la cuenta a 360 px. */
  body.con-pestanas #dashboard_header .actions_list {
    gap: 8px;
  }

  /* Las píldoras de la cabecera («Modo offline», «3 sin subir», «2 por
     revisar») se quedan en icono y cifra: con su texto, a 360 px empujaban los
     chips de la caja encima del logo y tapaban «Cerrar caja». El texto sigue
     ahí para el lector de pantalla y en el `title`. */
  body.con-pestanas #dashboard_header .cabecera-pildora__texto {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  /* Y aun en icono no caben con el logo: a 360 px la cabecera de la caja
     (logo, tres chips, campana y cuenta) deja 8 px libres. Mientras haya una
     píldora, el logo cede su sitio: avisa de algo que hay que atender, y a
     Inicio se sigue llegando por su pestaña. */
  body.con-pestanas #dashboard_header:has(.cabecera-pildora__texto) .cabecera-movil__logo {
    display: none;
  }

  body.con-pestanas #dashboard_header [data-ventas-pendientes]::after {
    content: attr(data-ventas-pendientes);
  }

  body.con-pestanas #dashboard_header [data-ventas-rechazadas]::after {
    content: '! ' attr(data-ventas-rechazadas);
  }

  body.con-pestanas #dashboard_header .actions_list .icon-chip--sm {
    --icon-chip-size: 36px;
    position: relative;
  }

  body.con-pestanas #dashboard_header .actions_list .icon-chip--sm::after {
    content: '';
    position: absolute;
    inset: -4px;
  }

  /* El menú del ⋯ se abría hacia la IZQUIERDA del chip (el DS lo ancla por la
     derecha, que en escritorio es lo que cabe): aquí el chip está pegado al
     logo y el menú caía en x = −61, con «Ver Ordenes» cortado. Se ancla por la
     izquierda y el pico se mueve con él. */
  body.con-pestanas #dashboard_header .actions_list .bubble {
    left: 0;
    right: auto;
  }

  body.con-pestanas #dashboard_header .actions_list .bubble::before {
    left: 10px;
    right: auto;
  }

  /* ---- Cierre de caja, a pantalla completa ---------------------------------
     Como el cobro (M2): en una ventana flotante el corte se leía a 280 px de
     ancho y «Cerrar Caja» quedaba al fondo de un desplazamiento DENTRO de la
     ventana. Ahora ocupa la pantalla y el botón queda anclado abajo. */
  body.con-pestanas #closePOS > .lightbox__content {
    display: flex;
    flex-direction: column;
    width: 100%;
    max-width: none;
    height: 100dvh;
    max-height: none;
    border-radius: 0;
  }

  body.con-pestanas #closePOS > .lightbox__content > .lightbox__header {
    flex-shrink: 0;
    height: calc(56px + env(safe-area-inset-top, 0px));
    padding-top: env(safe-area-inset-top, 0px);
    padding-left: 16px;
    border-radius: 0;
  }

  body.con-pestanas #closePOS > .lightbox__content .lightbox__close {
    width: 56px;
    height: 56px;
    border-radius: 0;
  }

  /* `!important` en el `display`: el cuerpo trae `.d-inline-block`, que es
     `inline-block !important` (`ds/utilities.css`). Sin él no era flex y el
     botón no bajaba al fondo cuando sobra pantalla (430 px con el arqueo
     plegado: 150 px vacíos debajo de «Cerrar Caja»). */
  body.con-pestanas #closePOS > .lightbox__content > .lightbox__body {
    flex: 1;
    min-height: 0;
    max-height: none;
    padding: 16px 16px 0;
    overscroll-behavior: contain;
    display: flex !important;
    flex-direction: column;
  }

  body.con-pestanas #closePOS > .lightbox__content > .lightbox__body > * {
    flex-shrink: 0;
  }

  body.con-pestanas #closePOS > .lightbox__content > .lightbox__body > .buttons_list {
    margin-top: auto;
    position: sticky;
    bottom: 0;
    z-index: 2;
    padding: 12px 0 calc(12px + env(safe-area-inset-bottom, 0px));
    background: var(--surface-page, #fff);
  }

  body.con-pestanas #closePOS .buttons_list .btn {
    flex: 1;
    min-height: 52px;
  }

  /* El arqueo: el plegable a 44 de alto, y cada denominación con su campo a
     16 px (a 12 el iPhone hacía zoom al tocarlo) y 44 de alto. */
  /* Con relleno y no con `display: flex`: un `<summary>` flex pierde su ▶. */
  body.con-pestanas #closePOS .arqueo_toggle {
    padding-block: 13px;
    line-height: 18px;
  }

  body.con-pestanas #closePOS .arqueo_denom_label {
    min-width: 52px;
  }

  body.con-pestanas #closePOS .arqueo_denom {
    flex: 1;
    min-width: 0;
    height: 44px;
    font-size: 16px;
  }

  /* ---- Abrir caja -----------------------------------------------------------
     Se queda como ventana (son dos campos), con el botón a todo el ancho. Los
     campos ya miden 44 por el token de arriba. */
  body.con-pestanas #openPOSLightbox .form_footer .btn {
    flex: 1;
    min-height: 52px;
  }
}

/* ============================================================================
   LAS TABLAS DE LOS LIGHTBOX Y LOS CAMPOS DE FECHA (doc 66, después de M5)
   ============================================================================ */
@media (max-width: 767.98px) {
  /* `.data_table` es la tabla de los lightbox (detalle de orden, reembolso,
     ventas rechazadas, detalle de un movimiento). En una ventana de 336 px sus
     cuatro columnas no cabían: la tabla se deslizaba de lado y la última
     («Total») quedaba cortada. Más apretada y con la cabecera en dos renglones,
     cabe; si alguna no cabe, su caja sigue deslizando como antes. */
  /* La cabecera se parte en renglones; donde una palabra sola no cabe, la
     cabecera trae guiones suaves (el reembolso: «Rein-tegrar»). El corte
     automático no sirve: la página se declara `en-US`. */
  body.con-pestanas .data_table thead th {
    padding: 8px;
    font-size: 11px;
    white-space: normal;
  }

  body.con-pestanas .data_table tbody td {
    padding: 8px;
  }

  body.con-pestanas .data_table tr > :first-child {
    padding-left: 12px;
  }

  body.con-pestanas .data_table tr > :last-child {
    padding-right: 12px;
  }

  /* Y si aun así no cabe, la tabla se desliza dentro de su caja en vez de
     salirse de ella (el detalle de un movimiento se salía de su tarjeta). */
  body.con-pestanas :has(> .data_table) {
    overflow-x: auto;
  }

  /* La tarjeta vieja (`.widget_body`, 30 px de relleno) que lleva una tabla
     (el detalle de un movimiento): en el teléfono, 16. Sólo ésa: `.widget_body`
     es también el cuerpo de todos los formularios, que M4 dejó como estaban. */
  body.con-pestanas .widget_body:has(.data_table) {
    padding: 16px;
  }

  /* Los campos de dentro de una tabla (cantidad y monto del reembolso) iban a
     12 px: el iPhone hace zoom al tocarlos. */
  body.con-pestanas .data_table input:not([type='checkbox']):not([type='radio']) {
    font-size: 16px;
  }

  /* LAS VENTANAS, MÁS ANCHAS. El DS deja 20 px contra cada borde de la
     pantalla y 25 de relleno dentro: en 390 px quedaban 300 para el contenido,
     y una tabla de cuatro columnas (el reembolso) se cortaba. En el teléfono, el
     mismo margen de 12 que el resto del contenido y 16 de relleno a los lados.
     Sólo los lados: el de arriba lo usa `--spaced-top`. El cobro y el grupo
     tienen sus propias reglas (pantalla completa) y no les afecta. */
  body.con-pestanas .lightbox {
    --lightbox-box-width: calc(100% - 24px);
  }

  body.con-pestanas .lightbox__body {
    padding-left: 16px;
    padding-right: 16px;
  }

  /* Y el título, alineado con el cuerpo (traía 24). El centrado va igual de
     los dos lados, o deja de estar centrado. */
  body.con-pestanas .lightbox__header {
    padding-left: 16px;
  }

  body.con-pestanas .lightbox__header--center {
    padding-inline: 16px;
  }

  /* Los campos de fecha y hora NATIVOS (sin la envoltura `.input` del DS: el
     filtro de Propinas, por ejemplo) medían 22 px a 13 px: chicos para el dedo
     y, a menos de 16 px, el iPhone hace zoom al tocarlos. */
  body.con-pestanas input[type='date']:not(.input__el),
  body.con-pestanas input[type='time']:not(.input__el),
  body.con-pestanas input[type='datetime-local']:not(.input__el) {
    min-height: 44px;
    font-size: 16px;
  }
}
