/* Escala — Page components */ const { useState: useStateP, useEffect: useEffectP, useMemo: useMemoP } = React; // ===================== HOME ===================== function HomePage({ navigate }) { const products = window.ESCALA_DATA.products; return (
{/* HERO with aurora */}

SS26 · Climbing essentials

Tu segunda
muda de piel.

Cuatro cortes. Dos colores. Un bordado vertical que cambia de color según quién eres en la pared.

{/* Marquee */}
ENVÍO GRATIS > 60€· DEVOLUCIÓN 30 DÍAS· HECHO EN PORTUGAL· 92% POLIÉSTER RECICLADO· PAGO SEGURO STRIPE· ENVÍO GRATIS > 60€· DEVOLUCIÓN 30 DÍAS· HECHO EN PORTUGAL· 92% POLIÉSTER RECICLADO· PAGO SEGURO STRIPE·
{/* Editorial collage grid — clickable, lleva al PDP */}

El catálogo

Cuatro camisetas.
Cero ruido.

{/* Tile 1 — large feature, T-01 */} navigate('/product/' + products[0].slug)}>
01 · {products[0].name}

{products[0].type.split('·')[1]?.trim() || products[0].type}

{/* Tile 2 — tall, T-02 */} navigate('/product/' + products[1].slug)}>
02 · {products[1].name}

{products[1].type.split('·')[1]?.trim() || products[1].type}

{/* Tile 3 — wide, T-03 */} navigate('/product/' + products[2].slug)}>
03 · {products[2].name}

{products[2].type.split('·')[1]?.trim() || products[2].type}

{/* Tile 4 — square, T-04 */} navigate('/product/' + products[3].slug)}>
04 · {products[3].name}

{products[3].type.split('·')[1]?.trim() || products[3].type}

{/* Editorial split */}

Construcción

Pensada para moverse contigo.

Tejido técnico de doble cara, costuras planas, secado rápido. Y un detalle: un bordado vertical en cuatro colores — tú eliges el que te define en la pared.

{[ ['128 g', 'Peso talla M'], ['92%', 'Material reciclado'], ['30 días','Devolución gratis'], ['Stripe', 'Pago protegido'], ].map(([k, v]) => (
{k}
{v}
))}
); } // ===================== SHOP ===================== function ShopPage({ navigate, queryStr }) { const all = window.ESCALA_DATA.products; const params = new URLSearchParams(queryStr || ''); const [color, setColor] = useStateP(params.get('color') || 'all'); const [sort, setSort] = useStateP(params.get('sort') || 'featured'); const [tag, setTag] = useStateP(params.get('tag') || 'all'); // all | new | best const [priceMax, setPriceMax] = useStateP(50); const items = useMemoP(() => { let r = all.slice(); if (color !== 'all') r = r.filter(p => p.colors.includes(color)); if (tag === 'new') r = r.filter(p => p.newIn); if (tag === 'best') r = r.filter(p => p.bestseller); r = r.filter(p => p.price <= priceMax); if (sort === 'price-asc') r.sort((a,b) => a.price - b.price); if (sort === 'price-desc') r.sort((a,b) => b.price - a.price); if (sort === 'new') r.sort((a,b) => Number(b.newIn) - Number(a.newIn)); return r; }, [all, color, sort, tag, priceMax]); return (

Catálogo · {items.length} productos

Tienda

{items.map(p => ( navigate('/product/' + p.slug)}/> ))}
{items.length === 0 && (

Sin resultados con esos filtros.

)}
); } // ===================== PRODUCT DETAIL ===================== function ProductPage({ navigate, slug, openCart }) { const product = window.ESCALA_DATA.products.find(p => p.slug === slug); const [color, setColor] = useStateP('white'); const [line, setLine] = useStateP(product?.embroideryColors[0]?.id); const [size, setSize] = useStateP('M'); const [imgIdx, setImgIdx] = useStateP(0); const [added, setAdded] = useStateP(false); if (!product) return

Producto no encontrado.

; const lineObj = product.embroideryColors.find(l => l.id === line); const onAdd = () => { window.ESCALA_CART.add({ productId: product.id, productName: product.name, color, line, lineLabel: lineObj.name, size, qty: 1, price: product.price, image: product.images[0], }); setAdded(true); setTimeout(() => { setAdded(false); openCart(); }, 600); }; return (
{/* Gallery */}
{product.images[imgIdx] ? {product.name} :
{product.name} · {color}
}
{product.images.map((src, i) => ( ))}
{/* Info */}

{product.type}

{product.name}

{window.ESCALA_FORMAT(product.price)}

{product.description}

{/* Color */}
Color {color === 'white' ? 'Blanco' : 'Negro'}
{product.colors.map(c => (
{/* Color del bordado */}
Color del bordado {lineObj?.name}
{product.embroideryColors.map(l => (
{/* Talla */}
{product.sizes.map(s => ( ))}
Envío gratis > 60€ · Devolución 30 días
{/* Specs */}
{Object.entries(product.specs).map(([k, v]) => (
{k} {v}
))}
); } Object.assign(window, { HomePage, ShopPage, ProductPage });