/* ============================================================================
   Juicy — Dashboard Design System · UTILITIES
   ----------------------------------------------------------------------------
   Reemplazo de `bootstrap-utilities.min.css` (56 KB). F6b, quitar Bootstrap.

   Reproduce SOLO las clases de utilidad EN USO por algún consumidor del DS
   (censo sobre juicy-core + gw-fields + Hub): no las ~1500 de Bootstrap. Una
   utilidad que falte mañana es un `add` de una línea — pero no se generan a lo
   bruto: lo que no se usa, no entra (mismo criterio que mató los tokens muertos
   del DS). "Usado" = la UNIÓN de consumidores, no un repo: el Hub añadió
   `border`/`border-top`/`p-3`/`pt-3`/`py-2`/`align-items-end` que juicy-core no
   usa — reproducirlas aquí evita que el Hub se rompa al quitar Bootstrap (F-hub-1).

   ⚠️ LLEVAN `!important`, A PROPÓSITO. Las utilidades de Bootstrap son
   `!important`, y el producto se apoya en eso: una `.text-center` gana aunque un
   selector más específico diga otra cosa. Reproducirlas SIN `!important` sería un
   cambio de conducta silencioso (perderían ante `.foo .bar{…}`). Es deuda —
   `!important` en utilidades es un martillo— pero quitarlo es una decisión
   aparte, medible, no un efecto colateral de esta migración. Ver el plan §4.a.

   Valores = la escala de Bootstrap 5, al pie de la letra (0·.25·.5·1·1.5·3 rem),
   para no mover un pixel. NO se cablean a `--space-*` del DS: esa escala es otra
   (y hoy ningún componente la consume). Convergerlas es trabajo futuro y visible.
   ============================================================================ */

/* ---- Display -------------------------------------------------------------- */
.d-none         { display: none !important; }
.d-block        { display: block !important; }
.d-inline-block { display: inline-block !important; }
.d-flex         { display: flex !important; }
.d-inline-flex  { display: inline-flex !important; }

/* ---- Flexbox -------------------------------------------------------------- */
.flex-column   { flex-direction: column !important; }
.flex-wrap     { flex-wrap: wrap !important; }
/* `start` es el valor por defecto de flex, así que la clase no mueve un píxel
   donde ya se usaba — pero el marcado la escribía y el DS no la tenía, y una
   clase que no existe se lee igual que un estilo mal hecho. Entra por simetría
   con las otras tres: tener `end` y no `start` es el hueco por el que el marcado
   se va a Bootstrap. */
.justify-content-start   { justify-content: flex-start !important; }
.justify-content-center  { justify-content: center !important; }
.justify-content-end     { justify-content: flex-end !important; }
.justify-content-between { justify-content: space-between !important; }
.align-items-start   { align-items: flex-start !important; }
.align-items-center  { align-items: center !important; }
.align-items-end     { align-items: flex-end !important; }

/* ---- Gap (escala de Bootstrap) -------------------------------------------- */
.gap-1 { gap: 0.25rem !important; }
.gap-2 { gap: 0.5rem !important; }
.gap-3 { gap: 1rem !important; }

/* ---- Sizing --------------------------------------------------------------- */
.w-100 { width: 100% !important; }

/* ---- Position ------------------------------------------------------------- */
.position-relative { position: relative !important; }
.position-sticky   { position: sticky !important; }

/* ---- Texto ---------------------------------------------------------------- */
.text-start  { text-align: left !important; }
.text-end    { text-align: right !important; }
.text-center { text-align: center !important; }

/* Utilidades de COLOR — el censo halló SOLO estas dos (1 uso c/u): el subtítulo
   de fecha del home (`text-secondary`) y el guion de "sin dato" del archive de
   clientes (`text-muted`). Bootstrap las pintaba con grises ARBITRARIOS
   (`text-secondary`=#6c757d, `text-muted`=rgba(33,37,41,.75)); aquí se mapean al
   TOKEN del DS de la misma intención — es el nombre de la clase cumpliendo lo que
   dice. Cambia el tono un pelo (DS-nativo) y de paso el guion vacío queda más
   tenue, que es lo correcto para un placeholder. Documentado como corrección
   deliberada, no como fidelidad al pixel. (Estas dos NO estaban en el censo
   inicial: mi regex de `text-*` no cubría los colores de tema — hueco corregido.) */
.text-secondary { color: var(--text-secondary) !important; }
.text-muted     { color: var(--text-muted) !important; }

/* `.text-red` — VINO DE `main.css` (0.9.157), donde estaba bajo "TEXTS COLORS" desde siempre.
   Es una utilidad de color como las dos de arriba, así que su sitio es esta hoja; que viviera en
   la legacy significaba que **el mismo marcado salía de dos colores**, porque el front nuevo no
   importa `main.css` a propósito. Medido con el espejo en Ajustes › Registradoras: el aviso de
   contraste del logo (`.juicy-logo-preview-warn`, que PHP emite con esta clase) daba
   `rgb(240,68,56)` en PHP y `rgb(62,67,73)` —el gris heredado— en React.

   ⚠ CON `--red-500` Y NO CON `--error-500`, que es lo que decía la regla original. Ese segundo es
   un ALIAS que define `main.css` (`--error-500: var(--red-500)`), o sea que en el front no existe
   y la declaración entera se cae sin decir nada. Es la trampa que ya está contada en
   `ds/bubble.css` a cuenta de esta misma clase, y por la que allí `.remove-filters-link` tuvo que
   declararse su propio color. El valor es el mismo #F04438, así que en PHP no se mueve un pixel —
   verificado con `foto-estilos.mjs` en dos pantallas, 0 diferencias.

   LA USAN 14 sitios del producto: los enlaces "Quitar Filtros" de ocho archives, los contadores de
   error de los tres importadores, los importes reembolsados del historial, el arqueo negativo de
   la caja y el aviso del logo de Ajustes. */
