/* ============================================================
   CHELCRIS - Hoja de estilos
   ------------------------------------------------------------
   Misma estructura de clases que DIOSACA / IBECO / FERREPLASTIC
   (medidas, layout, chips, tarjetas): app.js espera esos nombres.
   Lo que cambia es la piel.

   Identidad: el verde #22B475 y el cian #29ABE2 del logo, con el
   degradado verde->cian que traza el carrito del isotipo.

   --primary-color y --secondary-color llegan desde la tabla
   `configuracion` vía index.php; aquí solo van los respaldos. Los
   tonos derivados (--brand-grad, --tint...) se calculan con
   color-mix a partir de ellos, así que si el cliente cambia el
   color de marca desde phpMyAdmin, TODA la piel lo sigue sin
   tocar este archivo.

   El texto sobre el color de marca es --on-primary, que index.php
   calcula por luminancia (fórmula WCAG). Sobre el verde da blanco;
   si mañana ponen un color claro, da negro solo.
   ============================================================ */

:root {
    color-scheme: light;

    --primary-color: #22B475;   /* verde del logo */
    --secondary-color: #29ABE2; /* cian del logo */
    --on-primary: #ffffff;      /* index.php lo ajusta según el color */
    --on-secondary: #ffffff;

    /* Los botones y acentos van en verde sólido. El cian queda para detalles
       (precio, enlaces): dos colores planos se ven más limpios que un
       degradado repetido en cada botón. --brand-grad se conserva como alias
       para no tocar todas las reglas, pero ya no es un degradado. */
    --brand-grad: var(--primary-color);

    /* Derivados del color de marca. color-mix evita tener que escribir
       a mano un tono por cada estado. */
    --tint: color-mix(in srgb, var(--primary-color) 8%, #ffffff);
    --tint-strong: color-mix(in srgb, var(--primary-color) 16%, #ffffff);
    --ring: color-mix(in srgb, var(--primary-color) 35%, transparent);

    --bg-color: #f8f9fa;        /* el mismo gris casi blanco de FERREPLASTIC */
    --text-color: #2B2A29;      /* la tinta del logo */
    --muted: #6C757D;
    --card-bg: #ffffff;
    --border: #E6EBEE;
    --ok: #00AD13;
    --danger: #FF3838;

    /* Sombras suaves y en dos capas: el borde duro de la plantilla vieja
       se veía plano al lado de tarjetas redondeadas. */
    --shadow: 0 1px 2px rgba(16, 38, 51, .05), 0 6px 16px -6px rgba(16, 38, 51, .12);
    --shadow-lg: 0 2px 6px rgba(16, 38, 51, .06), 0 18px 40px -18px rgba(16, 38, 51, .28);

    --radius: 16px;
    --radius-sm: 10px;
    --sidebar-w: 260px;
    --font-family: 'Poppins', 'Helvetica Neue', Arial, sans-serif;
}

* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

body {
    font-family: var(--font-family);
    background-color: var(--bg-color);
    color: var(--text-color);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

.hidden {
    display: none !important;
}

/* Mientras el cajón de filtros está abierto en móvil, el fondo no se mueve */
/* Solo en body: en <html> rompería el header sticky. El bloqueo real de la
   rueda y el touch lo hace bloquearScrollFondo() en app.js. */
body.no-scroll {
    overflow: hidden;
}

/* ---------------- Header ---------------- */

/* Header sticky, blanco sólido, como en FERREPLASTIC. */
header {
    background-color: var(--card-bg);
    padding: .85rem 2rem;
    position: sticky;
    top: 0;
    z-index: 100;
    border-bottom: 1px solid var(--border);
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
}

.header-left {
    display: flex;
    align-items: center;
    gap: .6rem;
    flex-shrink: 0;
    order: 1;
}

/* Botón que abre los filtros. Solo se ve en móvil: en escritorio el panel
   está siempre a la vista y el botón sobraría. */
.filters-toggle {
    display: none;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 0;
    border: 1px solid #e6e6e6;
    border-radius: 10px;
    background: var(--card-bg);
    color: var(--secondary-color);
    cursor: pointer;
    transition: background .2s, border-color .2s, transform .2s;
}

.filters-toggle:hover,
.filters-toggle[aria-expanded="true"] {
    background: var(--primary-color);
    border-color: var(--primary-color);
    color: var(--on-primary);
}

.filters-toggle:active {
    transform: scale(.94);
}

/* ---------------- Marca del centro del header ---------------- */

/* Va entre el logo y el botón de Compartir. Ocupa el espacio libre y centra
   su contenido, así que no hace falta tocar el `order` de los otros bloques:
   .header-left es 1, esto también es 1 y el DOM decide, y el buscador sigue
   cayendo a la segunda fila con su order 3.

   flex-shrink es lo que salva el móvil: en 360px el bloque se encoge en vez de
   empujar el carrito fuera de la pantalla. */
.header-brand {
    display: flex;
    align-items: center;
    justify-content: center;
    order: 1;
    /* basis 0, no auto: con basis auto el bloque reclama el ancho de sus
       imágenes y en 360px el flex-wrap lo mandaba a una fila propia, 106px
       más de header sticky. Con basis 0 nunca pide más de lo que sobra y las
       imágenes encogen dentro. */
    flex: 1 1 0;
    min-width: 0;
}

/* Ahora es texto, no imagen: CHELCRIS no tiene un "catálogo en línea.png" y
   tampoco hace falta. El degradado de marca sobre el texto repite el del
   isotipo sin costar un solo byte de descarga.

   white-space: nowrap + text-overflow evita que en 360px se parta en dos
   líneas y le robe alto al header sticky. */
.brand-texto {
    display: block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 700;
    font-size: .95rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--primary-color);
}

.header-right {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-shrink: 0;
    order: 2;
    margin-left: auto;
}

.logo-container {
    display: flex;
    align-items: center;
    gap: 10px;
    font-weight: 700;
    font-size: 1.2rem;
}

.logo-badge {
    display: flex;
    align-items: center;
}

.logo-img {
    height: 44px;
    width: auto;
    display: block;
}

.logo-text {
    white-space: nowrap;
}

/* Botón secundario del header: contorno suave. El degradado de marca se
   reserva para las acciones de compra, que son las que tienen que saltar. */
.header-btn {
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .55rem 1rem;
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 999px;
    transition: background .2s, border-color .2s, transform .2s;
    font-size: .85rem;
    font-family: inherit;
    font-weight: 600;
    color: var(--text-color);
    text-decoration: none;
    white-space: nowrap;
}

.header-btn:hover {
    background: var(--tint);
    border-color: color-mix(in srgb, var(--primary-color) 40%, var(--border));
    transform: translateY(-1px);
}

.header-btn svg {
    flex-shrink: 0;
    stroke: currentColor;
}

.header-btn-text {
    display: inline;
}

.cart-icon {
    position: relative;
    cursor: pointer;
    padding: 8px;
    color: var(--secondary-color);
    transition: transform .2s ease;
}

.cart-count {
    position: absolute;
    top: 0;
    right: 0;
    background-color: var(--primary-color);
    color: var(--on-primary);
    font-size: .75rem;
    font-weight: 700;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    display: flex;
    justify-content: center;
    align-items: center;
    border: 1px solid var(--secondary-color);
}

.search-container {
    flex: 1 1 100%;
    max-width: 100%;
    margin: 0;
    order: 3;
    position: relative;
}

.search-input {
    width: 100%;
    padding: .8rem 1rem;
    border: 1px solid var(--border);
    border-radius: 20px;
    font-size: .95rem;
    font-family: inherit;
    outline: 0;
    transition: all .3s;
}

.search-input:focus {
    border-color: var(--secondary-color);
    box-shadow: 0 0 0 3px rgba(252, 208, 0, .45);
}

/* ---------------- Layout del catálogo ---------------- */

/* El panel de filtros es fijo y sale del flujo, así que aquí no hace falta
   flex: la columna de productos simplemente se corre a la derecha con un
   margen del ancho del panel. Sin tope de ancho: el catálogo aprovecha toda
   la pantalla, que es donde mejor se acomodan las tarjetas. */
.catalog-layout {
    display: block;
}

.catalog-main {
    margin-left: var(--sidebar-w);
    padding: 1.5rem 1.75rem 3rem;
    min-width: 0;
}

/* ---------------- Panel de filtros ---------------- */

/* Panel fijo: se queda quieto y solo scrollean los productos. Arranca justo
   debajo del header (--header-h la calcula app.js, porque el header es sticky
   y cambia de alto según el ancho) y llega hasta abajo de la pantalla. Si la
   lista de categorías es larga, el panel scrollea por dentro. */
.filters-sidebar {
    position: fixed;
    top: var(--header-h, 140px);
    left: 0;
    bottom: 0;
    width: var(--sidebar-w);
    z-index: 90;   /* debajo del header, que va en 100 */

    background: var(--card-bg);
    border-right: 1px solid var(--border);
    padding: 1.35rem 1.1rem 2rem;

    overflow-y: auto;
    overscroll-behavior: contain;   /* al llegar al final no arrastra la página */
    scrollbar-width: thin;
    scrollbar-color: #d9d9d9 transparent;
}

.filters-sidebar::-webkit-scrollbar {
    width: 6px;
}

.filters-sidebar::-webkit-scrollbar-thumb {
    background: #d9d9d9;
    border-radius: 3px;
}

/* Encabezado con la X: solo hace falta en el cajón de móvil, donde se queda
   fijo arriba mientras la lista de categorías scrollea debajo. */
.filters-head {
    display: none;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    border-bottom: 1px solid var(--border);
}

.filters-head h3 {
    font-size: 1.05rem;
}

/* Botón de cerrar del cajón: cuadrado de 40px para que se pueda tocar con el
   pulgar sin apuntar. El "&times;" suelto era un blanco muy chico. */
.filters-head .icon-close {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    margin-right: -.35rem;   /* alinea el icono con el borde, no la caja */
    border-radius: 50%;
    font-size: 1.6rem;
    transition: background .2s;
}

.filters-head .icon-close:active {
    background: #f0f0ee;
}

.filter-block + .filter-block {
    margin-top: 1.15rem;
    padding-top: 1.15rem;
    border-top: 1px solid #f0f0f0;
}

.filter-title {
    display: flex;
    align-items: center;
    gap: .4rem;
    margin-bottom: .75rem;
    padding-left: .1rem;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: #9a9a9a;
}

.filter-title svg {
    flex-shrink: 0;
    opacity: .55;
}

/* ---------------- Filtro de precio ---------------- */

.price-filter {
    display: flex;
    gap: .5rem;
}

.price-input {
    width: 100%;
    min-width: 0;
    padding: .5rem .6rem;
    border: 1px solid #e0e0e0;
    border-radius: 8px;
    font-family: inherit;
    font-size: .85rem;
    color: var(--text-color);
    outline: none;
    transition: border-color .2s, box-shadow .2s;
    appearance: textfield;
    -moz-appearance: textfield;
}

.price-input::-webkit-inner-spin-button,
.price-input::-webkit-outer-spin-button {
    -webkit-appearance: none;
    appearance: none;
    margin: 0;
}

.price-input:focus {
    border-color: var(--primary-color);
    box-shadow: 0 0 0 3px rgba(252, 208, 0, .35);
}

.price-clear {
    margin-top: .55rem;
    padding: 0;
    background: none;
    border: none;
    font-family: inherit;
    font-size: .78rem;
    font-weight: 600;
    color: #888;
    cursor: pointer;
    text-decoration: underline;
}

.price-clear:hover {
    color: var(--secondary-color);
}

/* ---------------- Categorías (lista vertical) ---------------- */

/* La lista no scrollea por su cuenta: el que scrollea es el panel entero.
   Con dos scrolls anidados la rueda del mouse se traba al pasar por encima
   de las categorías. */
.categories-nav {
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.category-btn {
    display: flex;
    align-items: center;
    gap: .5rem;
    width: 100%;
    padding: .58rem .7rem;
    background: transparent;
    border: none;
    border-radius: 9px;
    cursor: pointer;
    transition: background .18s ease, color .18s ease, transform .18s ease;
    font-size: .8rem;
    font-family: inherit;
    font-weight: 600;
    letter-spacing: .02em;
    text-transform: uppercase;
    text-align: left;
    line-height: 1.3;
    color: #5b6068;
}

.category-btn:hover {
    background: #f4f4f2;
    color: var(--secondary-color);
    transform: translateX(3px);   /* se corre un pelo: da idea de "esto se toca" */
}

.category-btn.active {
    background-color: var(--primary-color);
    color: var(--on-primary);
    box-shadow: 0 2px 8px rgba(0, 0, 0, .12);
}

.category-btn.active:hover {
    padding-left: .7rem;   /* el activo no se mueve */
}

.category-btn.active svg {
    fill: currentColor;
}

/* Favoritos va en su propio bloque, arriba de la lista de categorías: es un
   filtro aparte, no una categoría más del ERP. */
.category-fav {
    background: #faf9f7;
    border: 1px solid #eeece7;
}

.category-fav svg {
    flex-shrink: 0;
    color: #e0245e;
}

.category-fav.active {
    border-color: var(--primary-color);
}

.category-fav.active svg {
    color: inherit;
}

.category-count {
    margin-left: auto;
    min-width: 20px;
    padding: 0 .35rem;
    border-radius: 999px;
    background: rgba(0, 0, 0, .12);
    font-size: .7rem;
    font-weight: 700;
    text-align: center;
}

/* ---------------- Controles de vista ---------------- */

.view-controls {
    padding: 0 0 1.25rem;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    background: var(--bg-color);
}

.sort-selector {
    display: flex;
    align-items: center;
    gap: .5rem;
    background: var(--card-bg);
    padding: .5rem .75rem;
    border-radius: 8px;
    box-shadow: var(--shadow);
    border: 1px solid var(--border);
    transition: all .3s;
}

.sort-icon {
    flex-shrink: 0;
    color: var(--text-color);
    stroke: var(--text-color);
}

.sort-dropdown {
    border: none;
    background: transparent;
    font-size: .9rem;
    font-family: var(--font-family);
    color: var(--text-color);
    cursor: pointer;
    outline: none;
    padding: 0 1.5rem 0 0;
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23333' d='M6 9L1 4h10z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right center;
    min-width: 180px;
}

.sort-dropdown:hover {
    color: var(--secondary-color);
}

.sort-selector:hover {
    border-color: var(--primary-color);
}

.sort-selector:hover .sort-icon {
    stroke: var(--secondary-color);
}

.view-toggle {
    display: flex;
    gap: .5rem;
    background: var(--card-bg);
    padding: .25rem;
    border-radius: 8px;
    box-shadow: var(--shadow);
}

.view-toggle-btn {
    padding: .5rem;
    background: 0 0;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    transition: all .2s;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-color);
}

.view-toggle-btn:hover {
    background: rgba(0, 0, 0, .05);
}

.view-toggle-btn.active {
    background: var(--primary-color);
    color: var(--on-primary);
}

.view-toggle-btn.active svg {
    stroke: var(--on-primary);
}

/* ---------------- Grid de productos ---------------- */

/* Con el panel a la izquierda y el catálogo a todo el ancho entran más
   artículos por fila sin achicar la tarjeta: 235px de mínimo y el resto lo
   reparte la grilla. El padding lo pone .catalog-main. */
.products-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(235px, 1fr));
    gap: 1.5rem;
}

