/* Tarjeta de producto heredada del sistema anterior (REFERENCIA_TARJETA_
   PRODUCTO.md). El aspecto se conserva con fidelidad; el comportamiento se
   reescribe para el router (montar/desmontar, delegación de eventos).
   Una sola tarjeta, tres densidades: --admin, --pos, --store. */

.store-product-card {
    /* Excepciones documentadas del heredado: estos dos colores no están en
       la lista de tokens de la sección 11 porque la tarjeta se conserva
       "tal cual" (sección 11: "Se conserva sin cambios"). No se usan fuera
       de este componente. */
    --tarjeta-fondo: #fdfdfd;
    --tarjeta-imagen-vacia: #f1eeea;

    /* Ancla de la insignia de estado cuando se sube sobre la imagen. */
    position: relative;

    scroll-snap-align: start;
    flex: 0 0 172px;
    width: 172px;
    display: flex;
    flex-direction: column;
    border-radius: var(--radio-tarjeta);
    border: 1px solid var(--linea);
    background: var(--tarjeta-fondo);
    padding: 10px;
    gap: 8px;
}

.store-product-card:focus-visible {
    outline: 2px solid var(--accion);
    outline-offset: 2px;
}

.store-product-image {
    width: 100%;
    height: 108px;
    border-radius: 14px;
    background: var(--tarjeta-imagen-vacia);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    color: var(--tinta-tenue);
    font-size: 11px;
    font-weight: 700;
}

.store-product-image {
    position: relative;
}

/* Con foto, el hueco va blanco. El crema es para el cartel de "Sin imagen":
 * ahí sirve, porque marca que falta algo. Debajo de una foto que ya viene
 * sobre blanco no marca nada — deja un marco color hueso alrededor del
 * recorte y se nota justo lo que se quería disimular. */
.store-product-image:has(img) {
    background: #ffffff;
}

/* `contain` y no `cover`, que es lo que decía el diseño heredado.
 *
 * El cambio no es de gusto: cambió lo que hay dentro de la imagen. `cover`
 * llena el hueco recortando lo que sobra, y funciona cuando la foto es una
 * escena que se puede recortar por donde sea. Aquí toda foto pasa por el
 * emparejado y sale como un producto centrado sobre blanco: recortar eso es
 * cortarle la tapa a la lata y el tapón a la botella, que es exactamente lo
 * que se veía.
 *
 * `contain` deja el producto completo, y el sobrante no se nota porque el
 * fondo de la foto ya es blanco: se funde con la tarjeta en vez de dejar
 * las franjas grises que suele dejar `contain`.
 */
.store-product-image img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.store-price-status-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 6px;
}

.store-product-price {
    font-size: 16px;
    font-weight: 800;
    color: var(--tinta);
    font-variant-numeric: tabular-nums;
}

/* Precio con beneficio por pago inmediato: recuadro VERDE a la derecha del
   precio normal. Fue ámbar («dorado») hasta el 2026-10-15; el dueño lo
   cambió al ver el verde de Billetin: «cambiaremos el dorado por verde
   mejor en general». El mismo verde en la tienda y en el POS.
   La letra toma el papel del tema: blanca sobre el verde oscuro del tema
   claro, y oscura sobre el verde claro del tema oscuro de la tienda. */
.store-product-price-beneficio {
    padding: 2px 8px;
    border-radius: 8px;
    background: var(--ok);
    color: var(--papel-alto);
    font-size: 13px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Vive dentro de la imagen, abajo a la derecha, chiquita.
   El original medía 9px y se marcó como ilegible; queda en 10px, que es lo
   más chico que sigue leyéndose de un vistazo, con el peso alto y el fondo
   opaco haciendo el resto del trabajo. */
/* De pie y pegada al canto derecho, dentro de la imagen.
 *
 * Acostada abajo tapaba el producto justo donde se le mira la etiqueta, y el
 * dueño lo dijo: «tapa el producto». Girada, la palabra corre por el borde y
 * el centro de la foto queda libre — que es lo único que la tarjeta tiene
 * para vender. */
.store-product-status {
    position: absolute;
    right: 4px;
    top: 50%;
    transform: translateY(-50%) rotate(180deg);
    writing-mode: vertical-rl;
    z-index: 1;
    font-size: 10px;
    font-weight: 800;
    /* Sin mayúsculas ni tracking: "DISPONIBLE" así ocupaba casi todo el
       ancho de la imagen y parecía una banda, no una insignia. En minúscula
       la misma palabra mide la mitad. */
    padding: 6px 2px;
    border-radius: 999px;
    white-space: nowrap;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12);
    /* Que nunca sea más alta que la foto: con «no disponible» en una tarjeta
       de móvil se salía por arriba y por abajo. */
    max-height: calc(100% - 12px);
    overflow: hidden;
}

