diff --git a/src/_includes/footer.njk b/src/_includes/footer.njk index 223f2809..dd813484 100644 --- a/src/_includes/footer.njk +++ b/src/_includes/footer.njk @@ -1,9 +1,18 @@ + + + `; document.body.appendChild(notify); - setTimeout(() => { - notify.style.opacity = '0'; - setTimeout(() => notify.remove(), 500); - }, 4000); + setTimeout(() => { notify.style.opacity = '0'; setTimeout(() => notify.remove(), 500); }, 4000); } /** @@ -81,27 +181,39 @@ function showLevelUpNotification(newLevelIndex) { */ function applyTheme(theme) { const html = document.documentElement; + const heart = document.getElementById('footer-heart'); localStorage.setItem('theme', theme); - html.classList.remove('dark'); - // Clear dynamic styles + html.classList.remove('dark'); const props = ['--bg-page', '--bg-card', '--bg-footer', '--text-main', '--text-muted', '--border-color', '--accent']; props.forEach(p => html.style.removeProperty(p)); if (theme === 'dark') { html.classList.add('dark'); - } else if (theme === 'random') { + if (heart) heart.innerText = '๐Ÿ’œ'; + } + else if (theme === 'random') { const h = Math.floor(Math.random() * 360); html.style.setProperty('--bg-page', `hsl(${h}, 40%, 8%)`); html.style.setProperty('--bg-card', `hsl(${h}, 35%, 12%)`); - html.style.setProperty('--bg-footer', `hsl(${h}, 35%, 15%)`); + html.style.setProperty('--bg-footer', `hsl(${h}, 35%, 10%)`); + html.style.setProperty('--border-color', `hsl(${h}, 30%, 20%)`); html.style.setProperty('--text-main', `hsl(${h}, 20%, 95%)`); + html.style.setProperty('--text-muted', `hsl(${h}, 15%, 60%)`); html.style.setProperty('--accent', `hsl(${(h + 150) % 360}, 80%, 65%)`); + + if (heart) { + const hearts = ['๐Ÿ’š', '๐Ÿ’™', '๐Ÿ’›', '๐Ÿงก', '๐Ÿค', '๐ŸคŽ', '๐Ÿ–ค', '๐Ÿ’Ž', '๐ŸŒˆ', 'โœจ']; + heart.innerText = hearts[Math.floor(Math.random() * hearts.length)]; + } } + else if (heart) { heart.innerText = 'โค๏ธ'; } + updateThemeIcon(theme); } function toggleTheme() { + playSound('click'); const current = localStorage.getItem('theme') || 'light'; const next = current === 'light' ? 'dark' : (current === 'dark' ? 'random' : 'light'); applyTheme(next); @@ -113,105 +225,81 @@ function updateThemeIcon(theme) { } /** - * 4. EASTER EGG TRIGGERS + * 4. EASTER EGG LOGIC */ - -// EGG 1: Surprise Me x5 -> Matrix function scrollToRandomUser() { - // 1. Force the count to increment + playSound('click'); surpriseClickCount++; - console.log("Surprise clicks:", surpriseClickCount); // Debugging line - - // 2. Check threshold if (surpriseClickCount >= 5) { - // Reset immediately so the user can start the next 5-click cycle surpriseClickCount = 0; - - // Attempt level unlock - unlockEgg('matrix'); - - // FORCE start the matrix - initMatrix(); + triggerSecretUnlock('matrix'); } - // Standard card highlight/scroll logic const cards = document.querySelectorAll('.user-card'); if (cards.length === 0) return; - cards.forEach(c => c.classList.remove('highlight-pulse')); const randomCard = cards[Math.floor(Math.random() * cards.length)]; randomCard.scrollIntoView({ behavior: 'smooth', block: 'start' }); randomCard.classList.add('highlight-pulse'); - setTimeout(() => randomCard.classList.remove('highlight-pulse'), 3500); } -// EGG 2: Konami Code -> Barrel Roll const konamiCode = ['arrowup', 'arrowup', 'arrowdown', 'arrowdown', 'arrowleft', 'arrowright', 'arrowleft', 'arrowright', 'b', 'a']; let konamiPosition = 0; window.addEventListener('keydown', (e) => { - const key = e.key.toLowerCase(); + const key = e.key.toLowerCase(); + + // Developer Toggle + if (key === 'd' && e.target.tagName !== 'INPUT') { + const devPanel = document.getElementById('dev-tools'); + if (devPanel) { + const isHidden = devPanel.classList.toggle('hidden'); + playSound(isHidden ? 'click' : 'secret'); + } + return; + } - if (key === konamiCode[konamiPosition]) { - konamiPosition++; - if (konamiPosition === konamiCode.length) { - activateKonami(); - konamiPosition = 0; + // Konami Sequence + if (key === konamiCode[konamiPosition]) { + konamiPosition++; + if (konamiPosition === konamiCode.length) { + triggerSecretUnlock('konami'); + konamiPosition = 0; + } + } else { + konamiPosition = (key === 'arrowup') ? 1 : 0; } - } else { - // Reset, but check if the wrong key was actually the start of a new attempt - konamiPosition = (key === 'arrowup') ? 1 : 0; - } }); function activateKonami() { - // Apply to documentElement (html) so the sticky header spins too - document.documentElement.classList.add('konami-roll'); - - // Call your level up / egg unlock logic here - if (typeof unlockEgg === 'function') unlockEgg('konami'); - - setTimeout(() => { - document.documentElement.classList.remove('konami-roll'); - }, 2000); + playSound('secret'); + document.documentElement.classList.add('konami-roll'); + setTimeout(() => document.documentElement.classList.remove('konami-roll'), 2000); } -// EGG 3: Gravity Glitch -> Build Hash Click function triggerGravity(event) { if (event) event.preventDefault(); - - // Level up! - unlockEgg('gravity'); - - // Immediate feedback: Shake everything + playSound('secret'); document.body.classList.add('glitch-shake'); setTimeout(() => { document.body.classList.remove('glitch-shake'); - - // Target everything that should fall const elements = document.querySelectorAll('.user-card, header, footer, main, h1, #game-stats'); - const viewportHeight = window.innerHeight; - - elements.forEach((el, index) => { - const rect = el.getBoundingClientRect(); - // Calculate a personalized fall distance so they don't all hit at once - const fallDist = viewportHeight - rect.top + (Math.random() * 300 + 100); - const rotation = Math.random() * 90 - 45; // Wider rotation for more "chaos" - + elements.forEach((el) => { + const fallDist = window.innerHeight + 500; + const rotation = Math.random() * 90 - 45; el.style.transition = `transform ${1 + Math.random()}s cubic-bezier(0.47, 0, 0.745, 0.715), opacity 1.5s ease-in`; el.style.transform = `translateY(${fallDist}px) rotate(${rotation}deg)`; el.style.opacity = "0"; el.style.pointerEvents = "none"; }); - // Summon the Reset Button setTimeout(() => { if (!document.getElementById('repair-btn')) { const btn = document.createElement('button'); btn.id = 'repair-btn'; btn.innerHTML = "REPAIR CORE SYSTEM"; - btn.className = "fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-accent text-white px-10 py-5 rounded-full font-black z-[3000] shadow-[0_0_50px_rgba(0,0,0,0.5)] hover:scale-110 transition-all cursor-pointer border-4 border-white animate-pulse"; + btn.className = "fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-accent text-white px-10 py-5 rounded-full font-black z-[3000] shadow-2xl animate-pulse cursor-pointer border-4 border-white"; btn.onclick = () => window.location.reload(); document.body.appendChild(btn); } @@ -220,20 +308,17 @@ function triggerGravity(event) { } /** - * THE MATRIX ENGINE + * 5. MATRIX ENGINE */ function initMatrix() { - // 1. Reset state to ensure clean start matrixActive = true; const overlay = document.getElementById('matrix-overlay'); const canvas = document.getElementById('matrix-canvas'); if (!overlay || !canvas) return; - // 2. Show the overlay overlay.classList.remove('hidden'); overlay.style.display = 'block'; - // 3. Setup Canvas canvas.width = window.innerWidth; canvas.height = window.innerHeight; const ctx = canvas.getContext('2d'); @@ -242,14 +327,8 @@ function initMatrix() { const columns = Math.floor(canvas.width / fontSize); const rainDrops = Array.from({ length: columns }).fill(1); - // 4. Rendering Loop with explicit Kill Switch const render = () => { - if (!matrixActive) { - // Stop the loop entirely - ctx.clearRect(0, 0, canvas.width, canvas.height); - return; - } - + if (!matrixActive) return; ctx.fillStyle = 'rgba(0, 0, 0, 0.05)'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = '#0F0'; @@ -263,55 +342,20 @@ function initMatrix() { } requestAnimationFrame(render); }; - render(); - - // 5. Add Escape Listener window.addEventListener('keydown', handleMatrixEsc); } -// Separate function for the listener so we can remove it properly -function handleMatrixEsc(e) { - if (e.key === 'Escape') { - closeMatrix(); - } -} +function handleMatrixEsc(e) { if (e.key === 'Escape') closeMatrix(); } function closeMatrix() { - // 1. Flip the kill switch matrixActive = false; - - // 2. Hide the UI const overlay = document.getElementById('matrix-overlay'); - if (overlay) { - overlay.classList.add('hidden'); - overlay.style.display = 'none'; - } - - // 3. Clean up the listener to prevent memory leaks + if (overlay) { overlay.classList.add('hidden'); overlay.style.display = 'none'; } window.removeEventListener('keydown', handleMatrixEsc); - - // 4. Reset click counter so they don't get stuck in a loop - surpriseClickCount = 0; } -/** - * 6. INITIALIZATION - */ document.addEventListener('DOMContentLoaded', () => { - // 1. Theme applyTheme(localStorage.getItem('theme') || 'light'); - // 2. Game Stats updateGameUI(); }); - -// Helper for Bio page email copy -function copyToClipboard(text, el) { - navigator.clipboard.writeText(text); - const span = el.querySelector('span:last-child'); - if (span) { - const original = span.innerText; - span.innerText = 'Copied!'; - setTimeout(() => span.innerText = original, 2000); - } -}