/*
   ==========================================================================
   COMPONENTE: Catálogo (página completa, app/Views/catalogo.php)
   Grilla de productos con filtro por categoría y selector de tamaño,
   cantidad y precio en vivo. Hasta 2026-09-09 este mismo markup vivía
   adentro de un modal sobre la landing; ahora es una página propia en
   /catalogo, así que .catalog-head/.catalog-grid van directo dentro de un
   <section class="catalog-page"> + .container, sin wrapper de modal.
   ========================================================================== */

.catalog-head { margin-bottom: 1.5rem; }
.catalog-head > p { margin-bottom: 1.25rem; }

.catalog-head h1 {
  font-size: var(--fs-h2);
  margin-bottom: 0.9rem;
}

/* --------------------------------------------------------------------------
   Barra de herramientas: orden + botón "Filtros" (mobile) + contador de
   favoritos. Agregado 2026-09-10 junto con el sidebar de abajo.
   -------------------------------------------------------------------------- */
.catalog-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-bottom: 1.25rem;
  padding-bottom: 1.25rem;
  border-bottom: 1px solid var(--border-color);
}

.catalog-favorites-count {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--color-text-soft);
}
.catalog-favorites-count svg { width: 0.95rem; height: 0.95rem; color: var(--color-danger); }

.catalog-sort {
  display: flex;
  align-items: center;
  gap: 0.5em;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--color-text-soft);
}

.catalog-sort select {
  padding: 0.45rem 0.7rem;
  border-radius: var(--radius-sm);
  border: 1.5px solid var(--border-color);
  background-color: var(--color-bg-card);
  font-family: var(--font-body);
  /* 16px en mobile: con menos, iOS hace zoom al enfocar el campo y la
     página queda corrida de costado. Desde 700px vuelve a 0.82rem. */
  font-size: 1rem;
  font-weight: 500;
  color: var(--color-text-main);
  cursor: pointer;
}

.catalog-filters-toggle { display: inline-flex; }

/* --------------------------------------------------------------------------
   Layout: sidebar de filtros + grilla. En mobile el sidebar es un panel
   colapsable (togglea [hidden], como .site-menu) que se abre con el botón
   "Filtros" de la toolbar; desde 980px queda siempre visible como columna
   fija a la izquierda.
   -------------------------------------------------------------------------- */
.catalog-layout {
  display: flex;
  flex-direction: column;
  gap: 1.75rem;
}

.catalog-sidebar {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  padding: 1.1rem;
  background-color: var(--color-bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
}
.catalog-sidebar[hidden] { display: none; }

.catalog-sidebar-section h3 {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text-soft);
  margin: 0 0 0.75rem;
}

/* --------------------------------------------------------------------------
   Buscador por texto — vive en el sidebar de filtros (no en el nav, que
   perdió su propio buscador el 2026-09-21, ver CLAUDE.md ->
   "Decisiones descartadas"): acá es donde la búsqueda ya se combinaba con
   categoría/precio en applyFilters(), así que el input solo necesitó volver
   a escribir `searchTerm`, sin JS de filtrado nuevo.
   Es la única sección del sidebar con tarjeta propia (tinte verde suave +
   título en display) — a propósito: de los tres filtros (buscar/categoría/
   precio) es el punto de entrada principal, así que lleva el único acento
   fuerte del panel; categoría y precio se quedan en su tratamiento plano de
   siempre. El movimiento (brote respirando + cursor parpadeante en reposo)
   es la misma idea, no tres animaciones sueltas: invitan a escribir.
   -------------------------------------------------------------------------- */
.catalog-search-panel {
  padding: 1rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-color);
  background-color: color-mix(in srgb, var(--color-primary) 6%, var(--color-bg-card));
}

.catalog-search-heading {
  display: flex;
  align-items: center;
  gap: 0.33rem;
  margin-bottom: 0.2rem;
}
.catalog-search-heading h3 {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 600;
  font-size: 0.53rem;
  line-height: 1.2;
  color: var(--color-primary);
  margin: 0;
  text-transform: none;
  letter-spacing: 0;
}

