Backloom Studio

Welcome to Backloom Studio

Sign-in is a local demonstration and does not transmit credentials.

Contact the studio

The catalog

Choose your next wearable project

Filter by pace, level, and format to find a focused way into painted textiles.

Go to cart View fallows
`; const footerHTML = ``; document.querySelector('header').innerHTML = headerHTML; document.querySelector('footer').innerHTML = footerHTML; window.initSharedUI(); let products = [], filtered = [], page = 1; const perPage = 6; const fallowsKey = 'backloom-fallows', cartKey = 'backloom-cart'; function updateCart(id) { let cart = JSON.parse(localStorage.getItem(cartKey) || '[]'); const idx = cart.findIndex(i => i.id === id); if (idx > -1) cart[idx].quantity++; else cart.push({id, quantity: 1}); localStorage.setItem(cartKey, JSON.stringify(cart)); alert('Added to cart'); } function updateFallows(id) { let f = JSON.parse(localStorage.getItem(fallowsKey) || '[]'); if (!f.includes(id)) f.push(id); localStorage.setItem(fallowsKey, JSON.stringify(f)); alert('Added to Fallows'); } function showModal(product) { const modal = document.querySelector('#product-modal'); const content = document.querySelector('#modal-content'); content.innerHTML = `

${product.title}

${product.category} · ${product.level} · ${product.format} · ${product.duration}

${product.description}

Materials: ${product.materials.join(', ')}

Palette: ${product.palette}

$${product.price.toFixed(2)} ${product.currency}

`; modal.showModal(); modal.querySelectorAll('a').forEach(a => a.addEventListener('click', () => modal.close(), {once:true})); } function render() { const q = document.querySelector('#search').value.toLowerCase(); const c = document.querySelector('#category').value; const l = document.querySelector('#level').value; filtered = products.filter(x => (!q || (x.title + x.description + x.category).toLowerCase().includes(q)) && (!c || x.category === c) && (!l || x.level === l)); const start = (page - 1) * perPage; const items = filtered.slice(start, start + perPage); document.querySelector('#product-grid').innerHTML = items.map(x => `

${x.category} · ${x.level}

${x.title}

${x.description}

$${x.price.toFixed(2)}

Add to cart Track Details
`).join(''); document.querySelector('#pagination').innerHTML = Array.from({length: Math.ceil(filtered.length / perPage)}, (_, i) => `${i+1}`).join(''); document.querySelectorAll('[data-cart]').forEach(el => el.addEventListener('click', e => { e.preventDefault(); updateCart(el.dataset.cart); })); document.querySelectorAll('[data-fallow]').forEach(el => el.addEventListener('click', e => { e.preventDefault(); updateFallows(el.dataset.fallow); })); document.querySelectorAll('[data-detail]').forEach(el => el.addEventListener('click', e => { e.preventDefault(); const p = products.find(pr => pr.id === el.dataset.detail); showModal(p); })); document.querySelectorAll('[data-page]').forEach(el => el.addEventListener('click', e => { e.preventDefault(); page = +el.dataset.page; render(); })); } fetch('./catalog.json').then(r => r.json()).then(d => { products = d; ['category','level'].forEach(k => { [...new Set(d.map(x => x[k]))].forEach(v => document.querySelector('#'+k).insertAdjacentHTML('beforeend', ``)); }); render(); }); document.addEventListener('input', e => { if (e.target.matches('#search,#category,#level')) { page = 1; render(); } });