(() => { 'use strict'; const canvas = document.getElementById('confetti'); const ctx = canvas.getContext('2d'); const start = document.getElementById('startButton'); const encore = document.getElementById('encoreButton'); const rapButton = document.getElementById('rapButton'); const twinButton = document.getElementById('twinButton'); const toast = document.getElementById('toast'); const liveText = document.getElementById('liveText'); const reduced = matchMedia('(prefers-reduced-motion: reduce)'); const colors = ['#f22e3a', '#f6ff00', '#ffffff', '#111018', '#72d7ff', '#ff9fcf']; let pieces = []; let frame = null; let toastTimer = null; let rapTimer = null; let twinTimer = null; function resize() { const density = Math.min(devicePixelRatio || 1, 2); canvas.width = innerWidth * density; canvas.height = innerHeight * density; canvas.style.width = `${innerWidth}px`; canvas.style.height = `${innerHeight}px`; ctx.setTransform(density, 0, 0, density, 0, 0); } function piece(x, y, index) { const angle = -Math.PI * 0.9 + (index % 50) / 49 * Math.PI * 0.8; const speed = 7 + Math.random() * 14; return { x, y, vx: Math.cos(angle) * speed + (Math.random() - 0.5) * 5, vy: Math.sin(angle) * speed - Math.random() * 5, gravity: 0.18 + Math.random() * 0.14, drag: 0.988, rotation: Math.random() * 6.28, spin: (Math.random() - 0.5) * 0.3, size: 6 + Math.random() * 12, color: colors[index % colors.length], life: 160 + Math.random() * 80, shape: index % 3 }; } function burst(x = innerWidth / 2, y = innerHeight * 0.7) { if (reduced.matches) return; for (let index = 0; index < 220; index += 1) pieces.push(piece(x, y, index)); if (!frame) animate(); } function animate() { ctx.clearRect(0, 0, innerWidth, innerHeight); pieces = pieces.filter(item => item.life > 0 && item.y < innerHeight + 90); pieces.forEach(item => { item.vx *= item.drag; item.vy = item.vy * item.drag + item.gravity; item.x += item.vx; item.y += item.vy; item.rotation += item.spin; item.life -= 1; ctx.save(); ctx.translate(item.x, item.y); ctx.rotate(item.rotation); ctx.fillStyle = item.color; ctx.strokeStyle = '#111018'; ctx.lineWidth = 1; if (item.shape === 0) { ctx.fillRect(-item.size / 2, -item.size / 4, item.size, item.size / 2); ctx.strokeRect(-item.size / 2, -item.size / 4, item.size, item.size / 2); } else if (item.shape === 1) { ctx.beginPath(); ctx.moveTo(0, -item.size / 2); ctx.lineTo(item.size / 2, item.size / 2); ctx.lineTo(-item.size / 2, item.size / 2); ctx.closePath(); ctx.fill(); ctx.stroke(); } else { ctx.fillRect(-item.size / 3, -item.size / 2, item.size * 0.66, item.size); } ctx.restore(); }); if (pieces.length) frame = requestAnimationFrame(animate); else { frame = null; ctx.clearRect(0, 0, innerWidth, innerHeight); } } function count() { document.querySelectorAll('[data-count]').forEach(element => { const target = Number(element.dataset.count); if (Number(element.textContent) === target) return; let value = 0; const step = Math.max(1, Math.ceil(target / 55)); function tick() { value = Math.min(target, value + step); element.textContent = value; if (value < target) requestAnimationFrame(tick); } tick(); }); } function showToast(text = 'SVEIKINIMO BISAS PALEISTAS — PLOJIMAI DONATUI!') { clearTimeout(toastTimer); toast.textContent = text; toast.classList.add('visible'); toastTimer = setTimeout(() => toast.classList.remove('visible'), 3200); } function launch(event) { document.body.classList.add('started'); liveText.textContent = 'BISAS PALEISTAS'; start.querySelector('span').textContent = 'SVEIKINIMO BISAS ATIDARYTAS!'; const rect = event?.currentTarget?.getBoundingClientRect(); burst(rect ? rect.left + rect.width / 2 : innerWidth / 2, rect ? rect.top : innerHeight * 0.7); count(); showToast(); } function rap() { clearInterval(rapTimer); const lines = [...document.querySelectorAll('#rapText span')]; lines.forEach(line => line.classList.remove('active')); let index = 0; const next = () => { if (index < lines.length) lines[index++].classList.add('active'); else clearInterval(rapTimer); }; next(); rapTimer = setInterval(next, 650); showToast('REPAS DONATUI — PUBLIKA PRAŠO BISO!'); } function reunion(event) { clearInterval(twinTimer); const cards = [...document.querySelectorAll('.twin-card')]; cards.forEach(card => card.classList.remove('active')); if (reduced.matches) cards.forEach(card => card.classList.add('active')); else { let index = 0; const next = () => { cards.forEach(card => card.classList.remove('active')); cards[index % cards.length].classList.add('active'); index += 1; if (index > cards.length) clearInterval(twinTimer); }; next(); twinTimer = setInterval(next, 850); } const rect = event.currentTarget.getBoundingClientRect(); burst(rect.left + rect.width / 2, rect.top); showToast('KĮŽ3 SKAITMENINIS REUNIONAS PALEISTAS!'); } start.addEventListener('click', launch); encore.addEventListener('click', launch); rapButton.addEventListener('click', event => { rap(); const rect = event.currentTarget.getBoundingClientRect(); burst(rect.left + rect.width / 2, rect.top); }); twinButton.addEventListener('click', reunion); addEventListener('resize', resize, { passive: true }); resize(); const observer = new IntersectionObserver(entries => { if (entries.some(entry => entry.isIntersecting)) { count(); observer.disconnect(); } }, { threshold: 0.3 }); observer.observe(document.querySelector('.numbers')); })();