diff --git a/src/css/styles.css b/src/css/styles.css index 657fee9..22bcebb 100644 --- a/src/css/styles.css +++ b/src/css/styles.css @@ -202,6 +202,116 @@ h1.title { font-weight: 700; color: var(--vault-yellow); font-size: 1.4rem; + transition: all 0.3s ease; +} + +/* Professional Timer Warning - Polished & Theme-Aware */ +.score-big.timer-critical { + color: #ff3333 !important; + font-size: 2.2rem !important; + font-weight: 800 !important; + animation: timerUrgent 1.4s ease-in-out infinite; + transition: all 0.3s ease; +} + +/* Light theme adjustment */ +[data-theme="light"] .score-big.timer-critical { + color: #cc0000 !important; +} + +@keyframes timerUrgent { + 0%, 100% { + transform: scale(1); + text-shadow: 0 0 15px rgba(255, 51, 51, 0.7), + 0 0 30px rgba(255, 51, 51, 0.4), + 0 2px 6px rgba(0, 0, 0, 0.3); + } + 50% { + transform: scale(1.08); + text-shadow: 0 0 25px rgba(255, 51, 51, 0.9), + 0 0 50px rgba(255, 51, 51, 0.6), + 0 3px 8px rgba(0, 0, 0, 0.4); + } +} + +/* Light theme timer glow */ +[data-theme="light"] .score-big.timer-critical { + text-shadow: 0 0 12px rgba(204, 0, 0, 0.6), + 0 0 25px rgba(204, 0, 0, 0.3), + 0 2px 4px rgba(0, 0, 0, 0.2); +} + +/* Timer bar - smooth professional pulse */ +.timer-bar-fill.timer-bar-critical { + background: linear-gradient(90deg, #ff1a1a, #ff4444) !important; + animation: barPulse 1.4s ease-in-out infinite; + box-shadow: 0 0 12px rgba(255, 26, 26, 0.6); + transition: all 0.3s ease; +} + +/* Light theme bar */ +[data-theme="light"] .timer-bar-fill.timer-bar-critical { + background: linear-gradient(90deg, #cc0000, #ff3333) !important; + box-shadow: 0 0 10px rgba(204, 0, 0, 0.5); +} + +@keyframes barPulse { + 0%, 100% { + box-shadow: 0 0 12px rgba(255, 26, 26, 0.6); + } + 50% { + box-shadow: 0 0 20px rgba(255, 26, 26, 0.8), + 0 0 35px rgba(255, 26, 26, 0.4); + } +} + +/* Light theme bar pulse */ +[data-theme="light"] .timer-bar-fill.timer-bar-critical { + animation: barPulseLight 1.4s ease-in-out infinite; +} + +@keyframes barPulseLight { + 0%, 100% { + box-shadow: 0 0 10px rgba(204, 0, 0, 0.5); + } + 50% { + box-shadow: 0 0 18px rgba(204, 0, 0, 0.7), + 0 0 30px rgba(204, 0, 0, 0.3); + } +} + +/* Subtle screen vignette - professional urgency effect */ +body.game-critical::before { + content: ''; + position: fixed; + inset: 0; + pointer-events: none; + z-index: 1; + animation: screenVignette 2s ease-in-out infinite; + transition: opacity 0.3s ease; +} + +@keyframes screenVignette { + 0%, 100% { + box-shadow: inset 0 0 100px rgba(255, 0, 0, 0.12); + } + 50% { + box-shadow: inset 0 0 140px rgba(255, 0, 0, 0.18); + } +} + +/* Light theme vignette - more subtle */ +[data-theme="light"] body.game-critical::before { + animation: screenVignetteLight 2s ease-in-out infinite; +} + +@keyframes screenVignetteLight { + 0%, 100% { + box-shadow: inset 0 0 120px rgba(204, 0, 0, 0.08); + } + 50% { + box-shadow: inset 0 0 160px rgba(204, 0, 0, 0.12); + } } .stars { diff --git a/src/js/app.js b/src/js/app.js index 113abda..1cfb69e 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -175,12 +175,26 @@ timeEl.textContent = formatTime(Math.floor(timeLeft / 60), timeLeft % 60); const pct = Math.max(0, (timeLeft / timeTotal) * 100); timerBarFill.style.width = pct + '%'; + + // Game-style urgent warning at 10 seconds if (timeLeft === 10) { - alert("Hurry up! Only 10 seconds left!"); + playTone(800, 0.15); // warning sound + timeEl.classList.add('timer-critical'); + timerBarFill.classList.add('timer-bar-critical'); + document.body.classList.add('game-critical'); } }, 1000); } - function stopTimer() { if (timerId) { clearInterval(timerId); timerId = null } } + function stopTimer() { + if (timerId) { + clearInterval(timerId); + timerId = null; + // Remove critical state when timer stops + timeEl.classList.remove('timer-critical'); + timerBarFill.classList.remove('timer-bar-critical'); + document.body.classList.remove('game-critical'); + } + } function resetTimer() { stopTimer(); pairCount = Math.floor(difficulties[selectedDifficulty].tiles / 2); @@ -189,6 +203,10 @@ timeLeft = timeTotal; timeEl.textContent = formatTime(Math.floor(timeLeft / 60), timeLeft % 60); timerBarFill.style.width = '100%'; + // Remove all critical classes + timeEl.classList.remove('timer-critical'); + timerBarFill.classList.remove('timer-bar-critical'); + document.body.classList.remove('game-critical'); } // audio helpers (small tones using WebAudio)