.catalog-search-icon {
  position: relative;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.08rem;
  height: 1.08rem;
  border-radius: 50%;
  background-color: var(--color-bg-card);
  color: var(--color-primary);
}
.catalog-search-icon-sprout {
  position: absolute;
  right: -0.1rem;
  bottom: -0.1rem;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 0.53rem;
  height: 0.53rem;
  border-radius: 50%;
  background-color: var(--color-highlight);
  color: var(--color-primary);
  transform-origin: 50% 100%;
  animation: catalog-search-sway 4s ease-in-out infinite;
}
.catalog-search-icon-sprout svg { width: 0.31rem; height: 0.31rem; }

@keyframes catalog-search-sway {
  0%, 100% { transform: rotate(-6deg); }
  50% { transform: rotate(6deg); }
}

.catalog-search-sub {
  font-size: 0.78rem;
  color: var(--color-text-muted);
  margin: 0 0 0.75rem;
}

.catalog-search-bar {
  position: relative;
  display: flex;
  align-items: center;
  overflow: hidden;
  border-radius: 999px;
  border: 1.5px solid var(--border-color);
  background-color: var(--color-bg-card);
  padding-left: 0.9rem;
}
.catalog-search-bar input {
  flex: 1;
  min-width: 0;
  border: none;
  background: none;
  padding: 0.55rem 0.2rem;
  font-family: var(--font-body);
  /* 16px en mobile: con menos, iOS hace zoom al enfocar el campo y la
     página queda corrida de costado. Desde 700px vuelve a 0.85rem. */
  font-size: 1rem;
  color: var(--color-text-main);
}
.catalog-search-bar input:focus { outline: none; }
.catalog-search-bar:focus-within { border-color: var(--color-accent); }

.catalog-search-submit {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.2rem;
  height: 2.2rem;
  margin: 0.2rem;
  border: none;
  border-radius: 50%;
  background-color: var(--color-primary);
  color: var(--color-text-light);
  cursor: pointer;
  transition: background-color 0.18s ease;
}
.catalog-search-submit:hover { background-color: var(--color-primary-hover); }
.catalog-search-submit svg { width: 1rem; height: 1rem; }

/* Aviso breve de "solo letras": aparece al descartar un carácter que no
   es letra (ver syncSearchTerm() en catalogo.php) y se va solo. */
.catalog-search-bar:has(input[aria-invalid="true"]) { border-color: var(--color-danger); }
.catalog-search-error {
  margin: 0.45rem 0 0 0.9rem;
  font-size: 0.76rem;
  font-weight: 500;
  color: var(--color-danger);
}
.catalog-search-error[hidden] { display: none; }

@media (prefers-reduced-motion: reduce) {
  .catalog-search-icon-sprout { animation: none; }
}

/* --------------------------------------------------------------------------
   Filtros por categoría
   -------------------------------------------------------------------------- */
.catalog-filters {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.filter-chip {
  padding: 0.5rem 0.95rem;
  border-radius: var(--radius-sm);
  border: 1.5px solid var(--border-color);
  background: transparent;
  font-family: var(--font-body);
  font-size: 0.84rem;
  font-weight: 500;
  color: var(--color-text-muted);
  text-align: left;
  cursor: pointer;
  transition: border-color 0.18s ease, background-color 0.18s ease, color 0.18s ease;
}
.filter-chip:hover { border-color: var(--color-accent); color: var(--color-accent); }
.filter-chip[aria-pressed="true"] {
  background-color: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-text-light);
}

/* --------------------------------------------------------------------------
   Filtro de precio (Desde/Hasta)
   -------------------------------------------------------------------------- */
.price-range-inputs {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
}