.products-grid.grid-2 {
    grid-template-columns: repeat(auto-fill, minmax(380px, 1fr));
    gap: 2rem;
}

.grid-message {
    grid-column: 1 / -1;
    text-align: center;
    padding: 2rem;
}

.grid-message.error {
    color: #f45c43;
}

.grid-message.muted {
    color: #666;
    font-size: .9rem;
}

.product-card {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
    box-shadow: var(--shadow);
    transition: transform .25s ease, box-shadow .25s ease, border-color .25s ease;
    cursor: pointer;
    display: flex;
    flex-direction: column;
}

.product-card:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-lg);
    border-color: color-mix(in srgb, var(--primary-color) 35%, var(--border));
}

.product-image-wrap {
    display: block;
    position: relative;   /* ancla el corazón de favoritos */
}

/* ---------------- Favoritos ---------------- */

.fav-toggle {
    position: absolute;
    top: .55rem;
    right: .55rem;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: rgba(255, 255, 255, .92);
    color: #9aa0a6;
    cursor: pointer;
    box-shadow: 0 1px 4px rgba(0, 0, 0, .14);
    transition: color .2s, transform .15s, background .2s;
}

.fav-toggle svg {
    fill: none;
    transition: fill .2s;
}

.fav-toggle:hover {
    color: #e0245e;
    transform: scale(1.1);
}

