{"project":{"id":"XCvIX4Z","userId":"davidyarham@gmail.com","username":null,"userPicture":null,"name":"Focus Timer","visible":true,"contributors":"","githubRepo":null,"forkedFrom":null,"isTemplate":false,"tags":"","files":{"folder":"","files":[{"name":"index.html","content":"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>Untitled</title>\n  <link rel=\"stylesheet\" href=\"style.css\">\n<link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n<link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n<link href=\"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap\" rel=\"stylesheet\">\n<script src=\"https://unpkg.com/lucide@latest\"></script>\n</head>\n<body>\n<div class=\"aurora-container\">\n  <div class=\"aurora-blob aurora-blob--1\"></div>\n  <div class=\"aurora-blob aurora-blob--2\"></div>\n  <div class=\"aurora-blob aurora-blob--3\"></div>\n  <div class=\"content\">\n    <div class=\"card\">\n      <div class=\"card__header\">\n        <h1 class=\"card__title\">Focus Timer</h1>\n        <p class=\"card__subtitle\">Deep work sessions with ambient vibes</p>\n      </div>\n      <div class=\"timer\">\n        <div class=\"timer__display\" id=\"display\">25:00</div>\n        <div class=\"timer__controls\">\n          <button class=\"btn btn--primary\" id=\"startBtn\">\n            <i data-lucide=\"play\"></i>\n            <span>Start</span>\n          </button>\n          <button class=\"btn btn--secondary\" id=\"resetBtn\">\n            <i data-lucide=\"rotate-ccw\"></i>\n            <span>Reset</span>\n          </button>\n        </div>\n      </div>\n      <div class=\"presets\">\n        <button class=\"preset preset--active\" data-time=\"25\">25 min</button>\n        <button class=\"preset\" data-time=\"45\">45 min</button>\n        <button class=\"preset\" data-time=\"60\">60 min</button>\n      </div>\n    </div>\n  </div>\n</div>\n  <script type=\"module\" src=\"main.js\"></script>\n</body>\n</html>"},{"name":"main.js","content":"let timeLeft = 25 * 60;\nlet timerId = null;\nlet isRunning = false;\n\nconst display = document.getElementById('display');\nconst startBtn = document.getElementById('startBtn');\nconst resetBtn = document.getElementById('resetBtn');\nconst presets = document.querySelectorAll('.preset');\n\nfunction updateDisplay() {\n  const minutes = Math.floor(timeLeft / 60);\n  const seconds = timeLeft % 60;\n  display.textContent = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;\n}\n\nfunction startTimer() {\n  if (isRunning) {\n    clearInterval(timerId);\n    isRunning = false;\n    startBtn.innerHTML = '<i data-lucide=\"play\"></i><span>Start</span>';\n    lucide.createIcons();\n    return;\n  }\n\n  isRunning = true;\n  startBtn.innerHTML = '<i data-lucide=\"pause\"></i><span>Pause</span>';\n  lucide.createIcons();\n\n  timerId = setInterval(() => {\n    if (timeLeft > 0) {\n      timeLeft--;\n      updateDisplay();\n    } else {\n      clearInterval(timerId);\n      isRunning = false;\n      startBtn.innerHTML = '<i data-lucide=\"play\"></i><span>Start</span>';\n      lucide.createIcons();\n    }\n  }, 1000);\n}\n\nfunction resetTimer() {\n  clearInterval(timerId);\n  isRunning = false;\n  const activePreset = document.querySelector('.preset--active');\n  timeLeft = parseInt(activePreset.dataset.time) * 60;\n  updateDisplay();\n  startBtn.innerHTML = '<i data-lucide=\"play\"></i><span>Start</span>';\n  lucide.createIcons();\n}\n\nstartBtn.addEventListener('click', startTimer);\nresetBtn.addEventListener('click', resetTimer);\n\npresets.forEach(preset => {\n  preset.addEventListener('click', () => {\n    if (isRunning) return;\n    \n    presets.forEach(p => p.classList.remove('preset--active'));\n    preset.classList.add('preset--active');\n    \n    timeLeft = parseInt(preset.dataset.time) * 60;\n    updateDisplay();\n  });\n});\n\nlucide.createIcons();"},{"name":"style.css","content":":root {\n\tcolor-scheme: dark;\n\tfont-family: 'Inter', system-ui, sans-serif;\n\t--aurora-1: #3b82f6;\n\t--aurora-2: #10b981;\n\t--aurora-3: #06b6d4;\n\t--card-bg: rgba(17, 24, 39, 0.8);\n\t--text-primary: #f9fafb;\n\t--text-secondary: #d1d5db;\n\t--accent: #3b82f6;\n}\n\n* {\n\tbox-sizing: border-box;\n\tmargin: 0;\n\tpadding: 0;\n}\n\nbody {\n\tbackground: #0f172a;\n\tmin-height: 100vh;\n\toverflow: hidden;\n}\n\n.aurora-container {\n\tposition: relative;\n\twidth: 100vw;\n\theight: 100vh;\n\toverflow: hidden;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n}\n\n.aurora-blob {\n\tposition: absolute;\n\tborder-radius: 50%;\n\tfilter: blur(80px);\n\topacity: 0.6;\n\tmix-blend-mode: screen;\n}\n\n.aurora-blob--1 {\n\twidth: 500px;\n\theight: 500px;\n\tbackground: var(--aurora-1);\n\ttop: -10%;\n\tright: 20%;\n\tanimation: float1 20s ease-in-out infinite;\n}\n\n.aurora-blob--2 {\n\twidth: 600px;\n\theight: 600px;\n\tbackground: var(--aurora-2);\n\tbottom: -15%;\n\tleft: 10%;\n\tanimation: float2 25s ease-in-out infinite;\n}\n\n.aurora-blob--3 {\n\twidth: 450px;\n\theight: 450px;\n\tbackground: var(--aurora-3);\n\ttop: 40%;\n\tleft: 50%;\n\tanimation: float3 22s ease-in-out infinite;\n}\n\n@keyframes float1 {\n\t0%, 100% {\n\t\ttransform: translate(0, 0) scale(1);\n\t}\n\n\t33% {\n\t\ttransform: translate(100px, 80px) scale(1.1);\n\t}\n\n\t66% {\n\t\ttransform: translate(-50px, 120px) scale(0.9);\n\t}\n}\n\n@keyframes float2 {\n\t0%, 100% {\n\t\ttransform: translate(0, 0) scale(1);\n\t}\n\n\t33% {\n\t\ttransform: translate(-120px, -60px) scale(1.15);\n\t}\n\n\t66% {\n\t\ttransform: translate(80px, -100px) scale(0.95);\n\t}\n}\n\n@keyframes float3 {\n\t0%, 100% {\n\t\ttransform: translate(0, 0) scale(1);\n\t}\n\n\t50% {\n\t\ttransform: translate(-150px, 100px) scale(1.2);\n\t}\n}\n\n.content {\n\tposition: relative;\n\tz-index: 10;\n}\n\n.card {\n\tbackground: var(--card-bg);\n\tbackdrop-filter: blur(20px);\n\tborder: 1px solid rgba(255, 255, 255, 0.1);\n\tborder-radius: 32px;\n\tpadding: 48px;\n\tbox-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5),\n\t\t0 0 0 1px rgba(255, 255, 255, 0.05) inset,\n\t\t0 0 60px rgba(59, 130, 246, 0.15);\n\tmin-width: 420px;\n\tposition: relative;\n\toverflow: hidden;\n}\n\n.card::before {\n\tcontent: '';\n\tposition: absolute;\n\ttop: 0;\n\tleft: -100%;\n\twidth: 100%;\n\theight: 100%;\n\tbackground: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);\n\tanimation: shimmer 3s infinite;\n}\n\n@keyframes shimmer {\n\t0% {\n\t\tleft: -100%;\n\t}\n\n\t100% {\n\t\tleft: 100%;\n\t}\n}\n\n.card__header {\n\ttext-align: center;\n\tmargin-bottom: 48px;\n}\n\n.card__title {\n\tfont-size: 48px;\n\tfont-weight: 700;\n\tbackground: linear-gradient(135deg, #ffffff 0%, #3b82f6 100%);\n\t-webkit-background-clip: text;\n\t-webkit-text-fill-color: transparent;\n\tbackground-clip: text;\n\tmargin-bottom: 8px;\n\tletter-spacing: -0.02em;\n\tanimation: gradientShift 4s ease infinite;\n}\n\n@keyframes gradientShift {\n\t0%, 100% {\n\t\tbackground-position: 0% 50%;\n\t}\n\n\t50% {\n\t\tbackground-position: 100% 50%;\n\t}\n}\n\n.card__subtitle {\n\tfont-size: 16px;\n\tcolor: var(--text-secondary);\n\tfont-weight: 400;\n}\n\n.timer {\n\tmargin-bottom: 32px;\n}\n\n.timer__display {\n\tfont-size: 96px;\n\tfont-weight: 700;\n\tcolor: var(--text-primary);\n\ttext-align: center;\n\tmargin-bottom: 32px;\n\tletter-spacing: -0.03em;\n\tfont-variant-numeric: tabular-nums;\n\ttext-shadow: 0 0 40px rgba(59, 130, 246, 0.5),\n\t\t0 0 80px rgba(59, 130, 246, 0.3);\n\tposition: relative;\n}\n\n.timer__display::after {\n\tcontent: attr(data-time);\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbackground: linear-gradient(180deg, rgba(59, 130, 246, 0.8), rgba(16, 185, 129, 0.8));\n\t-webkit-background-clip: text;\n\t-webkit-text-fill-color: transparent;\n\tbackground-clip: text;\n\topacity: 0.3;\n\tfilter: blur(20px);\n}\n\n.timer__controls {\n\tdisplay: flex;\n\tgap: 16px;\n\tjustify-content: center;\n}\n\n.btn {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 16px 32px;\n\tborder: none;\n\tborder-radius: 16px;\n\tfont-size: 16px;\n\tfont-weight: 600;\n\tcursor: pointer;\n\ttransition: all 0.2s;\n\tfont-family: inherit;\n}\n\n.btn--primary {\n\tbackground: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);\n\tcolor: white;\n\tposition: relative;\n\toverflow: hidden;\n}\n\n.btn--primary::before {\n\tcontent: '';\n\tposition: absolute;\n\ttop: 50%;\n\tleft: 50%;\n\twidth: 0;\n\theight: 0;\n\tborder-radius: 50%;\n\tbackground: rgba(255, 255, 255, 0.3);\n\ttransform: translate(-50%, -50%);\n\ttransition: width 0.6s, height 0.6s;\n}\n\n.btn--primary:active::before {\n\twidth: 300px;\n\theight: 300px;\n}\n\n.btn--primary:hover {\n\tbackground: #2563eb;\n\ttransform: translateY(-2px);\n\tbox-shadow: 0 12px 24px -8px rgba(59, 130, 246, 0.5);\n}\n\n.btn--secondary {\n\tbackground: rgba(255, 255, 255, 0.1);\n\tcolor: var(--text-primary);\n}\n\n.btn--secondary:hover {\n\tbackground: rgba(255, 255, 255, 0.15);\n\ttransform: translateY(-2px);\n}\n\n.btn i {\n\twidth: 20px;\n\theight: 20px;\n}\n\n.presets {\n\tdisplay: flex;\n\tgap: 12px;\n\tjustify-content: center;\n}\n\n.preset {\n\tpadding: 12px 24px;\n\tbackground: rgba(255, 255, 255, 0.05);\n\tborder: 1px solid rgba(255, 255, 255, 0.1);\n\tborder-radius: 12px;\n\tcolor: var(--text-secondary);\n\tfont-size: 14px;\n\tfont-weight: 500;\n\tcursor: pointer;\n\ttransition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n\tfont-family: inherit;\n\tposition: relative;\n\toverflow: hidden;\n}\n\n.preset::before {\n\tcontent: '';\n\tposition: absolute;\n\ttop: 0;\n\tleft: -100%;\n\twidth: 100%;\n\theight: 100%;\n\tbackground: linear-gradient(90deg, transparent, rgba(59, 130, 246, 0.2), transparent);\n\ttransition: left 0.5s;\n}\n\n.preset:hover::before {\n\tleft: 100%;\n}\n\n.preset:hover {\n\tbackground: rgba(255, 255, 255, 0.1);\n\tborder-color: rgba(255, 255, 255, 0.2);\n}\n\n.preset--active {\n\tbackground: linear-gradient(135deg, rgba(59, 130, 246, 0.3), rgba(16, 185, 129, 0.2));\n\tborder-color: var(--accent);\n\tcolor: var(--text-primary);\n\tbox-shadow: 0 0 20px rgba(59, 130, 246, 0.3);\n\ttransform: scale(1.05);\n}"}],"folders":[]},"variants":null,"createdAt":"2026-02-04T20:03:44.807Z","updatedAt":"2026-03-04T16:30:36.069Z","hasThumbnail":true}}