.price-range-field {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.price-range-field label {
  font-family: var(--font-mono);
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-soft);
}
.price-range-field input {
  width: 100%;
  padding: 0.5rem 0.6rem;
  border-radius: var(--radius-sm);
  border: 1.5px solid var(--border-color);
  background-color: var(--color-bg-main);
  font-family: var(--font-body);
  /* 16px en mobile: con menos, iOS hace zoom al enfocar el campo y la
     página queda corrida de costado. Desde 700px vuelve a 0.85rem. */
  font-size: 1rem;
  color: var(--color-text-main);
}

.price-range-sep {
  align-self: flex-end;
  padding-bottom: 0.6rem;
  color: var(--color-text-soft);
}

/* --------------------------------------------------------------------------
   Grilla de productos
   -------------------------------------------------------------------------- */
.catalog-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
  align-content: start;
}

.catalog-empty-state {
  grid-column: 1 / -1;
  padding: 2.5rem 1.5rem;
  text-align: center;
  color: var(--color-text-soft);
  border: 1.5px dashed var(--border-color);
  border-radius: var(--radius-md);
}

.catalog-item {
  display: flex;
  flex-direction: column;
  background-color: var(--color-bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  transition: border-color 0.18s ease, box-shadow 0.18s ease, transform 0.18s ease;
}
.catalog-item:hover {
  border-color: var(--color-secondary);
  box-shadow: var(--shadow-md);
  transform: translateY(-3px);
}
.catalog-item[hidden] { display: none; }

.catalog-item-media { position: relative; aspect-ratio: 16 / 10; overflow: hidden; }
.catalog-item-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.35s ease;
}
.catalog-item:hover .catalog-item-media img { transform: scale(1.05); }

/* Favorito (agregado 2026-09-10): esquina opuesta al badge de descuento
   (.badge-discount vive en badges.css, arriba-izquierda) — solo visual,
   estado guardado en localStorage por el script al final de catalogo.php. */
.favorite-btn {
  position: absolute;
  top: 0.6rem;
  right: 0.6rem;
  width: 1.9rem;
  height: 1.9rem;
  border-radius: 50%;
  border: none;
  background-color: rgba(255, 253, 247, 0.85);
  backdrop-filter: blur(4px);
  color: var(--color-text-muted);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: color 0.18s ease, transform 0.18s ease;
}
.favorite-btn:hover { transform: scale(1.08); }
.favorite-btn svg { width: 0.95rem; height: 0.95rem; }
.favorite-btn[aria-pressed="true"] { color: var(--color-danger); }
.favorite-btn[aria-pressed="true"] svg { fill: currentColor; }

/* Botón "Vista previa" en la tarjeta (reemplazó el 2026-09-21 a la tira de
   miniaturas siempre visible que había acá): al pie del media, solo se
   imprime si el producto tiene más de una imagen (`products.image_url` +
   product_images) y abre el modal flotante de fotos — ver
   catalog-preview-modal.css y el script al final de catalogo.php. */

.catalog-item-body {
  flex: 1;
  padding: 0.8rem;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

/* Fila de metadatos de la tarjeta: categoria a la izquierda, stock real a la
   derecha. El stock sale de products.stock, el mismo numero que clampea el
   stepper (ver data-stock en catalogo.php). */
/* Cantidad en stock: último elemento del cuerpo de la tarjeta y pegada al
   borde derecho (el cuerpo es un flex column, así que la alineación
   horizontal la da `align-self`). Antes iba arriba, en la misma línea que la
   categoría. */
.catalog-item-stock {
  align-self: flex-end;
  margin-top: 0.4rem;
  font-family: var(--font-mono);
  font-size: 0.64rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--color-text-soft);
  white-space: nowrap;
}

.catalog-item-stock.is-empty {
  color: var(--color-danger);
}

.category-tag {
  align-self: flex-start;
  font-family: var(--font-mono);
  font-size: 0.64rem;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--color-secondary);
}

.catalog-item-body h4 {
  font-family: var(--font-display);
  font-size: 0.98rem;
  line-height: 1.25;
  font-weight: 600;
  color: var(--color-text-main);
  margin: 0;
}

