/* ============================================================ About Us — CSS sticky pin + rAF scroll-linked (no GSAP) Smoothest approach: CSS position:sticky handles the pin (native GPU compositing), rAF drives the cross-fade timeline. Stage 1 (au-1): intro(screen1) -> slogan(screen2) Stage 2 (au-3): Strong Resources(screen3) -> zoom+logo(screen4) ============================================================ */ (function () { var s1 = document.querySelector('#au-1'); var s3 = document.querySelector('#au-3'); if (!s1) return; var bg = s1.querySelector('.au-bg'); var intro = s1.querySelector('.au-inner'); var corner = s1.querySelector('.au-corner-img'); var mask = s1.querySelector('.au-mask'); var layer = s1.querySelector('.au-slogan-layer'); var sl = s1.querySelector('.au-slogan'); var cn = s1.querySelector('.au-slogan-cn'); var head = s3 ? s3.querySelector('.au-sec-head') : null; var zoom = s3 ? s3.querySelector('.au-zoom-img') : null; var zoomMask = s3 ? s3.querySelector('.au-zoom-mask') : null; var reveal = s3 ? s3.querySelector('.au-reveal') : null; function clamp(v, a, b) { return Math.max(a, Math.min(b, v)); } function lerp(a, b, t) { return a + (b - a) * clamp(t, 0, 1); } var start1 = 0, start3 = 0; function measure() { function dt(el) { var r = el.getBoundingClientRect(); return r.top + window.scrollY; } start1 = dt(s1); if (s3) start3 = dt(s3); } function update() { var vh = window.innerHeight; /* ---- au-1 (pin 2vh): intro held -> cross-fade to slogan ---- */ var p = clamp((window.scrollY - start1) / vh, 0, 2); // 0 -> 2 // bg: subtle cinematic scale throughout if (bg) bg.style.transform = 'scale(' + lerp(1.04, 1, p / 2).toFixed(4) + ')'; // intro (screen 1): held 0-0.3, fades up 0.3-0.6 var introT = clamp((p - 0.3) / 0.3, 0, 1); if (intro) { intro.style.opacity = String(1 - introT); intro.style.transform = 'translateY(' + (-introT * 30).toFixed(1) + 'px)'; } if (corner) corner.style.opacity = String(1 - introT); // mask: darkens 0.3-0.6 if (mask) mask.style.opacity = String(introT); // slogan (screen 2): triggered CSS transition at threshold (NIO-style auto rise-up) if (layer) layer.classList.toggle('is-current', p >= 0.5); /* ---- au-3 (pin 2vh): Strong Resources -> zoom + logo ---- */ if (s3) { var q = clamp((window.scrollY - start3) / vh, 0, 2); var t = clamp((q - 1.0) / 1.0, 0, 1); // head (screen 3): held first screen, fades second if (head) head.style.opacity = String(clamp(1 - (q - 0.6) / 0.3, 0, 1)); // zoom: scale to fullscreen; photo opacity stays 1 — a black veil fades in over it if (zoom) { zoom.style.transform = 'translate(-50%, -50%) scale(' + lerp(1, 2.2, t).toFixed(3) + ')'; } if (zoomMask) zoomMask.style.opacity = String(lerp(0, 0.8, t).toFixed(3)); // reveal (screen 4): logo+text in second screen if (reveal) reveal.style.opacity = String(clamp((q - 1.1) / 0.4, 0, 1)); } } var ticking = false; function onScroll() { if (ticking) return; ticking = true; requestAnimationFrame(function () { update(); ticking = false; }); } window.addEventListener('scroll', onScroll, { passive: true }); window.addEventListener('resize', function () { measure(); onScroll(); }); measure(); update(); })(); /* ============================================================ GPS data carousel — auto-rotate + dot navigation ============================================================ */ (function () { var track = document.querySelector('.au-gps__track'); var dotsWrap = document.querySelector('.au-gps__dots'); if (!track || !dotsWrap) return; var cards = Array.prototype.slice.call(track.children); if (cards.length < 2) return; var idx = 0, timer = null; cards.forEach(function (_, i) { var b = document.createElement('button'); b.setAttribute('aria-label', 'Slide ' + (i + 1)); b.addEventListener('click', function () { goTo(i); restart(); }); dotsWrap.appendChild(b); }); var dots = Array.prototype.slice.call(dotsWrap.children); function render() { track.style.transform = 'translateX(' + (-idx * 100) + '%)'; dots.forEach(function (d, i) { d.classList.toggle('active', i === idx); }); } function goTo(i) { idx = ((i % cards.length) + cards.length) % cards.length; render(); } function next() { goTo(idx + 1); } function start() { timer = setInterval(next, 4000); } function restart() { clearInterval(timer); start(); } render(); start(); // pause auto-rotate while hovering track.addEventListener('mouseenter', function () { clearInterval(timer); }); track.addEventListener('mouseleave', start); })();