WEBLEB
Accueil
Éditeur
Connexion
Pro
Français
English
Français
Español
Português
Deutsch
Italiano
हिंदी
HTML
CSS
JS
Halloween Countdown Clock Monster
Days left until Halloween:
--:--:--
•
--d --:--:--
Alarm clock-headed creature
An emaciated torso with an alarm clock for a head. The face spins while hands show the real time.
This interactive scene needs JavaScript enabled to display the live clock and countdown.
/* ===== CSS Variables ===== */ :root { --jx: 0px; --jy: 0px; --jr: 0deg; --bg-red-dark: #1a0508; --bg-red-mid: #2d0a0f; --bg-red-light: #3d0f15; --blood-red: #8b0000; --blood-dark: #4a0404; } /* ===== Reset & Base ===== */ * { box-sizing: border-box; margin: 0; padding: 0; } html { height: 100%; } body { height: 100%; color: #e8e1d7; font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif; /* Darker, more ominous base */ background: /* Blood splatter overlay */ radial-gradient(ellipse 200px 300px at 15% 20%, rgba(139, 0, 0, 0.3) 0%, transparent 40%), radial-gradient(ellipse 150px 200px at 85% 70%, rgba(74, 4, 4, 0.4) 0%, transparent 35%), radial-gradient(ellipse 300px 150px at 50% 90%, rgba(139, 0, 0, 0.2) 0%, transparent 30%), /* Main gradient */ radial-gradient( ellipse 140% 100% at 50% 50%, #1a0508 0%, #0d0204 40%, #000000 100% ); background-attachment: fixed; overflow: hidden; position: relative; /* Add pixelation to entire page */ image-rendering: optimizeSpeed; image-rendering: -moz-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; image-rendering: crisp-edges; } /* ===== Creepy Background Layer ===== */ body::before { content: ''; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: /* Organic noise texture */ url('data:image/svg+xml,%3Csvg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"%3E%3Cfilter id="noiseFilter"%3E%3CfeTurbulence type="fractalNoise" baseFrequency="0.85" numOctaves="6" stitchTiles="stitch"/%3E%3CfeColorMatrix values="0 0 0 0 0.1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1"/%3E%3C/filter%3E%3Crect width="100%25" height="100%25" filter="url(%23noiseFilter)"/%3E%3C/svg%3E'); opacity: 0.4; mix-blend-mode: multiply; pointer-events: none; z-index: 1; } /* ===== Animated Blood Drips ===== */ @keyframes blood-drip { 0% { transform: translateY(-100%); opacity: 0; } 10% { opacity: 0.8; } 90% { opacity: 0.8; } 100% { transform: translateY(calc(100vh + 100%)); opacity: 0; } } body::after { content: ''; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: /* Dripping blood effect */ radial-gradient(ellipse 4px 20px at 10% 0%, var(--blood-dark) 0%, transparent 100%), radial-gradient(ellipse 3px 25px at 25% 0%, var(--blood-red) 0%, transparent 100%), radial-gradient(ellipse 5px 30px at 40% 0%, var(--blood-dark) 0%, transparent 100%), radial-gradient(ellipse 3px 15px at 60% 0%, rgba(139, 0, 0, 0.6) 0%, transparent 100%), radial-gradient(ellipse 4px 35px at 75% 0%, var(--blood-dark) 0%, transparent 100%), radial-gradient(ellipse 6px 25px at 90% 0%, var(--blood-red) 0%, transparent 100%); background-size: 100% 200px; background-repeat: repeat-x; animation: blood-drip 20s linear infinite; pointer-events: none; z-index: 2; opacity: 0.6; } /* ===== Main Scene Container ===== */ .scene { position: fixed; top: 0; left: 0; width: 100%; height: 100%; isolation: isolate; z-index: 3; } /* ===== Creepy Floating Eyes ===== */ .scene::before { content: ''; position: absolute; width: 100%; height: 100%; background: /* Floating eyes in darkness */ radial-gradient(ellipse 8px 4px at 20% 30%, rgba(255, 0, 0, 0.6) 0%, rgba(255, 0, 0, 0.3) 30%, transparent 50%), radial-gradient(ellipse 8px 4px at 22% 30%, rgba(255, 0, 0, 0.6) 0%, rgba(255, 0, 0, 0.3) 30%, transparent 50%), radial-gradient(ellipse 6px 3px at 70% 60%, rgba(255, 100, 0, 0.4) 0%, transparent 50%), radial-gradient(ellipse 6px 3px at 72% 60%, rgba(255, 100, 0, 0.4) 0%, transparent 50%), radial-gradient(ellipse 5px 2px at 85% 20%, rgba(200, 0, 0, 0.5) 0%, transparent 40%), radial-gradient(ellipse 5px 2px at 87% 20%, rgba(200, 0, 0, 0.5) 0%, transparent 40%); animation: eyes-blink 8s ease-in-out infinite; pointer-events: none; z-index: 1; } @keyframes eyes-blink { 0%, 100% { opacity: 0.3; } 45% { opacity: 0.3; } 50% { opacity: 0; } 55% { opacity: 0.3; } 90% { opacity: 0.3; } 92% { opacity: 0; } 94% { opacity: 0.3; } } /* ===== HUD Display ===== */ .hud { position: absolute; top: 40px; left: 50%; transform: translateX(-50%); z-index: 10; } .chip { display: inline-block; padding: 10px 18px; border-radius: 999px; border: 1px solid rgba(139, 0, 0, 0.3); background: linear-gradient(135deg, rgba(15, 13, 12, 0.95), rgba(10, 9, 8, 0.95) ); backdrop-filter: blur(10px); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.05), 0 0 30px rgba(139, 0, 0, 0.2); } .chip-content { display: flex; align-items: center; gap: 12px; font-family: ui-monospace, 'Menlo', 'Consolas', monospace; } .chip .sep { opacity: 0.4; color: #8b7a6a; } .countdown-container { display: flex; flex-direction: column; align-items: center; gap: 2px; } .countdown-label { font-size: 9px; text-transform: uppercase; letter-spacing: 0.5px; color: #998570; opacity: 0.8; font-weight: 600; line-height: 1; } #localTime { font-size: 14px; color: #cdb9a0; font-variant-numeric: tabular-nums; } #toHalloween { font-size: 14px; color: #ff9966; font-variant-numeric: tabular-nums; font-weight: 500; text-shadow: 0 0 10px rgba(255, 153, 102, 0.3); } /* ===== Stage Container ===== */ .stage { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; transform: translate(var(--jx), var(--jy)) rotate(var(--jr)) scale(1.05); transition: transform 80ms steps(2, end); } /* ===== BIGGER, PIXELATED, OLD CLOCK ===== */ #clockhead { width: min(100vw, 95vh); max-width: none; height: auto; z-index: 5; /* Pixelation effect */ image-rendering: optimizeSpeed; image-rendering: -moz-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; image-rendering: crisp-edges; /* Multiple filters for old, degraded look */ filter: /* Heavy shadow */ drop-shadow(0 40px 100px rgba(0, 0, 0, 1)) drop-shadow(0 0 50px rgba(139, 0, 0, 0.4)) /* Contrast and saturation for old look */ contrast(1.3) saturate(0.7) brightness(0.9) /* Blur then sharpen for pixel effect */ blur(0.3px) contrast(1.5); /* Add chromatic aberration */ animation: shadow-pulse 4s ease-in-out infinite, chromatic-shift 0.5s ease-in-out infinite alternate, degrade-flicker 0.1s steps(2) infinite; /* Scale up for bigger appearance */ transform: scale(1.3); transform-origin: center center; } /* ===== Pixelation Enhancement via SVG Filter ===== */ .stage::after { content: ''; position: absolute; top: 50%; left: 50%; width: 120%; height: 120%; transform: translate(-50%, -50%); background: /* Pixel grid overlay */ repeating-linear-gradient( 0deg, transparent 0px, transparent 2px, rgba(0, 0, 0, 0.15) 2px, rgba(0, 0, 0, 0.15) 3px ), repeating-linear-gradient( 90deg, transparent 0px, transparent 2px, rgba(0, 0, 0, 0.15) 2px, rgba(0, 0, 0, 0.15) 3px ); pointer-events: none; mix-blend-mode: multiply; z-index: 6; } /* ===== Old CRT Monitor Effects ===== */ @keyframes chromatic-shift { 0% { text-shadow: -2px 0 rgba(255, 0, 0, 0.5), 2px 0 rgba(0, 255, 255, 0.5); } 100% { text-shadow: 2px 0 rgba(255, 0, 0, 0.5), -2px 0 rgba(0, 255, 255, 0.5); } } @keyframes degrade-flicker { 0% { opacity: 1; } 50% { opacity: 0.98; } 100% { opacity: 0.96; } } /* ===== Visual Effects ===== */ .gore { filter: drop-shadow(0 8px 16px rgba(120, 0, 0, 0.4)); image-rendering: pixelated; } /* ===== Overlay Container ===== */ .overlays { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; } /* ===== Enhanced Fog with Shadows ===== */ .fog { position: absolute; top: -10%; left: -10%; width: 120%; height: 120%; z-index: 20; filter: blur(3px); background: /* Moving shadows */ radial-gradient( 70% 40% at 20% 20%, rgba(0, 0, 0, 0.3), transparent 60% ), radial-gradient( 60% 35% at 80% 30%, rgba(139, 0, 0, 0.1), transparent 60% ), radial-gradient( 90% 50% at 50% 80%, rgba(0, 0, 0, 0.2), transparent 65% ); mix-blend-mode: multiply; animation: fog-drift 40s linear infinite, fog-pulse 8s ease-in-out infinite; } @keyframes fog-drift { to { transform: translate(-5%, -3%) scale(1.1); } } @keyframes fog-pulse { 0%, 100% { opacity: 0.4; } 50% { opacity: 0.7; } } /* ===== Heavy Retro Scanlines ===== */ .scanlines { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 30; mix-blend-mode: overlay; background: /* Thicker, more visible scanlines for retro feel */ repeating-linear-gradient( to bottom, transparent 0px, rgba(255, 0, 0, 0.05) 1px, rgba(0, 0, 0, 0.1) 2px, rgba(0, 0, 0, 0.1) 4px, transparent 5px ); animation: crt-flicker 4s steps(60, end) infinite, glitch 10s steps(1) infinite, scan-roll 8s linear infinite; } @keyframes scan-roll { 0% { background-position: 0 0; } 100% { background-position: 0 10px; } } @keyframes glitch { 92% { transform: translateX(0); } 93% { transform: translateX(-3px); filter: hue-rotate(90deg); } 94% { transform: translateX(3px); } 95% { transform: translateX(0); filter: hue-rotate(0deg); } } @keyframes crt-flicker { 0%, 100% { opacity: 0.3; } 50% { opacity: 0.4; } 60% { opacity: 0.35; } } /* ===== Enhanced Vignette for Old Screen ===== */ .vignette { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 40; background: /* CRT screen curve effect */ radial-gradient(circle at 0% 0%, rgba(0, 0, 0, 0.9) 0%, transparent 25%), radial-gradient(circle at 100% 0%, rgba(0, 0, 0, 0.9) 0%, transparent 25%), radial-gradient(circle at 0% 100%, rgba(0, 0, 0, 0.9) 0%, transparent 25%), radial-gradient(circle at 100% 100%, rgba(0, 0, 0, 0.9) 0%, transparent 25%), /* Main heavy vignette */ radial-gradient( ellipse 110% 90% at 50% 50%, transparent 25%, rgba(0, 0, 0, 0.4) 45%, rgba(0, 0, 0, 0.8) 75%, rgba(0, 0, 0, 0.98) 100% ); } /* ===== Screen Burn-in Effect ===== */ .vignette::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: /* Screen burn marks */ radial-gradient(ellipse 200px 150px at 30% 40%, rgba(100, 50, 0, 0.1) 0%, transparent 50%), radial-gradient(ellipse 150px 200px at 70% 60%, rgba(80, 40, 0, 0.08) 0%, transparent 50%), /* Screen cracks */ linear-gradient(105deg, transparent 40%, rgba(0, 0, 0, 0.1) 40.5%, transparent 41%), linear-gradient(-15deg, transparent 60%, rgba(139, 0, 0, 0.05) 60.5%, transparent 61%), linear-gradient(75deg, transparent 70%, rgba(0, 0, 0, 0.08) 70.5%, transparent 71%); opacity: 0.7; } /* ===== Bell Animation ===== */ #bells { transform-origin: 0 -90px; } .ring { animation: bell-wobble 240ms ease-in-out; } @keyframes bell-wobble { 0%, 100% { transform: rotate(0deg); } 25% { transform: rotate(-12deg); } 50% { transform: rotate(12deg); } 75% { transform: rotate(-6deg); } } /* ===== Pulsing Shadow for Clock ===== */ @keyframes shadow-pulse { 0%, 100% { filter: drop-shadow(0 40px 100px rgba(0, 0, 0, 1)) drop-shadow(0 0 50px rgba(139, 0, 0, 0.4)) contrast(1.3) saturate(0.7) brightness(0.9) blur(0.3px) contrast(1.5); } 50% { filter: drop-shadow(0 45px 110px rgba(0, 0, 0, 1)) drop-shadow(0 0 70px rgba(139, 0, 0, 0.6)) contrast(1.4) saturate(0.6) brightness(0.85) blur(0.4px) contrast(1.6); } } /* ===== Accessibility & Reduced Motion ===== */ @media (prefers-reduced-motion: reduce) { .stage, .fog, .scanlines, .ring, #clockhead, body::after, .scene::before { animation: none !important; transition: none !important; } } /* ===== Responsive Adjustments ===== */ @media (max-width: 768px) { .hud { top: 20px; } .chip { padding: 8px 14px; } .chip-content { gap: 10px; } .countdown-label { font-size: 8px; } #localTime, #toHalloween { font-size: 12px; } #clockhead { width: 100vw; transform: scale(1.1); } } @media (max-height: 600px) { .hud { top: 20px; } .chip { padding: 6px 12px; } .countdown-label { font-size: 8px; } #localTime, #toHalloween { font-size: 11px; } #clockhead { width: 95vw; transform: scale(1.0); } }
// === Halloween Time Clock Monster === // Enhanced with better error handling and performance optimizations (function() { 'use strict'; // Cache DOM elements const elements = { svg: document.getElementById('clockhead'), headGrp: document.getElementById('head'), faceSpin: document.getElementById('faceSpin'), bells: document.getElementById('bells'), hHand: document.getElementById('hHand'), mHand: document.getElementById('mHand'), sHand: document.getElementById('sHand'), ticksGrp: document.getElementById('ticks'), romansGrp: document.getElementById('romans'), localTimeEl: document.getElementById('localTime'), toHalloweenEl: document.getElementById('toHalloween') }; // Check if all elements exist const allElementsExist = Object.values(elements).every(el => el !== null); if (!allElementsExist) { console.error('Some required DOM elements are missing'); return; } // Audio context (lazy initialization) let audioCtx = null; // State let lastSecond = -1; let halloweenTarget = null; /* ---------- Build Clock Dial ---------- */ function buildDial() { const svgNS = 'http://www.w3.org/2000/svg'; // Create tick marks for (let i = 0; i < 60; i++) { const isMajor = i % 5 === 0; const tickLength = isMajor ? 12 : 6; const strokeWidth = isMajor ? 2 : 1; const angle = (i / 60) * Math.PI * 2 - Math.PI / 2; const radius = 92; const x1 = Math.cos(angle) * (radius - 2); const y1 = Math.sin(angle) * (radius - 2); const x2 = Math.cos(angle) * (radius - tickLength); const y2 = Math.sin(angle) * (radius - tickLength); const line = document.createElementNS(svgNS, 'line'); line.setAttribute('x1', x1.toFixed(2)); line.setAttribute('y1', y1.toFixed(2)); line.setAttribute('x2', x2.toFixed(2)); line.setAttribute('y2', y2.toFixed(2)); line.setAttribute('stroke', isMajor ? '#241913' : '#3a2b23'); line.setAttribute('stroke-width', strokeWidth); elements.ticksGrp.appendChild(line); } // Add Roman numerals const romans = ['XII', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X', 'XI']; const numeralRadius = 70; romans.forEach((numeral, i) => { const angle = (i / 12) * Math.PI * 2 - Math.PI / 2; const x = Math.cos(angle) * numeralRadius; const y = Math.sin(angle) * numeralRadius + 4; const text = document.createElementNS(svgNS, 'text'); text.textContent = numeral; text.setAttribute('x', x.toFixed(2)); text.setAttribute('y', y.toFixed(2)); text.setAttribute('text-anchor', 'middle'); text.setAttribute('font-size', '13'); text.setAttribute('fill', '#271a14'); text.setAttribute('font-family', 'ui-serif, Georgia, serif'); text.setAttribute('font-weight', 'bold'); elements.romansGrp.appendChild(text); }); } /* ---------- Utility Functions ---------- */ function pad(n) { return String(n).padStart(2, '0'); } function getNextHalloween(now = new Date()) { const currentYear = now.getFullYear(); const halloween = new Date(currentYear, 9, 31, 0, 0, 0); // October = month 9 // If Halloween has passed this year, get next year's if (now > halloween) { return new Date(currentYear + 1, 9, 31, 0, 0, 0); } return halloween; } function formatCountdown(milliseconds) { const totalSeconds = Math.max(0, Math.floor(milliseconds / 1000)); const days = Math.floor(totalSeconds / 86400); const hours = Math.floor((totalSeconds % 86400) / 3600); const minutes = Math.floor((totalSeconds % 3600) / 60); const seconds = totalSeconds % 60; return `${days}d ${pad(hours)}:${pad(minutes)}:${pad(seconds)}`; } function applyJitter(strength = 1) { const jitterX = (Math.random() - 0.5) * 1.6 * strength; const jitterY = (Math.random() - 0.5) * 1.6 * strength; const jitterRotate = (Math.random() - 0.5) * 0.35 * strength; document.documentElement.style.setProperty('--jx', `${jitterX.toFixed(2)}px`); document.documentElement.style.setProperty('--jy', `${jitterY.toFixed(2)}px`); document.documentElement.style.setProperty('--jr', `${jitterRotate.toFixed(3)}deg`); } function playBellSound() { if (!audioCtx) { try { audioCtx = new (window.AudioContext || window.webkitAudioContext)(); } catch (e) { console.log('Audio not supported'); return; } } if (audioCtx && audioCtx.state === 'running') { const startTime = audioCtx.currentTime; const oscillator = audioCtx.createOscillator(); const gainNode = audioCtx.createGain(); oscillator.type = 'triangle'; oscillator.frequency.value = 820; gainNode.gain.setValueAtTime(0.0001, startTime); gainNode.gain.exponentialRampToValueAtTime(0.3, startTime + 0.01); gainNode.gain.exponentialRampToValueAtTime(0.0001, startTime + 0.25); oscillator.connect(gainNode).connect(audioCtx.destination); oscillator.start(startTime); oscillator.stop(startTime + 0.26); } } function triggerBellAnimation() { elements.bells.classList.remove('ring'); void elements.bells.offsetWidth; // Force reflow elements.bells.classList.add('ring'); } /* ---------- Click Handler ---------- */ elements.svg.addEventListener('click', function(e) { e.preventDefault(); triggerBellAnimation(); playBellSound(); }); /* ---------- Main Animation Loop ---------- */ function updateClock() { const now = new Date(); // Update HUD time display const timeString = `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`; elements.localTimeEl.textContent = timeString; elements.localTimeEl.setAttribute('datetime', now.toISOString()); // Update Halloween countdown if (!halloweenTarget || now > halloweenTarget) { halloweenTarget = getNextHalloween(now); } const countdownMs = halloweenTarget - now; const countdownString = formatCountdown(countdownMs); elements.toHalloweenEl.textContent = countdownString; // Calculate hand positions const seconds = now.getSeconds() + now.getMilliseconds() / 1000; const minutes = now.getMinutes() + seconds / 60; const hours = (now.getHours() % 12) + minutes / 60; const secondDegrees = seconds * 6; // 360/60 const minuteDegrees = minutes * 6; const hourDegrees = hours * 30; // 360/12 // Update clock hands elements.hHand.setAttribute('transform', `rotate(${hourDegrees.toFixed(2)})`); elements.mHand.setAttribute('transform', `rotate(${minuteDegrees.toFixed(2)})`); elements.sHand.setAttribute('transform', `rotate(${secondDegrees.toFixed(2)})`); // Rotate entire head like a sweeping second hand elements.headGrp.setAttribute('transform', `translate(230,250) rotate(${secondDegrees.toFixed(2)})`); // Trigger effects on each new second const currentSecond = Math.floor(seconds); if (currentSecond !== lastSecond) { lastSecond = currentSecond; triggerBellAnimation(); // Stronger jitter every 10 seconds const jitterStrength = (currentSecond % 10 === 0) ? 1.6 : 1.0; applyJitter(jitterStrength); } requestAnimationFrame(updateClock); } /* ---------- Initialize ---------- */ function init() { buildDial(); halloweenTarget = getNextHalloween(); requestAnimationFrame(updateClock); } // Start when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();
Validating your code, please wait...
HTML
CSS
JS
Halloween Countdown Clock Monster
Days left until Halloween:
--:--:--
•
--d --:--:--
Alarm clock-headed creature
An emaciated torso with an alarm clock for a head. The face spins while hands show the real time.
This interactive scene needs JavaScript enabled to display the live clock and countdown.
/* ===== CSS Variables ===== */ :root { --jx: 0px; --jy: 0px; --jr: 0deg; --bg-red-dark: #1a0508; --bg-red-mid: #2d0a0f; --bg-red-light: #3d0f15; --blood-red: #8b0000; --blood-dark: #4a0404; } /* ===== Reset & Base ===== */ * { box-sizing: border-box; margin: 0; padding: 0; } html { height: 100%; } body { height: 100%; color: #e8e1d7; font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif; /* Darker, more ominous base */ background: /* Blood splatter overlay */ radial-gradient(ellipse 200px 300px at 15% 20%, rgba(139, 0, 0, 0.3) 0%, transparent 40%), radial-gradient(ellipse 150px 200px at 85% 70%, rgba(74, 4, 4, 0.4) 0%, transparent 35%), radial-gradient(ellipse 300px 150px at 50% 90%, rgba(139, 0, 0, 0.2) 0%, transparent 30%), /* Main gradient */ radial-gradient( ellipse 140% 100% at 50% 50%, #1a0508 0%, #0d0204 40%, #000000 100% ); background-attachment: fixed; overflow: hidden; position: relative; /* Add pixelation to entire page */ image-rendering: optimizeSpeed; image-rendering: -moz-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; image-rendering: crisp-edges; } /* ===== Creepy Background Layer ===== */ body::before { content: ''; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: /* Organic noise texture */ url('data:image/svg+xml,%3Csvg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"%3E%3Cfilter id="noiseFilter"%3E%3CfeTurbulence type="fractalNoise" baseFrequency="0.85" numOctaves="6" stitchTiles="stitch"/%3E%3CfeColorMatrix values="0 0 0 0 0.1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1"/%3E%3C/filter%3E%3Crect width="100%25" height="100%25" filter="url(%23noiseFilter)"/%3E%3C/svg%3E'); opacity: 0.4; mix-blend-mode: multiply; pointer-events: none; z-index: 1; } /* ===== Animated Blood Drips ===== */ @keyframes blood-drip { 0% { transform: translateY(-100%); opacity: 0; } 10% { opacity: 0.8; } 90% { opacity: 0.8; } 100% { transform: translateY(calc(100vh + 100%)); opacity: 0; } } body::after { content: ''; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: /* Dripping blood effect */ radial-gradient(ellipse 4px 20px at 10% 0%, var(--blood-dark) 0%, transparent 100%), radial-gradient(ellipse 3px 25px at 25% 0%, var(--blood-red) 0%, transparent 100%), radial-gradient(ellipse 5px 30px at 40% 0%, var(--blood-dark) 0%, transparent 100%), radial-gradient(ellipse 3px 15px at 60% 0%, rgba(139, 0, 0, 0.6) 0%, transparent 100%), radial-gradient(ellipse 4px 35px at 75% 0%, var(--blood-dark) 0%, transparent 100%), radial-gradient(ellipse 6px 25px at 90% 0%, var(--blood-red) 0%, transparent 100%); background-size: 100% 200px; background-repeat: repeat-x; animation: blood-drip 20s linear infinite; pointer-events: none; z-index: 2; opacity: 0.6; } /* ===== Main Scene Container ===== */ .scene { position: fixed; top: 0; left: 0; width: 100%; height: 100%; isolation: isolate; z-index: 3; } /* ===== Creepy Floating Eyes ===== */ .scene::before { content: ''; position: absolute; width: 100%; height: 100%; background: /* Floating eyes in darkness */ radial-gradient(ellipse 8px 4px at 20% 30%, rgba(255, 0, 0, 0.6) 0%, rgba(255, 0, 0, 0.3) 30%, transparent 50%), radial-gradient(ellipse 8px 4px at 22% 30%, rgba(255, 0, 0, 0.6) 0%, rgba(255, 0, 0, 0.3) 30%, transparent 50%), radial-gradient(ellipse 6px 3px at 70% 60%, rgba(255, 100, 0, 0.4) 0%, transparent 50%), radial-gradient(ellipse 6px 3px at 72% 60%, rgba(255, 100, 0, 0.4) 0%, transparent 50%), radial-gradient(ellipse 5px 2px at 85% 20%, rgba(200, 0, 0, 0.5) 0%, transparent 40%), radial-gradient(ellipse 5px 2px at 87% 20%, rgba(200, 0, 0, 0.5) 0%, transparent 40%); animation: eyes-blink 8s ease-in-out infinite; pointer-events: none; z-index: 1; } @keyframes eyes-blink { 0%, 100% { opacity: 0.3; } 45% { opacity: 0.3; } 50% { opacity: 0; } 55% { opacity: 0.3; } 90% { opacity: 0.3; } 92% { opacity: 0; } 94% { opacity: 0.3; } } /* ===== HUD Display ===== */ .hud { position: absolute; top: 40px; left: 50%; transform: translateX(-50%); z-index: 10; } .chip { display: inline-block; padding: 10px 18px; border-radius: 999px; border: 1px solid rgba(139, 0, 0, 0.3); background: linear-gradient(135deg, rgba(15, 13, 12, 0.95), rgba(10, 9, 8, 0.95) ); backdrop-filter: blur(10px); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.05), 0 0 30px rgba(139, 0, 0, 0.2); } .chip-content { display: flex; align-items: center; gap: 12px; font-family: ui-monospace, 'Menlo', 'Consolas', monospace; } .chip .sep { opacity: 0.4; color: #8b7a6a; } .countdown-container { display: flex; flex-direction: column; align-items: center; gap: 2px; } .countdown-label { font-size: 9px; text-transform: uppercase; letter-spacing: 0.5px; color: #998570; opacity: 0.8; font-weight: 600; line-height: 1; } #localTime { font-size: 14px; color: #cdb9a0; font-variant-numeric: tabular-nums; } #toHalloween { font-size: 14px; color: #ff9966; font-variant-numeric: tabular-nums; font-weight: 500; text-shadow: 0 0 10px rgba(255, 153, 102, 0.3); } /* ===== Stage Container ===== */ .stage { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; transform: translate(var(--jx), var(--jy)) rotate(var(--jr)) scale(1.05); transition: transform 80ms steps(2, end); } /* ===== BIGGER, PIXELATED, OLD CLOCK ===== */ #clockhead { width: min(100vw, 95vh); max-width: none; height: auto; z-index: 5; /* Pixelation effect */ image-rendering: optimizeSpeed; image-rendering: -moz-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: pixelated; image-rendering: crisp-edges; /* Multiple filters for old, degraded look */ filter: /* Heavy shadow */ drop-shadow(0 40px 100px rgba(0, 0, 0, 1)) drop-shadow(0 0 50px rgba(139, 0, 0, 0.4)) /* Contrast and saturation for old look */ contrast(1.3) saturate(0.7) brightness(0.9) /* Blur then sharpen for pixel effect */ blur(0.3px) contrast(1.5); /* Add chromatic aberration */ animation: shadow-pulse 4s ease-in-out infinite, chromatic-shift 0.5s ease-in-out infinite alternate, degrade-flicker 0.1s steps(2) infinite; /* Scale up for bigger appearance */ transform: scale(1.3); transform-origin: center center; } /* ===== Pixelation Enhancement via SVG Filter ===== */ .stage::after { content: ''; position: absolute; top: 50%; left: 50%; width: 120%; height: 120%; transform: translate(-50%, -50%); background: /* Pixel grid overlay */ repeating-linear-gradient( 0deg, transparent 0px, transparent 2px, rgba(0, 0, 0, 0.15) 2px, rgba(0, 0, 0, 0.15) 3px ), repeating-linear-gradient( 90deg, transparent 0px, transparent 2px, rgba(0, 0, 0, 0.15) 2px, rgba(0, 0, 0, 0.15) 3px ); pointer-events: none; mix-blend-mode: multiply; z-index: 6; } /* ===== Old CRT Monitor Effects ===== */ @keyframes chromatic-shift { 0% { text-shadow: -2px 0 rgba(255, 0, 0, 0.5), 2px 0 rgba(0, 255, 255, 0.5); } 100% { text-shadow: 2px 0 rgba(255, 0, 0, 0.5), -2px 0 rgba(0, 255, 255, 0.5); } } @keyframes degrade-flicker { 0% { opacity: 1; } 50% { opacity: 0.98; } 100% { opacity: 0.96; } } /* ===== Visual Effects ===== */ .gore { filter: drop-shadow(0 8px 16px rgba(120, 0, 0, 0.4)); image-rendering: pixelated; } /* ===== Overlay Container ===== */ .overlays { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; } /* ===== Enhanced Fog with Shadows ===== */ .fog { position: absolute; top: -10%; left: -10%; width: 120%; height: 120%; z-index: 20; filter: blur(3px); background: /* Moving shadows */ radial-gradient( 70% 40% at 20% 20%, rgba(0, 0, 0, 0.3), transparent 60% ), radial-gradient( 60% 35% at 80% 30%, rgba(139, 0, 0, 0.1), transparent 60% ), radial-gradient( 90% 50% at 50% 80%, rgba(0, 0, 0, 0.2), transparent 65% ); mix-blend-mode: multiply; animation: fog-drift 40s linear infinite, fog-pulse 8s ease-in-out infinite; } @keyframes fog-drift { to { transform: translate(-5%, -3%) scale(1.1); } } @keyframes fog-pulse { 0%, 100% { opacity: 0.4; } 50% { opacity: 0.7; } } /* ===== Heavy Retro Scanlines ===== */ .scanlines { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 30; mix-blend-mode: overlay; background: /* Thicker, more visible scanlines for retro feel */ repeating-linear-gradient( to bottom, transparent 0px, rgba(255, 0, 0, 0.05) 1px, rgba(0, 0, 0, 0.1) 2px, rgba(0, 0, 0, 0.1) 4px, transparent 5px ); animation: crt-flicker 4s steps(60, end) infinite, glitch 10s steps(1) infinite, scan-roll 8s linear infinite; } @keyframes scan-roll { 0% { background-position: 0 0; } 100% { background-position: 0 10px; } } @keyframes glitch { 92% { transform: translateX(0); } 93% { transform: translateX(-3px); filter: hue-rotate(90deg); } 94% { transform: translateX(3px); } 95% { transform: translateX(0); filter: hue-rotate(0deg); } } @keyframes crt-flicker { 0%, 100% { opacity: 0.3; } 50% { opacity: 0.4; } 60% { opacity: 0.35; } } /* ===== Enhanced Vignette for Old Screen ===== */ .vignette { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 40; background: /* CRT screen curve effect */ radial-gradient(circle at 0% 0%, rgba(0, 0, 0, 0.9) 0%, transparent 25%), radial-gradient(circle at 100% 0%, rgba(0, 0, 0, 0.9) 0%, transparent 25%), radial-gradient(circle at 0% 100%, rgba(0, 0, 0, 0.9) 0%, transparent 25%), radial-gradient(circle at 100% 100%, rgba(0, 0, 0, 0.9) 0%, transparent 25%), /* Main heavy vignette */ radial-gradient( ellipse 110% 90% at 50% 50%, transparent 25%, rgba(0, 0, 0, 0.4) 45%, rgba(0, 0, 0, 0.8) 75%, rgba(0, 0, 0, 0.98) 100% ); } /* ===== Screen Burn-in Effect ===== */ .vignette::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: /* Screen burn marks */ radial-gradient(ellipse 200px 150px at 30% 40%, rgba(100, 50, 0, 0.1) 0%, transparent 50%), radial-gradient(ellipse 150px 200px at 70% 60%, rgba(80, 40, 0, 0.08) 0%, transparent 50%), /* Screen cracks */ linear-gradient(105deg, transparent 40%, rgba(0, 0, 0, 0.1) 40.5%, transparent 41%), linear-gradient(-15deg, transparent 60%, rgba(139, 0, 0, 0.05) 60.5%, transparent 61%), linear-gradient(75deg, transparent 70%, rgba(0, 0, 0, 0.08) 70.5%, transparent 71%); opacity: 0.7; } /* ===== Bell Animation ===== */ #bells { transform-origin: 0 -90px; } .ring { animation: bell-wobble 240ms ease-in-out; } @keyframes bell-wobble { 0%, 100% { transform: rotate(0deg); } 25% { transform: rotate(-12deg); } 50% { transform: rotate(12deg); } 75% { transform: rotate(-6deg); } } /* ===== Pulsing Shadow for Clock ===== */ @keyframes shadow-pulse { 0%, 100% { filter: drop-shadow(0 40px 100px rgba(0, 0, 0, 1)) drop-shadow(0 0 50px rgba(139, 0, 0, 0.4)) contrast(1.3) saturate(0.7) brightness(0.9) blur(0.3px) contrast(1.5); } 50% { filter: drop-shadow(0 45px 110px rgba(0, 0, 0, 1)) drop-shadow(0 0 70px rgba(139, 0, 0, 0.6)) contrast(1.4) saturate(0.6) brightness(0.85) blur(0.4px) contrast(1.6); } } /* ===== Accessibility & Reduced Motion ===== */ @media (prefers-reduced-motion: reduce) { .stage, .fog, .scanlines, .ring, #clockhead, body::after, .scene::before { animation: none !important; transition: none !important; } } /* ===== Responsive Adjustments ===== */ @media (max-width: 768px) { .hud { top: 20px; } .chip { padding: 8px 14px; } .chip-content { gap: 10px; } .countdown-label { font-size: 8px; } #localTime, #toHalloween { font-size: 12px; } #clockhead { width: 100vw; transform: scale(1.1); } } @media (max-height: 600px) { .hud { top: 20px; } .chip { padding: 6px 12px; } .countdown-label { font-size: 8px; } #localTime, #toHalloween { font-size: 11px; } #clockhead { width: 95vw; transform: scale(1.0); } }
// === Halloween Time Clock Monster === // Enhanced with better error handling and performance optimizations (function() { 'use strict'; // Cache DOM elements const elements = { svg: document.getElementById('clockhead'), headGrp: document.getElementById('head'), faceSpin: document.getElementById('faceSpin'), bells: document.getElementById('bells'), hHand: document.getElementById('hHand'), mHand: document.getElementById('mHand'), sHand: document.getElementById('sHand'), ticksGrp: document.getElementById('ticks'), romansGrp: document.getElementById('romans'), localTimeEl: document.getElementById('localTime'), toHalloweenEl: document.getElementById('toHalloween') }; // Check if all elements exist const allElementsExist = Object.values(elements).every(el => el !== null); if (!allElementsExist) { console.error('Some required DOM elements are missing'); return; } // Audio context (lazy initialization) let audioCtx = null; // State let lastSecond = -1; let halloweenTarget = null; /* ---------- Build Clock Dial ---------- */ function buildDial() { const svgNS = 'http://www.w3.org/2000/svg'; // Create tick marks for (let i = 0; i < 60; i++) { const isMajor = i % 5 === 0; const tickLength = isMajor ? 12 : 6; const strokeWidth = isMajor ? 2 : 1; const angle = (i / 60) * Math.PI * 2 - Math.PI / 2; const radius = 92; const x1 = Math.cos(angle) * (radius - 2); const y1 = Math.sin(angle) * (radius - 2); const x2 = Math.cos(angle) * (radius - tickLength); const y2 = Math.sin(angle) * (radius - tickLength); const line = document.createElementNS(svgNS, 'line'); line.setAttribute('x1', x1.toFixed(2)); line.setAttribute('y1', y1.toFixed(2)); line.setAttribute('x2', x2.toFixed(2)); line.setAttribute('y2', y2.toFixed(2)); line.setAttribute('stroke', isMajor ? '#241913' : '#3a2b23'); line.setAttribute('stroke-width', strokeWidth); elements.ticksGrp.appendChild(line); } // Add Roman numerals const romans = ['XII', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X', 'XI']; const numeralRadius = 70; romans.forEach((numeral, i) => { const angle = (i / 12) * Math.PI * 2 - Math.PI / 2; const x = Math.cos(angle) * numeralRadius; const y = Math.sin(angle) * numeralRadius + 4; const text = document.createElementNS(svgNS, 'text'); text.textContent = numeral; text.setAttribute('x', x.toFixed(2)); text.setAttribute('y', y.toFixed(2)); text.setAttribute('text-anchor', 'middle'); text.setAttribute('font-size', '13'); text.setAttribute('fill', '#271a14'); text.setAttribute('font-family', 'ui-serif, Georgia, serif'); text.setAttribute('font-weight', 'bold'); elements.romansGrp.appendChild(text); }); } /* ---------- Utility Functions ---------- */ function pad(n) { return String(n).padStart(2, '0'); } function getNextHalloween(now = new Date()) { const currentYear = now.getFullYear(); const halloween = new Date(currentYear, 9, 31, 0, 0, 0); // October = month 9 // If Halloween has passed this year, get next year's if (now > halloween) { return new Date(currentYear + 1, 9, 31, 0, 0, 0); } return halloween; } function formatCountdown(milliseconds) { const totalSeconds = Math.max(0, Math.floor(milliseconds / 1000)); const days = Math.floor(totalSeconds / 86400); const hours = Math.floor((totalSeconds % 86400) / 3600); const minutes = Math.floor((totalSeconds % 3600) / 60); const seconds = totalSeconds % 60; return `${days}d ${pad(hours)}:${pad(minutes)}:${pad(seconds)}`; } function applyJitter(strength = 1) { const jitterX = (Math.random() - 0.5) * 1.6 * strength; const jitterY = (Math.random() - 0.5) * 1.6 * strength; const jitterRotate = (Math.random() - 0.5) * 0.35 * strength; document.documentElement.style.setProperty('--jx', `${jitterX.toFixed(2)}px`); document.documentElement.style.setProperty('--jy', `${jitterY.toFixed(2)}px`); document.documentElement.style.setProperty('--jr', `${jitterRotate.toFixed(3)}deg`); } function playBellSound() { if (!audioCtx) { try { audioCtx = new (window.AudioContext || window.webkitAudioContext)(); } catch (e) { console.log('Audio not supported'); return; } } if (audioCtx && audioCtx.state === 'running') { const startTime = audioCtx.currentTime; const oscillator = audioCtx.createOscillator(); const gainNode = audioCtx.createGain(); oscillator.type = 'triangle'; oscillator.frequency.value = 820; gainNode.gain.setValueAtTime(0.0001, startTime); gainNode.gain.exponentialRampToValueAtTime(0.3, startTime + 0.01); gainNode.gain.exponentialRampToValueAtTime(0.0001, startTime + 0.25); oscillator.connect(gainNode).connect(audioCtx.destination); oscillator.start(startTime); oscillator.stop(startTime + 0.26); } } function triggerBellAnimation() { elements.bells.classList.remove('ring'); void elements.bells.offsetWidth; // Force reflow elements.bells.classList.add('ring'); } /* ---------- Click Handler ---------- */ elements.svg.addEventListener('click', function(e) { e.preventDefault(); triggerBellAnimation(); playBellSound(); }); /* ---------- Main Animation Loop ---------- */ function updateClock() { const now = new Date(); // Update HUD time display const timeString = `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`; elements.localTimeEl.textContent = timeString; elements.localTimeEl.setAttribute('datetime', now.toISOString()); // Update Halloween countdown if (!halloweenTarget || now > halloweenTarget) { halloweenTarget = getNextHalloween(now); } const countdownMs = halloweenTarget - now; const countdownString = formatCountdown(countdownMs); elements.toHalloweenEl.textContent = countdownString; // Calculate hand positions const seconds = now.getSeconds() + now.getMilliseconds() / 1000; const minutes = now.getMinutes() + seconds / 60; const hours = (now.getHours() % 12) + minutes / 60; const secondDegrees = seconds * 6; // 360/60 const minuteDegrees = minutes * 6; const hourDegrees = hours * 30; // 360/12 // Update clock hands elements.hHand.setAttribute('transform', `rotate(${hourDegrees.toFixed(2)})`); elements.mHand.setAttribute('transform', `rotate(${minuteDegrees.toFixed(2)})`); elements.sHand.setAttribute('transform', `rotate(${secondDegrees.toFixed(2)})`); // Rotate entire head like a sweeping second hand elements.headGrp.setAttribute('transform', `translate(230,250) rotate(${secondDegrees.toFixed(2)})`); // Trigger effects on each new second const currentSecond = Math.floor(seconds); if (currentSecond !== lastSecond) { lastSecond = currentSecond; triggerBellAnimation(); // Stronger jitter every 10 seconds const jitterStrength = (currentSecond % 10 === 0) ? 1.6 : 1.0; applyJitter(jitterStrength); } requestAnimationFrame(updateClock); } /* ---------- Initialize ---------- */ function init() { buildDial(); halloweenTarget = getNextHalloween(); requestAnimationFrame(updateClock); } // Start when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();