/* La de EXISTENCIAS va horizontal, al centro y pegada abajo dentro de la
   miniatura. Lo pidió así el dueño y tiene razón por dos motivos.

   El de forma: vertical funcionaba para «Disponible» de la tienda —una
   palabra larga corriendo por el costado— pero un número puesto de lado no
   se lee, se descifra.

   Y el de fondo: en la lista del POS la insignia se montaba encima del
   cartel de «Sin foto» y se leían las dos cosas revueltas. Abajo y al
   centro no estorba, porque ahí la miniatura no tiene nada que decir.

   No agranda el chip: va en posición absoluta, así que no ocupa lugar. */
/* ---------- El hueco de «sin foto» ----------
 *
 * Estas reglas estaban SOLO en store/store.css, y ahí solo las veía la
 * tienda en línea. El POS y la Trastienda cargan esta hoja pero no aquella,
 * así que en sus listas el dibujo salía sin tamaño y el rótulo sin formato:
 * la miniatura de un producto sin foto quedaba a merced de lo que el
 * navegador decidiera. Es una pieza de la tarjeta, y la tarjeta vive aquí.
 *
 * La tienda le sigue pintando encima su degradado —eso sí es suyo— porque
 * carga esta hoja antes que la suya.
 */
.store-product-image--vacia {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    color: var(--tinta-tenue);
}

.store-product-image--vacia svg {
    width: 26px;
    height: 26px;
    opacity: 0.55;
}

