PageSourceSearch

https://seranking.com/wp-content/themes/se_theme/template-parts/header-2025/assets/app.js?v=3333

js seranking.com collected 2026-09-24 07:24:54 UTC 30,860 bytes, 849 lines download raw bytes

1(function () {
2    "use strict";
3
4    // ============================================================================
5    // CONSTANTS
6    // ============================================================================
7    const SELECTORS = {
8        menuContainer: ".header-menu-2025",
9        menuList: ".header-menu-2025__list",
10        menuItem: "li",
11        menuTabsWrapper: ".menu-tabs-wrapper",
12        titleWrapper: ".title-wrapper-depth-0",
13        tab: 'button[role="tab"], a[role="tab"]',
14        tabPanel: '[role="tabpanel"]',
15        tabList: ".menu-tablist",
16        tabsContainer: ".menu-tabs-container",
17        tabHeader: ".menu-tab-header",
18        appsMenu: ".header__apps-menu",
19        appsMenuToggle: ".header__apps-menu-toggle",
20        menuToggle: ".header__main-right-menu-toggle",
21        menuClose: ".header__main-right-menu-close",
22        header: ".header__container",
23        helloBar: "[data-hello-bar]",
24        langSwitcher: ".language-switcher-2025__wrap",
25        mobileButtons: ".header-menu-2025__mobile-buttons"
26    };
27
28    const BREAKPOINTS = {
29        mobile: 767,
30        tablet: { min: 768, max: 1279 },
31        desktop: 1279,
32        helloBarDesktop: 1024
33    };
34
35    const SCROLL_THRESHOLD = 10;
36    const SCROLL_HIDE_THRESHOLD = 50;
37    const RESIZE_DEBOUNCE = 150;
38    const HOVER_CLOSE_DELAY = 100;
39
40    // ============================================================================
41    // INITIALIZATION
42    // ============================================================================
43    const menuContainer = document.querySelector(SELECTORS.menuContainer);
44    if (!menuContainer) return;
45
46    let currentOpenMenu = null;
47    let hoverCloseTimer = null;
48    let wasMobileForMegaMenuTabs = false;
49
50    // ============================================================================
51    // VIEWPORT UTILITIES
52    // ============================================================================
53    function getViewportWidth() {
54        return window.innerWidth;
55    }
56
57    function isMobileViewport() {
58        return getViewportWidth() <= BREAKPOINTS.mobile;
59    }
60
61    function isTabletViewport() {
62        const width = getViewportWidth();
63        return width >= BREAKPOINTS.tablet.min && width <= BREAKPOINTS.tablet.max;
64    }
65
66    function isDesktopViewport() {
67        return getViewportWidth() > BREAKPOINTS.desktop;
68    }
69
70    function isHoverDevice() {
71        return window.matchMedia('(hover: hover) and (pointer: fine)').matches;
72    }
73
74    // ============================================================================
75    // HELPER FUNCTIONS
76    // ============================================================================
77    function hasRealHref(element) {
78        if (element.tagName !== "A") return false;
79        const href = element.getAttribute("href");
80        return href && href !== "#" && href.trim() !== "";
81    }
82
83    function isHelloBarDismissed(helloBar) {
84        if (!helloBar) return false;
85        return helloBar.classList.contains("hello-bar--dismissed") || 
86               sessionStorage.getItem("hello-bar-dismissed") === "true";
87    }
88
89    function resetTabState(tabs) {
90        tabs.forEach((tab) => {
91            tab.classList.remove("selected");
92            tab.setAttribute("aria-selected", "false");
93            tab.setAttribute("tabindex", "-1");
94        });
95    }
96
97    function setTabActive(tab) {
98        tab.classList.add("selected");
99        tab.setAttribute("aria-selected", "true");
100        tab.setAttribute("tabindex", "0");
101    }
102
103    function hideAllPanels(panels) {
104        panels.forEach((panel) => {
105            panel.classList.remove("selected");
106            panel.classList.add("hidden");
107            panel.setAttribute("hidden", "");
108        });
109    }
110
111    function showPanel(panel) {
112        if (!panel) return;
113        panel.classList.add("selected");
114        panel.classList.remove("hidden");
115        panel.removeAttribute("hidden");
116    }
117
118    function switchTab(tab, menuWrapper) {
119        const panelId = tab.getAttribute("aria-controls");
120        if (!panelId) return;
121
122        const allTabs = menuWrapper.querySelectorAll(SELECTORS.tab);
123        const allPanels = menuWrapper.querySelectorAll(SELECTORS.tabPanel);
124
125        resetTabState(allTabs);
126        setTabActive(tab);
127        hideAllPanels(allPanels);
128
129        const targetPanel = menuWrapper.querySelector(`[role="tabpanel"][id="${panelId}"]`);
130        showPanel(targetPanel);
131
132        return { allTabs, allPanels, tablist: menuWrapper.querySelector(SELECTORS.tabList) };
133    }
134
135    // ============================================================================
136    // MENU OPERATIONS
137    // ============================================================================
138    function closeAllMenus() {
139        const allMenus = menuContainer.querySelectorAll(SELECTORS.menuTabsWrapper);
140        allMenus.forEach((menu) => menu.classList.add("hidden"));
141
142        const allTitleWrappers = menuContainer.querySelectorAll(SELECTORS.titleWrapper);
143        allTitleWrappers.forEach((wrapper) => wrapper.classList.remove("active"));
144
145        if (isMobileViewport()) {
146            const allMenuItems = menuContainer.querySelectorAll(`${SELECTORS.menuList} > ${SELECTORS.menuItem}`);
147            allMenuItems.forEach((item) => item.classList.remove("menu-item-hidden-mobile"));
148        }
149
150        currentOpenMenu = null;
151        updateMobileButtonsVisibility();
152    }
153
154    function closeOtherMenus() {
155        const appsMenuWrapper = document.querySelector(SELECTORS.appsMenu);
156        if (appsMenuWrapper) {
157            appsMenuWrapper.classList.remove("active");
158        }
159
160        const langSwitcherWraps = document.querySelectorAll(SELECTORS.langSwitcher);
161        langSwitcherWraps.forEach((wrap) => wrap.classList.remove("active"));
162    }
163
164    function closeAllOtherMenus() {
165        closeOtherMenus();
166        menuContainer.classList.remove("mobile-menu-open", "right-fixation");
167        document.body.classList.remove("mobile-menu-open");
168        closeAllMenus();
169        toggleMenuButtons(false);
170    }
171
172    function openMenu(menuWrapper) {
173        closeOtherMenus();
174        closeAllMenus();
175        menuWrapper.classList.remove("hidden");
176        currentOpenMenu = menuWrapper;
177
178        const menuItem = menuWrapper.closest(SELECTORS.menuItem);
179        if (!menuItem) return;
180
181        const titleWrapper = menuItem.querySelector(SELECTORS.titleWrapper);
182        if (titleWrapper) {
183            titleWrapper.classList.add("active");
184        }
185
186        if (isMobileViewport()) {
187            const allMenuItems = menuContainer.querySelectorAll(`${SELECTORS.menuList} > ${SELECTORS.menuItem}`);
188            allMenuItems.forEach((item) => {
189                item.classList.toggle("menu-item-hidden-mobile", item !== menuItem);
190            });
191            resetAriaSelectedOnMobile();
192            hideAllTabpanelsOnMobile();
193        } else {
194            selectFirstTab(menuWrapper);
195        }
196        updateMobileButtonsVisibility();
197    }
198
199    function toggleMenuButtons(isOpen) {
200        const menuToggle = document.querySelector(SELECTORS.menuToggle);
201        const menuClose = document.querySelector(SELECTORS.menuClose);
202
203        if (menuToggle && menuClose) {
204            menuToggle.classList.toggle("hidden", isOpen);
205            menuClose.classList.toggle("active", isOpen);
206        }
207    }
208
209    function updateMobileButtonsVisibility() {
210        if (!isMobileViewport()) return;
211
212        const mobileButtons = menuContainer.querySelector(SELECTORS.mobileButtons);
213        if (!mobileButtons) return;
214
215        const isMainMenuOpen = menuContainer.classList.contains("mobile-menu-open");
216        const hasActiveCategory = menuContainer.querySelector(`${SELECTORS.titleWrapper}.active`);
217
218        if (isMainMenuOpen && !hasActiveCategory) {
219            mobileButtons.style.display = "flex";
220        } else {
221            mobileButtons.style.display = "none";
222        }
223    }
224
225    function showMenuOnDesktop() {
226        if (isDesktopViewport()) {
227            menuContainer.classList.remove("right-fixation", "mobile-menu-open");
228            document.body.classList.remove("mobile-menu-open");
229            menuContainer.style.display = "";
230            menuContainer.style.visibility = "";
231        }
232    }
233
234    // ============================================================================
235    // TAB OPERATIONS
236    // ============================================================================
237    function selectFirstTab(menuWrapper) {
238        if (isMobileViewport()) return;
239
240        const allTabs = menuWrapper.querySelectorAll(SELECTORS.tab);
241        if (allTabs.length === 0) return;
242
243        switchTab(allTabs[0], menuWrapper);
244    }
245
246    function resetAllMegaMenusToFirstTab() {
247        menuContainer.querySelectorAll(SELECTORS.menuTabsWrapper).forEach((wrapper) => {
248            selectFirstTab(wrapper);
249        });
250    }
251
252    function resetAriaSelectedOnMobile() {
253        if (!isMobileViewport()) return;
254        const allTabs = menuContainer.querySelectorAll(SELECTORS.tab);
255        allTabs.forEach((tab) => tab.setAttribute("aria-selected", "false"));
256    }
257
258    function hideAllTabpanelsOnMobile() {
259        if (!isMobileViewport()) return;
260
261        const allPanels = menuContainer.querySelectorAll(SELECTORS.tabPanel);
262        hideAllPanels(allPanels);
263
264        const allTabHeaders = menuContainer.querySelectorAll(SELECTORS.tabHeader);
265        allTabHeaders.forEach((header) => header.classList.add("hidden"));
266
267        const allTablists = menuContainer.querySelectorAll(SELECTORS.tabList);
268        allTablists.forEach((tablist) => tablist.classList.remove("hidden"));
269
270        const allTitleWrappers = menuContainer.querySelectorAll(`${SELECTORS.titleWrapper}.menu-tab-header-hidden`);
271        allTitleWrappers.forEach((wrapper) => wrapper.classList.remove("menu-tab-header-hidden"));
272    }
273
274    function createMobileTabHeader(tab, menuWrapper, tabsContainer, tablist) {
275        const menuItem = menuWrapper.closest(SELECTORS.menuItem);
276        if (menuItem) {
277            const titleWrapper = menuItem.querySelector(SELECTORS.titleWrapper);
278            if (titleWrapper) {
279                titleWrapper.classList.add("menu-tab-header-hidden");
280            }
281        }
282
283        const tabClone = tab.cloneNode(true);
284        tabClone.querySelectorAll("svg").forEach((svg) => svg.remove());
285        const tabText = tabClone.textContent.trim();
286
287        let tabHeader = menuWrapper.querySelector(SELECTORS.tabHeader);
288        if (!tabHeader) {
289            tabHeader = document.createElement("div");
290            tabHeader.className = "menu-tab-header";
291            tabsContainer.insertBefore(tabHeader, tablist);
292        }
293
294        const titleSpan = document.createElement("span");
295        titleSpan.className = "menu-tab-header-title";
296        titleSpan.textContent = tabText;
297
298        const chevronSpan = document.createElement("span");
299        chevronSpan.className = "menu-tab-header-chevron";
300
301        const backDiv = document.createElement("div");
302        backDiv.className = "menu-tab-header-back";
303        backDiv.appendChild(chevronSpan);
304        backDiv.appendChild(titleSpan);
305
306        tabHeader.innerHTML = "";
307        tabHeader.appendChild(backDiv);
308        tabHeader.classList.remove("hidden");
309
310        return { tabHeader, menuItem };
311    }
312
313    function setupMobileTabBackButton(tabHeader, menuItem, tablist, allPanels, allTabs) {
314        const backButton = tabHeader.querySelector(".menu-tab-header-back");
315        if (!backButton) return;
316
317        const newBackButton = backButton.cloneNode(true);
318        backButton.parentNode.replaceChild(newBackButton, backButton);
319
320        newBackButton.addEventListener("click", (e) => {
321            e.preventDefault();
322            e.stopPropagation();
323
324            tabHeader.classList.add("hidden");
325            tablist.classList.remove("hidden");
326
327            if (menuItem) {
328                const titleWrapper = menuItem.querySelector(SELECTORS.titleWrapper);
329                if (titleWrapper) {
330                    titleWrapper.classList.remove("menu-tab-header-hidden");
331                }
332            }
333
334            hideAllPanels(allPanels);
335            resetTabState(allTabs);
336            updateMobileButtonsVisibility();
337        });
338    }
339
340    function handleTabClick(e) {
341        const tab = e.target.closest(SELECTORS.tab);
342        if (!tab || hasRealHref(tab)) return;
343
344        if (isHoverDevice() && !isMobileViewport() && e.detail > 0) {
345            e.preventDefault();
346            e.stopPropagation();
347            return;
348        }
349
350        e.preventDefault();
351        e.stopPropagation();
352
353        const menuWrapper = tab.closest(SELECTORS.menuTabsWrapper);
354        if (!menuWrapper) return;
355
356        const { allTabs, allPanels, tablist } = switchTab(tab, menuWrapper);
357
358        if (isMobileViewport() && tablist) {
359            const tabsContainer = menuWrapper.querySelector(SELECTORS.tabsContainer);
360            if (tabsContainer) {
361                tablist.classList.add("hidden");
362                const { tabHeader, menuItem } = createMobileTabHeader(tab, menuWrapper, tabsContainer, tablist);
363                setupMobileTabBackButton(tabHeader, menuItem, tablist, allPanels, allTabs);
364            }
365            updateMobileButtonsVisibility();
366        }
367    }
368
369    function handleTabMouseEnter(e) {
370        if (!isHoverDevice() || isMobileViewport()) return;
371
372        const tab = e.currentTarget;
373        if (!tab || hasRealHref(tab)) return;
374
375        const menuWrapper = tab.closest(SELECTORS.menuTabsWrapper);
376        if (!menuWrapper) return;
377
378        switchTab(tab, menuWrapper);
379    }
380
381    function handleCategoryClick(e) {
382        if (isHoverDevice()) return;
383
384        const menuItem = e.currentTarget.closest(SELECTORS.menuItem);
385        if (!menuItem) return;
386
387        const menuWrapper = menuItem.querySelector(SELECTORS.menuTabsWrapper);
388        if (!menuWrapper) return;
389
390        const clickedLink = e.target.closest("a[href]");
391        if (clickedLink && hasRealHref(clickedLink)) return;
392
393        e.preventDefault();
394        e.stopPropagation();
395
396        if (currentOpenMenu === menuWrapper && !menuWrapper.classList.contains("hidden")) {
397            if (isTabletViewport()) return;
398            closeAllMenus();
399        } else {
400            openMenu(menuWrapper);
401        }
402    }
403
404    function handleCategoryMouseEnter(e) {
405        if (!isHoverDevice()) return;
406
407        const menuWrapper = e.currentTarget.querySelector(SELECTORS.menuTabsWrapper);
408        if (!menuWrapper) return;
409
410        if (hoverCloseTimer) {
411            clearTimeout(hoverCloseTimer);
412            hoverCloseTimer = null;
413        }
414
415        if (currentOpenMenu !== menuWrapper) {
416            openMenu(menuWrapper);
417        }
418    }
419
420    function handleCategoryMouseLeave() {
421        if (!isHoverDevice()) return;
422        if (menuContainer.classList.contains("right-fixation")) return;
423
424        hoverCloseTimer = setTimeout(() => {
425            closeAllMenus();
426            hoverCloseTimer = null;
427        }, HOVER_CLOSE_DELAY);
428    }
429
430    function handleOutsideClick(e) {
431        if (!currentOpenMenu) return;
432
433        if (isTabletViewport() && menuContainer.contains(e.target)) return;
434        if (e.target.closest(SELECTORS.tab)) return;
435        if (currentOpenMenu.contains(e.target) || e.target.closest(".menu-item-has-children")) return;
436
437        closeAllMenus();
438    }
439
440    // ============================================================================
441    // HEADER SCROLL & HELLO-BAR MANAGEMENT
442    // ============================================================================
443    function initHeaderHeightObserver() {
444        const header = document.querySelector(SELECTORS.header);
445        const helloBar = document.querySelector(SELECTORS.helloBar);
446        if (!header) return;
447
448        function updateHeaderHeight() {
449            const height = header.offsetHeight;
450            let observableHeight = height;
451
452            if (helloBar && helloBar.classList.contains("hello-bar--hidden")) {
453                observableHeight -= helloBar.offsetHeight + 12;
454            }
455
456            document.documentElement.style.setProperty("--header-2025-height", `${height}px`);
457            document.documentElement.style.setProperty("--header-2025-observable-height", `${observableHeight}px`);
458        }
459
460        updateHeaderHeight();
461
462        const resizeObserver = new ResizeObserver(updateHeaderHeight);
463        resizeObserver.observe(header);
464
465        window.addEventListener("scroll", updateHeaderHeight, { passive: true });
466    }
467
468    function initHelloBarHeightObserver() {
469        const helloBar = document.querySelector(SELECTORS.helloBar);
470
471        function updateHelloBarHeight() {
472            const height = helloBar ? helloBar.offsetHeight : 0;
473            document.documentElement.style.setProperty("--hello-bar-height", `${height}px`);
474        }
475
476        updateHelloBarHeight();
477        if (!helloBar) return;
478
479        const resizeObserver = new ResizeObserver(updateHelloBarHeight);
480        resizeObserver.observe(helloBar);
481    }
482
483    function initHeaderScroll() {
484        const header = document.querySelector(SELECTORS.header);
485        const helloBar = document.querySelector(SELECTORS.helloBar);
486        if (!header) return;
487
488        let lastScrollY = window.scrollY;
489        let scrollTimeout;
490        let isScrollingDown = false;
491
492        function updateBodyPadding() {
493            if (header.classList.contains("header--fixed")) {
494                document.body.style.paddingTop = `${header.offsetHeight}px`;
495            } else {
496                document.body.style.paddingTop = "0";
497            }
498        }
499
500        function updateHelloBarVisibility(currentScrollY) {
501            if (!helloBar || isHelloBarDismissed(helloBar)) return;
502
503            const width = window.innerWidth;
504            if (width <= BREAKPOINTS.helloBarDesktop - 1) {
505                helloBar.classList.toggle("hello-bar--hidden", isScrollingDown && currentScrollY > SCROLL_HIDE_THRESHOLD);
506            } else {
507                helloBar.classList.remove("hello-bar--hidden");
508            }
509        }
510
511        function handleScroll() {
512            const currentScrollY = window.scrollY;
513
514            if (Math.abs(currentScrollY - lastScrollY) > SCROLL_THRESHOLD) {
515                isScrollingDown = currentScrollY > lastScrollY;
516            }
517
518            const wasFixed = header.classList.contains("header--fixed");
519            header.classList.toggle("header--fixed", currentScrollY > 0);
520
521            if (wasFixed !== header.classList.contains("header--fixed")) {
522                updateBodyPadding();
523            }
524
525            updateHelloBarVisibility(currentScrollY);
526            lastScrollY = currentScrollY;
527        }
528
529        window.addEventListener("scroll", () => {
530            if (scrollTimeout) cancelAnimationFrame(scrollTimeout);
531            scrollTimeout = requestAnimationFrame(handleScroll);
532        }, { passive: true });
533
534        let resizeTimeout;
535        window.addEventListener("resize", () => {
536            clearTimeout(resizeTimeout);
537            resizeTimeout = setTimeout(() => {
538                updateBodyPadding();
539                if (helloBar && !isHelloBarDismissed(helloBar)) {
540                    if (window.innerWidth >= BREAKPOINTS.helloBarDesktop) {
541                        helloBar.classList.remove("hello-bar--hidden");
542                    } else {
543                        handleScroll();
544                    }
545                }
546            }, RESIZE_DEBOUNCE);
547        });
548
549        if (window.scrollY > 0) {
550            header.classList.add("header--fixed");
551            updateBodyPadding();
552        }
553
554        if (helloBar) {
555            if (isHelloBarDismissed(helloBar)) {
556                helloBar.classList.add("hello-bar--hidden");
557            } else {
558                const width = window.innerWidth;
559                if (width >= BREAKPOINTS.helloBarDesktop) {
560                    helloBar.classList.remove("hello-bar--hidden");
561                } else {
562                    helloBar.classList.toggle("hello-bar--hidden", window.scrollY > SCROLL_HIDE_THRESHOLD);
563                }
564            }
565        }
566
567        const resizeObserver = new ResizeObserver(() => {
568            if (header.classList.contains("header--fixed")) {
569                updateBodyPadding();
570            }
571        });
572        resizeObserver.observe(header);
573    }
574
575    // ============================================================================
576    // MENU TOGGLE HANDLERS
577    // ============================================================================
578    function initMobileMenuToggle() {
579        const menuToggle = document.querySelector(SELECTORS.menuToggle);
580        const menuClose = document.querySelector(SELECTORS.menuClose);
581        if (!menuToggle || !menuContainer) return;
582
583        function closeMobileMenu() {
584            menuContainer.classList.remove("mobile-menu-open");
585            document.body.classList.remove("mobile-menu-open");
586            closeAllMenus();
587            toggleMenuButtons(false);
588            updateMobileButtonsVisibility();
589        }
590
591        function openMobileMenu() {
592            closeOtherMenus();
593            menuContainer.classList.add("mobile-menu-open");
594            document.body.classList.add("mobile-menu-open");
595            toggleMenuButtons(true);
596            updateMobileButtonsVisibility();
597        }
598
599        menuToggle.addEventListener("click", (e) => {
600            e.preventDefault();
601            e.stopPropagation();
602            if (!isMobileViewport()) return;
603
604            const isOpen = menuContainer.classList.contains("mobile-menu-open");
605            if (isOpen) {
606                closeMobileMenu();
607            } else {
608                openMobileMenu();
609            }
610        });
611
612        if (menuClose) {
613            menuClose.addEventListener("click", (e) => {
614                if (!isMobileViewport()) return;
615
616                const langSwitcherWraps = document.querySelectorAll(SELECTORS.langSwitcher);
617                const isLangSwitcherOpen = Array.from(langSwitcherWraps).some((wrap) => 
618                    wrap.classList.contains("active")
619                );
620
621                if (isLangSwitcherOpen) return;
622
623                e.preventDefault();
624                e.stopPropagation();
625                closeMobileMenu();
626            });
627        }
628
629        document.addEventListener("click", (e) => {
630            if (!isMobileViewport() || !menuContainer.classList.contains("mobile-menu-open")) return;
631            if (menuContainer.contains(e.target) || menuToggle.contains(e.target)) return;
632            closeMobileMenu();
633        });
634
635        let resizeTimeout;
636        window.addEventListener("resize", () => {
637            clearTimeout(resizeTimeout);
638            resizeTimeout = setTimeout(() => {
639                if (!isMobileViewport() && menuContainer.classList.contains("mobile-menu-open")) {
640                    closeMobileMenu();
641                }
642            }, RESIZE_DEBOUNCE);
643        });
644    }
645
646    function initTabletMenuToggle() {
647        const menuToggle = document.querySelector(SELECTORS.menuToggle);
648        const menuClose = document.querySelector(SELECTORS.menuClose);
649        if (!menuToggle || !menuContainer) return;
650
651        function closeTabletMenu() {
652            menuContainer.classList.remove("right-fixation");
653            closeAllMenus();
654            toggleMenuButtons(false);
655        }
656
657        function openTabletMenu() {
658            closeOtherMenus();
659            menuContainer.classList.add("right-fixation");
660            toggleMenuButtons(true);
661
662            const firstMenuItem = menuContainer.querySelector(".menu-item-has-children");
663            const menuTabsWrapper = firstMenuItem?.querySelector(SELECTORS.menuTabsWrapper);
664            if (menuTabsWrapper) {
665                openMenu(menuTabsWrapper);
666            }
667        }
668
669        menuToggle.addEventListener("click", (e) => {
670            e.preventDefault();
671            e.stopPropagation();
672            if (!isTabletViewport()) return;
673
674            const isOpen = menuContainer.classList.contains("right-fixation");
675            if (isOpen) {
676                closeTabletMenu();
677            } else {
678                openTabletMenu();
679            }
680        });
681
682        if (menuClose) {
683            menuClose.addEventListener("click", (e) => {
684                e.preventDefault();
685                e.stopPropagation();
686                if (!isTabletViewport()) return;
687                closeTabletMenu();
688            });
689        }
690
691        document.addEventListener("click", (e) => {
692            if (!isTabletViewport() || !menuContainer.classList.contains("right-fixation")) return;
693            if (menuContainer.contains(e.target) || menuToggle.contains(e.target)) return;
694            closeTabletMenu();
695        });
696
697        let resizeTimeout;
698        window.addEventListener("resize", () => {
699            clearTimeout(resizeTimeout);
700            resizeTimeout = setTimeout(() => {
701                if (isDesktopViewport()) {
702                    if (menuContainer.classList.contains("right-fixation")) {
703                        closeTabletMenu();
704                    }
705                    menuContainer.style.display = "";
706                    menuContainer.style.visibility = "";
707                } else if (!isTabletViewport() && menuContainer.classList.contains("right-fixation")) {
708                    closeTabletMenu();
709                }
710            }, RESIZE_DEBOUNCE);
711        });
712    }
713
714    function initAppsMenuToggle() {
715        const appsMenuToggle = document.querySelector(SELECTORS.appsMenuToggle);
716        const appsMenuWrapper = document.querySelector(SELECTORS.appsMenu);
717        if (!appsMenuToggle || !appsMenuWrapper) return;
718
719        appsMenuToggle.addEventListener("click", (e) => {
720            e.preventDefault();
721            e.stopPropagation();
722            const isOpen = appsMenuWrapper.classList.contains("active");
723            if (isOpen) {
724                appsMenuWrapper.classList.remove("active");
725            } else {
726                closeAllOtherMenus();
727                appsMenuWrapper.classList.add("active");
728            }
729        });
730
731        document.addEventListener("click", (e) => {
732            if (!appsMenuWrapper.contains(e.target)) {
733                appsMenuWrapper.classList.remove("active");
734            }
735        });
736    }
737
738    // ============================================================================
739    // MENU CURRENT CLASSES UPDATE
740    // ============================================================================
741    function updateMenuCurrentClasses() {
742        const currentPath = window.location.pathname.replace(/\/$/, '') || '/';
743        const menuLinks = menuContainer.querySelectorAll('a[href]');
744
745        // First, remove all old classes
746        menuContainer.querySelectorAll('.current-menu-item, .current-menu-link, .menu-tab.selected').forEach(el => {
747            el.classList.remove('current-menu-item', 'current-menu-link', 'selected');
748        });
749        menuContainer.querySelectorAll('.menu-tab[aria-selected="true"]').forEach(tab => {
750            tab.setAttribute('aria-selected', 'false');
751        });
752
753        menuLinks.forEach(link => {
754            const href = link.getAttribute('href');
755            if (!href || href === '#' || href.startsWith('#')) return;
756
757            // Normalize link path
758            let hrefPath;
759            let hrefOrigin;
760            try {
761                // If href is relative, create full URL
762                const url = new URL(href, window.location.origin);
763                hrefOrigin = url.origin;
764                hrefPath = url.pathname.replace(/\/$/, '') || '/';
765            } catch (e) {
766                // If failed to parse as URL, use as is
767                hrefPath = href.split('?')[0].split('#')[0].replace(/\/$/, '') || '/';
768                hrefOrigin = window.location.origin; // Assume same origin for relative links
769            }
770
771            // Only compare paths if the link is on the same domain
772            if (hrefOrigin === window.location.origin && hrefPath === currentPath) {
773                // Add class to link
774                link.classList.add('current-menu-link');
775                
776                // Find parent <li>
777                let li = link.closest('li');
778                if (li) {
779                    li.classList.add('current-menu-item');
780                }
781            }
782        });
783    }
784
785    // ============================================================================
786    // INITIALIZATION
787    // ============================================================================
788    function initMenuHandlers() {
789        const menuList = menuContainer.querySelector(SELECTORS.menuList);
790        if (!menuList) return;
791
792        const categories = menuList.querySelectorAll(SELECTORS.menuItem);
793        categories.forEach((category) => {
794            const titleWrapper = category.querySelector(SELECTORS.titleWrapper);
795            if (titleWrapper && !titleWrapper.querySelector("a[href]")) {
796                category.addEventListener("click", handleCategoryClick);
797                category.addEventListener("mouseenter", handleCategoryMouseEnter);
798                category.addEventListener("mouseleave", handleCategoryMouseLeave);
799            }
800        });
801    }
802
803    function initTabHandlers() {
804        const tabs = menuContainer.querySelectorAll(SELECTORS.tab);
805        tabs.forEach((tab) => {
806            tab.addEventListener("click", handleTabClick);
807            tab.addEventListener("mouseenter", handleTabMouseEnter);
808        });
809    }
810
811    function init() {
812        initMenuHandlers();
813        initTabHandlers();
814        initAppsMenuToggle();
815        initTabletMenuToggle();
816        initMobileMenuToggle();
817        initHeaderHeightObserver();
818        initHelloBarHeightObserver();
819        initHeaderScroll();
820        document.addEventListener("click", handleOutsideClick);
821
822        updateMenuCurrentClasses();
823        resetAllMegaMenusToFirstTab();
824        wasMobileForMegaMenuTabs = isMobileViewport();
825        showMenuOnDesktop();
826        resetAriaSelectedOnMobile();
827        hideAllTabpanelsOnMobile();
828        updateMobileButtonsVisibility();
829
830        window.addEventListener("resize", () => {
831            const nowMobile = isMobileViewport();
832            if (nowMobile) {
833                resetAriaSelectedOnMobile();
834                hideAllTabpanelsOnMobile();
835            } else if (wasMobileForMegaMenuTabs) {
836                resetAllMegaMenusToFirstTab();
837            }
838            wasMobileForMegaMenuTabs = nowMobile;
839            showMenuOnDesktop();
840            updateMobileButtonsVisibility();
841        });
842    }
843
844    if (document.readyState === "loading") {
845        document.addEventListener("DOMContentLoaded", init);
846    } else {
847        init();
848    }
849})();

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.