// 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 &&

}
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.
);
}
window.Catalog = Catalog;