// ---------- CONFIG ---------- const CORRECT_PASSWORD = "2507"; // Tayyaba's birthday, DDMM // ---------- floating balloons ---------- const balloonColors = ["#b98ee8", "#d3b3f0", "#f6a6c1", "#ffffff", "#e8b64a", "#c9a6f2"]; const field = document.getElementById("balloonField"); function spawnBalloon() { const b = document.createElement("div"); b.className = "balloon"; const color = balloonColors[Math.floor(Math.random() * balloonColors.length)]; b.style.background = color; b.style.left = Math.random() * 96 + "vw"; const size = 50 + Math.random() * 40; b.style.width = size + "px"; b.style.height = size * 1.25 + "px"; const duration = 10 + Math.random() * 8; b.style.animationDuration = duration + "s"; field.appendChild(b); setTimeout(() => b.remove(), duration * 1000); } // seed some balloons immediately, then keep spawning for (let i = 0; i < 10; i++) { setTimeout(spawnBalloon, i * 700); } setInterval(spawnBalloon, 1400); // ---------- popup controls ---------- const openBtn = document.getElementById("openBtn"); const passOverlay = document.getElementById("passOverlay"); const closeOverlay = document.getElementById("closeOverlay"); const passForm = document.getElementById("passForm"); const passInput = document.getElementById("passInput"); const oopsPopup = document.getElementById("oopsPopup"); const oopsRetry = document.getElementById("oopsRetry"); const homePage = document.getElementById("homePage"); const letterPage = document.getElementById("letterPage"); openBtn.addEventListener("click", () => { passOverlay.classList.remove("hidden"); passInput.value = ""; passInput.focus(); }); closeOverlay.addEventListener("click", () => { passOverlay.classList.add("hidden"); }); passForm.addEventListener("submit", (e) => { e.preventDefault(); const val = passInput.value.trim(); if (val === CORRECT_PASSWORD) { passOverlay.classList.add("hidden"); homePage.classList.add("hidden"); letterPage.classList.remove("hidden"); window.scrollTo({ top: 0, behavior: "smooth" }); } else { passOverlay.classList.add("hidden"); oopsPopup.classList.remove("hidden"); } }); oopsRetry.addEventListener("click", () => { oopsPopup.classList.add("hidden"); passOverlay.classList.remove("hidden"); passInput.value = ""; passInput.focus(); }); // ---------- synthesized birthday tune (Web Audio, no external file needed) ---------- let audioCtx; const musicBtn = document.getElementById("musicBtn"); // a cheerful original little melody (note, duration in seconds) const tune = [ ["C5", 0.3], ["C5", 0.2], ["D5", 0.5], ["C5", 0.5], ["F5", 0.5], ["E5", 1.0], ["C5", 0.3], ["C5", 0.2], ["D5", 0.5], ["C5", 0.5], ["G5", 0.5], ["F5", 1.0], ["C5", 0.3], ["C5", 0.2], ["C6", 0.5], ["A5", 0.5], ["F5", 0.5], ["E5", 0.5], ["D5", 1.0], ["A#5", 0.3], ["A#5", 0.2], ["A5", 0.5], ["F5", 0.5], ["G5", 0.5], ["F5", 1.0] ]; const noteFreq = { "C5": 523.25, "D5": 587.33, "E5": 659.25, "F5": 698.46, "G5": 783.99, "A5": 880.00, "A#5": 932.33, "C6": 1046.50 }; function playTune() { if (!audioCtx) audioCtx = new (window.AudioContext || window.webkitAudioContext)(); let t = audioCtx.currentTime + 0.05; tune.forEach(([note, dur]) => { const osc = audioCtx.createOscillator(); const gain = audioCtx.createGain(); osc.type = "triangle"; osc.frequency.value = noteFreq[note]; gain.gain.setValueAtTime(0.0001, t); gain.gain.exponentialRampToValueAtTime(0.25, t + 0.05); gain.gain.exponentialRampToValueAtTime(0.0001, t + dur); osc.connect(gain).connect(audioCtx.destination); osc.start(t); osc.stop(t + dur + 0.05); t += dur; }); } let playing = false; musicBtn.addEventListener("click", () => { playTune(); musicBtn.textContent = "🎶 Playing..."; const totalDuration = tune.reduce((sum, [, d]) => sum + d, 0) * 1000; setTimeout(() => { musicBtn.textContent = "🎵 Play Birthday Tune"; }, totalDuration); });