.text-red       { color: var(--red-500) !important; }

/* `.screen-reader-text` — NO viene de Bootstrap: es la clase de WORDPRESS para texto que solo leen
   los lectores de pantalla, y la usa el marcado que sale de WooCommerce. En el dashboard de PHP la
   pintaba la hoja de WooCommerce; el front nuevo NO carga esa hoja, así que la clase no existía en
   ninguna parte y el texto salía A LA VISTA. Medido en el archive de productos: el precio de un
   producto en oferta se leía "$23.00 Original price was: $23.00.$20.00Current price is: $20.00." —
   `display:inline`, 178px de ancho, sin una sola regla que lo escondiera.

   Es la técnica canónica de WP (clip + 1x1), NO `display:none` ni `visibility:hidden`: esas dos lo
   esconden TAMBIÉN del lector de pantalla, que es justo lo contrario de lo que la clase promete. */
.screen-reader-text {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---- Bordes (solo las usa el Hub: `.border`, `.border-top`) ----------------
   Bootstrap las pinta con `var(--bs-border-color)` = #dee2e6, definido en el
   `:root` de bootstrap-grid. Al quitar Bootstrap ese token desaparece; se
   reproduce el valor literal (fiel al pixel, como toda esta hoja). Tokenizarlo a
   un borde del DS es convergencia futura (F-hub-2/3), no un efecto colateral. */
.border     { border: 1px solid #dee2e6 !important; }
.border-top { border-top: 1px solid #dee2e6 !important; }

/* ---- Spacing (margin/padding, escala 0·.25·.5·1·1.5·3 rem) ----------------
   Solo los lados/pasos EN USO. mx-auto centra en horizontal. */
.m-0  { margin: 0 !important; }
.mt-1 { margin-top: 0.25rem !important; }
.mt-2 { margin-top: 0.5rem !important; }
.mt-3 { margin-top: 1rem !important; }
.mt-4 { margin-top: 1.5rem !important; }
.mt-5 { margin-top: 3rem !important; }
.mb-0 { margin-bottom: 0 !important; }
.mb-1 { margin-bottom: 0.25rem !important; }
.mb-2 { margin-bottom: 0.5rem !important; }
.mb-3 { margin-bottom: 1rem !important; }
.mb-4 { margin-bottom: 1.5rem !important; }
.my-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; }
.mx-auto { margin-right: auto !important; margin-left: auto !important; }
/* `ms`/`me` = start/end, la nomenclatura lógica de Bootstrap 5 que ya sigue el
   resto del archivo (`.pe-1`). `ms-auto` es "empújame al final de la fila" y la
   usa el chevron del submenú de la barra lateral. */
.ms-auto { margin-left: auto !important; }
.me-auto { margin-right: auto !important; }

.p-0  { padding: 0 !important; }
.p-3  { padding: 1rem !important; }
.p-4  { padding: 1.5rem !important; }
.pe-1 { padding-right: 0.25rem !important; }
.pt-3 { padding-top: 1rem !important; }
.py-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; }
.py-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; }
.py-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; }
.py-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; }

/* ---- Responsivo (los únicos en uso: md/lg) -------------------------------- */

/* 768 = el MISMO corte que `col-md-*` de `grid.css`. Va atado a propósito: la
   cabecera del KDS pone `col-12 col-md-6` y alinea sus áreas a la derecha en el
   mismo punto en que la columna pasa a media fila. Con otro corte, hay un rango
   de anchos en que la columna ya es media y el contenido sigue a la izquierda. */
@media (min-width: 768px) {
  .justify-content-md-end { justify-content: flex-end !important; }
}

@media (min-width: 992px) {
  .d-lg-flex { display: flex !important; }
}

/* ---- Scroll horizontal SIN barra (`data-hscroll`) -------------------------
   Para barras que se desbordan a lo ancho: las categorías de la caja y los tabs
   de comensales. La barra de scroll estorba a la vista, y esconderla obliga a
   dar otra forma de moverse — de eso se encarga el JS (main.js): rueda del
   ratón (vertical → horizontal) y arrastre. En táctil el arrastre ya es nativo
   y no se toca.

   SIN `!important`, aunque el resto del archivo lo lleve: esto no es una
   utilidad de layout que deba ganarle a un componente, es un comportamiento.
   Un componente que necesite otro `overflow` tiene que poder pedirlo.
   ------------------------------------------------------------------------- */
[data-hscroll] {
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;          /* Firefox */
  -ms-overflow-style: none;       /* Edge legacy */
  overscroll-behavior-x: contain; /* llegar al borde no dispara el "atrás" */
}

/* Chrome/Safari ignoran `scrollbar-width`: ésta es la que de verdad la esconde
   ahí, y es la que faltaba (la barra de categorías ya traía la de Firefox). */
[data-hscroll]::-webkit-scrollbar {
  display: none;
}

/* Arrastrando: el cursor lo dice y el texto de los tabs no se selecciona
   (arrastrar sobre texto lo pinta de azul y se ve como un error). */
[data-hscroll].is-hdragging {
  cursor: grabbing;
  user-select: none;
}