.catalog-item-sci {
  font-style: italic;
  font-size: 0.76rem;
  color: var(--color-text-soft);
  margin: 0;
}

.catalog-item-desc {
  font-size: 0.78rem;
  line-height: 1.45;
  color: var(--color-text-muted);
  margin: 0.1rem 0 0.2rem;
  /* Tope de 2 líneas: con la tarjeta angosta, una descripción larga hacía
     crecer la fila entera. El texto completo sigue en la BD. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}

/* --------------------------------------------------------------------------
   Selector de tamaño
   -------------------------------------------------------------------------- */
.catalog-item-sizes {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

.size-chip {
  padding: 0.28rem 0.55rem;
  border-radius: var(--radius-sm);
  border: 1.5px solid var(--border-color);
  background: transparent;
  font-size: 0.72rem;
  font-weight: 500;
  color: var(--color-text-main);
  cursor: pointer;
  transition: border-color 0.18s ease, background-color 0.18s ease, color 0.18s ease;
}
.size-chip:hover { border-color: var(--color-accent); }
.size-chip[aria-pressed="true"] {
  background-color: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-text-light);
}
/* Presentación agotada (product_sizes.stock = 0): se puede seguir
   eligiendo —muestra "Cant: 0" y "Sin stock"—, pero se lee tachada para
   que se note antes de tocarla. */
.size-chip.is-out-of-stock {
  text-decoration: line-through;
  opacity: 0.6;
}

/* --------------------------------------------------------------------------
   Selector de color (opcional — solo en los artículos que lo declaran,
   p. ej. color de maceta. No todos los .catalog-item lo tienen.)
   -------------------------------------------------------------------------- */
.catalog-item-colors {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.catalog-item-colors .option-label {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-soft);
}

.color-swatches {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
}

/* El color en sí llega por variable inline (style="--swatch-color: #...")
   para no tener que crear una clase por color en el CSS. */
.color-swatch {
  width: 1.35rem;
  height: 1.35rem;
  border-radius: 50%;
  border: 2px solid var(--border-color);
  background-color: var(--swatch-color);
  padding: 0;
  cursor: pointer;
  transition: border-color 0.18s ease, transform 0.18s ease, box-shadow 0.18s ease;
}
.color-swatch:hover { transform: scale(1.08); }
.color-swatch[aria-pressed="true"] {
  border-color: var(--color-bg-card);
  box-shadow: 0 0 0 2px var(--color-accent);
}

/* --------------------------------------------------------------------------
   Cantidad + precio + agregar
   -------------------------------------------------------------------------- */
.catalog-item-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.4rem 0.5rem;
  margin-top: auto;
  padding-top: 0.45rem;
}

.qty-stepper {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  border: 1.5px solid var(--border-color);
  border-radius: var(--radius-sm);
  padding: 0.1rem 0.3rem;
}

.qty-btn {
  width: 1.45rem;
  height: 1.45rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  font-size: 1rem;
  line-height: 1;
  color: var(--color-text-main);
  cursor: pointer;
  transition: background-color 0.18s ease, color 0.18s ease;
}
.qty-btn:hover { background-color: var(--color-bg-alt); color: var(--color-accent); }
.qty-btn:disabled { opacity: 0.4; cursor: not-allowed; background: none; color: var(--color-text-main); }

.qty-value {
  width: 2rem;
  min-width: 1rem;
  text-align: center;
  font-family: var(--font-mono);
  /* 16px en mobile: con menos, iOS hace zoom al enfocar el campo y la
     página queda corrida de costado. Desde 700px vuelve a 0.8rem. */
  font-size: 1rem;
  border: none;
  background: none;
  color: var(--color-text-main);
  padding: 0;
  -moz-appearance: textfield;
}
.qty-value::-webkit-outer-spin-button,
.qty-value::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.qty-value:disabled { opacity: 0.4; }
.qty-value:focus { outline: none; color: var(--color-accent); }

.catalog-item-price {
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 600;
  color: var(--color-primary);
  text-align: right;
}

