const mottos = [ "Good systems should be easy to understand, maintain, and use.", "I would rather do something right the first time than work around it later.", "Knowing how things work underneath makes it easier to solve problems when they break.", "If I have to do something repeatedly, I am probably going to find a way to automate it.", "There is always something new to learn and usually a better way to do something.", ]; const glyphs = "01#@$%&*+<>/\\"; function prefersReducedMotion(): boolean { return window.matchMedia("(prefers-reduced-motion: reduce)").matches; } function initName(): void { const button = document.querySelector("[data-name-play]"); if (!button) return; const original = button.textContent?.trim() || "Owen Rummage"; let timer = 0; button.addEventListener("click", () => { window.clearInterval(timer); if (prefersReducedMotion()) { button.classList.toggle("is-glitched"); return; } let frame = 0; timer = window.setInterval(() => { button.textContent = [...original] .map((letter, index) => { if (letter === " " || index < frame / 2) return letter; return glyphs[Math.floor(Math.random() * glyphs.length)]; }) .join(""); frame += 1; if (frame > original.length * 2) { window.clearInterval(timer); button.textContent = original; } }, 34); }); } function initRoles(): void { document.querySelectorAll("[data-role-play]").forEach((role) => { const pin = role.querySelector("[data-role-pin]"); const toggle = () => { const pinned = role.classList.toggle("is-pinned"); pin?.setAttribute("aria-pressed", String(pinned)); }; role.addEventListener("dblclick", toggle); pin?.addEventListener("click", toggle); }); } function initMotto(): void { const button = document.querySelector("[data-motto-play]"); if (!button) return; let index = 0; button.addEventListener("click", () => { index = (index + 1) % mottos.length; button.classList.remove("is-swapping"); void button.offsetWidth; button.textContent = mottos[index]; button.classList.add("is-swapping"); }); } function initSkillsToggle(): void { const button = document.querySelector("[data-skills-toggle]"); const toolset = document.querySelector("[data-toolset]"); if (!button || !toolset) return; button.addEventListener("click", () => { const expanded = toolset.hasAttribute("data-show-extra"); if (expanded) { toolset.removeAttribute("data-show-extra"); } else { toolset.setAttribute("data-show-extra", ""); } button.setAttribute("aria-expanded", String(!expanded)); button.textContent = expanded ? "Show more" : "Show less"; }); } function celebrate(): void { const layer = document.createElement("div"); layer.className = "play-layer"; layer.setAttribute("aria-hidden", "true"); const count = prefersReducedMotion() ? 8 : 28; for (let i = 0; i < count; i += 1) { const bit = document.createElement("i"); bit.textContent = i % 3 === 0 ? "#" : i % 3 === 1 ? "0" : "1"; bit.style.setProperty("--x", `${Math.random() * 100}vw`); bit.style.setProperty("--delay", `${Math.random() * 0.6}s`); bit.style.setProperty("--drift", `${Math.random() * 80 - 40}px`); layer.appendChild(bit); } document.body.appendChild(layer); window.setTimeout(() => layer.remove(), 2600); } function initSecrets(): void { document .querySelector("[data-home-play]") ?.addEventListener("click", celebrate); const sequence = [ "ArrowUp", "ArrowUp", "ArrowDown", "ArrowDown", "ArrowLeft", "ArrowRight", "ArrowLeft", "ArrowRight", "b", "a", ]; let position = 0; window.addEventListener("keydown", (event) => { position = event.key.toLowerCase() === sequence[position]?.toLowerCase() ? position + 1 : 0; if (position === sequence.length) { celebrate(); position = 0; } }); } function init(): void { initName(); initRoles(); initMotto(); initSkillsToggle(); initSecrets(); } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", init, { once: true }); } else { init(); }