Clocks are more than just timekeepers; they are essential elements in user interfaces that can enhance both functionality and aesthetics. From digital to analog, the variety of clock designs available can suit any application or website.
In this article, we will explore 10 clock examples that showcase innovative design and practical implementation. Whether you're looking to add a simple time display or a complex world clock, these examples will inspire your next project.
CODE1
Here's the code:
CODETEXT1
CODE2
Here's the code:
CODETEXT2
CODE3
Here's the code:
CODETEXT3
CODE4
Here's the code:
CODETEXT4
CODE5
Here's the code:
CODETEXT5
Designers and developers, elevate your clock designs with Subframe's drag-and-drop interface and intuitive, responsive canvas. Create pixel-perfect UIs effortlessly, every time.
Loved by professionals, Subframe makes stunning design accessible to all. Start for free today!
CODE6
Here's the code:
CODETEXT6
CODE7
Here's the code:
CODETEXT7
CODE8
Here's the code:
CODETEXT8
CODE9
Here's the code:
CODETEXT9
CODE10
Here's the code:
CODETEXT10
Ready to elevate your UI designs? With Subframe, you can create pixel-perfect interfaces, including clocks, in minutes. Our drag-and-drop editor and beautifully crafted components make the process efficient and enjoyable.
Don't wait—start creating stunning UIs immediately. Start for free today!
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Smart Home Control Center Clock</title> <style> :root { --primary: #242424; --secondary: #383838; --accent: #727272; --text: #f5f5f5; --text-secondary: #a0a0a0; --highlight: #5d5d5d; --transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); --shadow: 0 4px 20px rgba(0, 0, 0, 0.1); --glow: 0 0 15px rgba(255, 255, 255, 0.1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', 'Helvetica Neue', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } body { background-color: var(--primary); color: var(--text); display: flex; justify-content: center; align-items: center; min-height: 100vh; overflow: hidden; } .container { width: 100%; max-width: 700px; height: 700px; background: linear-gradient(135deg, var(--primary), var(--secondary)); border-radius: 20px; box-shadow: var(--shadow); padding: 30px; position: relative; overflow: hidden; } .container::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: radial-gradient(circle at 50% 10%, rgba(255, 255, 255, 0.03), transparent 70%); pointer-events: none; } .clock-section { text-align: center; padding: 40px 0; transition: var(--transition); } .date { font-size: 1.2rem; color: var(--text-secondary); letter-spacing: 1px; margin-bottom: 10px; opacity: 0.8; font-weight: 300; } .time { font-size: 5rem; font-weight: 200; position: relative; display: inline-block; margin-bottom: 15px; letter-spacing: -2px; text-shadow: 0 0 10px rgba(255, 255, 255, 0.05); } .time-separator { display: inline-block; animation: pulse 1.5s infinite; width: 12px; } .time-period { font-size: 1.8rem; vertical-align: top; display: inline-block; margin-left: 10px; margin-top: 15px; font-weight: 300; color: var(--text-secondary); } .weather { font-size: 1.1rem; margin-top: 10px; display: flex; justify-content: center; align-items: center; gap: 10px; color: var(--text-secondary); font-weight: 300; } .weather i { font-size: 1.5rem; } .mode-indicator { display: flex; justify-content: center; gap: 12px; margin: 25px 0; } .indicator { background-color: var(--accent); width: 10px; height: 10px; border-radius: 50%; opacity: 0.4; transition: var(--transition); } .indicator.active { opacity: 1; box-shadow: 0 0 10px rgba(255, 255, 255, 0.3); } .schedules { margin-top: 30px; border-radius: 15px; background-color: rgba(0, 0, 0, 0.1); padding: 15px; box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.2); } .schedules-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; } .schedules-title { font-size: 1.2rem; font-weight: 400; } .schedules-actions { display: flex; gap: 15px; } .action-btn { background-color: var(--secondary); border: none; color: var(--text); width: 30px; height: 30px; border-radius: 50%; cursor: pointer; display: flex; justify-content: center; align-items: center; transition: var(--transition); } .action-btn:hover { background-color: var(--highlight); transform: translateY(-2px); box-shadow: var(--glow); } .schedule-list { display: grid; gap: 10px; margin-top: 10px; } .schedule-item { background-color: rgba(255, 255, 255, 0.05); border-radius: 10px; padding: 15px; display: flex; justify-content: space-between; align-items: center; transition: var(--transition); cursor: pointer; } .schedule-item:hover { background-color: rgba(255, 255, 255, 0.1); transform: translateX(5px); } .schedule-info { display: flex; flex-direction: column; gap: 5px; } .schedule-name { font-weight: 400; font-size: 1rem; } .schedule-time { font-size: 0.9rem; color: var(--text-secondary); } .schedule-status { width: 45px; height: 24px; background-color: var(--primary); border-radius: 12px; position: relative; padding: 2px; cursor: pointer; transition: var(--transition); } .schedule-status.active { background-color: rgba(255, 255, 255, 0.2); } .status-toggle { width: 20px; height: 20px; background-color: var(--accent); border-radius: 50%; position: absolute; left: 2px; transition: var(--transition); } .schedule-status.active .status-toggle { left: calc(100% - 22px); background-color: var(--text); } .modes { display: flex; justify-content: space-between; margin-top: 30px; gap: 10px; } .mode-card { flex: 1; background-color: rgba(0, 0, 0, 0.1); border-radius: 15px; padding: 20px; text-align: center; cursor: pointer; transition: var(--transition); display: flex; flex-direction: column; align-items: center; gap: 10px; } .mode-card:hover { background-color: rgba(255, 255, 255, 0.05); transform: translateY(-5px); box-shadow: var(--glow); } .mode-icon { font-size: 1.8rem; margin-bottom: 5px; } .mode-name { font-size: 0.9rem; font-weight: 400; } .brightness-slider { position: absolute; bottom: 30px; left: 50%; transform: translateX(-50%); width: 80%; display: flex; align-items: center; gap: 15px; } .brightness-icon { font-size: 1.3rem; color: var(--text-secondary); } input[type="range"] { -webkit-appearance: none; width: 100%; height: 4px; background-color: var(--secondary); border-radius: 5px; outline: none; } input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; width: 18px; height: 18px; background-color: var(--text); border-radius: 50%; cursor: pointer; box-shadow: 0 0 5px rgba(0, 0, 0, 0.3); transition: var(--transition); } input[type="range"]::-webkit-slider-thumb:hover { transform: scale(1.2); } .ambient-effects { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; opacity: 0.2; z-index: -1; } .ambient-effect { position: absolute; border-radius: 50%; opacity: 0; background: radial-gradient(circle, rgba(255, 255, 255, 0.2) 0%, transparent 70%); animation: ambient 8s ease-in-out infinite; } .ambient-effect:nth-child(1) { width: 300px; height: 300px; top: -100px; left: -100px; animation-delay: 0s; } .ambient-effect:nth-child(2) { width: 200px; height: 200px; bottom: -50px; right: -50px; animation-delay: 2s; } .ambient-effect:nth-child(3) { width: 150px; height: 150px; top: 50%; left: 20%; animation-delay: 4s; } .lowlight-mode { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0); pointer-events: none; transition: var(--transition); z-index: 10; } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.2; } } @keyframes ambient { 0% { transform: scale(0.8); opacity: 0; } 50% { opacity: 0.2; } 100% { transform: scale(1.2); opacity: 0; } } @media (max-width: 600px) { .container { padding: 20px; border-radius: 15px; } .time { font-size: 4rem; } .modes { flex-wrap: wrap; } .mode-card { flex: 1 0 45%; padding: 15px; } .schedule-item { padding: 10px; } } @media (max-width: 400px) { .time { font-size: 3.5rem; } .clock-section { padding: 20px 0; } .schedules { margin-top: 20px; } .mode-card { flex: 1 0 100%; margin-bottom: 10px; } } </style> </head> <body> <div class="container"> <div class="clock-section"> <div class="date" id="date">Wednesday, June 12</div> <div class="time"> <span id="hours">08</span><span class="time-separator">:</span><span id="minutes">45</span> <span class="time-period" id="period">AM</span> </div> <div class="weather"> <i class="icon">☀️</i> <span>24°C • Feels like 26°C</span> </div> </div> <div class="mode-indicator"> <div class="indicator active"></div> <div class="indicator"></div> <div class="indicator"></div> </div> <div class="schedules"> <div class="schedules-header"> <div class="schedules-title">Today's Schedule</div> <div class="schedules-actions"> <button class="action-btn">+</button> <button class="action-btn">⋮</button> </div> </div> <div class="schedule-list"> <div class="schedule-item"> <div class="schedule-info"> <div class="schedule-name">Morning Startup</div> <div class="schedule-time">7:00 AM • Lights & Blinds</div> </div> <div class="schedule-status active"> <div class="status-toggle"></div> </div> </div> <div class="schedule-item"> <div class="schedule-info"> <div class="schedule-name">Evening Mode</div> <div class="schedule-time">6:30 PM • Full System</div> </div> <div class="schedule-status active"> <div class="status-toggle"></div> </div> </div> <div class="schedule-item"> <div class="schedule-info"> <div class="schedule-name">Night Security</div> <div class="schedule-time">11:00 PM • Security System</div> </div> <div class="schedule-status"> <div class="status-toggle"></div> </div> </div> </div> </div> <div class="modes"> <div class="mode-card"> <div class="mode-icon">💤</div> <div class="mode-name">Sleep</div> </div> <div class="mode-card"> <div class="mode-icon">🏠</div> <div class="mode-name">Home</div> </div> <div class="mode-card"> <div class="mode-icon">🌙</div> <div class="mode-name">Away</div> </div> </div> <div class="brightness-slider"> <div class="brightness-icon">🔆</div> <input type="range" min="0" max="100" value="70" id="brightness-control"> <div class="brightness-icon">🔅</div> </div> <div class="ambient-effects"> <div class="ambient-effect"></div> <div class="ambient-effect"></div> <div class="ambient-effect"></div> </div> <div class="lowlight-mode" id="lowlight"></div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Initialize time and date updateTime(); setInterval(updateTime, 1000); // Set current date const now = new Date(); const options = { weekday: 'long', month: 'long', day: 'numeric' }; document.getElementById('date').textContent = now.toLocaleDateString('en-US', options); // Handle toggle switches const scheduleStatuses = document.querySelectorAll('.schedule-status'); scheduleStatuses.forEach(status => { status.addEventListener('click', function() { this.classList.toggle('active'); // Add subtle animation for toggle this.querySelector('.status-toggle').style.transition = 'left 0.3s cubic-bezier(0.34, 1.56, 0.64, 1)'; setTimeout(() => { this.querySelector('.status-toggle').style.transition = 'var(--transition)'; }, 300); }); }); // Mode cards selection const modeCards = document.querySelectorAll('.mode-card'); const indicators = document.querySelectorAll('.indicator'); modeCards.forEach((card, index) => { card.addEventListener('click', function() { // Reset all cards modeCards.forEach(c => c.style.backgroundColor = 'rgba(0, 0, 0, 0.1)'); indicators.forEach(i => i.classList.remove('active')); // Activate selected card this.style.backgroundColor = 'rgba(255, 255, 255, 0.05)'; indicators[index].classList.add('active'); // Show activation ripple const ripple = document.createElement('div'); ripple.style.position = 'absolute'; ripple.style.borderRadius = '50%'; ripple.style.backgroundColor = 'rgba(255, 255, 255, 0.2)'; ripple.style.transform = 'translate(-50%, -50%)'; ripple.style.pointerEvents = 'none'; ripple.style.width = '10px'; ripple.style.height = '10px'; ripple.style.left = '50%'; ripple.style.top = '50%'; this.style.position = 'relative'; this.style.overflow = 'hidden'; this.appendChild(ripple); ripple.animate( [ { width: '10px', height: '10px', opacity: 1 }, { width: '200px', height: '200px', opacity: 0 } ], { duration: 800, easing: 'cubic-bezier(0.22, 1, 0.36, 1)' } ).onfinish = () => ripple.remove(); }); }); // Brightness control const brightnessControl = document.getElementById('brightness-control'); const lowlight = document.getElementById('lowlight'); brightnessControl.addEventListener('input', function() { const brightnessValue = this.value; const opacity = (100 - brightnessValue) / 100 * 0.7; // Max 70% darkness lowlight.style.backgroundColor = `rgba(0, 0, 0, ${opacity})`; // Optimize for low light reading when brightness is low if (brightnessValue < 30) { document.documentElement.style.setProperty('--text', '#ffffff'); document.documentElement.style.setProperty('--text-secondary', '#d0d0d0'); } else { document.documentElement.style.setProperty('--text', '#f5f5f5'); document.documentElement.style.setProperty('--text-secondary', '#a0a0a0'); } }); // Animate time updates function animateTimeChange(element, newValue) { const current = element.textContent; if (current !== newValue) { // Create temporary overlay element for transition const overlay = document.createElement('span'); overlay.style.position = 'absolute'; overlay.style.top = '0'; overlay.style.left = '0'; overlay.style.width = '100%'; overlay.style.height = '100%'; overlay.style.display = 'flex'; overlay.style.alignItems = 'center'; overlay.style.justifyContent = 'center'; overlay.textContent = newValue; overlay.style.opacity = '0'; overlay.style.transform = 'translateY(10px)'; overlay.style.transition = 'all 0.3s ease'; element.style.position = 'relative'; element.appendChild(overlay); // Animate out current value element.style.transition = 'all 0.3s ease'; element.style.opacity = '0'; element.style.transform = 'translateY(-10px)'; // Animate in new value setTimeout(() => { overlay.style.opacity = '1'; overlay.style.transform = 'translateY(0)'; }, 50); // Update actual content setTimeout(() => { element.textContent = newValue; element.style.opacity = '1'; element.style.transform = 'translateY(0)'; element.style.transition = ''; }, 300); } } // Update time function function updateTime() { const now = new Date(); let hours = now.getHours(); const minutes = now.getMinutes().toString().padStart(2, '0'); const period = hours >= 12 ? 'PM' : 'AM'; hours = hours % 12; hours = hours ? hours.toString().padStart(2, '0') : '12'; animateTimeChange(document.getElementById('hours'), hours); animateTimeChange(document.getElementById('minutes'), minutes); document.getElementById('period').textContent = period; } // Touch interface const container = document.querySelector('.container'); container.addEventListener('touchstart', handleTouchStart, false); container.addEventListener('touchmove', handleTouchMove, false); let xDown = null; let yDown = null; function handleTouchStart(evt) { xDown = evt.touches[0].clientX; yDown = evt.touches[0].clientY; } function handleTouchMove(evt) { if (!xDown || !yDown) { return; } const xUp = evt.touches[0].clientX; const yUp = evt.touches[0].clientY; const xDiff = xDown - xUp; const yDiff = yDown - yUp; if (Math.abs(xDiff) > Math.abs(yDiff)) { if (xDiff > 0) { // Swipe left - next mode nextMode(); } else { // Swipe right - previous mode prevMode(); } } xDown = null; yDown = null; } function nextMode() { let activeIndex = -1; indicators.forEach((ind, i) => { if (ind.classList.contains('active')) activeIndex = i; }); if (activeIndex < indicators.length - 1) { modeCards[activeIndex + 1].click(); } } function prevMode() { let activeIndex = -1; indicators.forEach((ind, i) => { if (ind.classList.contains('active')) activeIndex = i; }); if (activeIndex > 0) { modeCards[activeIndex - 1].click(); } } // Double tap to show/hide schedules let lastTap = 0; const schedules = document.querySelector('.schedules'); container.addEventListener('click', function(e) { const currentTime = new Date().getTime(); const tapLength = currentTime - lastTap; if (tapLength < 300 && tapLength > 0) { // Double tap schedules.style.display = schedules.style.display === 'none' ? 'block' : 'none'; e.preventDefault(); } lastTap = currentTime; }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>FitPulse - Fitness Clock</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { width: 100%; height: 100vh; display: flex; justify-content: center; align-items: center; background-color: #1a1a1a; overflow: hidden; } .container { width: 700px; height: 700px; display: flex; flex-direction: column; justify-content: center; align-items: center; padding: 20px; color: white; position: relative; background: linear-gradient(145deg, #232323, #1c1c1c); } .fitness-tracker { width: 320px; height: 380px; border-radius: 40px; background: linear-gradient(145deg, #222, #111); box-shadow: 0 15px 35px rgba(0, 0, 0, 0.5), 0 5px 15px rgba(0, 0, 0, 0.3), inset 0 1px 1px rgba(255, 255, 255, 0.1); display: flex; flex-direction: column; align-items: center; justify-content: center; position: relative; overflow: hidden; padding: 20px; transition: transform 0.3s ease; } .fitness-tracker:hover { transform: scale(1.02); } .fitness-tracker::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(45deg, transparent, rgba(255, 255, 255, 0.03), transparent); pointer-events: none; } .screen { width: 280px; height: 340px; border-radius: 35px; background: #000; position: relative; overflow: hidden; display: flex; flex-direction: column; align-items: center; justify-content: flex-start; padding: 20px; } .time-display { font-size: 54px; font-weight: 700; margin-top: 10px; color: #fff; text-shadow: 0 0 10px rgba(0, 255, 200, 0.7); letter-spacing: 2px; transition: all 0.3s ease; position: relative; z-index: 5; } .am-pm { font-size: 16px; font-weight: 600; color: #0fe; margin-top: -5px; } .date-display { font-size: 14px; font-weight: 500; margin-top: 5px; color: rgba(255, 255, 255, 0.7); letter-spacing: 1px; } .metrics-container { display: flex; justify-content: space-between; width: 100%; margin-top: 20px; padding: 0 10px; } .metric { display: flex; flex-direction: column; align-items: center; position: relative; } .metric-icon { width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; background: rgba(15, 238, 238, 0.15); border-radius: 50%; margin-bottom: 5px; position: relative; transition: all 0.3s ease; } .metric-icon svg { width: 16px; height: 16px; fill: #0fe; } .metric-value { font-size: 18px; font-weight: 700; color: white; } .metric-label { font-size: 10px; color: rgba(255, 255, 255, 0.6); margin-top: 3px; } .heart-rate-ring { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 220px; height: 220px; border-radius: 50%; background: transparent; border: 3px solid rgba(15, 238, 238, 0.05); z-index: 1; pointer-events: none; } .heart-rate-progress { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 220px; height: 220px; border-radius: 50%; background: transparent; z-index: 2; pointer-events: none; } .time-zone-selector { display: flex; justify-content: center; gap: 10px; margin-top: 20px; width: 100%; } .time-zone-btn { padding: 6px 8px; border-radius: 20px; background: rgba(15, 238, 238, 0.1); color: rgba(255, 255, 255, 0.8); font-size: 12px; border: none; cursor: pointer; transition: all 0.2s ease; outline: none; } .time-zone-btn:hover, .time-zone-btn.active { background: rgba(15, 238, 238, 0.3); color: white; } .activity-ring { position: absolute; width: 240px; height: 240px; border-radius: 50%; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 0; } .workout-mode { margin-top: 30px; width: 100%; display: flex; flex-direction: column; align-items: center; } .workout-status { font-size: 12px; color: #0fe; margin-bottom: 5px; text-transform: uppercase; font-weight: 600; letter-spacing: 1px; } .workout-type { font-size: 16px; color: white; font-weight: 600; margin-bottom: 10px; } .workout-timer { font-size: 20px; font-weight: 700; color: white; } .mode-toggle { position: absolute; top: 15px; right: 20px; background: rgba(15, 238, 238, 0.15); border: none; color: #0fe; font-size: 12px; padding: 5px 10px; border-radius: 15px; cursor: pointer; transition: all 0.2s ease; z-index: 10; } .mode-toggle:hover { background: rgba(15, 238, 238, 0.3); } .pulse-effect { position: absolute; width: 240px; height: 240px; border-radius: 50%; background: transparent; border: 2px solid rgba(15, 238, 238, 0.2); top: 50%; left: 50%; transform: translate(-50%, -50%) scale(0.8); opacity: 0; z-index: 0; animation: pulse 2s ease-out infinite; } @keyframes pulse { 0% { transform: translate(-50%, -50%) scale(0.8); opacity: 0.8; } 100% { transform: translate(-50%, -50%) scale(1.2); opacity: 0; } } .buttons-panel { position: absolute; bottom: 20px; width: 100%; display: flex; justify-content: space-around; padding: 0 20px; } .control-btn { width: 40px; height: 40px; border-radius: 50%; background: rgba(15, 238, 238, 0.1); border: none; color: white; font-size: 16px; cursor: pointer; transition: all 0.2s ease; display: flex; justify-content: center; align-items: center; } .control-btn:hover { background: rgba(15, 238, 238, 0.3); transform: scale(1.1); } .control-btn svg { width: 18px; height: 18px; fill: #0fe; } .notification { position: absolute; top: 10px; left: 50%; transform: translateX(-50%); padding: 8px 15px; background: rgba(15, 238, 238, 0.15); border-radius: 20px; color: white; font-size: 12px; opacity: 0; transition: all 0.3s ease; z-index: 20; white-space: nowrap; } .notification.show { opacity: 1; top: 20px; } .battery-indicator { position: absolute; top: 15px; left: 20px; display: flex; align-items: center; gap: 5px; } .battery-icon { width: 20px; height: 10px; border: 1px solid rgba(255, 255, 255, 0.5); border-radius: 2px; position: relative; } .battery-icon::after { content: ''; position: absolute; right: -3px; top: 2px; width: 2px; height: 6px; background: rgba(255, 255, 255, 0.5); border-radius: 0 1px 1px 0; } .battery-level { position: absolute; left: 1px; top: 1px; bottom: 1px; width: calc(85% - 2px); background: #0fe; border-radius: 1px; } .battery-percentage { font-size: 10px; color: rgba(255, 255, 255, 0.7); } .tap-hint { position: absolute; width: 100%; text-align: center; bottom: 60px; font-size: 11px; color: rgba(255, 255, 255, 0.4); opacity: 0; animation: fadeInOut 5s ease-in-out infinite; } @keyframes fadeInOut { 0%, 100% { opacity: 0; } 50% { opacity: 0.7; } } @media (max-width: 400px) { .fitness-tracker { width: 280px; height: 340px; } .screen { width: 240px; height: 300px; } .time-display { font-size: 42px; } .heart-rate-ring, .heart-rate-progress, .activity-ring, .pulse-effect { width: 200px; height: 200px; } .metric-icon { width: 24px; height: 24px; } .metric-value { font-size: 16px; } } </style> </head> <body> <div class="container"> <div class="fitness-tracker"> <div class="screen"> <div class="battery-indicator"> <div class="battery-icon"> <div class="battery-level"></div> </div> <div class="battery-percentage">85%</div> </div> <button class="mode-toggle">WORKOUT</button> <div class="notification" id="notification">Switching to New York time</div> <div class="heart-rate-ring"></div> <div class="heart-rate-progress" id="heartRateProgress"></div> <div class="pulse-effect"></div> <div class="time-display" id="timeDisplay">12:45</div> <div class="am-pm" id="amPmDisplay">PM</div> <div class="date-display" id="dateDisplay">THU, JUN 15</div> <div class="metrics-container"> <div class="metric"> <div class="metric-icon"> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/> </svg> </div> <div class="metric-value" id="heartRateValue">78</div> <div class="metric-label">BPM</div> </div> <div class="metric"> <div class="metric-icon"> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M13.5 5.5c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zM9.8 8.9L7 23h2.1l1.8-8 2.1 2v6h2v-7.5l-2.1-2 .6-3C14.8 12 16.8 13 19 13v-2c-1.9 0-3.5-1-4.3-2.4l-1-1.6c-.4-.6-1-1-1.7-1-.3 0-.5.1-.8.1L6 8.3V13h2V9.6l1.8-.7"/> </svg> </div> <div class="metric-value" id="stepsValue">8,742</div> <div class="metric-label">STEPS</div> </div> <div class="metric"> <div class="metric-icon"> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zM16 18H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"/> </svg> </div> <div class="metric-value" id="caloriesValue">426</div> <div class="metric-label">KCAL</div> </div> </div> <div class="time-zone-selector"> <button class="time-zone-btn active" data-zone="local">LOCAL</button> <button class="time-zone-btn" data-zone="nyc">NYC</button> <button class="time-zone-btn" data-zone="lon">LDN</button> <button class="time-zone-btn" data-zone="tok">TKY</button> </div> <div class="workout-mode" style="display: none;"> <div class="workout-status">ACTIVE WORKOUT</div> <div class="workout-type">OUTDOOR RUN</div> <div class="workout-timer" id="workoutTimer">24:18</div> </div> <div class="tap-hint">Tap screen to toggle metrics</div> </div> <div class="buttons-panel"> <button class="control-btn" id="menuBtn"> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"/> </svg> </button> <button class="control-btn" id="startBtn"> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M8 5v14l11-7z"/> </svg> </button> <button class="control-btn" id="statsBtn"> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 7v2h14V7H7z"/> </svg> </button> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Initial setup updateTime(); updateHeartRateRing(); startHeartRateSimulation(); setInterval(updateTime, 1000); // Time zone selector const timeZoneButtons = document.querySelectorAll('.time-zone-btn'); timeZoneButtons.forEach(button => { button.addEventListener('click', function() { timeZoneButtons.forEach(btn => btn.classList.remove('active')); this.classList.add('active'); showNotification(`Switching to ${getTimeZoneName(this.dataset.zone)} time`); updateTime(); }); }); // Mode toggle const modeToggle = document.querySelector('.mode-toggle'); const workoutMode = document.querySelector('.workout-mode'); const timeDisplay = document.querySelector('.time-display'); const amPmDisplay = document.querySelector('.am-pm'); const dateDisplay = document.querySelector('.date-display'); const timeZoneSelector = document.querySelector('.time-zone-selector'); modeToggle.addEventListener('click', function() { if (workoutMode.style.display === 'none') { workoutMode.style.display = 'flex'; timeDisplay.style.fontSize = '36px'; timeDisplay.style.marginTop = '5px'; amPmDisplay.style.marginTop = '-10px'; dateDisplay.style.display = 'none'; timeZoneSelector.style.display = 'none'; modeToggle.textContent = 'CLOCK'; startWorkoutTimer(); } else { workoutMode.style.display = 'none'; timeDisplay.style.fontSize = '54px'; timeDisplay.style.marginTop = '10px'; amPmDisplay.style.marginTop = '-5px'; dateDisplay.style.display = 'block'; timeZoneSelector.style.display = 'flex'; modeToggle.textContent = 'WORKOUT'; clearInterval(workoutTimerInterval); } }); // Screen tap to toggle metrics const screen = document.querySelector('.screen'); const metricsContainer = document.querySelector('.metrics-container'); screen.addEventListener('click', function(e) { // Only handle clicks on the main screen area, not on buttons if (e.target === screen || e.target.closest('.time-display') || e.target.closest('.date-display')) { if (metricsContainer.style.opacity === '0') { metricsContainer.style.opacity = '1'; } else { metricsContainer.style.opacity = '0'; } } }); // Controls const startBtn = document.getElementById('startBtn'); const menuBtn = document.getElementById('menuBtn'); const statsBtn = document.getElementById('statsBtn'); startBtn.addEventListener('click', function() { if (workoutMode.style.display === 'none') { // If in clock mode, click the workout toggle modeToggle.click(); } else { // If already in workout mode, pause/resume the workout if (workoutPaused) { workoutPaused = false; startBtn.innerHTML = '<svg viewBox="0 0 24 24"><path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/></svg>'; } else { workoutPaused = true; startBtn.innerHTML = '<svg viewBox="0 0 24 24"><path d="M8 5v14l11-7z"/></svg>'; } } }); menuBtn.addEventListener('click', function() { showNotification('Menu accessed'); }); statsBtn.addEventListener('click', function() { showNotification('Stats dashboard opened'); }); // Heart rate progress animation let heartRateValue = 78; let heartRateDirection = 1; let heartRateProgress = document.getElementById('heartRateProgress'); let heartRateDisplay = document.getElementById('heartRateValue'); function updateHeartRateRing() { const circumference = 2 * Math.PI * 110; // radius is 110px const offset = circumference - (heartRateValue / 200) * circumference; heartRateProgress.style.background = `conic-gradient( ${getHeartRateColor(heartRateValue)} ${(heartRateValue / 200) * 360}deg, transparent ${(heartRateValue / 200) * 360}deg )`; } function getHeartRateColor(rate) { if (rate < 60) return '#3498db'; // Blue for low if (rate < 100) return '#2ecc71'; // Green for normal if (rate < 140) return '#f39c12'; // Orange for moderate return '#e74c3c'; // Red for high } function startHeartRateSimulation() { setInterval(() => { // Simulate heart rate changes const change = Math.random() * 2; if (heartRateValue > 110) heartRateDirection = -1; if (heartRateValue < 75) heartRateDirection = 1; heartRateValue += change * heartRateDirection; heartRateValue = Math.round(heartRateValue); heartRateDisplay.textContent = heartRateValue; updateHeartRateRing(); // Update step count occasionally if (Math.random() > 0.7) { const stepsValue = document.getElementById('stepsValue'); const currentSteps = parseInt(stepsValue.textContent.replace(',', '')); const newSteps = currentSteps + Math.floor(Math.random() * 10) + 1; stepsValue.textContent = newSteps.toLocaleString(); // Update calories based on steps const caloriesValue = document.getElementById('caloriesValue'); const currentCalories = parseInt(caloriesValue.textContent); const newCalories = Math.floor(newSteps / 20); caloriesValue.textContent = newCalories; } }, 2000); } // Workout timer functionality let workoutSeconds = 24 * 60 + 18; // Start at 24:18 let workoutTimerInterval; let workoutPaused = false; function startWorkoutTimer() { clearInterval(workoutTimerInterval); workoutTimerInterval = setInterval(() => { if (!workoutPaused) { workoutSeconds++; updateWorkoutTimer(); } }, 1000); } function updateWorkoutTimer() { const minutes = Math.floor(workoutSeconds / 60); const seconds = workoutSeconds % 60; document.getElementById('workoutTimer').textContent = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; } // Helper functions function updateTime() { const now = new Date(); const activeZone = document.querySelector('.time-zone-btn.active').dataset.zone; let displayTime; switch(activeZone) { case 'nyc': displayTime = new Date(now.toLocaleString('en-US', {timeZone: 'America/New_York'})); break; case 'lon': displayTime = new Date(now.toLocaleString('en-US', {timeZone: 'Europe/London'})); break; case 'tok': displayTime = new Date(now.toLocaleString('en-US', {timeZone: 'Asia/Tokyo'})); break; default: displayTime = now; } let hours = displayTime.getHours(); const minutes = displayTime.getMinutes(); const ampm = hours >= 12 ? 'PM' : 'AM'; hours = hours % 12; hours = hours ? hours : 12; // the hour '0' should be '12' document.getElementById('timeDisplay').textContent = `${hours}:${minutes.toString().padStart(2, '0')}`; document.getElementById('amPmDisplay').textContent = ampm; const days = ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT']; const months = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC']; document.getElementById('dateDisplay').textContent = `${days[displayTime.getDay()]}, ${months[displayTime.getMonth()]} ${displayTime.getDate()}`; } function getTimeZoneName(zone) { switch(zone) { case 'nyc': return 'New York'; case 'lon': return 'London'; case 'tok': return 'Tokyo'; default: return 'Local'; } } function showNotification(message) { const notification = document.getElementById('notification'); notification.textContent = message; notification.classList.add('show'); setTimeout(() => { notification.classList.remove('show'); }, 2000); } }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Financial Trading Dashboard Clock</title> <style> :root { --neon-blue: #00f3ff; --neon-green: #00ff9d; --neon-red: #ff355e; --neon-yellow: #f6fa70; --dark-bg: #0a0e17; --darker-bg: #060911; --panel-bg: rgba(16, 23, 41, 0.7); --text-color: #e0e0e0; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', 'Roboto', sans-serif; } body { background: var(--dark-bg); color: var(--text-color); height: 100vh; display: flex; flex-direction: column; justify-content: center; align-items: center; overflow-x: hidden; position: relative; } .container { width: 100%; max-width: 700px; height: 700px; padding: 20px; display: flex; flex-direction: column; position: relative; overflow: hidden; } .grid-pattern { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-image: linear-gradient(rgba(16, 23, 41, 0.3) 1px, transparent 1px), linear-gradient(90deg, rgba(16, 23, 41, 0.3) 1px, transparent 1px); background-size: 20px 20px; z-index: -1; } .blur-circle { position: absolute; border-radius: 50%; filter: blur(60px); z-index: -1; } .blur-circle-1 { width: 300px; height: 300px; background: rgba(0, 243, 255, 0.15); top: -100px; left: -100px; } .blur-circle-2 { width: 250px; height: 250px; background: rgba(0, 255, 157, 0.15); bottom: -80px; right: -80px; } .main-clock { background: var(--panel-bg); border-radius: 12px; border: 1px solid rgba(255, 255, 255, 0.1); padding: 20px; margin-bottom: 20px; display: flex; flex-direction: column; align-items: center; box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2); position: relative; overflow: hidden; } .main-clock::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 3px; background: linear-gradient(90deg, var(--neon-blue), var(--neon-green)); } .time-display { font-size: 4rem; font-weight: 700; margin: 10px 0; color: white; text-shadow: 0 0 10px rgba(0, 243, 255, 0.7); letter-spacing: 2px; } .date-display { font-size: 1.2rem; margin-bottom: 10px; color: rgba(255, 255, 255, 0.7); } .location-display { display: flex; align-items: center; margin-bottom: 15px; } .location-dot { width: 10px; height: 10px; border-radius: 50%; background-color: var(--neon-green); margin-right: 8px; animation: pulse 2s infinite; } .market-status { font-size: 0.9rem; padding: 5px 12px; border-radius: 20px; margin-top: 10px; } .market-open { background-color: rgba(0, 255, 157, 0.2); color: var(--neon-green); border: 1px solid rgba(0, 255, 157, 0.3); } .market-closed { background-color: rgba(255, 53, 94, 0.2); color: var(--neon-red); border: 1px solid rgba(255, 53, 94, 0.3); } .market-pre { background-color: rgba(246, 250, 112, 0.2); color: var(--neon-yellow); border: 1px solid rgba(246, 250, 112, 0.3); } .timezone-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px; width: 100%; } .timezone-card { background: var(--panel-bg); border-radius: 8px; border: 1px solid rgba(255, 255, 255, 0.05); padding: 15px; cursor: pointer; transition: all 0.3s ease; position: relative; overflow: hidden; } .timezone-card:hover { transform: translateY(-5px); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3); border-color: rgba(0, 243, 255, 0.3); } .timezone-card.active { border: 1px solid var(--neon-blue); box-shadow: 0 0 15px rgba(0, 243, 255, 0.3); } .timezone-card.active::after { content: ''; position: absolute; top: 0; right: 0; width: 10px; height: 10px; background: var(--neon-blue); border-radius: 50%; margin: 10px; } .timezone-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; } .timezone-name { font-weight: 600; font-size: 1rem; } .timezone-time { font-size: 1.5rem; font-weight: 700; margin: 5px 0; } .timezone-details { display: flex; justify-content: space-between; font-size: 0.8rem; color: rgba(255, 255, 255, 0.6); } .timezone-indicator { height: 3px; background: var(--neon-blue); border-radius: 3px; margin-top: 10px; width: 30%; transition: width 0.3s ease; } .timezone-indicator.market-open { background: var(--neon-green); width: 100%; } .timezone-indicator.market-closed { background: var(--neon-red); width: 30%; } .timezone-indicator.market-pre { background: var(--neon-yellow); width: 60%; } .market-insights { background: var(--panel-bg); border-radius: 12px; border: 1px solid rgba(255, 255, 255, 0.1); padding: 15px; margin-top: 20px; } .market-insights-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; } .market-insights-title { font-size: 1rem; font-weight: 600; } .market-insights-content { font-size: 0.9rem; color: rgba(255, 255, 255, 0.7); line-height: 1.4; } .upcoming-event { display: flex; align-items: center; margin-top: 10px; padding: 8px; border-radius: 6px; background: rgba(0, 243, 255, 0.1); border-left: 3px solid var(--neon-blue); } .event-time { font-weight: 600; margin-right: 10px; color: var(--neon-blue); } @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(0, 255, 157, 0.7); } 70% { box-shadow: 0 0 0 10px rgba(0, 255, 157, 0); } 100% { box-shadow: 0 0 0 0 rgba(0, 255, 157, 0); } } @keyframes flash { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } .flash-market-open { animation: flash 2s infinite; } .settings-button { position: absolute; top: 20px; right: 20px; background: none; border: none; color: rgba(255, 255, 255, 0.6); font-size: 1.2rem; cursor: pointer; transition: all 0.3s ease; } .settings-button:hover { color: var(--neon-blue); transform: rotate(180deg); } @media screen and (max-width: 600px) { .time-display { font-size: 3rem; } .timezone-grid { grid-template-columns: 1fr; } } </style> </head> <body> <div class="container"> <div class="grid-pattern"></div> <div class="blur-circle blur-circle-1"></div> <div class="blur-circle blur-circle-2"></div> <div class="main-clock"> <div class="date-display" id="date-display">Loading date...</div> <div class="time-display" id="time-display">00:00:00</div> <div class="location-display"> <div class="location-dot"></div> <span id="main-location">New York (EDT)</span> </div> <div class="market-status" id="market-status">Checking market status...</div> <button class="settings-button">⚙</button> </div> <div class="timezone-grid"> <div class="timezone-card" data-timezone="Europe/London" data-market="London"> <div class="timezone-header"> <div class="timezone-name">London (BST)</div> </div> <div class="timezone-time">--:--:--</div> <div class="timezone-details"> <span>LSE</span> <span class="timezone-market-status">--</span> </div> <div class="timezone-indicator"></div> </div> <div class="timezone-card" data-timezone="Asia/Tokyo" data-market="Tokyo"> <div class="timezone-header"> <div class="timezone-name">Tokyo (JST)</div> </div> <div class="timezone-time">--:--:--</div> <div class="timezone-details"> <span>TSE</span> <span class="timezone-market-status">--</span> </div> <div class="timezone-indicator"></div> </div> <div class="timezone-card" data-timezone="Asia/Shanghai" data-market="Shanghai"> <div class="timezone-header"> <div class="timezone-name">Shanghai (CST)</div> </div> <div class="timezone-time">--:--:--</div> <div class="timezone-details"> <span>SSE</span> <span class="timezone-market-status">--</span> </div> <div class="timezone-indicator"></div> </div> <div class="timezone-card" data-timezone="Europe/Frankfurt" data-market="Frankfurt"> <div class="timezone-header"> <div class="timezone-name">Frankfurt (CEST)</div> </div> <div class="timezone-time">--:--:--</div> <div class="timezone-details"> <span>FWB</span> <span class="timezone-market-status">--</span> </div> <div class="timezone-indicator"></div> </div> </div> <div class="market-insights"> <div class="market-insights-header"> <div class="market-insights-title">Market Insights</div> </div> <div class="market-insights-content"> Key market events for today's trading session. </div> <div class="upcoming-event"> <span class="event-time" id="next-event-time">14:30</span> <span id="next-event-desc">US Jobless Claims Report</span> </div> </div> </div> <script> // Market hours (in local timezone for each market) const marketHours = { 'New York': { open: 9.5, close: 16 }, // 9:30 AM to 4:00 PM 'London': { open: 8, close: 16.5 }, // 8:00 AM to 4:30 PM 'Tokyo': { open: 9, close: 15 }, // 9:00 AM to 3:00 PM 'Shanghai': { open: 9.5, close: 15 }, // 9:30 AM to 3:00 PM 'Frankfurt': { open: 9, close: 17.5 } // 9:00 AM to 5:30 PM }; // Market events for today const marketEvents = [ { time: "8:30", description: "EU Economic Forecast" }, { time: "10:00", description: "ECB Monetary Policy Statement" }, { time: "14:30", description: "US Jobless Claims Report" }, { time: "16:00", description: "Fed Chair Powell Speech" } ]; // Set the next upcoming event function setUpcomingEvent() { const now = new Date(); const currentHour = now.getHours(); const currentMinute = now.getMinutes(); const currentTime = currentHour + currentMinute/60; // Find the next event let nextEvent = null; for (const event of marketEvents) { const [eventHour, eventMinute] = event.time.split(':').map(Number); const eventTime = eventHour + eventMinute/60; if (eventTime > currentTime) { nextEvent = event; break; } } if (nextEvent) { document.getElementById('next-event-time').textContent = nextEvent.time; document.getElementById('next-event-desc').textContent = nextEvent.description; } else { document.getElementById('next-event-time').textContent = "EOD"; document.getElementById('next-event-desc').textContent = "No more events scheduled for today"; } } // Initialize the dashboard function init() { updateMainClock(); updateTimezoneClocks(); setUpcomingEvent(); // Set up click handlers for timezone cards document.querySelectorAll('.timezone-card').forEach(card => { card.addEventListener('click', function() { const timezone = this.dataset.timezone; const market = this.dataset.market; // Update main clock with this timezone document.getElementById('main-location').textContent = `${market} (${timezone.split('/')[1]})`; document.querySelectorAll('.timezone-card').forEach(c => c.classList.remove('active')); this.classList.add('active'); updateMainClock(timezone); checkMarketStatus(timezone, market); }); }); // Set intervals for updates setInterval(updateMainClock, 1000); setInterval(updateTimezoneClocks, 1000); setInterval(setUpcomingEvent, 60000); // Update upcoming event every minute } // Format time for display function formatTime(date) { return date.toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' }); } // Format date for display function formatDate(date) { return date.toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }); } // Update the main clock function updateMainClock(timezone = 'America/New_York') { const now = new Date(); // Get time in the specified timezone const options = { timeZone: timezone }; const timeString = now.toLocaleTimeString('en-US', { ...options, hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' }); const dateString = now.toLocaleDateString('en-US', { ...options, weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }); document.getElementById('time-display').textContent = timeString; document.getElementById('date-display').textContent = dateString; // Check market status for the main display const market = document.getElementById('main-location').textContent.split(' ')[0]; checkMarketStatus(timezone, market); } // Update all timezone clocks function updateTimezoneClocks() { document.querySelectorAll('.timezone-card').forEach(card => { const timezone = card.dataset.timezone; const market = card.dataset.market; const now = new Date(); // Get time in the specified timezone const options = { timeZone: timezone }; const timeString = now.toLocaleTimeString('en-US', { ...options, hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' }); card.querySelector('.timezone-time').textContent = timeString; // Check market status for each timezone const timeElements = timeString.split(':'); const hours = parseFloat(timeElements[0]) + parseFloat(timeElements[1])/60; const marketHour = marketHours[market]; const statusElement = card.querySelector('.timezone-market-status'); const indicatorElement = card.querySelector('.timezone-indicator'); if (marketHour) { if (hours >= marketHour.open && hours < marketHour.close) { statusElement.textContent = "OPEN"; indicatorElement.className = "timezone-indicator market-open"; } else if (hours >= marketHour.open - 1 && hours < marketHour.open) { statusElement.textContent = "PRE-MKT"; indicatorElement.className = "timezone-indicator market-pre"; } else { statusElement.textContent = "CLOSED"; indicatorElement.className = "timezone-indicator market-closed"; } } }); } // Check market status for the main display function checkMarketStatus(timezone, marketName) { const now = new Date(); const options = { timeZone: timezone }; const timeString = now.toLocaleTimeString('en-US', { ...options, hour12: false, hour: '2-digit', minute: '2-digit' }); const timeElements = timeString.split(':'); const hours = parseFloat(timeElements[0]) + parseFloat(timeElements[1])/60; const marketHour = marketHours[marketName]; const statusElement = document.getElementById('market-status'); if (marketHour) { if (hours >= marketHour.open && hours < marketHour.close) { statusElement.textContent = "MARKET OPEN"; statusElement.className = "market-status market-open flash-market-open"; } else if (hours >= marketHour.open - 1 && hours < marketHour.open) { statusElement.textContent = "PRE-MARKET"; statusElement.className = "market-status market-pre"; } else { statusElement.textContent = "MARKET CLOSED"; statusElement.className = "market-status market-closed"; } } } // When document is ready, initialize the dashboard document.addEventListener('DOMContentLoaded', init); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Event Management Scheduling Clock</title> <style> :root { --primary: #2c3e50; --secondary: #34495e; --accent: #3498db; --light: #ecf0f1; --highlight: #e74c3c; --success: #2ecc71; --warning: #f39c12; --text: #2c3e50; --shadow: rgba(0, 0, 0, 0.1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', 'Segoe UI', sans-serif; } body { background-color: var(--light); color: var(--text); display: flex; justify-content: center; align-items: center; min-height: 700px; overflow: hidden; padding: 1rem; } .event-scheduler { width: 100%; max-width: 650px; height: 650px; background: linear-gradient(135deg, #fff, #f7f9fc); border-radius: 24px; box-shadow: 0 12px 30px var(--shadow); display: flex; flex-direction: column; overflow: hidden; position: relative; } .event-header { padding: 1.5rem; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid rgba(0, 0, 0, 0.05); } .event-title { font-size: 1.5rem; font-weight: 700; color: var(--primary); } .event-subtitle { font-size: 0.9rem; opacity: 0.7; margin-top: 0.25rem; } .clock-container { display: flex; align-items: center; gap: 10px; } .clock { font-size: 1.2rem; font-weight: 700; letter-spacing: 0.5px; background: linear-gradient(135deg, var(--primary), var(--accent)); -webkit-background-clip: text; background-clip: text; color: transparent; } .date-selector { display: flex; padding: 1rem 1.5rem; gap: 0.5rem; overflow-x: auto; scrollbar-width: none; position: relative; } .date-selector::-webkit-scrollbar { display: none; } .date-card { flex: 0 0 auto; padding: 0.75rem 1rem; background: rgba(255, 255, 255, 0.8); border-radius: 12px; cursor: pointer; transition: all 0.3s ease; border: 1px solid transparent; text-align: center; min-width: 75px; } .date-card:hover { transform: translateY(-3px); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); } .date-card.active { background: linear-gradient(135deg, var(--primary), var(--accent)); color: white; border-color: transparent; box-shadow: 0 6px 15px rgba(52, 152, 219, 0.25); } .day-name { font-size: 0.8rem; font-weight: 600; margin-bottom: 0.25rem; } .date-num { font-size: 1.2rem; font-weight: 700; } .timeline-container { flex: 1; padding: 0.5rem 1.5rem 1.5rem; overflow-y: auto; scrollbar-width: thin; } .timeline-container::-webkit-scrollbar { width: 4px; } .timeline-container::-webkit-scrollbar-thumb { background-color: rgba(0, 0, 0, 0.2); border-radius: 4px; } .event-timeline { position: relative; padding-left: 28px; } .event-timeline::before { content: ''; position: absolute; top: 0; left: 8px; width: 2px; height: 100%; background: linear-gradient(to bottom, var(--accent), rgba(52, 152, 219, 0.2)); } .event-item { margin-bottom: 1.25rem; position: relative; transition: all 0.3s ease; } .event-item:hover { transform: translateX(3px); } .event-item::before { content: ''; position: absolute; left: -28px; top: 12px; width: 16px; height: 16px; border-radius: 50%; background: white; border: 2px solid var(--accent); z-index: 1; } .event-item.now::before { background: var(--highlight); border-color: var(--highlight); box-shadow: 0 0 0 4px rgba(231, 76, 60, 0.2); } .event-item.past::before { background: var(--accent); border-color: var(--accent); } .event-time { font-size: 0.9rem; font-weight: 600; color: var(--primary); margin-bottom: 0.25rem; display: flex; align-items: center; gap: 0.5rem; } .event-status { font-size: 0.7rem; font-weight: 600; padding: 0.15rem 0.5rem; border-radius: 12px; text-transform: uppercase; } .status-now { background-color: rgba(231, 76, 60, 0.15); color: var(--highlight); } .status-upcoming { background-color: rgba(243, 156, 18, 0.15); color: var(--warning); } .status-past { background-color: rgba(46, 204, 113, 0.15); color: var(--success); } .event-card { padding: 1rem; background: white; border-radius: 12px; box-shadow: 0 4px 10px rgba(0, 0, 0, 0.03); border-left: 3px solid var(--accent); transition: all 0.3s ease; } .event-item.now .event-card { border-left-color: var(--highlight); background: linear-gradient(to right, rgba(231, 76, 60, 0.05), white); } .event-item.past .event-card { border-left-color: var(--success); opacity: 0.7; } .event-card:hover { box-shadow: 0 6px 15px rgba(0, 0, 0, 0.08); } .event-name { font-weight: 600; font-size: 1.1rem; margin-bottom: 0.5rem; } .event-details { display: flex; gap: 1rem; margin-top: 0.75rem; font-size: 0.85rem; } .event-location, .event-speaker { display: flex; align-items: center; gap: 0.35rem; color: var(--secondary); } .icon { opacity: 0.7; font-size: 0.95rem; } .action-button { margin-top: 0.75rem; padding: 0.5rem 1rem; background: linear-gradient(135deg, var(--accent), #2980b9); color: white; border: none; border-radius: 6px; font-weight: 600; font-size: 0.85rem; cursor: pointer; display: inline-flex; align-items: center; gap: 0.5rem; transition: all 0.3s ease; box-shadow: 0 4px 8px rgba(52, 152, 219, 0.2); } .action-button:hover { transform: translateY(-2px); box-shadow: 0 6px 12px rgba(52, 152, 219, 0.3); } .action-button.outline { background: transparent; color: var(--accent); border: 1px solid var(--accent); box-shadow: none; } .action-button.outline:hover { background: rgba(52, 152, 219, 0.05); } .event-description { font-size: 0.85rem; line-height: 1.4; color: var(--secondary); margin-bottom: 0.75rem; } .filter-bar { padding: 0.5rem 1.5rem; display: flex; align-items: center; justify-content: space-between; border-top: 1px solid rgba(0, 0, 0, 0.05); background: rgba(255, 255, 255, 0.7); backdrop-filter: blur(5px); } .filter-item { font-size: 0.85rem; padding: 0.5rem 0.75rem; border-radius: 6px; cursor: pointer; transition: all 0.2s ease; font-weight: 500; } .filter-item:hover { background: rgba(52, 152, 219, 0.1); } .filter-item.active { background: var(--accent); color: white; } .tooltip { position: absolute; background: var(--primary); color: white; padding: 0.5rem 0.75rem; border-radius: 6px; font-size: 0.8rem; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); pointer-events: none; opacity: 0; transform: translateY(10px); transition: all 0.3s ease; z-index: 10; } .tooltip.visible { opacity: 1; transform: translateY(0); } .tooltip::after { content: ''; position: absolute; top: 100%; left: 50%; transform: translateX(-50%); border-width: 5px; border-style: solid; border-color: var(--primary) transparent transparent transparent; } .reminder-dot { position: absolute; top: 0; right: 0; width: 8px; height: 8px; background: var(--highlight); border-radius: 50%; animation: pulse 2s infinite; } @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(231, 76, 60, 0.6); } 70% { box-shadow: 0 0 0 6px rgba(231, 76, 60, 0); } 100% { box-shadow: 0 0 0 0 rgba(231, 76, 60, 0); } } .event-item.expanded .event-description { display: block; animation: fadeIn 0.3s ease; } @keyframes fadeIn { from { opacity: 0; transform: translateY(-5px); } to { opacity: 1; transform: translateY(0); } } .notification-badge { position: absolute; bottom: 1.5rem; right: 1.5rem; width: 56px; height: 56px; background: var(--primary); border-radius: 50%; display: flex; justify-content: center; align-items: center; color: white; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); cursor: pointer; transition: all 0.3s ease; z-index: 5; } .notification-badge:hover { transform: scale(1.05); background: var(--accent); } .notification-count { position: absolute; top: -5px; right: -5px; background: var(--highlight); color: white; width: 20px; height: 20px; border-radius: 50%; font-size: 0.7rem; display: flex; justify-content: center; align-items: center; font-weight: 700; } .notifications-panel { position: absolute; bottom: 70px; right: 1.5rem; width: 280px; background: white; border-radius: 15px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15); padding: 1rem; z-index: 4; transform: translateY(20px); opacity: 0; visibility: hidden; transition: all 0.3s ease; } .notifications-panel.show { transform: translateY(0); opacity: 1; visibility: visible; } .notification-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.75rem; padding-bottom: 0.75rem; border-bottom: 1px solid rgba(0, 0, 0, 0.05); } .notification-title { font-weight: 700; font-size: 1rem; } .clear-all { font-size: 0.75rem; color: var(--accent); cursor: pointer; } .notification-item { padding: 0.75rem 0; border-bottom: 1px solid rgba(0, 0, 0, 0.05); font-size: 0.85rem; } .notification-item:last-child { border-bottom: none; } .notification-time { font-size: 0.7rem; opacity: 0.7; margin-top: 0.25rem; } .notification-actions { display: flex; margin-top: 0.5rem; gap: 0.5rem; } .notification-btn { font-size: 0.7rem; padding: 0.25rem 0.5rem; border-radius: 4px; cursor: pointer; transition: all 0.2s ease; } .notification-btn.primary { background: var(--accent); color: white; } .notification-btn.secondary { background: rgba(0, 0, 0, 0.05); color: var(--text); } /* Responsive adjustments */ @media (max-width: 480px) { .event-scheduler { border-radius: 15px; height: 600px; } .event-header { padding: 1rem; } .event-title { font-size: 1.2rem; } .date-selector { padding: 0.75rem 1rem; } .date-card { padding: 0.5rem 0.75rem; min-width: 60px; } .timeline-container { padding: 0.5rem 1rem 1rem; } .event-card { padding: 0.75rem; } .event-name { font-size: 1rem; } .event-details { flex-direction: column; gap: 0.5rem; } } /* Animation for Time Display */ .animated-time { display: inline-block; animation: colorShift 10s infinite alternate; background-position: 0% 50%; } @keyframes colorShift { 0% { filter: hue-rotate(0deg); } 100% { filter: hue-rotate(30deg); } } /* Shine effect for active session */ .event-item.now::after { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 100%; background: linear-gradient( 45deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.1) 50%, rgba(255,255,255,0) 100% ); z-index: 1; animation: shine 2s infinite; } @keyframes shine { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } } </style> </head> <body> <div class="event-scheduler"> <div class="event-header"> <div> <h1 class="event-title">TechConf 2023 Schedule</h1> <p class="event-subtitle">Innovation Theater, San Francisco</p> </div> <div class="clock-container"> <div class="clock"><span class="animated-time" id="current-time">10:45 AM</span></div> </div> </div> <div class="date-selector" id="date-selector"> <div class="date-card" data-date="2023-11-10"> <div class="day-name">Fri</div> <div class="date-num">10</div> </div> <div class="date-card active" data-date="2023-11-11"> <div class="day-name">Sat</div> <div class="date-num">11</div> </div> <div class="date-card" data-date="2023-11-12"> <div class="day-name">Sun</div> <div class="date-num">12</div> </div> <div class="date-card" data-date="2023-11-13"> <div class="day-name">Mon</div> <div class="date-num">13</div> </div> <div class="date-card" data-date="2023-11-14"> <div class="day-name">Tue</div> <div class="date-num">14</div> </div> </div> <div class="timeline-container"> <div class="event-timeline"> <div class="event-item past"> <div class="event-time"> 09:00 AM - 09:45 AM <span class="event-status status-past">Completed</span> </div> <div class="event-card"> <h3 class="event-name">Opening Keynote: The Future of Tech</h3> <p class="event-description">Join industry visionary Sarah Chen as she explores emerging trends in technology and their impact on business transformation.</p> <div class="event-details"> <div class="event-location"> <span class="icon">📍</span> Main Stage </div> <div class="event-speaker"> <span class="icon">👤</span> Sarah Chen, CEO of FutureTech </div> </div> </div> </div> <div class="event-item past"> <div class="event-time"> 10:00 AM - 10:45 AM <span class="event-status status-past">Completed</span> </div> <div class="event-card"> <h3 class="event-name">AI Ethics in Product Development</h3> <p class="event-description">A critical examination of ethical considerations when implementing AI in modern product development workflows.</p> <div class="event-details"> <div class="event-location"> <span class="icon">📍</span> Workshop Room B </div> <div class="event-speaker"> <span class="icon">👤</span> Dr. Marcus Wong, AI Ethics Institute </div> </div> </div> </div> <div class="event-item now"> <div class="event-time"> 11:00 AM - 11:45 AM <span class="event-status status-now">Now</span> </div> <div class="event-card"> <h3 class="event-name">Designing Intuitive User Experiences</h3> <p class="event-description">Learn practical techniques for creating user interfaces that feel natural and reduce cognitive load for your users.</p> <div class="event-details"> <div class="event-location"> <span class="icon">📍</span> Design Lab </div> <div class="event-speaker"> <span class="icon">👤</span> Elena Rodriguez, UX Director </div> </div> <button class="action-button"> <span class="icon">📱</span> View Slides </button> </div> </div> <div class="event-item"> <div class="event-time"> 12:00 PM - 01:30 PM <span class="event-status status-upcoming">Upcoming</span> </div> <div class="event-card"> <h3 class="event-name">Networking Lunch: Tech Leaders Roundtable</h3> <p class="event-description">Connect with industry peers while enjoying a catered lunch in a structured networking format focused on collaboration.</p> <div class="event-details"> <div class="event-location"> <span class="icon">📍</span> Terrace Garden </div> <div class="event-speaker"> <span class="icon">👤</span> Facilitated by Conference Staff </div> </div> <div class="reminder-dot"></div> </div> </div> <div class="event-item"> <div class="event-time"> 01:45 PM - 02:30 PM <span class="event-status status-upcoming">Upcoming</span> </div> <div class="event-card"> <h3 class="event-name">Scaling Microservices Architecture</h3> <p class="event-description">Technical deep dive into efficient microservices architecture patterns for high-scale distributed applications.</p> <div class="event-details"> <div class="event-location"> <span class="icon">📍</span> Developer Theatre </div> <div class="event-speaker"> <span class="icon">👤</span> James Patel, Principal Architect </div> </div> <button class="action-button outline"> <span class="icon">🔔</span> Set Reminder </button> </div> </div> <div class="event-item"> <div class="event-time"> 02:45 PM - 03:30 PM <span class="event-status status-upcoming">Upcoming</span> </div> <div class="event-card"> <h3 class="event-name">Quantum Computing: Practical Applications</h3> <p class="event-description">Moving beyond theory: Explore real-world applications of quantum computing in cryptography, materials science, and optimization.</p> <div class="event-details"> <div class="event-location"> <span class="icon">📍</span> Innovation Lab </div> <div class="event-speaker"> <span class="icon">👤</span> Dr. Aisha Sharma, Quantum Research Lead </div> </div> <button class="action-button outline"> <span class="icon">🔔</span> Set Reminder </button> </div> </div> <div class="event-item"> <div class="event-time"> 04:00 PM - 05:30 PM <span class="event-status status-upcoming">Upcoming</span> </div> <div class="event-card"> <h3 class="event-name">Startup Showcase & Closing Reception</h3> <p class="event-description">Meet innovative startups and celebrate the conference conclusion with refreshments and networking opportunities.</p> <div class="event-details"> <div class="event-location"> <span class="icon">📍</span> Exhibition Hall </div> <div class="event-speaker"> <span class="icon">👤</span> Various Presenters </div> </div> <button class="action-button outline"> <span class="icon">🔔</span> Set Reminder </button> </div> </div> </div> </div> <div class="filter-bar"> <div class="filter-item active">All Sessions</div> <div class="filter-item">Workshops</div> <div class="filter-item">Keynotes</div> <div class="filter-item">Networking</div> </div> <div class="notification-badge" id="notification-badge"> <i class="icon">🔔</i> <div class="notification-count">3</div> </div> <div class="notifications-panel" id="notifications-panel"> <div class="notification-header"> <div class="notification-title">Notifications</div> <div class="clear-all">Clear All</div> </div> <div class="notification-item"> <div>Your next session "Networking Lunch" begins in 15 minutes</div> <div class="notification-time">Just now</div> <div class="notification-actions"> <div class="notification-btn primary">View</div> <div class="notification-btn secondary">Dismiss</div> </div> </div> <div class="notification-item"> <div>Slides for "AI Ethics in Product Development" are now available</div> <div class="notification-time">45 minutes ago</div> <div class="notification-actions"> <div class="notification-btn primary">Download</div> <div class="notification-btn secondary">Dismiss</div> </div> </div> <div class="notification-item"> <div>Room change: "Quantum Computing" moved to Innovation Lab</div> <div class="notification-time">1 hour ago</div> <div class="notification-actions"> <div class="notification-btn secondary">Dismiss</div> </div> </div> </div> <div class="tooltip" id="tooltip"></div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Update current time function updateTime() { const now = new Date(); let hours = now.getHours(); const minutes = now.getMinutes().toString().padStart(2, '0'); const ampm = hours >= 12 ? 'PM' : 'AM'; hours = hours % 12; hours = hours ? hours : 12; // Convert 0 to 12 document.getElementById('current-time').textContent = `${hours}:${minutes} ${ampm}`; } updateTime(); setInterval(updateTime, 60000); // Update every minute // Date selector functionality const dateSelector = document.getElementById('date-selector'); const dateCards = dateSelector.querySelectorAll('.date-card'); dateCards.forEach(card => { card.addEventListener('click', function() { // Remove active class from all cards dateCards.forEach(c => c.classList.remove('active')); // Add active class to clicked card this.classList.add('active'); // Here you would typically load events for the selected date // For this demo, we'll just show a tooltip showTooltip(this, `Loading events for ${this.querySelector('.day-name').textContent}, Nov ${this.querySelector('.date-num').textContent}`); }); }); // Event item expansion const eventItems = document.querySelectorAll('.event-item'); eventItems.forEach(item => { const card = item.querySelector('.event-card'); card.addEventListener('click', function() { item.classList.toggle('expanded'); }); }); // Notification panel toggle const notificationBadge = document.getElementById('notification-badge'); const notificationsPanel = document.getElementById('notifications-panel'); notificationBadge.addEventListener('click', function() { notificationsPanel.classList.toggle('show'); }); // Close notifications panel when clicking outside document.addEventListener('click', function(event) { if (!notificationsPanel.contains(event.target) && !notificationBadge.contains(event.target)) { notificationsPanel.classList.remove('show'); } }); // Notification action buttons const notificationBtns = document.querySelectorAll('.notification-btn'); notificationBtns.forEach(btn => { btn.addEventListener('click', function() { const notificationItem = this.closest('.notification-item'); // Simulate action (in a real app, this would do something specific) if (this.classList.contains('primary')) { showTooltip(this, 'Action performed!'); } // If it's a dismiss button, remove the notification if (this.textContent.trim() === 'Dismiss') { notificationItem.style.height = notificationItem.offsetHeight + 'px'; notificationItem.style.overflow = 'hidden'; setTimeout(() => { notificationItem.style.height = '0'; notificationItem.style.padding = '0'; notificationItem.style.margin = '0'; notificationItem.style.borderBottom = 'none'; }, 10); setTimeout(() => { notificationItem.remove(); // Update the count const count = document.querySelectorAll('.notification-item').length; document.querySelector('.notification-count').textContent = count; // Hide the badge if no notifications if (count === 0) { document.querySelector('.notification-count').style.display = 'none'; } }, 300); } }); }); // Clear all notifications document.querySelector('.clear-all').addEventListener('click', function() { const notificationItems = document.querySelectorAll('.notification-item'); notificationItems.forEach(item => { item.remove(); }); document.querySelector('.notification-count').textContent = '0'; document.querySelector('.notification-count').style.display = 'none'; notificationsPanel.classList.remove('show'); }); // Filter functionality const filterItems = document.querySelectorAll('.filter-item'); filterItems.forEach(item => { item.addEventListener('click', function() { // Remove active class from all filter items filterItems.forEach(i => i.classList.remove('active')); // Add active class to clicked filter item this.classList.add('active'); // Show tooltip with filter action showTooltip(this, `Filtered by: ${this.textContent}`); // In a real app, you would filter the events here }); }); // "Set Reminder" button functionality const reminderButtons = document.querySelectorAll('.action-button.outline'); reminderButtons.forEach(button => { if (button.textContent.trim().includes('Set Reminder')) { button.addEventListener('click', function(e) { e.stopPropagation(); // Prevent the event item from expanding const eventItem = this.closest('.event-item'); const eventName = eventItem.querySelector('.event-name').textContent; // Toggle reminder dot if (eventItem.querySelector('.reminder-dot')) { eventItem.querySelector('.reminder-dot').remove(); this.innerHTML = '<span class="icon">🔔</span> Set Reminder'; showTooltip(this, `Reminder removed for "${eventName}"`); } else { const reminderDot = document.createElement('div'); reminderDot.className = 'reminder-dot'; eventItem.querySelector('.event-card').appendChild(reminderDot); this.innerHTML = '<span class="icon">✓</span> Reminder Set'; showTooltip(this, `Reminder set for "${eventName}"`); } }); } }); // View Slides button const actionButtons = document.querySelectorAll('.action-button:not(.outline)'); actionButtons.forEach(button => { button.addEventListener('click', function(e) { e.stopPropagation(); // Prevent the event item from expanding if (button.textContent.trim().includes('View Slides')) { showTooltip(this, 'Opening slides in a new tab...'); } }); }); // Tooltip functionality function showTooltip(element, text) { const tooltip = document.getElementById('tooltip'); tooltip.textContent = text; // Position the tooltip const rect = element.getBoundingClientRect(); tooltip.style.left = rect.left + (rect.width / 2) - (tooltip.offsetWidth / 2) + 'px'; tooltip.style.top = rect.top - tooltip.offsetHeight - 10 + 'px'; // Show the tooltip tooltip.classList.add('visible'); // Hide the tooltip after a delay setTimeout(() => { tooltip.classList.remove('visible'); }, 2000); } // Simulate scroll effect for date selector let isDown = false; let startX; let scrollLeft; dateSelector.addEventListener('mousedown', (e) => { isDown = true; dateSelector.classList.add('active'); startX = e.pageX - dateSelector.offsetLeft; scrollLeft = dateSelector.scrollLeft; }); dateSelector.addEventListener('mouseleave', () => { isDown = false; dateSelector.classList.remove('active'); }); dateSelector.addEventListener('mouseup', () => { isDown = false; dateSelector.classList.remove('active'); }); dateSelector.addEventListener('mousemove', (e) => { if (!isDown) return; e.preventDefault(); const x = e.pageX - dateSelector.offsetLeft; const walk = (x - startX) * 2; dateSelector.scrollLeft = scrollLeft - walk; }); // Touch events for date selector dateSelector.addEventListener('touchstart', (e) => { isDown = true; startX = e.touches[0].pageX - dateSelector.offsetLeft; scrollLeft = dateSelector.scrollLeft; }, { passive: true }); dateSelector.addEventListener('touchend', () => { isDown = false; }); dateSelector.addEventListener('touchmove', (e) => { if (!isDown) return; const x = e.touches[0].pageX - dateSelector.offsetLeft; const walk = (x - startX) * 2; dateSelector.scrollLeft = scrollLeft - walk; }, { passive: true }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Learning Time Companion</title> <style> :root { --primary: #5B85AA; --secondary: #FFC09F; --accent: #FFEE93; --green: #95E1D3; --purple: #D4BFFF; --text: #333333; --light: #FFFFFF; --shadow: rgba(0, 0, 0, 0.1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Nunito', sans-serif; } body { width: 100%; height: 100vh; display: flex; justify-content: center; align-items: center; background-color: #f5f7fa; overflow: hidden; } .container { width: 700px; height: 700px; display: flex; flex-direction: column; justify-content: center; align-items: center; padding: 20px; position: relative; } .clock-container { width: 400px; height: 400px; position: relative; margin-bottom: 30px; transform-style: preserve-3d; perspective: 1000px; } .clock { width: 100%; height: 100%; border-radius: 50%; background: linear-gradient(135deg, var(--light), #f0f0f0); box-shadow: 0 10px 30px var(--shadow), inset 0 0 15px var(--shadow); position: relative; display: flex; justify-content: center; align-items: center; transform: rotateY(0deg); transition: transform 1.5s ease-in-out; overflow: hidden; } .clock.flipped { transform: rotateY(180deg); } .clock-front, .clock-back { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; border-radius: 50%; display: flex; justify-content: center; align-items: center; } .clock-back { transform: rotateY(180deg); background: linear-gradient(135deg, var(--purple), var(--green)); padding: 40px; } .flip-btn { position: absolute; bottom: 10px; right: 10px; background: var(--primary); color: white; border: none; border-radius: 50%; width: 40px; height: 40px; display: flex; justify-content: center; align-items: center; cursor: pointer; z-index: 10; box-shadow: 0 4px 8px var(--shadow); transition: all 0.3s ease; } .flip-btn:hover { background: #4A6D8C; transform: translateY(-2px); box-shadow: 0 6px 12px var(--shadow); } .flip-icon { font-size: 20px; animation: pulse 2s infinite; } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.1); } 100% { transform: scale(1); } } .hour-marks { position: absolute; width: 100%; height: 100%; } .hour-mark { position: absolute; width: 6px; height: 20px; background-color: var(--primary); top: 10px; left: 50%; transform-origin: bottom center; border-radius: 3px; } .minute-marks { position: absolute; width: 100%; height: 100%; } .minute-mark { position: absolute; width: 2px; height: 10px; background-color: var(--text); opacity: 0.3; top: 10px; left: 50%; transform-origin: bottom center; border-radius: 1px; } .clock-center { position: absolute; width: 20px; height: 20px; background: linear-gradient(135deg, var(--primary), #4A6D8C); border-radius: 50%; z-index: 5; } .hand { position: absolute; transform-origin: bottom center; z-index: 2; border-radius: 5px; transition: transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); } .hour-hand { width: 8px; height: 100px; background-color: var(--text); bottom: 50%; } .minute-hand { width: 6px; height: 140px; background-color: var(--primary); bottom: 50%; } .second-hand { width: 2px; height: 160px; background-color: var(--secondary); bottom: 50%; z-index: 3; } .time-display { position: absolute; bottom: 140px; background: var(--light); border-radius: 20px; padding: 15px 30px; font-size: 24px; font-weight: 700; color: var(--text); box-shadow: 0 5px 15px var(--shadow); border: 2px solid var(--green); transition: all 0.3s ease; display: flex; align-items: center; justify-content: center; } .time-display:hover { transform: translateY(-5px); box-shadow: 0 8px 20px var(--shadow); } .buttons { display: flex; gap: 15px; margin-top: 20px; } .btn { padding: 12px 24px; border: none; border-radius: 30px; font-size: 16px; font-weight: 600; cursor: pointer; transition: all 0.3s ease; box-shadow: 0 4px 8px var(--shadow); display: flex; align-items: center; justify-content: center; gap: 8px; } .btn-primary { background-color: var(--primary); color: white; } .btn-secondary { background-color: var(--secondary); color: var(--text); } .btn-accent { background-color: var(--accent); color: var(--text); } .btn:hover { transform: translateY(-3px); box-shadow: 0 6px 12px var(--shadow); } .btn:active { transform: translateY(0); box-shadow: 0 2px 4px var(--shadow); } .fun-fact { padding: 20px; border-radius: 15px; background-color: rgba(255, 255, 255, 0.9); color: var(--text); font-size: 18px; line-height: 1.5; text-align: center; box-shadow: 0 5px 15px var(--shadow); } .fact-title { color: var(--primary); font-weight: 700; margin-bottom: 10px; font-size: 22px; } .tooltip { position: absolute; background-color: var(--accent); color: var(--text); padding: 10px 15px; border-radius: 10px; font-size: 14px; opacity: 0; transition: opacity 0.3s, transform 0.3s; pointer-events: none; max-width: 220px; box-shadow: 0 4px 10px var(--shadow); z-index: 100; } .tooltip.visible { opacity: 1; transform: translateY(-10px); } .tooltip::after { content: ''; position: absolute; bottom: -10px; left: 50%; transform: translateX(-50%); border-width: 10px 10px 0; border-style: solid; border-color: var(--accent) transparent transparent; } .timer-controls { display: flex; gap: 10px; margin-top: 20px; } .timer-btn { width: 40px; height: 40px; border-radius: 50%; display: flex; justify-content: center; align-items: center; background-color: var(--primary); color: white; border: none; cursor: pointer; transition: all 0.3s ease; box-shadow: 0 4px 8px var(--shadow); } .timer-btn:hover { background-color: #4A6D8C; transform: translateY(-2px); } .progress-ring { position: absolute; width: 400px; height: 400px; } .progress-ring circle { stroke-width: 10; stroke-linecap: round; fill: transparent; transform: rotate(-90deg); transform-origin: center; transition: stroke-dashoffset 0.3s ease; } .progress-bg { stroke: rgba(0, 0, 0, 0.05); } .progress-fill { stroke: var(--secondary); stroke-dasharray: 1194; stroke-dashoffset: 1194; } .clock-numbers { position: absolute; width: 100%; height: 100%; } .clock-number { position: absolute; font-size: 22px; color: var(--text); font-weight: 700; transform-origin: center; width: 40px; height: 40px; display: flex; justify-content: center; align-items: center; } .mode-selector { position: absolute; top: 10px; display: flex; gap: 10px; background: rgba(255, 255, 255, 0.9); padding: 10px; border-radius: 20px; box-shadow: 0 5px 15px var(--shadow); } .mode-btn { padding: 8px 16px; border-radius: 15px; border: none; background: var(--light); color: var(--text); font-weight: 600; cursor: pointer; transition: all 0.3s ease; } .mode-btn.active { background: var(--primary); color: white; } /* Animation for the tooltip appearing */ @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } /* Character animations */ .character { position: absolute; width: 80px; height: 80px; border-radius: 50%; background: var(--green); bottom: 50px; left: 50px; display: flex; justify-content: center; align-items: center; animation: float 3s ease-in-out infinite; box-shadow: 0 5px 15px var(--shadow); transition: all 0.3s ease; cursor: pointer; z-index: 20; } .character:hover { transform: scale(1.1); } .character-face { position: relative; width: 60px; height: 60px; } .character-eye { position: absolute; width: 14px; height: 14px; background: var(--text); border-radius: 50%; top: 20px; } .character-eye.left { left: 12px; } .character-eye.right { right: 12px; } .character-mouth { position: absolute; width: 30px; height: 10px; background: var(--text); border-radius: 0 0 15px 15px; bottom: 10px; left: 15px; } @keyframes float { 0% { transform: translateY(0px); } 50% { transform: translateY(-10px); } 100% { transform: translateY(0px); } } /* Responsive styles */ @media (max-width: 700px) { .clock-container { width: 300px; height: 300px; } .progress-ring { width: 300px; height: 300px; } .hour-hand { height: 75px; } .minute-hand { height: 105px; } .second-hand { height: 120px; } .time-display { font-size: 20px; padding: 10px 20px; bottom: 100px; } .clock-number { font-size: 18px; } .btn { padding: 10px 20px; font-size: 14px; } .character { width: 60px; height: 60px; bottom: 30px; left: 30px; } .character-face { width: 45px; height: 45px; } .character-eye { width: 10px; height: 10px; top: 15px; } .character-eye.left { left: 9px; } .character-eye.right { right: 9px; } .character-mouth { width: 22px; height: 8px; bottom: 8px; left: 12px; } } @keyframes bounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-10px); } } .bounce { animation: bounce 0.5s; } .session-progress { position: absolute; bottom: 80px; width: 300px; height: 15px; background-color: rgba(255, 255, 255, 0.3); border-radius: 10px; overflow: hidden; } .progress-bar { height: 100%; background: linear-gradient(90deg, var(--green), var(--primary)); width: 0%; transition: width 0.5s ease; border-radius: 10px; } </style> </head> <body> <div class="container"> <div class="mode-selector"> <button class="mode-btn active" data-mode="clock">Clock</button> <button class="mode-btn" data-mode="timer">Timer</button> <button class="mode-btn" data-mode="stopwatch">Stopwatch</button> </div> <div class="clock-container"> <svg class="progress-ring"> <circle class="progress-bg" cx="200" cy="200" r="190" /> <circle class="progress-fill" cx="200" cy="200" r="190" /> </svg> <div class="clock"> <div class="clock-front"> <div class="hour-marks"></div> <div class="minute-marks"></div> <div class="clock-numbers"></div> <div class="hour-hand hand"></div> <div class="minute-hand hand"></div> <div class="second-hand hand"></div> <div class="clock-center"></div> </div> <div class="clock-back"> <div class="fun-fact"> <div class="fact-title">Did you know?</div> <p id="fun-fact-text">The world's first mechanical clock was invented in China during the Song Dynasty around 1000 AD. It was designed by a Buddhist monk named Yi Xing.</p> </div> </div> </div> <button class="flip-btn"> <span class="flip-icon">↻</span> </button> </div> <div class="time-display">00:00:00</div> <div class="session-progress"> <div class="progress-bar"></div> </div> <div class="buttons clock-buttons"> <button class="btn btn-primary" id="time-trivia"> <span>Time Trivia</span> <span>🎓</span> </button> <button class="btn btn-secondary" id="theme-toggle"> <span>Change Theme</span> <span>🎨</span> </button> </div> <div class="timer-controls" style="display: none;"> <button class="btn btn-primary" id="start-btn">Start</button> <button class="btn btn-secondary" id="pause-btn">Pause</button> <button class="btn btn-accent" id="reset-btn">Reset</button> </div> <div class="character" id="helper-character"> <div class="character-face"> <div class="character-eye left"></div> <div class="character-eye right"></div> <div class="character-mouth"></div> </div> </div> <div class="tooltip" id="tooltip"></div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // DOM Elements const hourHand = document.querySelector('.hour-hand'); const minuteHand = document.querySelector('.minute-hand'); const secondHand = document.querySelector('.second-hand'); const timeDisplay = document.querySelector('.time-display'); const flipBtn = document.querySelector('.flip-btn'); const clock = document.querySelector('.clock'); const timerControls = document.querySelector('.timer-controls'); const clockButtons = document.querySelector('.clock-buttons'); const startBtn = document.getElementById('start-btn'); const pauseBtn = document.getElementById('pause-btn'); const resetBtn = document.getElementById('reset-btn'); const timeTriviaBtn = document.getElementById('time-trivia'); const themeToggleBtn = document.getElementById('theme-toggle'); const tooltip = document.getElementById('tooltip'); const helperCharacter = document.getElementById('helper-character'); const modeBtns = document.querySelectorAll('.mode-btn'); const progressRing = document.querySelector('.progress-fill'); const progressBar = document.querySelector('.progress-bar'); const funFactText = document.getElementById('fun-fact-text'); // Set up clock face createClockFace(); // Variables let mode = 'clock'; let timer = 0; let isRunning = false; let timerInterval; let currentTheme = 0; const themes = [ { primary: '#5B85AA', secondary: '#FFC09F', accent: '#FFEE93', green: '#95E1D3', purple: '#D4BFFF' }, { primary: '#FF6B6B', secondary: '#4ECDC4', accent: '#FFD166', green: '#83D483', purple: '#C38D9E' }, { primary: '#845EC2', secondary: '#FF9671', accent: '#FFC75F', green: '#F9F871', purple: '#B39CD0' }, { primary: '#00B8A9', secondary: '#F8F3D4', accent: '#F6416C', green: '#FFDE7D', purple: '#E493B3' } ]; // Fun facts about time const funFacts = [ "The world's first mechanical clock was invented in China during the Song Dynasty around 1000 AD. It was designed by a Buddhist monk named Yi Xing.", "The concept of the 24-hour day comes from ancient Egypt, where they first divided the day into 12 hours of daylight and 12 hours of darkness.", "The first wristwatch was made for a woman, Countess Koscowicz of Hungary, by Swiss watchmaker Patek Philippe in 1868.", "February used to be the last month of the year in the ancient Roman calendar until 450 BCE when January and February were moved to the beginning.", "The shortest unit of time is the 'Planck time' - it takes light roughly this time to travel one Planck length. It's about 10^-43 seconds!", "Daylight Saving Time was first proposed by Benjamin Franklin in 1784, but it wasn't implemented widely until World War I to conserve energy.", "The most accurate clock in the world is the atomic clock at the National Institute of Standards and Technology in Colorado. It would neither gain nor lose a second in about 100 million years!", "In some remote parts of the world, people don't use hours and minutes but instead track time by natural events, like when certain stars appear." ]; // Time trivia for tooltips const timeTrivia = [ "In Japan, being on time is so important that some trains issue delay certificates if they're more than five minutes late!", "Ancient Greeks used water clocks called 'clepsydra' that measured time by the regulated flow of water through a small hole.", "The word 'clock' comes from the Celtic words 'clocca' and 'clogan', which mean 'bell'.", "Milliseconds matter! Olympic swimmers can win or lose by just 0.01 seconds - that's faster than a blink!", "The Earth's rotation is gradually slowing down, making our days about 1.7 milliseconds longer every century.", "The phrase 'o'clock' is a contraction of 'of the clock' from when sundials and clocks coexisted and needed to be distinguished.", "The International Space Station experiences 16 sunrises and sunsets every 24 hours because it orbits Earth so quickly!", "Most digital watches and clocks are actually slightly ahead of the actual time to make people punctual." ]; // Init updateClock(); setInterval(updateClock, 1000); updateProgressBar(0); // Functions function createClockFace() { const hourMarksContainer = document.querySelector('.hour-marks'); const minuteMarksContainer = document.querySelector('.minute-marks'); const clockNumbersContainer = document.querySelector('.clock-numbers'); // Create hour marks for (let i = 0; i < 12; i++) { const hourMark = document.createElement('div'); hourMark.classList.add('hour-mark'); hourMark.style.transform = `rotate(${i * 30}deg)`; hourMarksContainer.appendChild(hourMark); // Create clock numbers const clockNumber = document.createElement('div'); clockNumber.classList.add('clock-number'); const angle = i * 30; const radius = 160; // Adjust as needed const numValue = i === 0 ? 12 : i; const x = Math.sin(angle * (Math.PI / 180)) * radius; const y = -Math.cos(angle * (Math.PI / 180)) * radius; clockNumber.style.left = `calc(50% + ${x}px - 20px)`; clockNumber.style.top = `calc(50% + ${y}px - 20px)`; clockNumber.textContent = numValue; clockNumbersContainer.appendChild(clockNumber); } // Create minute marks for (let i = 0; i < 60; i++) { if (i % 5 !== 0) { // Skip positions where hour marks are const minuteMark = document.createElement('div'); minuteMark.classList.add('minute-mark'); minuteMark.style.transform = `rotate(${i * 6}deg)`; minuteMarksContainer.appendChild(minuteMark); } } } function updateClock() { if (mode === 'clock') { const now = new Date(); const hours = now.getHours() % 12; const minutes = now.getMinutes(); const seconds = now.getSeconds(); const hourDeg = (hours * 30) + (minutes * 0.5); const minuteDeg = (minutes * 6) + (seconds * 0.1); const secondDeg = seconds * 6; hourHand.style.transform = `rotate(${hourDeg}deg)`; minuteHand.style.transform = `rotate(${minuteDeg}deg)`; secondHand.style.transform = `rotate(${secondDeg}deg)`; const timeStr = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' }); timeDisplay.textContent = timeStr; // Mock progress for a typical school day (8am to 3pm) const startHour = 8; const endHour = 15; const currentHour = hours + (minutes / 60); if (currentHour >= startHour && currentHour <= endHour) { const progress = ((currentHour - startHour) / (endHour - startHour)) * 100; updateProgressBar(progress); } else { updateProgressBar(0); } } } function updateTimer() { const hours = Math.floor(timer / 3600); const minutes = Math.floor((timer % 3600) / 60); const seconds = timer % 60; timeDisplay.textContent = `${padZero(hours)}:${padZero(minutes)}:${padZero(seconds)}`; // Update visual timer if (mode === 'timer') { const timerMax = 25 * 60; // 25 minutes in seconds (Pomodoro) const progress = (timer / timerMax) * 100; updateProgressRing(100 - progress); updateProgressBar(progress); } else if (mode === 'stopwatch') { const progress = Math.min(timer / 3600, 1) * 100; updateProgressRing(progress); updateProgressBar(progress); } } function padZero(num) { return num.toString().padStart(2, '0'); } function updateProgressRing(percent) { const circumference = 2 * Math.PI * 190; const offset = circumference - (percent / 100 * circumference); progressRing.style.strokeDashoffset = offset; } function updateProgressBar(percent) { progressBar.style.width = `${percent}%`; } function showTooltip(content, element) { tooltip.textContent = content; tooltip.classList.add('visible'); const rect = element.getBoundingClientRect(); const containerRect = document.querySelector('.container').getBoundingClientRect(); tooltip.style.left = `${rect.left + rect.width/2 - containerRect.left - tooltip.offsetWidth/2}px`; tooltip.style.top = `${rect.top - containerRect.top - tooltip.offsetHeight - 10}px`; setTimeout(() => { tooltip.classList.remove('visible'); }, 5000); } function switchMode(newMode) { mode = newMode; modeBtns.forEach(btn => { btn.classList.toggle('active', btn.dataset.mode === mode); }); // Reset timer and UI clearInterval(timerInterval); isRunning = false; timer = 0; if (mode === 'clock') { timerControls.style.display = 'none'; clockButtons.style.display = 'flex'; updateClock(); } else { timerControls.style.display = 'flex'; clockButtons.style.display = 'none'; updateTimer(); updateProgressRing(0); } } // Event Listeners flipBtn.addEventListener('click', () => { clock.classList.toggle('flipped'); // Change fun fact when flipped if (clock.classList.contains('flipped')) { const randomFact = funFacts[Math.floor(Math.random() * funFacts.length)]; funFactText.textContent = randomFact; } }); startBtn.addEventListener('click', () => { if (!isRunning) { isRunning = true; if (mode === 'timer' && timer === 0) { // Default timer: 25 minutes (Pomodoro) timer = 25 * 60; } timerInterval = setInterval(() => { if (mode === 'timer') { if (timer > 0) { timer--; if (timer === 0) { clearInterval(timerInterval); isRunning = false; helperCharacter.classList.add('bounce'); setTimeout(() => { helperCharacter.classList.remove('bounce'); }, 500); showTooltip("Great job! Time for a break!", timeDisplay); } } } else if (mode === 'stopwatch') { timer++; } updateTimer(); }, 1000); } }); pauseBtn.addEventListener('click', () => { clearInterval(timerInterval); isRunning = false; }); resetBtn.addEventListener('click', () => { clearInterval(timerInterval); isRunning = false; timer = 0; updateTimer(); updateProgressRing(0); updateProgressBar(0); }); timeTriviaBtn.addEventListener('click', () => { const randomTrivia = timeTrivia[Math.floor(Math.random() * timeTrivia.length)]; showTooltip(randomTrivia, timeTriviaBtn); }); themeToggleBtn.addEventListener('click', () => { currentTheme = (currentTheme + 1) % themes.length; const theme = themes[currentTheme]; document.documentElement.style.setProperty('--primary', theme.primary); document.documentElement.style.setProperty('--secondary', theme.secondary); document.documentElement.style.setProperty('--accent', theme.accent); document.documentElement.style.setProperty('--green', theme.green); document.documentElement.style.setProperty('--purple', theme.purple); showTooltip("Theme changed! Personalize your learning environment.", themeToggleBtn); }); helperCharacter.addEventListener('click', () => { const helperTips = [ "Click 'Time Trivia' for fun time facts!", "Flip the clock to discover interesting time facts.", "Use the timer for focused study sessions.", "Change themes to match your mood or time of day.", "The progress bar shows how far you are in your session." ]; const randomTip = helperTips[Math.floor(Math.random() * helperTips.length)]; showTooltip(randomTip, helperCharacter); helperCharacter.classList.add('bounce'); setTimeout(() => { helperCharacter.classList.remove('bounce'); }, 500); }); modeBtns.forEach(btn => { btn.addEventListener('click', () => { switchMode(btn.dataset.mode); }); }); // Initial setup progressRing.style.strokeDasharray = 2 * Math.PI * 190; updateProgressRing(0); }); </script> </body> </html>
<html> <head> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Montserrat', sans-serif; } body { display: flex; justify-content: center; align-items: center; min-height: 700px; width: 100%; background-color: #f6f8fa; padding: 20px; } .app-container { width: 100%; max-width: 660px; height: 660px; background-color: #2B3A67; border-radius: 24px; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15); overflow: hidden; position: relative; display: flex; flex-direction: column; } .map-header { padding: 20px; display: flex; justify-content: space-between; align-items: center; color: white; background-color: #1A2648; border-bottom: 1px solid rgba(255, 255, 255, 0.1); z-index: 10; } .map-title { font-size: 1.4rem; font-weight: 700; letter-spacing: 0.5px; } .map-subtitle { font-size: 0.9rem; font-weight: 400; opacity: 0.8; margin-top: 5px; } .current-time { font-size: 1.8rem; font-weight: 700; text-align: right; letter-spacing: 1px; color: #FC9E4F; text-shadow: 0 0 10px rgba(252, 158, 79, 0.3); } .date-display { font-size: 0.9rem; opacity: 0.8; text-align: right; } .map-container { position: relative; flex: 1; overflow: hidden; background-color: #2B3A67; background-image: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%233F5AA0' fill-opacity='0.3'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); } .timezone-regions { position: absolute; width: 100%; height: 100%; display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr); gap: 4px; padding: 20px; } .region { background-color: rgba(255, 255, 255, 0.08); border-radius: 16px; cursor: pointer; transition: all 0.3s ease; position: relative; overflow: hidden; border: 2px solid transparent; display: flex; flex-direction: column; justify-content: center; align-items: center; padding: 10px; } .region:hover { background-color: rgba(255, 255, 255, 0.12); transform: translateY(-2px); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); } .region.active { border-color: #FC9E4F; background-color: rgba(252, 158, 79, 0.15); transform: translateY(-3px); box-shadow: 0 8px 20px rgba(252, 158, 79, 0.2); } .region-name { font-size: 0.9rem; font-weight: 600; color: white; text-align: center; z-index: 2; margin-bottom: 6px; } .region-time { font-size: 1.1rem; font-weight: 700; color: #FC9E4F; text-align: center; z-index: 2; } .region-detail { font-size: 0.7rem; color: rgba(255, 255, 255, 0.6); text-align: center; margin-top: 4px; z-index: 2; } .compass { position: absolute; bottom: 30px; right: 30px; width: 80px; height: 80px; border-radius: 50%; background-color: rgba(26, 38, 72, 0.7); border: 2px solid rgba(255, 255, 255, 0.2); display: flex; justify-content: center; align-items: center; box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); z-index: 5; } .compass-inner { width: 60px; height: 60px; border-radius: 50%; background-color: #1A2648; position: relative; display: flex; justify-content: center; align-items: center; } .compass-needle { position: absolute; width: 4px; height: 50px; background: linear-gradient(to bottom, #FC9E4F 0%, #FC9E4F 45%, #ffffff 45%, #ffffff 55%, #3F5AA0 55%, #3F5AA0 100%); border-radius: 2px; transform-origin: center; transform: rotate(0deg); transition: transform 0.8s cubic-bezier(0.68, -0.55, 0.265, 1.55); } .compass-center { width: 10px; height: 10px; background-color: #ffffff; border-radius: 50%; z-index: 2; } .compass-marker { position: absolute; font-size: 0.6rem; font-weight: 700; color: white; } .marker-n { top: 5px; } .marker-e { right: 5px; } .marker-s { bottom: 5px; } .marker-w { left: 5px; } .day-night-indicator { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(to bottom, rgba(252, 158, 79, 0) 0%, rgba(252, 158, 79, 0.05) 50%, rgba(63, 90, 160, 0.1) 50%, rgba(63, 90, 160, 0.2) 100%); opacity: 0.6; pointer-events: none; transition: all 1s ease; z-index: 1; border-radius: 16px; } .sun-moon { position: absolute; width: 20px; height: 20px; border-radius: 50%; z-index: 2; transition: all 0.8s ease; } .sun { background-color: #FC9E4F; box-shadow: 0 0 15px rgba(252, 158, 79, 0.7); } .moon { background-color: #E9F1FF; box-shadow: 0 0 15px rgba(255, 255, 255, 0.5); } @media (max-width: 600px) { .map-header { padding: 15px; } .map-title { font-size: 1.2rem; } .current-time { font-size: 1.5rem; } .timezone-regions { padding: 10px; gap: 3px; } .region-name { font-size: 0.8rem; } .region-time { font-size: 1rem; } .region-detail { font-size: 0.6rem; } .compass { width: 70px; height: 70px; bottom: 20px; right: 20px; } .compass-inner { width: 50px; height: 50px; } } /* Info panel styling */ .info-panel { position: absolute; bottom: -200px; left: 0; width: 100%; background-color: #1A2648; padding: 20px; border-top-left-radius: 24px; border-top-right-radius: 24px; transition: transform 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55); z-index: 20; box-shadow: 0 -5px 20px rgba(0, 0, 0, 0.2); } .info-panel.active { transform: translateY(-200px); } .info-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; } .info-title { font-size: 1.2rem; font-weight: 700; color: white; } .close-info { background: none; border: none; color: white; font-size: 1.2rem; cursor: pointer; opacity: 0.7; transition: opacity 0.3s ease; } .close-info:hover { opacity: 1; } .info-content { color: rgba(255, 255, 255, 0.8); font-size: 0.9rem; line-height: 1.5; } .info-stats { display: flex; justify-content: space-between; margin-top: 15px; } .stat { text-align: center; flex: 1; } .stat-value { font-size: 1.2rem; font-weight: 700; color: #FC9E4F; } .stat-label { font-size: 0.8rem; color: rgba(255, 255, 255, 0.6); margin-top: 5px; } /* Map coordinates overlay */ .coordinates { position: absolute; top: 20px; left: 20px; background-color: rgba(26, 38, 72, 0.7); padding: 8px 12px; border-radius: 20px; color: white; font-size: 0.8rem; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); backdrop-filter: blur(4px); z-index: 5; } </style> </head> <body> <div class="app-container"> <div class="map-header"> <div> <div class="map-title">Chrono Navigator</div> <div class="map-subtitle">Global Time Explorer</div> </div> <div> <div class="current-time" id="current-time">12:00</div> <div class="date-display" id="date-display">Monday, Jan 1</div> </div> </div> <div class="map-container"> <div class="coordinates" id="coordinates">48.8°N, 2.3°E</div> <div class="timezone-regions" id="timezone-regions"> <!-- Regions will be dynamically generated --> </div> <div class="compass"> <div class="compass-inner"> <div class="compass-needle" id="compass-needle"></div> <div class="compass-center"></div> <div class="compass-marker marker-n">N</div> <div class="compass-marker marker-e">E</div> <div class="compass-marker marker-s">S</div> <div class="compass-marker marker-w">W</div> </div> </div> </div> <div class="info-panel" id="info-panel"> <div class="info-header"> <div class="info-title" id="info-title">Tokyo, Japan</div> <button class="close-info" id="close-info">×</button> </div> <div class="info-content" id="info-content"> Located in the Japan Standard Time (JST) zone, Tokyo is 9 hours ahead of UTC. As a major global hub, timing here affects financial markets and international connections. </div> <div class="info-stats"> <div class="stat"> <div class="stat-value" id="stat-utc-offset">UTC+9</div> <div class="stat-label">Offset</div> </div> <div class="stat"> <div class="stat-value" id="stat-sunrise">06:24</div> <div class="stat-label">Sunrise</div> </div> <div class="stat"> <div class="stat-value" id="stat-sunset">17:45</div> <div class="stat-label">Sunset</div> </div> </div> </div> </div> <script> // Region data with timezone information const regions = [ { name: "New York", timezone: "America/New_York", offset: -5, coordinates: "40.7°N, 74.0°W", description: "Eastern Time (ET) is used across the U.S. east coast. New York's time influences global financial markets and serves as a reference for many international business operations.", sunrise: "07:15", sunset: "16:52" }, { name: "London", timezone: "Europe/London", offset: 0, coordinates: "51.5°N, 0.1°W", description: "Greenwich Mean Time (GMT) or British Summer Time (BST) during daylight savings. London sits at the center of global time standards, with UTC established at the Royal Observatory.", sunrise: "08:04", sunset: "16:26" }, { name: "Tokyo", timezone: "Asia/Tokyo", offset: 9, coordinates: "35.7°N, 139.8°E", description: "Located in the Japan Standard Time (JST) zone, Tokyo is 9 hours ahead of UTC. As a major global hub, timing here affects financial markets and international connections.", sunrise: "06:24", sunset: "17:45" }, { name: "Sydney", timezone: "Australia/Sydney", offset: 11, coordinates: "33.9°S, 151.2°E", description: "Australian Eastern Standard/Daylight Time (AEST/AEDT). As one of the first major cities to see each new day, Sydney often hosts global New Year celebrations ahead of other regions.", sunrise: "05:45", sunset: "19:58" }, { name: "Dubai", timezone: "Asia/Dubai", offset: 4, coordinates: "25.3°N, 55.3°E", description: "Gulf Standard Time (GST) with no daylight savings adjustments. Dubai's strategic position makes it a connecting hub between East and West time zones for global travelers.", sunrise: "07:05", sunset: "17:35" }, { name: "Paris", timezone: "Europe/Paris", offset: 1, coordinates: "48.8°N, 2.3°E", description: "Central European Time (CET) or Central European Summer Time (CEST). Paris serves as a reference point for much of continental Europe's business and travel schedules.", sunrise: "08:36", sunset: "17:13" }, { name: "São Paulo", timezone: "America/Sao_Paulo", offset: -3, coordinates: "23.5°S, 46.6°W", description: "Brasília Time (BRT) or Brasília Summer Time (BRST). As South America's largest city, São Paulo's time zone influences business operations across the continent.", sunrise: "06:08", sunset: "19:42" }, { name: "Singapore", timezone: "Asia/Singapore", offset: 8, coordinates: "1.3°N, 103.8°E", description: "Singapore Standard Time (SGT) with no daylight savings. Singapore's position as a global financial center makes its time zone crucial for Asian market operations.", sunrise: "07:02", sunset: "19:11" }, { name: "Delhi", timezone: "Asia/Kolkata", offset: 5.5, coordinates: "28.6°N, 77.2°E", description: "Indian Standard Time (IST) which is offset by 5:30 hours from UTC. One of the few time zones with a half-hour offset, covering the entire Indian subcontinent.", sunrise: "07:08", sunset: "17:32" } ]; // DOM elements const timezoneRegionsEl = document.getElementById('timezone-regions'); const currentTimeEl = document.getElementById('current-time'); const dateDisplayEl = document.getElementById('date-display'); const compassNeedleEl = document.getElementById('compass-needle'); const coordinatesEl = document.getElementById('coordinates'); const infoPanel = document.getElementById('info-panel'); const infoTitle = document.getElementById('info-title'); const infoContent = document.getElementById('info-content'); const closeInfoBtn = document.getElementById('close-info'); const statUtcOffset = document.getElementById('stat-utc-offset'); const statSunrise = document.getElementById('stat-sunrise'); const statSunset = document.getElementById('stat-sunset'); // Current active region let activeRegion = regions[0]; // Create regions regions.forEach((region, index) => { const regionEl = document.createElement('div'); regionEl.className = 'region'; regionEl.dataset.index = index; // Create day/night indicator const dayNightIndicator = document.createElement('div'); dayNightIndicator.className = 'day-night-indicator'; regionEl.appendChild(dayNightIndicator); // Create sun or moon const celestialBody = document.createElement('div'); celestialBody.className = `sun-moon ${index % 2 === 0 ? 'sun' : 'moon'}`; // Random position within the region const topPos = 20 + Math.random() * 60; const leftPos = 20 + Math.random() * 60; celestialBody.style.top = `${topPos}%`; celestialBody.style.left = `${leftPos}%`; regionEl.appendChild(celestialBody); // Region content const regionNameEl = document.createElement('div'); regionNameEl.className = 'region-name'; regionNameEl.textContent = region.name; const regionTimeEl = document.createElement('div'); regionTimeEl.className = 'region-time'; regionTimeEl.id = `region-time-${index}`; const regionDetailEl = document.createElement('div'); regionDetailEl.className = 'region-detail'; regionDetailEl.textContent = `UTC${region.offset >= 0 ? '+' + region.offset : region.offset}`; regionEl.appendChild(regionNameEl); regionEl.appendChild(regionTimeEl); regionEl.appendChild(regionDetailEl); // Add event listener regionEl.addEventListener('click', () => { setActiveRegion(index); showInfoPanel(region); // Rotate compass needle // Calculate rotation based on longitude coordinates const coordStr = region.coordinates; const longMatch = coordStr.match(/(\d+\.\d+)°([EW])/); if (longMatch) { const longValue = parseFloat(longMatch[1]); const longDir = longMatch[2]; // Calculate degrees - E is positive, W is negative const rotationDeg = longDir === 'E' ? longValue : -longValue; compassNeedleEl.style.transform = `rotate(${rotationDeg}deg)`; } // Update coordinates display coordinatesEl.textContent = region.coordinates; }); timezoneRegionsEl.appendChild(regionEl); }); // Set initial active region setActiveRegion(0); // Update all clocks function function updateClocks() { const now = new Date(); // Update main clock const mainTime = formatTimeForTimezone(now, activeRegion.offset); currentTimeEl.textContent = mainTime; // Update date const options = { weekday: 'long', month: 'short', day: 'numeric' }; dateDisplayEl.textContent = now.toLocaleDateString('en-US', options); // Update region clocks regions.forEach((region, index) => { const regionTimeEl = document.getElementById(`region-time-${index}`); if (regionTimeEl) { regionTimeEl.textContent = formatTimeForTimezone(now, region.offset); } }); } // Format time for a specific timezone function formatTimeForTimezone(date, offsetHours) { // Clone the date to avoid modifying the original const newDate = new Date(date); // Get UTC time in milliseconds const utcTime = date.getTime() + (date.getTimezoneOffset() * 60000); // Calculate the time in the target timezone const targetTime = new Date(utcTime + (offsetHours * 3600000)); // Format the time const hours = targetTime.getHours().toString().padStart(2, '0'); const minutes = targetTime.getMinutes().toString().padStart(2, '0'); return `${hours}:${minutes}`; } // Set active region function setActiveRegion(index) { // Remove active class from all regions document.querySelectorAll('.region').forEach(el => { el.classList.remove('active'); }); // Add active class to selected region const regionEl = document.querySelector(`.region[data-index="${index}"]`); if (regionEl) { regionEl.classList.add('active'); activeRegion = regions[index]; } } // Show info panel function showInfoPanel(region) { infoTitle.textContent = region.name; infoContent.textContent = region.description; // Update stats statUtcOffset.textContent = `UTC${region.offset >= 0 ? '+' + region.offset : region.offset}`; statSunrise.textContent = region.sunrise; statSunset.textContent = region.sunset; // Show panel infoPanel.classList.add('active'); } // Close info panel closeInfoBtn.addEventListener('click', () => { infoPanel.classList.remove('active'); }); // Add a subtle animation to the sun/moon elements function animateCelestialBodies() { document.querySelectorAll('.sun-moon').forEach(el => { // Get current position const computedStyle = window.getComputedStyle(el); let top = parseFloat(computedStyle.top); let left = parseFloat(computedStyle.left); // Add a small random movement top += (Math.random() - 0.5) * 2; left += (Math.random() - 0.5) * 2; // Keep within bounds (10% to 90%) top = Math.max(10, Math.min(90, top)); left = Math.max(10, Math.min(90, left)); // Apply new position el.style.top = `${top}%`; el.style.left = `${left}%`; }); } // Initialize and start clock updates updateClocks(); setInterval(updateClocks, 1000); setInterval(animateCelestialBodies, 3000); // Initialize with coordinates from active region coordinatesEl.textContent = activeRegion.coordinates; // Set the compass needle based on the active region's longitude const coordStr = activeRegion.coordinates; const longMatch = coordStr.match(/(\d+\.\d+)°([EW])/); if (longMatch) { const longValue = parseFloat(longMatch[1]); const longDir = longMatch[2]; const rotationDeg = longDir === 'E' ? longValue : -longValue; compassNeedleEl.style.transform = `rotate(${rotationDeg}deg)`; } </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Cyberpunk Gaming Interface Clock</title> <style> @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;700;900&family=Share+Tech+Mono&display=swap'); :root { --neon-pink: #ff007f; --neon-blue: #00f0ff; --neon-green: #39ff14; --neon-yellow: #ffec00; --neon-purple: #bc13fe; --dark-bg: #0d0d0f; --darker-bg: #07070a; --panel-bg: rgba(20, 20, 30, 0.7); --glass-effect: rgba(255, 255, 255, 0.05); --shadow-color: rgba(0, 240, 255, 0.2); } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Share Tech Mono', monospace; background-color: var(--dark-bg); color: #ffffff; height: 100vh; display: flex; justify-content: center; align-items: center; background-image: radial-gradient(circle at 15% 15%, rgba(255, 0, 127, 0.1) 0%, transparent 25%), radial-gradient(circle at 85% 85%, rgba(0, 240, 255, 0.1) 0%, transparent 25%); overflow: hidden; } .interface-container { width: 100%; max-width: 600px; height: auto; background-color: var(--panel-bg); border-radius: 10px; backdrop-filter: blur(5px); border: 1px solid var(--glass-effect); box-shadow: 0 0 20px var(--shadow-color), inset 0 0 10px var(--shadow-color); padding: 20px; position: relative; overflow: hidden; } .grid-lines { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-image: linear-gradient(to right, rgba(0, 240, 255, 0.05) 1px, transparent 1px), linear-gradient(to bottom, rgba(0, 240, 255, 0.05) 1px, transparent 1px); background-size: 20px 20px; z-index: -1; } .header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; padding-bottom: 15px; border-bottom: 1px solid rgba(0, 240, 255, 0.2); position: relative; } .header::after { content: ''; position: absolute; bottom: -1px; left: 0; width: 100%; height: 1px; background: linear-gradient(90deg, transparent, var(--neon-blue), transparent); animation: scanline 3s infinite linear; } .logo { font-family: 'Orbitron', sans-serif; font-weight: 700; font-size: 24px; color: var(--neon-blue); text-shadow: 0 0 5px var(--neon-blue); letter-spacing: 1px; } .status { background-color: rgba(13, 13, 15, 0.6); padding: 5px 10px; border-radius: 5px; font-size: 12px; border: 1px solid var(--neon-green); color: var(--neon-green); position: relative; } .status::before { content: '●'; margin-right: 5px; animation: blink 2s infinite; } .main-clock { text-align: center; margin: 10px 0 25px; position: relative; } .time-display { font-family: 'Orbitron', sans-serif; font-size: 5rem; font-weight: 700; color: white; text-shadow: 0 0 10px var(--neon-blue); margin-bottom: 5px; position: relative; z-index: 2; } .date-display { font-size: 1.2rem; color: var(--neon-pink); letter-spacing: 2px; text-transform: uppercase; margin-bottom: 15px; } .session-info { display: flex; justify-content: space-around; margin: 20px 0; border-radius: 8px; background-color: rgba(13, 13, 15, 0.6); padding: 15px; border: 1px solid rgba(255, 0, 127, 0.2); } .session-stat { text-align: center; position: relative; } .stat-value { font-size: 1.8rem; color: var(--neon-yellow); font-weight: bold; text-shadow: 0 0 5px var(--neon-yellow); } .stat-label { font-size: 0.8rem; color: rgba(255, 255, 255, 0.6); text-transform: uppercase; letter-spacing: 1px; margin-top: 5px; } .controls { display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-top: 20px; } .control-section { background-color: rgba(13, 13, 15, 0.6); border-radius: 8px; padding: 15px; border: 1px solid rgba(0, 240, 255, 0.2); } .section-title { font-family: 'Orbitron', sans-serif; font-size: 14px; color: var(--neon-purple); margin-bottom: 10px; text-transform: uppercase; letter-spacing: 1px; display: flex; align-items: center; } .section-title::before { content: '//'; margin-right: 5px; color: var(--neon-pink); } .timer-display { font-family: 'Orbitron', sans-serif; font-size: 2rem; color: var(--neon-green); text-align: center; margin: 10px 0; text-shadow: 0 0 5px var(--neon-green); } .time-input { display: flex; gap: 5px; margin-bottom: 10px; } .time-input input { flex: 1; background-color: rgba(0, 0, 0, 0.5); border: 1px solid var(--neon-blue); color: white; padding: 8px; border-radius: 4px; font-family: 'Share Tech Mono', monospace; } .button { background: linear-gradient(45deg, var(--darker-bg), var(--dark-bg)); border: 1px solid; border-image-slice: 1; border-image-source: linear-gradient(45deg, var(--neon-blue), var(--neon-pink)); color: white; padding: 8px 15px; cursor: pointer; font-family: 'Share Tech Mono', monospace; font-size: 14px; border-radius: 4px; transition: all 0.3s ease; text-transform: uppercase; letter-spacing: 1px; } .button:hover { box-shadow: 0 0 10px var(--neon-blue); text-shadow: 0 0 5px var(--neon-blue); } .button-group { display: flex; gap: 10px; justify-content: center; margin-top: 10px; } .milestone-list { list-style-type: none; margin-top: 10px; } .milestone { display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid rgba(255, 255, 255, 0.1); font-size: 14px; transition: background-color 0.3s ease; } .milestone:hover { background-color: rgba(255, 255, 255, 0.05); cursor: pointer; } .milestone-name { color: white; } .milestone-time { color: var(--neon-yellow); } .active-milestone { background-color: rgba(57, 255, 20, 0.1); border-left: 3px solid var(--neon-green); padding-left: 10px; } .active-milestone .milestone-name { color: var(--neon-green); } .footer { margin-top: 20px; text-align: center; font-size: 12px; color: rgba(255, 255, 255, 0.5); padding-top: 10px; border-top: 1px solid rgba(255, 255, 255, 0.1); } .system-message { margin-top: 5px; font-style: italic; color: var(--neon-pink); } .glitch-effect { position: relative; display: inline-block; } .glitch-effect::before, .glitch-effect::after { content: attr(data-text); position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: 0.8; } .glitch-effect::before { color: var(--neon-blue); z-index: -1; animation: glitch-effect 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94) both infinite; } .glitch-effect::after { color: var(--neon-pink); z-index: -2; animation: glitch-effect 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94) reverse both infinite; } /* ANIMATIONS */ @keyframes glitch-effect { 0% { transform: translate(0); } 20% { transform: translate(-2px, 2px); } 40% { transform: translate(-2px, -2px); } 60% { transform: translate(2px, 2px); } 80% { transform: translate(2px, -2px); } 100% { transform: translate(0); } } @keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0.2; } } @keyframes scanline { 0% { transform: translateX(-100%); } 100% { transform: translateX(100%); } } @keyframes pulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.05); opacity: 0.8; } } .pulse { animation: pulse 2s infinite ease-in-out; } /* Responsive adjustments */ @media (max-width: 700px) { .interface-container { max-width: 95%; padding: 15px; } .time-display { font-size: 3.5rem; } .controls { grid-template-columns: 1fr; } .session-info { flex-direction: column; gap: 15px; } .stat-value { font-size: 1.5rem; } } /* Overlay Glitch Effect */ .glitch-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: transparent; pointer-events: none; z-index: 10; opacity: 0; transition: opacity 0.3s ease; } .glitch-lines { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: repeating-linear-gradient( 0deg, transparent 0px, transparent 2px, rgba(255, 0, 127, 0.1) 2px, rgba(255, 0, 127, 0.1) 4px ); animation: moveLines 0.2s infinite linear; mix-blend-mode: overlay; } .glitch-block { position: absolute; background: rgba(0, 240, 255, 0.3); mix-blend-mode: overlay; } @keyframes moveLines { 0% { transform: translateY(0); } 100% { transform: translateY(4px); } } .clock-border { position: absolute; top: -10px; left: -10px; right: -10px; bottom: -10px; border: 2px solid transparent; border-radius: 15px; background-image: linear-gradient(var(--panel-bg), var(--panel-bg)), linear-gradient(45deg, var(--neon-blue), var(--neon-pink), var(--neon-blue)); background-origin: border-box; background-clip: padding-box, border-box; z-index: -1; animation: borderPulse 4s infinite alternate; } @keyframes borderPulse { 0% { box-shadow: 0 0 10px var(--neon-blue); } 50% { box-shadow: 0 0 20px var(--neon-pink); } 100% { box-shadow: 0 0 10px var(--neon-blue); } } </style> </head> <body> <div class="interface-container"> <div class="clock-border"></div> <div class="grid-lines"></div> <div class="glitch-overlay"> <div class="glitch-lines"></div> </div> <div class="header"> <div class="logo">CHRONOS-X HUD</div> <div class="status">SYNC ACTIVE</div> </div> <div class="main-clock"> <div class="time-display" id="time">00:00:00</div> <div class="date-display" id="date">INITIALIZING...</div> </div> <div class="session-info"> <div class="session-stat"> <div class="stat-value" id="session-time">03:42:17</div> <div class="stat-label">SESSION TIME</div> </div> <div class="session-stat"> <div class="stat-value" id="objectives">4/6</div> <div class="stat-label">OBJECTIVES</div> </div> <div class="session-stat"> <div class="stat-value" id="system-status">OPTIMAL</div> <div class="stat-label">SYSTEM STATUS</div> </div> </div> <div class="controls"> <div class="control-section"> <div class="section-title">EVENT COUNTDOWN</div> <div class="timer-display" id="countdown-timer">00:10:00</div> <div class="time-input"> <input type="number" id="minutes-input" placeholder="Min" min="0" max="59"> <input type="number" id="seconds-input" placeholder="Sec" min="0" max="59"> </div> <div class="button-group"> <button class="button" id="start-timer">START</button> <button class="button" id="reset-timer">RESET</button> </div> <div class="system-message" id="timer-message"></div> </div> <div class="control-section"> <div class="section-title">GAME MILESTONES</div> <ul class="milestone-list"> <li class="milestone active-milestone"> <span class="milestone-name">Boss Fight: Cyberdragon</span> <span class="milestone-time">T-00:10:00</span> </li> <li class="milestone"> <span class="milestone-name">Supply Drop</span> <span class="milestone-time">T-00:25:00</span> </li> <li class="milestone"> <span class="milestone-name">Zone Collapse</span> <span class="milestone-time">T-00:45:00</span> </li> <li class="milestone"> <span class="milestone-name">Midnight Protocol</span> <span class="milestone-time">T-01:30:00</span> </li> </ul> </div> </div> <div class="footer"> <div>CHRONOS-X v2.077.1 • NETRUNNER PROTOCOLS ACTIVE</div> <div class="system-message" id="system-message">CONNECTION STABLE // ENCRYPTION LEVEL: MAXIMUM</div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Main clock functionality function updateClock() { const now = new Date(); const hours = now.getHours().toString().padStart(2, '0'); const minutes = now.getMinutes().toString().padStart(2, '0'); const seconds = now.getSeconds().toString().padStart(2, '0'); const timeDisplay = document.getElementById('time'); const dateDisplay = document.getElementById('date'); // Update time with glitch effect on seconds change if (timeDisplay.textContent.slice(-2) !== seconds) { triggerGlitchEffect(); } timeDisplay.textContent = `${hours}:${minutes}:${seconds}`; // Format date in cyberpunk style const day = now.getDate().toString().padStart(2, '0'); const month = (now.getMonth() + 1).toString().padStart(2, '0'); const year = now.getFullYear(); dateDisplay.textContent = `${day}.${month}.${year} • SYSTEM DATE`; } // Initial clock update updateClock(); // Update clock every second setInterval(updateClock, 1000); // Countdown timer functionality let countdownInterval; let totalSeconds = 600; // default 10 minutes function updateCountdown() { const minutes = Math.floor(totalSeconds / 60).toString().padStart(2, '0'); const seconds = (totalSeconds % 60).toString().padStart(2, '0'); document.getElementById('countdown-timer').textContent = `00:${minutes}:${seconds}`; if (totalSeconds <= 0) { clearInterval(countdownInterval); document.getElementById('timer-message').textContent = "EVENT TRIGGERED! CHECK OBJECTIVES."; triggerMajorGlitchEffect(); // Reset to default after alarm setTimeout(() => { totalSeconds = 600; updateCountdown(); }, 5000); } else { totalSeconds--; } } // Start timer button document.getElementById('start-timer').addEventListener('click', function() { // Clear any existing interval clearInterval(countdownInterval); // Get input values const minutesInput = document.getElementById('minutes-input').value; const secondsInput = document.getElementById('seconds-input').value; // Validate and set total seconds if (minutesInput !== '' || secondsInput !== '') { totalSeconds = (parseInt(minutesInput || 0) * 60) + parseInt(secondsInput || 0); } // Start countdown updateCountdown(); countdownInterval = setInterval(updateCountdown, 1000); // Update message document.getElementById('timer-message').textContent = "COUNTDOWN INITIATED. STAY ALERT."; }); // Reset timer button document.getElementById('reset-timer').addEventListener('click', function() { clearInterval(countdownInterval); totalSeconds = 600; // Reset to 10 minutes updateCountdown(); document.getElementById('timer-message').textContent = "TIMER RESET. READY FOR INPUT."; }); // Milestone click event document.querySelectorAll('.milestone').forEach(milestone => { milestone.addEventListener('click', function() { // Remove active class from all milestones document.querySelectorAll('.milestone').forEach(m => { m.classList.remove('active-milestone'); }); // Add active class to clicked milestone this.classList.add('active-milestone'); // Parse time from milestone const timeString = this.querySelector('.milestone-time').textContent; const matches = timeString.match(/T-(\d+):(\d+):(\d+)/); if (matches) { const hours = parseInt(matches[1]); const minutes = parseInt(matches[2]); const seconds = parseInt(matches[3]); totalSeconds = hours * 3600 + minutes * 60 + seconds; // Update countdown display clearInterval(countdownInterval); updateCountdown(); countdownInterval = setInterval(updateCountdown, 1000); document.getElementById('timer-message').textContent = `TRACKING: ${this.querySelector('.milestone-name').textContent}`; } }); }); // Session time update let sessionSeconds = 13337; // 3:42:17 in seconds function updateSessionTime() { const hours = Math.floor(sessionSeconds / 3600).toString().padStart(2, '0'); const minutes = Math.floor((sessionSeconds % 3600) / 60).toString().padStart(2, '0'); const seconds = (sessionSeconds % 60).toString().padStart(2, '0'); document.getElementById('session-time').textContent = `${hours}:${minutes}:${seconds}`; sessionSeconds++; } // Update session time every second setInterval(updateSessionTime, 1000); // Glitch effect functions function triggerGlitchEffect() { const timeDisplay = document.getElementById('time'); // Add glitch class timeDisplay.classList.add('glitch-effect'); timeDisplay.setAttribute('data-text', timeDisplay.textContent); // Show overlay with scanlines briefly const glitchOverlay = document.querySelector('.glitch-overlay'); glitchOverlay.style.opacity = '0.3'; // Remove effects after short delay setTimeout(() => { timeDisplay.classList.remove('glitch-effect'); glitchOverlay.style.opacity = '0'; }, 300); } function triggerMajorGlitchEffect() { const container = document.querySelector('.interface-container'); const glitchOverlay = document.querySelector('.glitch-overlay'); // Add intense glitch effect glitchOverlay.style.opacity = '0.7'; // Create random glitch blocks for (let i = 0; i < 5; i++) { const glitchBlock = document.createElement('div'); glitchBlock.classList.add('glitch-block'); // Random position and size glitchBlock.style.top = `${Math.random() * 100}%`; glitchBlock.style.left = `${Math.random() * 100}%`; glitchBlock.style.width = `${Math.random() * 50 + 10}px`; glitchBlock.style.height = `${Math.random() * 20 + 5}px`; glitchOverlay.appendChild(glitchBlock); } // Add shake effect to container container.style.animation = 'none'; container.offsetHeight; // Trigger reflow container.style.animation = 'glitch-effect 0.1s infinite'; // Update system message document.getElementById('system-message').textContent = "⚠ ANOMALY DETECTED // STABILIZING SYSTEMS ⚠"; // Remove effects after delay setTimeout(() => { glitchOverlay.style.opacity = '0'; container.style.animation = ''; // Remove all glitch blocks const glitchBlocks = document.querySelectorAll('.glitch-block'); glitchBlocks.forEach(block => block.remove()); document.getElementById('system-message').textContent = "CONNECTION STABILIZED // SYSTEMS NOMINAL"; }, 2000); } // Random system message update function updateSystemMessage() { const messages = [ "CONNECTION STABLE // ENCRYPTION LEVEL: MAXIMUM", "PROCESSING NEURAL DATA // SYNC RATE: 98.7%", "TRACKING MULTIPLE OBJECTIVES // PRIORITY LEVEL: HIGH", "NEURAL INTERFACE ACTIVE // BANDWIDTH OPTIMAL", "SYSTEM SCAN COMPLETE // NO ANOMALIES DETECTED" ]; document.getElementById('system-message').textContent = messages[Math.floor(Math.random() * messages.length)]; } // Update system message randomly between 15-30 seconds setInterval(updateSystemMessage, Math.random() * 15000 + 15000); // Easter egg: Konami code const konamiCode = ['ArrowUp', 'ArrowUp', 'ArrowDown', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'ArrowLeft', 'ArrowRight', 'b', 'a']; let konamiIndex = 0; document.addEventListener('keydown', function(e) { if (e.key === konamiCode[konamiIndex]) { konamiIndex++; if (konamiIndex === konamiCode.length) { // Activate easter egg document.getElementById('system-status').textContent = "GOD MODE"; document.getElementById('system-status').style.color = "var(--neon-purple)"; document.getElementById('system-message').textContent = "CHEAT CODE ACTIVATED // ALL SYSTEMS OVERCLOCKED"; // Reset index konamiIndex = 0; } } else { konamiIndex = 0; } }); // Initial countdown update updateCountdown(); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Productivity Timer</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; } :root { --primary: #3a86ff; --primary-light: #61a0ff; --secondary: #ff006e; --accent: #fb5607; --dark: #212529; --light: #f8f9fa; --neutral: #6c757d; --neutral-light: #dee2e6; --success: #38b000; --warning: #ffbe0b; --font-display: 'Inter', sans-serif; } body { display: flex; justify-content: center; align-items: center; min-height: 700px; width: 100%; background-color: var(--light); color: var(--dark); overflow: hidden; } .container { width: 100%; max-width: 700px; height: 700px; padding: 2rem; display: flex; flex-direction: column; justify-content: space-between; background-color: var(--light); border-radius: 8px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.05); position: relative; overflow: hidden; } .header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem; } .title { font-size: 1.75rem; font-weight: 700; color: var(--dark); } .theme-toggle { width: 48px; height: 24px; background-color: var(--neutral-light); border-radius: 12px; position: relative; cursor: pointer; transition: background-color 0.3s ease; } .theme-toggle::after { content: ''; position: absolute; width: 20px; height: 20px; border-radius: 50%; background-color: white; top: 2px; left: 2px; transition: transform 0.3s ease; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); } .dark-mode .theme-toggle { background-color: var(--primary); } .dark-mode .theme-toggle::after { transform: translateX(24px); } .timer-display { display: flex; flex-direction: column; align-items: center; justify-content: center; flex-grow: 1; position: relative; } .progress-container { width: 300px; height: 300px; position: relative; display: flex; justify-content: center; align-items: center; } .progress-ring { transform: rotate(-90deg); transform-origin: center; } .progress-ring__circle { stroke: var(--primary); stroke-width: 8; fill: transparent; stroke-linecap: round; transition: stroke-dashoffset 0.3s ease; } .progress-ring__circle-bg { stroke: var(--neutral-light); stroke-width: 8; fill: transparent; } .time { position: absolute; font-size: 4rem; font-weight: 700; color: var(--dark); text-align: center; } .time-label { margin-top: 0.5rem; font-size: 1.25rem; font-weight: 500; color: var(--neutral); } .controls { display: flex; justify-content: center; gap: 1rem; margin-top: 2rem; } .btn { padding: 0.75rem 1.5rem; border: none; border-radius: 8px; font-weight: 600; font-size: 1rem; cursor: pointer; transition: all 0.2s ease; display: flex; align-items: center; justify-content: center; gap: 0.5rem; } .btn:active { transform: scale(0.97); } .btn-primary { background-color: var(--primary); color: white; } .btn-primary:hover { background-color: var(--primary-light); } .btn-secondary { background-color: var(--neutral-light); color: var(--dark); } .btn-secondary:hover { background-color: var(--neutral); color: white; } .btn-danger { background-color: var(--secondary); color: white; } .btn-danger:hover { background-color: #ff3385; } .btn-icon { width: 20px; height: 20px; } .task-section { margin-top: 2rem; border-top: 1px solid var(--neutral-light); padding-top: 1.5rem; } .task-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem; } .task-title { font-size: 1.25rem; font-weight: 600; } .task-input-container { display: flex; gap: 0.5rem; margin-bottom: 1rem; } .task-input { flex-grow: 1; padding: 0.75rem; border: 2px solid var(--neutral-light); border-radius: 6px; font-size: 1rem; transition: border-color 0.2s ease; } .task-input:focus { outline: none; border-color: var(--primary); } .task-list { max-height: 150px; overflow-y: auto; } .task-item { display: flex; align-items: center; padding: 0.75rem; border-radius: 6px; margin-bottom: 0.5rem; background-color: white; transition: background-color 0.2s ease; animation: fadeIn 0.3s ease; } .task-item:hover { background-color: rgba(222, 226, 230, 0.5); } .task-checkbox { margin-right: 0.75rem; width: 20px; height: 20px; border-radius: 4px; border: 2px solid var(--neutral-light); display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.2s ease; } .task-checkbox.checked { background-color: var(--success); border-color: var(--success); } .task-checkbox.checked::after { content: '✓'; color: white; font-weight: bold; } .task-text { flex-grow: 1; font-size: 1rem; transition: color 0.2s ease, text-decoration 0.2s ease; } .task-item.completed .task-text { color: var(--neutral); text-decoration: line-through; } .task-delete { color: var(--neutral); background: none; border: none; cursor: pointer; font-size: 1.25rem; opacity: 0; transition: opacity 0.2s ease, color 0.2s ease; } .task-item:hover .task-delete { opacity: 1; } .task-delete:hover { color: var(--secondary); } .settings { margin-top: 1.5rem; } .settings-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem; cursor: pointer; } .settings-title { font-size: 1rem; font-weight: 500; color: var(--neutral); } .settings-content { display: none; padding: 1rem; background-color: rgba(222, 226, 230, 0.3); border-radius: 8px; margin-bottom: 1rem; } .settings-content.active { display: block; animation: fadeIn 0.3s ease; } .settings-row { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.75rem; } .settings-label { font-size: 0.875rem; color: var(--dark); } .settings-input { width: 80px; padding: 0.5rem; border: 1px solid var(--neutral-light); border-radius: 4px; text-align: center; } .toast { position: fixed; bottom: -60px; left: 50%; transform: translateX(-50%); background-color: var(--dark); color: white; padding: 0.75rem 1.5rem; border-radius: 8px; font-size: 0.875rem; font-weight: 500; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); opacity: 0; transition: bottom 0.3s ease, opacity 0.3s ease; z-index: 1000; } .toast.active { bottom: 20px; opacity: 1; } .notification { position: absolute; top: 20px; right: 20px; background-color: var(--primary); color: white; padding: 0.75rem 1rem; border-radius: 8px; font-size: 0.875rem; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); transform: translateX(150%); opacity: 0; transition: transform 0.3s ease, opacity 0.3s ease; z-index: 1000; max-width: 300px; } .notification.active { transform: translateX(0); opacity: 1; } .dark-mode { background-color: var(--dark); color: var(--light); } .dark-mode .container { background-color: #2b2d42; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2); } .dark-mode .title { color: var(--light); } .dark-mode .time { color: var(--light); } .dark-mode .progress-ring__circle-bg { stroke: #3d3d3d; } .dark-mode .btn-secondary { background-color: #3d3d3d; color: var(--light); } .dark-mode .btn-secondary:hover { background-color: #4d4d4d; } .dark-mode .task-section { border-color: #3d3d3d; } .dark-mode .task-input { background-color: #3d3d3d; border-color: #3d3d3d; color: var(--light); } .dark-mode .task-item { background-color: #3d3d3d; color: var(--light); } .dark-mode .task-item:hover { background-color: #4d4d4d; } .dark-mode .settings-content { background-color: #3d3d3d; } .dark-mode .settings-label { color: var(--light); } .dark-mode .settings-input { background-color: #2b2d42; border-color: #3d3d3d; color: var(--light); } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } @keyframes spin { to { transform: rotate(360deg); } } .pulse { animation: pulse 1s infinite; } .completed-label { font-size: 1.5rem; font-weight: 600; color: var(--success); margin-top: 1rem; opacity: 0; transition: opacity 0.3s ease; } .completed-label.active { opacity: 1; animation: fadeIn 0.5s ease; } .productivity-tip { padding: 1rem; background-color: rgba(58, 134, 255, 0.1); border-left: 4px solid var(--primary); border-radius: 4px; margin-top: 1rem; font-size: 0.875rem; line-height: 1.4; } .tip-title { font-weight: 600; margin-bottom: 0.5rem; color: var(--primary); } /* Responsive styles */ @media (max-width: 600px) { .container { padding: 1.5rem; } .progress-container { width: 250px; height: 250px; } .time { font-size: 3.5rem; } .task-list { max-height: 120px; } } @media (max-width: 400px) { .container { padding: 1rem; } .progress-container { width: 200px; height: 200px; } .time { font-size: 3rem; } .controls { flex-direction: column; gap: 0.5rem; } .btn { width: 100%; } } </style> </head> <body> <div class="container"> <div class="header"> <h1 class="title">Focus Timer</h1> <div class="theme-toggle" id="themeToggle"></div> </div> <div class="timer-display"> <div class="progress-container"> <svg class="progress-ring" width="300" height="300"> <circle class="progress-ring__circle-bg" cx="150" cy="150" r="120"></circle> <circle class="progress-ring__circle" cx="150" cy="150" r="120" stroke-dasharray="754" stroke-dashoffset="0"></circle> </svg> <div class="time" id="time">25:00</div> </div> <div class="time-label" id="timeLabel">Focus Session</div> <div class="completed-label" id="completedLabel">Session Complete!</div> <div class="controls"> <button class="btn btn-primary" id="startBtn"> <svg class="btn-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M8 5.14V19.14L19 12.14L8 5.14Z" fill="currentColor"/> </svg> Start Focus </button> <button class="btn btn-secondary" id="pauseBtn" disabled> <svg class="btn-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M6 19H10V5H6V19ZM14 5V19H18V5H14Z" fill="currentColor"/> </svg> Pause </button> <button class="btn btn-danger" id="resetBtn" disabled> <svg class="btn-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M17.65 6.35C16.2 4.9 14.21 4 12 4C7.58 4 4.01 7.58 4.01 12C4.01 16.42 7.58 20 12 20C15.73 20 18.84 17.45 19.73 14H17.65C16.83 16.33 14.61 18 12 18C8.69 18 6 15.31 6 12C6 8.69 8.69 6 12 6C13.66 6 15.14 6.69 16.22 7.78L13 11H20V4L17.65 6.35Z" fill="currentColor"/> </svg> Reset </button> </div> </div> <div class="task-section"> <div class="task-header"> <h2 class="task-title">Current Tasks</h2> <span id="taskCount">0 tasks</span> </div> <div class="task-input-container"> <input type="text" class="task-input" id="taskInput" placeholder="Add a new task..."> <button class="btn btn-primary" id="addTaskBtn">Add</button> </div> <div class="task-list" id="taskList"> <!-- Tasks will be added here dynamically --> </div> <div class="productivity-tip"> <div class="tip-title">Productivity Tip</div> <p>Break complex projects into small, actionable tasks. Completing these micro-tasks creates momentum and keeps your motivation high throughout the day.</p> </div> </div> <div class="settings"> <div class="settings-header" id="settingsToggle"> <h3 class="settings-title">Timer Settings</h3> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M7 10L12 15L17 10H7Z" fill="currentColor"/> </svg> </div> <div class="settings-content" id="settingsContent"> <div class="settings-row"> <span class="settings-label">Focus Time (minutes)</span> <input type="number" class="settings-input" id="focusTimeInput" value="25" min="1" max="60"> </div> <div class="settings-row"> <span class="settings-label">Short Break (minutes)</span> <input type="number" class="settings-input" id="shortBreakInput" value="5" min="1" max="30"> </div> <div class="settings-row"> <span class="settings-label">Long Break (minutes)</span> <input type="number" class="settings-input" id="longBreakInput" value="15" min="1" max="60"> </div> <div class="settings-row"> <span class="settings-label">Sessions before long break</span> <input type="number" class="settings-input" id="sessionsInput" value="4" min="1" max="10"> </div> <button class="btn btn-primary" id="saveSettingsBtn">Save Settings</button> </div> </div> </div> <div class="toast" id="toast">Settings saved successfully!</div> <div class="notification" id="notification">Time to take a break!</div> <script> document.addEventListener('DOMContentLoaded', function() { // DOM Elements const timeDisplay = document.getElementById('time'); const timeLabel = document.getElementById('timeLabel'); const completedLabel = document.getElementById('completedLabel'); const startBtn = document.getElementById('startBtn'); const pauseBtn = document.getElementById('pauseBtn'); const resetBtn = document.getElementById('resetBtn'); const progressRing = document.querySelector('.progress-ring__circle'); const taskInput = document.getElementById('taskInput'); const addTaskBtn = document.getElementById('addTaskBtn'); const taskList = document.getElementById('taskList'); const taskCount = document.getElementById('taskCount'); const settingsToggle = document.getElementById('settingsToggle'); const settingsContent = document.getElementById('settingsContent'); const saveSettingsBtn = document.getElementById('saveSettingsBtn'); const focusTimeInput = document.getElementById('focusTimeInput'); const shortBreakInput = document.getElementById('shortBreakInput'); const longBreakInput = document.getElementById('longBreakInput'); const sessionsInput = document.getElementById('sessionsInput'); const toast = document.getElementById('toast'); const notification = document.getElementById('notification'); const themeToggle = document.getElementById('themeToggle'); // Timer variables let timer; let timeLeft; let totalTime; let isRunning = false; let isPaused = false; let mode = 'focus'; // focus, shortBreak, longBreak let sessionsCompleted = 0; const circumference = 2 * Math.PI * 120; progressRing.style.strokeDasharray = circumference; progressRing.style.strokeDashoffset = 0; // Settings let settings = { focusTime: 25, shortBreak: 5, longBreak: 15, sessionsBeforeLongBreak: 4 }; // Initialize timer function initTimer() { switch (mode) { case 'focus': totalTime = settings.focusTime * 60; timeLeft = totalTime; timeLabel.textContent = 'Focus Session'; progressRing.style.stroke = '#3a86ff'; break; case 'shortBreak': totalTime = settings.shortBreak * 60; timeLeft = totalTime; timeLabel.textContent = 'Short Break'; progressRing.style.stroke = '#38b000'; break; case 'longBreak': totalTime = settings.longBreak * 60; timeLeft = totalTime; timeLabel.textContent = 'Long Break'; progressRing.style.stroke = '#ffbe0b'; break; } updateTimeDisplay(); progressRing.style.strokeDashoffset = 0; } // Format time as MM:SS function formatTime(seconds) { const mins = Math.floor(seconds / 60); const secs = seconds % 60; return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`; } // Update time display function updateTimeDisplay() { timeDisplay.textContent = formatTime(timeLeft); const progress = (totalTime - timeLeft) / totalTime; const offset = circumference * progress; progressRing.style.strokeDashoffset = offset; } // Start timer function startTimer() { if (isRunning) return; isRunning = true; isPaused = false; startBtn.disabled = true; pauseBtn.disabled = false; resetBtn.disabled = false; completedLabel.classList.remove('active'); timer = setInterval(() => { timeLeft--; updateTimeDisplay(); if (timeLeft <= 0) { clearInterval(timer); isRunning = false; timerComplete(); } // Add pulse effect when 10 seconds left if (timeLeft <= 10 && mode === 'focus') { timeDisplay.classList.add('pulse'); } else { timeDisplay.classList.remove('pulse'); } }, 1000); } // Pause timer function pauseTimer() { if (!isRunning || isPaused) return; clearInterval(timer); isPaused = true; isRunning = false; pauseBtn.innerHTML = ` <svg class="btn-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M8 5.14V19.14L19 12.14L8 5.14Z" fill="currentColor"/> </svg> Resume `; startBtn.disabled = true; } // Resume timer function resumeTimer() { if (!isPaused) return; isPaused = false; pauseBtn.innerHTML = ` <svg class="btn-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M6 19H10V5H6V19ZM14 5V19H18V5H14Z" fill="currentColor"/> </svg> Pause `; startTimer(); } // Reset timer function resetTimer() { clearInterval(timer); isRunning = false; isPaused = false; initTimer(); startBtn.disabled = false; pauseBtn.disabled = true; resetBtn.disabled = true; pauseBtn.innerHTML = ` <svg class="btn-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M6 19H10V5H6V19ZM14 5V19H18V5H14Z" fill="currentColor"/> </svg> Pause `; timeDisplay.classList.remove('pulse'); completedLabel.classList.remove('active'); } // Timer complete handler function timerComplete() { if (mode === 'focus') { sessionsCompleted++; showNotification('Focus session complete! Time for a break.'); completedLabel.classList.add('active'); if (sessionsCompleted % settings.sessionsBeforeLongBreak === 0) { mode = 'longBreak'; } else { mode = 'shortBreak'; } } else { showNotification('Break complete! Time to focus again.'); mode = 'focus'; } initTimer(); startBtn.disabled = false; pauseBtn.disabled = true; resetBtn.disabled = true; } // Add task function function addTask() { const taskText = taskInput.value.trim(); if (!taskText) return; createTaskElement(taskText); taskInput.value = ''; updateTaskCount(); // Save to local storage saveTasks(); } // Create task element function createTaskElement(text, completed = false) { const taskItem = document.createElement('div'); taskItem.className = `task-item ${completed ? 'completed' : ''}`; const checkbox = document.createElement('div'); checkbox.className = `task-checkbox ${completed ? 'checked' : ''}`; checkbox.addEventListener('click', () => { checkbox.classList.toggle('checked'); taskItem.classList.toggle('completed'); updateTaskCount(); saveTasks(); }); const taskText = document.createElement('div'); taskText.className = 'task-text'; taskText.textContent = text; const deleteBtn = document.createElement('button'); deleteBtn.className = 'task-delete'; deleteBtn.innerHTML = '×'; deleteBtn.addEventListener('click', () => { taskItem.remove(); updateTaskCount(); saveTasks(); }); taskItem.appendChild(checkbox); taskItem.appendChild(taskText); taskItem.appendChild(deleteBtn); taskList.appendChild(taskItem); } // Update task count function updateTaskCount() { const totalTasks = taskList.querySelectorAll('.task-item').length; const completedTasks = taskList.querySelectorAll('.task-item.completed').length; taskCount.textContent = `${completedTasks}/${totalTasks} tasks`; } // Save tasks to local storage function saveTasks() { const tasks = []; taskList.querySelectorAll('.task-item').forEach(item => { tasks.push({ text: item.querySelector('.task-text').textContent, completed: item.classList.contains('completed') }); }); localStorage.setItem('focusTimer_tasks', JSON.stringify(tasks)); } // Load tasks from local storage function loadTasks() { const savedTasks = localStorage.getItem('focusTimer_tasks'); if (savedTasks) { const tasks = JSON.parse(savedTasks); tasks.forEach(task => { createTaskElement(task.text, task.completed); }); updateTaskCount(); } } // Save settings to local storage function saveSettings() { settings.focusTime = parseInt(focusTimeInput.value) || 25; settings.shortBreak = parseInt(shortBreakInput.value) || 5; settings.longBreak = parseInt(longBreakInput.value) || 15; settings.sessionsBeforeLongBreak = parseInt(sessionsInput.value) || 4; localStorage.setItem('focusTimer_settings', JSON.stringify(settings)); // Reset timer with new settings resetTimer(); // Show toast message showToast('Settings saved successfully!'); // Close settings panel settingsContent.classList.remove('active'); } // Load settings from local storage function loadSettings() { const savedSettings = localStorage.getItem('focusTimer_settings'); if (savedSettings) { settings = JSON.parse(savedSettings); focusTimeInput.value = settings.focusTime; shortBreakInput.value = settings.shortBreak; longBreakInput.value = settings.longBreak; sessionsInput.value = settings.sessionsBeforeLongBreak; } } // Show toast message function showToast(message) { toast.textContent = message; toast.classList.add('active'); setTimeout(() => { toast.classList.remove('active'); }, 3000); } // Show notification function showNotification(message) { notification.textContent = message; notification.classList.add('active'); setTimeout(() => { notification.classList.remove('active'); }, 4000); } // Toggle dark mode function toggleDarkMode() { document.body.classList.toggle('dark-mode'); const isDarkMode = document.body.classList.contains('dark-mode'); localStorage.setItem('focusTimer_darkMode', isDarkMode); } // Load dark mode preference function loadDarkModePreference() { const isDarkMode = localStorage.getItem('focusTimer_darkMode') === 'true'; if (isDarkMode) { document.body.classList.add('dark-mode'); } } // Event listeners startBtn.addEventListener('click', startTimer); pauseBtn.addEventListener('click', () => { if (isPaused) { resumeTimer(); } else { pauseTimer(); } }); resetBtn.addEventListener('click', resetTimer); addTaskBtn.addEventListener('click', addTask); taskInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') { addTask(); } }); settingsToggle.addEventListener('click', () => { settingsContent.classList.toggle('active'); }); saveSettingsBtn.addEventListener('click', saveSettings); themeToggle.addEventListener('click', toggleDarkMode); // Initialize app initTimer(); loadTasks(); loadSettings(); loadDarkModePreference(); }); </script> </body> </html>
<html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Sports Event Clock</title> <style> :root { --team1-primary: #e74c3c; --team1-secondary: #c0392b; --team2-primary: #3498db; --team2-secondary: #2980b9; --neutral: #ecf0f1; --dark: #2c3e50; --highlight: #f1c40f; --time-bg: rgba(44, 62, 80, 0.85); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Roboto', 'Segoe UI', sans-serif; transition: all 0.3s ease; } body { display: flex; justify-content: center; align-items: center; min-height: 100vh; background: linear-gradient(135deg, var(--dark) 0%, #34495e 100%); overflow: hidden; } .sports-clock-container { width: 100%; max-width: 680px; height: 680px; position: relative; border-radius: 16px; overflow: hidden; box-shadow: 0 15px 35px rgba(0, 0, 0, 0.3); } .live-indicator { position: absolute; top: 20px; left: 20px; z-index: 100; display: flex; align-items: center; background: rgba(0, 0, 0, 0.6); padding: 8px 15px; border-radius: 50px; } .live-dot { width: 12px; height: 12px; background-color: #e74c3c; border-radius: 50%; margin-right: 8px; animation: pulse 1.5s infinite; } .live-text { color: white; font-weight: 700; font-size: 14px; letter-spacing: 1px; text-transform: uppercase; } .background { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: url('https://images.unsplash.com/photo-1574629810360-7efbbe195018?q=80&w=1936&auto=format&fit=crop') center/cover no-repeat; filter: brightness(0.6); z-index: 1; } .teams-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, rgba(231, 76, 60, 0.3) 0%, rgba(255, 255, 255, 0) 40%, rgba(255, 255, 255, 0) 60%, rgba(52, 152, 219, 0.3) 100%); z-index: 2; } .game-info { position: absolute; top: 60px; left: 0; width: 100%; z-index: 5; text-align: center; } .league { color: var(--neutral); font-size: 16px; text-transform: uppercase; letter-spacing: 2px; font-weight: 500; margin-bottom: 10px; opacity: 0.9; } .match-type { color: var(--highlight); font-size: 18px; text-transform: uppercase; letter-spacing: 1px; font-weight: 700; margin-bottom: 30px; background-color: rgba(0, 0, 0, 0.5); padding: 5px 15px; border-radius: 30px; display: inline-block; } .teams { display: flex; justify-content: space-between; align-items: center; padding: 0 30px; margin-bottom: 30px; position: relative; } .team { display: flex; flex-direction: column; align-items: center; color: white; width: 40%; } .team.team1 { text-align: right; } .team.team2 { text-align: left; } .team-logo { width: 80px; height: 80px; background-color: rgba(255, 255, 255, 0.1); border-radius: 50%; display: flex; justify-content: center; align-items: center; margin-bottom: 15px; position: relative; overflow: hidden; border: 3px solid var(--neutral); } .team1 .team-logo { box-shadow: 0 0 20px var(--team1-primary); } .team2 .team-logo { box-shadow: 0 0 20px var(--team2-primary); } .team-logo::before { content: ''; position: absolute; width: 100%; height: 100%; background-color: rgba(255, 255, 255, 0.1); border-radius: 50%; } .team1 .team-logo::before { background-color: var(--team1-primary); opacity: 0.4; } .team2 .team-logo::before { background-color: var(--team2-primary); opacity: 0.4; } .team-name { font-size: 24px; font-weight: 700; margin-bottom: 5px; text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.5); } .team-score { font-size: 42px; font-weight: 900; text-shadow: 3px 3px 6px rgba(0, 0, 0, 0.6); } .team1 .team-score { color: var(--team1-primary); } .team2 .team-score { color: var(--team2-primary); } .vs { font-size: 20px; font-weight: 700; color: var(--neutral); position: relative; } .time-display { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 10; background-color: var(--time-bg); padding: 20px 40px; border-radius: 60px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); text-align: center; width: 280px; border: 3px solid rgba(255, 255, 255, 0.1); } .time { font-size: 48px; font-weight: 900; color: white; margin-bottom: 5px; font-variant-numeric: tabular-nums; letter-spacing: 1px; } .period { font-size: 16px; font-weight: 600; color: var(--highlight); text-transform: uppercase; letter-spacing: 1px; } .game-events { position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%); z-index: 5; width: 90%; max-width: 600px; } .event-list { list-style: none; max-height: 180px; overflow-y: auto; padding: 0 10px; margin-top: 10px; border-radius: 8px; background-color: rgba(0, 0, 0, 0.6); scrollbar-width: thin; scrollbar-color: var(--neutral) transparent; } .event-list::-webkit-scrollbar { width: 5px; } .event-list::-webkit-scrollbar-track { background: transparent; } .event-list::-webkit-scrollbar-thumb { background-color: var(--neutral); border-radius: 20px; } .event-item { display: flex; align-items: center; padding: 10px; border-bottom: 1px solid rgba(255, 255, 255, 0.1); color: white; transition: transform 0.3s, background-color 0.3s; } .event-item:last-child { border-bottom: none; } .event-item:hover { background-color: rgba(255, 255, 255, 0.1); transform: translateX(5px); } .event-time { font-size: 14px; font-weight: 700; margin-right: 10px; padding: 4px 8px; background-color: rgba(255, 255, 255, 0.15); border-radius: 4px; min-width: 45px; text-align: center; } .event-icon { margin: 0 10px; font-size: 18px; } .event-team1 { color: var(--team1-primary); } .event-team2 { color: var(--team2-primary); } .event-description { flex: 1; font-size: 14px; } .event-player { font-weight: 700; } .events-title { color: white; font-size: 20px; margin-bottom: 10px; text-align: center; position: relative; display: inline-block; left: 50%; transform: translateX(-50%); padding: 5px 20px; background-color: rgba(0, 0, 0, 0.6); border-radius: 30px; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); } .events-title::before { content: "📢"; margin-right: 10px; } .next-event-alert { position: absolute; top: 20px; right: 20px; z-index: 100; background-color: var(--highlight); color: var(--dark); padding: 10px 20px; border-radius: 8px; font-weight: 700; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3); transform: translateY(-100px); opacity: 0; transition: transform 0.5s, opacity 0.5s; } .next-event-alert.show { transform: translateY(0); opacity: 1; } .time-controls { display: flex; justify-content: center; margin-top: 15px; gap: 10px; } .control-btn { background: rgba(255, 255, 255, 0.15); border: none; color: white; border-radius: 50%; width: 36px; height: 36px; display: flex; justify-content: center; align-items: center; cursor: pointer; transition: all 0.2s; } .control-btn:hover { background: rgba(255, 255, 255, 0.3); transform: scale(1.1); } .control-btn:active { transform: scale(0.95); } .play-btn { background: var(--highlight); color: var(--dark); width: 50px; height: 50px; font-size: 20px; } .play-btn:hover { background: #f39c12; } .countdown-container { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%) scale(0); z-index: 20; background-color: rgba(0, 0, 0, 0.8); border-radius: 50%; width: 200px; height: 200px; display: flex; justify-content: center; align-items: center; opacity: 0; transition: transform 0.5s, opacity 0.5s; } .countdown-container.show { transform: translate(-50%, -50%) scale(1); opacity: 1; } .countdown-number { font-size: 80px; font-weight: 900; color: var(--highlight); } @keyframes pulse { 0% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.2); opacity: 0.7; } 100% { transform: scale(1); opacity: 1; } } @keyframes scorePulse { 0% { transform: scale(1); } 50% { transform: scale(1.2); } 100% { transform: scale(1); } } @keyframes highlightEvent { 0% { background-color: rgba(255, 255, 255, 0); } 50% { background-color: rgba(255, 255, 255, 0.3); } 100% { background-color: rgba(255, 255, 255, 0); } } /* Responsive Design */ @media (max-width: 700px) { .sports-clock-container { height: 100vh; max-height: 680px; border-radius: 0; } .teams { padding: 0 15px; } .team-logo { width: 60px; height: 60px; } .team-name { font-size: 20px; } .team-score { font-size: 36px; } .time-display { width: 240px; padding: 15px 30px; } .time { font-size: 40px; } .game-events { width: 95%; } .event-list { max-height: 150px; } } @media (max-width: 500px) { .game-info { top: 40px; } .team-logo { width: 50px; height: 50px; } .team-name { font-size: 16px; } .team-score { font-size: 32px; } .time-display { width: 220px; padding: 12px 25px; } .time { font-size: 36px; } .period { font-size: 14px; } .event-list { max-height: 120px; } .event-item { padding: 8px; } .event-time { font-size: 12px; min-width: 40px; } .event-description { font-size: 12px; } } </style> </head> <body> <div class="sports-clock-container"> <div class="background"></div> <div class="teams-overlay"></div> <div class="live-indicator"> <div class="live-dot"></div> <div class="live-text">Live</div> </div> <div class="next-event-alert" id="nextEventAlert"> Coming up: Water break in 2 minutes </div> <div class="game-info"> <div class="league">Premier League</div> <div class="match-type">Semi-Final</div> <div class="teams"> <div class="team team1"> <div class="team-logo"> <svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 2L2 7L12 12L22 7L12 2Z" fill="#ffffff" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M2 17L12 22L22 17" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M2 12L12 17L22 12" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> <div class="team-name">Arsenal</div> <div class="team-score" id="team1Score">2</div> </div> <div class="vs">VS</div> <div class="team team2"> <div class="team-logo"> <svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M12 8L8 12L12 16L16 12L12 8Z" fill="#ffffff" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> <div class="team-name">Chelsea</div> <div class="team-score" id="team2Score">1</div> </div> </div> </div> <div class="time-display"> <div class="time" id="matchTime">67:32</div> <div class="period" id="periodDisplay">Second Half</div> <div class="time-controls"> <button class="control-btn" id="prevBtn">⏮️</button> <button class="control-btn play-btn" id="playBtn">▶️</button> <button class="control-btn" id="nextBtn">⏭️</button> </div> </div> <div class="countdown-container" id="countdownContainer"> <div class="countdown-number" id="countdownNumber">3</div> </div> <div class="game-events"> <div class="events-title">Match Timeline</div> <ul class="event-list" id="eventList"> <li class="event-item"> <div class="event-time">4'</div> <i class="event-icon event-team1">⚽</i> <div class="event-description"><span class="event-player">Smith</span> scores from a brilliant free kick!</div> </li> <li class="event-item"> <div class="event-time">23'</div> <i class="event-icon event-team2">🟨</i> <div class="event-description"><span class="event-player">Mitchell</span> booked for a late challenge.</div> </li> <li class="event-item"> <div class="event-time">29'</div> <i class="event-icon event-team2">⚽</i> <div class="event-description"><span class="event-player">Palmer</span> equalizes with a counter-attack goal!</div> </li> <li class="event-item"> <div class="event-time">45+2'</div> <i class="event-icon">🔄</i> <div class="event-description">First half ends. Score: 1-1</div> </li> <li class="event-item"> <div class="event-time">46'</div> <i class="event-icon">🔄</i> <div class="event-description">Second half begins!</div> </li> <li class="event-item"> <div class="event-time">54'</div> <i class="event-icon event-team1">⚽</i> <div class="event-description"><span class="event-player">Martinelli</span> puts Arsenal back in front! Wonderful team goal.</div> </li> <li class="event-item"> <div class="event-time">58'</div> <i class="event-icon event-team2">🔄</i> <div class="event-description">Substitution: <span class="event-player">Felix</span> replaces <span class="event-player">Hudson-Odoi</span></div> </li> </ul> </div> </div> <script> // DOM elements const playBtn = document.getElementById('playBtn'); const prevBtn = document.getElementById('prevBtn'); const nextBtn = document.getElementById('nextBtn'); const matchTimeEl = document.getElementById('matchTime'); const periodDisplayEl = document.getElementById('periodDisplay'); const team1ScoreEl = document.getElementById('team1Score'); const team2ScoreEl = document.getElementById('team2Score'); const eventListEl = document.getElementById('eventList'); const nextEventAlertEl = document.getElementById('nextEventAlert'); const countdownContainerEl = document.getElementById('countdownContainer'); const countdownNumberEl = document.getElementById('countdownNumber'); // Match state let matchState = { isPlaying: false, currentMinute: 67, currentSecond: 32, period: "Second Half", team1Score: 2, team2Score: 1, events: [ { time: "4", team: 1, type: "goal", player: "Smith", description: "scores from a brilliant free kick!" }, { time: "23", team: 2, type: "yellow", player: "Mitchell", description: "booked for a late challenge." }, { time: "29", team: 2, type: "goal", player: "Palmer", description: "equalizes with a counter-attack goal!" }, { time: "45+2", team: 0, type: "period", player: "", description: "First half ends. Score: 1-1" }, { time: "46", team: 0, type: "period", player: "", description: "Second half begins!" }, { time: "54", team: 1, type: "goal", player: "Martinelli", description: "puts Arsenal back in front! Wonderful team goal." }, { time: "58", team: 2, type: "substitution", player: "Felix", description: "replaces Hudson-Odoi" }, { time: "70", team: 0, type: "break", player: "", description: "Water break." }, { time: "76", team: 2, type: "goal-miss", player: "Sterling", description: "misses a great chance! Hits the crossbar." }, { time: "82", team: 1, type: "substitution", player: "Saka", description: "comes off for Nelson. Tactical change." }, { time: "88", team: 2, type: "red", player: "James", description: "sent off for second yellow card!" }, { time: "90+4", team: 0, type: "period", player: "", description: "Full time! Arsenal 2-1 Chelsea" } ], upcomingEvents: [ { time: 70, description: "Water break" }, { time: 75, description: "Substitution window" }, { time: 88, description: "Final changes" }, { time: 90, description: "Added time announcement" }, ], nextEventIndex: 0 }; // Icon mapping const iconMap = { "goal": "⚽", "yellow": "🟨", "red": "🟥", "substitution": "🔄", "period": "🔄", "break": "🥤", "goal-miss": "❌" }; // Timer variables let clockInterval; let alertTimeout; // Initialize the match time display function updateTimeDisplay() { matchTimeEl.textContent = `${matchState.currentMinute}:${matchState.currentSecond.toString().padStart(2, '0')}`; periodDisplayEl.textContent = matchState.period; } // Update scores function updateScores() { team1ScoreEl.textContent = matchState.team1Score; team2ScoreEl.textContent = matchState.team2Score; } // Start/stop match timer function togglePlayState() { matchState.isPlaying = !matchState.isPlaying; if (matchState.isPlaying) { playBtn.innerHTML = "⏸️"; startClock(); } else { playBtn.innerHTML = "▶️"; stopClock(); } } // Start the match clock function startClock() { if (clockInterval) clearInterval(clockInterval); clockInterval = setInterval(() => { matchState.currentSecond++; if (matchState.currentSecond >= 60) { matchState.currentSecond = 0; matchState.currentMinute++; // Check for upcoming events checkUpcomingEvents(); } updateTimeDisplay(); // End the match at 90+5 if (matchState.currentMinute >= 95) { endMatch(); } // Change period at 45+ if (matchState.currentMinute === 47 && matchState.currentSecond === 0 && matchState.period === "First Half") { showCountdown("Second Half"); } }, 1000); } // Stop the match clock function stopClock() { clearInterval(clockInterval); } // Show a countdown animation function showCountdown(nextPeriod) { stopClock(); matchState.isPlaying = false; playBtn.innerHTML = "▶️"; countdownContainerEl.classList.add('show'); let count = 3; countdownNumberEl.textContent = count; const countInterval = setInterval(() => { count--; countdownNumberEl.textContent = count; if (count <= 0) { clearInterval(countInterval); countdownContainerEl.classList.remove('show'); // Set up for next period if (nextPeriod === "Second Half") { matchState.currentMinute = 46; matchState.currentSecond = 0; matchState.period = "Second Half"; updateTimeDisplay(); } } }, 1000); } // End the match function endMatch() { stopClock(); matchState.isPlaying = false; playBtn.innerHTML = "▶️"; matchState.period = "Full Time"; updateTimeDisplay(); // Add final event addEventToTimeline({ time: "90+4", team: 0, type: "period", player: "", description: "Full time! Arsenal 2-1 Chelsea" }); } // Check for upcoming events function checkUpcomingEvents() { if (matchState.nextEventIndex < matchState.upcomingEvents.length) { const nextEvent = matchState.upcomingEvents[matchState.nextEventIndex]; if (matchState.currentMinute === nextEvent.time - 2) { showEventAlert(`Coming up: ${nextEvent.description} in 2 minutes`); } else if (matchState.currentMinute === nextEvent.time) { addEventToTimeline({ time: matchState.currentMinute.toString(), team: 0, type: nextEvent.description.toLowerCase().includes("water") ? "break" : "period", player: "", description: nextEvent.description }); matchState.nextEventIndex++; } } } // Show event alert popup function showEventAlert(message) { nextEventAlertEl.textContent = message; nextEventAlertEl.classList.add('show'); if (alertTimeout) clearTimeout(alertTimeout); alertTimeout = setTimeout(() => { nextEventAlertEl.classList.remove('show'); }, 5000); } // Add event to timeline function addEventToTimeline(event) { const li = document.createElement('li'); li.className = 'event-item'; const timeDiv = document.createElement('div'); timeDiv.className = 'event-time'; timeDiv.textContent = event.time + "'"; const iconI = document.createElement('i'); iconI.className = `event-icon ${event.team === 1 ? 'event-team1' : event.team === 2 ? 'event-team2' : ''}`; iconI.textContent = iconMap[event.type] || "🔄"; const descDiv = document.createElement('div'); descDiv.className = 'event-description'; if (event.player) { const playerSpan = document.createElement('span'); playerSpan.className = 'event-player'; playerSpan.textContent = event.player; descDiv.appendChild(playerSpan); descDiv.append(" " + event.description); } else { descDiv.textContent = event.description; } li.appendChild(timeDiv); li.appendChild(iconI); li.appendChild(descDiv); eventListEl.prepend(li); // Animate the new event li.style.animation = 'highlightEvent 2s ease'; // If it's a goal, update the score and animate if (event.type === 'goal') { if (event.team === 1) { matchState.team1Score++; team1ScoreEl.style.animation = 'scorePulse 0.5s ease'; setTimeout(() => { team1ScoreEl.style.animation = ''; }, 500); } else if (event.team === 2) { matchState.team2Score++; team2ScoreEl.style.animation = 'scorePulse 0.5s ease'; setTimeout(() => { team2ScoreEl.style.animation = ''; }, 500); } updateScores(); } // Scroll to the top eventListEl.scrollTop = 0; } // Skip forward in time function skipForward() { matchState.currentMinute += 5; if (matchState.currentMinute > 90) { matchState.currentMinute = 90; matchState.currentSecond = 0; } updateTimeDisplay(); checkUpcomingEvents(); } // Skip backward in time function skipBackward() { matchState.currentMinute -= 5; if (matchState.currentMinute < 0) { matchState.currentMinute = 0; matchState.currentSecond = 0; } updateTimeDisplay(); } // Event listeners playBtn.addEventListener('click', togglePlayState); nextBtn.addEventListener('click', skipForward); prevBtn.addEventListener('click', skipBackward); // Initialize updateTimeDisplay(); updateScores(); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Smartwatch Face Clock</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { display: flex; justify-content: center; align-items: center; min-height: 100vh; background: #1a1a1a; overflow: hidden; } .watch-container { position: relative; width: 350px; height: 400px; display: flex; justify-content: center; align-items: center; } .watch-body { position: relative; width: 300px; height: 300px; background: #000; border-radius: 50%; box-shadow: 0 0 30px rgba(0, 150, 255, 0.25); overflow: hidden; display: flex; flex-direction: column; justify-content: center; align-items: center; border: 2px solid #333; transition: all 0.5s ease; } .watch-body::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: radial-gradient(circle at center, rgba(0, 150, 255, 0.05), transparent 70%); pointer-events: none; } .watch-body::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, transparent 100%); pointer-events: none; } .watch-crown { position: absolute; width: 10px; height: 20px; background: #444; right: -10px; top: 50%; transform: translateY(-50%); border-radius: 0 5px 5px 0; cursor: pointer; z-index: 2; } .watch-crown:hover { background: #666; } .watch-strap-top, .watch-strap-bottom { position: absolute; width: 60px; height: 50px; background: #333; border-radius: 10px; } .watch-strap-top { top: -50px; } .watch-strap-bottom { bottom: -50px; } .clock-face { position: relative; width: 100%; height: 100%; display: flex; flex-direction: column; justify-content: center; align-items: center; color: white; transition: transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); } .time { font-size: 3.5rem; font-weight: 300; letter-spacing: -1px; margin-bottom: 5px; text-shadow: 0 0 10px rgba(0, 150, 255, 0.7); } .date { font-size: 1rem; opacity: 0.7; margin-bottom: 20px; } .complications { display: flex; justify-content: space-between; width: 80%; margin-bottom: 20px; } .complication { display: flex; flex-direction: column; align-items: center; cursor: pointer; transition: transform 0.3s ease, opacity 0.3s ease; opacity: 0.7; } .complication:hover { transform: scale(1.1); opacity: 1; } .complication-icon { font-size: 1.5rem; margin-bottom: 3px; } .complication-value { font-size: 0.8rem; } .activity-ring { position: absolute; width: 260px; height: 260px; border-radius: 50%; border: 2px solid rgba(50, 50, 50, 0.8); pointer-events: none; } .activity-progress { position: absolute; width: 260px; height: 260px; border-radius: 50%; border: 2px solid transparent; border-top-color: #FF3B30; border-right-color: #FF3B30; animation: rotate 2s linear infinite; pointer-events: none; clip-path: polygon(50% 0%, 100% 0%, 100% 100%, 50% 100%); } @keyframes rotate { 0% { transform: rotate(45deg); } 100% { transform: rotate(405deg); } } .detail-view { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: #000; display: flex; flex-direction: column; justify-content: center; align-items: center; transform: translateX(100%); transition: transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); z-index: 1; } .detail-view.active { transform: translateX(0); } .detail-header { position: absolute; top: 30px; font-size: 1.5rem; font-weight: 300; } .back-btn { position: absolute; top: 30px; left: 30px; font-size: 1.2rem; cursor: pointer; opacity: 0.7; transition: opacity 0.3s ease; } .back-btn:hover { opacity: 1; } .detail-content { display: flex; flex-direction: column; align-items: center; width: 80%; } /* Weather Detail View */ .weather-detail .detail-icon { font-size: 3rem; margin-bottom: 10px; color: #0080FF; } .temperature { font-size: 2.5rem; margin-bottom: 5px; } .weather-condition { font-size: 1.2rem; margin-bottom: 15px; opacity: 0.7; } .weather-info { display: flex; justify-content: space-between; width: 100%; margin-top: 15px; } .weather-info-item { display: flex; flex-direction: column; align-items: center; } .weather-info-label { font-size: 0.7rem; opacity: 0.5; margin-bottom: 3px; } .weather-info-value { font-size: 0.9rem; } /* Activity Detail View */ .activity-detail .detail-content { width: 100%; } .activity-stats { display: flex; justify-content: space-around; width: 100%; margin-top: 20px; } .activity-stat { display: flex; flex-direction: column; align-items: center; } .activity-stat-value { font-size: 1.5rem; margin-bottom: 3px; } .activity-stat-label { font-size: 0.7rem; opacity: 0.5; } .activity-chart { width: 80%; height: 80px; margin-top: 20px; display: flex; align-items: flex-end; } .chart-bar { flex: 1; background: linear-gradient(to top, #FF3B30, #FF9500); margin: 0 2px; border-radius: 2px 2px 0 0; transition: height 0.5s ease; } /* Calendar Detail View */ .calendar-detail .calendar-events { width: 100%; margin-top: 10px; } .calendar-event { padding: 10px; border-radius: 8px; background-color: rgba(0, 150, 255, 0.1); margin-bottom: 10px; border-left: 3px solid #0080FF; transition: transform 0.3s ease, background-color 0.3s ease; cursor: pointer; } .calendar-event:hover { transform: translateX(5px); background-color: rgba(0, 150, 255, 0.2); } .event-time { font-size: 0.8rem; opacity: 0.7; margin-bottom: 3px; } .event-title { font-size: 1rem; margin-bottom: 3px; } .event-location { font-size: 0.7rem; opacity: 0.5; } /* Battery Indicator */ .battery-indicator { position: absolute; top: 15px; right: 15px; display: flex; align-items: center; opacity: 0.7; font-size: 0.8rem; } .battery-icon { position: relative; width: 16px; height: 8px; border: 1px solid #fff; border-radius: 2px; margin-right: 5px; } .battery-icon::after { content: ''; position: absolute; right: -3px; top: 2px; width: 2px; height: 4px; background: #fff; border-radius: 0 2px 2px 0; } .battery-level { position: absolute; left: 1px; top: 1px; height: 6px; width: calc(85% * 0.14px); background: #4CD964; border-radius: 1px; } /* Notifications */ .notification { position: absolute; top: 70px; width: 90%; padding: 12px; background: rgba(30, 30, 30, 0.9); border-radius: 10px; transform: translateY(-100px); opacity: 0; transition: transform 0.5s ease, opacity 0.5s ease; z-index: 10; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); } .notification.show { transform: translateY(0); opacity: 1; } .notification-header { display: flex; justify-content: space-between; margin-bottom: 5px; } .notification-app { font-size: 0.8rem; font-weight: bold; } .notification-time { font-size: 0.7rem; opacity: 0.6; } .notification-content { font-size: 0.9rem; } /* Touch Gestures Visual Feedback */ .touch-feedback { position: absolute; width: 50px; height: 50px; border-radius: 50%; background: rgba(255, 255, 255, 0.3); transform: scale(0); opacity: 0; pointer-events: none; } @keyframes touchRipple { 0% { transform: scale(0); opacity: 0.5; } 100% { transform: scale(2); opacity: 0; } } /* Watch Face Themes */ .theme-selector { position: absolute; bottom: 15px; display: flex; justify-content: center; gap: 10px; } .theme-option { width: 15px; height: 15px; border-radius: 50%; cursor: pointer; transition: transform 0.3s ease; } .theme-option:hover { transform: scale(1.2); } .theme-option.active { border: 2px solid white; } .theme-blue { background: #0080FF; } .theme-red { background: #FF3B30; } .theme-green { background: #4CD964; } .theme-purple { background: #AF52DE; } /* Responsive adjustments */ @media (max-width: 400px) { .watch-body { width: 280px; height: 280px; } .time { font-size: 3rem; } .activity-ring, .activity-progress { width: 240px; height: 240px; } } /* Theme Classes */ .theme-blue-active .time { text-shadow: 0 0 10px rgba(0, 128, 255, 0.7); } .theme-red-active .time { text-shadow: 0 0 10px rgba(255, 59, 48, 0.7); } .theme-green-active .time { text-shadow: 0 0 10px rgba(76, 217, 100, 0.7); } .theme-purple-active .time { text-shadow: 0 0 10px rgba(175, 82, 222, 0.7); } .theme-blue-active .activity-progress { border-top-color: #0080FF; border-right-color: #0080FF; } .theme-red-active .activity-progress { border-top-color: #FF3B30; border-right-color: #FF3B30; } .theme-green-active .activity-progress { border-top-color: #4CD964; border-right-color: #4CD964; } .theme-purple-active .activity-progress { border-top-color: #AF52DE; border-right-color: #AF52DE; } </style> </head> <body> <div class="watch-container"> <div class="watch-strap-top"></div> <div class="watch-body theme-blue-active"> <div class="battery-indicator"> <div class="battery-icon"> <div class="battery-level"></div> </div> <span>85%</span> </div> <div class="watch-crown"></div> <div class="clock-face"> <div class="time">10:42</div> <div class="date">Thursday, Jun 15</div> <div class="complications"> <div class="complication" data-type="weather"> <div class="complication-icon">☀️</div> <div class="complication-value">72°</div> </div> <div class="complication" data-type="activity"> <div class="complication-icon">⭕</div> <div class="complication-value">6,240</div> </div> <div class="complication" data-type="calendar"> <div class="complication-icon">📅</div> <div class="complication-value">3 events</div> </div> </div> <div class="activity-ring"></div> <div class="activity-progress"></div> </div> <!-- Weather Detail View --> <div class="detail-view weather-detail"> <div class="back-btn">←</div> <div class="detail-header">Weather</div> <div class="detail-content"> <div class="detail-icon">☀️</div> <div class="temperature">72°F</div> <div class="weather-condition">Sunny</div> <div class="location">Palo Alto</div> <div class="weather-info"> <div class="weather-info-item"> <div class="weather-info-label">WIND</div> <div class="weather-info-value">5 mph</div> </div> <div class="weather-info-item"> <div class="weather-info-label">HUMIDITY</div> <div class="weather-info-value">45%</div> </div> <div class="weather-info-item"> <div class="weather-info-label">UV INDEX</div> <div class="weather-info-value">7</div> </div> </div> </div> </div> <!-- Activity Detail View --> <div class="detail-view activity-detail"> <div class="back-btn">←</div> <div class="detail-header">Activity</div> <div class="detail-content"> <div class="activity-stats"> <div class="activity-stat"> <div class="activity-stat-value">6,240</div> <div class="activity-stat-label">STEPS</div> </div> <div class="activity-stat"> <div class="activity-stat-value">2.8</div> <div class="activity-stat-label">MILES</div> </div> <div class="activity-stat"> <div class="activity-stat-value">247</div> <div class="activity-stat-label">CALORIES</div> </div> </div> <div class="activity-chart"> <div class="chart-bar" style="height: 40%;"></div> <div class="chart-bar" style="height: 60%;"></div> <div class="chart-bar" style="height: 30%;"></div> <div class="chart-bar" style="height: 70%;"></div> <div class="chart-bar" style="height: 50%;"></div> <div class="chart-bar" style="height: 35%;"></div> <div class="chart-bar" style="height: 65%;"></div> </div> </div> </div> <!-- Calendar Detail View --> <div class="detail-view calendar-detail"> <div class="back-btn">←</div> <div class="detail-header">Calendar</div> <div class="detail-content"> <div class="calendar-events"> <div class="calendar-event"> <div class="event-time">11:00 AM - 12:00 PM</div> <div class="event-title">Product Design Review</div> <div class="event-location">Zoom Meeting</div> </div> <div class="calendar-event"> <div class="event-time">2:30 PM - 3:30 PM</div> <div class="event-title">UX Feedback Session</div> <div class="event-location">Conference Room B</div> </div> <div class="calendar-event"> <div class="event-time">5:00 PM - 6:00 PM</div> <div class="event-title">Weekly Team Sync</div> <div class="event-location">Main Office</div> </div> </div> </div> </div> <div class="notification"> <div class="notification-header"> <div class="notification-app">Messages</div> <div class="notification-time">Now</div> </div> <div class="notification-content">Sarah: Are we still meeting for coffee at 3?</div> </div> <div class="touch-feedback"></div> <div class="theme-selector"> <div class="theme-option theme-blue active" data-theme="blue"></div> <div class="theme-option theme-red" data-theme="red"></div> <div class="theme-option theme-green" data-theme="green"></div> <div class="theme-option theme-purple" data-theme="purple"></div> </div> </div> <div class="watch-strap-bottom"></div> </div> <script> document.addEventListener('DOMContentLoaded', () => { // Initialize the watch updateTime(); setInterval(updateTime, 1000); updateBatteryLevel(); // Touch feedback effect const watchBody = document.querySelector('.watch-body'); const touchFeedback = document.querySelector('.touch-feedback'); watchBody.addEventListener('click', (e) => { if (e.target.closest('.detail-view') && !e.target.closest('.back-btn')) return; // Calculate position for touch feedback const rect = watchBody.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; // Position and animate the touch feedback touchFeedback.style.left = `${x - 25}px`; touchFeedback.style.top = `${y - 25}px`; touchFeedback.style.animation = 'none'; // Trigger reflow void touchFeedback.offsetWidth; touchFeedback.style.animation = 'touchRipple 0.6s ease-out forwards'; }); // Complications click handlers const complications = document.querySelectorAll('.complication'); const detailViews = document.querySelectorAll('.detail-view'); const backBtns = document.querySelectorAll('.back-btn'); complications.forEach(complication => { complication.addEventListener('click', () => { const type = complication.getAttribute('data-type'); const detailView = document.querySelector(`.${type}-detail`); if (detailView) { detailView.classList.add('active'); } }); }); backBtns.forEach(btn => { btn.addEventListener('click', () => { const detailView = btn.closest('.detail-view'); detailView.classList.remove('active'); }); }); // Watch crown interaction const watchCrown = document.querySelector('.watch-crown'); watchCrown.addEventListener('click', () => { showNotification(); }); // Theme selector const themeOptions = document.querySelectorAll('.theme-option'); themeOptions.forEach(option => { option.addEventListener('click', () => { const theme = option.getAttribute('data-theme'); // Remove active class from all theme options themeOptions.forEach(opt => opt.classList.remove('active')); // Add active class to clicked theme option option.classList.add('active'); // Update watch theme watchBody.className = 'watch-body'; watchBody.classList.add(`theme-${theme}-active`); }); }); // Simulate chart animation animateChart(); // Simulate activity progress simulateActivityProgress(); }); function updateTime() { const now = new Date(); // Format time let hours = now.getHours(); const minutes = now.getMinutes().toString().padStart(2, '0'); // 12-hour format if (hours > 12) { hours -= 12; } else if (hours === 0) { hours = 12; } const timeElement = document.querySelector('.time'); timeElement.textContent = `${hours}:${minutes}`; // Format date const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; const dayName = days[now.getDay()]; const monthName = months[now.getMonth()]; const date = now.getDate(); const dateElement = document.querySelector('.date'); dateElement.textContent = `${dayName}, ${monthName} ${date}`; } function updateBatteryLevel() { const batteryLevel = document.querySelector('.battery-level'); const batteryValue = 85; // In percentage batteryLevel.style.width = `${batteryValue * 0.14}px`; // Change color based on battery level if (batteryValue <= 20) { batteryLevel.style.background = '#FF3B30'; } else if (batteryValue <= 50) { batteryLevel.style.background = '#FF9500'; } else { batteryLevel.style.background = '#4CD964'; } } function showNotification() { const notification = document.querySelector('.notification'); notification.classList.add('show'); // Hide notification after 3 seconds setTimeout(() => { notification.classList.remove('show'); }, 3000); } function animateChart() { const chartBars = document.querySelectorAll('.chart-bar'); chartBars.forEach((bar, index) => { setTimeout(() => { bar.style.height = `${parseInt(bar.style.height)}%`; }, index * 100); }); } function simulateActivityProgress() { const activityProgress = document.querySelector('.activity-progress'); let rotation = 45; // Starting rotation let direction = 1; // 1 for increasing, -1 for decreasing setInterval(() => { rotation += direction; // Change direction at certain thresholds to create a subtle pulsing effect if (rotation >= 85) { direction = -1; } else if (rotation <= 45) { direction = 1; } activityProgress.style.transform = `rotate(${rotation}deg)`; }, 50); } </script> </body> </html>