Card de Producto — Listado de Tienda
Componente de presentación reutilizable para el catálogo de productos. Soporta estado sin imagen, interacción hover y acción de carrito.
/shop) y colecciones. Excluye la página de detalle de producto (PDP).32×32px. Z-index sobre la imagen. Contraste mínimo WCAG AA.1:1 (cuadrado). object-fit: cover. Si la imagen falla o no existe, mostrar placeholder gris (#2e3249) con icono SVG centrado.font-size: 14px, font-weight: 600, máximo 2 líneas con text-overflow: ellipsis.Intl.NumberFormat). font-size: 18px, font-weight: 700, color --accent2. Si hay precio tachado (oferta) mostrarlo en gris a 14px.transform: translateY(-4px), box-shadow: 0 8px 24px rgba(0,0,0,.35). Transición: all 200ms ease. Equivalente :focus-visible para teclado.Nombre muy largo
Nombres de más de 60 caracteres: truncar a 2 líneas con ellipsis. No romper el layout.
Imagen rota (error 404)
Event onError en <img> activa el placeholder gris automáticamente.
Error en API de carrito
Si la llamada falla: botón vuelve a default y se muestra toast de error (no definido en esta spec; ver toast-system).
Precio sin decimales
Intl.NumberFormat con minimumFractionDigits: 0 para precios enteros. Nunca mostrar €20.00 → mostrar €20.
Móvil / touch
El efecto hover no aplica en dispositivos táctiles (@media (hover: none)). El botón conserva tamaño mínimo de 44×44px (touch target WCAG).
Sin logo de marca
Si el logo no está disponible: ocultar el espacio reservado (no placeholder). El nombre del producto asume la identificación.
--accent2 (precio), --surface (fondo card), --border (borde), --text (nombre)toast-system · cart-api · image-optimizerPOST /api/cart/add — body: {"variant_id": string, "qty": 1} — responde 200 o 4xxrole="article" en la card · aria-label en botón con nombre de producto · aria-disabled cuando agotado