// Theme cycle: dark → light → forest → coffee (function() { const themes = ['dark', 'light', 'forest', 'coffee']; const icons = { dark: '🌙', light: '☀️', forest: '🌿', coffee: '☕' }; function getStored() { try { return localStorage.getItem('kp-theme'); } catch(e) { return null; } } function setStored(theme) { try { localStorage.setItem('kp-theme', theme); } catch(e) {} } function applyTheme(theme) { document.documentElement.setAttribute('data-theme', theme); setStored(theme); var btn = document.getElementById('theme-toggle'); if (btn) btn.textContent = icons[theme] || '🌙'; } // Init: stored preference, then data-theme attr, then default dark var stored = getStored(); var current = stored || document.documentElement.getAttribute('data-theme') || 'dark'; if (themes.indexOf(current) === -1) current = 'dark'; applyTheme(current); // Toggle document.getElementById('theme-toggle').addEventListener('click', function() { var idx = themes.indexOf(document.documentElement.getAttribute('data-theme')); var next = themes[(idx < 0 ? 0 : idx + 1) % themes.length]; applyTheme(next); }); })(); // Mobile nav toggle document.getElementById('nav-toggle').addEventListener('click', function() { var menu = document.getElementById('nav-menu'); this.classList.toggle('is-active'); menu.classList.toggle('is-active'); }); // Contact form - sends to backend API var form = document.getElementById('contact-form'); if (form) { form.addEventListener('submit', function(e) { e.preventDefault(); var status = document.getElementById('form-status'); var submitBtn = form.querySelector('button[type="submit"]'); var originalBtnText = submitBtn.textContent; // Collect form data var formData = new FormData(form); var data = { name: formData.get('name'), email: formData.get('email'), service: formData.get('service'), message: formData.get('message') }; // Honeypot for spam var honeypot = formData.get('website') || formData.get('url') || formData.get('honey'); if (honeypot) { // Bot detected - pretend success status.className = 'notification is-success'; status.textContent = 'Message received. We\'ll respond within 48 hours.'; status.style.display = 'block'; form.reset(); return; } // Disable button and show sending state submitBtn.disabled = true; submitBtn.textContent = 'Sending...'; status.style.display = 'none'; // Send to API fetch('/api/contact', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }) .then(function(response) { return response.json(); }) .then(function(result) { if (result.success) { status.className = 'notification is-success'; status.textContent = result.message || 'Message received. We\'ll respond within 48 hours.'; status.style.display = 'block'; form.reset(); } else { throw new Error(result.error || 'Failed to send message'); } }) .catch(function(error) { status.className = 'notification is-danger'; status.textContent = error.message || 'Failed to send message. Please try again.'; status.style.display = 'block'; }) .finally(function() { submitBtn.disabled = false; submitBtn.textContent = originalBtnText; }); }); }