.store-product-image--vacia > span:not(.store-product-status) {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

/* Y el rótulo «Sin foto» se queda en el dibujo, sin la palabra.
 *
 * Mover el número abajo no bastaba: ahí es donde vivía el texto, y las dos
 * cosas se leían revueltas —«Si 0 to»—. Se quita la palabra y no el número
 * porque en la Trastienda y en el POS lo que se mira de reojo es cuántos
 * hay; que un producto no tenga foto ya lo dice la canasta vacía, sin
 * gastar el único renglón que cabe.
 *
 * En la tienda en línea el texto se queda: ahí el cliente sí está mirando
 * fotos, y un dibujo sin explicación parece una imagen rota.
 *
 * El `:not()` no es decoración: la insignia de existencias es OTRO span
 * dentro del mismo hueco, y sin excluirla esta regla la escondía junto con
 * el rótulo — desaparecía justo el número que se quería mostrar.
 */
.store-product-card--admin .store-product-image--vacia > span:not(.store-product-status) {
    display: none;
}

/* Y la canasta sube lo que ocupa la insignia. Centrada del todo le rozaba
   el borde de arriba, y dos dibujos que se tocan se leen como uno solo mal
   hecho. */
.store-product-card--admin .store-product-image--vacia > svg {
    transform: translateY(-6px);
}

.store-product-card--admin .store-product-status {
    writing-mode: horizontal-tb;
    top: auto;
    right: auto;
    bottom: 3px;
    left: 50%;
    transform: translateX(-50%);
    padding: 1px 6px;
    font-size: 10px;
    line-height: 1.5;
    max-width: calc(100% - 8px);
    max-height: none;
    text-overflow: ellipsis;
}

.store-product-status.available {
    background: var(--ok-fondo);
    color: var(--ok);
}

.store-product-status.unavailable {
    background: var(--peligro-fondo);
    color: var(--peligro);
}

.store-product-status.alerta {
    background: #fdf1e0;
    color: var(--alerta);
}

.store-product-name {
    margin: 0;
    font-size: 13.5px;
    line-height: 1.28;
    /* Corrección obligatoria: font-weight 750 solo funciona con fuente
       variable. IBM Plex Sans aquí es estática, así que se queda en 700. */
    font-weight: 700;
    color: var(--tinta);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    min-height: 34px;
}

.store-product-description {
    margin: 0;
    font-size: 11.5px;
    line-height: 1.3;
    color: var(--tinta-suave);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    min-height: 28px;
}

.store-product-controls {
    margin-top: auto;
}

.store-add-button {
    width: 100%;
    /* El original medía 38px. Se subió a 44 por el mínimo táctil y el dueño
       lo fue pidiendo más delgado hasta aquí: 36 se ve proporcionado con el
       resto de la tarjeta y sigue siendo cómodo de atinar, porque es un
       botón ancho — lo difícil de tocar es lo angosto, no lo bajito. Los
       botones que mueven dinero en el POS siguen en 44+. */
    min-height: 36px;
    border-radius: 12px;
    border: none;
    background: linear-gradient(135deg, var(--marca), var(--marca-hondo));
    color: #fff;
    font-size: 13px;
    font-weight: 800;
    cursor: pointer;
    transition: transform 0.1s ease, opacity 0.1s ease;
}

.store-add-button:active {
    transform: scale(0.97);
}

.store-add-button:focus-visible,
.store-qty-btn:focus-visible {
    outline: 2px solid var(--accion);
    outline-offset: 2px;
}

.store-add-button:disabled {
    background: var(--papel-hondo);
    color: var(--tinta-tenue);
    cursor: not-allowed;
}

/* El control de cantidad ocupa el lugar del botón y se queda: el cliente
   sigue viendo cuánto lleva sin abrir el carrito. Más chico y con aire
   entre las piezas, para que no se vea como un bloque. */
.store-qty-control {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 6px;
    min-height: 36px;
    border-radius: 999px;
    background: var(--papel-hondo);
    padding: 3px;
}

.store-qty-control[hidden] {
    display: none;
}

.store-qty-btn {
    /* El original medía 30px. Estos 34 quedan por encima de eso y por
       debajo del botón entero, que es lo que el dueño buscaba: que el
       control no se vea más pesado que la tarjeta. */
    width: 34px;
    height: 30px;
    border-radius: 999px;
    border: none;
    background: var(--papel-alto);
    color: var(--tinta);
    font-size: 16px;
    font-weight: 800;
    cursor: pointer;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
}

.store-qty-value {
    font-size: 14px;
    font-weight: 800;
    color: var(--tinta);
    font-variant-numeric: tabular-nums;
}

@media (prefers-reduced-motion: reduce) {
    .store-add-button {
        transition: none;
    }
    .store-add-button:active {
        transform: none;
    }
}

/* ---------- Fila horizontal (secciones destacadas) ---------- */

.store-row {
    display: flex;
    gap: 12px;
    overflow-x: auto;
    padding-bottom: 4px;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
}

.store-row::-webkit-scrollbar {
    display: none;
}

/* ---------- Corrección obligatoria: variante en cuadrícula para catálogo
   completo y resultados de búsqueda. Misma tarjeta, sin desperdiciar
   espacio en escritorio. ---------- */

/* La columna se fija en el ancho real de la tarjeta, no con `1fr`.
 *
 * Con `minmax(172px, 1fr)` la tarjeta se estiraba para rellenar el renglón,
 * así que la misma tienda cambiaba de tamaño al pasar de la portada —donde
 * las filas horizontales sí respetan los 172px— a un departamento. Cambiar
 * de sección no debe cambiar el tamaño de las cosas.
 *
 * Es el mismo arreglo que ya traía la pantalla de venta más abajo, por el
 * mismo motivo. CLAUDE.md sección 11 lo pedía desde el principio: la
 * cuadrícula conserva **exactamente la misma tarjeta**.
 */
.store-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, 172px);
    justify-content: start;
    gap: 12px;
}

.store-grid .store-product-card {
    width: auto;
}

@media (max-width: 640px) {
    .store-product-card {
        flex-basis: 140px;
        width: 140px;
    }

    /* Dos tarjetas y media a la vista. La media tarjeta es el mensaje: sin
       ella la fila parece que se acaba ahí y nadie la desliza. Se mide
       contra el ancho real de la fila, no con un número fijo, para que
       valga igual en un teléfono de 320 que en uno de 430. */
    .store-row .store-product-card {
        flex: 0 0 calc(40% - 7px);
        width: auto;
        /* Sin esto no sirve de nada: un elemento flex trae min-width:auto y
           se niega a bajar del ancho de su propio contenido, así que la
           base de 40% se la pasaba por alto. */
        min-width: 0;
    }

    /* Con la tarjeta angosta, el precio de beneficio se va al renglón de
       abajo en vez de salirse por la derecha. */
    .store-row .store-price-status-row {
        flex-wrap: wrap;
        gap: 4px;
    }

    .store-row .store-product-price-beneficio {
        font-size: 12px;
        padding: 1px 7px;
    }
    .store-product-image {
        height: 92px;
    }
    /* En el teléfono, centrada: con dos tarjetas de 148 sobra un poco de
       renglón, y repartido a los lados se lee como margen. Todo del lado
       derecho se lee como que algo se rompió. */
    .store-grid {
        grid-template-columns: repeat(auto-fill, 148px);
        justify-content: center;
    }
}

