{"project":{"id":"iEsRkij","userId":"davidyarham@gmail.com","username":null,"userPicture":null,"name":"Pop frenzy","thumbnail":"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","visible":true,"contributors":"","githubRepo":null,"forkedFrom":null,"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<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\">\n</head>\n<body>\n<div class=\"game\">\n\t<canvas id=\"gameCanvas\" class=\"game__canvas\"></canvas>\n\t<div class=\"game__hud\">\n\t\t<div class=\"game__score-wrap\">\n\t\t\t<span class=\"game__label\">SCORE</span>\n\t\t\t<span class=\"game__score\" id=\"score\">0</span>\n\t\t</div>\n\t\t<div class=\"game__combo-wrap\">\n\t\t\t<span class=\"game__label\">COMBO</span>\n\t\t\t<span class=\"game__combo\" id=\"combo\">x1</span>\n\t\t</div>\n\t\t<div class=\"game__lives-wrap\">\n\t\t\t<span class=\"game__label\">LIVES</span>\n\t\t\t<span class=\"game__lives\" id=\"lives\">♥♥♥</span>\n\t\t</div>\n\t</div>\n\t<div class=\"game__overlay\" id=\"startScreen\">\n\t\t<div class=\"game__overlay-content\">\n\t\t\t<h1 class=\"game__title\">POP<span class=\"game__title--accent\">FRENZY</span></h1>\n\t\t\t<p class=\"game__subtitle\">Tap the orbs before they escape!</p>\n\t\t\t<p class=\"game__hint\">Chain combos for massive points<br>Miss 3 and it's game over</p>\n\t\t\t<button class=\"game__btn\" id=\"startBtn\">TAP TO PLAY</button>\n\t\t</div>\n\t</div>\n\t<div class=\"game__overlay game__overlay--hidden\" id=\"gameOverScreen\">\n\t\t<div class=\"game__overlay-content\">\n\t\t\t<h1 class=\"game__title game__title--small\">GAME OVER</h1>\n\t\t\t<p class=\"game__final-score\">Score: <span id=\"finalScore\">0</span></p>\n\t\t\t<p class=\"game__best-score\">Best: <span id=\"bestScore\">0</span></p>\n\t\t\t<button class=\"game__btn\" id=\"restartBtn\">PLAY AGAIN</button>\n\t\t</div>\n\t</div>\n</div>\n  <script type=\"module\" src=\"main.js\"></script>\n</body>\n</html>"},{"name":"main.js","content":"(function() {\n\t'use strict';\n\n\tconst canvas = document.getElementById('gameCanvas');\n\tconst ctx = canvas.getContext('2d');\n\tconst scoreEl = document.getElementById('score');\n\tconst comboEl = document.getElementById('combo');\n\tconst livesEl = document.getElementById('lives');\n\tconst startScreen = document.getElementById('startScreen');\n\tconst gameOverScreen = document.getElementById('gameOverScreen');\n\tconst finalScoreEl = document.getElementById('finalScore');\n\tconst bestScoreEl = document.getElementById('bestScore');\n\tconst startBtn = document.getElementById('startBtn');\n\tconst restartBtn = document.getElementById('restartBtn');\n\n\tlet W, H, dpr;\n\tlet audioCtx;\n\n\tfunction initAudio() {\n\t\tif (!audioCtx) {\n\t\t\taudioCtx = new(window.AudioContext || window.webkitAudioContext)();\n\t\t}\n\t\tif (audioCtx.state === 'suspended') audioCtx.resume();\n\t}\n\n\tfunction playPop(comboLevel) {\n\t\tif (!audioCtx) return;\n\t\tconst baseFreq = 400 + Math.min(comboLevel, 10) * 60;\n\t\tconst osc = audioCtx.createOscillator();\n\t\tconst gain = audioCtx.createGain();\n\t\tosc.connect(gain);\n\t\tgain.connect(audioCtx.destination);\n\t\tosc.type = 'sine';\n\t\tosc.frequency.setValueAtTime(baseFreq, audioCtx.currentTime);\n\t\tosc.frequency.exponentialRampToValueAtTime(baseFreq * 2.5, audioCtx.currentTime + 0.08);\n\t\tgain.gain.setValueAtTime(0.25, audioCtx.currentTime);\n\t\tgain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + 0.15);\n\t\tosc.start(audioCtx.currentTime);\n\t\tosc.stop(audioCtx.currentTime + 0.15);\n\t}\n\n\tfunction playCombo(level) {\n\t\tif (!audioCtx || level < 3) return;\n\t\tconst t = audioCtx.currentTime;\n\t\tconst osc = audioCtx.createOscillator();\n\t\tconst gain = audioCtx.createGain();\n\t\tosc.connect(gain);\n\t\tgain.connect(audioCtx.destination);\n\t\tosc.type = 'triangle';\n\t\tconst freq = 600 + level * 80;\n\t\tosc.frequency.setValueAtTime(freq, t);\n\t\tosc.frequency.exponentialRampToValueAtTime(freq * 1.5, t + 0.1);\n\t\tgain.gain.setValueAtTime(0.15, t);\n\t\tgain.gain.exponentialRampToValueAtTime(0.001, t + 0.2);\n\t\tosc.start(t);\n\t\tosc.stop(t + 0.2);\n\t}\n\n\tfunction playMiss() {\n\t\tif (!audioCtx) return;\n\t\tconst t = audioCtx.currentTime;\n\t\tconst osc = audioCtx.createOscillator();\n\t\tconst gain = audioCtx.createGain();\n\t\tosc.connect(gain);\n\t\tgain.connect(audioCtx.destination);\n\t\tosc.type = 'square';\n\t\tosc.frequency.setValueAtTime(200, t);\n\t\tosc.frequency.exponentialRampToValueAtTime(80, t + 0.25);\n\t\tgain.gain.setValueAtTime(0.15, t);\n\t\tgain.gain.exponentialRampToValueAtTime(0.001, t + 0.3);\n\t\tosc.start(t);\n\t\tosc.stop(t + 0.3);\n\t}\n\n\tfunction playGameOver() {\n\t\tif (!audioCtx) return;\n\t\tconst t = audioCtx.currentTime;\n\t\tconst notes = [400, 350, 300, 200];\n\t\tnotes.forEach((freq, i) => {\n\t\t\tconst osc = audioCtx.createOscillator();\n\t\t\tconst gain = audioCtx.createGain();\n\t\t\tosc.connect(gain);\n\t\t\tgain.connect(audioCtx.destination);\n\t\t\tosc.type = 'sawtooth';\n\t\t\tosc.frequency.setValueAtTime(freq, t + i * 0.18);\n\t\t\tgain.gain.setValueAtTime(0.12, t + i * 0.18);\n\t\t\tgain.gain.exponentialRampToValueAtTime(0.001, t + i * 0.18 + 0.3);\n\t\t\tosc.start(t + i * 0.18);\n\t\t\tosc.stop(t + i * 0.18 + 0.3);\n\t\t});\n\t}\n\n\tfunction playSpecialPop() {\n\t\tif (!audioCtx) return;\n\t\tconst t = audioCtx.currentTime;\n\t\t[800, 1000, 1200].forEach((freq, i) => {\n\t\t\tconst osc = audioCtx.createOscillator();\n\t\t\tconst gain = audioCtx.createGain();\n\t\t\tosc.connect(gain);\n\t\t\tgain.connect(audioCtx.destination);\n\t\t\tosc.type = 'sine';\n\t\t\tosc.frequency.setValueAtTime(freq, t + i * 0.06);\n\t\t\tosc.frequency.exponentialRampToValueAtTime(freq * 2, t + i * 0.06 + 0.12);\n\t\t\tgain.gain.setValueAtTime(0.18, t + i * 0.06);\n\t\t\tgain.gain.exponentialRampToValueAtTime(0.001, t + i * 0.06 + 0.18);\n\t\t\tosc.start(t + i * 0.06);\n\t\t\tosc.stop(t + i * 0.06 + 0.18);\n\t\t});\n\t}\n\tlet orbs = [];\n\tlet particles = [];\n\tlet floatingTexts = [];\n\tlet score = 0;\n\tlet combo = 0;\n\tlet comboTimer = 0;\n\tlet lives = 3;\n\tlet gameRunning = false;\n\tlet spawnTimer = 0;\n\tlet spawnInterval = 1.2;\n\tlet difficulty = 1;\n\tlet elapsed = 0;\n\tlet lastTime = 0;\n\tlet bestScore = parseInt(localStorage.getItem('popfrenzy_best') || '0');\n\tlet bgStars = [];\n\tlet shakeAmount = 0;\n\n\tconst ORB_COLORS = [{\n\t\t\tfill: '#ff2d78',\n\t\t\tglow: 'rgba(255,45,120,0.4)',\n\t\t\tpoints: 10\n\t\t},\n\t\t{\n\t\t\tfill: '#00e5ff',\n\t\t\tglow: 'rgba(0,229,255,0.4)',\n\t\t\tpoints: 10\n\t\t},\n\t\t{\n\t\t\tfill: '#39ff14',\n\t\t\tglow: 'rgba(57,255,20,0.4)',\n\t\t\tpoints: 10\n\t\t},\n\t\t{\n\t\t\tfill: '#ffe135',\n\t\t\tglow: 'rgba(255,225,53,0.4)',\n\t\t\tpoints: 10\n\t\t},\n\t\t{\n\t\t\tfill: '#ff6f00',\n\t\t\tglow: 'rgba(255,111,0,0.4)',\n\t\t\tpoints: 15\n\t\t},\n\t\t{\n\t\t\tfill: '#e040fb',\n\t\t\tglow: 'rgba(224,64,251,0.4)',\n\t\t\tpoints: 15\n\t\t},\n\t];\n\n\tconst SPECIAL_ORB = {\n\t\tfill: '#ffffff',\n\t\tglow: 'rgba(255,255,255,0.6)',\n\t\tpoints: 50\n\t};\n\n\tfunction resize() {\n\t\tdpr = Math.min(window.devicePixelRatio || 1, 2);\n\t\tW = window.innerWidth;\n\t\tH = window.innerHeight;\n\t\tcanvas.width = W * dpr;\n\t\tcanvas.height = H * dpr;\n\t\tcanvas.style.width = W + 'px';\n\t\tcanvas.style.height = H + 'px';\n\t\tctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n\t\tinitStars();\n\t}\n\n\tfunction initStars() {\n\t\tbgStars = [];\n\t\tfor (let i = 0; i < 60; i++) {\n\t\t\tbgStars.push({\n\t\t\t\tx: Math.random() * W,\n\t\t\t\ty: Math.random() * H,\n\t\t\t\tr: Math.random() * 1.5 + 0.5,\n\t\t\t\talpha: Math.random() * 0.5 + 0.2,\n\t\t\t\tspeed: Math.random() * 0.3 + 0.1\n\t\t\t});\n\t\t}\n\t}\n\n\tclass Orb {\n\t\tconstructor() {\n\t\t\tconst isSpecial = Math.random() < 0.08;\n\t\t\tconst colorData = isSpecial ? SPECIAL_ORB : ORB_COLORS[Math.floor(Math.random() * ORB_COLORS.length)];\n\t\t\tthis.color = colorData.fill;\n\t\t\tthis.glow = colorData.glow;\n\t\t\tthis.points = colorData.points;\n\t\t\tthis.isSpecial = isSpecial;\n\n\t\t\tconst baseR = Math.random() * 12 + 22;\n\t\t\tthis.r = baseR;\n\t\t\tthis.maxR = baseR;\n\t\t\tthis.x = Math.random() * (W - baseR * 2) + baseR;\n\t\t\tthis.y = H + baseR + 20;\n\n\t\t\tconst speed = (Math.random() * 40 + 50) * (0.8 + difficulty * 0.15);\n\t\t\tthis.vy = -speed;\n\t\t\tthis.vx = (Math.random() - 0.5) * 30;\n\n\t\t\tthis.lifespan = (H + 200) / speed + Math.random() * 0.8;\n\t\t\tthis.age = 0;\n\t\t\tthis.alive = true;\n\t\t\tthis.popped = false;\n\t\t\tthis.wobble = Math.random() * Math.PI * 2;\n\t\t\tthis.wobbleSpeed = Math.random() * 3 + 2;\n\t\t\tthis.wobbleAmp = Math.random() * 8 + 4;\n\t\t\tthis.pulsePhase = Math.random() * Math.PI * 2;\n\t\t\tthis.scaleIn = 0;\n\t\t}\n\n\t\tupdate(dt) {\n\t\t\tthis.age += dt;\n\t\t\tthis.scaleIn = Math.min(1, this.age / 0.15);\n\t\t\tthis.y += this.vy * dt;\n\t\t\tthis.wobble += this.wobbleSpeed * dt;\n\t\t\tthis.x += Math.sin(this.wobble) * this.wobbleAmp * dt;\n\t\t\tthis.pulsePhase += dt * 4;\n\n\t\t\tif (this.x < this.r) this.x = this.r;\n\t\t\tif (this.x > W - this.r) this.x = W - this.r;\n\n\t\t\tif (this.y < -this.r - 40) {\n\t\t\t\tthis.alive = false;\n\t\t\t\tif (!this.popped) {\n\t\t\t\t\tloseLife();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tdraw() {\n\t\t\tconst scale = this.scaleIn;\n\t\t\tconst pulse = 1 + Math.sin(this.pulsePhase) * 0.06;\n\t\t\tconst r = this.r * scale * pulse;\n\n\t\t\tctx.save();\n\t\t\tctx.translate(this.x, this.y);\n\n\t\t\t// Glow\n\t\t\tconst glowSize = r * (this.isSpecial ? 3 : 2.2);\n\t\t\tconst glowGrad = ctx.createRadialGradient(0, 0, r * 0.3, 0, 0, glowSize);\n\t\t\tglowGrad.addColorStop(0, this.glow);\n\t\t\tglowGrad.addColorStop(1, 'transparent');\n\t\t\tctx.fillStyle = glowGrad;\n\t\t\tctx.beginPath();\n\t\t\tctx.arc(0, 0, glowSize, 0, Math.PI * 2);\n\t\t\tctx.fill();\n\n\t\t\t// Body\n\t\t\tconst bodyGrad = ctx.createRadialGradient(-r * 0.3, -r * 0.3, r * 0.1, 0, 0, r);\n\t\t\tbodyGrad.addColorStop(0, '#ffffff');\n\t\t\tbodyGrad.addColorStop(0.3, this.color);\n\t\t\tbodyGrad.addColorStop(1, this.darken(this.color, 0.4));\n\t\t\tctx.fillStyle = bodyGrad;\n\t\t\tctx.beginPath();\n\t\t\tctx.arc(0, 0, r, 0, Math.PI * 2);\n\t\t\tctx.fill();\n\n\t\t\t// Highlight\n\t\t\tctx.fillStyle = 'rgba(255,255,255,0.35)';\n\t\t\tctx.beginPath();\n\t\t\tctx.ellipse(-r * 0.2, -r * 0.3, r * 0.35, r * 0.2, -0.5, 0, Math.PI * 2);\n\t\t\tctx.fill();\n\n\t\t\tif (this.isSpecial) {\n\t\t\t\tctx.strokeStyle = 'rgba(255,255,255,0.5)';\n\t\t\t\tctx.lineWidth = 2;\n\t\t\t\tctx.beginPath();\n\t\t\t\tconst sparkAngle = this.pulsePhase * 2;\n\t\t\t\tfor (let i = 0; i < 4; i++) {\n\t\t\t\t\tconst a = sparkAngle + (Math.PI / 2) * i;\n\t\t\t\t\tctx.moveTo(Math.cos(a) * (r + 4), Math.sin(a) * (r + 4));\n\t\t\t\t\tctx.lineTo(Math.cos(a) * (r + 10), Math.sin(a) * (r + 10));\n\t\t\t\t}\n\t\t\t\tctx.stroke();\n\t\t\t}\n\n\t\t\tctx.restore();\n\t\t}\n\n\t\tdarken(hex, amount) {\n\t\t\tconst num = parseInt(hex.slice(1), 16);\n\t\t\tconst r = Math.max(0, ((num >> 16) & 0xff) * (1 - amount)) | 0;\n\t\t\tconst g = Math.max(0, ((num >> 8) & 0xff) * (1 - amount)) | 0;\n\t\t\tconst b = Math.max(0, (num & 0xff) * (1 - amount)) | 0;\n\t\t\treturn `rgb(${r},${g},${b})`;\n\t\t}\n\n\t\thitTest(px, py) {\n\t\t\tconst dx = px - this.x;\n\t\t\tconst dy = py - this.y;\n\t\t\tconst touchR = this.r * 1.3; // generous touch area\n\t\t\treturn dx * dx + dy * dy <= touchR * touchR;\n\t\t}\n\t}\n\n\tclass Particle {\n\t\tconstructor(x, y, color) {\n\t\t\tthis.x = x;\n\t\t\tthis.y = y;\n\t\t\tthis.color = color;\n\t\t\tconst angle = Math.random() * Math.PI * 2;\n\t\t\tconst speed = Math.random() * 250 + 80;\n\t\t\tthis.vx = Math.cos(angle) * speed;\n\t\t\tthis.vy = Math.sin(angle) * speed;\n\t\t\tthis.r = Math.random() * 4 + 2;\n\t\t\tthis.life = 1;\n\t\t\tthis.decay = Math.random() * 1.5 + 1.5;\n\t\t\tthis.gravity = 200;\n\t\t}\n\n\t\tupdate(dt) {\n\t\t\tthis.x += this.vx * dt;\n\t\t\tthis.y += this.vy * dt;\n\t\t\tthis.vy += this.gravity * dt;\n\t\t\tthis.vx *= 0.98;\n\t\t\tthis.life -= this.decay * dt;\n\t\t}\n\n\t\tdraw() {\n\t\t\tif (this.life <= 0) return;\n\t\t\tctx.globalAlpha = this.life;\n\t\t\tctx.fillStyle = this.color;\n\t\t\tctx.beginPath();\n\t\t\tctx.arc(this.x, this.y, this.r * this.life, 0, Math.PI * 2);\n\t\t\tctx.fill();\n\t\t\tctx.globalAlpha = 1;\n\t\t}\n\t}\n\n\tclass FloatingText {\n\t\tconstructor(x, y, text, color) {\n\t\t\tthis.x = x;\n\t\t\tthis.y = y;\n\t\t\tthis.text = text;\n\t\t\tthis.color = color;\n\t\t\tthis.life = 1;\n\t\t\tthis.vy = -80;\n\t\t}\n\n\t\tupdate(dt) {\n\t\t\tthis.y += this.vy * dt;\n\t\t\tthis.life -= dt * 1.2;\n\t\t}\n\n\t\tdraw() {\n\t\t\tif (this.life <= 0) return;\n\t\t\tctx.globalAlpha = this.life;\n\t\t\tctx.fillStyle = this.color;\n\t\t\tctx.font = `bold ${18 + (1 - this.life) * 8}px 'Lilita One', cursive`;\n\t\t\tctx.textAlign = 'center';\n\t\t\tctx.fillText(this.text, this.x, this.y);\n\t\t\tctx.globalAlpha = 1;\n\t\t}\n\t}\n\n\tfunction spawnOrb() {\n\t\torbs.push(new Orb());\n\t}\n\n\tfunction popOrb(orb, index) {\n\t\torb.popped = true;\n\t\torb.alive = false;\n\n\t\tcombo++;\n\t\tcomboTimer = 1.5;\n\n\t\tconst multiplier = Math.min(combo, 10);\n\t\tconst pts = orb.points * multiplier;\n\t\tscore += pts;\n\n\t\t// Sound\n\t\tif (orb.isSpecial) {\n\t\t\tplaySpecialPop();\n\t\t} else {\n\t\t\tplayPop(combo);\n\t\t}\n\t\tplayCombo(combo);\n\n\t\tscoreEl.textContent = score;\n\t\tcomboEl.textContent = 'x' + multiplier;\n\t\tcomboEl.classList.add('game__combo--pulse');\n\t\tsetTimeout(() => comboEl.classList.remove('game__combo--pulse'), 100);\n\n\t\t// Particles\n\t\tconst count = orb.isSpecial ? 25 : 14;\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tparticles.push(new Particle(orb.x, orb.y, orb.color));\n\t\t}\n\n\t\t// Floating text\n\t\tconst label = (multiplier > 1 ? `+${pts} x${multiplier}` : `+${pts}`);\n\t\tfloatingTexts.push(new FloatingText(orb.x, orb.y - 20, label, orb.color));\n\n\t\tshakeAmount = Math.min(8, combo * 1.5);\n\t}\n\n\tfunction loseLife() {\n\t\tlives--;\n\t\tcombo = 0;\n\t\tcomboEl.textContent = 'x1';\n\t\tplayMiss();\n\t\tlivesEl.textContent = '♥'.repeat(Math.max(0, lives)) + '♡'.repeat(Math.max(0, 3 - lives));\n\t\tshakeAmount = 10;\n\n\t\tif (lives <= 0) {\n\t\t\tgameOver();\n\t\t}\n\t}\n\n\tfunction gameOver() {\n\t\tgameRunning = false;\n\t\tplayGameOver();\n\t\tfinalScoreEl.textContent = score;\n\t\tif (score > bestScore) {\n\t\t\tbestScore = score;\n\t\t\tlocalStorage.setItem('popfrenzy_best', bestScore.toString());\n\t\t}\n\t\tbestScoreEl.textContent = bestScore;\n\t\tgameOverScreen.classList.remove('game__overlay--hidden');\n\t}\n\n\tfunction startGame() {\n\t\tscore = 0;\n\t\tcombo = 0;\n\t\tlives = 3;\n\t\tdifficulty = 1;\n\t\telapsed = 0;\n\t\tspawnInterval = 1.2;\n\t\tspawnTimer = 0;\n\t\torbs = [];\n\t\tparticles = [];\n\t\tfloatingTexts = [];\n\n\t\tscoreEl.textContent = '0';\n\t\tcomboEl.textContent = 'x1';\n\t\tlivesEl.textContent = '♥♥♥';\n\n\t\tstartScreen.classList.add('game__overlay--hidden');\n\t\tgameOverScreen.classList.add('game__overlay--hidden');\n\n\t\tinitAudio();\n\t\tgameRunning = true;\n\t\tlastTime = performance.now();\n\t\trequestAnimationFrame(loop);\n\t}\n\n\tfunction handleTap(px, py) {\n\t\tif (!gameRunning) return;\n\n\t\tlet hitAny = false;\n\t\t// Check from top (newest/closest) to bottom\n\t\tfor (let i = orbs.length - 1; i >= 0; i--) {\n\t\t\tconst orb = orbs[i];\n\t\t\tif (!orb.alive || orb.popped) continue;\n\t\t\tif (orb.hitTest(px, py)) {\n\t\t\t\tpopOrb(orb, i);\n\t\t\t\thitAny = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (!hitAny) {\n\t\t\tcombo = 0;\n\t\t\tcomboEl.textContent = 'x1';\n\t\t}\n\t}\n\n\tfunction drawBackground(dt) {\n\t\tfor (const star of bgStars) {\n\t\t\tstar.y -= star.speed * 20 * dt;\n\t\t\tif (star.y < -5) {\n\t\t\t\tstar.y = H + 5;\n\t\t\t\tstar.x = Math.random() * W;\n\t\t\t}\n\t\t\tctx.globalAlpha = star.alpha * (0.5 + 0.5 * Math.sin(elapsed * star.speed * 5));\n\t\t\tctx.fillStyle = '#ffffff';\n\t\t\tctx.beginPath();\n\t\t\tctx.arc(star.x, star.y, star.r, 0, Math.PI * 2);\n\t\t\tctx.fill();\n\t\t}\n\t\tctx.globalAlpha = 1;\n\t}\n\n\tfunction loop(now) {\n\t\tif (!gameRunning) return;\n\n\t\tconst dt = Math.min((now - lastTime) / 1000, 0.05);\n\t\tlastTime = now;\n\t\telapsed += dt;\n\n\t\t// Difficulty ramp\n\t\tdifficulty = 1 + elapsed / 30;\n\t\tspawnInterval = Math.max(0.3, 1.2 - elapsed * 0.008);\n\n\t\t// Spawn\n\t\tspawnTimer += dt;\n\t\tif (spawnTimer >= spawnInterval) {\n\t\t\tspawnTimer -= spawnInterval;\n\t\t\tspawnOrb();\n\t\t\t// Double spawn after 45s\n\t\t\tif (elapsed > 45 && Math.random() < 0.4) spawnOrb();\n\t\t}\n\n\t\t// Combo timer\n\t\tif (comboTimer > 0) {\n\t\t\tcomboTimer -= dt;\n\t\t\tif (comboTimer <= 0) {\n\t\t\t\tcombo = 0;\n\t\t\t\tcomboEl.textContent = 'x1';\n\t\t\t}\n\t\t}\n\n\t\t// Shake decay\n\t\tshakeAmount *= Math.pow(0.05, dt);\n\n\t\t// Update\n\t\tfor (const orb of orbs) orb.update(dt);\n\t\tfor (const p of particles) p.update(dt);\n\t\tfor (const ft of floatingTexts) ft.update(dt);\n\n\t\t// Cleanup\n\t\torbs = orbs.filter(o => o.alive);\n\t\tparticles = particles.filter(p => p.life > 0);\n\t\tfloatingTexts = floatingTexts.filter(ft => ft.life > 0);\n\n\t\t// Draw\n\t\tctx.clearRect(0, 0, W, H);\n\n\t\tctx.save();\n\t\tif (shakeAmount > 0.5) {\n\t\t\tctx.translate(\n\t\t\t\t(Math.random() - 0.5) * shakeAmount,\n\t\t\t\t(Math.random() - 0.5) * shakeAmount\n\t\t\t);\n\t\t}\n\n\t\tdrawBackground(dt);\n\n\t\tfor (const orb of orbs) orb.draw();\n\t\tfor (const p of particles) p.draw();\n\t\tfor (const ft of floatingTexts) ft.draw();\n\n\t\tctx.restore();\n\n\t\trequestAnimationFrame(loop);\n\t}\n\n\t// Events\n\tcanvas.addEventListener('pointerdown', (e) => {\n\t\te.preventDefault();\n\t\tconst rect = canvas.getBoundingClientRect();\n\t\tconst px = e.clientX - rect.left;\n\t\tconst py = e.clientY - rect.top;\n\t\thandleTap(px, py);\n\t});\n\n\t// Support multi-touch for frantic tapping\n\tcanvas.addEventListener('touchstart', (e) => {\n\t\te.preventDefault();\n\t\tconst rect = canvas.getBoundingClientRect();\n\t\tfor (const touch of e.changedTouches) {\n\t\t\tconst px = touch.clientX - rect.left;\n\t\t\tconst py = touch.clientY - rect.top;\n\t\t\thandleTap(px, py);\n\t\t}\n\t}, {\n\t\tpassive: false\n\t});\n\n\tstartBtn.addEventListener('click', startGame);\n\trestartBtn.addEventListener('click', startGame);\n\twindow.addEventListener('resize', resize);\n\n\tresize();\n\n\t// Ambient animation on start screen\n\tfunction ambientLoop(now) {\n\t\tif (gameRunning) return;\n\t\tconst dt = lastTime ? Math.min((now - lastTime) / 1000, 0.05) : 0.016;\n\t\tlastTime = now;\n\t\telapsed += dt;\n\n\t\tctx.clearRect(0, 0, W, H);\n\t\tdrawBackground(dt);\n\n\t\trequestAnimationFrame(ambientLoop);\n\t}\n\tlastTime = performance.now();\n\trequestAnimationFrame(ambientLoop);\n})();"},{"name":"style.css","content":"@import url('https://fonts.googleapis.com/css2?family=Lilita+One&family=Nunito:wght@700;900&display=swap');\n\n:root {\n\t--bg-primary: #1b0a2e;\n\t--bg-secondary: #2d1250;\n\t--accent-pink: #ff2d78;\n\t--accent-cyan: #00e5ff;\n\t--accent-yellow: #ffe135;\n\t--accent-green: #39ff14;\n\t--text-primary: #ffffff;\n\t--text-muted: rgba(255, 255, 255, 0.6);\n\tcolor-scheme: dark;\n}\n\n* {\n\tbox-sizing: border-box;\n\tmargin: 0;\n\tpadding: 0;\n\t-webkit-tap-highlight-color: transparent;\n\tuser-select: none;\n}\n\nhtml, body {\n\theight: 100%;\n\toverflow: hidden;\n\ttouch-action: none;\n}\n\nbody {\n\tfont-family: 'Nunito', sans-serif;\n\tbackground: var(--bg-primary);\n}\n\n.game {\n\tposition: relative;\n\twidth: 100%;\n\theight: 100dvh;\n\toverflow: hidden;\n\tbackground: radial-gradient(ellipse at 50% 80%, var(--bg-secondary) 0%, var(--bg-primary) 70%);\n}\n\n.game__canvas {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\theight: 100%;\n\tz-index: 1;\n}\n\n.game__hud {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tz-index: 10;\n\tdisplay: flex;\n\tjustify: space-between;\n\talign-items: flex-start;\n\tpadding: 12px 16px;\n\tpadding-top: max(12px, env(safe-area-inset-top));\n\tbackground: linear-gradient(to bottom, rgba(0, 0, 0, 0.5) 0%, transparent 100%);\n\tpointer-events: none;\n}\n\n.game__label {\n\tdisplay: block;\n\tfont-size: 9px;\n\tfont-weight: 700;\n\tletter-spacing: 2px;\n\tcolor: var(--text-muted);\n\ttext-transform: uppercase;\n}\n\n.game__score {\n\tfont-family: 'Lilita One', cursive;\n\tfont-size: 32px;\n\tcolor: var(--text-primary);\n\tline-height: 1;\n\ttext-shadow: 0 0 20px rgba(255, 45, 120, 0.5);\n}\n\n.game__combo {\n\tfont-family: 'Lilita One', cursive;\n\tfont-size: 24px;\n\tcolor: var(--accent-yellow);\n\tline-height: 1;\n\ttext-shadow: 0 0 15px rgba(255, 225, 53, 0.5);\n\ttransition: transform 0.1s;\n}\n\n.game__combo--pulse {\n\ttransform: scale(1.4);\n}\n\n.game__lives {\n\tfont-size: 20px;\n\tcolor: var(--accent-pink);\n\tline-height: 1;\n\ttext-shadow: 0 0 10px rgba(255, 45, 120, 0.6);\n}\n\n.game__score-wrap,\n.game__combo-wrap,\n.game__lives-wrap {\n\ttext-align: center;\n}\n\n.game__overlay {\n\tposition: absolute;\n\tinset: 0;\n\tz-index: 20;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tbackground: rgba(10, 4, 20, 0.88);\n\tbackdrop-filter: blur(12px);\n\tanimation: fadeIn 0.3s ease;\n}\n\n.game__overlay--hidden {\n\tdisplay: none;\n}\n\n@keyframes fadeIn {\n\tfrom {\n\t\topacity: 0;\n\t}\n\n\tto {\n\t\topacity: 1;\n\t}\n}\n\n.game__overlay-content {\n\ttext-align: center;\n\tpadding: 24px;\n}\n\n.game__title {\n\tfont-family: 'Lilita One', cursive;\n\tfont-size: clamp(48px, 14vw, 80px);\n\tcolor: var(--text-primary);\n\tline-height: 1;\n\tmargin-bottom: 12px;\n\ttext-shadow:\n\t\t0 0 30px rgba(255, 45, 120, 0.4),\n\t\t0 4px 0 rgba(0, 0, 0, 0.3);\n}\n\n.game__title--accent {\n\tdisplay: block;\n\tbackground: linear-gradient(135deg, var(--accent-pink), var(--accent-cyan));\n\t-webkit-background-clip: text;\n\t-webkit-text-fill-color: transparent;\n\tbackground-clip: text;\n\tfilter: drop-shadow(0 4px 0 rgba(0, 0, 0, 0.3));\n}\n\n.game__title--small {\n\tfont-size: clamp(36px, 10vw, 56px);\n}\n\n.game__subtitle {\n\tfont-size: 18px;\n\tfont-weight: 700;\n\tcolor: var(--accent-cyan);\n\tmargin-bottom: 8px;\n}\n\n.game__hint {\n\tfont-size: 14px;\n\tcolor: var(--text-muted);\n\tline-height: 1.6;\n\tmargin-bottom: 32px;\n}\n\n.game__final-score {\n\tfont-family: 'Lilita One', cursive;\n\tfont-size: 28px;\n\tcolor: var(--accent-cyan);\n\tmargin-bottom: 4px;\n}\n\n.game__best-score {\n\tfont-size: 16px;\n\tcolor: var(--accent-yellow);\n\tfont-weight: 700;\n\tmargin-bottom: 32px;\n}\n\n.game__btn {\n\tfont-family: 'Lilita One', cursive;\n\tfont-size: 22px;\n\tcolor: var(--bg-primary);\n\tbackground: linear-gradient(135deg, var(--accent-yellow), #ffab00);\n\tborder: none;\n\tborder-radius: 50px;\n\tpadding: 16px 48px;\n\tcursor: pointer;\n\tbox-shadow:\n\t\t0 4px 0 #b89800,\n\t\t0 8px 30px rgba(255, 225, 53, 0.3);\n\ttransition: transform 0.1s, box-shadow 0.1s;\n\tletter-spacing: 1px;\n}\n\n.game__btn:active {\n\ttransform: translateY(4px);\n\tbox-shadow:\n\t\t0 0 0 #b89800,\n\t\t0 2px 15px rgba(255, 225, 53, 0.3);\n}"}],"folders":[]},"variants":null,"createdAt":"2026-02-28T13:40:55.692Z","updatedAt":"2026-03-04T16:30:47.883Z"}}