/* St. Regis Case Study - Animations + UTM Tracking */ /* Google Analytics config */ window.dataLayer=window.dataLayer||[]; function gtag(){dataLayer.push(arguments)} gtag('js',new Date()); gtag('config','G-1VFSPH23D9'); /* Animations */ (function(){ var w=window,d=document; function seen(el){var r=el.getBoundingClientRect();return r.top0} function seenWell(el){var r=el.getBoundingClientRect();return r.top0} /* Counter */ var counted=false,bar=d.getElementById("statsBar"); function count(el){ var to=+el.getAttribute("data-to"),pre=el.getAttribute("data-prefix")||"",suf=el.getAttribute("data-suffix")||"",t0=performance.now(); el.textContent=pre+"0"+suf; (function step(now){ var p=Math.min((now-t0)/1800,1),v=Math.round((1-Math.pow(1-p,3))*to); el.textContent=pre+(v>=1000?v.toLocaleString("en-US"):String(v))+suf; if(p<1)requestAnimationFrame(step); })(t0); } /* WhatsApp messages — hide on load, reveal on scroll */ var waDone=false,waBox=d.getElementById("waMockup"); var msgs=waBox?waBox.querySelectorAll(".wa-msg"):[]; msgs.forEach(function(m){m.classList.add("pending")}); /* Journey steps — stagger in on scroll */ var jrnDone=false; var jrnSteps=d.querySelectorAll(".journey-step"); jrnSteps.forEach(function(s){s.style.animation="none";s.classList.add("pending")}); /* Philosophy QR flow — slide in on scroll */ var qrDone=false,qrBox=d.querySelector(".qr-flow"); var qrSteps=qrBox?qrBox.querySelectorAll(".qr-flow-step"):[]; if(qrBox){var qrParent=qrBox.closest(".reveal");if(qrParent)qrParent.style.animation="none"} qrSteps.forEach(function(s){s.classList.add("pending")}); /* Device grid 5 to 30 */ var devDone=false,devBox=d.getElementById("deviceGraphic"); function onScroll(){ if(!counted&&bar&&seenWell(bar)){ counted=true; d.querySelectorAll(".stat-number[data-to]").forEach(count); } if(!waDone&&waBox&&seenWell(waBox)){ waDone=true; msgs.forEach(function(m,i){ setTimeout(function(){m.classList.remove("pending")},i*600); }); } if(!jrnDone&&jrnSteps.length&&seenWell(jrnSteps[0])){ jrnDone=true; jrnSteps.forEach(function(s,i){ setTimeout(function(){s.classList.add("shown")},i*250); }); } if(!qrDone&&qrBox&&seenWell(qrBox)){ qrDone=true; qrSteps.forEach(function(s,i){ setTimeout(function(){s.classList.add("shown")},i*400); }); } if(!devDone&&devBox&&seenWell(devBox)){ devDone=true; setTimeout(function(){ var bl=d.querySelectorAll(".device-icon.blocked"); var svg=""; bl.forEach(function(el,i){ setTimeout(function(){ el.classList.remove("blocked"); el.classList.add("active"); el.innerHTML=svg; el.style.transform="scale(1.15)"; setTimeout(function(){el.style.transform="scale(1)"},200); },i*80); }); setTimeout(function(){ var lb=d.getElementById("deviceLabel"); if(lb){ lb.style.transition="opacity .4s"; lb.style.opacity="0"; setTimeout(function(){ lb.innerHTML="30 connected \xb7 All butlers active"; lb.style.opacity="1"; },400); } var bg=d.getElementById("waBadge"); if(bg){bg.style.opacity="1";bg.style.transform="translateY(0)"} },bl.length*80+300); },1500); } if(counted&&waDone&&jrnDone&&qrDone&&devDone)w.removeEventListener("scroll",onScroll); } w.addEventListener("scroll",onScroll,{passive:true}); /* Delay first check so browser paints pending state before we remove it */ requestAnimationFrame(function(){requestAnimationFrame(function(){onScroll()})}); })(); /* Review Carousel — separate block so animation errors can't break it */ (function(){ var d=document; var curR=0,totR=4; var rTr=d.getElementById("reviewTrack"); var rDots=d.querySelectorAll(".review-dot"); var prevBtn=d.getElementById("revPrev"); var nextBtn=d.getElementById("revNext"); var rc=d.getElementById("reviewCarousel"); if(!rTr||rTr.getAttribute("data-js"))return; rTr.setAttribute("data-js","1"); /* Stop CSS animation, switch to JS-controlled transitions */ rTr.style.animation="none"; rTr.style.transition="transform .5s cubic-bezier(.23,1,.32,1)"; rDots.forEach(function(dot){dot.style.animation="none"}); function goTo(i){ curR=i; rTr.style.transform="translateX(-"+(curR*100)+"%)"; rDots.forEach(function(dot,j){dot.classList.toggle("active",j===curR)}); } goTo(0); function next(){goTo(curR+1>=totR?0:curR+1)} function prev(){goTo(curR-1<0?totR-1:curR-1)} if(prevBtn)prevBtn.addEventListener("click",prev); if(nextBtn)nextBtn.addEventListener("click",next); rDots.forEach(function(dot,i){dot.addEventListener("click",function(){goTo(i)})}); var autoR=setInterval(next,6000); if(rc){ rc.addEventListener("mouseenter",function(){clearInterval(autoR)}); rc.addEventListener("mouseleave",function(){autoR=setInterval(next,6000)}); var tx=0; rc.addEventListener("touchstart",function(e){tx=e.touches[0].clientX;clearInterval(autoR)},{passive:true}); rc.addEventListener("touchend",function(e){var df=tx-e.changedTouches[0].clientX;if(Math.abs(df)>50){if(df>0)next();else prev()}autoR=setInterval(next,6000)},{passive:true}); } })(); /* UTM Tracking */ (function(){ var d=['utm_source','utm_medium','utm_campaign','utm_content','utm_term','gclid','gbraid','wbraid','fbclid','msclkid']; var p=new URLSearchParams(window.location.search); var k={}; d.forEach(function(x){var v=p.get(x);if(v)k[x]=v}); if(Object.keys(k).length>0){try{sessionStorage.setItem('_chatlyn_utms',JSON.stringify(k))}catch(e){}} else{try{var s=sessionStorage.getItem('_chatlyn_utms');if(s)k=JSON.parse(s)}catch(e){}} if(Object.keys(k).length===0)return; function ap(h){ try{ var u=new URL(h,window.location.origin); if(u.protocol!=='http:'&&u.protocol!=='https:')return h; Object.keys(k).forEach(function(x){if(!u.searchParams.has(x))u.searchParams.set(x,k[x])}); return u.toString(); }catch(e){return h} } document.addEventListener('click',function(e){ var l=e.target.closest('a'); if(!l)return; var h=l.getAttribute('href'); if(!h||h.charAt(0)==='#'||h.indexOf('mailto:')===0||h.indexOf('tel:')===0||h.indexOf('javascript:')===0)return; l.setAttribute('href',ap(h)); },true); })();