Motionstead

The course shelf

Choose a practice worth returning to.

Each course is a focused, practical invitation to think more clearly and coach with more intention.

View fallows

`; document.getElementById('site-header').innerHTML = headerHTML; document.getElementById('site-footer').innerHTML = footerHTML; })(); const state = {items:[],filtered:[],page:1,perPage:6}; const getJSON = (key,fallback) => {try{return JSON.parse(localStorage.getItem(key))||fallback}catch{return fallback}}; const setJSON = (key,val) => localStorage.setItem(key,JSON.stringify(val)); const favorites = getJSON('motionstead-favorites',[]); const cart = getJSON('motionstead-cart',[]); async function loadCatalog(){ try { const res = await fetch('./catalog.json'); state.items = await res.json(); } catch(e){ state.items = [{"id":"c01","title":"Foundations of Movement","category":"Movement Foundations","level":"Beginner","format":"Online","duration":"6 weeks","price":890,"description":"Establish core principles of grounded training and body awareness.","outcomes":["Build safe movement patterns","Develop proprioception","Understand load management"],"accent":"Foundations"},{"id":"c02","title":"Advanced Programming","category":"Programming","level":"Advanced","format":"Hybrid","duration":"8 weeks","price":1290,"description":"Design progressive training cycles for diverse populations.","outcomes":["Create periodized plans","Manage fatigue markers","Optimize progression rates"],"accent":"Programming"}]; } buildCategoryOptions(); filterAndRender(); } function buildCategoryOptions(){ const select = document.getElementById('catalog-category'); const cats = [...new Set(state.items.map(i => i.category))].sort(); cats.forEach(cat => { const opt = document.createElement('option'); opt.value = cat; opt.textContent = cat; select.appendChild(opt); }); } function filterAndRender(){ const q = (document.getElementById('catalog-search').value || '').toLowerCase(); const cat = document.getElementById('catalog-category').value; state.filtered = state.items.filter(item => { const matchQ = !q || item.title.toLowerCase().includes(q) || item.description.toLowerCase().includes(q); const matchCat = cat === 'all' || item.category === cat; return matchQ && matchCat; }); state.page = 1; renderGrid(); } function renderGrid(){ const grid = document.getElementById('catalog-grid'); grid.innerHTML = ''; const start = (state.page-1)*state.perPage; const slice = state.filtered.slice(start, start+state.perPage); const countEl = document.getElementById('catalog-count'); countEl.textContent = `${state.filtered.length} course${state.filtered.length===1?'':'s'} available`; slice.forEach(item => { const isFav = favorites.includes(item.id); const card = document.createElement('div'); card.className = `dd23l border border-[#d8c4ae] bg-[#f4ede3] rounded-3xl p-6 flex flex-col`; card.innerHTML = `
${item.accent}

${item.title}

${item.category} · ${item.level}
${item.format} · ${item.duration}
$${item.price}
`; grid.appendChild(card); }); addCardListeners(); renderPagination(); } function addCardListeners(){ document.querySelectorAll('[data-fav]').forEach(btn => { btn.onclick = () => { const id = btn.dataset.fav; const idx = favorites.indexOf(id); if(idx > -1) favorites.splice(idx,1); else favorites.push(id); setJSON('motionstead-favorites',favorites); filterAndRender(); }; }); document.querySelectorAll('[data-detail]').forEach(btn => { btn.onclick = () => showModal(btn.dataset.detail); }); document.querySelectorAll('[data-cart]').forEach(btn => { btn.onclick = () => { const id = btn.dataset.cart; const existing = cart.findIndex(x => x.id === id); if(existing > -1) cart[existing].quantity++; else cart.push({id, quantity:1}); setJSON('motionstead-cart',cart); btn.textContent = 'Added'; setTimeout(()=>{btn.textContent='Add to cart';},1200); }; }); } function renderPagination(){ const pag = document.getElementById('pagination'); pag.innerHTML = ''; const pages = Math.ceil(state.filtered.length / state.perPage); for(let i=1; i<=pages; i++){ const b = document.createElement('button'); b.className = `px-4 py-2 border rounded-full text-sm font-semibold ${i===state.page ? 'bg-[#5b3a29] text-[#fffaf3] border-[#5b3a29]' : 'border-[#d8c4ae]'}`; b.textContent = i; b.onclick = () => {state.page=i; renderGrid();}; pag.appendChild(b); } } function showModal(id){ const item = state.items.find(x => x.id === id); if(!item) return; const modal = document.getElementById('course-modal'); const detail = document.getElementById('course-detail'); let html = `

${item.title}

`; html += `
${item.category} · ${item.level} · ${item.format}
`; html += `
${item.description}
`; html += ``; html += `
Add to cart — $${item.price}Ask a coach
`; detail.innerHTML = html; modal.classList.remove('hidden'); modal.classList.add('flex'); modal.querySelector('[data-close-course]').onclick = () => { modal.classList.remove('flex'); modal.classList.add('hidden'); }; } function initFilters(){ document.getElementById('catalog-search').oninput = filterAndRender; document.getElementById('catalog-category').onchange = filterAndRender; } function initHeaderScripts(){ const mobileBtn = document.querySelector('[data-menu-toggle]'); const mobileNav = document.querySelector('[data-mobile-menu]'); if(mobileBtn && mobileNav){ mobileBtn.onclick = () => mobileNav.classList.toggle('hidden'); } document.querySelectorAll('[data-auth]').forEach(b => { b.onclick = () => { document.querySelector('[data-auth-modal]').classList.remove('hidden'); document.querySelector('[data-auth-modal]').classList.add('flex'); }; }); const authModal = document.querySelector('[data-auth-modal]'); if(authModal){ authModal.onclick = (e) => { if(e.target===authModal) authModal.classList.add('hidden'); }; const closeBtn = authModal.querySelector('[data-modal-close]'); if(closeBtn) closeBtn.onclick = () => authModal.classList.add('hidden'); } const themeBtn = document.querySelector('[data-theme-toggle]'); if(themeBtn){ themeBtn.onclick = () => { document.body.classList.toggle('bg-[#2f2119]'); document.body.classList.toggle('text-[#f4ede3]'); }; } } function initFooterScripts(){ const banner = document.querySelector('[data-cookie-banner]'); const close = document.querySelector('[data-cookie-close]'); if(banner && close){ const key = 'motionstead-cookie-consent'; if(!localStorage.getItem(key)) banner.style.display = 'flex'; close.onclick = () => { localStorage.setItem(key,'true'); banner.style.display = 'none'; }; } } window.onload = async () => { initFilters(); await loadCatalog(); initHeaderScripts(); initFooterScripts(); };