.fav-toggle.is-fav {
    color: #e0245e;
}

.fav-toggle.is-fav svg {
    fill: currentColor;
}

/* Latido corto al marcar o desmarcar */
.fav-toggle.pop {
    animation: fav-pop .3s ease;
}

@keyframes fav-pop {
    0%   { transform: scale(1); }
    45%  { transform: scale(1.32); }
    100% { transform: scale(1); }
}

.empty-favs {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .4rem;
    color: #8a8a8a;
}

.empty-favs svg {
    color: #d5d5d5;
    margin-bottom: .4rem;
}

/* aspect-ratio en vez de height fija: la tarjeta se adapta al ancho de la
   columna y las fotos del ERP, que vienen de tamaños distintos, quedan todas
   en el mismo marco sin recortarse (object-fit: contain). */
.product-image {
    width: 100%;
    aspect-ratio: 1 / 1;
    height: auto;
    object-fit: contain;
    background-color: #fff;
    padding: 1rem;
    display: block;
    transition: transform .3s ease;
}



.product-card:hover .product-image {
    transform: scale(1.04);
}

/* Respaldo cuando la imagen del producto no carga: conserva el
   mismo alto y el gris de la tarjeta, así nada se descuadra. */
.product-image.img-placeholder {
    object-fit: contain;
    background-color: #f5f5f5;
    padding: 1rem;
}

.products-grid.grid-2 .product-image {
    height: 300px;
    padding: 1.5rem;
}

.product-info {
    padding: 1rem;
    flex-grow: 1;
    display: flex;
    flex-direction: column;
}

.product-code {
    font-size: .75rem;
    color: var(--muted);
    margin-bottom: .25rem;
    font-weight: 500;
}

.product-title {
    font-weight: 600;
    margin-bottom: .5rem;
}

.product-meta {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: .8rem;
    margin-bottom: .5rem;
    gap: .5rem;
}

/* Chips planos: sin degradados, en tonos suaves */
.product-unit,
.product-stock {
    padding: .15rem .5rem;
    border-radius: 999px;
    /* "12 DISPONIBLES" no se debe partir en dos líneas dentro del chip */
    white-space: nowrap;
    font-weight: 600;
    font-size: .68rem;
    letter-spacing: .03em;
    text-transform: uppercase;
}

.product-unit {
    background: #f0f0ee;
    color: #6b7280;
}

.product-stock.in-stock {
    background: rgba(4, 120, 87, .12);
    color: #047857;
}

.product-stock.out-of-stock {
    background: #fdecec;
    color: #b3261e;
}

/* El precio va en la tinta del texto, no en el color de marca: sobre blanco
   el verde compite con los chips y el botón de comprar, y el precio tiene que
   leerse de un vistazo. */
/* ---- Precios: REF1 (detal, el del pedido) y REF2 (informativa) ---- */

.product-prices {
    margin-top: auto;
    display: flex;
    flex-direction: column;
    gap: .15rem;
}

.price-line {
    display: flex;
    align-items: baseline;
    gap: .4rem;
}

.price-tag {
    font-size: .65rem;
    font-weight: 700;
    letter-spacing: .04em;
    color: #8a8a8a;
    background: #f2f2f2;
    border-radius: 4px;
    padding: .1rem .3rem;
    flex-shrink: 0;
}

.price-line-alt .price-tag {
    background: transparent;
    padding-left: 0;
    padding-right: 0;
}

.product-price {
    color: color-mix(in srgb, var(--secondary-color) 68%, var(--text-color));
    font-weight: 800;
    font-size: 1.25rem;
}

.product-price-alt {
    color: #6b6b6b;
    font-weight: 700;
    font-size: .95rem;
}

.product-actions {
    padding: 1rem;
    margin-top: auto;
    display: flex;
    gap: 10px;
    align-items: center;
}

/* El selector de cantidad y el botón no caben lado a lado en la tarjeta
   compacta sin apretarse: van apilados. */
.products-grid:not(.grid-2) .product-actions {
    flex-direction: column;
    gap: .5rem;
}

.products-grid:not(.grid-2) .product-actions .qty-selector {
    width: 100%;
    justify-content: center;
}

.products-grid:not(.grid-2) .product-actions .qty-input {
    flex-grow: 1;
}

.products-grid:not(.grid-2) .product-actions .add-to-cart-btn {
    width: 100%;
}

/* ---------------- Cantidad ---------------- */

.qty-selector {
    display: flex;
    align-items: center;
    border: 1px solid var(--secondary-color);
    border-radius: 8px;
    overflow: hidden;
    height: 40px;
    flex-shrink: 0;
}

.qty-btn {
    background: var(--primary-color);
    border: none;
    width: 30px;
    height: 100%;
    font-weight: 700;
    cursor: pointer;
    color: var(--on-primary);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: opacity .2s;
}

.qty-btn:hover {
    opacity: .85;
}

.qty-btn:disabled {
    opacity: .5;
    cursor: not-allowed;
}

.qty-input {
    width: 40px;
    height: 100%;
    border: none;
    text-align: center;
    font-weight: 600;
    font-family: inherit;
    appearance: textfield;
    -moz-appearance: textfield;
    font-size: .9rem;
    color: var(--text-color);
    outline: none;
}

.qty-input::-webkit-inner-spin-button,
.qty-input::-webkit-outer-spin-button {
    -webkit-appearance: none;
    appearance: none;
    margin: 0;
}

.qty-input:disabled {
    background: var(--tint);
    cursor: not-allowed;
}

/* ---------------- Botones ---------------- */

.add-to-cart-btn {
    flex-grow: 1;
    height: 40px;
    padding: 0 1rem;
    background: var(--brand-grad);
    color: var(--on-primary);
    border: none;
    border-radius: 999px;
    font-weight: 700;
    font-family: inherit;
    font-size: .9rem;
    cursor: pointer;
    transition: filter .2s, transform .2s, box-shadow .2s;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
}

.add-to-cart-btn:hover:not(:disabled) {
    filter: brightness(1.06);
    transform: translateY(-1px);
}

.add-to-cart-btn:disabled {
    background: var(--border);
    color: var(--muted);
    cursor: not-allowed;
}

.btn-primary {
    background: var(--brand-grad);
    color: var(--on-primary);
    border: none;
    padding: 1rem;
    width: 100%;
    border-radius: 999px;
    font-weight: 700;
    font-family: inherit;
    cursor: pointer;
    font-size: 1rem;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .55rem;
    text-decoration: none;
    transition: filter .2s, transform .2s;
}

.btn-primary:hover:not(:disabled) {
    filter: brightness(1.06);
    transform: translateY(-1px);
}

/* Deshabilitado de verdad apagado: mientras no hay tasa del día, el botón de
   pagar no debe parecer pulsable. */
.btn-primary:disabled {
    background: var(--border);
    color: var(--muted);
    cursor: not-allowed;
    box-shadow: none;
    transform: none;
    filter: none;
}

/* Secundario: contorno, sin relleno de marca */
.btn-danger {
    background-color: transparent;
    color: var(--text-color);
    border: 1px solid var(--border);
    padding: .8rem;
    width: 100%;
    margin-bottom: 1rem;
    border-radius: var(--radius);
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    transition: all .2s;
    display: block;
    text-align: center;
}

.btn-danger:hover {
    background-color: var(--secondary-color);
    color: var(--on-secondary);
}

.btn-submit {
    margin-top: 1rem;
}

/* ---------------- Modal de producto ---------------- */

.modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, .5);
    display: none;
    justify-content: center;
    align-items: center;
    /* Por encima del carrito (2000): un modal siempre gana al panel lateral */
    z-index: 2100;
    opacity: 0;
    transition: opacity .3s ease;
}

.modal-overlay.open {
    display: flex;
    opacity: 1;
}

.modal-content {
    background: var(--card-bg);
    width: 90%;
    max-width: 800px;
    border-radius: var(--radius);
    overflow: hidden;
    display: flex;
    flex-direction: row;
    max-height: 90vh;
    position: relative;
    animation: slideUp .3s ease;
}

@keyframes slideUp {
    from {
        transform: translateY(20px);
        opacity: 0;
    }

    to {
        transform: translateY(0);
        opacity: 1;
    }
}

.modal-image {
    width: 50%;
    object-fit: contain;
    background-color: #f5f5f5;
    padding: 2rem;
}

.modal-details {
    padding: 2rem;
    width: 50%;
    overflow-y: auto;
}

.modal-details h2 {
    margin-bottom: .5rem;
}

.modal-details .product-meta {
    margin-bottom: 1rem;
}

.modal-desc {
    color: #666;
    margin-bottom: 1rem;
}

.modal-prices {
    margin-bottom: 2rem;
    display: flex;
    flex-direction: column;
    gap: .25rem;
}

.modal-price {
    color: color-mix(in srgb, var(--secondary-color) 68%, var(--text-color));
    font-weight: 800;
    font-size: 1.6rem;
}

.modal-price-alt {
    color: #6b6b6b;
    font-weight: 700;
    font-size: 1.15rem;
}

.close-modal {
    position: absolute;
    top: 1rem;
    right: 1rem;
    background: 0 0;
    border: none;
    font-size: 1.5rem;
    cursor: pointer;
    color: var(--text-color);
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
}

.modal-actions {
    display: flex;
    gap: 1rem;
    margin-top: 2rem;
}

.modal-actions .qty-selector {
    height: 50px;
}

.modal-actions .qty-btn {
    width: 40px;
}

.modal-actions .qty-input {
    width: 50px;
    font-size: 1.1rem;
}

.modal-actions .add-to-cart-btn {
    height: 50px;
    font-size: 1.1rem;
}

.mobile-only {
    display: none;
}

/* ---------------- Carrito ---------------- */

.cart-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1900;
    background: rgba(0, 0, 0, .4);
    opacity: 0;
    visibility: hidden;
    transition: opacity .3s, visibility .3s;
}

.cart-backdrop.visible {
    opacity: 1;
    visibility: visible;
}

.cart-sidebar {
    position: fixed;
    top: 0;
    right: -400px;
    width: 100%;
    max-width: 400px;
    height: 100%;
    background: var(--card-bg);
    box-shadow: -2px 0 10px rgba(0, 0, 0, .1);
    z-index: 2000;
    transition: right .3s ease;
}

.cart-sidebar.open {
    right: 0;
}

#cart-view,
.checkout-view {
    height: 100%;
    display: flex;
    flex-direction: column;
}

.cart-header {
    padding: 1.5rem;
    border-bottom: 1px solid var(--border);
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-shrink: 0;
}

.cart-header-back {
    display: flex;
    align-items: center;
    gap: 10px;
}

.icon-close,
.icon-back {
    background: none;
    border: none;
    cursor: pointer;
    color: var(--text-color);
    line-height: 1;
}

.icon-close {
    font-size: 1.5rem;
}

.icon-back {
    font-size: 1.2rem;
}

.cart-items {
    flex-grow: 1;
    overflow-y: auto;
    padding: 1.5rem;
    min-height: 0;
}

.cart-empty {
    text-align: center;
    padding: 2rem;
    color: #666;
}

.cart-item {
    display: flex;
    gap: 1rem;
    margin-bottom: 1.5rem;
}

.cart-item-img {
    width: 60px;
    height: 60px;
    border-radius: 8px;
    object-fit: contain;
    background-color: #f5f5f5;
    padding: .25rem;
    flex-shrink: 0;
}

.cart-item-body {
    flex-grow: 1;
    min-width: 0;
}

.cart-item-name {
    font-weight: 600;
}

.cart-item-price {
    color: #666;
    font-size: .9rem;
}

.cart-item-side {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    align-items: flex-end;
    flex-shrink: 0;
}

.cart-item-remove {
    background: none;
    border: none;
    color: red;
    cursor: pointer;
    font-size: 1.1rem;
    line-height: 1;
}

.cart-item-subtotal {
    text-align: right;
    font-weight: 700;
    font-size: .9rem;
}

.cart-qty-selector {
    display: flex;
    align-items: center;
    border: 1px solid var(--secondary-color);
    border-radius: 6px;
    height: 30px;
    width: fit-content;
    margin-top: 5px;
    overflow: hidden;
}

.cart-qty-btn {
    background: var(--primary-color);
    border: none;
    width: 25px;
    height: 100%;
    cursor: pointer;
    font-size: 1rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--on-primary);
}

.cart-qty-input {
    width: 35px;
    height: 100%;
    border: none;
    text-align: center;
    font-size: .9rem;
    font-family: inherit;
    outline: none;
    appearance: textfield;
    -moz-appearance: textfield;
}

.cart-qty-input::-webkit-inner-spin-button,
.cart-qty-input::-webkit-outer-spin-button {
    -webkit-appearance: none;
    appearance: none;
    margin: 0;
}

.cart-footer {
    padding: 1.5rem;
    border-top: 1px solid var(--border);
    flex-shrink: 0;
}

.cart-total-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 1rem;
    font-weight: 700;
    font-size: 1.1rem;
    color: var(--secondary-color);
}

/* ---------------- Checkout ---------------- */

.checkout-body {
    padding: 1.5rem;
    overflow-y: auto;
    flex-grow: 1;
}

.form-group {
    margin-bottom: 1rem;
}

.form-group label {
    display: block;
    margin-bottom: .5rem;
    font-weight: 500;
}

.form-group input,
.form-group select,
.form-group textarea {
    width: 100%;
    padding: .8rem;
    border: 1px solid var(--border);
    border-radius: 8px;
    font-family: inherit;
    font-size: .95rem;
    outline: none;
    transition: border-color .2s;
}

.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
    border-color: var(--secondary-color);
}

.form-group textarea {
    resize: vertical;
}

.form-row {
    display: flex;
    gap: 10px;
    width: 100%;
}

/* Debe ganarle a `.form-group select { width: 100% }` */
.form-group .w-80 {
    width: 80px;
    flex: 0 0 80px;
}

.form-group .w-90 {
    width: 92px;
    flex: 0 0 92px;
}

.form-group .grow {
    flex: 1 1 auto;
    width: auto;
    min-width: 0;
}

/* ---------------- Spinner ---------------- */

.loading-spinner {
    grid-column: 1 / -1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
    padding: 4rem 1rem;
    color: #666;
}

.spinner {
    width: 38px;
    height: 38px;
    border: 3px solid var(--border);
    border-top-color: var(--primary-color);
    border-radius: 50%;
    animation: spin .8s linear infinite;
}

@keyframes spin {
    to {
        transform: rotate(360deg);
    }
}

/* ---------------- Extras ---------------- */

.flying-img {
    position: fixed;
    z-index: 3000;
    object-fit: contain;
    border-radius: 8px;
    pointer-events: none;
    transition: all .8s cubic-bezier(.2, .8, .3, 1);
}

.scroll-top-btn {
    position: fixed;
    right: 1.5rem;
    bottom: 1.5rem;
    z-index: 900;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 46px;
    height: 46px;
    border: none;
    border-radius: 50%;
    background: var(--primary-color);
    color: var(--on-primary);
    cursor: pointer;
    box-shadow: var(--shadow);
    opacity: 0;
    visibility: hidden;
    transform: translateY(10px);
    transition: all .25s;
}

