View cart
The catalog
Courses for a practiced eye.
Compare concise introductions, studio intensives, and archive-led studies. Each listing explains its rhythm, materials, and intended outcome.
Loading the botanical catalog…
The catalog
Compare concise introductions, studio intensives, and archive-led studies. Each listing explains its rhythm, materials, and intended outcome.
Loading the botanical catalog…
${esc(x.category)} · ${esc(x.level)}
${esc(x.summary)}
$${x.price.toFixed(2)} · ${esc(x.duration)}
${esc(x.description)}
Botanical focus: ${esc(x.botanicalFocus)}
Instructor: ${esc(x.instructor)} · Format: ${esc(x.format)}
${x.materials.map(esc).join(" · ")}
`;document.querySelector("#detail-modal").classList.replace("hidden","flex");} document.addEventListener("click",e=>{const d=e.target.closest("[data-detail]"),f=e.target.closest("[data-fav]"),c=e.target.closest("[data-cart]"),p=e.target.closest("[data-page]");if(d)openDetail(d.dataset.detail);if(f){let a=getFav();a=a.includes(f.dataset.fav)?a.filter(id=>id!==f.dataset.fav):[...a,f.dataset.fav];localStorage.setItem(favKey,JSON.stringify(a));render()}if(c){const cart=JSON.parse(localStorage.getItem(cartKey)||"{}");cart[c.dataset.cart]=(cart[c.dataset.cart]||0)+1;localStorage.setItem(cartKey,JSON.stringify(cart));document.querySelector("#catalog-status").textContent="Course added to your cart.";}if(p){e.preventDefault();state.page=Number(p.dataset.page);render()}}); document.querySelector("#close-detail").onclick=()=>document.querySelector("#detail-modal").classList.replace("flex","hidden"); fetch("./catalog.json").then(r=>r.json()).then(data=>{state.items=data;const cats=new Set(),levs=new Set();data.forEach(x=>{cats.add(x.category);levs.add(x.level);});const catSel=document.querySelector("#category"),levSel=document.querySelector("#level");cats.forEach(c=>catSel.innerHTML+=``);levs.forEach(l=>levSel.innerHTML+=``);["#search","#category","#level"].forEach(sel=>document.querySelector(sel).oninput=()=>{state.page=1;render()});render();}).catch(()=>{document.querySelector("#catalog-status").textContent="Catalog data unavailable.";}); const nav=document.querySelector("#main-nav"),toggle=document.querySelector("#mobile-menu-toggle"),auth=document.querySelector("#auth-modal");if(toggle){toggle.onclick=()=>{const open=nav.classList.toggle("hidden");toggle.setAttribute("aria-expanded",String(!open));};}if(document.querySelector("#login-open")){document.querySelector("#login-open").onclick=e=>{e.preventDefault();document.querySelector("#auth-title").textContent="Log in to your studio space";auth.classList.replace("hidden","flex")};}if(document.querySelector("#register-open")){document.querySelector("#register-open").onclick=e=>{e.preventDefault();document.querySelector("#auth-title").textContent="Register your interest";auth.classList.replace("hidden","flex")};}if(document.querySelector("#auth-close")){document.querySelector("#auth-close").onclick=()=>auth.classList.replace("flex","hidden");}if(document.querySelector("#theme-toggle")){document.querySelector("#theme-toggle").onclick=()=>{const light=document.body.classList.toggle("bg-[#F7F2E8]");document.body.classList.toggle("text-[#071426]",light);localStorage.setItem("swiftmarkTheme",light?"light":"dark")};}if(localStorage.getItem("swiftmarkTheme")==="light")document.body.classList.add("bg-[#F7F2E8]","text-[#071426]");const banner=document.querySelector("#cookie-banner");if(localStorage.getItem("swiftmarkCookieConsent")==="accepted"&&banner)banner.remove();else if(document.querySelector("#cookie-close")){document.querySelector("#cookie-close").onclick=()=>{localStorage.setItem("swiftmarkCookieConsent","accepted");if(banner)banner.remove()};}