/* ---------- Variante --admin: existencias + estado web, botón Editar,
   color de acción azul (nunca rojo en Admin/POS). ---------- */

.store-product-card--admin .store-add-button,
.store-product-card--pos .store-add-button {
    background: var(--accion);
}

.store-product-card--admin .store-product-status.oculto {
    background: var(--papel-hondo);
    color: var(--tinta-suave);
}

/* ---------- Variante --pos: más compacta, sin descripción, precio más
   grande. Se usa en la búsqueda y el catálogo del POS (fase 3). ----------

   El ancho aquí SÍ se reduce respecto a los 172px heredados, y es
   deliberado: en la caja se comparan varias opciones de un vistazo y la
   tarjeta grande obligaba a desplazarse por tres o cuatro productos. La
   tarjeta heredada NO se toca — conserva su tamaño en la tienda en línea,
   que es donde el diseño original importa (CLAUDE.md sección 11). Aquí es
   otra densidad de la misma tarjeta, que es justo lo que esa sección
   permite con sus modificadores. */

.store-product-card--pos {
    flex-basis: 132px;
    width: 132px;
    padding: 8px;
    position: relative;
}

.store-product-card--pos .store-product-image {
    height: 76px;
}

.store-product-card--pos .store-product-description {
    display: none;
}

.store-product-card--pos .store-product-price {
    font-size: 15px;
}

.store-product-card--pos .store-product-name {
    font-size: 12.5px;
}

/* El botón conserva sus 44px de área táctil: achicar la tarjeta no puede
   costar la posibilidad de darle con el dedo (sección 11). */
.store-product-card--pos .store-add-button {
    font-size: 13px;
}

/* La cuadrícula del POS usa columnas de ancho FIJO, no 1fr: con 1fr las
   columnas se estiran para repartirse el sobrante y la tarjeta acaba casi
   del tamaño original (la regla .store-grid .store-product-card{width:auto}
   hace que la tarjeta tome el ancho de su columna). Fijando la columna, la
   tarjeta mide de verdad lo que debe medir y caben más por renglón. */
.tm-venta .store-grid {
    grid-template-columns: repeat(auto-fill, 138px);
    justify-content: start;
}

/* La tarjeta entera se toca para agregar (ver venta.js): el cursor lo
   anuncia y el realce confirma que es un objetivo, no un adorno. */
.store-product-card--pos {
    cursor: pointer;
    transition: background-color 0.12s ease;
}

.store-product-card--pos:hover {
    background: var(--accion-tenue);
}

/* En pantalla chica las tarjetas ocupan todo el ancho en dos columnas, en
   vez de quedarse en 138px dejando huecos: en el celular cada pixel
   desperdiciado son productos que no ves sin desplazarte. */
@media (max-width: 767px) {
    /* minmax(0, 1fr) y no 1fr a secas: '1fr' equivale a minmax(auto, 1fr),
       así que un nombre largo empuja su columna y las dos quedan
       desiguales. Con mínimo 0 las columnas miden exactamente lo mismo y el
       nombre se acomoda dentro. */
    .tm-venta .store-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .tm-venta .store-product-card--pos .store-product-name {
        overflow-wrap: anywhere;
    }

    .tm-venta .store-product-card--pos .store-product-image {
        height: 96px;
    }

    .tm-venta .store-product-card--pos .store-product-price {
        font-size: 17px;
    }

    .tm-venta .store-product-card--pos .store-product-name {
        font-size: 13.5px;
    }
}

@media (prefers-reduced-motion: reduce) {
    .store-product-card--pos {
        transition: none;
    }
}

/* La tarjeta del Admin lleva los mismos botones que la tabla, porque en el
   teléfono la tabla no se ve: la tarjeta ES la tabla ahí. Van en fila y
   ocupan el sitio donde la variante de tienda pone "Agregar". */
.store-product-controls--admin {
    display: flex;
    justify-content: center;
}

.store-product-controls--admin .tm-acciones-producto {
    display: flex;
    gap: 8px;
    justify-content: center;
    width: 100%;
}

.store-product-controls--admin .tm-fila-boton {
    flex: 1;
    min-height: 40px;
}


/* ---------- El corazón de favorito ----------
 *
 * Arriba a la izquierda dentro de la foto: abajo a la derecha ya vive la
 * insignia de disponible, y en diagonal no se estorban ni en la tarjeta más
 * angosta.
 *
 * Relleno cuando está puesto y solo contorno cuando no, además del color:
 * el rojo contra el gris no lo distingue todo el mundo, y la forma sí.
 */
