Spaces:
Running
Running
| // Simple color and theme management | |
| (function () { | |
| const config = { | |
| primary: "gray", | |
| secondary: "slate", | |
| theme: "light", // light | dark | |
| }; | |
| function applyTheme(theme) { | |
| const root = document.documentElement; | |
| if (theme === "dark") { | |
| root.classList.add("dark"); | |
| } else { | |
| root.classList.remove("dark"); | |
| } | |
| } | |
| // Theme toggle | |
| const toggle = document.getElementById("themeToggle"); | |
| if (toggle) { | |
| toggle.addEventListener("click", () => { | |
| const isDark = document.documentElement.classList.toggle("dark"); | |
| const next = isDark ? "dark" : "light"; | |
| try { | |
| localStorage.setItem("theme", next); | |
| } catch (_) {} | |
| }); | |
| } | |
| // Restore saved theme | |
| try { | |
| const saved = localStorage.getItem("theme"); | |
| if (saved === "dark" || saved === "light") { | |
| applyTheme(saved); | |
| } else { | |
| applyTheme(config.theme); | |
| } | |
| } catch (_) { | |
| applyTheme(config.theme); | |
| } | |
| // Device tilt effect (hero) | |
| const device = document.getElementById("device3d"); | |
| if (device) { | |
| let raf = null; | |
| let rx = 0, ry = 0, tx = 0, ty = 0; | |
| const max = 8; | |
| const onMove = (e) => { | |
| const rect = device.getBoundingClientRect(); | |
| const cx = rect.left + rect.width / 2; | |
| const cy = rect.top + rect.height / 2; | |
| const dx = (e.clientX - cx) / (rect.width / 2); | |
| const dy = (e.clientY - cy) / (rect.height / 2); | |
| tx = Math.max(-1, Math.min(1, dx)); | |
| ty = Math.max(-1, Math.min(1, dy)); | |
| ry = tx * max; | |
| rx = -ty * max; | |
| if (!raf) { | |
| raf = requestAnimationFrame(() => { | |
| device.style.transform = `perspective(1000px) rotateX(${rx.toFixed(2)}deg) rotateY(${ry.toFixed(2)}deg) translateZ(0)`; | |
| raf = null; | |
| }); | |
| } | |
| }; | |
| const reset = () => { | |
| device.style.transform = "perspective(1000px) rotateX(0deg) rotateY(0deg)"; | |
| }; | |
| window.addEventListener("mousemove", onMove, { passive: true }); | |
| window.addEventListener("mouseleave", reset); | |
| window.addEventListener("touchmove", (e) => { | |
| if (!e.touches || e.touches.length === 0) return; | |
| const t = e.touches[0]; | |
| onMove({ clientX: t.clientX, clientY: t.clientY }); | |
| }, { passive: true }); | |
| window.addEventListener("touchend", reset); | |
| } | |
| // Optional: uncomment to log config or expose it for debugging | |
| // console.log("iPhone 1 Landing — Config:", config); | |
| })(); |