1(function () { 2 'use strict'; 3 4 var WORD_W = 377; 5 var WORD_H = 63; 6 var WORD_CX = 188.5; 7 var WORD_CY = 31.5; 8 9 var DEFAULT_CONFIG = { 10 slideIn: { 11 startX: 420, 12 duration: 0.87, 13 stagger: 0.055, 14 ease: 'sine.out', 15 order: ['M1', 'U', 'L', 'T', 'I', 'C', 'M2', 'A'], 16 }, 17 readyTimeoutMs: 6000, 18 minHoldMs: 0, 19 scale: { 20 start: 0.13, 21 end: 0.87, 22 duration: 0.29, 23 ease: 'expo.inOut', 24 centerY: 0.5, 25 }, 26 whiteFade: { 27 fromOpacity: 1, 28 toOpacity: 0, 29 duration: 0.35, 30 ease: 'power1.out', 31 offset: 0.1, 32 }, 33 holdAfterScaleMs: 400, 34 zoom: { 35 duration: 0.26, 36 ease: 'expo.in', 37 endScale: 500, 38 /** Letter used as zoom pivot (matches data-letter on SVG paths). */ 39 pivotLetter: 'I', 40 /** SVG-unit nudge right for I outline counter (between ~0.5 too left and ~2 toward C). */ 41 cOffsetX: 1, 42 cOffsetY: 0, 43 }, 44 reducedMotionFadeMs: 300, 45 debug: false, 46 }; 47 48 function deepClone(o) { 49 return JSON.parse(JSON.stringify(o)); 50 } 51 52 function deepMerge(base, patch) { 53 if (!patch || typeof patch !== 'object') return base; 54 Object.keys(patch).forEach(function (k) { 55 var v = patch[k]; 56 if (v && typeof v === 'object' && !Array.isArray(v) && typeof v !== 'number') { 57 if (!base[k]) base[k] = {}; 58 deepMerge(base[k], v); 59 } else { 60 base[k] = v; 61 } 62 }); 63 return base; 64 } 65 66 function setByPath(obj, path, value) { 67 var parts = path.split('.'); 68 var cur = obj; 69 for (var i = 0; i < parts.length - 1; i++) { 70 var p = parts[i]; 71 if (!cur[p]) cur[p] = {}; 72 cur = cur[p]; 73 } 74 cur[parts[parts.length - 1]] = value; 75 } 76 77 function coerceVal(s) { 78 if (s === 'true') return true; 79 if (s === 'false') return false; 80 var n = parseFloat(s); 81 if (!isNaN(n) && String(n) === s) return n; 82 return s; 83 } 84 85 function parseIntroQueryString() { 86 try { 87 var params = new URLSearchParams(window.location.search); 88 var raw = params.get('intro'); 89 if (!raw) return; 90 raw.split(',').forEach(function (pair) { 91 var eq = pair.indexOf('='); 92 if (eq === -1) return; 93 var path = pair.slice(0, eq).trim(); 94 var val = coerceVal(pair.slice(eq + 1).trim()); 95 if (path === 'debug') { 96 window.homeIntro.CONFIG.debug = val === true || val === 1 || val === '1'; 97 return; 98 } 99 setByPath(window.homeIntro.CONFIG, path, val); 100 }); 101 } catch (e) { /* ignore */ } 102 } 103 104 var easeStringCache = {}; 105 var easeIdSeq = 0; 106 107 function resolveEase(str) { 108 if (!str || str === 'none') return 'none'; 109 if (easeStringCache[str]) return easeStringCache[str]; 110 if (typeof CustomEase === 'undefined') { 111 easeStringCache[str] = str; 112 return str; 113 } 114 if (str.indexOf('cubic(') === 0) { 115 var inner = str.slice(6, -1).replace(/\s+/g, ''); 116 var nums = inner.split(',').map(parseFloat); 117 if (nums.length === 4 && nums.every(function (x) { return !isNaN(x); })) { 118 var id = 'mcHiCubic_' + (easeIdSeq++); 119 try { 120 CustomEase.create(id, 'M0,0 C' + nums[0] + ',' + nums[1] + ' ' + nums[2] + ',' + nums[3] + ' 1,1'); 121 easeStringCache[str] = id; 122 return id; 123 } catch (e) { /* fall through */ } 124 } 125 } 126 if (str.charAt(0) === 'M' || str.indexOf('M0,0') === 0) { 127 var pathId = 'mcHiPath_' + (easeIdSeq++); 128 try { 129 CustomEase.create(pathId, str); 130 easeStringCache[str] = pathId; 131 return pathId; 132 } catch (e2) { /* fall through */ } 133 } 134 easeStringCache[str] = str; 135 return str; 136 } 137 138 var activeTimeline = null; 139 var overlayNode = null; 140 var introStartMs = 0; 141 142 function sliceScale(svg) { 143 var r = svg.getBoundingClientRect(); 144 var vb = svg.viewBox.baseVal; 145 if (!vb || !vb.width) return Math.max(r.width / 100, r.height / 100); 146 return Math.max(r.width / vb.width, r.height / vb.height); 147 } 148 149 function wordScaleForFraction(svg, fraction) { 150 var sc = sliceScale(svg); 151 var targetPx = fraction * window.innerWidth; 152 return targetPx / (WORD_W * sc); 153 } 154 155 var LETTER_ANCHOR_X = { 156 M1: 36.5, 157 U: 113, 158 L: 138.5, 159 T: 156, 160 I: 189.35, 161 C: 228, 162 M2: 277, 163 A: 335, 164 }; 165 166 /** Prefer clip-free box map from measureLetterBoxesFromVisibleClone (matches slide clips). */ 167 function pivotCenterXFromLetter(boxMap, pivotKey, wrap) { 168 var b = boxMap && boxMap[pivotKey]; 169 if (b && b.width > 0 && b.height > 0) { 170 return b.x + b.width / 2; 171 } 172 var el = wrap && wrap.querySelector('[data-letter="' + pivotKey + '"]'); 173 if (el) {
174 try { 175 var bb = el.getBBox(); 176 if (bb.width > 0 && bb.height > 0) { 177 return bb.x + bb.width / 2; 178 } 179 } catch (eBb) { /* ignore */ } 180 } 181 var ax = LETTER_ANCHOR_X[pivotKey]; 182 if (typeof ax === 'number') return ax; 183 return WORD_CX; 184 } 185 186 function responsiveOverrides() { 187 var w = window.innerWidth; 188 if (w > 1024) return {}; 189 if (w > 768) { 190 return { 191 scaleEnd: 1, 192 cOffsetX: 1, 193 endScaleMin: 800, 194 }; 195 } 196 return { 197 scaleStart: 0.4, 198 scaleEnd: .9, 199 cOffsetX: .6, 200 endScaleMin: 1000, 201 }; 202 } 203 204 /** Zoom multiplier so the wordmark grows past viewport bounds (avoids an end-of-intro opacity cheat). */ 205 function zoomScaleToClearViewport(svg, S1, endScaleMin) { 206 var cfg = window.homeIntro.CONFIG; 207 var r = svg.getBoundingClientRect(); 208 var sc = sliceScale(svg); 209 var halfWordPx = WORD_W * 0.52 * S1 * sc; 210 if (halfWordPx < 6) halfWordPx = 6; 211 var diag = Math.hypot(r.width, r.height); 212 var zMin = (diag * 0.62) / halfWordPx;
213 var floor = endScaleMin != null ? endScaleMin : (cfg.zoom.endScale || 30); 214 return Math.max(floor, zMin); 215 } 216 217 function buildBaseMatrix(S, centerYFrac) { 218 var cy = centerYFrac * 100; 219 return new DOMMatrix() 220 .translate(50, cy) 221 .scale(S, S) 222 .translate(-WORD_CX, -WORD_CY); 223 } 224 225 function matrixToAttr(m) { 226 return 'matrix(' + m.a + ',' + m.b + ',' + m.c + ',' + m.d + ',' + m.e + ',' + m.f + ')'; 227 } 228 229 /** 230 * Geometry inside defs/mask often reports getBBox() as 0Ã0; clone into the visible svg subtree to measure. 231 */ 232 function measureLetterBoxesFromVisibleClone(group, svg) { 233 var map = {}; 234 if (!group || !svg) return map; 235 var clone = group.cloneNode(true); 236 clone.removeAttribute('id'); 237 var toUnclip = clone.querySelectorAll('[clip-path]'); 238 for (var u = 0; u < toUnclip.length; u++) { 239 toUnclip[u].removeAttribute('clip-path'); 240 } 241 clone.setAttribute('visibility', 'hidden'); 242 clone.setAttribute('pointer-events', 'none'); 243 svg.appendChild(clone); 244 try { 245 var paths = clone.querySelectorAll('[data-letter]'); 246 for (var i = 0; i < paths.length; i++) { 247 var p = paths[i]; 248 var k = p.getAttribute('data-letter'); 249 if (!k) continue; 250 map[k] = p.getBBox(); 251 } 252 } finally { 253 svg.removeChild(clone); 254 } 255 return map; 256 } 257 258 /** 259 * Per-letter clip rects; glyph translates while clip stays fixed in parent coords. 260 * boxMap from measureLetterBoxesFromVisibleClone (defs/mask getBBox is unreliable in browsers). 261 */ 262 function applyLetterClips(group, defs, prefix, boxMap) { 263 if (!group || !defs) return; 264 var pad = 1.25; 265 boxMap = boxMap || {}; 266 var letters = group.querySelectorAll('[data-letter]'); 267 for (var i = 0; i < letters.length; i++) { 268 var el = letters[i]; 269 var key = el.getAttribute('data-letter'); 270 if (!key) continue; 271 var bb = boxMap[key] || el.getBBox(); 272 if (!(bb.width > 0 && bb.height > 0)) continue; 273 var clipId = prefix + '-clip-' + key; 274 var cp = document.createElementNS('http://www.w3.org/2000/svg', 'clipPath'); 275 cp.setAttribute('id', clipId); 276 cp.setAttribute('clipPathUnits', 'userSpaceOnUse'); 277 var r = document.createElementNS('http://www.w3.org/2000/svg', 'rect'); 278 r.setAttribute('x', String(bb.x - pad)); 279 r.setAttribute('y', String(bb.y - pad)); 280 r.setAttribute('width', String(bb.width + 2 * pad)); 281 r.setAttribute('height', String(bb.height + 2 * pad)); 282 cp.appendChild(r); 283 defs.appendChild(cp); 284 /* Clip on parent <g>: if clip-path sits on the same node GSAP translates, the clip moves with the glyph (no reveal). */ 285 var clipG = document.createElementNS('http://www.w3.org/2000/svg', 'g'); 286 clipG.setAttribute('clip-path', 'url(#' + clipId + ')'); 287 var par = el.parentNode; 288 if (par) { 289 par.insertBefore(clipG, el); 290 clipG.appendChild(el); 291 } 292 } 293 } 294 295 function hideMcTransitionOverlay() { 296 var ov = document.getElementById('transition-overlay'); 297 if (!ov) return; 298 if (typeof gsap !== 'undefined') { 299 gsap.set(ov, { autoAlpha: 0, pointerEvents: 'none' }); 300 } 301 ov.style.display = 'none'; 302 } 303 304 function mountOverlayFromTemplate() { 305 var tpl = document.getElementById('home-intro-overlay-source'); 306 if (!tpl || !tpl.content) return null; 307 var node = tpl.content.firstElementChild.cloneNode(true); 308 document.body.appendChild(node); 309 return node; 310 } 311 312 function removeBootLayerNextFrame() { 313 requestAnimationFrame(function () { 314 document.documentElement.classList.remove('mc-home-intro-route'); 315 }); 316 } 317 318 function stopLenis() { 319 var L = window.__marketingLenis; 320 if (L && typeof L.stop === 'function') { 321 try { 322 L.stop(); 323 } catch (e) { /* ignore */ } 324 } 325 } 326 327 function startLenis() { 328 var L = window.__marketingLenis; 329 if (L && typeof L.start === 'function') { 330 try { 331 L.start(); 332 } catch (e) { /* ignore */ } 333 } 334 if (typeof window.marketingLenisEnsureRunning === 'function') { 335 window.marketingLenisEnsureRunning(); 336 } 337 } 338 339 function raceTimeout(promise, ms) { 340 if (!promise || typeof promise.then !== 'function') return Promise.resolve(); 341 return Promise.race([ 342 promise, 343 new Promise(function (resolve) { 344 setTimeout(resolve, ms); 345 }), 346 ]); 347 } 348 349 function sleep(ms) { 350 return new Promise(function (r) { 351 setTimeout(r, ms); 352 }); 353 } 354 355 function getHeroImageUrl(explicit) { 356 if (explicit) return explicit; 357 var img = document.getElementById('hero-intro-image'); 358 return img ? img.src || img.getAttribute('src') : ''; 359 } 360 361 function diffConfig(current, defaults) { 362 var out = {}; 363 function walk(c, d, prefix) {
364 Object.keys(c).forEach(function (k) { 365 var ck = c[k]; 366 var dk = d[k]; 367 var path = prefix ? prefix + '.' + k : k; 368 if (ck && typeof ck === 'object' && !Array.isArray(ck) && dk && typeof dk === 'object' && !Array.isArray(dk)) { 369 walk(ck, dk, path); 370 } else if (JSON.stringify(ck) !== JSON.stringify(dk)) { 371 setByPath(out, path, ck); 372 } 373 }); 374 } 375 walk(current, defaults, ''); 376 return out; 377 } 378 379 function encodeIntroParam(diff) { 380 var pairs = []; 381 function flatten(o, prefix) { 382 Object.keys(o).forEach(function (k) { 383 var v = o[k]; 384 var p = prefix ? prefix + '.' + k : k; 385 if (v && typeof v === 'object' && !Array.isArray(v)) { 386 flatten(v, p); 387 } else { 388 pairs.push(p + '=' + String(v)); 389 } 390 }); 391 } 392 flatten(diff, ''); 393 return pairs.join(','); 394 } 395 396 var EASE_OPTIONS = [ 397 'none', 398 'power1.in', 'power1.out', 'power1.inOut', 399 'power2.in', 'power2.out', 'power2.inOut', 400 'power3.in', 'power3.out', 'power3.inOut', 401 'power4.in', 'power4.out', 'power4.inOut', 402 'expo.in', 'expo.out', 'expo.inOut', 403 'circ.in', 'circ.out', 'circ.inOut', 404 'sine.in', 'sine.out', 'sine.inOut', 405 'back.in', 'back.out', 'back.inOut', 406 'elastic.out(1,0.3)', 407 'bounce.out', 408 ]; 409 410 function buildDebugPanel() { 411 if (document.getElementById('home-intro-debug-panel')) return; 412 var cfg = window.homeIntro.CONFIG; 413 var panel = document.createElement('div'); 414 panel.id = 'home-intro-debug-panel'; 415 panel.setAttribute('role', 'region'); 416 panel.setAttribute('aria-label', 'Home intro tuning'); 417 418 function addRange(label, path, min, max, step) { 419 var wrap = document.createElement('div'); 420 var lab = document.createElement('label'); 421 lab.textContent = label; 422 var input = document.createElement('input'); 423 input.type = 'range'; 424 input.min = min; 425 input.max = max; 426 input.step = step; 427 input.value = String(evalPath(cfg, path)); 428 input.addEventListener('change', function () { 429 setByPath(cfg, path, parseFloat(input.value)); 430 }); 431 wrap.appendChild(lab); 432 wrap.appendChild(input); 433 panel.appendChild(wrap); 434 } 435 436 function evalPath(obj, path) { 437 return path.split('.').reduce(function (a, k) { return a[k]; }, obj); 438 } 439 440 function addEase(label, path) { 441 var wrap = document.createElement('div'); 442 var lab = document.createElement('label'); 443 lab.textContent = label; 444 var sel = document.createElement('select'); 445 EASE_OPTIONS.forEach(function (e) { 446 var o = document.createElement('option'); 447 o.value = e; 448 o.textContent = e; 449 sel.appendChild(o); 450 }); 451 var optCustom = document.createElement('option'); 452 optCustom.value = '__custom'; 453 optCustom.textContent = 'Customâ¦'; 454 sel.appendChild(optCustom); 455 var cur = evalPath(cfg, path); 456 if (EASE_OPTIONS.indexOf(cur) >= 0) sel.value = cur; 457 else sel.value = '__custom'; 458 var ta = document.createElement('textarea'); 459 ta.placeholder = 'CustomEase path or cubic(0.2,0,0,1)'; 460 if (sel.value === '__custom') ta.value = cur; 461 ta.style.display = sel.value === '__custom' ? 'block' : 'none'; 462 sel.addEventListener('change', function () { 463 if (sel.value === '__custom') { 464 ta.style.display = 'block'; 465 } else { 466 ta.style.display = 'none'; 467 setByPath(cfg, path, sel.value); 468 } 469 }); 470 ta.addEventListener('change', function () { 471 setByPath(cfg, path, ta.value.trim()); 472 }); 473 wrap.appendChild(lab); 474 wrap.appendChild(sel); 475 wrap.appendChild(ta); 476 panel.appendChild(wrap); 477 } 478 479 var h1 = document.createElement('strong'); 480 h1.textContent = 'Slide-in'; 481 panel.appendChild(h1); 482 addRange('duration', 'slideIn.duration', 0.1, 2, 0.01); 483 addRange('stagger', 'slideIn.stagger', 0, 0.4, 0.005); 484 addRange('startX', 'slideIn.startX', 60, 800, 10); 485 addEase('ease', 'slideIn.ease'); 486 487 var h2 = document.createElement('strong'); 488 h2.textContent = 'Scale'; 489 panel.appendChild(h2); 490 addRange('duration', 'scale.duration', 0.2, 3, 0.01); 491 addRange('start', 'scale.start', 0.05, 0.5, 0.01); 492 addRange('end', 'scale.end', 0.6, 1.5, 0.01); 493 addRange('centerY', 'scale.centerY', 0.2, 0.8, 0.01); 494 addEase('ease', 'scale.ease'); 495 496 var h3 = document.createElement('strong'); 497 h3.textContent = 'White fade'; 498 panel.appendChild(h3); 499 addRange('duration', 'whiteFade.duration', 0.1, 2, 0.01); 500 addRange('offset', 'whiteFade.offset', -0.5, 1, 0.01); 501 addEase('ease', 'whiteFade.ease'); 502 503 var h4 = document.createElement('strong'); 504 h4.textContent = 'Hold ms'; 505 panel.appendChild(h4); 506 addRange('holdAfterScaleMs', 'holdAfterScaleMs', 0, 2000, 25); 507 508 var h5 = document.createElement('strong'); 509 h5.textContent = 'Zoom'; 510 panel.appendChild(h5); 511 addRange('duration', 'zoom.duration', 0.2, 3, 0.01); 512 addRange('endScale', 'zoom.endScale', 5, 80, 1); 513 addRange('cOffsetX', 'zoom.cOffsetX', -50, 50, 0.5); 514 addRange('cOffsetY', 'zoom.cOffsetY', -50, 50, 0.5); 515 addEase('ease', 'zoom.ease'); 516 517 var btnRow = document.createElement('div'); 518 [['Replay', function () { window.homeIntro.replay(); }], 519 ['Copy URL', function () { 520 var diff = diffConfig(window.homeIntro.CONFIG, deepClone(DEFAULT_CONFIG)); 521 var enc = encodeURIComponent(encodeIntroParam(diff)); 522 var u = location.origin + location.pathname + '?intro=' + enc; 523 if (navigator.clipboard && navigator.clipboard.writeText) { 524 navigator.clipboard.writeText(u); 525 } 526 }], 527 ['Reset', function () { 528 window.homeIntro.resetConfig(); 529 }], 530 ['Export JSON', function () { 531 var diff = diffConfig(window.homeIntro.CONFIG, deepClone(DEFAULT_CONFIG)); 532 var ta2 = document.createElement('textarea'); 533 ta2.value = JSON.stringify(diff, null, 2); 534 ta2.style.width = '100%'; 535 ta2.style.minHeight = '80px'; 536 ta2.style.marginTop = '8px'; 537 panel.appendChild(ta2); 538 }], 539 ].forEach(function (pair) { 540 var b = document.createElement('button'); 541 b.type = 'button'; 542 b.textContent = pair[0]; 543 b.addEventListener('click', pair[1]); 544 btnRow.appendChild(b); 545 }); 546 panel.appendChild(btnRow); 547 548 document.body.appendChild(panel); 549 550 document.addEventListener('keydown', function escClose(ev) { 551 if (ev.key === 'Escape' && panel.parentNode) { 552 panel.parentNode.removeChild(panel); 553 document.removeEventListener('keydown', escClose); 554 } 555 }); 556 } 557 558 function maybeShowDebugPanel() { 559 var cfg = window.homeIntro.CONFIG; 560 try { 561 var qs = new URLSearchParams(window.location.search); 562 if (qs.get('intro') === 'debug=0') { 563 localStorage.removeItem('homeIntroDebug'); 564 return; 565 } 566 localStorage.removeItem('homeIntroDebug'); 567 } catch (e) { /* ignore */ } 568 if (cfg.debug) { 569 buildDebugPanel(); 570 } 571 } 572 573 function cleanupIntro(opts) { 574 opts = opts || {}; 575 if (activeTimeline) {
576 try { 577 activeTimeline.kill(); 578 } catch (e) { /* ignore */ } 579 activeTimeline = null; 580 } 581 var letters = document.querySelectorAll( 582 '#mc-letters-wrap [data-letter], #mc-letters-wrap-stencil [data-letter]' 583 ); 584 if (typeof gsap !== 'undefined') { 585 gsap.killTweensOf(letters); 586 gsap.killTweensOf('#mc-white, #mc-bg, #mc-letters-wrap, #mc-letters-wrap-stencil'); 587 } 588 if (overlayNode && overlayNode.parentNode) { 589 overlayNode.parentNode.removeChild(overlayNode); 590 } 591 overlayNode = null; 592 document.documentElement.classList.remove('home-intro-active'); 593 document.documentElement.classList.remove('mc-home-intro-route'); 594 if (typeof window.__marketingSetPageChromeInert === 'function') { 595 window.__marketingSetPageChromeInert(false); 596 } 597 startLenis(); 598 window.dispatchEvent(new CustomEvent('home-intro-complete')); 599 window._homeIntroCleanup = null; 600 } 601 602 function runFullIntro(opts) { 603 var readyPromise = opts.readyPromise || Promise.resolve(); 604 605 hideMcTransitionOverlay(); 606 stopLenis(); 607 608 overlayNode = mountOverlayFromTemplate(); 609 if (!overlayNode) { 610 cleanupIntro(); 611 startLenis(); 612 return Promise.resolve(); 613 } 614 615 gsap.set(overlayNode, { autoAlpha: 1 }); 616 617 removeBootLayerNextFrame(); 618 document.documentElement.classList.add('home-intro-active'); 619 if (typeof window.__marketingSetPageChromeInert === 'function') { 620 window.__marketingSetPageChromeInert(true); 621 } 622 623 var svg = overlayNode; 624 var wrap = svg.querySelector('#mc-letters-wrap'); 625 var wrapStencil = svg.querySelector('#mc-letters-wrap-stencil'); 626 var mcWhite = svg.querySelector('#mc-white'); 627 var mcBg = svg.querySelector('#mc-bg'); 628 var cfg = window.homeIntro.CONFIG; 629 630 var lettersOrdered = cfg.slideIn.order.map(function (key) { 631 return wrap.querySelector('[data-letter="' + key + '"]'); 632 }).filter(Boolean); 633 634 var lettersStencilOrdered = cfg.slideIn.order.map(function (key) { 635 return wrapStencil && wrapStencil.querySelector('[data-letter="' + key + '"]'); 636 }).filter(Boolean); 637 638 var defs = svg.querySelector('defs'); 639 640 lettersOrdered.concat(lettersStencilOrdered).forEach(function (el) { 641 el.removeAttribute('transform'); 642 }); 643 644 var boxMapMain = measureLetterBoxesFromVisibleClone(wrap, svg); 645 var boxMapStencil = wrapStencil ? measureLetterBoxesFromVisibleClone(wrapStencil, svg) : {}; 646 647 if (defs) { 648 applyLetterClips(wrap, defs, 'mc-hi', boxMapMain); 649 if (wrapStencil) applyLetterClips(wrapStencil, defs, 'mc-hi-s', boxMapStencil); 650 } 651 652 lettersOrdered.concat(lettersStencilOrdered).forEach(function (el) { 653 gsap.set(el, { x: cfg.slideIn.startX }); 654 }); 655 656 var initOverrides = responsiveOverrides(); 657 var scaleStart = initOverrides.scaleStart != null ? initOverrides.scaleStart : cfg.scale.start; 658 var S0 = wordScaleForFraction(svg, scaleStart); 659 var stencilM = matrixToAttr(buildBaseMatrix(S0, cfg.scale.centerY)); 660 wrap.setAttribute('transform', stencilM); 661 if (wrapStencil) wrapStencil.setAttribute('transform', stencilM); 662 gsap.set(mcWhite, { opacity: cfg.whiteFade.fromOpacity }); 663 gsap.set(mcBg, { opacity: 1 }); 664 665 return new Promise(function (resolveRunFullIntro) { 666 requestAnimationFrame(function () { 667 requestAnimationFrame(function () { 668 introStartMs = performance.now(); 669 670 var slideTl = gsap.timeline(); 671 var slideEase = resolveEase(cfg.slideIn.ease); 672 var slideDur = cfg.slideIn.duration; 673 var slideSt = cfg.slideIn.stagger; 674 slideTl.to(lettersOrdered, { 675 x: 0, 676 duration: slideDur, 677 stagger: slideSt, 678 ease: slideEase, 679 }, 0); 680 if (lettersStencilOrdered.length) { 681 slideTl.to(lettersStencilOrdered, { 682 x: 0, 683 duration: slideDur, 684 stagger: slideSt, 685 ease: slideEase, 686 }, 0); 687 } 688 689 var slideDone = new Promise(function (resolve) { 690 slideTl.eventCallback('onComplete', resolve); 691 }); 692 693 slideDone.then(function () { 694 var waits = [raceTimeout(readyPromise, cfg.readyTimeoutMs)]; 695 return Promise.all(waits); 696 }).then(function () {
697 var elapsed = performance.now() - introStartMs; 698 if (elapsed < cfg.minHoldMs) return sleep(cfg.minHoldMs - elapsed); 699 }).then(function () { 700 var overrides = responsiveOverrides(); 701 var scaleEnd = overrides.scaleEnd != null ? overrides.scaleEnd : cfg.scale.end; 702 var S1 = wordScaleForFraction(svg, scaleEnd); 703 var master = gsap.timeline({ 704 onComplete: function () { 705 activeTimeline = null; 706 }, 707 }); 708 activeTimeline = master; 709 710 var scaleProxy = { S: S0 }; 711 master.to(scaleProxy, { 712 S: S1, 713 duration: cfg.scale.duration, 714 ease: resolveEase(cfg.scale.ease), 715 onUpdate: function () { 716 var m = matrixToAttr(buildBaseMatrix(scaleProxy.S, cfg.scale.centerY)); 717 wrap.setAttribute('transform', m); 718 if (wrapStencil) wrapStencil.setAttribute('transform', m); 719 }, 720 }, 0); 721 722 master.to(mcWhite, { 723 opacity: cfg.whiteFade.toOpacity, 724 duration: cfg.whiteFade.duration, 725 ease: resolveEase(cfg.whiteFade.ease), 726 }, Math.max(0, cfg.whiteFade.offset)); 727 728 master.to({}, { duration: cfg.holdAfterScaleMs / 1000 }, cfg.scale.duration); 729 730 var pivotKey = String(cfg.zoom.pivotLetter || 'I'); 731 if (!/^[A-Za-z0-9]{1,5}$/.test(pivotKey)) pivotKey = 'I'; 732 var cxLocal = pivotCenterXFromLetter(boxMapMain, pivotKey, wrap); 733 var cyLocal = WORD_CY; 734 var baseM = buildBaseMatrix(S1, cfg.scale.centerY); 735 var pivot = { x: cxLocal, y: cyLocal }; 736 try { 737 var pt = new DOMPoint(cxLocal, cyLocal).matrixTransform(baseM); 738 pivot.x = pt.x; 739 pivot.y = pt.y; 740 } catch (ePt) { 741 pivot.x = (cxLocal - WORD_CX) * S1 + 50; 742 pivot.y = (cyLocal - WORD_CY) * S1 + cfg.scale.centerY * 100; 743 } 744 pivot.x += overrides.cOffsetX != null ? overrides.cOffsetX : cfg.zoom.cOffsetX; 745 pivot.y += cfg.zoom.cOffsetY; 746 747 var zoomProxy = { z: 1 }; 748 var zoomStart = cfg.scale.duration + cfg.holdAfterScaleMs / 1000; 749 var zoomEnd = zoomScaleToClearViewport(svg, S1, overrides.endScaleMin); 750 master.to(zoomProxy, { 751 z: zoomEnd, 752 duration: cfg.zoom.duration, 753 ease: resolveEase(cfg.zoom.ease), 754 onUpdate: function () { 755 var zm = new DOMMatrix() 756 .translate(pivot.x, pivot.y) 757 .scale(zoomProxy.z, zoomProxy.z) 758 .translate(-pivot.x, -pivot.y) 759 .multiply(baseM); 760 var matStr = matrixToAttr(zm); 761 wrap.setAttribute('transform', matStr); 762 if (wrapStencil) wrapStencil.setAttribute('transform', matStr); 763 }, 764 }, zoomStart); 765 766 return new Promise(function (resolve) { 767 master.eventCallback('onComplete', function () { 768 cleanupIntro(); 769 resolve(); 770 }); 771 }); 772 }).then(resolveRunFullIntro); 773 }); 774 }); 775 }); 776 } 777 778 window.homeIntro = { 779 CONFIG: deepClone(DEFAULT_CONFIG), 780 781 applyConfig: function (partial) { 782 deepMerge(window.homeIntro.CONFIG, partial); 783 }, 784 785 resetConfig: function () { 786 window.homeIntro.CONFIG = deepClone(DEFAULT_CONFIG); 787 parseIntroQueryString(); 788 }, 789 790 cleanup: function (opts) { 791 cleanupIntro(opts || {}); 792 }, 793 794 replay: function () { 795 return window.homeIntro.run({ 796 replay: true, 797 readyPromise: Promise.resolve(), 798 heroImageUrl: getHeroImageUrl(), 799 }); 800 }, 801 802 run: function (opts) { 803 opts = opts || {}; 804 if (typeof gsap === 'undefined') { 805 cleanupIntro(); 806 return Promise.resolve(); 807 } 808 809 window._homeIntroCleanup = function () { 810 window.homeIntro.cleanup(); 811 }; 812 813 var reduced = false;
814 try { 815 reduced = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches; 816 } catch (e) { /* ignore */ } 817 818 if (reduced && !opts.replay) { 819 hideMcTransitionOverlay(); 820 stopLenis(); 821 overlayNode = mountOverlayFromTemplate(); 822 removeBootLayerNextFrame(); 823 document.documentElement.classList.add('home-intro-active'); 824 if (typeof window.__marketingSetPageChromeInert === 'function') { 825 window.__marketingSetPageChromeInert(true); 826 } 827 var mcW = overlayNode && overlayNode.querySelector('#mc-white'); 828 if (mcW && typeof gsap !== 'undefined') { 829 gsap.set(mcW, { opacity: 0 }); 830 } 831 return raceTimeout(opts.readyPromise || Promise.resolve(), window.homeIntro.CONFIG.readyTimeoutMs) 832 .then(function () { 833 var ms = window.homeIntro.CONFIG.reducedMotionFadeMs || 300; 834 if (overlayNode && typeof gsap !== 'undefined') { 835 return new Promise(function (resolve) { 836 gsap.to(overlayNode, { 837 autoAlpha: 0, 838 duration: ms / 1000, 839 onComplete: function () { 840 cleanupIntro(); 841 resolve(); 842 }, 843 }); 844 }); 845 } 846 cleanupIntro(); 847 }); 848 } 849 850 if (opts.replay && overlayNode) { 851 cleanupIntro(); 852 } 853 854 return runFullIntro(opts); 855 }, 856 }; 857 858 parseIntroQueryString(); 859 maybeShowDebugPanel(); 860})();
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.