.scroll-top-btn.visible {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

/* ---------------- Responsive ---------------- */

/* ---------------- Filtros en móvil: cajón lateral ----------------

   Hasta 900px el panel sale del flujo y se convierte en un cajón que entra
   desde la izquierda con el botón del header. Se cierra con la X, tocando el
   fondo oscuro o eligiendo una categoría. */

.filters-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1700;
    background: rgba(0, 0, 0, .45);
    opacity: 0;
    visibility: hidden;
    transition: opacity .3s, visibility .3s;
}

@media (max-width: 900px) {
    .filters-toggle {
        display: flex;
    }

    .catalog-main {
        margin-left: 0;
        padding: 1rem;
    }

    .filters-sidebar {
        position: fixed;
        top: 0;
        left: 0;
        bottom: auto;
        width: 82%;
        max-width: 320px;
        height: 100%;
        z-index: 1800;
        border: none;
        border-radius: 0 var(--radius) var(--radius) 0;
        box-shadow: 4px 0 24px rgba(0, 0, 0, .18);

        /* El cajón no scrollea: scrollea .filters-body. Así la cabecera con
           la X se queda siempre arriba, aunque haya 40 categorías. */
        display: flex;
        flex-direction: column;
        padding: 0;
        overflow: hidden;

        /* Fuera de pantalla hasta que se abre */
        transform: translateX(-100%);
        visibility: hidden;
        transition: transform .32s cubic-bezier(.22, .8, .3, 1), visibility .32s;
    }

    .filters-sidebar.open {
        transform: translateX(0);
        visibility: visible;
    }

    .filters-backdrop.visible {
        opacity: 1;
        visibility: visible;
    }

    .filters-head {
        display: flex;
        flex-shrink: 0;
        padding: .9rem 1.25rem;
    }

    .filters-body {
        flex: 1 1 auto;
        min-height: 0;          /* sin esto el flex no deja que scrollee */
        overflow-y: auto;
        overscroll-behavior: contain;
        padding: 1.15rem 1.25rem 2rem;
        scrollbar-width: thin;
        scrollbar-color: #d9d9d9 transparent;
    }

    /* El primer bloque queda pegado a la cabecera: no necesita su separador */
    .filters-body .filter-block:first-child {
        margin-top: 0;
        padding-top: 0;
        border-top: none;
    }

    .category-btn {
        padding: .7rem .65rem;
        font-size: .85rem;
    }

    .price-input {
        padding: .65rem .6rem;
        font-size: .9rem;
    }

    .modal-content {
        flex-direction: column;
        max-height: 92vh;
    }

    .modal-image {
        width: 100%;
        max-height: 40vh;
    }

    .modal-details {
        width: 100%;
        padding: 1.5rem;
    }
}

@media (max-width: 768px) {
    header {
        padding: .75rem 1rem;
    }

    /* El logo baja a 36px, así que el texto puede subir un poco sin que el
       header crezca. */
    .brand-texto {
        max-height: 34px;
    }

    .logo-container {
        font-size: 1rem;
    }

    .logo-img {
        height: 36px;
    }

    .header-right {
        gap: .5rem;
    }

    .header-btn-text {
        display: none;
    }

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

    .products-grid {
        grid-template-columns: repeat(2, 1fr);
        gap: 1rem;
    }

    .products-grid.grid-2 {
        grid-template-columns: 1fr;
    }

    .product-image {
        height: 150px;
    }

    .products-grid.grid-2 .product-image {
        height: 250px;
    }

    .fav-toggle {
        width: 30px;
        height: 30px;
        top: .4rem;
        right: .4rem;
    }

    .sort-dropdown {
        min-width: 140px;
    }

    .product-title {
        font-size: .9rem;
    }

    .product-price {
        font-size: 1.1rem;
    }

    .product-price-alt {
        font-size: .85rem;
    }

    .price-tag {
        font-size: .6rem;
    }

    .product-meta {
        font-size: .7rem;
        flex-wrap: wrap;
        gap: .25rem;
    }

    .product-stock {
        font-size: .65rem;
        padding: .2rem .4rem;
    }

    .product-actions {
        padding: .5rem;
        flex-direction: column;
        gap: .5rem;
    }

    /* Solo en la tarjeta: ahí los controles van apilados y el selector
       ocupa todo el ancho. En el modal siguen lado a lado, así que el
       selector conserva su ancho o empujaría el botón fuera de pantalla. */
    .product-actions .qty-selector {
        width: 100%;
        justify-content: center;
    }

    .product-actions .qty-input {
        flex-grow: 1;
    }

    .product-actions .add-to-cart-btn {
        width: 100%;
    }

    .modal-actions .qty-selector {
        flex: 0 0 auto;
    }

    .modal-overlay {
        padding: 0;
    }

    .modal-content {
        width: 100%;
        height: 100%;
        max-height: 100%;
        border-radius: 0;
    }

    .desktop-only {
        display: none;
    }

    .mobile-only {
        display: flex;
    }

    .cart-sidebar {
        max-width: 100%;
        right: -100%;
    }
}

/* ---------------- Capas (z-index) ---------------- */

/*
   Orden de apilado del sitio, de abajo hacia arriba:

      90   panel de filtros fijo (escritorio)
     100   header
     900   botón "volver arriba"
    1700   fondo oscuro de los filtros (móvil)
    1800   cajón de filtros (móvil)
    1900   fondo oscuro del carrito
    2000   panel del carrito
    2100   modal de producto
    3000   imagen que vuela al carrito
    4000   SweetAlert2 (confirmaciones, checkout, "pedido exitoso")

   SweetAlert2 trae 1060 por defecto, que lo dejaba por debajo del panel del
   carrito: los avisos salían tapados. Como esa clase la escribe la librería,
   el !important es necesario para ganarle a su hoja de estilos.
*/
.swal2-container {
    z-index: 4000 !important;
}

/* ============================================================
   CHELCRIS - Bloques propios
   ------------------------------------------------------------
   Todo lo que no existe en la plantilla hermana: la franja de
   fotos de la tienda, los pasos y el resumen del checkout, los
   esqueletos de carga y la página de retorno del banco.
   ============================================================ */

/* ---------------- Franja de fotos de la tienda ---------------- */

/* Fotos reales del local, no stock. Sirven para que el cliente reconozca
   dónde está comprando antes de ver el primer producto.

   Es una franja baja a propósito: el catálogo es lo que la gente vino a
   ver, y un héroe de pantalla completa solo le hace hacer scroll. */
.hero {
    position: relative;
    /* Va dentro de .catalog-main, que ya trae el padding lateral: el panel de
       filtros es position:fixed y, suelto en la página, le tapaba el lado
       izquierdo al hero. */
    margin: 0 0 1.5rem;
    border-radius: var(--radius);
    overflow: hidden;
    box-shadow: var(--shadow);
    aspect-ratio: 21 / 6;
    min-height: 150px;
    background: var(--tint-strong);
}

.hero-slide {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    opacity: 0;
    transition: opacity 1s ease;
}

.hero-slide.is-active {
    opacity: 1;
}

/* Velo oscuro por la izquierda: solo lo justo para que el texto se lea
   sobre cualquier foto. Nada de colores de marca encima de la imagen. */
.hero::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, rgba(0, 0, 0, .62) 0%, rgba(0, 0, 0, .25) 55%, rgba(0, 0, 0, 0) 100%);
    pointer-events: none;
}

.hero-texto {
    position: absolute;
    z-index: 1;
    left: clamp(1rem, 4vw, 2.5rem);
    top: 50%;
    transform: translateY(-50%);
    max-width: min(55%, 30rem);
    color: #fff;
    text-shadow: 0 2px 12px rgba(0, 0, 0, .35);
}

.hero-texto h1 {
    font-size: clamp(1.1rem, 2.6vw, 1.9rem);
    font-weight: 800;
    line-height: 1.15;
    margin-bottom: .35rem;
}

.hero-texto p {
    font-size: clamp(.78rem, 1.4vw, .95rem);
    font-weight: 500;
    opacity: .95;
}

/* Sin animación para quien pidió que no se muevan las cosas. */
@media (prefers-reduced-motion: reduce) {
    .hero-slide {
        transition: none;
    }
}

@media (max-width: 900px) {
    .hero {
        margin: 0 0 1rem;
        aspect-ratio: 16 / 9;
        min-height: 0;
    }

    .hero-texto {
        max-width: 78%;
    }
}

