1/* ============================================================= 2 landingpage.js â Shared JS for google, amazon, ai 3 All blocks use defensive element checks and are safe to run 4 on any page (no-op if the element doesn't exist). 5 ============================================================= */ 6 7// ââ SVG Chart: hero siLine/siArea/siDot (google, amazon, ai) âââââââââââââââââ 8(function () { 9 var line = document.getElementById('siLine'); 10 var area = document.getElementById('siArea'); 11 var dot = document.getElementById('siDot'); 12 if (!line) return; 13 var len = line.getTotalLength(); 14 function play() { 15 line.style.animation = 'none'; area.style.animation = 'none'; dot.style.animation = 'none'; 16 line.style.strokeDasharray = len; line.style.strokeDashoffset = len; 17 area.style.opacity = '0'; dot.style.opacity = '0'; 18 requestAnimationFrame(function () { 19 requestAnimationFrame(function () { 20 line.style.animation = 'drawLine 2s ease-out forwards'; 21 area.style.animation = 'fadeInFill 0.6s ease-out forwards 1.8s'; 22 dot.style.animation = 'fadeInFill 0.3s ease-out forwards 1.8s'; 23 }); 24 }); 25 } 26 document.addEventListener('DOMContentLoaded', play); 27})(); 28 29// ââ SVG Chart: CTA sparkline (google only) âââââââââââââââââââââââââââââââââââ 30(function () { 31 var line = document.getElementById('ctaSparkLine'); 32 var area = document.getElementById('ctaSparkArea'); 33 var dot = document.getElementById('ctaSparkDot'); 34 if (!line) return; 35 var len = line.getTotalLength(); 36 line.style.strokeDasharray = len; 37 line.style.strokeDashoffset = len; 38 39 function play() {
40 line.style.animation = 'none'; area.style.animation = 'none'; dot.style.animation = 'none'; 41 line.style.strokeDasharray = len; line.style.strokeDashoffset = len; 42 area.style.opacity = '0'; dot.style.opacity = '0'; 43 requestAnimationFrame(function () { 44 requestAnimationFrame(function () { 45 line.style.animation = 'drawLine 1.6s ease-out forwards'; 46 area.style.animation = 'fadeInFill 0.5s ease-out forwards 1.4s'; 47 dot.style.animation = 'fadeInFill 0.3s ease-out forwards 1.4s'; 48 }); 49 }); 50 } 51 52 var section = document.getElementById('trial'); 53 if (section && 'IntersectionObserver' in window) { 54 var played = false; 55 new IntersectionObserver(function (entries) { 56 if (entries[0].isIntersecting && !played) { played = true; play(); } 57 }, { threshold: 0.3 }).observe(section); 58 } else { 59 document.addEventListener('DOMContentLoaded', play); 60 } 61})(); 62 63// ââ SVG Chart: google feature chart (fsiLine/fsiArea/fsiDots) ââââââââââââââââ 64(function () { 65 var chart = document.getElementById('feature-chart'); 66 var line = document.getElementById('fsiLine'); 67 var area = document.getElementById('fsiArea'); 68 var dots = document.getElementById('fsiDots'); 69 if (!line) return; 70 var len = line.getTotalLength(); 71 line.style.strokeDasharray = len; line.style.strokeDashoffset = len; 72 73 function play() {
74 line.style.animation = 'none'; 75 if (area) area.style.animation = 'none'; 76 if (dots) dots.style.animation = 'none'; 77 line.style.strokeDasharray = len; line.style.strokeDashoffset = len; 78 if (area) area.style.opacity = '0'; 79 if (dots) dots.style.opacity = '0'; 80 requestAnimationFrame(function () { 81 requestAnimationFrame(function () { 82 line.style.animation = 'drawLine 2s ease-out forwards'; 83 if (area) area.style.animation = 'fadeInFill 0.6s ease-out forwards 1.8s'; 84 if (dots) dots.style.animation = 'fadeInFill 0.5s ease-out forwards 1.8s'; 85 }); 86 }); 87 } 88 89 document.addEventListener('DOMContentLoaded', play); 90 if (chart) chart.addEventListener('mouseenter', play); 91})(); 92 93// ââ SVG Chart: ai-onpage-chart multi-line (ai only) ââââââââââââââââââââââââââ 94(function () { 95 var chart = document.getElementById('ai-onpage-chart'); 96 if (!chart) return; 97 var pairs = [1,2,3,4].map(function (n) { 98 return { line: document.getElementById('fsiLine' + n), area: document.getElementById('fsiArea' + n) }; 99 }).filter(function (p) { return p.line; }); 100 101 pairs.forEach(function (p) { 102 var len = p.line.getTotalLength(); 103 p.line._len = len; 104 p.line.style.strokeDasharray = len; 105 p.line.style.strokeDashoffset = len; 106 }); 107 108 function play() { 109 pairs.forEach(function (p) { 110 var len = p.line._len;
111 p.line.style.animation = 'none'; 112 if (p.area) p.area.style.animation = 'none'; 113 p.line.style.strokeDasharray = len; 114 p.line.style.strokeDashoffset = len; 115 if (p.area) p.area.style.opacity = '0'; 116 }); 117 requestAnimationFrame(function () { 118 requestAnimationFrame(function () { 119 pairs.forEach(function (p) { 120 p.line.style.animation = 'drawLine 2s ease-out forwards'; 121 if (p.area) p.area.style.animation = 'fadeInFill 0.6s ease-out forwards 1.8s'; 122 }); 123 }); 124 }); 125 } 126 127 document.addEventListener('DOMContentLoaded', play); 128 chart.addEventListener('mouseenter', play); 129})(); 130 131// ââ SVG Chart: bento-fsi-chart (ai only) âââââââââââââââââââââââââââââââââââââ 132(function () { 133 var chart = document.getElementById('bento-fsi-chart'); 134 var line = document.getElementById('bentoFsiLine'); 135 var area = document.getElementById('bentoFsiArea'); 136 if (!line) return; 137 var len = line.getTotalLength(); 138 line.style.strokeDasharray = len; 139 line.style.strokeDashoffset = len; 140 141 function play() {
142 line.style.animation = 'none'; 143 if (area) area.style.animation = 'none'; 144 line.style.strokeDasharray = len; 145 line.style.strokeDashoffset = len; 146 if (area) area.style.opacity = '0'; 147 requestAnimationFrame(function () { 148 requestAnimationFrame(function () { 149 line.style.animation = 'drawLine 2s ease-out forwards'; 150 if (area) area.style.animation = 'fadeInFill 0.6s ease-out forwards 1.8s'; 151 }); 152 }); 153 } 154 155 document.addEventListener('DOMContentLoaded', play); 156 if (chart) chart.addEventListener('mouseenter', play); 157})(); 158 159// ââ SVG Chart: bento6 multi-line (ai only) âââââââââââââââââââââââââââââââââââ 160(function () { 161 var box = document.getElementById('bento6-box'); 162 var ids = ['bento6-line-1','bento6-line-2','bento6-line-3','bento6-line-4','bento6-line-5']; 163 var lens = []; 164 165 function play() { 166 var els = ids.map(function (id, i) { 167 var el = document.getElementById(id); 168 if (!el) return null; 169 if (!lens[i]) lens[i] = el.getTotalLength(); 170 el.style.transition = 'none'; 171 el.style.strokeDasharray = lens[i]; 172 el.style.strokeDashoffset = lens[i]; 173 return el; 174 }); 175 requestAnimationFrame(function () { 176 requestAnimationFrame(function () { 177 els.forEach(function (el, i) { 178 if (!el) return; 179 el.style.transition = 'stroke-dashoffset ' + (1.4 + i * 0.12) + 's ease-out ' + (i * 0.08) + 's'; 180 el.style.strokeDashoffset = '0'; 181 }); 182 }); 183 }); 184 } 185 186 if (!ids.some(function (id) { return document.getElementById(id); })) return; 187 document.addEventListener('DOMContentLoaded', play); 188 if (box) box.addEventListener('mouseenter', play); 189})(); 190 191// ââ Amazon BVI counter (amazon only) âââââââââââââââââââââââââââââââââââââââââ 192(function () { 193 var chart = document.getElementById('prompt-chart'); 194 var numEl = document.getElementById('bvi-number'); 195 var badgeEl = document.getElementById('bvi-badge'); 196 if (!chart || !numEl || !badgeEl) return; 197 198 var TARGET_CENTS = 163893; 199 var DURATION = 900; 200 var animating = false; 201 202 function formatBVI(cents) { 203 var dec = (cents % 100).toString().padStart(2, '0'); 204 var whole = Math.floor(cents / 100); 205 var wholeStr = whole >= 1000 206 ? Math.floor(whole / 1000) + '.' + (whole % 1000).toString().padStart(3, '0') 207 : whole.toString(); 208 return wholeStr + ',' + dec; 209 } 210 211 function play() { 212 if (animating) return; 213 animating = true; 214 badgeEl.style.transition = 'none'; 215 badgeEl.style.opacity = '0'; 216 var start = performance.now(); 217 218 function step(now) { 219 var t = Math.min((now - start) / DURATION, 1); 220 var ease = 1 - Math.pow(1 - t, 3); 221 numEl.textContent = formatBVI(Math.round(ease * TARGET_CENTS)); 222 if (t < 1) { 223 requestAnimationFrame(step); 224 } else { 225 numEl.textContent = '1.638,93'; 226 badgeEl.style.transition = 'opacity 0.3s ease-out'; 227 badgeEl.style.opacity = '1'; 228 animating = false; 229 } 230 } 231 requestAnimationFrame(step); 232 } 233 234 chart.addEventListener('mouseenter', play); 235})(); 236 237// ââ Hero Parallax (google: hero-text / hero-cards-wrap) âââââââââââââââââââââââ 238(function () { 239 var heroText = document.getElementById('hero-text'); 240 var heroCardsWrap = document.getElementById('hero-cards-wrap'); 241 if (!heroText || !heroCardsWrap) return; 242 243 heroCardsWrap.style.willChange = 'transform'; 244 heroCardsWrap.style.transform = 'translateZ(0)'; 245 heroCardsWrap.style.webkitBackfaceVisibility = 'hidden'; 246 heroCardsWrap.style.backfaceVisibility = 'hidden'; 247 heroText.style.willChange = 'transform'; 248 heroText.style.transform = 'translateZ(0)'; 249 heroText.style.webkitBackfaceVisibility = 'hidden'; 250 heroText.style.backfaceVisibility = 'hidden'; 251 252 var ticking = false; 253 window.addEventListener('scroll', function () { 254 if (ticking) return; 255 ticking = true; 256 requestAnimationFrame(function () { 257 var y = window.scrollY; 258 heroText.style.transform = 'translateY(' + (y * 0.07) + 'px)'; 259 heroCardsWrap.style.transform = 'translateY(' + (y * 0.16) + 'px)'; 260 ticking = false;
261 }); 262 }, { passive: true }); 263})(); 264 265// ââ Hero Parallax (amazon: amz-hero-text / amz-hero-cards-wrap) ââââââââââââââ 266(function () { 267 var heroText = document.getElementById('amz-hero-text'); 268 var heroCardsWrap = document.getElementById('amz-hero-cards-wrap'); 269 if (!heroText || !heroCardsWrap) return; 270 271 heroCardsWrap.style.willChange = 'transform'; 272 heroCardsWrap.style.transform = 'translateZ(0)'; 273 heroCardsWrap.style.webkitBackfaceVisibility = 'hidden'; 274 heroCardsWrap.style.backfaceVisibility = 'hidden'; 275 heroText.style.willChange = 'transform'; 276 heroText.style.transform = 'translateZ(0)'; 277 heroText.style.webkitBackfaceVisibility = 'hidden'; 278 heroText.style.backfaceVisibility = 'hidden'; 279 280 var ticking = false; 281 window.addEventListener('scroll', function () { 282 if (ticking) return; 283 ticking = true; 284 requestAnimationFrame(function () { 285 var y = window.scrollY; 286 heroText.style.transform = 'translateY(' + (y * 0.07) + 'px)'; 287 heroCardsWrap.style.transform = 'translateY(' + (y * 0.16) + 'px)'; 288 ticking = false; 289 }); 290 }, { passive: true }); 291})(); 292 293// ââ Hero Parallax (ai: ai-hero-text / ai-hero-cards-wrap) âââââââââââââââââââââ 294(function () { 295 var heroText = document.getElementById('ai-hero-text'); 296 var heroCardsWrap = document.getElementById('ai-hero-cards-wrap'); 297 if (!heroText || !heroCardsWrap) return; 298 299 heroText.style.willChange = 'transform'; 300 heroCardsWrap.style.willChange = 'transform'; 301 302 var ticking = false; 303 window.addEventListener('scroll', function () { 304 if (ticking) return; 305 ticking = true; 306 requestAnimationFrame(function () { 307 var y = window.scrollY; 308 heroText.style.transform = 'translateY(' + (y * 0.07) + 'px)'; 309 heroCardsWrap.style.transform = 'translateY(' + (y * 0.16) + 'px)'; 310 ticking = false; 311 }); 312 }, { passive: true }); 313})(); 314 315// ââ Hero card 3D tilt (amazon) ââââââââââââââââââââââââââââââââââââââââââââââââ 316(function () { 317 [{ id: 'amz-hero-card-1', baseRotate: 3, baseZ: '10' }, 318 { id: 'amz-hero-card-2', baseRotate: -1.5, baseZ: '20' }].forEach(function (cfg) { 319 var card = document.getElementById(cfg.id); 320 if (!card) return; 321 var rafId = null; 322 card.addEventListener('mousemove', function (e) { 323 var rect = card.getBoundingClientRect(); 324 if (rafId) return; 325 rafId = requestAnimationFrame(function () { 326 rafId = null; 327 var dx = (e.clientX - (rect.left + rect.width / 2)) / (rect.width / 2); 328 var dy = (e.clientY - (rect.top + rect.height / 2)) / (rect.height / 2); 329 card.style.transition = 'transform 0.08s ease-out'; 330 card.style.transform = 'rotate(' + cfg.baseRotate + 'deg) perspective(700px) rotateX(' + (-dy * 12) + 'deg) rotateY(' + (dx * 12) + 'deg) scale(1.04)'; 331 card.style.zIndex = '40'; 332 }); 333 }); 334 card.addEventListener('mouseleave', function () { 335 card.style.transition = 'transform 0.45s cubic-bezier(0.23,1,0.32,1)'; 336 card.style.transform = 'rotate(' + cfg.baseRotate + 'deg)'; 337 card.style.zIndex = cfg.baseZ; 338 }); 339 }); 340})(); 341 342// ââ Subtle tilt: feature/section charts (google) ââââââââââââââââââââââââââââââ 343(function () { 344 ['feature-chart', 'concurrence-chart', 'ca-card', 'onpage-chart'].forEach(function (id) { 345 var el = document.getElementById(id); 346 if (!el) return; 347 var rafId = null; 348 el.addEventListener('mousemove', function (e) { 349 var r = el.getBoundingClientRect(); 350 if (rafId) return; 351 rafId = requestAnimationFrame(function () { 352 rafId = null; 353 var dx = (e.clientX - (r.left + r.width / 2)) / (r.width / 2); 354 var dy = (e.clientY - (r.top + r.height / 2)) / (r.height / 2); 355 el.style.transition = 'transform 0.1s ease-out'; 356 el.style.transform = 'perspective(900px) rotateX(' + (-dy * 5) + 'deg) rotateY(' + (dx * 5) + 'deg)
356scale(1.02)'; 357 }); 358 }); 359 el.addEventListener('mouseleave', function () { 360 el.style.transition = 'transform 0.5s cubic-bezier(0.23,1,0.32,1)'; 361 el.style.transform = ''; 362 }); 363 }); 364})(); 365 366// ââ Subtle tilt: feature/section charts (amazon) âââââââââââââââââââââââââââââ 367(function () { 368 ['prompt-chart', 'prompt-cloud', 'ai-card-1'].forEach(function (id) { 369 var el = document.getElementById(id); 370 if (!el) return; 371 var rafId = null; 372 el.addEventListener('mousemove', function (e) { 373 var r = el.getBoundingClientRect(); 374 if (rafId) return; 375 rafId = requestAnimationFrame(function () { 376 rafId = null; 377 var dx = (e.clientX - (r.left + r.width / 2)) / (r.width / 2); 378 var dy = (e.clientY - (r.top + r.height / 2)) / (r.height / 2); 379 el.style.transition = 'transform 0.1s ease-out'; 380 el.style.transform = 'perspective(900px) rotateX(' + (-dy * 5) + 'deg) rotateY(' + (dx * 5) + 'deg) scale(1.02)'; 381 }); 382 }); 383 el.addEventListener('mouseleave', function () { 384 el.style.transition = 'transform 0.5s cubic-bezier(0.23,1,0.32,1)'; 385 el.style.transform = ''; 386 }); 387 }); 388})(); 389 390// ââ Subtle tilt: bento-fsi-chart (ai) ââââââââââââââââââââââââââââââââââââââââ 391(function () { 392 var chart = document.getElementById('bento-fsi-chart'); 393 if (!chart) return; 394 var rafId = null; 395 chart.addEventListener('mousemove', function (e) { 396 var r = chart.getBoundingClientRect(); 397 if (rafId) return; 398 rafId = requestAnimationFrame(function () { 399 rafId = null; 400 var dx = (e.clientX - (r.left + r.width / 2)) / (r.width / 2); 401 var dy = (e.clientY - (r.top + r.height / 2)) / (r.height / 2); 402 chart.style.transition = 'transform 0.1s ease-out'; 403 chart.style.transform = 'perspective(900px) rotateX(' + (-dy * 5) + 'deg) rotateY(' + (dx * 5) + 'deg) scale(1.02)'; 404 }); 405 }); 406 chart.addEventListener('mouseleave', function () { 407 chart.style.transition = 'transform 0.5s cubic-bezier(0.23,1,0.32,1)'; 408 chart.style.transform = ''; 409 }); 410})(); 411 412// ââ Typewriter: google ca-card ââââââââââââââââââââââââââââââââââââââââââââââââ 413(function () { 414 var el = document.getElementById('ca-typewriter'); 415 var card = document.getElementById('ca-card'); 416 if (!el || !card) return; 417 var fullText = el.dataset.text || ''; 418 var cursor = '<span class="font-medium" style="animation:caBlinkCursor 0.8s step-end infinite;border-right:2px solid #888;margin-left:1px;"> </span>'; 419 var timer = null; 420 421 function startTyping() { 422 if (timer) clearTimeout(timer); 423 var i = 0; 424 function type() { 425 el.innerHTML = fullText.substring(0, i) + cursor; 426 if (i <= fullText.length) { i++; timer = setTimeout(type, 28 + Math.random() * 22); } 427 } 428 timer = setTimeout(type, 300); 429 } 430 431 card.addEventListener('mouseenter', startTyping); 432 document.addEventListener('DOMContentLoaded', startTyping); 433})(); 434 435// ââ Typewriter: amazon ai-card-1 âââââââââââââââââââââââââââââââââââââââââââ 436(function () { 437 var el = document.getElementById('ca-typewriter'); 438 var card = document.getElementById('ai-card-1'); 439 if (!el || !card) return; 440 var fullText = el.dataset.text || ''; 441 var cursor = '<span class="font-medium" style="animation:caBlinkCursor 0.8s step-end infinite;border-right:2px solid #888;margin-left:1px;"> </span>'; 442 var timer = null; 443 444 function startTyping() { 445 if (timer) clearTimeout(timer); 446 var i = 0; 447 function type() { 448 el.innerHTML = fullText.substring(0, i) + cursor; 449 if (i <= fullText.length) { i++; timer = setTimeout(type, 28 + Math.random() * 22); } 450 } 451 timer = setTimeout(type, 300); 452 } 453 454 card.addEventListener('mouseenter', startTyping); 455 document.addEventListener('DOMContentLoaded', startTyping); 456})(); 457
458// ââ Typewriter: ai-ca-card (Forces) ââââââââââââââââââââââââââââââââââââââââââ 459(function () { 460 var el = document.getElementById('ai-ca-typewriter'); 461 var card = document.getElementById('ai-ca-card'); 462 if (!el || !card) return; 463 var fullText = el.getAttribute('data-tw-text') || "More Nutrition est une marque moderne et lifestyle-orientée, connue pour ses protéines multi-composants de haute qualité, arômes excellents, faibles en sucre et forte présence sur les réseaux sociaux."; 464 var cursor = '<span class="font-medium" style="animation:caBlinkCursor 0.8s step-end infinite;border-right:2px solid #888;margin-left:1px;"> </span>'; 465 var timer = null; 466 467 function startTyping() { 468 if (timer) clearTimeout(timer); 469 var i = 0; 470 function type() { 471 el.innerHTML = fullText.substring(0, i) + cursor; 472 if (i <= fullText.length) { i++; timer = setTimeout(type, 28 + Math.random() * 22); } 473 } 474 timer = setTimeout(type, 300); 475 } 476 477 card.addEventListener('mouseenter', startTyping); 478 document.addEventListener('DOMContentLoaded', startTyping); 479})(); 480 481// ââ Typewriter: ai-ca-card-2 (Faiblesses) ââââââââââââââââââââââââââââââââââââ 482(function () { 483 var el = document.getElementById('ai-ca-typewriter-2'); 484 var card = document.getElementById('ai-ca-card-2'); 485 if (!el || !card) return; 486 var fullText = el.getAttribute('data-tw-text') || "Les produits More Nutrition sont nettement plus chers (env. 1,50 ⬠par portion). La marque est critiquée pour ses produits ultra-transformés, ses nombreux additifs et ses allégations marketing non conformes."; 487 var cursor = '<span class="font-medium" style="animation:caBlinkCursor 0.8s step-end infinite;border-right:2px solid #888;margin-left:1px;"> </span>'; 488 var timer = null; 489 490 function startTyping() { 491 if (timer) clearTimeout(timer); 492 var i = 0; 493 function type() { 494 el.innerHTML = fullText.substring(0, i) + cursor; 495 if (i <= fullText.length) { i++; timer = setTimeout(type, 28 + Math.random() * 22); } 496 } 497 timer = setTimeout(type, 500); 498 } 499 500 card.addEventListener('mouseenter', startTyping); 501 document.addEventListener('DOMContentLoaded', startTyping); 502})(); 503 504// ââ AI card-2 hover z-index (ai only) ââââââââââââââââââââââââââââââââââââââââ 505(function () { 506 var card1 = document.getElementById('ai-ca-card'); 507 var card2 = document.getElementById('ai-ca-card-2'); 508 if (!card1 || !card2) return; 509 510 card2.addEventListener('mouseenter', function () { 511 card2.style.zIndex = '30'; 512 card2.style.transform = 'translateX(-8px)'; 513 card1.style.zIndex = '10'; 514 }); 515 card2.addEventListener('mouseleave', function () { 516 card2.style.zIndex = '10'; 517 card2.style.transform = ''; 518 card1.style.zIndex = '20'; 519 }); 520})(); 521 522// ââ Section 2: bubble scale-in (google only) ââââââââââââââââââââââââââââââââââ 523(function () { 524 var chart = document.getElementById('concurrence-chart'); 525 if (!chart) return; 526 var bubbles = ['b-decathlon', 'b-cdiscount', 'b-fnac', 'b-leboncoin', 'b-facebook', 'b-youtube', 'b-amazon']; 527 528 bubbles.forEach(function (id) { 529 var el = document.getElementById(id); 530 if (el) { el.style.transform = 'scale(0)'; el.style.opacity = '0'; } 531 }); 532 533 function playBubbles(delay) { 534 bubbles.forEach(function (id) { 535 var el = document.getElementById(id); 536 if (!el) return; 537 el.style.transition = 'none'; 538 el.style.transform = 'scale(0)'; 539 el.style.opacity = '0'; 540 }); 541 requestAnimationFrame(function () { 542 requestAnimationFrame(function () { 543 bubbles.forEach(function (id, i) { 544 var el = document.getElementById(id); 545 if (!el) return; 546 setTimeout(function () { 547 el.style.transition = 'transform 0.4s cubic-bezier(0.34,1.56,0.64,1), opacity 0.3s ease-out'; 548 el.style.transform = 'scale(1)'; 549 el.style.opacity = '1'; 550 }, delay + i * 110); 551 }); 552 }); 553 }); 554 } 555 556 document.addEventListener('DOMContentLoaded', function () { playBubbles(400); }); 557 chart.addEventListener('mouseenter', function () { playBubbles(0); }); 558})(); 559 560// ââ Word cloud sequential fade (ai only) ââââââââââââââââââââââââââââââââââââââ 561(function () { 562 var chart = document.getElementById('ai-concurrence-chart'); 563 if (!chart) return; 564 var words = Array.from(chart.querySelectorAll('.wc-w')); 565 var playing = false;
566 567 function playWords() { 568 if (playing) return; 569 playing = true; 570 words.forEach(function (w) { 571 w.style.transition = 'none'; 572 w.style.opacity = '0'; 573 w.style.transform = 'translateY(10px) scale(0.92)'; 574 }); 575 requestAnimationFrame(function () { 576 requestAnimationFrame(function () { 577 words.forEach(function (w, i) { 578 setTimeout(function () { 579 w.style.transition = 'opacity 0.65s cubic-bezier(0.22,1,0.36,1), transform 0.65s cubic-bezier(0.22,1,0.36,1)'; 580 w.style.opacity = '1'; 581 w.style.transform = 'translateY(0) scale(1)'; 582 if (i === words.length - 1) { 583 setTimeout(function () { playing = false; }, 700); 584 } 585 }, i * 120); 586 }); 587 }); 588 }); 589 } 590 591 new IntersectionObserver(function (entries) { 592 entries.forEach(function (entry) { 593 if (entry.isIntersecting) { playWords(); } 594 }); 595 }, { threshold: 0.25 }).observe(chart); 596 chart.addEventListener('mouseenter', playWords); 597})(); 598 599// ââ Row slide-in with opacity levels (google: onpage-chart) ââââââââââââââââââ 600(function () { 601 var rowDefs = [ 602 { id: 'row-1', opacity: '0.6' }, { id: 'row-2', opacity: '0.8' }, 603 { id: 'row-3', opacity: '1' }, { id: 'row-4', opacity: '0.8' }, 604 { id: 'row-5', opacity: '0.6' }, { id: 'row-6', opacity: '0.4' }, 605 { id: 'row-7', opacity: '0.2' }, 606 ]; 607 608 var chart = document.getElementById('onpage-chart'); 609 if (!chart) return; 610 611 rowDefs.forEach(function (r) { 612 var el = chart.querySelector('#' + r.id); 613 if (el) { el.style.opacity = '0'; el.style.transform = 'translateX(-10px)'; } 614 }); 615 616 function playRows(delay) { 617 rowDefs.forEach(function (r, i) { 618 var el = chart.querySelector('#' + r.id); 619 if (!el) return; 620 el.style.transition = 'none'; 621 el.style.opacity = '0'; 622 el.style.transform = 'translateX(-10px)'; 623 requestAnimationFrame(function () { 624 requestAnimationFrame(function () { 625 setTimeout(function () { 626 el.style.transition = 'opacity 0.35s ease-out, transform 0.35s ease-out'; 627 el.style.opacity = r.opacity; 628 el.style.transform = 'translateX(0)'; 629 }, delay + i * 75); 630 }); 631 }); 632 }); 633 } 634 635 document.addEventListener('DOMContentLoaded', function () { playRows(400); }); 636 chart.addEventListener('mouseenter', function () { playRows(0); }); 637})(); 638 639// ââ Row slide-in with opacity levels (amazon: prompt-cloud + ai-card-1) ââ 640(function () { 641 var rowDefs = [ 642 { id: 'row-1', opacity: '0.6' }, { id: 'row-2', opacity: '0.8' }, 643 { id: 'row-3', opacity: '1' }, { id: 'row-4', opacity: '0.8' }, 644 { id: 'row-5', opacity: '0.6' }, { id: 'row-6', opacity: '0.4' }, 645 { id: 'row-7', opacity: '0.2' }, 646 ]; 647 648 ['prompt-cloud', 'ai-card-1'].forEach(function (chartId) { 649 var chart = document.getElementById(chartId); 650 if (!chart) return; 651 652 rowDefs.forEach(function (r) { 653 var el = chart.querySelector('#' + r.id); 654 if (el) { el.style.opacity = '0'; el.style.transform = 'translateX(-10px)'; } 655 }); 656 657 function playRows(delay) { 658 rowDefs.forEach(function (r, i) { 659 var el = chart.querySelector('#' + r.id); 660 if (!el) return; 661 el.style.transition = 'none'; 662 el.style.opacity = '0'; 663 el.style.transform = 'translateX(-10px)'; 664 requestAnimationFrame(function () { 665 requestAnimationFrame(function () { 666 setTimeout(function () { 667 el.style.transition = 'opacity 0.35s ease-out, transform 0.35s ease-out'; 668 el.style.opacity = r.opacity; 669 el.style.transform = 'translateX(0)'; 670 }, delay + i * 75); 671 }); 672 }); 673 }); 674 } 675 676 document.addEventListener('DOMContentLoaded', function () { playRows(400); }); 677 chart.addEventListener('mouseenter', function () { playRows(0); }); 678 }); 679})(); 680 681// ââ Row slide-in with opacity levels (content-creator: prompt-chart) ââââ 682(function () { 683 var rowDefs = [ 684 { id: 'row-1', opacity: '0.6' }, { id: 'row-2', opacity: '0.8' }, 685 { id: 'row-3', opacity: '1' }, { id: 'row-4', opacity: '0.8' }, 686 { id: 'row-5', opacity: '0.6' }, { id: 'row-6', opacity: '0.4' }, 687 { id: 'row-7', opacity: '0.2' }, 688 ]; 689 690 var chart = document.getElementById('prompt-chart'); 691 if (!chart) return; 692
693 rowDefs.forEach(function (r) { 694 var el = chart.querySelector('#' + r.id); 695 if (el) { el.style.opacity = '0'; el.style.transform = 'translateX(-10px)'; } 696 }); 697 698 function playRows(delay) { 699 rowDefs.forEach(function (r, i) { 700 var el = chart.querySelector('#' + r.id); 701 if (!el) return; 702 el.style.transition = 'none'; 703 el.style.opacity = '0'; 704 el.style.transform = 'translateX(-10px)'; 705 requestAnimationFrame(function () { 706 requestAnimationFrame(function () { 707 setTimeout(function () { 708 el.style.transition = 'opacity 0.35s ease-out, transform 0.35s ease-out'; 709 el.style.opacity = r.opacity; 710 el.style.transform = 'translateX(0)'; 711 }, delay + i * 75); 712 }); 713 }); 714 }); 715 } 716 717 document.addEventListener('DOMContentLoaded', function () { playRows(400); }); 718 chart.addEventListener('mouseenter', function () { playRows(0); }); 719})(); 720 721// ââ Row slide-in (ai: ai-feature-chart) ââââââââââââââââââââââââââââââââââââââ 722(function () { 723 var chart = document.getElementById('ai-feature-chart'); 724 if (!chart) return; 725 var rows = ['row-1','row-2','row-3','row-4','row-5','row-6','row-7']; 726 727 rows.forEach(function (id) { 728 var el = document.getElementById(id); 729 if (el) { el.style.opacity = '0'; el.style.transform = 'translateX(-10px)'; } 730 }); 731 732 function playRows(delay) { 733 var els = rows.map(function (id) { return document.getElementById(id); }); 734 els.forEach(function (el) { 735 if (!el) return; 736 el.style.transition = 'none'; 737 el.style.opacity = '0'; 738 el.style.transform = 'translateX(-10px)'; 739 }); 740 requestAnimationFrame(function () { 741 requestAnimationFrame(function () { 742 els.forEach(function (el, i) { 743 if (!el) return; 744 setTimeout(function () { 745 el.style.transition = 'opacity 0.35s ease-out, transform 0.35s ease-out'; 746 el.style.opacity = '1'; 747 el.style.transform = 'translateX(0)'; 748 }, delay + i * 75); 749 }); 750 }); 751 }); 752 } 753 754 document.addEventListener('DOMContentLoaded', function () { playRows(400); }); 755 chart.addEventListener('mouseenter', function () { playRows(0); }); 756})(); 757 758// ââ Counter animation (ai: ai-onpage-chart) âââââââââââââââââââââââââââââââââââ 759(function () { 760 var container = document.getElementById('ai-onpage-chart'); 761 if (!container) return; 762 763 var DURATION = 900; 764 var animating = false; 765 var boxes = [ 766 { numId: 'ai-num-1', badgeId: 'ai-badge-1', target: 1876, type: 'decimal1', final: '187,6' }, 767 { numId: 'ai-num-2', badgeId: 'ai-badge-2', target: 2341, type: 'int_thousands', final: '2.341' }, 768 { numId: 'ai-num-3', badgeId: 'ai-badge-3', target: 823, type: 'int', final: '823' }, 769 { numId: 'ai-num-4', badgeId: 'ai-badge-4', target: 562, type: 'decimal1', final: '56,2' }, 770 ]; 771 772 function fmt(val, type) { 773 if (type === 'decimal1') { 774 return Math.floor(val / 10) + ',' + (val % 10); 775 } 776 if (type === 'int_thousands') { 777 var v = Math.round(val); 778 return v >= 1000 779 ? Math.floor(v / 1000) + '.' + (v % 1000).toString().padStart(3, '0') 780 : v.toString(); 781 } 782 return Math.round(val).toString(); 783 } 784 785 function play() { 786 if (animating) return; 787 animating = true; 788 boxes.forEach(function (b) { 789 var badge = document.getElementById(b.badgeId); 790 if (badge) { badge.style.transition = 'none'; badge.style.opacity = '0'; } 791 }); 792 var start = performance.now(); 793 function step(now) { 794 var t = Math.min((now - start) / DURATION, 1); 795 var ease = 1 - Math.pow(1 - t, 3); 796 boxes.forEach(function (b) { 797 var el = document.getElementById(b.numId); 798 if (el) el.textContent = fmt(Math.round(ease * b.target), b.type); 799 }); 800 if (t < 1) { 801 requestAnimationFrame(step); 802 } else { 803 boxes.forEach(function (b) { 804 var el = document.getElementById(b.numId); 805 var badge = document.getElementById(b.badgeId); 806 if (el) el.textContent = b.final; 807 if (badge) { badge.style.transition = 'opacity 0.3s ease-out'; badge.style.opacity = '1'; } 808 }); 809 animating = false;
810 } 811 } 812 requestAnimationFrame(step); 813 } 814 815 container.addEventListener('mouseenter', play); 816})(); 817 818// ââ Testimonials carousel (google only) âââââââââââââââââââââââââââââââââââââââ 819(function () { 820 var outer = document.getElementById('testimonials-outer'); 821 var track = document.getElementById('testimonials-track'); 822 if (!track || !outer) return; 823 var cards = Array.from(track.querySelectorAll('.t-card')); 824 var dots = Array.from(document.querySelectorAll('#testimonials-dots .t-dot')); 825 var n = cards.length; 826 var active = 1; 827 var cardW = 560; 828 var carouselTimer = null; 829 830 function scheduleNext() { 831 clearTimeout(carouselTimer); 832 carouselTimer = setTimeout(function () { go(active + 1); }, 5000); 833 } 834 835 function calcCardW() { 836 var ow = outer.offsetWidth; 837 cardW = Math.min(560, Math.max(300, ow * 0.68)); 838 cards.forEach(function (c) { c.style.width = cardW + 'px'; }); 839 } 840 841 function updateCarousel() { 842 var ow = outer.offsetWidth; 843 var offset = (ow - cardW) / 2 - active * cardW; 844 track.style.transform = 'translateX(' + offset + 'px)'; 845 cards.forEach(function (c, i) { 846 c.classList.toggle('is-center', i === active); 847 c.classList.toggle('is-side', i !== active); 848 }); 849 dots.forEach(function (d, i) { d.classList.toggle('active', i === active); d.setAttribute('aria-selected', i === active ? 'true' : 'false'); }); 850 } 851 852 function go(idx) { 853 active = ((idx % n) + n) % n; 854 updateCarousel(); 855 scheduleNext(); 856 } 857 858 track.addEventListener('transitionend', scheduleNext); 859 cards.forEach(function (c, i) { 860 c.addEventListener('click', function () { if (i !== active) go(i); }); 861 }); 862 dots.forEach(function (d, i) { 863 d.addEventListener('click', function () { go(i); }); 864 }); 865 window.addEventListener('resize', function () { calcCardW(); updateCarousel(); }); 866 867 function init() { calcCardW(); updateCarousel(); scheduleNext(); } 868 if (document.readyState === 'loading') { 869 document.addEventListener('DOMContentLoaded', init); 870 } else { 871 init(); 872 } 873})(); 874 875// ââ AI button border rotation (ai only) âââââââââââââââââââââââââââââââââââââââ 876(function () { 877 var buttons = document.querySelectorAll('.ai-button'); 878 if (!buttons.length) return; 879 var animRunning = false; 880 var angle = 0; 881 var lastTime = 0; 882 var duration = 2500; 883 884 function step(timestamp) { 885 if (!animRunning) return; 886 if (!lastTime) lastTime = timestamp; 887 angle = (angle + ((timestamp - lastTime) / duration) * 360) % 360; 888 lastTime = timestamp; 889 buttons.forEach(function (btn) { 890 if (!btn.matches(':hover')) { 891 btn.style.setProperty('--ai-border-angle', angle + 'deg'); 892 } 893 }); 894 requestAnimationFrame(step); 895 } 896 897 new IntersectionObserver(function (entries) { 898 var visible = entries.some(function (e) { return e.isIntersecting; }); 899 if (visible && !animRunning) { 900 animRunning = true; 901 lastTime = 0; 902 requestAnimationFrame(step); 903 } else if (!visible) { 904 animRunning = false; 905 } 906 }, { threshold: 0.1 }).observe(buttons[0]); 907 buttons.forEach(function (btn) { 908 new IntersectionObserver(function (entries) { 909 var visible = entries.some(function (e) { return e.isIntersecting; }); 910 if (visible && !animRunning) { animRunning = true; lastTime = 0; requestAnimationFrame(step); } 911 else if (!visible && !Array.from(buttons).some(function (b) { return b.getBoundingClientRect().top < window.innerHeight; })) { animRunning = false; } 912 }, { threshold: 0.1 }).observe(btn); 913 }); 914})(); 915 916// ââ Sticky subnav: google (sticky-subnav / features-sentinel) âââââââââââââââââ 917(function () { 918 var subnav = document.getElementById('sticky-subnav'); 919 var sentinel = document.getElementById('features-sentinel'); 920 if (!subnav || !sentinel) return; 921 922 function show() { 923 subnav.style.transform = 'translateY(0)'; 924 subnav.style.opacity = '1'; 925 subnav.style.pointerEvents = 'auto'; 926 subnav.removeAttribute('inert'); 927 } 928 function hide() { 929 subnav.style.transform = 'translateY(-100%)'; 930 subnav.style.opacity = '0'; 931 subnav.style.pointerEvents = 'none'; 932 subnav.setAttribute('inert', ''); 933 } 934 function check() { 935 sentinel.getBoundingClientRect().top <= 120 ? show() : hide(); 936 } 937 938 window.addEventListener('scroll', check, { passive: true }); 939 check(); 940})(); 941
942// ââ Sticky subnav: amazon (amz-sticky-subnav / amz-features-sentinel) âââââââââ 943(function () { 944 var subnav = document.getElementById('amz-sticky-subnav'); 945 var sentinel = document.getElementById('amz-features-sentinel'); 946 if (!subnav || !sentinel) return; 947 948 function show() { 949 subnav.style.transform = 'translateY(0)'; 950 subnav.style.opacity = '1'; 951 subnav.style.pointerEvents = 'auto'; 952 subnav.removeAttribute('inert'); 953 } 954 function hide() { 955 subnav.style.transform = 'translateY(-100%)'; 956 subnav.style.opacity = '0'; 957 subnav.style.pointerEvents = 'none'; 958 subnav.setAttribute('inert', ''); 959 } 960 function check() { 961 sentinel.getBoundingClientRect().top <= 120 ? show() : hide(); 962 } 963 964 window.addEventListener('scroll', check, { passive: true }); 965 check(); 966})(); 967 968// ââ Sticky subnav: ai (ai-sticky-subnav / ai-features-sentinel, uses inert) âââ 969(function () { 970 var subnav = document.getElementById('ai-sticky-subnav'); 971 var sentinel = document.getElementById('ai-features-sentinel'); 972 if (!subnav || !sentinel) return; 973 974 function show() { 975 subnav.style.transform = 'translateY(0)'; 976 subnav.style.opacity = '1'; 977 subnav.style.pointerEvents = 'auto'; 978 subnav.removeAttribute('inert'); 979 } 980 function hide() { 981 subnav.style.transform = 'translateY(-100%)'; 982 subnav.style.opacity = '0'; 983 subnav.style.pointerEvents = 'none'; 984 subnav.setAttribute('inert', ''); 985 } 986 function check() { 987 sentinel.getBoundingClientRect().top <= 120 ? show() : hide(); 988 } 989 990 window.addEventListener('scroll', check, { passive: true }); 991 check(); 992})(); 993 994// ââ Shared page init: sticky-subnav aria-hidden, main-nav move, tilt, testimonials ââ 995(function() { 996 // inert is set in HTML and managed via show()/hide() above 997 998 // Move global #main-nav into #heroSection as first child (skip if inline script already did it) 999 var nav = document.getElementById('main-nav'); 1000 var hero = document.getElementById('heroSection'); 1001 if (nav && hero && hero.firstChild !== nav) { 1002 hero.insertBefore(nav, hero.firstChild); 1003 } 1004 1005 document.addEventListener('DOMContentLoaded', function() { 1006 var track = document.getElementById('testimonials-track'); 1007 1008 var cards = Array.from(document.querySelectorAll('.feature-row .glasrand-outer, .feature-row-reverse .glasrand-outer, .feature-row .glasrand-outer-dark, .feature-row-reverse .glasrand-outer-dark')).filter(function(card) { 1009 var main = card.closest('main'); 1010 return !main || main.hasAttribute('data-tilt-sections'); // Tilt-Hover im Hero immer, in Sections nur auf den mit data-tilt-sections markierten Hub-Seiten (google/amazon/ai) 1011 }); 1012 cards.forEach(function(card) { 1013 var rafId = null; 1014 var lastE = null; 1015 card.addEventListener('mouseenter', function() { 1016 card.style.willChange = 'transform'; 1017 card.style.animationPlayState = 'paused'; 1018 card.style.transition = 'transform 0.12s ease, box-shadow 0.2s ease'; 1019 }); 1020 card.addEventListener('mousemove', function(e) { 1021 if (window.innerWidth < 672) return; 1022 lastE = e; 1023 if (rafId) return; 1024 rafId = requestAnimationFrame(function() { 1025 rafId = null; 1026 if (!lastE) return; 1027 var rect = card.getBoundingClientRect(); 1028 var cx = rect.left + rect.width / 2; 1029 var cy = rect.top + rect.height / 2; 1030 var dx = (lastE.clientX - cx) / (rect.width / 2); 1031 var dy = (lastE.clientY - cy) / (rect.height / 2); 1032 var maxDeg = 7; 1033 var rotX = (-dy * maxDeg).toFixed(2); 1034 var rotY = (dx * maxDeg).toFixed(2); 1035 card.style.transform = 'perspective(700px) rotateX(' + rotX + 'deg) rotateY(' + rotY + 'deg) scale(1.025)'; 1036 }); 1037 }); 1038 card.addEventListener('mouseleave', function() { 1039 lastE = null; 1040 card.style.transition = 'transform 0.45s ease, box-shadow 0.3s ease'; 1041 card.style.transform = 'perspective(700px) rotateX(0deg) rotateY(0deg) scale(1)'; 1042 setTimeout(function() { 1043 card.style.willChange = ''; 1044 card.style.animationPlayState = ''; 1045 card.style.transition = ''; 1046 card.style.transform = ''; 1047 }, 450); 1048 }); 1049 }); 1050
1051 // Hero card tilt (google/amazon hero cards) 1052 [{ id: 'cc-hero-card-1', baseRotate: 3, baseZ: '1' }, 1053 { id: 'cc-hero-card-2', baseRotate: -1.5, baseZ: '2' }].forEach(function(cfg) { 1054 var hCard = document.getElementById(cfg.id); 1055 if (!hCard) return; 1056 var hRaf = null; 1057 var hLastE = null; 1058 hCard.addEventListener('mousemove', function(e) { 1059 if (window.innerWidth < 672) return; 1060 hLastE = e; 1061 if (hRaf) return; 1062 hRaf = requestAnimationFrame(function() { 1063 hRaf = null; 1064 if (!hLastE) return; 1065 var rect = hCard.getBoundingClientRect(); 1066 var dx = (hLastE.clientX - (rect.left + rect.width / 2)) / (rect.width / 2); 1067 var dy = (hLastE.clientY - (rect.top + rect.height / 2)) / (rect.height / 2); 1068 hCard.style.transition = 'transform 0.08s ease-out'; 1069 hCard.style.transform = 'rotate(' + cfg.baseRotate + 'deg) perspective(700px) rotateX(' + (-dy * 12) + 'deg) rotateY(' + (dx * 12) + 'deg) scale(1.04)'; 1070 hCard.style.zIndex = '4'; 1071 }); 1072 }); 1073 hCard.addEventListener('mouseleave', function() { 1074 hLastE = null; 1075 hCard.style.transition = 'transform 0.45s cubic-bezier(0.23,1,0.32,1)'; 1076 hCard.style.transform = 'rotate(' + cfg.baseRotate + 'deg)'; 1077 hCard.style.zIndex = cfg.baseZ; 1078 }); 1079 }); 1080 1081// ââ Hero card 3D tilt (api / technologie-analyse) ââââââââââââââââââââââââââââ 1082(function () { 1083 [{ id: 'bb-hero-card-1', baseRotate: 3, baseZ: '1' }, 1084 { id: 'bb-hero-card-2', baseRotate: -1.5, baseZ: '2' }].forEach(function(cfg) { 1085 var hCard = document.getElementById(cfg.id); 1086 if (!hCard) return; 1087 var hRaf = null, hLastE = null; 1088 hCard.addEventListener('mousemove', function(e) { 1089 hLastE = e; 1090 if (hRaf) return; 1091 hRaf = requestAnimationFrame(function() { 1092 hRaf = null; 1093 if (!hLastE) return; 1094 var r = hCard.getBoundingClientRect(); 1095 var dx = (hLastE.clientX - (r.left + r.width / 2)) / (r.width / 2); 1096 var dy = (hLastE.clientY - (r.top + r.height / 2)) / (r.height / 2); 1097 hCard.style.transition = 'transform 0.08s ease-out'; 1098 hCard.style.transform = 'rotate(' + cfg.baseRotate + 'deg) perspective(700px) rotateX(' + (-dy * 12) + 'deg) rotateY(' + (dx * 12) + 'deg) scale(1.04)'; 1099 hCard.style.zIndex = '4'; 1100 }); 1101 }); 1102 hCard.addEventListener('mouseleave', function() { 1103 hLastE = null; 1104 hCard.style.transition = 'transform 0.45s cubic-bezier(0.23,1,0.32,1)'; 1105 hCard.style.transform = 'rotate(' + cfg.baseRotate + 'deg)'; 1106 hCard.style.zIndex = cfg.baseZ; 1107 }); 1108 }); 1109})(); 1110 1111 // will-change for testimonials only during animation 1112 if (track) { 1113 var observer = new MutationObserver(function() { 1114 track.style.willChange = 'transform'; 1115 clearTimeout(track._wcTimer); 1116 track._wcTimer = setTimeout(function() { 1117 track.style.willChange = 'auto'; 1118 }, 600); 1119 }); 1120 observer.observe(track, { attributes: true, attributeFilter: ['style'] }); 1121 } 1122 }); 1123})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.