/* En la esquina de la TARJETA, no de la foto: así queda medio fuera de la
   imagen —«no importa que se salga de la imagen mientras no salga de la
   tarjeta»— y de paso escapa del recorte del contenedor de la foto, que se
   lo comía. Con los 10px de relleno de la tarjeta, estos 2px lo dejan bien
   metido en la esquina sin tocar el borde. */
.store-product-corazon {
    position: absolute;
    top: 2px;
    left: 2px;
    z-index: 2;
    width: 34px;
    height: 34px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.82);
    color: var(--tinta-tenue);
    cursor: pointer;
    /* El toque se siente en el acto y sin esperar al servidor. */
    transition: transform 120ms ease, color 120ms ease;
}

.store-product-corazon svg {
    width: 19px;
    height: 19px;
    fill: none;
}

.store-product-corazon--puesto {
    color: var(--marca);
}

/* Relleno SIN borde. Con los dos a la vez, el corazón marcado crecía casi
   dos píxeles por lado y en una fila de tarjetas se veían de dos tamaños
   —«solo quiero 1 tamaño de corazón»—. Sin el borde, el rojo mide
   exactamente lo mismo que el gris. */
.store-product-corazon--puesto svg {
    fill: currentColor;
}

.store-product-corazon--puesto svg path {
    stroke: none;
}

.store-product-corazon:active {
    transform: scale(0.88);
}

.store-product-corazon:focus-visible {
    outline: 2px solid var(--marca);
    outline-offset: 1px;
}

@media (prefers-reduced-motion: reduce) {
    .store-product-corazon {
        transition: none;
    }
}

/* A granel el precio es por kilo, y se dice. */
.store-product-price-unidad {
  margin-left: 1px;
  font-size: 0.78em;
  font-weight: 600;
  color: var(--tinta-suave);
}

/* El precio con descuento de Billetin (store/billetin.js).
 *
 * Viaja escondido en cada tarjeta de la tienda que tiene dos precios, y sale
 * cuando el cliente escoge pagar en efectivo o transferencia: en verde a la
 * izquierda, y el de etiqueta tachado y chico al lado. El dueño escogió el
 * verde en maqueta (2026-10-15).
 *
 * Todo cabe en el mismo renglón y a la misma altura que el precio de
 * siempre: la tarjeta heredada no cambia de tamaño (CLAUDE.md §11). Si el
 * tachado no cabe junto al que paga (un precio de tres cifras en la fila
 * angosta del teléfono), baja a un segundo renglón que queda fuera de la
 * vista: mejor no enseñarlo que enseñar «$3…» recortado. El que paga nunca
 * se va. Va al final del archivo para ganarle a las reglas de arriba. */
.store-product-price-descuento {
    display: none;
}

.tm-paga-inmediato .store-price-status-row--descuento {
    justify-content: flex-start;
    align-items: baseline;
    flex-wrap: wrap;
    column-gap: 6px;
    row-gap: 0;
    height: 22px;
    overflow: hidden;
}

.tm-paga-inmediato .store-price-status-row--descuento .store-product-price-descuento {
    display: inline;
    order: -1;
    flex-shrink: 0;
    font-size: 16px;
    font-weight: 800;
    color: var(--ok);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.tm-paga-inmediato .store-price-status-row--descuento .store-product-price {
    font-size: 12px;
    font-weight: 600;
    color: var(--tinta-suave);
    text-decoration: line-through;
    white-space: nowrap;
}

.tm-paga-inmediato .store-price-status-row--descuento .store-product-price .store-product-price-unidad,
.tm-paga-inmediato .store-price-status-row--descuento .store-product-price-beneficio {
    display: none;
}

/* En la fila angosta del teléfono (dos tarjetas y media) el renglón mide
   83 px a 360 de ancho: «$25.00» y «$27.00» a 16 y 12 px piden 97. Un
   punto menos en cada uno y juntos, y los precios de dos cifras caben. */
@media (max-width: 640px) {
    .tm-paga-inmediato .store-row .store-price-status-row--descuento {
        column-gap: 3px;
    }

    .tm-paga-inmediato .store-row .store-price-status-row--descuento .store-product-price-descuento {
        font-size: 14px;
        letter-spacing: -0.2px;
    }

    .tm-paga-inmediato .store-row .store-price-status-row--descuento .store-product-price {
        font-size: 11px;
        letter-spacing: -0.2px;
    }
}