/* ---------------- Checkout: pasos ---------------- */

.checkout-step {
    display: flex;
    align-items: center;
    gap: .6rem;
    margin: 1.5rem 0 .9rem;
    font-weight: 700;
    font-size: .95rem;
}

.checkout-step:first-child {
    margin-top: 0;
}

.step-num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    flex-shrink: 0;
    border-radius: 50%;
    background: var(--brand-grad);
    color: var(--on-primary);
    font-size: .75rem;
    font-weight: 700;
}

.field-hint {
    display: block;
    margin-top: .35rem;
    color: var(--muted);
    font-size: .78rem;
    line-height: 1.35;
}

.check-line {
    display: flex;
    align-items: flex-start;   /* el texto puede partirse en dos líneas en móvil */
    gap: .6rem;
    font-weight: 500;
    cursor: pointer;
    margin-bottom: 0;
}

/* Debe ganarle a `.form-group input { width: 100% }` */
.check-line input[type="checkbox"] {
    width: 18px;
    height: 18px;
    flex: 0 0 18px;
    margin-top: .15rem;
    accent-color: var(--primary-color);
    cursor: pointer;
}

/* ---------------- Checkout: modo de entrega ---------------- */

.delivery-options {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: .6rem;
}

/* Tarjeta clicable en vez de un radio suelto: el área de toque es toda la
   tarjeta, no el círculo de 14px. */
.radio-card {
    position: relative;
    display: block;
    margin: 0;
    cursor: pointer;
}

.radio-card input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

.radio-card-body {
    display: flex;
    flex-direction: column;
    gap: .15rem;
    padding: .8rem;
    border: 1.5px solid var(--border);
    border-radius: var(--radius-sm);
    transition: border-color .2s, background .2s;
}

.radio-card input:checked + .radio-card-body {
    border-color: var(--primary-color);
    background: var(--tint);
}

.radio-card input:focus-visible + .radio-card-body {
    box-shadow: 0 0 0 3px var(--ring);
}

.radio-card-title {
    font-weight: 600;
    font-size: .9rem;
}

.radio-card-note {
    color: var(--muted);
    font-size: .76rem;
}

/* ---------------- Checkout: resumen ---------------- */

.checkout-summary {
    background: var(--tint);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 1rem;
    margin-bottom: 1rem;
}

.summary-line {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    font-size: .9rem;
    margin-bottom: .5rem;
}

.summary-line span:first-child {
    color: var(--muted);
}

.summary-total {
    padding-top: .55rem;
    margin-bottom: 0;
    border-top: 1px dashed var(--border);
    font-size: 1.05rem;
    font-weight: 700;
}

.summary-total span:first-child {
    color: inherit;
}

/* La línea que de verdad importa: el catálogo está en dólares pero el banco
   debita en bolívares, y el cliente tiene que ver ESE monto antes de pulsar. */
.summary-bs {
    margin-top: .85rem;
    padding-top: .75rem;
    border-top: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    gap: .15rem;
}

.summary-bs span {
    font-weight: 700;
    font-size: 1rem;
    color: var(--primary-color);
}

.summary-bs small {
    color: var(--muted);
    font-size: .76rem;
}

.summary-bs-error span {
    color: var(--danger);
}

.checkout-legal {
    margin-top: .8rem;
    color: var(--muted);
    font-size: .75rem;
    line-height: 1.45;
    text-align: center;
}

/* Botón de pagar mientras se habla con el banco */
.btn-submit.is-loading {
    pointer-events: none;
    opacity: .75;
}

/* ---------------- Esqueletos de carga ---------------- */

/* Reemplazan el salto en blanco mientras llega api.php?action=products: la
   página ya tiene la forma final antes de tener los datos. */
.skeleton-card {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
    padding-bottom: 1rem;
}

.skeleton-box {
    background: linear-gradient(90deg,
        var(--border) 25%,
        color-mix(in srgb, var(--border) 45%, var(--card-bg)) 37%,
        var(--border) 63%);
    background-size: 400% 100%;
    animation: skeleton-wave 1.4s ease infinite;
}

.skeleton-img {
    width: 100%;
    aspect-ratio: 1 / 1;
}

.skeleton-line {
    height: 12px;
    border-radius: 6px;
    margin: .75rem 1rem 0;
}

.skeleton-line.short {
    width: 45%;
}

.skeleton-line.medium {
    width: 70%;
}

@keyframes skeleton-wave {
    0%   { background-position: 100% 50%; }
    100% { background-position: 0 50%; }
}

@media (prefers-reduced-motion: reduce) {
    .skeleton-box {
        animation: none;
    }
}

/* ---------------- Página de retorno del pago ---------------- */

.pago-body {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 2rem 1rem;
    background: var(--bg-color);
}

.pago-wrap {
    width: 100%;
    max-width: 30rem;
}

.pago-marca {
    display: flex;
    justify-content: center;
    margin-bottom: 1.5rem;
    text-decoration: none;
    color: var(--text-color);
    font-weight: 800;
    font-size: 1.3rem;
}

.pago-marca img {
    height: 52px;
    width: auto;
}

.pago-card {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 22px;
    box-shadow: var(--shadow-lg);
    padding: 2rem 1.75rem;
    text-align: center;
}

.pago-card h1 {
    font-size: 1.4rem;
    font-weight: 800;
    margin-bottom: .6rem;
}

.pago-detalle {
    color: var(--muted);
    font-size: .92rem;
    line-height: 1.5;
    margin-bottom: 1.5rem;
}

.pago-icono {
    display: flex;
    justify-content: center;
    margin-bottom: 1.25rem;
}

.pago-icono svg {
    width: 84px;
    height: 84px;
}

.pago-check-circle {
    stroke-width: 2.5;
    stroke-dasharray: 160;
    stroke-dashoffset: 160;
    animation: pago-trazo .6s ease forwards;
}

.pago-check-mark {
    stroke-width: 4;
    stroke-linecap: round;
    stroke-linejoin: round;
    stroke-dasharray: 60;
    stroke-dashoffset: 60;
    animation: pago-trazo .4s ease .5s forwards;
}

.is-ok .pago-check-circle,
.is-ok .pago-check-mark {
    stroke: var(--primary-color);
}

.is-fail .pago-check-circle,
.is-fail .pago-check-mark {
    stroke: var(--danger);
}

