// Hi-Fi B — Catalog (mosaico assimétrico, lê do Store) function CatalogFilter({ active, onChange, cats }) { return (
{cats.map((c) => ( ))}
); } function ProductCard({ p }) { const [hover, setHover] = useState(false); return ( setHover(true)} onMouseLeave={() => setHover(false)} style={{ position: 'relative', display: 'block', background: 'var(--ink)', border: '3px solid var(--ink)', boxShadow: '6px 6px 0 var(--primary)', overflow: 'hidden', aspectRatio: '1 / 1', transition: 'transform 0.18s, box-shadow 0.18s' }}>
{p.sketch && }
SKETCH / 3D
{p.image && {p.name}}
PEÇA FINAL
{p.badge && (
{p.badge}
)}
{p.categoryLabel}
{p.name}
{p.priceType === 'fixed' ? p.price : 'sob consulta'}
PASSE O MOUSE PARA VER
); } function Catalog() { const [active, setActive] = useState('tudo'); const [products, setProducts] = useState(window.Store.getProducts()); const [cats, setCats] = useState(window.Store.getCategories()); useEffect(() => window.Store.subscribe(() => { setProducts(window.Store.getProducts()); setCats(window.Store.getCategories()); }), []); const filtered = active === 'tudo' ? products : products.filter((p) => p.category === active); const s = window.Store.getSettings(); return (
03 / O Vault

O VAULT.
EDIÇÃO 2026.

Peças prontas e exemplos de personalizações já entregues. Cada uma é única — não imprimimos a mesma duas vezes.
{filtered.map((p) => )}
Mostrando {filtered.length} de {products.length} peças Pedir algo personalizado
); } window.Catalog = Catalog;