const menuBtn = document.querySelector(".menu-btn"); const menu = document.querySelector(".menu"); if(menuBtn && menu){ const setMenuOpen = (isOpen) => { menu.classList.toggle("show", isOpen); menuBtn.classList.toggle("is-open", isOpen); menuBtn.setAttribute("aria-expanded", String(isOpen)); menuBtn.setAttribute("aria-label", isOpen ? "Close menu" : "Open menu"); }; menuBtn.addEventListener("click",()=>setMenuOpen(!menu.classList.contains("show"))); menu.querySelectorAll("a").forEach(a=>a.addEventListener("click",()=>setMenuOpen(false))); document.addEventListener("keydown",event=>{ if(event.key === "Escape" && menu.classList.contains("show")){ setMenuOpen(false); menuBtn.focus(); } }); document.querySelectorAll(".nav-dropdown-toggle").forEach(button=>button.addEventListener("click",event=>{ event.stopPropagation(); const dropdown=button.parentElement; const isOpen=dropdown.classList.toggle("open"); button.setAttribute("aria-expanded",String(isOpen)); document.querySelectorAll(".nav-dropdown.open").forEach(item=>{ if(item!==dropdown){ item.classList.remove("open"); item.querySelector(".nav-dropdown-toggle")?.setAttribute("aria-expanded","false"); } }); })); document.addEventListener("click",event=>{ if(!event.target.closest(".nav-dropdown")){ document.querySelectorAll(".nav-dropdown.open").forEach(item=>{ item.classList.remove("open"); item.querySelector(".nav-dropdown-toggle")?.setAttribute("aria-expanded","false"); }); } }); document.addEventListener("keydown",event=>{ if(event.key === "Escape"){ document.querySelectorAll(".nav-dropdown.open").forEach(item=>{ item.classList.remove("open"); item.querySelector(".nav-dropdown-toggle")?.setAttribute("aria-expanded","false"); }); } }); } const translations = { hi: { brand:"माँ दुर्गा सेवा समिति", brandSub:"बादशाह नगर, बाराबंकी", home:"होम", about:"मंदिर परिचय", committee:"मंदिर समिति", navratri:"नवरात्रि", ramleela:"नव युवक रामलीला", gallery:"गैलरी", contact:"संपर्क", footerAbout:"आस्था, सेवा और संस्कार का पवित्र केंद्र। माँ दुर्गा के चरणों में सभी श्रद्धालुओं का स्वागत है।", address:"बादशाह नगर, बाराबंकी, उत्तर प्रदेश", phone:"संपर्क: 8953000895" }, en: { brand:"Maa Durga Sewa Samiti", brandSub:"Badshah Nagar, Barabanki", home:"Home", about:"About Temple", committee:"Temple Committee", navratri:"Navratri", ramleela:"Nav Yuvak Ramlila", gallery:"Gallery", contact:"Contact", footerAbout:"A sacred center of faith, service and values. All devotees are warmly welcomed at Maa Durga's feet.", address:"Badshah Nagar, Barabanki, Uttar Pradesh", phone:"Contact: 8953000895" } }; function setLanguage(lang){ localStorage.setItem("siteLang",lang); document.documentElement.lang = lang === "hi" ? "hi" : "en"; document.querySelectorAll("[data-hi][data-en]").forEach(el=>{ const value = lang === "hi" ? el.dataset.hi : el.dataset.en; if (el.classList.contains("blog-rich-text")) el.innerHTML = value; else el.textContent = value; }); const historyTranslations = { ".history-committee .history-heading .kicker": ["सामूहिक नेतृत्व", "Collective Leadership"], ".history-committee .history-heading h2": ["दुर्गा पूजा समिति — परंपरा की यात्रा", "Durga Puja Committee — A Journey of Tradition"], ".history-committee .history-heading p": ["अतीत से वर्तमान तक, सेवा और आयोजन को संभालने वाले अध्यक्षों की स्मृति।", "Remembering the presidents who carried service and celebrations from the past to the present."], ".history-president-list h3": ["अतीत से वर्तमान तक अध्यक्ष", "Presidents from Past to Present"], ".history-president strong": ["नाम उपलब्ध नहीं", "Name not available"], ".history-president span": ["कार्यकाल और विवरण Admin panel से जोड़ें", "Add tenure and details from the Admin panel"], ".history-timeline-date": ["जानकारी लंबित", "Information pending"], ".history-founder-highlight h3": ["परंपरा की नींव के निर्माता एवं मार्गदर्शक", "Builders and Guides of the Tradition"], ".history-founder-highlight p": ["इस ऐतिहासिक जानकारी को समिति द्वारा शीघ्र अपडेट किया जाएगा।", "This historical information will be updated by the committee soon."], ".history-profile-placeholder span:last-child": ["प्रोफाइल फोटो एवं परिचय के लिए स्थान", "Space for profile photo and introduction"], ".history-immersion .kicker": ["स्मृति-रेखा", "Memory Line"], ".history-immersion h3": ["मूर्ति विसर्जन का इतिहास", "History of Idol Immersion"], ".history-immersion p": ["इस ऐतिहासिक जानकारी को समिति द्वारा शीघ्र अपडेट किया जाएगा।", "This historical information will be updated by the committee soon."], ".history-mini-steps span:nth-child(1)": ["आरंभ", "Beginning"], ".history-mini-steps span:nth-child(2)": ["परंपरा", "Tradition"], ".history-mini-steps span:nth-child(3)": ["आज", "Today"], ".ramlila-history-hero .kicker": ["भक्ति मंच पर जीवंत", "Devotion Comes Alive on Stage"], ".ramlila-history-hero h2": ["रामलीला — हमारी सांस्कृतिक परंपरा", "Ramlila — Our Cultural Tradition"], ".ramlila-history-hero p": ["जहाँ भक्ति मंच पर जीवंत होती है, और परंपरा पीढ़ियों तक पहुँचती है।", "Where devotion comes alive on stage and tradition reaches generations."], ".ramlila-history-panel:nth-child(1) .kicker": ["पहला अध्याय", "The First Chapter"], ".ramlila-history-panel:nth-child(1) h3": ["पहली बार रामलीला कब प्रारंभ हुई", "When Ramlila Began for the First Time"], ".ramlila-history-panel:nth-child(1) p": ["इस ऐतिहासिक जानकारी को समिति द्वारा शीघ्र अपडेट किया जाएगा।", "This historical information will be updated by the committee soon."], ".ramlila-history-panel:nth-child(2) .kicker": ["पुनः आरंभ", "The Revival"], ".ramlila-history-panel:nth-child(2) h3": ["पुनः रामलीला कब शुरू हुई", "When Ramlila Started Again"], ".ramlila-history-panel:nth-child(2) p": ["इस ऐतिहासिक जानकारी को समिति द्वारा शीघ्र अपडेट किया जाएगा।", "This historical information will be updated by the committee soon."], ".ramlila-history-panel .history-detail-row:nth-of-type(1) span": ["तिथि", "Date"], ".ramlila-history-panel .history-detail-row:nth-of-type(2) span": ["डायरेक्टर एवं मुख्य लोग", "Directors and key people"], ".ramlila-history-panel .history-detail-row strong": ["जानकारी लंबित", "Information pending"], ".ramlila-gallery-block .kicker": ["स्मृतियों का मंच", "A Stage of Memories"], ".ramlila-gallery-block h3": ["अतीत के दीपक", "Lights of the Past"], ".ramlila-gallery-block p": ["पुराने कलाकारों की फोटो, नाम और भूमिका यहाँ सुरक्षित की जा सकेगी।", "Photos, names and roles of former artists can be preserved here."], ".history-gallery-placeholder strong": ["कलाकार", "Artist"], ".history-gallery-placeholder small": ["फोटो · नाम · भूमिका", "Photo · Name · Role"], ".ramlila-legacy h3": ["अतीत से वर्तमान तक रामलीला समिति के डायरेक्टर", "Ramlila Committee Directors from Past to Present"], ".ramlila-legacy-list span": ["नाम उपलब्ध नहीं", "Name not available"], ".ramlila-legacy-list small": ["वर्ष / भूमिका Admin panel से जोड़ें", "Add year / role from the Admin panel"], ".history-quote small": ["मंदिर और रामलीला की साझा विरासत", "The shared heritage of the temple and Ramlila"] }; if (document.querySelector(".history-page")) Object.entries(historyTranslations).forEach(([selector, values]) => document.querySelectorAll(selector).forEach(el => { el.textContent = lang === "hi" ? values[0] : values[1]; })); const historyQuote = document.querySelector(".history-quote"); if (historyQuote?.firstChild?.nodeType === Node.TEXT_NODE) historyQuote.firstChild.textContent = lang === "hi" ? "“परंपरा वही जीवित रहती है, जिसे श्रद्धा से अगली पीढ़ी तक पहुँचाया जाए।”" : "“Tradition lives on when it is passed with devotion to the next generation.”"; const constructionHeading = document.querySelector(".history-timeline-section .history-heading h2"); if (constructionHeading) constructionHeading.textContent = lang === "hi" ? "मंदिर निर्माण एवं विकास की यात्रा" : "The Journey of Temple Construction & Growth"; document.querySelectorAll("[data-placeholder-hi][data-placeholder-en]").forEach(el=>{ el.placeholder = lang === "hi" ? el.dataset.placeholderHi : el.dataset.placeholderEn; }); document.querySelectorAll("[data-title-hi][data-title-en]").forEach(el=>{ el.title = lang === "hi" ? el.dataset.titleHi : el.dataset.titleEn; }); document.querySelectorAll("[data-aria-label-hi][data-aria-label-en]").forEach(el=>{ el.setAttribute("aria-label", lang === "hi" ? el.dataset.ariaLabelHi : el.dataset.ariaLabelEn); }); document.querySelectorAll(".history-hi").forEach(el=>el.hidden = lang !== "hi"); document.querySelectorAll(".history-en").forEach(el=>el.hidden = lang === "hi"); document.querySelectorAll("[data-blog-language-content]").forEach(el=>{ el.hidden = el.dataset.blogLanguageContent !== lang; }); document.querySelectorAll("[data-lang]").forEach(el=>{ el.textContent = lang === "hi" ? "English" : "हिन्दी"; }); } const langBtn = document.querySelector("[data-lang]"); if(langBtn){ langBtn.addEventListener("click",()=>{ const current = localStorage.getItem("siteLang") || "hi"; setLanguage(current === "hi" ? "en" : "hi"); window.dispatchEvent(new Event("site-language-changed")); }); } setLanguage(localStorage.getItem("siteLang") || "hi"); const aartiSearch = document.querySelector("[data-aarti-search]"); if (aartiSearch) { const input = aartiSearch.querySelector("[data-aarti-search-input]"); const clearButton = aartiSearch.querySelector("[data-aarti-search-clear]"); const suggestions = aartiSearch.querySelector("[data-aarti-suggestions]"); const records = JSON.parse(document.getElementById("aarti-search-data")?.textContent || "[]"); const renderSuggestions = () => { const term = input.value.trim().toLocaleLowerCase(); clearButton.hidden = !term; if (!term) { suggestions.hidden = true; suggestions.innerHTML = ""; return; } const matches = records.filter(record => `${record.title_hi} ${record.title_en}`.toLocaleLowerCase().includes(term)).slice(0, 6); suggestions.replaceChildren(); matches.forEach(record => { const link = document.createElement("a"); link.className = "aarti-suggestion"; link.setAttribute("role", "option"); link.href = `/aartiya/${encodeURIComponent(record.id)}`; const title = document.createElement("span"); title.className = "aarti-suggestion-title"; title.dataset.hi = record.title_hi; title.dataset.en = record.title_en; title.textContent = document.documentElement.lang === "en" ? record.title_en : record.title_hi; const translatedTitle = document.createElement("span"); translatedTitle.dataset.hi = record.title_en; translatedTitle.dataset.en = record.title_hi; translatedTitle.textContent = document.documentElement.lang === "en" ? record.title_hi : record.title_en; link.append(title, translatedTitle); suggestions.append(link); }); suggestions.hidden = matches.length === 0; }; input.addEventListener("input", renderSuggestions); clearButton.addEventListener("click", () => { input.value = ""; renderSuggestions(); input.focus(); }); document.addEventListener("click", event => { if (!aartiSearch.contains(event.target)) suggestions.hidden = true; }); } const fullscreenDialog = document.querySelector("[data-aarti-fullscreen-dialog]"); if (fullscreenDialog) { document.querySelector("[data-aarti-fullscreen-open]")?.addEventListener("click", () => fullscreenDialog.showModal()); fullscreenDialog.querySelector("[data-aarti-fullscreen-close]")?.addEventListener("click", () => fullscreenDialog.close()); fullscreenDialog.addEventListener("click", event => { if (event.target === fullscreenDialog) fullscreenDialog.close(); }); } const successPopup = document.querySelector("[data-contact-success]"); if (successPopup) { document.body.classList.add("contact-popup-open"); const closeSuccessPopup = () => { successPopup.classList.remove("is-visible"); document.body.classList.remove("contact-popup-open"); document.querySelector(".contact-success-fallback")?.classList.add("is-visible"); }; requestAnimationFrame(() => successPopup.classList.add("is-visible")); successPopup.querySelector("[data-contact-success-close]")?.addEventListener("click", closeSuccessPopup); successPopup.addEventListener("click", event => { if (event.target === successPopup) closeSuccessPopup(); }); } const screenResolution = `${window.screen.width}x${window.screen.height}`; const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content; if (csrfToken && /^\d{2,5}x\d{2,5}$/.test(screenResolution)) { fetch('/visitor-screen', {method:'POST', headers:{'Content-Type':'application/json','X-CSRF-TOKEN':csrfToken,'Accept':'application/json'}, body:JSON.stringify({screen_resolution:screenResolution}), keepalive:true}).catch(()=>{}); } // Ask only when Firebase is configured and the visitor explicitly opts in. (() => { const config = window.__pushConfig; const consent = document.getElementById('push-consent'); const button = document.getElementById('push-consent-button'); const consentText = document.getElementById('push-consent-text'); if (!config || !consent || !button || !('Notification' in window) || !('serviceWorker' in navigator)) return; let requestingPermission = false; const showStatus = (message, label) => { consent.hidden = false; consentText.textContent = message; button.textContent = label; }; const isLikelyPrivateWindow = async () => { if (!navigator.storage?.estimate) return false; try { const estimate = await navigator.storage.estimate(); return Number.isFinite(estimate.quota) && estimate.quota > 0 && estimate.quota <= 150 * 1024 * 1024; } catch (error) { return false; } }; const saveToken = async () => { if (Notification.permission !== 'granted') return; for (let attempt = 0; !window.firebase && attempt < 30; attempt += 1) await new Promise(resolve => setTimeout(resolve, 100)); if (!window.firebase) return; if (!firebase.apps.length) firebase.initializeApp(config); const registration = await navigator.serviceWorker.register(window.__pushServiceWorkerUrl); const messaging = firebase.messaging(); messaging.onMessage((payload) => { const title = payload.notification?.title || 'Maa Durga Sewa Samiti'; const options = { body: payload.notification?.body || '', icon: '/storage/shivom/maadurga.png', data: { url: payload.data?.url || '/' } }; if (Notification.permission === 'granted') registration.showNotification(title, options); }); const token = await messaging.getToken({ vapidKey: config.vapidKey, serviceWorkerRegistration: registration }); if (!token) return; const response = await fetch(window.__pushSubscriptionUrl, { method: 'POST', headers: {'Content-Type':'application/json','X-CSRF-TOKEN':csrfToken,'Accept':'application/json'}, body: JSON.stringify({token}), keepalive: true }); if (!response.ok) throw new Error(`Subscription save failed: ${response.status}`); consent.hidden = true; }; const start = async () => { if (Notification.permission === 'default' && await isLikelyPrivateWindow()) { consent.hidden = true; return; } if (Notification.permission === 'granted') saveToken().catch(() => {}); else if (Notification.permission === 'default') consent.hidden = false; else { showStatus('Notifications blocked hain. Browser site settings me jaakar Notifications ko Allow karein, phir page reload karein.', 'Kaise Allow karein'); } }; button.addEventListener('click', async () => { if (requestingPermission) return; if (Notification.permission === 'granted') { requestingPermission = true; try { await saveToken(); } catch (error) { showStatus('Notifications save nahi ho paayi. Page reload karke dobara try karein.', 'Dobara try karein'); console.error('Push notification setup failed', error); } finally { requestingPermission = false; } return; } if (Notification.permission === 'denied') { alert('Address bar ke lock icon par click karein → Notifications → Allow select karein → page reload karein.'); return; } requestingPermission = true; button.disabled = true; try { const permission = await Notification.requestPermission(); if (permission === 'granted') { await saveToken(); } else if (permission === 'denied') { showStatus('Notifications block ho gayi hain. Address bar ke lock icon me jaakar Notifications ko Allow karein, phir page reload karein.', 'Kaise Allow karein'); } else { consent.hidden = true; } } catch (error) { showStatus('Notifications is browser window me available nahi hain. Normal tab me page kholkar try karein.', 'Normal tab me try karein'); console.error('Push notification setup failed', error); } finally { requestingPermission = false; button.disabled = false; } }); window.addEventListener('load', start, { once: true }); })(); document.querySelectorAll("[data-demo-form]").forEach(form=>{ form.addEventListener("submit",e=>{ e.preventDefault(); const toast=document.querySelector(".toast"); if(toast){ toast.textContent=(localStorage.getItem("siteLang")||"hi")==="hi" ? "धन्यवाद! आपका संदेश प्राप्त हो गया है।" : "Thank you! Your message has been received."; toast.style.display="block"; setTimeout(()=>toast.style.display="none",3000); } form.reset(); }); }); document.querySelectorAll(".year").forEach(el=>el.textContent=new Date().getFullYear()); // Scroll reveal animation const revealObserver = new IntersectionObserver(entries=>{ entries.forEach(entry=>{ if(entry.isIntersecting) entry.target.classList.add("visible"); }); },{threshold:.12}); document.querySelectorAll(".reveal").forEach(el=>revealObserver.observe(el)); // Scroll-to-top button const upBtn=document.getElementById("upBtn"); window.addEventListener("scroll",()=>{ if(upBtn) upBtn.classList.toggle("show",window.scrollY>450); }); if(upBtn) upBtn.addEventListener("click",()=>window.scrollTo({top:0,behavior:"smooth"})); // Live Navratri countdown: the next festival date is configured below. // Hindu lunar new year date configured here. Update the date annually if required. const cd=document.getElementById("navratriCountdown"); if(cd){ function countdown(){ const target=new Date(cd.dataset.target).getTime(); const now=Date.now(); let diff=Math.max(0,target-now); const d=Math.floor(diff/86400000); diff%=86400000; const h=Math.floor(diff/3600000); diff%=3600000; const m=Math.floor(diff/60000); diff%=60000; const s=Math.floor(diff/1000); ["days","hours","minutes","seconds"].forEach((k,i)=>{ const el=document.getElementById("cd-"+k); if(el) el.textContent=String([d,h,m,s][i]).padStart(2,"0"); }); } countdown(); setInterval(countdown,1000); } // Gallery slider const slider=document.querySelector(".gallery-slider"); if(slider){ const track=slider.querySelector(".gallery-track"), slides=[...slider.querySelectorAll(".gallery-slide")]; const dots=[...slider.querySelectorAll(".dot")]; let idx=0; function go(n){idx=(n+slides.length)%slides.length;track.style.transform=`translateX(-${idx*100}%)`;dots.forEach((d,i)=>d.classList.toggle("active",i===idx));} slider.querySelector(".slider-prev")?.addEventListener("click",()=>go(idx-1)); slider.querySelector(".slider-next")?.addEventListener("click",()=>go(idx+1)); dots.forEach((d,i)=>d.addEventListener("click",()=>go(i))); setInterval(()=>go(idx+1),5000); } // Donation tabs document.querySelectorAll("[data-tabs]").forEach(wrap=>{ const buttons=[...wrap.querySelectorAll(".tab-btn")], panels=[...wrap.querySelectorAll(".tab-panel")]; buttons.forEach(btn=>btn.addEventListener("click",()=>{ const target=btn.dataset.tab; buttons.forEach(b=>b.classList.toggle("active",b===btn)); panels.forEach(p=>p.classList.toggle("active",p.dataset.panel===target)); })); }); // About testimonials carousel const testimonialCarousel = document.querySelector("[data-testimonial-carousel]"); if (testimonialCarousel) { const slider = testimonialCarousel.querySelector("[data-testimonial-slider]"); const prevBtn = testimonialCarousel.querySelector(".testimonial-prev"); const nextBtn = testimonialCarousel.querySelector(".testimonial-next"); const cards = [...slider.querySelectorAll(".testimonial-card")]; let currentIndex = 0; let autoAdvance = null; const getVisibleCards = () => (window.innerWidth <= 767 ? 1 : 3); const shouldUseCarousel = () => cards.length > getVisibleCards(); const getMaxIndex = () => Math.max(0, cards.length - getVisibleCards()); const stopAutoAdvance = () => { if (autoAdvance) { clearInterval(autoAdvance); autoAdvance = null; } }; const updateControls = () => { if (!prevBtn || !nextBtn) return; const useCarousel = shouldUseCarousel(); prevBtn.disabled = !useCarousel || currentIndex <= 0; nextBtn.disabled = !useCarousel || currentIndex >= getMaxIndex(); prevBtn.classList.toggle("is-disabled", prevBtn.disabled); nextBtn.classList.toggle("is-disabled", nextBtn.disabled); prevBtn.setAttribute("aria-disabled", String(prevBtn.disabled)); nextBtn.setAttribute("aria-disabled", String(nextBtn.disabled)); }; const updateCarousel = () => { if (!cards.length) return; const useCarousel = shouldUseCarousel(); slider.classList.toggle("has-carousel", useCarousel); prevBtn.style.display = useCarousel ? "grid" : "none"; nextBtn.style.display = useCarousel ? "grid" : "none"; if (!useCarousel) { stopAutoAdvance(); currentIndex = 0; slider.style.transform = "translateX(0)"; updateControls(); return; } const visibleCards = getVisibleCards(); const gap = parseFloat(getComputedStyle(slider).gap || "18"); const cardWidth = cards[0].getBoundingClientRect().width + gap; const maxIndex = getMaxIndex(); currentIndex = Math.min(currentIndex, maxIndex); slider.style.transform = `translateX(-${currentIndex * cardWidth}px)`; updateControls(); }; const goToNext = () => { if (!shouldUseCarousel()) return; if (currentIndex >= getMaxIndex()) return; currentIndex += 1; updateCarousel(); stopAutoAdvance(); autoAdvance = setInterval(goToNext, 5000); }; const goToPrev = () => { if (!shouldUseCarousel()) return; if (currentIndex <= 0) return; currentIndex -= 1; updateCarousel(); stopAutoAdvance(); autoAdvance = setInterval(goToNext, 5000); }; prevBtn?.addEventListener("click", () => { if (!prevBtn.disabled) goToPrev(); }); nextBtn?.addEventListener("click", () => { if (!nextBtn.disabled) goToNext(); }); window.addEventListener("resize", updateCarousel, { passive: true }); updateCarousel(); if (shouldUseCarousel()) { autoAdvance = setInterval(goToNext, 5000); } } // Related aartiya carousel const aartiCarousel = document.querySelector("[data-aarti-carousel]"); if (aartiCarousel) { const track = aartiCarousel.querySelector("[data-aarti-track]"); const cards = [...track.querySelectorAll(".aarti-card")]; const prevBtn = aartiCarousel.querySelector(".aarti-carousel-prev"); const nextBtn = aartiCarousel.querySelector(".aarti-carousel-next"); const pageButtons = [...aartiCarousel.parentElement.querySelectorAll("[data-aarti-page]")]; let currentIndex = 0; let startX = 0; const getVisibleCards = () => window.innerWidth <= 600 ? 1 : window.innerWidth <= 980 ? 2 : 3; const getMaxIndex = () => Math.max(0, cards.length - getVisibleCards()); const updateCarousel = () => { currentIndex = Math.min(currentIndex, getMaxIndex()); const gap = parseFloat(getComputedStyle(track).gap || "18"); const cardWidth = cards[0]?.getBoundingClientRect().width || 0; track.style.transform = `translateX(-${currentIndex * (cardWidth + gap)}px)`; prevBtn.disabled = currentIndex === 0; nextBtn.disabled = currentIndex >= getMaxIndex(); pageButtons.forEach((button, index) => { button.classList.toggle("active", index === currentIndex); if (index === currentIndex) button.setAttribute("aria-current", "page"); else button.removeAttribute("aria-current"); }); }; prevBtn.addEventListener("click", () => { if (currentIndex > 0) { currentIndex -= 1; updateCarousel(); } }); nextBtn.addEventListener("click", () => { if (currentIndex < getMaxIndex()) { currentIndex += 1; updateCarousel(); } }); pageButtons.forEach((button, index) => button.addEventListener("click", () => { currentIndex = Math.min(index, getMaxIndex()); updateCarousel(); })); track.addEventListener("touchstart", event => { startX = event.touches[0].clientX; }, { passive: true }); track.addEventListener("touchend", event => { const distance = event.changedTouches[0].clientX - startX; if (Math.abs(distance) < 40) return; if (distance < 0 && currentIndex < getMaxIndex()) currentIndex += 1; if (distance > 0 && currentIndex > 0) currentIndex -= 1; updateCarousel(); }, { passive: true }); window.addEventListener("resize", updateCarousel, { passive: true }); updateCarousel(); } // Audio: explicit play/pause with visual state and volume. const audio2=document.getElementById("templeAudio"), audioBtn2=document.getElementById("audioToggle"); if(audio2 && audioBtn2){ audio2.volume=.85; audio2.loop=true; audioBtn2.addEventListener("click", async ()=>{ try{ if(audio2.paused){await audio2.play();audioBtn2.textContent="⏸";audioBtn2.classList.add("playing");} else{audio2.pause();audioBtn2.textContent="🔔";audioBtn2.classList.remove("playing");} }catch(e){audioBtn2.textContent="▶";} }); // Autoplay on first visit if(!sessionStorage.getItem("audioPlayed")) { const playAudioOnFirstVisit = async () => { try { if(audio2.paused) { await audio2.play(); audioBtn2.textContent="⏸"; audioBtn2.classList.add("playing"); } sessionStorage.setItem("audioPlayed", "true"); // Remove fallback listeners once played document.removeEventListener("click", playAudioOnFirstVisit); document.removeEventListener("keydown", playAudioOnFirstVisit); } catch(e) { // Autoplay blocked, wait for user interaction } }; // Attempt immediate autoplay playAudioOnFirstVisit(); // Fallback: play on first user interaction if blocked document.addEventListener("click", playAudioOnFirstVisit); document.addEventListener("keydown", playAudioOnFirstVisit); } } // Particle Animation Logic function createParticles() { const container = document.createElement('div'); container.className = 'particles'; document.body.appendChild(container); for (let i = 0; i < 35; i++) { const p = document.createElement('div'); p.className = 'particle'; p.style.left = Math.random() * 100 + 'vw'; p.style.animationDuration = (Math.random() * 6 + 6) + 's'; p.style.animationDelay = (Math.random() * 5) + 's'; const size = (Math.random() * 4 + 3); p.style.width = size + 'px'; p.style.height = size + 'px'; container.appendChild(p); } } document.addEventListener("DOMContentLoaded", createParticles);