@keyframes pago-trazo {
    to { stroke-dashoffset: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .pago-check-circle,
    .pago-check-mark {
        animation: none;
        stroke-dashoffset: 0;
    }
}

/* Datos del pago: el comprobante que el cliente va a querer capturar. */
.pago-datos {
    text-align: left;
    background: var(--tint);
    border-radius: var(--radius);
    padding: 1rem;
    margin-bottom: 1.5rem;
}

.pago-datos > div {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: .4rem 0;
    font-size: .88rem;
}

.pago-datos > div + div {
    border-top: 1px dashed var(--border);
}

.pago-datos dt {
    color: var(--muted);
}

.pago-datos dd {
    font-weight: 600;
    text-align: right;
    word-break: break-word;
}

.pago-acciones {
    display: flex;
    flex-direction: column;
    gap: .6rem;
}

.btn-ghost {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: .85rem 1rem;
    width: 100%;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: transparent;
    color: var(--text-color);
    font-family: inherit;
    font-weight: 600;
    font-size: .92rem;
    text-decoration: none;
    cursor: pointer;
    transition: background .2s, border-color .2s;
}

.btn-ghost:hover {
    background: var(--tint);
    border-color: color-mix(in srgb, var(--primary-color) 40%, var(--border));
}

/* WhatsApp con su propio verde: es una marca ajena y reconocerla de un
   vistazo vale más que la coherencia con nuestra paleta. */
.btn-wa {
    background: #25D366;
    color: #fff;
    box-shadow: none;
}

.pago-nota {
    margin-top: 1.1rem;
    color: var(--muted);
    font-size: .78rem;
    line-height: 1.45;
}

/* Pago a medias: ni verde de confirmado ni rojo de rechazo. El cliente
   todavía puede terminarlo, y pintarlo de rojo lo manda a llamar por teléfono
   cuando lo único que hace falta es volver a intentar. */
.is-wait .pago-check-circle,
.is-wait .pago-check-mark {
    stroke: #E5A200;
}

/* ---------------- Ajustes de móvil ---------------- */

/* El cajón del carrito vive fuera de la pantalla (right: -100%) y, aunque no
   se vea, ensancha el documento: en 375px salían 4px de scroll horizontal.

   OJO: `overflow-x: hidden` aquí ROMPE el position: sticky del header (un
   ancestro con overflow distinto de visible lo anula). `clip` recorta igual
   pero no crea contexto de scroll, así que el header se queda pegado. */
html,
body {
    overflow-x: clip;
}

@media (max-width: 900px) {
    /* "Catálogo en línea" no cabe junto al logo y quedaba como "CAT…". El logo
       ya dice quiénes somos. */
    .header-brand {
        display: none;
    }

    /* El selector de orden cede ancho en vez de empujar los botones de vista
       fuera de la pantalla. */
    .sort-selector {
        flex: 1 1 auto;
        min-width: 0;
    }

    .sort-dropdown {
        min-width: 0;
        width: 100%;
    }

    .view-toggle {
        flex-shrink: 0;
    }
}

/* ---------------- Esperas: spinners, pasos y overlay ---------------- */

/* Spinner grande con el degradado de marca: gira un anillo con un hueco. */
.pago-spinner {
    width: 84px;
    height: 84px;
    border-radius: 50%;
    background: conic-gradient(from 0deg, transparent 0 25%, var(--primary-color) 100%);
    -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 7px), #000 calc(100% - 6px));
    mask: radial-gradient(farthest-side, transparent calc(100% - 7px), #000 calc(100% - 6px));
    animation: pago-girar 1s linear infinite;
}

.pago-spinner.is-error {
    animation: none;
    background: var(--danger);
}

@keyframes pago-girar {
    to { transform: rotate(360deg); }
}

/* Spinner chico para dentro de un botón */
.btn-spinner {
    display: inline-block;
    width: 16px;
    height: 16px;
    margin-right: .5rem;
    vertical-align: -3px;
    border-radius: 50%;
    border: 2px solid currentColor;
    border-right-color: transparent;
    animation: pago-girar .7s linear infinite;
}

/* Lista de pasos: hecho (check), activo (punto latiendo), pendiente (gris) */
.pago-pasos {
    list-style: none;
    margin: 0 auto 1.25rem;
    padding: 0;
    text-align: left;
    max-width: 22rem;
}

.pago-pasos li {
    position: relative;
    padding: .45rem 0 .45rem 2rem;
    color: var(--muted);
    font-size: .9rem;
    transition: color .3s;
}

.pago-pasos li::before {
    content: '';
    position: absolute;
    left: .35rem;
    top: .8rem;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    border: 2px solid var(--border);
    background: transparent;
    transition: all .3s;
}

.pago-pasos li.is-active {
    color: var(--text-color);
    font-weight: 600;
}

.pago-pasos li.is-active::before {
    border-color: var(--primary-color);
    background: var(--primary-color);
    animation: pago-latir 1.1s ease-in-out infinite;
}

.pago-pasos li.is-done {
    color: var(--text-color);
}

/* Hecho: círculo relleno de marca con una palomita encima (::after) */
.pago-pasos li.is-done::before {
    border-color: var(--primary-color);
    background: var(--primary-color);
}

.pago-pasos li.is-done::after {
    content: '';
    position: absolute;
    left: calc(.35rem + 5px);
    top: calc(.8rem + 3px);
    width: 4px;
    height: 7px;
    border: solid var(--on-primary);
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}

@keyframes pago-latir {
    0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--primary-color) 45%, transparent); }
    50%      { box-shadow: 0 0 0 6px transparent; }
}

/* Overlay dentro del panel del carrito mientras se habla con el banco */
.checkout-overlay {
    position: absolute;
    inset: 0;
    z-index: 5;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;
    background: color-mix(in srgb, var(--card-bg) 92%, transparent);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    opacity: 0;
    transition: opacity .25s ease;
}

.checkout-overlay.is-visible {
    opacity: 1;
}

.checkout-overlay-box {
    text-align: center;
    width: 100%;
    max-width: 22rem;
}

.checkout-overlay-box .pago-spinner {
    margin: 0 auto 1.25rem;
    width: 64px;
    height: 64px;
}

.checkout-overlay-title {
    font-weight: 700;
    font-size: 1.1rem;
    margin-bottom: .75rem;
}

.checkout-overlay-note {
    color: var(--muted);
    font-size: .78rem;
}

@media (prefers-reduced-motion: reduce) {
    .pago-spinner,
    .btn-spinner,
    .pago-pasos li.is-active::before {
        animation: none;
    }
}

/* ---------------- Aviso de pago pendiente en el catálogo ---------------- */

.aviso-pendiente {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: .75rem 1rem;
    margin-bottom: 1.25rem;
    padding: .9rem 1.1rem;
    border-radius: var(--radius);
    border: 1px solid color-mix(in srgb, #E5A200 45%, var(--border));
    background: color-mix(in srgb, #E5A200 10%, var(--card-bg));
    box-shadow: var(--shadow);
}

.aviso-pendiente-texto {
    display: flex;
    flex-direction: column;
    gap: .15rem;
    min-width: 0;
    flex: 1 1 18rem;
}

.aviso-pendiente-texto strong {
    font-size: .95rem;
}

.aviso-pendiente-texto span {
    color: var(--muted);
    font-size: .84rem;
}

.aviso-pendiente-botones {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
}

.aviso-btn {
    padding: .55rem .95rem;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--card-bg);
    color: var(--text-color);
    font-family: inherit;
    font-weight: 600;
    font-size: .84rem;
    cursor: pointer;
    transition: background .2s, border-color .2s;
}

.aviso-btn:hover:not(:disabled) {
    background: var(--tint);
}

.aviso-btn:disabled {
    opacity: .7;
    cursor: wait;
}

.aviso-btn-primary {
    background: var(--brand-grad);
    color: var(--on-primary);
    border-color: transparent;
}

.aviso-btn-primary:hover:not(:disabled) {
    background: var(--brand-grad);
    filter: brightness(1.06);
}

.aviso-btn-quiet {
    background: transparent;
    border-color: transparent;
    color: var(--muted);
}

/* Pedido cerrado (vencido o cancelado): gris neutro, ni éxito ni error */
.is-closed .pago-check-circle,
.is-closed .pago-check-mark {
    stroke: var(--muted);
}

.btn-cancelar {
    color: var(--danger);
    border-color: color-mix(in srgb, var(--danger) 35%, var(--border));
}

.btn-cancelar:hover {
    background: color-mix(in srgb, var(--danger) 8%, var(--card-bg));
    border-color: var(--danger);
}

/* El botón de pagar tiene un texto largo: en 375px se parte en dos líneas.
   Que se parta bien, con interlineado y sin que el icono se estire. */
.btn-submit {
    white-space: normal;
    line-height: 1.25;
    padding: .9rem 1.25rem;
}

.btn-submit svg {
    flex-shrink: 0;
}

/* ============================================================
   Revisión UX final: foco, toque, teclado móvil, errores inline
   ============================================================ */

/* ---------- Foco visible ----------
   Varios controles traían `outline: none` de la plantilla. Sin anillo de
   foco, quien navega con teclado no sabe dónde está. Se restituye con
   :focus-visible, que solo aparece con teclado, no al hacer clic. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
    outline: 3px solid var(--ring);
    outline-offset: 2px;
}

.form-group input:focus-visible,
.form-group select:focus-visible,
.form-group textarea:focus-visible,
.search-input:focus-visible,
.price-input:focus-visible {
    outline: none;
    border-color: var(--primary-color);
    box-shadow: 0 0 0 3px var(--ring);
}

/* ---------- El carrito ahora es un <button> de verdad ---------- */
.cart-icon {
    background: none;
    border: none;
    font: inherit;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
}

/* ---------- Toque ---------- */

/* Quita los 300 ms de retraso del doble-tap en móvil y evita zooms
   accidentales sobre los controles. */
button,
a,
input,
select,
textarea,
.product-card,
.radio-card {
    touch-action: manipulation;
}

/* Botones +/-: 30 px y 25 px no llegan al mínimo de 44 px de toque. En
   móvil se agrandan; en escritorio el ratón no lo necesita. */
@media (max-width: 900px) {
    .qty-selector {
        height: 44px;
    }

    .qty-btn {
        width: 40px;
        font-size: 1.15rem;
    }

    .cart-qty-btn {
        width: 34px;
        min-height: 36px;
    }

    .view-toggle-btn {
        min-width: 44px;
        min-height: 44px;
    }

    .header-btn,
    .aviso-btn {
        min-height: 44px;
    }

    .icon-close,
    .icon-back,
    .cart-item-remove {
        min-width: 44px;
        min-height: 44px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }

    /* Por debajo de 16 px, iOS hace zoom al enfocar un campo. */
    input,
    select,
    textarea,
    .search-input,
    .price-input,
    .sort-dropdown,
    .form-group input,
    .form-group select,
    .form-group textarea {
        font-size: 16px;
    }
}

/* ---------- Errores junto al campo ---------- */

/* El popup sigue existiendo para errores del servidor, pero el campo que
   falló se marca y el mensaje va debajo, donde el cliente lo está mirando. */
.form-group input.is-invalid,
.form-group select.is-invalid,
.form-group textarea.is-invalid {
    border-color: var(--danger);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--danger) 25%, transparent);
}

