// ... continued gradient definition poolGradient.addColorStop(0.6, 'transparent'); ctx.fillStyle = poolGradient; ctx.arc(canvas.width / 2, canvas.height / 2 - 80, 300, 0, Math.PI * 2); ctx.fill(); } // Draw bubbles function drawBubbles() { for (let { x, y, radius, speed, opacity } of bubbles) { ctx.globalAlpha = opacity; ctx.beginPath(); ctx.arc(x, canvas.height - y, radius, 0, Math.PI * 2); ctx.fill(); ctx.globalAlpha = 1; // Move and draw again if off-screen if (y < -radius) { bubbles.push({ x: Math.random() * canvas.width, y: canvas.height + Math.random() * 200, radius: 10 + Math.random() * 20, speed: 0.5 + Math.random() * 2, opacity: 0.3 + Math.random() * 0.5 }); } y -= speed; } } // Animation loop function animate() { ctx.clearRect(0, 0, canvas.width, canvas.height); drawPool(); drawBubbles(); requestAnimationFrame(animate); } animate