From aaeac47a67e62c8fc8c95c24e08a0cd70ec0714c Mon Sep 17 00:00:00 2001 From: John Bampton Date: Mon, 26 Jan 2026 15:33:32 +1000 Subject: [PATCH] fix ups --- src/assets/css/style.css | 274 ++++++++++++++++++++++----------------- src/assets/js/script.js | 147 +++++++++++++-------- 2 files changed, 248 insertions(+), 173 deletions(-) diff --git a/src/assets/css/style.css b/src/assets/css/style.css index 04d2193f..819209de 100644 --- a/src/assets/css/style.css +++ b/src/assets/css/style.css @@ -35,7 +35,7 @@ html, body { } /** - * 2. USER CARDS & BLUE LEGIBILITY + * 2. USER CARDS & LEGIBILITY */ .user-card h2 { color: #1e40af !important; @@ -53,7 +53,7 @@ html, body { } /** - * 3. PILL-SHAPED INTERACTIVES (SKILLS & SURPRISE) + * 3. PILL-SHAPED INTERACTIVES */ .skill-item { position: relative; @@ -80,37 +80,39 @@ html, body { transform: translateY(-3px) scale(1.05); box-shadow: 0 4px 12px rgba(var(--accent-rgb), 0.4); } - -.surprise-btn { - background-color: var(--accent) !important; - color: #ffffff !important; - display: inline-flex !important; - align-items: center; - justify-content: center; - border-radius: 9999px; - font-weight: 900; - box-shadow: 0 4px 20px rgba(var(--accent-rgb), 0.4); - transition: 0.3s; -} - -.surprise-btn:hover { - filter: brightness(1.1); - box-shadow: 0 8px 30px rgba(var(--accent-rgb), 0.6); - transform: translateY(-2px); +/** + * FIXED SURPRISE BUTTON & SKILL SHIMMER + */ +.surprise-btn, .skill-item { + position: relative; /* REQUIRED to contain the ::after element */ + overflow: hidden; /* REQUIRED to hide the diagonal ribbon outside the button */ + isolation: isolate; /* Prevents z-index bleeding */ } -.surprise-btn::after, .skill-item:hover::after { +/* Ensure the ribbon starts off-screen and is actually a gradient, not a solid block */ +.surprise-btn::after, .skill-item::after { content: ''; position: absolute; - top: -50%; left: -50%; width: 200%; height: 200%; - background: linear-gradient(45deg, transparent, rgba(255,255,255,0.3), transparent); - transform: rotate(45deg); - transition: 0.5s; + top: 0; + left: -150%; /* Start much further left */ + width: 100%; /* Match width of parent */ + height: 100%; + background: linear-gradient( + 90deg, + transparent, + rgba(255, 255, 255, 0.4), + transparent + ); + transform: skewX(-20deg); /* Use skew instead of rotate for better clipping */ + transition: 0.6s cubic-bezier(0.19, 1, 0.22, 1); +} + +.surprise-btn:hover::after, .skill-item:hover::after { + left: 150%; /* Slide all the way across */ } -.surprise-btn:hover::after, .skill-item:hover::after { left: 120%; } /** - * 4. DEVELOPER TOOLS & SELF DESTRUCT + * 4. DEVELOPER TOOLS & CONSOLE LOCK */ #dev-tools { backdrop-filter: blur(20px); @@ -118,6 +120,24 @@ html, body { border: 2px solid var(--accent); padding: 1.5rem; border-radius: 1rem; + z-index: 99999 !important; + position: fixed !important; +} + +/* NUCLEAR LOCK: Keeps console visible during Self Destruct & Shake */ +html body #dev-tools[data-lock="true"] { + display: block !important; + visibility: visible !important; + opacity: 1 !important; + position: fixed !important; + top: 20px !important; + right: 20px !important; + z-index: 2147483647 !important; + transform: none !important; + transition: none !important; + pointer-events: auto !important; + border-color: var(--danger); + box-shadow: 0 0 50px rgba(239, 68, 68, 0.4); } #dev-tools button { @@ -142,34 +162,56 @@ html, body { #dev-tools button[onclick*="badge_click"] { color: #bc13fe !important; border-color: rgba(188, 19, 254, 0.4) !important; } #dev-tools button[onclick*="resetPlayer"] { color: #f97316 !important; border-color: rgba(249, 115, 22, 0.4) !important; } -/* Animated Self Destruct Styling */ -#dev-tools button[onclick*="selfDestruct"] { - color: #ef4444 !important; - border-color: rgba(239, 68, 68, 0.4) !important; - font-weight: 900; +#dev-tools button:hover { + background: rgba(255, 255, 255, 0.1); + box-shadow: 0 0 15px currentColor; + transform: translateX(4px); } -#dev-tools button[onclick*="selfDestruct"].is-destructing { +/** + * 5. SELF DESTRUCT & PROGRESS BARS + */ +#self-destruct-btn.is-destructing { background: linear-gradient(270deg, #2563eb, #f97316, #ef4444) !important; background-size: 400% 400% !important; - animation: heat-up 2s ease infinite !important; + animation: heat-up 2s linear infinite !important; color: white !important; - border-color: white !important; + border: 2px solid white !important; + pointer-events: none; + overflow: hidden; } -#dev-tools button::after { opacity: 0; transition: 0.3s; } -#dev-tools button[onclick*="resetPlayer"]::after { content: '🔄'; } -#dev-tools button[onclick*="selfDestruct"]::after { content: '💣'; } -#dev-tools button:hover::after { opacity: 1; margin-left: 10px; } +#destruct-bar-container { + width: 100%; + height: 14px; + background: #000; + border: 2px solid #333; + margin-top: 15px; + border-radius: 4px; +} -#dev-tools button:hover { - background: rgba(255, 255, 255, 0.1); - box-shadow: 0 0 15px currentColor; - transform: translateX(4px); +#destruct-bar-progress { + height: 100%; + width: 0%; + background: #22c55e; + transition: width 1s linear, background-color 0.3s; +} + +/* Fix for the Ribbon Artifact */ +#destruct-bar { + position: absolute; + bottom: 0; + left: 0; + height: 4px; + width: 0%; + background-color: transparent; + transition: width 1s linear, background-color 0.5s ease; + z-index: 10; + pointer-events: none; } /** - * 5. ANIMATIONS & GAME SYSTEMS + * 6. ANIMATIONS */ @keyframes heat-up { 0% { background-position: 0% 50%; } @@ -177,14 +219,25 @@ html, body { 100% { background-position: 0% 50%; } } -@keyframes violent-shake { - 0%, 100% { transform: translate(0, 0); } +@keyframes shake-anim { + 0% { transform: translate(0, 0); } 25% { transform: translate(3px, -3px); } 50% { transform: translate(-3px, 3px); } + 100% { transform: translate(0, 0); } } -#level-progress { box-shadow: 0 0 10px var(--accent); transition: width 1s ease; } -.glitch-shake { animation: violent-shake 0.1s infinite; overflow: hidden; } +.glitch-shake { + animation: shake-anim 0.1s infinite; + overflow: hidden; +} + +.bar-jitter { animation: jitter 0.1s infinite; } + +@keyframes jitter { + 0% { transform: translateX(0); } + 50% { transform: translateX(2px); filter: brightness(1.5); } + 100% { transform: translateX(-1px); } +} #repair-btn { background-color: var(--danger) !important; @@ -195,88 +248,71 @@ html, body { font-weight: 900; box-shadow: 0 0 60px rgba(239, 68, 68, 0.6); z-index: 10001; + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); } -/* Animation for the button background */ -#dev-tools button.is-destructing { - background: linear-gradient(270deg, #2563eb, #f97316, #ef4444) !important; - background-size: 400% 400% !important; - animation: heat-up 2s linear infinite !important; - color: white !important; - pointer-events: none; -} - -/* High-Priority Console Stacking */ -#dev-tools { - z-index: 99999 !important; /* Above everything else */ - position: fixed !important; -} - -/* Loading Bar Styling */ -/* Jitter effect for the last 2 seconds */ +#level-progress { box-shadow: 0 0 10px var(--accent); transition: width 1s ease; } -.bar-jitter { - animation: jitter 0.1s infinite; +/* Ensure Hash Button remains top-level */ +button[onclick*="gravity"] { + position: relative; + z-index: 10; } - -@keyframes jitter { - 0% { transform: translateX(0); } - 50% { transform: translateX(2px); filter: brightness(1.5); } - 100% { transform: translateX(-1px); } -} - -/* Lock the dev tools during the countdown */ -#dev-tools[data-lock="true"] { - display: block !important; - visibility: visible !important; - opacity: 1 !important; - z-index: 999999 !important; - position: fixed !important; - /* This stops the glitch-shake from moving the panel */ - transform: none !important; - pointer-events: auto !important; +/** + * RE-ASSERTING SURPRISE BUTTON BLUE + */ +.surprise-btn { + /* Explicitly use the blue hex if the variable is failing */ + background-color: #2563eb !important; + color: #ffffff !important; + display: inline-flex !important; + align-items: center; + justify-content: center; + padding: 0.6rem 1.5rem; + border-radius: 9999px; + font-weight: 900; + text-transform: uppercase; + letter-spacing: 0.05em; + border: none; + cursor: pointer; + box-shadow: 0 4px 15px rgba(37, 99, 235, 0.3); + transition: all 0.3s ease; + position: relative; + overflow: hidden; } -/* Ensure the progress bar is high-contrast */ -#destruct-bar-container { - width: 100%; - height: 14px; - background: #000; - border: 2px solid #333; - margin-top: 15px; - border-radius: 4px; +/* Ensure Dark Mode uses its specific blue/accent */ +.dark .surprise-btn { + background-color: var(--accent) !important; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5); } -#destruct-bar-progress { - height: 100%; - width: 0%; - background: #22c55e; - transition: width 1s linear, background-color 0.3s; +.surprise-btn:hover { + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(37, 99, 235, 0.5); + filter: brightness(1.1); } -/* Specific button styling during destruction */ -.is-destructing { - background: #ef4444 !important; - animation: pulse 0.5s infinite !important; - border: 2px solid white !important; -} -/* This selector is extremely specific to override any other styles */ -html body #dev-tools[data-lock="true"] { - display: block !important; - visibility: visible !important; - opacity: 1 !important; - position: fixed !important; - top: 20px !important; - right: 20px !important; - z-index: 2147483647 !important; /* Maximum possible z-index */ - transform: none !important; /* Prevents gravity/shake from moving it */ - transition: none !important; /* Prevents fading out */ - pointer-events: auto !important; +/* The "Shimmer" fix from before to prevent the gray ribbon */ +.surprise-btn::after { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient( + 90deg, + transparent, + rgba(255, 255, 255, 0.3), + transparent + ); + transition: 0.5s; } -/* Ensure the progress bar is always visible inside the locked console */ -#dev-tools[data-lock="true"] #destruct-bar-container, -#dev-tools[data-lock="true"] #destruct-bar-progress { - visibility: visible !important; - opacity: 1 !important; +.surprise-btn:hover::after { + left: 100%; } diff --git a/src/assets/js/script.js b/src/assets/js/script.js index 1260bdbc..855dd098 100644 --- a/src/assets/js/script.js +++ b/src/assets/js/script.js @@ -152,22 +152,6 @@ function unlockEgg(eggId) { * UNIVERSAL EGG UNLOCKER * 4 Secrets: matrix, konami, gravity (hash), badge_click */ -function triggerSecretUnlock(effectType) { - // 1. Trigger Visuals - if (effectType === 'matrix') { - initMatrix(); - } else if (effectType === 'konami') { - activateKonami(); - } else if (effectType === 'gravity') { - // This is triggered by clicking the Hash or the Dev Button - triggerGravity(null); - } else if (effectType === 'badge_click') { - playSound('click'); - } - - // 2. Grant Level (Fixed IDs ensure max level 4) - unlockEgg(`secret_${effectType}`); -} // Ensure the actual badge click also uses this logic function handleLevelClick() { @@ -376,64 +360,119 @@ let destructInterval; * SELF DESTRUCT ENGINE * Forces console visibility and manages the dynamic loading bar */ +/** + * RE-INITIALIZE THE SELF-DESTRUCT (SOUND + PERSISTENCE) + */ window.startSelfDestruct = function() { const btn = document.getElementById('self-destruct-btn'); const devPanel = document.getElementById('dev-tools'); + const timerText = document.getElementById('destruct-timer'); + const progressBar = document.getElementById('destruct-bar'); if (destructInterval) return; - // 1. Move console to BODY to escape parent container collapses - document.body.appendChild(devPanel); - - // 2. Lock and Audio Resume - devPanel.setAttribute('data-lock', 'true'); + // AUDIO BOOTUP if (!audioCtx) audioCtx = new (window.AudioContext || window.webkitAudioContext)(); audioCtx.resume(); - let barContainer = document.getElementById('destruct-bar-container') || createBar(btn); - const progressBar = document.getElementById('destruct-bar-progress'); - + // UI LOCKING + document.body.appendChild(devPanel); + devPanel.setAttribute('data-lock', 'true'); btn.classList.add('is-destructing'); + let timeLeft = 10; destructInterval = setInterval(() => { - timeLeft--; + timeLeft--; // Countdown moves from 10 towards 0 - // FORCE RE-CHECK (The 4-second fix) - devPanel.classList.remove('hidden'); - devPanel.style.display = 'block'; + // 1. Update the numerical text + const timerDisplay = document.getElementById('destruct-timer'); + const statusText = document.getElementById('destruct-text'); - const progressPercent = ((10 - timeLeft) / 10) * 100; - progressBar.style.width = `${progressPercent}%`; + if (timerDisplay) { + timerDisplay.innerText = `${timeLeft}s`; + timerDisplay.style.color = "#fff"; // Ensure it's visible against the red + } - // Color Change: Green -> Yellow -> Red - progressBar.style.backgroundColor = timeLeft > 5 ? "#22c55e" : (timeLeft > 2 ? "#eab308" : "#ef4444"); + // 2. Update the progress bar (Green -> Red) + const progressBar = document.getElementById('destruct-bar'); + if (progressBar) { + const percent = ((10 - timeLeft) / 10) * 100; + progressBar.style.width = `${percent}%`; - btn.innerHTML = `HALT SYSTEM IN ${timeLeft}s 💣`; + // Color transition logic + if (timeLeft > 5) progressBar.style.backgroundColor = "#22c55e"; // Green + else if (timeLeft > 2) progressBar.style.backgroundColor = "#eab308"; // Yellow + else progressBar.style.backgroundColor = "#ef4444"; // Red + } - // Sound Engine (scheduling precisely) - if (audioCtx) { - const osc = audioCtx.createOscillator(); - const gain = audioCtx.createGain(); - osc.connect(gain); gain.connect(audioCtx.destination); - osc.frequency.setValueAtTime(200 + (progressPercent * 10), audioCtx.currentTime); - gain.gain.setValueAtTime(0.1, audioCtx.currentTime); - gain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + 0.1); - osc.start(); osc.stop(audioCtx.currentTime + 0.1); - } + // 3. Audio & Haptics + if (audioCtx) { + const osc = audioCtx.createOscillator(); + const g = audioCtx.createGain(); + osc.connect(g); g.connect(audioCtx.destination); + // Pitch goes up as time runs out + osc.frequency.setValueAtTime(300 + (10 - timeLeft) * 50, audioCtx.currentTime); + g.gain.setValueAtTime(0.1, audioCtx.currentTime); + g.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + 0.1); + osc.start(); osc.stop(audioCtx.currentTime + 0.1); + } - if (timeLeft <= 4) { - document.body.classList.add('glitch-shake'); - } + // 4. Visual Panic (Last 4 seconds) + if (timeLeft <= 4) { + document.body.classList.add('glitch-shake'); + if (statusText) statusText.innerText = "SYSTEM_FAILURE_IMMINENT"; + } + + // 5. Termination + if (timeLeft <= 0) { + clearInterval(destructInterval); + destructInterval = null; + if (timerDisplay) timerDisplay.innerText = "0s"; + + // Release lock and trigger explosion + const devPanel = document.getElementById('dev-tools'); + devPanel.setAttribute('data-lock', 'false'); + triggerSecretUnlock('gravity'); + } +}, 1000); +} +/** + * UPDATED TRIGGER LOGIC + * Corrects the 'Gravity' failure for the Commit Hash + */ +function triggerSecretUnlock(type) { + if (type === 'gravity') { + // Run specific gravity visual logic + activateGravityEffect(); + } else if (type === 'matrix') { + initMatrix(); + } else if (type === 'konami') { + activateKonami(); + } + + // Global XP Unlock + unlockEgg(`secret_${type}`); +} + +function activateGravityEffect() { + playSound('secret'); + document.body.classList.add('glitch-shake'); + + setTimeout(() => { + document.body.classList.remove('glitch-shake'); + // Targeted elements for falling + const targets = document.querySelectorAll('.user-card, header, footer, main, h1'); + targets.forEach(el => { + const dist = window.innerHeight + 500; + el.style.transition = `transform ${1 + Math.random()}s ease-in, opacity 1s`; + el.style.transform = `translateY(${dist}px) rotate(${Math.random() * 60 - 30}deg)`; + el.style.opacity = "0"; + el.style.pointerEvents = "none"; + }); + }, 500); +} - if (timeLeft <= 0) { - clearInterval(destructInterval); - destructInterval = null; - devPanel.setAttribute('data-lock', 'false'); // Finally release the lock - triggerSecretUnlock('gravity'); - } - }, 1000); -}; // Internal helper to ensure bar exists function createBar(btn) { const container = document.createElement('div');