/* Precio tachado "antes de descuento" (agregado 2026-09-10): solo aparece
   en artículos con .badge-discount / data-discount — ver updatePrice() en
   el script de catalogo.php, que lo calcula a partir del % de descuento. */
.price-was {
  display: block;
  font-family: var(--font-body);
  font-size: 0.68rem;
  font-weight: 500;
  color: var(--color-text-soft);
  text-decoration: line-through;
}
.price-was:empty { display: none; }

/* Producto agotado — mismo estado que pinta el botón .btn-sold-out (ver
   buttons.css): con stock 0 el nombre y el precio también van tachados en
   rojo, para que la tarjeta se lea como "no está" sin tener que llegar al
   botón del final. La clase la agrega el script de catalogo.php al leer
   data-stock, en el mismo bloque que deshabilita stepper y botón. */
.catalog-item.is-sold-out h4,
.catalog-item.is-sold-out .catalog-item-price {
  color: var(--color-danger);
  text-decoration: line-through;
  text-decoration-thickness: 2px;
}
/* El "antes de descuento" ya viene tachado en gris por .price-was; el
   tachado del padre se pinta igual encima (text-decoration no se puede
   cancelar desde un hijo) y quedaba doble línea sobre un precio que, sin
   stock, no dice nada. */
.catalog-item.is-sold-out .price-was { display: none; }

/* El botón también baja de escala: con la tarjeta angosta, el tamaño de
   buttons.css se comía media tarjeta. */
.catalog-item .btn-block {
  margin-top: 0.5rem;
  padding: 0.55rem 0.75rem;
  font-size: 0.76rem;
}

/* --------------------------------------------------------------------------
   Desde tablet: la cantidad de columnas la decide el ancho disponible, no un
   número fijo — `auto-fill` suma una columna cuando entra, sin necesidad de
   un breakpoint por cada salto. Con el contenedor de 1180px de base.css: 2
   columnas a 640px, 3 desde ~740px, y 4 en escritorio (1180px menos el
   sidebar de 15.5rem deja 904px de grilla).

   12rem (192px) es el piso, y está medido: por debajo de eso el stepper y el
   precio del footer dejan de convivir en la misma fila. No subirlo a 13rem
   sin remedir — con ese valor, entre 980px y ~1030px de viewport la grilla
   cae a 2 columnas (ahí antes había 3).
   -------------------------------------------------------------------------- */
@media (min-width: 640px) {
  .catalog-grid {
    grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
    gap: 1.25rem;
  }
}

/* --------------------------------------------------------------------------
   Desde escritorio (980px, breakpoint dominante del sitio)
   -------------------------------------------------------------------------- */
@media (min-width: 980px) {
  .catalog-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1.5rem;
  }
  .catalog-head h1 { margin-bottom: 0; }

  .catalog-filters-toggle { display: none; }

  .catalog-layout {
    flex-direction: row;
    align-items: flex-start;
  }

  .catalog-sidebar {
    flex: none;
    width: 15.5rem;
    position: sticky;
    top: 6.5rem; /* debajo de .site-header sticky (ver nav.css) */
  }
  .catalog-sidebar[hidden] { display: flex; } /* en escritorio el toggle mobile no aplica */

  /* `min-width: 0` para que el flex item no se niegue a achicarse por debajo
     del contenido de la grilla (si no, las columnas se desbordan del layout). */
  .catalog-grid {
    flex: 1;
    min-width: 0;
  }

  .catalog-item-body { padding: 0.9rem; gap: 0.35rem; }
}

/* Campos de formulario: vuelven a su tamaño de escritorio (ver el
   comentario de 16px en mobile más arriba). */
@media (min-width: 700px) {
  .catalog-sort select { font-size: 0.82rem; }
  .catalog-search-bar input { font-size: 0.85rem; }
  .price-range-field input { font-size: 0.85rem; }
  .qty-value { width: 1.6rem; font-size: 0.8rem; }
}