.field-error {
    display: block;
    margin-top: .35rem;
    color: var(--danger);
    font-size: .8rem;
    font-weight: 500;
    line-height: 1.35;
}

/* ---------- Feedback al pulsar tarjetas y botones ---------- */
.add-to-cart-btn:active:not(:disabled),
.btn-primary:active:not(:disabled),
.aviso-btn-primary:active:not(:disabled) {
    transform: scale(.98);
}

/* ---------- Modal de producto: alineación y tamaños ---------- */

/* El selector de cantidad y el botón van a la MISMA altura y en una sola
   línea. Antes el botón tenía 50 px de alto pero el texto "Agregar al
   Carrito" se partía en dos líneas y quedaba más alto que el selector. */
.modal-actions {
    align-items: stretch;
    gap: .75rem;
    margin-top: 1.5rem;
}

.modal-actions .qty-selector {
    height: 48px;
    flex: 0 0 auto;
}

.modal-actions .qty-btn {
    width: 44px;
    font-size: 1.15rem;
}

.modal-actions .add-to-cart-btn {
    height: 48px;
    font-size: 1rem;
    white-space: nowrap;
    padding: 0 1.25rem;
    min-width: 0;
}

/* El fondo se queda quieto con el modal abierto (la rueda del mouse antes
   seguía moviendo el catálogo por detrás). El overlay tiene su propio scroll
   por si el modal es más alto que la pantalla. */
.modal-overlay.open {
    overflow-y: auto;
    overscroll-behavior: contain;
}

@media (max-width: 480px) {
    .modal-actions {
        flex-direction: column;
    }

    .modal-actions .qty-selector {
        width: 100%;
        justify-content: center;
    }

    .modal-actions .add-to-cart-btn {
        width: 100%;
    }
}

/* Chips del modal juntos a la izquierda, no uno en cada extremo */
.modal-details .product-meta {
    justify-content: flex-start;
    gap: .5rem;
}

.modal-details .modal-prices {
    margin-top: 1rem;
}

/* El contenedor del modal recibe el foco al abrir; sin anillo, que el
   borde del propio modal ya lo delimita. */
.modal-content:focus {
    outline: none;
}

/* Reserva el espacio de la barra de scroll aunque el scroll esté bloqueado:
   sin esto, al abrir el modal desaparece la barra y todo el fondo salta
   15 px a la derecha (en Windows se nota mucho). */
html {
    scrollbar-gutter: stable;
}

/* El marco del selector de cantidad va del mismo verde que sus botones; en
   cian desentonaba al lado del botón "Agregar". */
.qty-selector,
.cart-qty {
    border-color: var(--primary-color);
}

.cart-total-row span:first-child {
    color: var(--text-color);
}

/* ============================================================
   Superficies del navegador y detalles de acabado (Impeccable)
   ------------------------------------------------------------
   Lo que no se dibuja también lleva el diseño: selección de texto, caret,
   barras de scroll, números tabulares. Con los valores por defecto del
   navegador la página se ve ensamblada, no construida.
   ============================================================ */

::selection {
    background: color-mix(in srgb, var(--primary-color) 28%, #ffffff);
    color: var(--text-color);
}

html {
    accent-color: var(--primary-color);
    caret-color: var(--primary-color);
}

/* Barras de scroll finas y del tono de la página en los paneles internos */
.cart-items,
.checkout-body,
.filters-sidebar,
.modal-overlay.open {
    scrollbar-width: thin;
    scrollbar-color: var(--border) transparent;
}

/* Precios y totales con cifras tabulares: al cambiar la cantidad, el ancho
   del número no baila. */
.product-price,
.modal-price,
.cart-item-price,
.cart-item-total,
.cart-total-row,
.summary-line,
.summary-bs,
.pago-datos dd,
.qty-input,
.cart-qty-input {
    font-variant-numeric: tabular-nums;
}

/* Títulos equilibrados: sin una palabra huérfana en la segunda línea */
h1, h2, h3,
.product-title,
.pago-card h1 {
    text-wrap: balance;
}

/* Icono en el aviso de pago pendiente en lugar del borde lateral */
.aviso-pendiente-texto {
    position: relative;
    padding-left: 2rem;
}

.aviso-pendiente-texto::before {
    content: '';
    position: absolute;
    left: 0;
    top: .15rem;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    border: 2px solid #E5A200;
    background:
        linear-gradient(#E5A200, #E5A200) 50% 40% / 2px 7px no-repeat,
        linear-gradient(#E5A200, #E5A200) 50% 72% / 2px 2px no-repeat;
}

/* En teléfono el hero es bajo: el título en una talla contenida y el
   subtítulo a dos líneas máximo, para que nada se corte. */
@media (max-width: 600px) {
    .hero-texto {
        max-width: 88%;
    }

    .hero-texto h1 {
        font-size: 1.15rem;
        margin-bottom: .25rem;
    }

    /* El subtítulo no cabe entero sobre una foto de 16:9 en 375 px y
       cortado a media palabra se ve peor que ausente. El título ya lo dice. */
    .hero-texto p {
        display: none;
    }
}

/* ---------- Formulario del checkout: selects, checkbox, textarea ---------- */

/* Flecha propia en los <select>: la nativa quedaba pegada al borde y sin
   aire. appearance: none + un chevron dibujado, con espacio a la derecha. */
.form-group select,
#delivery-zone {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 2.4rem;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236C757D' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right .9rem center;
    background-size: 16px 16px;
    cursor: pointer;
}

/* Los selects cortos (V / 0414 / J) necesitan un poco más de ancho para que
   el valor y la flecha no se toquen. */
.form-group .w-80 {
    width: 88px;
    flex: 0 0 88px;
}

.form-group .w-90 {
    width: 104px;
    flex: 0 0 104px;
}

/* Checkbox centrado con su texto */
.check-line {
    align-items: center;
    line-height: 1.3;
}

.check-line input[type="checkbox"] {
    margin: 0;
    flex: 0 0 20px;
    width: 20px;
    height: 20px;
}

/* La dirección no se redimensiona: el tirador de la esquina rompe el panel
   y tres líneas son suficientes. */
.form-group textarea {
    resize: none;
    min-height: 92px;
}

/* ---------- Sala de espera mientras se paga en otra pestaña ---------- */
.checkout-overlay-text {
    color: var(--muted);
    font-size: .88rem;
    line-height: 1.45;
    margin-bottom: 1rem;
}

.espera-botones {
    display: flex;
    flex-direction: column;
    gap: .5rem;
    margin-bottom: 1rem;
}

.espera-botones .btn-ghost {
    padding: .7rem 1rem;
    font-size: .88rem;
}
