About ClearGate

ClearGate Furniture Restoration Academy is dedicated to teaching practical skills with elegant simplicity. Our courses emphasize safety, repeatable processes, and attention to detail.

Sunlit vintage woodworking bench with classic hand tools neatly arranged

Mission

We exist to conserve furniture heritage through disciplined instruction and hands-on mentorship. Our mission is to make restoration safe, methodical, and auditable.

  • Safety-first practices and standards
  • Repeatable processes and checklists
  • Respect for materials and provenance

Teaching Philosophy

Structured Minimalism

Clear goals, small steps, clean rigs. We avoid noise to keep attention on craft.

Evidence-Based

Every method cites sources and is verified by instructor demos and student trials.

Feedback Loops

Rapid critique with rubrics and annotated photos accelerates learning.

Our Principles

Milestones

Founding

Built by restorers and educators with decades of combined shop experience.

Curriculum Review

Each syllabus is audited for safety, sequence, and outcome validity.

Certification

Earn a course certificate by passing practical checkpoints.

Hands applying shellac on an oak drawer front showing detailed wood grain and glossy finish

Team Values

Transparency

We continuously track learning quality. View our live metrics.

Contact

Email: [email protected]

Phone: +1 (332) 614-9072

.round(percent)} percent`); }; const rotateTip = () => { const tipEl = qs('#warmupTip'); const idx = Math.floor((duration - remaining) / 20) % tips.length; tipEl.textContent = tips[idx]; ttsSpeak(tips[idx]); }; const tick = () => { if (remaining > 0) { remaining -= 1; if (remaining % 20 === 0) rotateTip(); updateUI(); } else { stop(); showToast('Warm-up complete', 'success'); ttsSpeak('Warm up complete. You are ready.'); } }; const startMetronome = () => { stopMetronome(); metronomeId = setInterval(() => beep(), 2000); }; const stopMetronome = () => { if (metronomeId) { clearInterval(metronomeId); metronomeId = null; } }; const start = () => { if (timerId) { pause(); return; } timerId = setInterval(tick, 1000); tipId = setInterval(rotateTip, 20000); rotateTip(); qs('#startWarmup').textContent = 'Pause'; showToast('Warm-up started'); if (qs('#beepToggle')?.checked) startMetronome(); ttsSpeak('Starting two minute warm up. Breathe in for four, out for six.'); }; const pause = () => { if (timerId) { clearInterval(timerId); timerId = null; } if (tipId) { clearInterval(tipId); tipId = null; } stopMetronome(); qs('#startWarmup').textContent = 'Resume'; showToast('Paused'); }; const stop = () => { if (timerId) { clearInterval(timerId); timerId = null; } if (tipId) { clearInterval(tipId); tipId = null; } stopMetronome(); qs('#startWarmup').textContent = 'Start'; }; const reset = () => { stop(); remaining = duration; updateUI(); qs('#warmupTip').textContent = 'Tip: Breathe in through the nose for 4, out for 6.'; showToast('Reset'); if (speaking && 'speechSynthesis' in window) speechSynthesis.cancel(); }; const init = () => { remaining = duration; updateUI(); qs('#startWarmup').addEventListener('click', start); qs('#resetWarmup').addEventListener('click', reset); qs('#beepToggle')?.addEventListener('change', (e) => { if (e.target.checked && timerId) startMetronome(); else stopMetronome(); }); const stored = consent.get(); const ttsDefault = stored?.tts ?? false; const ttsToggle = qs('#ttsToggle'); if (ttsToggle) ttsToggle.checked = ttsDefault; }; return { init, reset }; })(); const injectPartials = async () => { try { const [h, f] = await Promise.allSettled([fetch('./header.html'), fetch('./footer.html')]); if (h.status === 'fulfilled' && h.value.ok) { const text = await h.value.text(); document.querySelector('header').innerHTML = text; } if (f.status === 'fulfilled' && f.value.ok) { const text = await f.value.text(); document.querySelector('footer').innerHTML = text; } } catch {} initGlobalUI(); }; const initGlobalUI = () => { theme.load(); const openThemeBtn = qs('#openTheme'); const themeModal = qs('#themeModal'); openThemeBtn?.addEventListener('click', () => themeModal?.showModal()); qs('#closeTheme')?.addEventListener('click', () => themeModal?.close()); qs('#closeThemeBottom')?.addEventListener('click', () => themeModal?.close()); qs('#themeForm')?.addEventListener('change', (e) => { const v = new FormData(e.currentTarget).get('theme'); theme.apply(v); }); qs('#fabTheme')?.addEventListener('click', () => theme.toggle()); const loginModal = qs('#loginModal'); qs('#openLogin')?.addEventListener('click', () => loginModal?.showModal()); qs('#closeLogin')?.addEventListener('click', () => loginModal?.close()); const registerModal = qs('#registerModal'); qs('#openRegister')?.addEventListener('click', () => registerModal?.showModal()); qs('#closeRegister')?.addEventListener('click', () => registerModal?.close()); const cmdModal = qs('#cmdModal'); qs('#openCmd')?.addEventListener('click', () => { cmdModal?.showModal(); qs('#cmdInput')?.focus(); }); qsa('dialog').forEach(d => { d.addEventListener('click', (e) => { const r = d.getBoundingClientRect(); const inDialog = r.top <= e.clientY && e.clientY <= r.top + r.height && r.left <= e.clientX && e.clientX <= r.left + r.width; if (!inDialog) d.close(); }); d.addEventListener('cancel', (e) => { e.preventDefault(); d.close(); }); }); consent.ensureBanner(); qs('#cookieAccept')?.addEventListener('click', () => { consent.save({ essential: true, analytics: true, tts: true }); consent.ensureBanner(); showToast('Preferences saved', 'success'); }); qs('#cookieReject')?.addEventListener('click', () => { consent.save({ essential: true, analytics: false, tts: false }); consent.ensureBanner(); showToast('Only essential cookies enabled'); }); qs('#cookieSettings')?.addEventListener('click', () => { const c = consent.get() || { essential: true, analytics: false, tts: false }; qs('#consentAnalytics').checked = !!c.analytics; qs('#consentTTS').checked = !!c.tts; qs('#cookieModal').showModal(); }); qs('#closeCookieModal')?.addEventListener('click', () => qs('#cookieModal').close()); qs('#saveConsent')?.addEventListener('click', () => { const analytics = qs('#consentAnalytics').checked; const tts = qs('#consentTTS').checked; consent.save({ essential: true, analytics, tts }); consent.ensureBanner(); qs('#cookieModal').close(); showToast('Preferences updated', 'success'); }); warmup.init(); qs('#openContact')?.addEventListener('click', () => qs('#contactModal').showModal()); qs('#closeContact')?.addEventListener('click', () => qs('#contactModal').close()); qs('#loginForm')?.addEventListener('submit', (e) => { e.preventDefault(); const data = Object.fromEntries(new FormData(e.currentTarget)); const validEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(data.email); if (!validEmail || (data.password || '').length < 8) { showToast('Check your credentials', 'error'); return; } localStorage.setItem('user', JSON.stringify({ email: data.email })); showToast('Welcome back', 'success'); qs('#loginModal').close(); }); qs('#registerForm')?.addEventListener('submit', (e) => { e.preventDefault(); const fd = new FormData(e.currentTarget); const email = fd.get('email'); const pwd = fd.get('password'); const first = fd.get('first'); const last = fd.get('last'); const ok = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email) && String(pwd).length >= 8 && String(first).trim() && String(last).trim() && qs('#tos').checked; if (!ok) { showToast('Please complete all fields properly', 'error'); return; } localStorage.setItem('user', JSON.stringify({ email, first, last })); showToast('Account created', 'success'); qs('#registerModal').close(); }); qs('#contactForm')?.addEventListener('submit', (e) => { e.preventDefault(); const fd = new FormData(e.currentTarget); const email = fd.get('email'); const name = fd.get('name'); const message = fd.get('message'); const ok = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email) && String(name).trim().length > 1 && String(message).trim().length >= 10; if (!ok) { showToast('Please provide valid contact details', 'error'); return; } showToast('Message sent. We will reply shortly.', 'success'); qs('#contactModal').close(); e.currentTarget.reset(); }); const cmd = qs('#cmdModal'); const input = qs('#cmdInput'); const runCmd = (c) => { if (!c) return; if (c === 'home') location.assign('./index.html'); if (c === 'about') location.assign('./about.html'); if (c === 'theme') theme.toggle(); if (c === 'contact') qs('#contactModal').showModal(); cmd.close(); }; qsa('#cmdList [data-cmd]').forEach(b => b.addEventListener('click', () => runCmd(b.dataset.cmd))); input?.addEventListener('keydown', (e) => { if (e.key === 'Enter') { const v = e.currentTarget.value.trim().toLowerCase(); if (v.includes('home')) runCmd('home'); else if (v.includes('about')) runCmd('about'); else if (v.includes('theme')) runCmd('theme'); else if (v.includes('contact')) runCmd('contact'); else showToast('No match', 'error'); } }); window.addEventListener('keydown', (e) => { if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'k') { e.preventDefault(); qs('#cmdModal')?.showModal(); qs('#cmdInput')?.focus(); } }); }; document.addEventListener('DOMContentLoaded', () => { theme.load(); injectPartials(); });