@hortonstudio/main 1.9.32 → 1.9.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/assets/{hs-animations-B2hXpM0Z.js → hs-animations-DSOzyBn9.js} +3 -3
  2. package/dist/assets/hs-animations-DSOzyBn9.js.br +0 -0
  3. package/dist/assets/hs-animations-DSOzyBn9.js.gz +0 -0
  4. package/dist/assets/{hs-animations-B2hXpM0Z.js.map → hs-animations-DSOzyBn9.js.map} +1 -1
  5. package/dist/assets/{hs-counter-DxT32FUj.js → hs-counter-J3XivMD4.js} +2 -2
  6. package/dist/assets/hs-counter-J3XivMD4.js.br +0 -0
  7. package/dist/assets/hs-counter-J3XivMD4.js.gz +0 -0
  8. package/dist/assets/{hs-counter-DxT32FUj.js.map → hs-counter-J3XivMD4.js.map} +1 -1
  9. package/dist/assets/hs-default-J2cvzRiu.js +2 -0
  10. package/dist/assets/hs-default-J2cvzRiu.js.br +0 -0
  11. package/dist/assets/hs-default-J2cvzRiu.js.gz +0 -0
  12. package/dist/assets/hs-default-J2cvzRiu.js.map +1 -0
  13. package/dist/assets/{hs-marquee-SNfwk82r.js → hs-marquee-Bq_EGDiW.js} +2 -2
  14. package/dist/assets/hs-marquee-Bq_EGDiW.js.br +0 -0
  15. package/dist/assets/hs-marquee-Bq_EGDiW.js.gz +0 -0
  16. package/dist/assets/{hs-marquee-SNfwk82r.js.map → hs-marquee-Bq_EGDiW.js.map} +1 -1
  17. package/dist/assets/{hs-normalize-B-mB80zY.js → hs-normalize-CW1mxe_R.js} +2 -2
  18. package/dist/assets/hs-normalize-CW1mxe_R.js.br +0 -0
  19. package/dist/assets/hs-normalize-CW1mxe_R.js.gz +0 -0
  20. package/dist/assets/{hs-normalize-B-mB80zY.js.map → hs-normalize-CW1mxe_R.js.map} +1 -1
  21. package/dist/assets/hs-utils-BfSJf3ld.js +2 -0
  22. package/dist/assets/hs-utils-BfSJf3ld.js.br +0 -0
  23. package/dist/assets/hs-utils-BfSJf3ld.js.gz +0 -0
  24. package/dist/assets/hs-utils-BfSJf3ld.js.map +1 -0
  25. package/dist/main.js +2 -2
  26. package/dist/main.js.br +0 -0
  27. package/dist/main.js.gz +0 -0
  28. package/dist/main.js.map +1 -1
  29. package/package.json +4 -1
  30. package/dist/assets/hs-animations-B2hXpM0Z.js.br +0 -0
  31. package/dist/assets/hs-animations-B2hXpM0Z.js.gz +0 -0
  32. package/dist/assets/hs-counter-DxT32FUj.js.br +0 -0
  33. package/dist/assets/hs-counter-DxT32FUj.js.gz +0 -0
  34. package/dist/assets/hs-default-Cg-fyGlj.js +0 -2
  35. package/dist/assets/hs-default-Cg-fyGlj.js.br +0 -0
  36. package/dist/assets/hs-default-Cg-fyGlj.js.gz +0 -0
  37. package/dist/assets/hs-default-Cg-fyGlj.js.map +0 -1
  38. package/dist/assets/hs-marquee-SNfwk82r.js.br +0 -0
  39. package/dist/assets/hs-marquee-SNfwk82r.js.gz +0 -0
  40. package/dist/assets/hs-normalize-B-mB80zY.js.br +0 -0
  41. package/dist/assets/hs-normalize-B-mB80zY.js.gz +0 -0
  42. package/dist/assets/hs-utils-BDoLvY4b.js +0 -2
  43. package/dist/assets/hs-utils-BDoLvY4b.js.br +0 -0
  44. package/dist/assets/hs-utils-BDoLvY4b.js.gz +0 -0
  45. package/dist/assets/hs-utils-BDoLvY4b.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hs-default-J2cvzRiu.js","sources":["../../src/modules/default/functions/transition.ts","../../src/modules/default/functions/smooth-scroll.ts","../../src/modules/default/functions/navbar/functions/dropdown.ts","../../src/modules/default/functions/navbar/functions/menu.ts","../../src/modules/default/functions/navbar/functions/arrow-navigation.ts","../../src/modules/default/functions/navbar/navbar.ts","../../src/modules/default/functions/accordion.ts","../../src/modules/default/functions/toc/functions/heading-links.ts","../../src/modules/default/functions/toc/toc.ts","../../src/modules/default/functions/toc/functions/progress-bar.ts","../../src/modules/default/functions/pagination.ts","../../src/modules/default/functions/comparison.ts","../../src/modules/default/functions/tabs.ts","../../src/modules/default/functions/form/functions/range.ts","../../src/modules/default/functions/form/functions/select/functions/states.ts","../../src/modules/default/functions/form/functions/select/functions/custom-select.ts","../../src/modules/default/functions/form/functions/select/select.ts","../../src/modules/default/functions/form/form.ts","../../src/modules/default/functions/form/functions/honeypot.ts","../../src/modules/default/functions/form/functions/test.ts","../../node_modules/quicklink/dist/quicklink.mjs","../../src/modules/default/functions/link-prefetch.ts","../../src/modules/default/default.ts"],"sourcesContent":["/**\n * Page Transition\n *\n * Provides animated page transitions by intercepting link clicks and triggering\n * Webflow IX animations. Supports namespace-based transitions for different page\n * types (home, contact, etc.) and both MPA and SPA architectures.\n *\n * Features:\n * - Auto link interception for seamless page transitions (MPA mode)\n * - Namespace system for page-specific transitions (Barba.js compatible)\n * - Separate exit/enter triggers for precise animation control\n * - Configurable timing with exit-time and first-delay\n * - Session-aware first load handling\n * - SPA event-based integration support\n * - Loading class after 2s wait for IX3\n *\n * Usage:\n * <div data-hs-transition=\"wrapper\" data-hs-transition-exit-time=\"0.5\" data-hs-transition-first-delay=\"0.3\">\n * <!-- Default triggers (fallback) -->\n * <div data-hs-transition-exit-trigger>Exit animation</div>\n * <div data-hs-transition-enter-trigger>Enter animation</div>\n * <!-- OR -->\n * <div data-hs-transition-trigger=\"exit\">Exit animation</div>\n * <div data-hs-transition-trigger=\"enter\">Enter animation</div>\n *\n * <!-- Namespace-specific (for Barba.js) -->\n * <div data-hs-transition-namespace=\"home\">\n * <div data-hs-transition-trigger=\"exit\">Home exit</div>\n * <div data-hs-transition-trigger=\"enter\">Home enter</div>\n * </div>\n * </div>\n */\n\nimport config from '@config';\nimport { getSelector, querySelector } from '@utils';\nimport { isWebflow, waitForIx3 } from '@utils';\n\nconst globalConfig = config._global;\nconst moduleConfig = config.default.transition;\nconst API_NAME = globalConfig.apiName;\n\nexport async function init() {\n // Check if transition wrapper exists - skip if not found\n const transitionWrapper = querySelector(moduleConfig as any, 'wrapper');\n if (!transitionWrapper) {\n return {\n result: 'transition skipped - no wrapper found',\n destroy: () => {},\n };\n }\n\n // Prevent double initialization (important for SPA when wrapper is outside Barba container)\n const initializedAttr = 'data-hs-transition-initialized';\n if (transitionWrapper.hasAttribute(initializedAttr)) {\n return {\n result: 'transition already initialized',\n destroy: () => {},\n };\n }\n\n // Mark as initialized\n transitionWrapper.setAttribute(initializedAttr, 'true');\n\n // Check if running in SPA mode\n const isSPA = window[API_NAME]?.settings?.isSPA || false;\n\n // Store event handlers and timeouts for cleanup\n const eventHandlers = new Map();\n let delayTimeout: number | null = null;\n let navTimeout: number | null = null;\n let loadingTimeout: number | null = null;\n\n const cleanup = () => {\n // Clear any pending timeouts\n if (delayTimeout) clearTimeout(delayTimeout);\n if (navTimeout) clearTimeout(navTimeout);\n if (loadingTimeout) clearTimeout(loadingTimeout);\n\n // Remove all event listeners\n eventHandlers.forEach((handler, event) => {\n if (event === 'click' || event === 'pageshow' || event === 'resize') {\n const target = event === 'click' ? document : window;\n target.removeEventListener(event, handler);\n } else {\n window.removeEventListener(event, handler);\n }\n });\n eventHandlers.clear();\n\n // Remove initialization flag to allow re-initialization\n transitionWrapper.removeAttribute(initializedAttr);\n };\n\n /**\n * Find trigger element for specific type (exit or enter) and optional namespace\n * Supports trigger patterns with priority:\n * 1. Namespace-specific triggers (if namespace provided)\n * 2. Default triggers (no namespace)\n */\n const findTrigger = (\n type: 'exit' | 'enter',\n namespace: string | null = null,\n root: Element = transitionWrapper\n ): Element | null => {\n const triggerAttr = getSelector(moduleConfig as any, 'trigger');\n const namespaceAttr = getSelector(moduleConfig as any, 'namespace');\n\n // Try new syntax: data-hs-transition-trigger=\"exit\" or \"enter\"\n const newSyntaxTriggers = root.querySelectorAll(`[${triggerAttr}=\"${type}\"]`);\n\n if (newSyntaxTriggers.length > 0) {\n // If namespace specified, look inside namespace wrapper\n if (namespace) {\n const namespaceWrapper = root.querySelector(`[${namespaceAttr}=\"${namespace}\"]`);\n if (namespaceWrapper) {\n const namespaceTrigger = namespaceWrapper.querySelector(`[${triggerAttr}=\"${type}\"]`);\n if (namespaceTrigger) return namespaceTrigger;\n }\n }\n\n // Fallback to default (not inside ANY namespace wrapper)\n const defaultTrigger = Array.from(newSyntaxTriggers).find((trigger) => {\n // Check if trigger is inside any namespace wrapper\n let parent = trigger.parentElement;\n while (parent && parent !== root) {\n if (parent.hasAttribute(namespaceAttr)) {\n return false; // Inside a namespace, skip it\n }\n parent = parent.parentElement;\n }\n return true; // Not inside any namespace\n });\n\n if (defaultTrigger) return defaultTrigger;\n }\n\n // Try separate exit/enter trigger syntax\n const separateTriggerAttr =\n type === 'exit'\n ? getSelector(moduleConfig as any, 'exitTrigger')\n : getSelector(moduleConfig as any, 'enterTrigger');\n const separateTriggers = root.querySelectorAll(`[${separateTriggerAttr}]`);\n\n if (separateTriggers.length > 0) {\n // If namespace specified, look inside namespace wrapper\n if (namespace) {\n const namespaceWrapper = root.querySelector(`[${namespaceAttr}=\"${namespace}\"]`);\n if (namespaceWrapper) {\n const namespaceTrigger = namespaceWrapper.querySelector(`[${separateTriggerAttr}]`);\n if (namespaceTrigger) return namespaceTrigger;\n }\n }\n\n // Fallback to default (not inside ANY namespace wrapper)\n const defaultTrigger = Array.from(separateTriggers).find((trigger) => {\n // Check if trigger is inside any namespace wrapper\n let parent = trigger.parentElement;\n while (parent && parent !== root) {\n if (parent.hasAttribute(namespaceAttr)) {\n return false; // Inside a namespace, skip it\n }\n parent = parent.parentElement;\n }\n return true; // Not inside any namespace\n });\n\n if (defaultTrigger) return defaultTrigger;\n }\n\n return null;\n };\n\n /**\n * Get exit time from wrapper element\n */\n const getExitTime = (): number => {\n const exitTimeAttr = getSelector(moduleConfig as any, 'exitTime');\n const value = transitionWrapper.getAttribute(exitTimeAttr);\n if (value) return parseFloat(value) * 1000;\n\n return 0;\n };\n\n /**\n * Get first delay from wrapper element (only applies on first load)\n */\n const getFirstDelay = (): number => {\n const firstDelayAttr = getSelector(moduleConfig as any, 'firstDelay');\n const value = transitionWrapper.getAttribute(firstDelayAttr);\n if (value) return parseFloat(value) * 1000;\n\n return 0;\n };\n\n /**\n * Play exit animation (when leaving page)\n */\n const playExitAnimation = (namespace: string | null = null): Promise<void> => {\n return new Promise((resolve) => {\n const exitTrigger = findTrigger('exit', namespace);\n if (!exitTrigger) {\n resolve();\n return;\n }\n\n const exitTime = getExitTime();\n\n // Trigger the animation\n (exitTrigger as HTMLElement).click();\n\n // Resolve after animation completes\n setTimeout(() => resolve(), exitTime);\n });\n };\n\n /**\n * Play enter animation (when arriving on page)\n */\n const playEnterAnimation = (namespace: string | null = null): Promise<void> => {\n return new Promise((resolve) => {\n const enterTrigger = findTrigger('enter', namespace);\n if (!enterTrigger) {\n resolve();\n return;\n }\n\n // Check if first load\n const isFirstLoad = !sessionStorage.getItem('transition-loaded');\n const firstDelay = getFirstDelay();\n\n const triggerAnimation = () => {\n (enterTrigger as HTMLElement).click();\n\n // Mark as loaded for session\n if (isFirstLoad) {\n sessionStorage.setItem('transition-loaded', 'true');\n }\n\n resolve();\n };\n\n // Only apply delay on first load\n if (isFirstLoad && firstDelay > 0) {\n delayTimeout = setTimeout(triggerAnimation, firstDelay) as unknown as number;\n } else {\n triggerAnimation();\n }\n });\n };\n\n // Always listen for custom events (works for both MPA and SPA)\n // SPA frameworks (like Barba) can dispatch these with namespace data\n const handleExitEvent = (event?: CustomEvent) => {\n const namespace = (event as any)?.detail?.namespace || null;\n playExitAnimation(namespace);\n };\n\n const handleEnterEvent = (event?: CustomEvent) => {\n const namespace = (event as any)?.detail?.namespace || null;\n playEnterAnimation(namespace);\n };\n\n eventHandlers.set('hsmain:transition-exit', handleExitEvent);\n eventHandlers.set('hsmain:transition-enter', handleEnterEvent);\n window.addEventListener('hsmain:transition-exit', handleExitEvent as EventListener);\n window.addEventListener('hsmain:transition-enter', handleEnterEvent as EventListener);\n\n // MPA Mode: Intercept link clicks\n if (!isSPA) {\n const linkClickHandler = (e: MouseEvent) => {\n const link = (e.target as Element).closest('a[href]') as HTMLAnchorElement;\n\n if (\n link &&\n link.hostname === window.location.hostname &&\n link.getAttribute('href') &&\n link.getAttribute('href')!.indexOf('#') === -1 &&\n link.getAttribute('target') !== '_blank'\n ) {\n e.preventDefault();\n const href = link.href;\n\n // Play exit animation, then navigate\n playExitAnimation().then(() => {\n window.location.href = href;\n });\n }\n };\n\n eventHandlers.set('click', linkClickHandler);\n document.addEventListener('click', linkClickHandler);\n\n // Handle back button navigation\n const pageShowHandler = (event: PageTransitionEvent) => {\n if (event.persisted) {\n window.location.reload();\n }\n };\n\n eventHandlers.set('pageshow', pageShowHandler);\n window.addEventListener('pageshow', pageShowHandler);\n }\n\n // Hide transition on window resize (prevents visual glitches)\n const resizeHandler = () => {\n if (transitionWrapper) {\n (transitionWrapper as HTMLElement).style.display = 'none';\n }\n };\n\n eventHandlers.set('resize', resizeHandler);\n window.addEventListener('resize', resizeHandler);\n\n // On DOM ready, play enter animation (only in MPA mode)\n // In SPA mode, Barba handles all transitions via events\n if (!isSPA) {\n const domReadyHandler = async () => {\n // Wait for Webflow IX3 to be ready before triggering enter animation\n const isWf = isWebflow();\n if (isWf) {\n // Set loading class after 2s if IX3 hasn't loaded yet\n loadingTimeout = setTimeout(() => {\n (transitionWrapper as HTMLElement).classList.add(globalConfig.classes.loading);\n }, 2000) as unknown as number;\n\n // Wait indefinitely for IX3 (no timeout)\n await waitForIx3();\n\n // Clear loading timeout if IX3 loaded before 2s\n if (loadingTimeout) {\n clearTimeout(loadingTimeout);\n loadingTimeout = null;\n }\n\n // Remove loading class once IX3 is ready\n (transitionWrapper as HTMLElement).classList.remove(globalConfig.classes.loading);\n }\n\n playEnterAnimation();\n };\n\n eventHandlers.set(`${API_NAME}:dom-ready`, domReadyHandler);\n window.addEventListener(`${API_NAME}:dom-ready`, domReadyHandler as EventListener, {\n once: true,\n });\n }\n\n return {\n result: 'transition initialized',\n destroy: cleanup,\n };\n}\n","/**\n * Smooth Scroll\n *\n * Provides smooth animated scrolling for anchor links with optional offset.\n * Automatically intercepts anchor link clicks, animates scroll with GSAP,\n * and handles accessibility (focus management, keyboard navigation).\n *\n * Features:\n * - Auto-detects and handles all anchor links (a[href^=\"#\"])\n * - Dynamic offset via proxy element's computed CSS top value\n * - GSAP animation with reduced motion support\n * - Keyboard navigation (Enter/Space on links)\n * - Focus management for screen readers\n * - Disables Webflow's native scroll behavior\n * - Triggers scroll-based animations on init\n *\n * Structure:\n * Optional offset proxy element with CSS top value:\n * <div data-hs-scroll-offset=\"proxy\" style=\"top: var(--_hs---scroll-offset)\"></div>\n */\n\nimport { getGsap, prefersReducedMotion, querySelector } from '@utils';\n\n// Type declaration for jQuery (runtime dependency)\ndeclare const $: any;\n\ninterface ModuleConfig {\n attributes: {\n elements: {\n 'offset-proxy': {\n primary: string;\n aliases: string[];\n };\n };\n };\n}\n\nexport async function init(config: ModuleConfig) {\n // Store event handlers for cleanup\n let clickHandler: ((e: Event) => void) | null = null;\n let keydownHandler: ((e: KeyboardEvent) => void) | null = null;\n\n // Disable Webflow's native scroll behavior (jQuery-based)\n // This runs immediately since default module already waits for IX3\n if (typeof $ !== 'undefined') {\n $(document).off('click.wf-scroll');\n }\n\n // Disable CSS smooth scrolling\n document.documentElement.style.scrollBehavior = 'auto';\n document.body.style.scrollBehavior = 'auto';\n\n function getScrollOffset(): number {\n // Find element with data-hs-scroll-offset=\"proxy\" and read its computed top value\n const proxyElement = querySelector(config, 'offset-proxy');\n console.log('[smooth-scroll] Proxy element:', proxyElement);\n if (proxyElement && proxyElement instanceof HTMLElement) {\n const computedTop = getComputedStyle(proxyElement).top;\n const offset = parseFloat(computedTop) || 0;\n console.log('[smooth-scroll] Computed top:', computedTop, '-> offset:', offset);\n return offset;\n }\n console.log('[smooth-scroll] No proxy element found, using offset: 0');\n return 0;\n }\n\n // Smooth scroll to element with offset\n function scrollToElement(target: HTMLElement, offset = 0): void {\n if (!target) return;\n\n const gsapLib = getGsap('smooth-scroll', false);\n\n // Skip animation if user prefers reduced motion or GSAP not available\n if (prefersReducedMotion() || !gsapLib) {\n const targetPosition = target.getBoundingClientRect().top + window.scrollY - offset;\n window.scrollTo(0, targetPosition);\n target.setAttribute('tabindex', '-1');\n target.focus({ preventScroll: true });\n return;\n }\n\n gsapLib.gsap.to(window, {\n duration: 1,\n scrollTo: {\n y: target,\n offsetY: offset,\n },\n ease: 'power2.out',\n onComplete: function () {\n target.setAttribute('tabindex', '-1');\n target.focus({ preventScroll: true });\n },\n });\n }\n\n function handleAnchorActivation(e: Event): void {\n const link = (e.target as Element).closest('a[href^=\"#\"]');\n if (!link) return;\n\n const href = link.getAttribute('href');\n if (!href || href === '#') return;\n\n const targetId = href.substring(1);\n const targetElement = document.getElementById(targetId);\n\n if (targetElement) {\n e.preventDefault();\n if (history.replaceState) {\n history.replaceState(null, null, `#${targetElement.id}`);\n }\n const offset = getScrollOffset();\n scrollToElement(targetElement, offset);\n }\n }\n\n // Handle anchor link clicks and keyboard activation\n function handleAnchorClicks(): void {\n clickHandler = handleAnchorActivation;\n keydownHandler = (e: KeyboardEvent): void => {\n if (e.key === 'Enter' || e.key === ' ') {\n handleAnchorActivation(e);\n }\n };\n\n document.addEventListener('click', clickHandler);\n document.addEventListener('keydown', keydownHandler);\n }\n\n // Initialize anchor link handling\n handleAnchorClicks();\n\n return {\n result: 'autoInit-smooth-scroll initialized',\n destroy: () => {\n // Remove event listeners\n if (clickHandler) {\n document.removeEventListener('click', clickHandler);\n clickHandler = null;\n }\n if (keydownHandler) {\n document.removeEventListener('keydown', keydownHandler);\n keydownHandler = null;\n }\n\n // Re-enable CSS smooth scrolling\n document.documentElement.style.scrollBehavior = '';\n document.body.style.scrollBehavior = '';\n },\n };\n}\n","/**\n * Dropdown\n *\n * Provides accessible navigation dropdowns with hover or click behavior.\n * Handles ARIA states, keyboard navigation, optional height animation,\n * and automatic focus management for both desktop hover and mobile click modes.\n *\n * Features:\n * - Hover mode: Desktop hover with full keyboard navigation (ArrowDown/Up, Escape)\n * - Click mode: Mobile/accordion click-only with simple keyboard (Space, Enter, Escape)\n * - Automatic ARIA state management (aria-expanded, aria-controls, role=menu)\n * - Optional height animation via data-hs-height wrapper\n * - Inert state for collapsed dropdowns (non-interactive)\n * - MutationObserver syncs ARIA with visual state changes\n * - Focus management for keyboard and screen reader users\n *\n * Structure:\n * <div data-hs-nav-dropdown=\"wrapper\" data-hs-nav-dropdown-type=\"hover\">\n * <button data-hs-clickable=\"button\">Menu</button>\n * <div data-hs-nav-dropdown=\"list\" role=\"menu\">\n * <a href=\"#\" data-hs-clickable=\"button\" role=\"menuitem\">Item 1</a>\n * <a href=\"#\" data-hs-clickable=\"button\" role=\"menuitem\">Item 2</a>\n * </div>\n * </div>\n */\n\nimport {\n querySelectorAll,\n querySelector,\n getSelector,\n globalConfig,\n animateHeight,\n setHeight,\n} from '@utils';\n\ninterface EventHandler {\n element: Element;\n event: string;\n handler: EventListener;\n options?: AddEventListenerOptions;\n}\n\ninterface ModuleConfig {\n attributes: {\n elements: Record<string, { primary: string; aliases?: string[] }>;\n properties?: Record<string, string>;\n };\n}\n\n// Module-scoped config (set during init)\nlet moduleConfig: ModuleConfig | null = null;\n\nexport function init(config: ModuleConfig) {\n // Store config at module scope for helper functions\n moduleConfig = config;\n\n const cleanup = {\n observers: [] as MutationObserver[],\n handlers: [] as EventHandler[],\n };\n\n const addObserver = (observer: MutationObserver): void => {\n cleanup.observers.push(observer);\n };\n const addHandler = (\n element: Element,\n event: string,\n handler: EventListener,\n options?: AddEventListenerOptions\n ): void => {\n element.addEventListener(event, handler, options);\n cleanup.handlers.push({ element, event, handler, options });\n };\n\n function sanitizeForID(text: string): string {\n return text\n .toLowerCase()\n .replace(/[^a-z0-9\\s]/g, '')\n .replace(/\\s+/g, '-')\n .replace(/^-+|-+$/g, '')\n .substring(0, 50);\n }\n\n function setupDropdown(\n addObserver: (observer: MutationObserver) => void,\n addHandler: (\n element: Element,\n event: string,\n handler: EventListener,\n options?: AddEventListenerOptions\n ) => void\n ): void {\n const dropdownWrappers = querySelectorAll(moduleConfig as any, 'wrapper');\n const hoverDropdowns: Element[] = []; // Track hover-type dropdowns for focus-loss handling\n\n dropdownWrappers.forEach((wrapper) => {\n const clickableSelector = getSelector(globalConfig.clickable as any, 'button');\n const toggle = wrapper.querySelector(clickableSelector);\n const dropdownList = querySelector(moduleConfig as any, 'list', wrapper);\n\n if (!toggle || !dropdownList) {\n console.warn('[dropdown] Dropdown wrapper missing required elements:', wrapper);\n return;\n }\n\n // Get dropdown type (hover or click)\n const type = wrapper.getAttribute('data-hs-nav-dropdown-type') || 'hover';\n\n // Check for visual height wrapper (contains data-hs-height=\"element\")\n // If found, animate that instead of the list (list is for ARIA only)\n // If not found, no height animation (optional feature)\n const heightWrapper = wrapper.querySelector('[data-hs-height=\"element\"]');\n const animationTarget = heightWrapper ? heightWrapper.parentElement : null;\n\n const toggleText = toggle.textContent?.trim() || 'dropdown';\n const sanitizedText = sanitizeForID(toggleText);\n const toggleId = `navbar-dropdown-${sanitizedText}-toggle`;\n const listId = `navbar-dropdown-${sanitizedText}-list`;\n\n toggle.id = toggleId;\n toggle.setAttribute('aria-haspopup', 'menu');\n toggle.setAttribute('aria-expanded', 'false');\n toggle.setAttribute('aria-controls', listId);\n\n dropdownList.id = listId;\n dropdownList.setAttribute('role', 'menu');\n (dropdownList as HTMLElement).inert = true; // Initial state: hidden and non-interactive\n\n const menuItems = Array.from(dropdownList.querySelectorAll(clickableSelector));\n menuItems.forEach((item, index) => {\n item.setAttribute('role', 'menuitem');\n item.setAttribute('tabindex', '-1');\n\n // Add context for first item to help screen readers understand dropdown content\n if (index === 0) {\n const toggleText = toggle.textContent?.trim() || 'menu';\n const existingLabel = item.getAttribute('aria-label');\n if (!existingLabel) {\n item.setAttribute('aria-label', `${item.textContent?.trim()}, ${toggleText} submenu`);\n }\n }\n });\n\n let currentMenuItemIndex = -1;\n\n // Function to check if dropdown is open\n function isDropdownOpen() {\n return wrapper.classList.contains(globalConfig.classes.active);\n }\n\n // Update ARIA states based on current visual state\n function updateARIAStates() {\n const isOpen = isDropdownOpen();\n const wasOpen = toggle.getAttribute('aria-expanded') === 'true';\n\n // If dropdown is closing (was open, now closed), focus the toggle first\n if (wasOpen && !isOpen && dropdownList.contains(document.activeElement)) {\n (toggle as HTMLElement).focus();\n }\n\n toggle.setAttribute('aria-expanded', isOpen ? 'true' : 'false');\n (dropdownList as HTMLElement).inert = !isOpen; // Enable/disable interaction based on state\n menuItems.forEach((item) => {\n item.setAttribute('tabindex', isOpen ? '0' : '-1');\n });\n\n if (!isOpen) {\n currentMenuItemIndex = -1;\n }\n\n // Animate height wrapper (visual container, not ARIA list)\n animateHeight(animationTarget, isOpen, {\n duration: type === 'hover' ? 200 : 300,\n ease: 'power2.inOut',\n });\n }\n\n // Set initial height without animation\n setHeight(animationTarget, isDropdownOpen());\n\n // Set initial ARIA states\n updateARIAStates();\n\n // Monitor for class changes and update ARIA states\n const observer = new MutationObserver(() => {\n updateARIAStates();\n });\n\n observer.observe(wrapper, {\n attributes: true,\n attributeFilter: ['class'],\n });\n\n addObserver(observer);\n\n // ========================================\n // TYPE-SPECIFIC HANDLERS\n // ========================================\n\n if (type === 'hover') {\n // HOVER TYPE: Desktop behavior with hover + full keyboard navigation\n\n // Track this as a hover dropdown for focus-loss handling\n hoverDropdowns.push(wrapper);\n\n // Hover handlers\n const mouseenterHandler = () => {\n wrapper.classList.add('is-active');\n };\n\n const mouseleaveHandler = () => {\n wrapper.classList.remove('is-active');\n };\n\n addHandler(wrapper, 'mouseenter', mouseenterHandler);\n addHandler(wrapper, 'mouseleave', mouseleaveHandler);\n\n // Full keyboard navigation for toggle\n const toggleKeydownHandler = (e: KeyboardEvent): void => {\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n\n if (!isDropdownOpen()) {\n wrapper.classList.add(globalConfig.classes.active);\n\n // Focus first menu item after brief delay\n if (menuItems.length > 0) {\n setTimeout(() => {\n currentMenuItemIndex = 0;\n (menuItems[0] as HTMLElement).focus();\n }, 100);\n }\n }\n } else if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault();\n\n if (!isDropdownOpen()) {\n wrapper.classList.add(globalConfig.classes.active);\n\n // Focus first menu item after brief delay\n if (menuItems.length > 0) {\n setTimeout(() => {\n currentMenuItemIndex = 0;\n (menuItems[0] as HTMLElement).focus();\n }, 100);\n }\n } else {\n wrapper.classList.remove(globalConfig.classes.active);\n }\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n\n if (!isDropdownOpen()) {\n wrapper.classList.add(globalConfig.classes.active);\n\n // Focus last menu item after brief delay\n if (menuItems.length > 0) {\n setTimeout(() => {\n currentMenuItemIndex = menuItems.length - 1;\n (menuItems[currentMenuItemIndex] as HTMLElement).focus();\n }, 100);\n }\n }\n } else if (e.key === 'Escape') {\n e.preventDefault();\n\n if (isDropdownOpen()) {\n wrapper.classList.remove(globalConfig.classes.active);\n }\n }\n };\n\n addHandler(toggle, 'keydown', toggleKeydownHandler);\n\n // Handle navigation within open dropdown (arrow keys)\n const dropdownKeydownHandler = (e: KeyboardEvent): void => {\n if (!isDropdownOpen()) return;\n if (!wrapper.contains(document.activeElement)) return;\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n if (currentMenuItemIndex < menuItems.length - 1) {\n currentMenuItemIndex++;\n (menuItems[currentMenuItemIndex] as HTMLElement).focus();\n }\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n if (currentMenuItemIndex === 0) {\n wrapper.classList.remove(globalConfig.classes.active);\n (toggle as HTMLElement).focus();\n currentMenuItemIndex = -1;\n } else if (currentMenuItemIndex > 0) {\n currentMenuItemIndex--;\n (menuItems[currentMenuItemIndex] as HTMLElement).focus();\n } else {\n (toggle as HTMLElement).focus();\n currentMenuItemIndex = -1;\n }\n } else if (e.key === 'Escape') {\n e.preventDefault();\n wrapper.classList.remove('is-active');\n }\n };\n\n addHandler(wrapper, 'keydown', dropdownKeydownHandler);\n } else if (type === 'click') {\n // CLICK TYPE: Mobile/accordion behavior with click only + simple keyboard\n\n // Click handler to toggle\n const clickHandler = (e: MouseEvent): void => {\n e.preventDefault();\n wrapper.classList.toggle(globalConfig.classes.active);\n };\n\n addHandler(toggle, 'click', clickHandler);\n\n // Simple keyboard navigation (NO arrow keys)\n const toggleKeydownHandler = (e: KeyboardEvent): void => {\n if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault();\n wrapper.classList.toggle(globalConfig.classes.active);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n if (isDropdownOpen()) {\n wrapper.classList.remove(globalConfig.classes.active);\n }\n }\n };\n\n addHandler(toggle, 'keydown', toggleKeydownHandler);\n }\n });\n\n // Close hover dropdowns when focus leaves (click dropdowns stay open)\n const focusinHandler = (e: FocusEvent): void => {\n hoverDropdowns.forEach((wrapper) => {\n if (wrapper.classList.contains('is-active') && !wrapper.contains(e.target as Node)) {\n wrapper.classList.remove('is-active');\n }\n });\n };\n\n // Only add handler if there are hover dropdowns\n if (hoverDropdowns.length > 0) {\n addHandler(document.body, 'focusin', focusinHandler);\n }\n }\n\n setupDropdown(addObserver, addHandler);\n\n return {\n result: 'dropdown initialized',\n destroy: () => {\n // Disconnect all observers\n cleanup.observers.forEach((obs) => obs.disconnect());\n cleanup.observers.length = 0;\n\n // Remove all event listeners\n cleanup.handlers.forEach(({ element, event, handler, options }) => {\n element.removeEventListener(event, handler, options);\n });\n cleanup.handlers.length = 0;\n\n // Clear module config\n moduleConfig = null;\n },\n };\n}\n","/**\n * Menu\n *\n * Provides mobile menu button and modal behavior for navigation.\n * Handles menu toggle with modal overlay, focus trap, ARIA states,\n * and automatic inert management for collapsed dropdowns in the menu.\n *\n * Features:\n * - Modal behavior with overlay and body scroll lock\n * - Focus trap keeps keyboard navigation within open menu\n * - ARIA state management (aria-expanded, aria-controls)\n * - Inert state for collapsed menu dropdowns (non-interactive)\n * - MutationObserver syncs inert state with dropdown visual state\n * - Escape key to close menu\n * - Returns focus to menu button on close\n *\n * Structure:\n * <button data-hs-nav-menu=\"button\">Menu</button>\n * <div data-hs-nav-menu=\"wrapper\" aria-labelledby=\"menu-button\">\n * <!-- Menu content with dropdowns -->\n * </div>\n */\n\nimport {\n querySelectorAll,\n querySelector,\n getSelector,\n globalConfig,\n cssVariables,\n animateHeight,\n setHeight,\n openModal,\n closeModal,\n} from '@utils';\n\ninterface EventHandler {\n element: Element | Document;\n event: string;\n handler: EventListener;\n options?: AddEventListenerOptions;\n}\n\ninterface ModuleConfig {\n attributes: {\n elements: Record<string, { primary: string; aliases?: string[] }>;\n };\n}\n\nexport function init(config: ModuleConfig, navbarConfig?: ModuleConfig) {\n const cleanup = {\n observers: [] as MutationObserver[],\n handlers: [] as EventHandler[],\n state: {\n focusTrapHandler: null as ((e: KeyboardEvent) => void) | null,\n },\n };\n\n const addObserver = (observer: MutationObserver): void => {\n cleanup.observers.push(observer);\n };\n const addHandler = (\n element: Element | Document,\n event: string,\n handler: EventListener,\n options?: AddEventListenerOptions\n ): void => {\n element.addEventListener(event, handler, options);\n cleanup.handlers.push({ element, event, handler, options });\n };\n\n function createFocusTrap(menuButton: Element): ((e: KeyboardEvent) => void) | undefined {\n const navbarWrapper = navbarConfig\n ? querySelector(navbarConfig as any, 'wrapper')\n : document.querySelector('[data-hs-nav=\"wrapper\"]');\n\n if (!navbarWrapper) return;\n\n const focusTrapHandler = (e: KeyboardEvent): void => {\n if (e.key === 'Tab') {\n const clickableSelector = getSelector(globalConfig.clickable as any, 'button');\n const clickableItems = Array.from(navbarWrapper.querySelectorAll(clickableSelector));\n const formElements = navbarWrapper.querySelectorAll(\n 'input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\n );\n const focusableArray = [...clickableItems, ...Array.from(formElements)];\n const firstElement = focusableArray[0];\n const lastElement = focusableArray[focusableArray.length - 1];\n\n if (e.shiftKey) {\n // Shift+Tab: moving backwards\n if (document.activeElement === firstElement) {\n e.preventDefault();\n (lastElement as HTMLElement).focus();\n }\n } else {\n // Tab: moving forwards\n if (document.activeElement === lastElement) {\n e.preventDefault();\n (firstElement as HTMLElement).focus();\n }\n }\n }\n };\n\n document.addEventListener('keydown', focusTrapHandler);\n return focusTrapHandler;\n }\n\n function removeFocusTrap(focusTrapHandler: ((e: KeyboardEvent) => void) | null): void {\n if (focusTrapHandler) {\n document.removeEventListener('keydown', focusTrapHandler);\n }\n }\n\n function setupMenu(\n addObserver: (observer: MutationObserver) => void,\n addHandler: (\n element: Element | Document,\n event: string,\n handler: EventListener,\n options?: AddEventListenerOptions\n ) => void\n ): void {\n const menuButtons = querySelectorAll(config as any, 'button');\n const menu = querySelector(config as any, 'wrapper');\n\n if (!menuButtons.length || !menu) return;\n\n // Get navbar wrapper for styling (e.g., backdrop blur)\n const navbarWrapper = navbarConfig ? querySelector(navbarConfig as any, 'wrapper') : null;\n\n const menuId = `menu-${Date.now()}`;\n\n menu.id = menuId;\n menu.setAttribute('role', 'dialog');\n menu.setAttribute('aria-modal', 'true');\n (menu as HTMLElement).inert = true; // Initial state: hidden and non-interactive\n\n // Check for visual height wrapper (optional)\n // Only look for a descendant with data-hs-height=\"element\"\n // If found, animate that element's parent. If not found, no height animation.\n const heightWrapper = menu.querySelector('[data-hs-height=\"element\"]');\n const animationTarget = heightWrapper ? heightWrapper.parentElement : null;\n\n menuButtons.forEach((menuButton) => {\n menuButton.setAttribute('aria-expanded', 'false');\n menuButton.setAttribute('aria-controls', menuId);\n menuButton.setAttribute('aria-label', 'Open navigation menu');\n\n let focusTrapHandler: ((e: KeyboardEvent) => void) | null = null;\n let shouldAutoFocus: boolean | 'last' = false; // Track if menu should autofocus (keyboard activation)\n\n // Check if menu is open by looking for is-active class on button\n function isMenuOpen() {\n return menuButton.classList.contains(globalConfig.classes.active);\n }\n\n // Update ARIA states and menu behavior based on current visual state\n function updateMenuState() {\n const isOpen = isMenuOpen();\n const wasOpen = menuButton.getAttribute('aria-expanded') === 'true';\n\n if (isOpen && !wasOpen) {\n // Opening\n openModal();\n\n // Add is-active to menu wrapper and enable interaction\n menu.classList.add(globalConfig.classes.active);\n (menu as HTMLElement).inert = false; // Enable interaction\n\n // Add class to navbar wrapper for styling (e.g., backdrop blur)\n if (navbarWrapper) {\n navbarWrapper.classList.add('hs-menu-open');\n }\n\n menuButtons.forEach((btn) => {\n btn.setAttribute('aria-expanded', 'true');\n btn.setAttribute('aria-label', 'Close navigation menu');\n });\n\n // Animate height if configured\n if (animationTarget) {\n animateHeight(animationTarget, true, { duration: 300, ease: 'power2.inOut' });\n }\n\n // Create focus trap for navbar\n focusTrapHandler = createFocusTrap(menuButton);\n\n // Only autofocus for keyboard activation\n if (shouldAutoFocus) {\n setTimeout(() => {\n const menuClickableSelector = getSelector(globalConfig.clickable as any, 'button');\n const allElements = Array.from(menu.querySelectorAll(menuClickableSelector));\n\n if (shouldAutoFocus === 'last') {\n // Focus last item (ArrowUp)\n const lastElement = allElements[allElements.length - 1];\n if (lastElement) {\n (lastElement as HTMLElement).focus();\n }\n } else {\n // Focus first item (Space/Enter/ArrowDown)\n const firstElement = allElements[0];\n if (firstElement) {\n (firstElement as HTMLElement).focus();\n }\n }\n }, 100);\n shouldAutoFocus = false; // Reset flag\n }\n } else if (!isOpen && wasOpen) {\n // Closing - focus button BEFORE updating ARIA\n if (menu.contains(document.activeElement)) {\n (menuButton as HTMLElement).focus();\n }\n\n // Now update ARIA and visual state\n closeModal();\n\n // Remove is-active from menu wrapper and disable interaction\n menu.classList.remove(globalConfig.classes.active);\n (menu as HTMLElement).inert = true; // Disable interaction\n\n // Remove class from navbar wrapper\n if (navbarWrapper) {\n navbarWrapper.classList.remove('hs-menu-open');\n }\n\n menuButtons.forEach((btn) => {\n btn.setAttribute('aria-expanded', 'false');\n btn.setAttribute('aria-label', 'Open navigation menu');\n });\n\n // Animate height if configured\n if (animationTarget) {\n animateHeight(animationTarget, false, { duration: 300, ease: 'power2.inOut' });\n }\n\n // Remove focus trap\n removeFocusTrap(focusTrapHandler);\n focusTrapHandler = null;\n }\n }\n\n // Set initial height without animation (if configured)\n if (animationTarget) {\n setHeight(animationTarget, isMenuOpen());\n }\n\n // Set initial ARIA states\n updateMenuState();\n\n // Monitor for class changes on button and update menu state\n const observer = new MutationObserver(() => {\n updateMenuState();\n });\n\n observer.observe(menuButton, {\n attributes: true,\n attributeFilter: ['class'],\n });\n\n addObserver(observer);\n\n // Click handler\n const clickHandler = function (e) {\n e.preventDefault();\n menuButton.classList.toggle('is-active');\n };\n\n addHandler(menuButton, 'click', clickHandler);\n\n // Keyboard navigation (dialog/modal pattern)\n const keydownHandler = function (e) {\n if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault();\n shouldAutoFocus = true; // Set flag for keyboard activation\n menuButton.classList.toggle(globalConfig.classes.active);\n } else if (e.key === 'ArrowDown') {\n e.preventDefault();\n if (!isMenuOpen()) {\n shouldAutoFocus = true; // Open and focus first item\n menuButton.classList.add(globalConfig.classes.active);\n }\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n if (!isMenuOpen()) {\n shouldAutoFocus = 'last'; // Open and focus last item\n menuButton.classList.add(globalConfig.classes.active);\n }\n } else if (e.key === 'Escape') {\n e.preventDefault();\n\n if (isMenuOpen()) {\n menuButton.classList.remove(globalConfig.classes.active);\n }\n }\n };\n\n addHandler(menuButton, 'keydown', keydownHandler);\n\n // Store focus trap handler for cleanup\n cleanup.state.focusTrapHandler = focusTrapHandler;\n });\n }\n\n function setupMenuDisplayObserver(addObserver) {\n const menu = querySelector(config, 'wrapper');\n if (!menu) return;\n\n let previousState = null;\n\n function handleStateChange() {\n const computedStyle = window.getComputedStyle(menu);\n const currentState = computedStyle.getPropertyValue(cssVariables.state).trim();\n\n // Detect state change from active (1) to inactive (0)\n if (\n previousState === globalConfig.cssVars.state.values.active &&\n currentState === globalConfig.cssVars.state.values.inactive\n ) {\n // Get menu button to check if menu is open\n const menuButton = document.querySelector('[data-hs-nav-menu=\"button\"]');\n const isMenuOpen = menuButton && menuButton.getAttribute('aria-expanded') === 'true';\n\n // If menu is open, close it cleanly (triggers animation and proper cleanup)\n if (isMenuOpen && menuButton) {\n menuButton.classList.remove('is-active');\n }\n }\n\n previousState = currentState;\n }\n\n const stateObserver = new ResizeObserver(handleStateChange);\n stateObserver.observe(menu);\n addObserver(stateObserver);\n // Initial check\n handleStateChange();\n }\n\n setupMenu(addObserver, addHandler);\n setupMenuDisplayObserver(addObserver);\n\n return {\n result: 'menu initialized',\n destroy: () => {\n // Clean up focus trap\n if (cleanup.state.focusTrapHandler) {\n document.removeEventListener('keydown', cleanup.state.focusTrapHandler);\n cleanup.state.focusTrapHandler = null;\n }\n\n // Disconnect all observers\n cleanup.observers.forEach((obs) => obs.disconnect());\n cleanup.observers.length = 0;\n\n // Remove all event listeners\n cleanup.handlers.forEach(({ element, event, handler, options }) => {\n element.removeEventListener(event, handler, options);\n });\n cleanup.handlers.length = 0;\n\n // Remove body overflow class if present\n document.body.classList.remove('u-overflow-hidden');\n },\n };\n}\n","/**\n * Arrow Navigation\n *\n * Provides keyboard arrow navigation for navbar and mobile menu.\n * Handles ArrowLeft/Right in desktop navbar and ArrowUp/Down in mobile menu,\n * plus Home/End/Escape keys for complete keyboard accessibility.\n *\n * Features:\n * - Desktop: ArrowLeft/Right to navigate navbar items\n * - Mobile menu: ArrowUp/Down, Home/End navigation\n * - Skips hidden elements and inactive dropdowns\n * - Respects inert state for collapsed accordions\n * - Escape to close mobile menu\n * - ArrowLeft/Right to collapse/expand mobile dropdowns\n */\n\nimport { getSelector, globalConfig, querySelector } from '@utils';\n\ninterface EventHandler {\n element: Element | Document;\n event: string;\n handler: EventListener;\n options?: AddEventListenerOptions;\n}\n\ninterface ModuleConfig {\n attributes: {\n elements: Record<string, { primary: string; aliases?: string[] }>;\n };\n}\n\ninterface NavbarConfig {\n attributes: {\n elements: {\n wrapper: { primary: string; aliases?: string[] };\n 'skip-link': { primary: string; aliases?: string[] };\n };\n };\n menu: ModuleConfig;\n}\n\nexport function init(config: ModuleConfig, navbarConfig?: NavbarConfig) {\n const cleanup = {\n handlers: [] as EventHandler[],\n };\n\n const addHandler = (\n element: Element | Document,\n event: string,\n handler: EventListener,\n options?: AddEventListenerOptions\n ): void => {\n element.addEventListener(event, handler, options);\n cleanup.handlers.push({ element, event, handler, options });\n };\n\n function setupDesktopArrowNavigation(\n addHandler: (\n element: Element | Document,\n event: string,\n handler: EventListener,\n options?: AddEventListenerOptions\n ) => void\n ): void {\n const keydownHandler = (e: KeyboardEvent): void => {\n if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return;\n\n const menu = navbarConfig\n ? querySelector(navbarConfig.menu as any, 'wrapper')\n : document.querySelector('[data-hs-nav-menu=\"wrapper\"]');\n if (menu && menu.contains(document.activeElement)) return;\n\n const navbar = navbarConfig\n ? querySelector(navbarConfig as any, 'wrapper')\n : document.querySelector('[data-hs-nav=\"wrapper\"]');\n\n if (!navbar || !navbar.contains(document.activeElement)) return;\n\n // Check if focus is inside an open dropdown (using .is-active class)\n const openDropdown = navbar.querySelector(\n `.${globalConfig.classes.active}[data-hs-nav-dropdown]`\n );\n if (openDropdown && openDropdown.contains(document.activeElement)) return;\n\n e.preventDefault();\n\n const clickableSelector = getSelector(globalConfig.clickable as any, 'button');\n const allNavbarElements = Array.from(navbar.querySelectorAll(clickableSelector));\n const focusableElements = Array.from(allNavbarElements).filter((el) => {\n if (el.getAttribute('tabindex') === '-1') return false;\n\n const isInDropdownList = el.closest('[role=\"menu\"]');\n if (isInDropdownList) return false;\n\n const menuSelector = navbarConfig\n ? navbarConfig.menu.attributes.elements.wrapper.primary.split('=')[0]\n : 'data-hs-nav-menu';\n const isInMenu = el.closest(`[${menuSelector}=\"wrapper\"]`);\n if (isInMenu) return false;\n\n const skipSelector = navbarConfig\n ? navbarConfig.attributes.elements['skip-link'].primary.split('=')[0]\n : 'data-hs-nav';\n const isInSkipLink = el.closest(`[${skipSelector}=\"skip-link\"]`);\n if (isInSkipLink) return false;\n\n const computedStyle = window.getComputedStyle(el);\n const htmlEl = el as HTMLElement;\n const isHidden =\n computedStyle.display === 'none' ||\n computedStyle.visibility === 'hidden' ||\n computedStyle.opacity === '0' ||\n htmlEl.offsetWidth === 0 ||\n htmlEl.offsetHeight === 0;\n if (isHidden) return false;\n\n let parent = el.parentElement;\n while (parent && parent !== navbar) {\n const parentStyle = window.getComputedStyle(parent);\n const parentHtmlEl = parent as HTMLElement;\n const parentHidden =\n parentStyle.display === 'none' ||\n parentStyle.visibility === 'hidden' ||\n parentHtmlEl.offsetWidth === 0 ||\n parentHtmlEl.offsetHeight === 0;\n if (parentHidden) return false;\n parent = parent.parentElement;\n }\n\n return true;\n });\n\n const currentIndex = focusableElements.indexOf(document.activeElement as Element);\n if (currentIndex === -1) return;\n\n if (e.key === 'ArrowRight') {\n if (currentIndex < focusableElements.length - 1) {\n const nextIndex = currentIndex + 1;\n (focusableElements[nextIndex] as HTMLElement).focus();\n }\n } else {\n if (currentIndex > 0) {\n const nextIndex = currentIndex - 1;\n (focusableElements[nextIndex] as HTMLElement).focus();\n }\n }\n };\n\n addHandler(document, 'keydown', keydownHandler);\n }\n\n function setupMenuArrowNavigation(\n addHandler: (\n element: Element | Document,\n event: string,\n handler: EventListener,\n options?: AddEventListenerOptions\n ) => void\n ): void {\n const menuContainer = navbarConfig\n ? querySelector(navbarConfig.menu as any, 'wrapper')\n : document.querySelector('[data-hs-nav-menu=\"wrapper\"]');\n if (!menuContainer) return;\n\n function getFocusableElements(): Element[] {\n const menuClickableSelector = getSelector(globalConfig.clickable as any, 'button');\n const allElements = Array.from(menuContainer.querySelectorAll(menuClickableSelector));\n return Array.from(allElements).filter((el) => {\n // Check if element or any ancestor is inert (inactive dropdown)\n let current: Element | null = el;\n while (current && current !== menuContainer) {\n if ((current as HTMLElement).inert) {\n return false;\n }\n current = current.parentElement;\n }\n return true;\n });\n }\n\n let currentFocusIndex = -1;\n\n const keydownHandler = (e: KeyboardEvent): void => {\n const focusableElements = getFocusableElements();\n if (focusableElements.length === 0) return;\n\n const activeElement = document.activeElement;\n currentFocusIndex = focusableElements.indexOf(activeElement as Element);\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n if (currentFocusIndex < focusableElements.length - 1) {\n currentFocusIndex = currentFocusIndex + 1;\n (focusableElements[currentFocusIndex] as HTMLElement).focus();\n }\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n if (currentFocusIndex > 0) {\n currentFocusIndex = currentFocusIndex - 1;\n (focusableElements[currentFocusIndex] as HTMLElement).focus();\n }\n } else if (e.key === 'ArrowRight') {\n e.preventDefault();\n if (\n activeElement &&\n (activeElement as HTMLElement).tagName === 'BUTTON' &&\n activeElement.hasAttribute('aria-controls')\n ) {\n const isExpanded = activeElement.getAttribute('aria-expanded') === 'true';\n if (!isExpanded) {\n (activeElement as HTMLElement).click();\n }\n return;\n }\n } else if (e.key === 'ArrowLeft') {\n e.preventDefault();\n if (\n activeElement &&\n (activeElement as HTMLElement).tagName === 'BUTTON' &&\n activeElement.hasAttribute('aria-controls')\n ) {\n const isExpanded = activeElement.getAttribute('aria-expanded') === 'true';\n if (isExpanded) {\n (activeElement as HTMLElement).click();\n }\n return;\n }\n } else if (e.key === 'Home') {\n e.preventDefault();\n currentFocusIndex = 0;\n (focusableElements[0] as HTMLElement).focus();\n } else if (e.key === 'End') {\n e.preventDefault();\n currentFocusIndex = focusableElements.length - 1;\n (focusableElements[focusableElements.length - 1] as HTMLElement).focus();\n } else if (e.key === ' ' && activeElement && (activeElement as HTMLElement).tagName === 'A') {\n e.preventDefault();\n } else if (e.key === 'Escape') {\n const menuButton = navbarConfig\n ? querySelector(navbarConfig.menu as any, 'button')\n : document.querySelector('[data-hs-nav-menu=\"button\"]');\n if (menuButton) {\n (menuButton as HTMLElement).click();\n (menuButton as HTMLElement).focus();\n }\n }\n };\n\n addHandler(menuContainer, 'keydown', keydownHandler);\n }\n\n setupDesktopArrowNavigation(addHandler);\n setupMenuArrowNavigation(addHandler);\n\n return {\n result: 'arrow-navigation initialized',\n destroy: () => {\n // Remove all event listeners\n cleanup.handlers.forEach(({ element, event, handler, options }) => {\n element.removeEventListener(event, handler, options);\n });\n cleanup.handlers.length = 0;\n },\n };\n}\n","/**\n * Navbar Orchestrator\n * Manages navigation functions in parallel\n *\n * Uses static imports and passes config down to functions\n */\nimport { init as dropdownInit } from './functions/dropdown.ts';\nimport { init as menuInit } from './functions/menu.ts';\nimport { init as arrowNavigationInit } from './functions/arrow-navigation.ts';\n\nexport async function init(navbarConfig) {\n const cleanup = { destroyFunctions: [] };\n\n // Load all functions in parallel - use allSettled for resilient loading\n const results = await Promise.allSettled([\n dropdownInit(navbarConfig.dropdown),\n menuInit(navbarConfig.menu, navbarConfig),\n arrowNavigationInit(navbarConfig['arrow-navigation'], navbarConfig),\n ]);\n\n // Collect destroy functions from successful inits\n results.forEach((result) => {\n if (result.status === 'fulfilled' && result.value?.destroy) {\n cleanup.destroyFunctions.push(result.value.destroy);\n }\n });\n\n // Log summary\n const succeeded = results.filter((r) => r.status === 'fulfilled').length;\n const failed = results.length - succeeded;\n if (failed > 0) {\n console.warn(\n `[navbar] ${succeeded}/${results.length} functions loaded successfully. ${failed} failed but won't affect other functions.`\n );\n }\n\n return {\n result: 'navbar initialized',\n destroy: () => {\n cleanup.destroyFunctions.forEach((destroyFn) => {\n try {\n destroyFn();\n } catch (error) {\n console.error('[navbar] Error during cleanup:', error);\n }\n });\n cleanup.destroyFunctions.length = 0;\n },\n };\n}\n","/**\n * Accordion Module\n *\n * Accessible accordion/collapsible panels with smooth height animations.\n * Syncs ARIA states with visual state via class changes and MutationObserver.\n *\n * Features:\n * - ARIA-compliant (aria-expanded, aria-controls, inert)\n * - Optional button text state swap (open/closed text)\n * - Smooth GSAP height animations\n * - Focus management (returns focus to button when closing)\n * - Default open state support\n *\n * Structure:\n * <div data-hs-accordion=\"wrapper\" data-hs-accordion-default=\"open\">\n * <button data-hs-accordion=\"toggle\">\n * Question\n * <span data-hs-accordion=\"state\">Open</span>\n * </button>\n * <div data-hs-accordion=\"content\">\n * <div data-hs-height=\"element\">Answer content</div>\n * </div>\n * </div>\n */\n\nimport {\n querySelectorAll,\n querySelector,\n getSelector,\n globalConfig,\n animateHeight,\n setHeight,\n} from '@utils';\n\ninterface EventHandler {\n element: Element | Document;\n event: string;\n handler: EventListener;\n options?: AddEventListenerOptions;\n}\n\nexport function init(config: any) {\n const cleanup = {\n observers: [] as MutationObserver[],\n handlers: [] as EventHandler[],\n };\n\n const addObserver = (observer: MutationObserver): number => cleanup.observers.push(observer);\n const addHandler = (\n element: Element | Document,\n event: string,\n handler: EventListener,\n options?: AddEventListenerOptions\n ): void => {\n element.addEventListener(event, handler, options);\n cleanup.handlers.push({ element, event, handler, options });\n };\n\n function setupAccordionAccessibility(\n addObserver: (observer: MutationObserver) => number,\n addHandler: (\n element: Element | Document,\n event: string,\n handler: EventListener,\n options?: AddEventListenerOptions\n ) => void\n ): number {\n const accordionWrappers = querySelectorAll(config, 'wrapper');\n\n if (accordionWrappers.length === 0) {\n return 0;\n }\n\n let initializedCount = 0;\n\n accordionWrappers.forEach((wrapper, index) => {\n const button = querySelector(config, 'toggle', wrapper);\n const content = querySelector(config, 'content', wrapper);\n\n if (!button || !content) {\n return;\n }\n\n initializedCount++;\n\n // Check for visual height wrapper (contains data-hs-height=\"element\")\n // If found, animate that instead of the content (content is for ARIA only)\n const heightSelector = `[${globalConfig.attributes.height}=\"${globalConfig.attributes.heightValue}\"]`;\n const heightWrapper = wrapper.querySelector(heightSelector);\n const animationTarget = heightWrapper ? heightWrapper.parentElement : content;\n\n // Generate unique IDs\n const buttonId = `hs-accordion-btn-${index}`;\n const contentId = `hs-accordion-content-${index}`;\n\n // Get text state attributes (optional)\n const openText = wrapper.getAttribute(config.attributes.properties.open);\n const closedText = wrapper.getAttribute(config.attributes.properties.closed);\n const hasTextSwap = openText && closedText;\n\n // Find all state text elements (if text swap enabled)\n let stateElements = [];\n if (hasTextSwap) {\n const stateSelector = getSelector(config, 'state');\n stateElements = Array.from(button.querySelectorAll(stateSelector));\n }\n\n // Function to update state text elements\n function updateStateText(text: string): void {\n if (!hasTextSwap) return;\n stateElements.forEach((el) => {\n el.textContent = text;\n });\n }\n\n // Set initial IDs and ARIA attributes\n button.setAttribute('id', buttonId);\n content.setAttribute('id', contentId);\n content.setAttribute('role', 'region');\n content.setAttribute('aria-labelledby', buttonId);\n button.setAttribute('aria-controls', contentId);\n\n // Function to check if accordion is open\n function isAccordionOpen() {\n return wrapper.classList.contains(globalConfig.classes.active);\n }\n\n // Update ARIA states based on current visual state\n function updateARIAStates() {\n const isOpen = isAccordionOpen();\n const wasOpen = button.getAttribute('aria-expanded') === 'true';\n\n // If closing and focus is inside content, return focus first\n if (wasOpen && !isOpen && content.contains(document.activeElement)) {\n const buttonEl = button as HTMLElement;\n buttonEl.focus();\n }\n\n // Update ARIA attributes\n button.setAttribute('aria-expanded', isOpen ? 'true' : 'false');\n const contentEl = content as HTMLElement;\n contentEl.inert = !isOpen; // Use inert instead of aria-hidden\n\n // Update state text if text swap enabled\n if (hasTextSwap && stateElements.length > 0) {\n updateStateText(isOpen ? openText : closedText);\n }\n\n // Animate height wrapper (visual container, not ARIA content)\n animateHeight(animationTarget, isOpen, { duration: 300, ease: 'power2.inOut' });\n }\n\n // Handle default open state\n const defaultState = wrapper.getAttribute(config.attributes.properties.default);\n if (defaultState && defaultState.toLowerCase() === 'open') {\n wrapper.classList.add(globalConfig.classes.active);\n }\n\n // Set initial height without animation\n setHeight(animationTarget, isAccordionOpen());\n\n // Set initial state based on existing is-active class\n updateARIAStates();\n\n // Add click handler to button\n const clickHandler = (e: Event) => {\n e.preventDefault();\n wrapper.classList.toggle(globalConfig.classes.active);\n };\n addHandler(button, 'click', clickHandler);\n\n // Monitor for class changes on wrapper\n const observer = new MutationObserver(() => {\n updateARIAStates();\n });\n\n observer.observe(wrapper, {\n attributes: true,\n attributeFilter: ['class'],\n });\n\n addObserver(observer);\n });\n\n return initializedCount;\n }\n\n setupAccordionAccessibility(addObserver, addHandler);\n\n return {\n result: 'accordion initialized',\n destroy: () => {\n // Disconnect all observers\n cleanup.observers.forEach((obs) => obs.disconnect());\n cleanup.observers.length = 0;\n\n // Remove all event listeners\n cleanup.handlers.forEach(({ element, event, handler, options }) => {\n element.removeEventListener(event, handler, options);\n });\n cleanup.handlers.length = 0;\n },\n };\n}\n","/**\n * TOC Heading Links\n *\n * Automatically generates table of contents from H2 headings in rich text.\n * Creates links with smooth scrolling and active state tracking.\n *\n * Features:\n * - Automatically adds IDs to H2 headings based on text content\n * - Generates numbered TOC entries from template item\n * - Active state tracking with IntersectionObserver (25% from top trigger)\n * - Smooth scroll handled by smooth-scroll module\n * - Full cleanup on destroy (removes IDs, observers, handlers)\n */\n\nimport globalConfig from '@config';\nimport { querySelectorAll } from '@utils';\n\nexport function init(config) {\n const activeClass = globalConfig._global.classes.active;\n const cleanup = {\n observers: [],\n handlers: [],\n scrollTimeout: null,\n headings: [],\n };\n\n const addObserver = (observer: IntersectionObserver) => cleanup.observers.push(observer);\n const addHandler = (element: Element | Window, event: string, handler: EventListener) => {\n element.addEventListener(event, handler);\n cleanup.handlers.push({ element, event, handler });\n };\n\n const contentAreas = querySelectorAll(config, 'content');\n const tocLists = querySelectorAll(config, 'list');\n\n contentAreas.forEach((contentArea) => {\n // Since there's only 1 content area and 1 TOC list per page, use the first TOC list\n const tocList = tocLists[0];\n\n if (!tocList || tocList.children.length === 0) {\n return;\n }\n\n const template = tocList.children[0].cloneNode(true) as HTMLElement;\n const templateLink = template.querySelector('a');\n if (templateLink) {\n templateLink.classList.remove(activeClass);\n }\n\n // Clear all original TOC items\n tocList.innerHTML = '';\n\n const h2Headings = contentArea.querySelectorAll('h2');\n\n // Add IDs directly to H2 headings\n h2Headings.forEach((heading) => {\n const sectionId = heading.textContent\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/(^-|-$)/g, '');\n\n heading.id = sectionId;\n cleanup.headings.push(heading);\n });\n\n // Create TOC entries\n h2Headings.forEach((heading, index) => {\n const tocItem = template.cloneNode(true) as HTMLElement;\n const link = tocItem.querySelector('a');\n const sectionId = heading.id;\n link.href = `#${sectionId}`;\n\n // Bold numbered text\n const number = document.createElement('strong');\n number.textContent = `${index + 1}. `;\n\n // Clear the link and add the number + text\n link.innerHTML = '';\n link.appendChild(number);\n link.appendChild(document.createTextNode(heading.textContent));\n\n tocList.appendChild(tocItem);\n });\n\n // Set up IntersectionObserver for active state\n const tocLinks = tocList.querySelectorAll('a');\n let currentActive = null;\n\n const updateActiveLink = () => {\n const windowHeight = window.innerHeight;\n const trigger = windowHeight * 0.25; // 25% from top (natural reading position)\n\n let newActive = null;\n\n // Find the last heading whose top is above the trigger point\n for (let i = h2Headings.length - 1; i >= 0; i--) {\n const rect = h2Headings[i].getBoundingClientRect();\n if (rect.top <= trigger) {\n newActive = h2Headings[i].id;\n break;\n }\n }\n\n // Only update if active section changed\n if (newActive !== currentActive) {\n currentActive = newActive;\n\n // Remove all active classes\n tocLinks.forEach((link) => link.classList.remove(activeClass));\n\n // Add to current\n if (currentActive) {\n const activeLink = Array.from(tocLinks).find(\n (link) => link.getAttribute('href') === `#${currentActive}`\n );\n if (activeLink) {\n activeLink.classList.add(activeClass);\n }\n }\n }\n };\n\n const observerOptions = {\n rootMargin: '-25% 0px -75% 0px',\n threshold: 0,\n };\n\n const observer = new IntersectionObserver(() => {\n updateActiveLink();\n }, observerOptions);\n\n // Observe all headings\n h2Headings.forEach((heading) => observer.observe(heading));\n addObserver(observer);\n\n // Also update on scroll for smoother tracking\n const scrollHandler = () => {\n if (cleanup.scrollTimeout) clearTimeout(cleanup.scrollTimeout);\n cleanup.scrollTimeout = setTimeout(updateActiveLink, 50);\n };\n addHandler(window, 'scroll', scrollHandler);\n });\n\n return {\n result: 'toc initialized',\n destroy: () => {\n // Remove IDs from headings\n cleanup.headings.forEach((heading) => {\n heading.removeAttribute('id');\n });\n cleanup.headings.length = 0;\n\n // Disconnect all observers\n cleanup.observers.forEach((obs) => obs.disconnect());\n cleanup.observers.length = 0;\n\n // Remove all event listeners\n cleanup.handlers.forEach(({ element, event, handler }) => {\n element.removeEventListener(event, handler);\n });\n cleanup.handlers.length = 0;\n\n // Clear scroll timeout\n if (cleanup.scrollTimeout) {\n clearTimeout(cleanup.scrollTimeout);\n cleanup.scrollTimeout = null;\n }\n },\n };\n}\n","/**\n * Table of Contents Orchestrator\n *\n * Loads TOC sub-modules based on element presence.\n * Static imports ensure all modules bundle into single file.\n *\n * Features:\n * - Conditional initialization based on element presence\n * - Centralized cleanup management\n * - Single bundled output file\n *\n * Modules:\n * - heading-links: Main TOC functionality (adds IDs, generates links)\n * - progress-bar: Optional reading progress indicator\n */\n\nimport config from '@config';\nimport { getSelector, type ModuleConfig } from '@utils';\nimport { init as headingLinksInit } from './functions/heading-links.ts';\nimport { init as progressBarInit } from './functions/progress-bar.ts';\n\nexport async function init() {\n const moduleConfig = config.default.toc;\n const cleanup = {\n destroyFunctions: [] as Array<() => void>,\n };\n\n // Initialize heading-links if TOC list exists\n const headingLinksSelector = getSelector(moduleConfig as ModuleConfig, 'list');\n if (document.querySelector(headingLinksSelector)) {\n try {\n const result = await headingLinksInit(moduleConfig);\n if (result?.destroy) {\n cleanup.destroyFunctions.push(result.destroy);\n }\n } catch (error) {\n console.error('[toc] Error initializing heading-links:', error);\n }\n }\n\n // Initialize progress-bar if wrapper exists\n const progressBarSelector = getSelector(moduleConfig['progress-bar'] as ModuleConfig, 'wrapper');\n if (document.querySelector(progressBarSelector)) {\n try {\n const result = await progressBarInit({\n progressConfig: moduleConfig['progress-bar'],\n tocConfig: moduleConfig,\n } as any);\n if (result?.destroy) {\n cleanup.destroyFunctions.push(result.destroy);\n }\n } catch (error) {\n console.error('[toc] Error initializing progress-bar:', error);\n }\n }\n\n return {\n result: `toc initialized (${cleanup.destroyFunctions.length} modules active)`,\n destroy: () => {\n cleanup.destroyFunctions.forEach((destroyFn) => {\n try {\n destroyFn();\n } catch (error) {\n console.error('[toc] Error during cleanup:', error);\n }\n });\n cleanup.destroyFunctions.length = 0;\n },\n };\n}\n","/**\n * Progress Bar\n *\n * Scroll-based progress bar tracking reading progress through content.\n * Uses GSAP ScrollTrigger to animate bar width from 0% to 100%.\n *\n * Structure:\n * <div data-hs-toc=\"content\">\n * <!-- Content to track -->\n * </div>\n * <div data-hs-toc-progress=\"wrapper\">\n * <div data-hs-toc-progress=\"element\"></div>\n * </div>\n */\n\nimport { querySelector, querySelectorAll, getGsap, prefersReducedMotion } from '@utils';\n\ninterface ProgressBarConfig {\n progressConfig: {\n attributes: {\n elements: {\n wrapper: { primary: string; aliases?: string[] };\n element: { primary: string; aliases?: string[] };\n };\n };\n };\n tocConfig: {\n attributes: {\n elements: {\n content: { primary: string; aliases?: string[] };\n };\n };\n };\n}\n\nexport async function init(configObj: ProgressBarConfig) {\n const { progressConfig: config, tocConfig } = configObj;\n\n // Skip if user prefers reduced motion\n if (prefersReducedMotion()) {\n return { result: 'progress-bar skipped - prefers-reduced-motion enabled' };\n }\n\n const gsapLib = getGsap('progress-bar');\n if (!gsapLib) {\n return { result: 'progress-bar skipped - GSAP not loaded' };\n }\n\n const { gsap, ScrollTrigger } = gsapLib;\n\n if (!ScrollTrigger) {\n console.warn('[progress-bar] GSAP ScrollTrigger plugin not loaded');\n return { result: 'progress-bar skipped - ScrollTrigger not loaded' };\n }\n\n gsap.registerPlugin(ScrollTrigger);\n\n const cleanup = {\n scrollTriggers: [] as unknown[],\n };\n\n // Find content area (using toc config since they share the same content)\n const content = querySelector(tocConfig, 'content');\n if (!content) {\n return { result: 'progress-bar skipped - no content element found' };\n }\n\n // Find all progress bar wrappers\n const wrappers = querySelectorAll(config, 'wrapper');\n if (wrappers.length === 0) {\n return { result: 'progress-bar skipped - no wrapper elements found' };\n }\n\n wrappers.forEach((wrapper) => {\n // Show wrapper\n gsap.set(wrapper, { display: 'block' });\n\n // Find progress bar elements inside this wrapper using config\n const progressBars = Array.from(wrapper.querySelectorAll('*')).filter((el) => {\n // Check primary selector\n const primaryAttr = config.attributes.elements.element.primary;\n const [attr, value] = primaryAttr.split('=');\n const cleanValue = value?.replace(/['\"]/g, '');\n return el.getAttribute(attr) === cleanValue;\n });\n\n progressBars.forEach((bar) => {\n // Set initial width to 0%\n gsap.set(bar, { width: '0%' });\n\n // Animate from 0% to 100% based on scroll\n gsap.to(bar, {\n width: '100%',\n ease: 'none',\n scrollTrigger: {\n trigger: content,\n start: 'top bottom', // Start when top of content touches bottom of viewport\n end: 'bottom 75%', // End when bottom of content reaches 75% down the viewport\n scrub: true,\n invalidateOnRefresh: true,\n onUpdate: (self) => {\n // Store the scrollTrigger instance for cleanup\n if (!cleanup.scrollTriggers.includes(self)) {\n cleanup.scrollTriggers.push(self);\n }\n },\n },\n });\n });\n });\n\n return {\n result: `progress-bar initialized (${wrappers.length} instances)`,\n destroy: () => {\n // Kill all scroll triggers\n cleanup.scrollTriggers.forEach((st) => {\n if (st && typeof st === 'object' && 'kill' in st && typeof st.kill === 'function') {\n st.kill();\n }\n });\n cleanup.scrollTriggers.length = 0;\n },\n };\n}\n","/**\n * Pagination\n *\n * Paginated lists with controls, counters, and dot navigation.\n * Supports infinite looping, mobile/desktop layouts, and full accessibility.\n *\n * Features:\n * - Infinite loop navigation with cloned pages\n * - Responsive items-per-page (desktop/mobile breakpoints)\n * - Dot navigation with keyboard support\n * - Live region announcements for screen readers\n * - Auto-hide controls for single page\n * - Dynamic height adjustment\n * - Focus management with inert attribute\n *\n * HTML Structure:\n * <div data-hs-pagination=\"wrapper\">\n * <div data-hs-pagination=\"list\">\n * <!-- Items here -->\n * </div>\n * <div data-hs-pagination=\"controls\" data-hs-pagination-show=\"6\" data-hs-pagination-show-mobile=\"3\">\n * <div data-hs-pagination=\"previous\"><button>Prev</button></div>\n * <div data-hs-pagination=\"counter\"></div>\n * <div data-hs-pagination=\"next\"><button>Next</button></div>\n * </div>\n * <div data-hs-pagination=\"dots\">\n * <div class=\"is-active\">•</div>\n * <div>•</div>\n * </div>\n * </div>\n */\n\nimport { querySelectorAll, querySelector, getSelector, globalConfig, cssVariables } from '@utils';\n\nexport function init(config) {\n const cleanup = {\n observers: [] as ResizeObserver[],\n handlers: [] as Array<{ element: Element; event: string; handler: EventListener }>,\n liveRegions: [] as HTMLElement[],\n };\n\n // Initialize all pagination containers\n try {\n querySelectorAll(config, 'wrapper').forEach((container) => {\n try {\n const instance = initPaginationInstance(container, cleanup, config);\n if (!instance) {\n console.warn('[pagination] Failed to initialize container', container);\n }\n } catch (error) {\n console.error('[pagination] Error initializing container:', error, container);\n }\n });\n } catch (error) {\n console.error('[pagination] Critical error during initialization:', error);\n }\n\n return {\n result: 'pagination initialized',\n destroy: () => {\n try {\n // Remove all live regions\n cleanup.liveRegions.forEach((liveRegion) => {\n try {\n if (liveRegion.parentNode) {\n liveRegion.parentNode.removeChild(liveRegion);\n }\n } catch (error) {\n console.error('[pagination] Error removing live region:', error);\n }\n });\n cleanup.liveRegions.length = 0;\n\n // Disconnect all observers\n cleanup.observers.forEach((obs) => {\n try {\n obs.disconnect();\n } catch (error) {\n console.error('[pagination] Error disconnecting observer:', error);\n }\n });\n cleanup.observers.length = 0;\n\n // Remove all event listeners\n cleanup.handlers.forEach(({ element, event, handler }) => {\n try {\n element.removeEventListener(event, handler);\n } catch (error) {\n console.error('[pagination] Error removing event listener:', error);\n }\n });\n cleanup.handlers.length = 0;\n } catch (error) {\n console.error('[pagination] Critical error during cleanup:', error);\n }\n },\n };\n}\n\nfunction initPaginationInstance(\n container: Element,\n cleanup: {\n observers: ResizeObserver[];\n handlers: Array<{ element: Element; event: string; handler: EventListener }>;\n liveRegions: HTMLElement[];\n },\n config: any\n) {\n const list = querySelector(config, 'list', container) as HTMLElement;\n if (!list) {\n console.warn('[pagination] Missing required element: list');\n return null;\n }\n\n const wrapper = list.parentElement as HTMLElement;\n if (!wrapper) return null;\n\n const elements = {\n controls: querySelector(config, 'controls', container) as HTMLElement | null,\n counter: querySelector(config, 'counter', container) as HTMLElement | null,\n dotsWrap: querySelector(config, 'dots', container) as HTMLElement | null,\n nextButton: null as HTMLElement | null,\n prevButton: null as HTMLElement | null,\n };\n\n // Early exit for infinite mode - no controls means no pagination\n if (!elements.controls) {\n return { initialized: false };\n }\n\n // Find next/previous buttons using clickable pattern\n const nextClickable = querySelector(config, 'next', container);\n const prevClickable = querySelector(config, 'previous', container);\n\n const clickableSelector = getSelector(\n globalConfig.clickable as {\n attributes: { elements: { [key: string]: { primary: string; aliases?: string[] } } };\n },\n 'button'\n );\n const nextButton = (nextClickable?.querySelector(clickableSelector) ||\n nextClickable) as HTMLElement | null;\n const prevButton = (prevClickable?.querySelector(clickableSelector) ||\n prevClickable) as HTMLElement | null;\n\n if (!nextButton || !prevButton) {\n console.warn('[pagination] Missing required navigation buttons');\n return null;\n }\n\n elements.nextButton = nextButton;\n elements.prevButton = prevButton;\n\n // Add ARIA attributes to buttons\n elements.nextButton.setAttribute('aria-label', 'Go to next page');\n elements.prevButton.setAttribute('aria-label', 'Go to previous page');\n if (elements.counter) {\n elements.counter.setAttribute('aria-live', 'polite');\n elements.counter.setAttribute('aria-label', 'Current page');\n }\n\n // Parse configuration from attributes\n const desktopItems =\n parseInt(elements.controls?.getAttribute(config.attributes.properties.show) || '6') || 6;\n const mobileItems =\n parseInt(\n elements.controls?.getAttribute(config.attributes.properties.showMobile) ||\n String(desktopItems)\n ) || desktopItems;\n\n const isMobileLayout = () => {\n const stateValue = getComputedStyle(list).getPropertyValue(cssVariables.state).trim();\n return stateValue === globalConfig.cssVars.state.values.active;\n };\n\n const allItems = Array.from(list.children) as HTMLElement[];\n const totalItems = allItems.length;\n if (!totalItems) return null;\n\n const state = {\n totalPages: 1,\n currentIndex: 1,\n currentPage: 1,\n isAnimating: false,\n itemsPerPage: desktopItems,\n dotTemplates: { active: null as Element | null, inactive: null as Element | null },\n };\n let wrapperChildren: Element[] = [];\n\n // Create live region for announcements\n const liveRegion = document.createElement('div');\n liveRegion.className = 'sr-only';\n liveRegion.setAttribute('aria-live', 'assertive');\n liveRegion.setAttribute('aria-atomic', 'true');\n liveRegion.style.cssText =\n 'position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden;';\n container.appendChild(liveRegion);\n cleanup.liveRegions.push(liveRegion);\n\n const updateCounter = () => {\n if (elements.counter) {\n elements.counter.textContent = `${state.currentPage} / ${state.totalPages}`;\n }\n };\n\n const announcePageChange = () => {\n liveRegion.textContent = `Page ${state.currentPage} of ${state.totalPages}`;\n setTimeout(() => (liveRegion.textContent = ''), 1000);\n };\n\n const manageFocus = () => {\n wrapperChildren.forEach((page, index) => {\n const htmlPage = page as HTMLElement;\n if (index === state.currentIndex) {\n htmlPage.removeAttribute('inert');\n } else {\n htmlPage.setAttribute('inert', '');\n }\n });\n };\n\n const updateHeight = () => {\n const targetPage = wrapperChildren[state.currentIndex] as HTMLElement;\n if (targetPage && targetPage.offsetHeight !== undefined) {\n wrapper.style.height = targetPage.offsetHeight + 'px';\n }\n };\n\n const initializeDots = () => {\n if (!elements.dotsWrap) return;\n\n // Find existing dots as templates\n const existingDots = Array.from(elements.dotsWrap.children);\n if (!existingDots.length) return;\n\n // Identify active and inactive templates\n const activeDot = existingDots.find((dot) => dot.classList.contains('is-active'));\n const inactiveDot = existingDots.find((dot) => !dot.classList.contains('is-active'));\n\n // Store templates (use same template for both if only one exists)\n state.dotTemplates.active = activeDot\n ? (activeDot.cloneNode(true) as Element)\n : (existingDots[0].cloneNode(true) as Element);\n state.dotTemplates.inactive = inactiveDot\n ? (inactiveDot.cloneNode(true) as Element)\n : (existingDots[0].cloneNode(true) as Element);\n\n // Clear existing dots\n elements.dotsWrap.innerHTML = '';\n\n // Add pagination accessibility attributes\n elements.dotsWrap.setAttribute('role', 'group');\n elements.dotsWrap.setAttribute('aria-label', 'Page navigation');\n\n // Create dots for each page\n for (let i = 1; i <= state.totalPages; i++) {\n const dot = (i === 1 ? state.dotTemplates.active : state.dotTemplates.inactive)!.cloneNode(\n true\n ) as HTMLElement;\n\n // Add accessibility attributes\n dot.setAttribute('role', 'button');\n dot.setAttribute('tabindex', '0');\n dot.setAttribute('aria-label', `Go to page ${i}`);\n dot.setAttribute('aria-current', i === 1 ? 'page' : 'false');\n dot.setAttribute('data-page', String(i));\n\n // Set initial active state\n if (i === 1) {\n dot.classList.add('is-active');\n } else {\n dot.classList.remove('is-active');\n }\n\n // Click handler\n const clickHandler = () => navigateToPage(i);\n dot.addEventListener('click', clickHandler);\n cleanup.handlers.push({ element: dot, event: 'click', handler: clickHandler });\n\n // Keyboard handler\n const keyHandler = (e: KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n navigateToPage(i);\n }\n };\n dot.addEventListener('keydown', keyHandler as EventListener);\n cleanup.handlers.push({\n element: dot,\n event: 'keydown',\n handler: keyHandler as EventListener,\n });\n\n elements.dotsWrap.appendChild(dot);\n }\n };\n\n const updateActiveDot = () => {\n if (!elements.dotsWrap) return;\n\n const dots = Array.from(elements.dotsWrap.children);\n dots.forEach((dot, index) => {\n const dotPage = index + 1;\n if (dotPage === state.currentPage) {\n dot.classList.add('is-active');\n dot.setAttribute('aria-current', 'page');\n } else {\n dot.classList.remove('is-active');\n dot.setAttribute('aria-current', 'false');\n }\n });\n };\n\n const initializePagination = (forceItemsPerPage: number | null = null) => {\n const currentIsMobile = isMobileLayout();\n state.itemsPerPage = forceItemsPerPage || (currentIsMobile ? mobileItems : desktopItems);\n state.totalPages = Math.ceil(totalItems / state.itemsPerPage);\n\n // Remove old dot event handlers to prevent memory leaks\n if (elements.dotsWrap) {\n cleanup.handlers = cleanup.handlers.filter(({ element }) => {\n return !elements.dotsWrap!.contains(element);\n });\n }\n\n // Clean up previous page lists\n Array.from(wrapper.children).forEach((child) => {\n if (child !== list) wrapper.removeChild(child);\n });\n list.innerHTML = '';\n allItems.forEach((item) => list.appendChild(item));\n\n // Single page case\n if (state.totalPages <= 1) {\n if (elements.controls) {\n if (elements.controls.contains(document.activeElement) && document.activeElement) {\n (document.activeElement as HTMLElement).blur();\n }\n elements.controls.style.display = 'none';\n elements.controls.setAttribute('aria-hidden', 'true');\n }\n if (elements.dotsWrap) {\n elements.dotsWrap.style.display = 'none';\n elements.dotsWrap.setAttribute('aria-hidden', 'true');\n }\n Object.assign(state, { totalPages: 1, currentIndex: 1, currentPage: 1, isAnimating: false });\n wrapper.style.cssText = `transform: translateX(0%); height: ${list.offsetHeight}px;`;\n wrapperChildren = [list];\n return 1;\n }\n\n // Show controls and dots\n if (elements.controls) {\n elements.controls.style.display = '';\n elements.controls.removeAttribute('aria-hidden');\n }\n if (elements.dotsWrap) {\n elements.dotsWrap.style.display = '';\n elements.dotsWrap.removeAttribute('aria-hidden');\n }\n\n // Create page lists\n const pageLists = Array.from({ length: state.totalPages }, (_, page) => {\n const pageList = list.cloneNode(false) as HTMLElement;\n const startIndex = page * state.itemsPerPage;\n const endIndex = Math.min(startIndex + state.itemsPerPage, totalItems);\n allItems\n .slice(startIndex, endIndex)\n .forEach((item) => pageList.appendChild(item.cloneNode(true)));\n return pageList;\n });\n\n // Insert cloned pages for infinite loop\n wrapper.insertBefore(pageLists[pageLists.length - 1].cloneNode(true), list);\n pageLists.slice(1).forEach((page) => wrapper.appendChild(page));\n wrapper.appendChild(pageLists[0].cloneNode(true));\n\n // Populate original list with first page\n list.innerHTML = '';\n Array.from(pageLists[0].children).forEach((item) => list.appendChild(item as Node));\n\n Object.assign(state, { currentIndex: 1, currentPage: 1, isAnimating: false });\n wrapperChildren = Array.from(wrapper.children);\n\n // Set initial position without animation\n wrapper.style.transition = 'none';\n wrapper.style.transform = 'translateX(-100%)';\n // Force reflow to apply transform immediately\n wrapper.offsetHeight;\n // Re-enable transitions\n wrapper.style.transition = '';\n\n updateCounter();\n updateHeight();\n manageFocus();\n initializeDots();\n return state.totalPages;\n };\n\n let currentLayoutIsMobile = isMobileLayout();\n\n const checkLayoutChange = () => {\n // Prevent resize during animation\n if (state.isAnimating) return;\n\n const newIsMobile = isMobileLayout();\n if (newIsMobile !== currentLayoutIsMobile) {\n currentLayoutIsMobile = newIsMobile;\n initializePagination();\n } else {\n updateHeight();\n }\n };\n\n const resizeObserver = new ResizeObserver(checkLayoutChange);\n resizeObserver.observe(wrapper);\n cleanup.observers.push(resizeObserver);\n\n initializePagination();\n\n const navigateToPage = (targetPage: number) => {\n if (state.isAnimating || state.totalPages <= 1 || targetPage === state.currentPage) return;\n state.isAnimating = true;\n\n state.currentIndex = targetPage;\n state.currentPage = targetPage;\n\n updateCounter();\n announcePageChange();\n updateHeight();\n updateActiveDot();\n\n if (isMobileLayout() && elements.controls) {\n setTimeout(() => {\n const controlsBottom =\n elements.controls.getBoundingClientRect().bottom + window.pageYOffset;\n const clearance = 5 * 16; // 5rem in pixels\n const targetScrollPosition = controlsBottom - window.innerHeight + clearance;\n window.scrollTo({ top: targetScrollPosition, behavior: 'smooth' });\n }, 50);\n }\n\n wrapper.style.transform = `translateX(${-state.currentIndex * 100}%)`;\n\n let transitionTimeout = null;\n\n const handleTransitionEnd = () => {\n clearTimeout(transitionTimeout);\n wrapper.removeEventListener('transitionend', handleTransitionEnd);\n\n updateCounter();\n announcePageChange();\n updateHeight();\n manageFocus();\n updateActiveDot();\n state.isAnimating = false;\n };\n\n // Safety timeout in case transitionend never fires\n transitionTimeout = setTimeout(handleTransitionEnd, 1000);\n\n wrapper.addEventListener('transitionend', handleTransitionEnd);\n };\n\n const navigate = (direction: number) => {\n if (state.isAnimating || state.totalPages <= 1) return;\n state.isAnimating = true;\n state.currentIndex += direction;\n\n state.currentPage =\n state.currentIndex > state.totalPages\n ? 1\n : state.currentIndex < 1\n ? state.totalPages\n : state.currentIndex;\n\n updateCounter();\n announcePageChange();\n updateHeight();\n updateActiveDot();\n\n if (isMobileLayout() && elements.controls) {\n setTimeout(() => {\n const controlsBottom =\n elements.controls.getBoundingClientRect().bottom + window.pageYOffset;\n const clearance = 5 * 16; // 5rem in pixels\n const targetScrollPosition = controlsBottom - window.innerHeight + clearance;\n window.scrollTo({ top: targetScrollPosition, behavior: 'smooth' });\n }, 50);\n }\n\n wrapper.style.transform = `translateX(${-state.currentIndex * 100}%)`;\n\n let transitionTimeout = null;\n\n const handleTransitionEnd = () => {\n clearTimeout(transitionTimeout);\n wrapper.removeEventListener('transitionend', handleTransitionEnd);\n\n if (state.currentIndex > state.totalPages) {\n state.currentIndex = 1;\n state.currentPage = 1;\n // Disable transition for instant jump\n wrapper.style.transition = 'none';\n wrapper.style.transform = 'translateX(-100%)';\n // Force reflow to apply the instant jump\n wrapper.offsetHeight;\n // Re-enable CSS transition\n wrapper.style.transition = '';\n } else if (state.currentIndex < 1) {\n state.currentIndex = state.totalPages;\n state.currentPage = state.totalPages;\n // Disable transition for instant jump\n wrapper.style.transition = 'none';\n wrapper.style.transform = `translateX(${-state.totalPages * 100}%)`;\n // Force reflow to apply the instant jump\n wrapper.offsetHeight;\n // Re-enable CSS transition\n wrapper.style.transition = '';\n }\n\n updateCounter();\n announcePageChange();\n updateHeight();\n manageFocus();\n updateActiveDot();\n state.isAnimating = false;\n };\n\n // Safety timeout in case transitionend never fires\n transitionTimeout = setTimeout(handleTransitionEnd, 1000);\n\n wrapper.addEventListener('transitionend', handleTransitionEnd);\n };\n\n const nextHandler = () => navigate(1);\n const prevHandler = () => navigate(-1);\n\n elements.nextButton.addEventListener('click', nextHandler);\n elements.prevButton.addEventListener('click', prevHandler);\n\n cleanup.handlers.push(\n { element: elements.nextButton, event: 'click', handler: nextHandler },\n { element: elements.prevButton, event: 'click', handler: prevHandler }\n );\n\n return { initialized: true };\n}\n","/**\n * Comparison Module\n *\n * Before/after image comparison slider with GSAP Draggable.\n * Uses template list to manage multiple slides with a single persistent slider.\n *\n * Structure:\n * <!-- Template list (hidden, inside wrapper) -->\n * <div data-hs-comparison=\"wrapper\">\n * <div data-hs-comparison-template=\"list\" class=\"u-display-none\">\n * <div data-hs-comparison-template=\"item\">\n * <h3 data-hs-comparison-template=\"name\">Project 1</h3>\n * <div data-hs-comparison-template=\"description\">Description 1</div>\n * <img data-hs-comparison-template=\"before\" src=\"before1.jpg\" alt=\"Before\">\n * <img data-hs-comparison-template=\"after\" src=\"after1.jpg\" alt=\"After\">\n * </div>\n * </div>\n *\n * <!-- Visible slider elements -->\n * <div data-hs-comparison=\"image-wrapper\">\n * <div data-hs-comparison-image=\"before\">\n * <img src=\"placeholder.jpg\">\n * </div>\n * <div data-hs-comparison-image=\"after\">\n * <img src=\"placeholder.jpg\">\n * </div>\n * </div>\n * <div data-hs-comparison=\"slider\"></div>\n * <span data-hs-comparison=\"name\">Placeholder</span>\n * <span data-hs-comparison=\"description\">Placeholder</span>\n * </div>\n */\n\nimport {\n querySelector,\n querySelectorAll,\n getSelector,\n globalConfig,\n getGsap,\n warnMissingDependencies,\n cssVariables,\n} from '@utils';\n\nexport async function init(config: any) {\n const gsapLib = getGsap('comparison');\n if (!gsapLib) {\n return { result: 'comparison skipped - GSAP not loaded' };\n }\n\n const { gsap, Draggable } = gsapLib;\n\n // Warn about missing required dependencies\n warnMissingDependencies('comparison', ['Draggable'], 'error');\n\n const wrappers = querySelectorAll(config, 'wrapper');\n const cleanup = {\n draggables: [] as any[],\n handlers: [] as Array<{ element: Element; event: string; handler: EventListener }>,\n };\n\n // Cache template selectors once (they never change)\n const templateNameSelector = getSelector(config, 'template-name');\n const templateDescSelector = getSelector(config, 'template-description');\n const templateBeforeImageSelector = getSelector(config, 'template-before-image');\n const templateAfterImageSelector = getSelector(config, 'template-after-image');\n\n // Helper functions with access to config and gsap via closure\n function updateClipPath(wrapper: HTMLElement, percentage: number) {\n // Set CSS variable on wrapper, CSS handles the actual clip-path\n wrapper.style.setProperty(cssVariables.clip, `${percentage}%`);\n }\n\n function loadSlide(instance: any, index: number) {\n const templateItem = instance.templateItems[index];\n if (!templateItem) return;\n\n // Update name\n const templateName = templateItem.querySelector(templateNameSelector);\n if (instance.nameElement && templateName) {\n instance.nameElement.textContent = templateName.textContent;\n }\n\n // Update description\n const templateDesc = templateItem.querySelector(templateDescSelector);\n if (instance.descElement && templateDesc) {\n instance.descElement.textContent = templateDesc.textContent;\n }\n\n // Update before image\n const templateBeforeImage = templateItem.querySelector(\n templateBeforeImageSelector\n ) as HTMLImageElement;\n\n if (instance.beforeImage && templateBeforeImage) {\n instance.beforeImage.src = templateBeforeImage.src;\n instance.beforeImage.alt = templateBeforeImage.alt || '';\n }\n\n // Update after image\n const templateAfterImage = templateItem.querySelector(\n templateAfterImageSelector\n ) as HTMLImageElement;\n\n if (instance.afterImage && templateAfterImage) {\n instance.afterImage.src = templateAfterImage.src;\n instance.afterImage.alt = templateAfterImage.alt || '';\n\n // Apply current mode to maintain slider state\n applyMode(instance);\n }\n\n instance.currentIndex = index;\n\n // Update pagination\n updatePagination(instance.wrapper, index);\n }\n\n function applyMode(instance: any) {\n const slider = instance.slider;\n const wrapper = instance.wrapper;\n\n switch (instance.mode) {\n case 'before':\n // Set variable to 100% (hide after image completely)\n wrapper.style.setProperty(cssVariables.clip, '100%');\n slider.style.display = 'none';\n break;\n case 'after':\n // Set variable to 0% (show after image completely)\n wrapper.style.setProperty(cssVariables.clip, '0%');\n slider.style.display = 'none';\n break;\n case 'split':\n // Restore slider position without resetting\n updateClipPath(wrapper, instance.sliderPosition);\n slider.style.display = 'flex';\n break;\n }\n }\n\n function setMode(instance: any, mode: string) {\n const wrapper = instance.wrapper;\n const modeButtons = wrapper.querySelectorAll(`[${config.attributes.properties.modeType}]`);\n const activeClass = globalConfig.classes.active;\n\n // Update button states\n modeButtons.forEach((btn: Element) => {\n const btnMode = btn.getAttribute(config.attributes.properties.modeType);\n if (btnMode === mode) {\n btn.classList.add(activeClass);\n } else {\n btn.classList.remove(activeClass);\n }\n });\n\n instance.mode = mode;\n applyMode(instance);\n }\n\n function updatePagination(wrapper: HTMLElement, index: number) {\n const paginationContainer = querySelector(config, 'pagination', wrapper);\n if (!paginationContainer) return;\n\n const activeClass = globalConfig.classes.active;\n const dots = Array.from(paginationContainer.children);\n dots.forEach((dot, dotIndex) => {\n if (dotIndex === index) {\n dot.classList.add(activeClass);\n } else {\n dot.classList.remove(activeClass);\n }\n });\n }\n\n function navigateSlide(instance: any, direction: number) {\n const newIndex = instance.currentIndex + direction;\n const maxIndex = instance.templateItems.length - 1;\n\n let targetIndex: number;\n if (newIndex > maxIndex) {\n targetIndex = 0;\n } else if (newIndex < 0) {\n targetIndex = maxIndex;\n } else {\n targetIndex = newIndex;\n }\n\n loadSlide(instance, targetIndex);\n }\n\n function setupNavigation(instance: any, wrapper: HTMLElement) {\n const leftArrow = wrapper.querySelector(`[${config.attributes.properties.navType}=\"previous\"]`);\n const rightArrow = wrapper.querySelector(`[${config.attributes.properties.navType}=\"next\"]`);\n\n if (leftArrow) {\n const clickableSelector = getSelector(globalConfig.clickable as any, 'button');\n const button = (leftArrow.querySelector(clickableSelector) || leftArrow) as HTMLElement;\n button.setAttribute('aria-label', 'Previous image');\n\n const handler = (e: Event) => {\n e.preventDefault();\n navigateSlide(instance, -1);\n };\n\n button.addEventListener('click', handler);\n cleanup.handlers.push({ element: button, event: 'click', handler });\n }\n\n if (rightArrow) {\n const clickableSelector = getSelector(globalConfig.clickable as any, 'button');\n const button = (rightArrow.querySelector(clickableSelector) || rightArrow) as HTMLElement;\n button.setAttribute('aria-label', 'Next image');\n\n const handler = (e: Event) => {\n e.preventDefault();\n navigateSlide(instance, 1);\n };\n\n button.addEventListener('click', handler);\n cleanup.handlers.push({ element: button, event: 'click', handler });\n }\n }\n\n function setupPagination(instance: any, paginationContainer: HTMLElement) {\n const templateDot = paginationContainer.children[0];\n if (!templateDot) return;\n\n const activeClass = globalConfig.classes.active;\n paginationContainer.innerHTML = '';\n\n instance.templateItems.forEach((_: any, index: number) => {\n const dot = templateDot.cloneNode(true) as HTMLElement;\n\n // Remove active class from all dots, then add only to first\n dot.classList.remove(activeClass);\n if (index === 0) {\n dot.classList.add(activeClass);\n }\n\n const clickHandler = () => {\n loadSlide(instance, index);\n };\n\n dot.addEventListener('click', clickHandler);\n cleanup.handlers.push({ element: dot, event: 'click', handler: clickHandler });\n\n paginationContainer.appendChild(dot);\n });\n }\n\n function setupKeyboardNav(instance: any) {\n const keydownHandler = (e: KeyboardEvent) => {\n if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\n e.preventDefault();\n navigateSlide(instance, -1);\n } else if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\n e.preventDefault();\n navigateSlide(instance, 1);\n }\n };\n\n instance.wrapper.addEventListener('keydown', keydownHandler);\n instance.wrapper.setAttribute('tabindex', '0');\n cleanup.handlers.push({ element: instance.wrapper, event: 'keydown', handler: keydownHandler });\n }\n\n // Main initialization loop\n wrappers.forEach((wrapper) => {\n // Find template list inside wrapper\n const templateList = querySelector(config, 'template-list', wrapper);\n if (!templateList) {\n console.warn('[comparison] No template list found in wrapper');\n return;\n }\n\n const templateItemsSelector = getSelector(config, 'template-item');\n const templateItems = Array.from(templateList.querySelectorAll(templateItemsSelector));\n\n if (templateItems.length === 0) {\n console.warn('[comparison] No template items found');\n return;\n }\n\n // Add simple aria-live for screen reader announcements\n wrapper.setAttribute('aria-live', 'polite');\n wrapper.setAttribute('aria-label', 'Before and after image comparison');\n\n // Get references to visible elements and cache them\n const imageWrapper = querySelector(config, 'image-wrapper', wrapper) as HTMLElement;\n const slider = querySelector(config, 'slider', wrapper) as HTMLElement;\n const beforeImageWrapper = querySelector(config, 'before-image', wrapper) as HTMLElement;\n const afterImageWrapper = querySelector(config, 'after-image', wrapper) as HTMLElement;\n const nameElement = querySelector(config, 'name', wrapper) as HTMLElement;\n const descElement = querySelector(config, 'description', wrapper) as HTMLElement;\n\n if (!imageWrapper || !slider || !afterImageWrapper) {\n const missing = [];\n if (!imageWrapper) missing.push('image-wrapper (data-hs-comparison=\"image-wrapper\")');\n if (!slider) missing.push('slider (data-hs-comparison=\"slider\")');\n if (!afterImageWrapper) missing.push('after-image (data-hs-comparison-image=\"after\")');\n console.warn(`[comparison] Missing required elements: ${missing.join(', ')}`);\n return;\n }\n\n const instance = {\n wrapper: wrapper as HTMLElement,\n templateItems,\n currentIndex: 0,\n mode: 'split',\n sliderPosition: 50,\n imageWrapper,\n slider,\n beforeImage: beforeImageWrapper?.querySelector('img') as HTMLImageElement,\n afterImage: afterImageWrapper?.querySelector('img') as HTMLImageElement,\n nameElement,\n descElement,\n draggable: null as any,\n };\n\n // Load first slide\n loadSlide(instance, 0);\n\n // Set initial clip path to 50%\n updateClipPath(wrapper as HTMLElement, 50);\n\n // Setup GSAP Draggable for slider\n if (Draggable) {\n const draggableInstance = Draggable.create(slider, {\n type: 'x',\n bounds: imageWrapper,\n onDrag: function () {\n const rect = imageWrapper.getBoundingClientRect();\n const sliderRect = slider.getBoundingClientRect();\n const x = sliderRect.left - rect.left;\n const percentage = Math.max(0, Math.min(100, (x / rect.width) * 100));\n\n updateClipPath(wrapper as HTMLElement, percentage);\n instance.sliderPosition = percentage;\n },\n });\n\n cleanup.draggables.push(draggableInstance);\n instance.draggable = draggableInstance[0]; // Store reference to draggable\n\n // Click on image wrapper to jump slider\n const clickHandler = (e: MouseEvent) => {\n if (instance.mode !== 'split') return;\n\n const rect = imageWrapper.getBoundingClientRect();\n const clickX = e.clientX - rect.left;\n const percentage = Math.max(0, Math.min(100, (clickX / rect.width) * 100));\n\n // Calculate target position accounting for slider's center point\n // Draggable starts from slider's initial position (50% = center)\n const centerX = rect.width / 2;\n const offsetX = clickX - centerX;\n\n // Update Draggable's x position from center\n if (instance.draggable) {\n gsap.set(slider, { x: offsetX });\n instance.draggable.update();\n }\n\n updateClipPath(wrapper as HTMLElement, percentage);\n instance.sliderPosition = percentage;\n };\n\n imageWrapper.addEventListener('click', clickHandler);\n cleanup.handlers.push({ element: imageWrapper, event: 'click', handler: clickHandler });\n }\n\n // Setup mode buttons\n const modeButtons = wrapper.querySelectorAll(`[${config.attributes.properties.modeType}]`);\n modeButtons.forEach((modeWrapper) => {\n const mode = modeWrapper.getAttribute(config.attributes.properties.modeType);\n const clickableSelector = getSelector(globalConfig.clickable as any, 'button');\n const button = (modeWrapper.querySelector(clickableSelector) || modeWrapper) as HTMLElement;\n\n // Set initial state\n if (mode === instance.mode) {\n modeWrapper.classList.add(globalConfig.classes.active);\n }\n\n const clickHandler = (e: Event) => {\n e.preventDefault();\n setMode(instance, mode!);\n };\n\n button.addEventListener('click', clickHandler);\n cleanup.handlers.push({ element: button, event: 'click', handler: clickHandler });\n });\n\n // Setup navigation\n setupNavigation(instance, wrapper as HTMLElement);\n\n // Setup pagination\n const paginationContainer = querySelector(config, 'pagination', wrapper);\n if (paginationContainer && templateItems.length > 1) {\n setupPagination(instance, paginationContainer as HTMLElement);\n }\n\n // Setup keyboard navigation\n setupKeyboardNav(instance);\n });\n\n return {\n result: `comparison initialized (${wrappers.length} instances)`,\n destroy: () => {\n // Kill all draggables\n cleanup.draggables.forEach((d) => {\n if (d && d[0] && d[0].kill) d[0].kill();\n });\n\n // Remove all event listeners\n cleanup.handlers.forEach(({ element, event, handler }) => {\n element.removeEventListener(event, handler);\n });\n\n // Clear arrays\n cleanup.draggables.length = 0;\n cleanup.handlers.length = 0;\n },\n };\n}\n","/**\n * Tabs\n *\n * Accessible tab system with autoplay, keyboard navigation, and optional animations.\n * Index-based matching: first button controls first panel, second controls second, etc.\n *\n * Features:\n * - Index-based tab/panel matching (no manual ID configuration needed)\n * - Optional autoplay with configurable duration\n * - CSS progress variable for visual countdown (--_hs---progress)\n * - Pause on hover and focus (accessibility)\n * - Previous/next/toggle controls\n * - Keyboard navigation (Arrow keys, Home, End)\n * - Optional fade or height animations\n * - Respects prefers-reduced-motion\n * - Full ARIA support (auto-generated IDs, aria-controls, aria-selected)\n *\n * Structure:\n * <div data-hs-tab=\"wrapper\" data-hs-tab-autoplay=\"true\" data-hs-tab-duration=\"6\">\n * <div data-hs-tab=\"links\" role=\"tablist\">\n * <div class=\"tab-link\">\n * <button role=\"tab\" data-hs-clickable=\"button\">Tab 1</button>\n * </div>\n * </div>\n * <div data-hs-tab=\"list\">\n * <div role=\"tabpanel\">Panel 1 content</div>\n * <div role=\"tabpanel\">Panel 2 content</div>\n * </div>\n * </div>\n */\n\nimport {\n querySelectorAll,\n querySelector,\n getSelector,\n globalConfig,\n prefersReducedMotion,\n getGsap,\n hasGsap,\n} from '@utils';\n\ninterface EventHandler {\n element: Element | Document;\n event: string;\n handler: EventListener;\n options?: AddEventListenerOptions;\n}\n\ninterface ModuleConfig {\n attributes: {\n elements: Record<string, { primary: string; aliases?: string[] }>;\n properties?: Record<string, string>;\n };\n cssVars?: {\n progress?: string;\n };\n}\n\nexport function init(moduleConfig: ModuleConfig) {\n const cleanup = {\n handlers: [] as EventHandler[],\n timers: [] as number[],\n animationFrames: [] as number[],\n observers: [] as IntersectionObserver[],\n };\n\n const addHandler = (\n element: Element | Document,\n event: string,\n handler: EventListener,\n options?: AddEventListenerOptions\n ): void => {\n element.addEventListener(event, handler, options);\n cleanup.handlers.push({ element, event, handler, options });\n };\n\n const addTimer = (id: number) => cleanup.timers.push(id);\n const addAnimationFrame = (id: number) => cleanup.animationFrames.push(id);\n const addObserver = (obs: IntersectionObserver) => cleanup.observers.push(obs);\n\n // Helper: Generate unique IDs for ARIA\n const generateId = (prefix: string) => `${prefix}-${Math.random().toString(36).substring(2, 9)}`;\n\n // Helper: Get CSS var name with prefix\n const getProgressVarName = () =>\n `${globalConfig.cssVars.prefix}${moduleConfig.cssVars?.progress || 'progress'}`;\n\n // Helper: Set progress CSS variable on element\n const setProgress = (element: HTMLElement, progress: number) =>\n element.style.setProperty(getProgressVarName(), String(progress));\n\n // Helper: Fade animation using GSAP\n async function animateFade(\n outPanel: HTMLElement,\n inPanel: HTMLElement,\n duration: number\n ): Promise<void> {\n // Handle reduced motion by setting duration to 0\n if (prefersReducedMotion()) duration = 0;\n\n const gsapInstance = getGsap('tabs', false);\n\n // Fallback to instant switch if GSAP not available\n if (!gsapInstance) {\n outPanel.style.display = 'none';\n outPanel.style.position = '';\n (outPanel as HTMLElement).inert = true;\n outPanel.style.pointerEvents = 'none';\n\n inPanel.style.display = 'block';\n inPanel.style.position = '';\n (inPanel as HTMLElement).inert = false;\n inPanel.style.pointerEvents = '';\n return;\n }\n\n const { gsap } = gsapInstance;\n\n return new Promise<void>((resolve) => {\n const tl = gsap.timeline({\n onComplete: () => {\n // Final cleanup after animation\n outPanel.style.display = 'none';\n outPanel.style.position = '';\n outPanel.style.opacity = '';\n (outPanel as HTMLElement).inert = true;\n outPanel.style.pointerEvents = 'none';\n\n inPanel.style.position = '';\n inPanel.style.opacity = '';\n (inPanel as HTMLElement).inert = false;\n inPanel.style.pointerEvents = '';\n\n resolve();\n },\n defaults: { duration: duration, ease: 'power1.out' },\n });\n\n // Set old panel to absolute position\n tl.set(outPanel, { position: 'absolute', top: 0, left: 0, width: '100%' });\n\n // Set new panel to visible and relative\n tl.set(inPanel, { display: 'block', position: 'relative', opacity: 0 });\n\n // Fade out old panel\n tl.to(outPanel, { opacity: 0 });\n\n // Fade in new panel (starts at 50% of fade out)\n tl.to(inPanel, { opacity: 1 }, '<50%');\n });\n }\n\n // Helper: Clip-path animation using GSAP\n async function animateClip(\n outPanel: HTMLElement,\n inPanel: HTMLElement,\n duration: number\n ): Promise<void> {\n // Handle reduced motion by setting duration to 0\n if (prefersReducedMotion()) duration = 0;\n\n const gsapInstance = getGsap('tabs', false);\n\n // Fallback to instant switch if GSAP not available\n if (!gsapInstance) {\n outPanel.style.display = 'none';\n outPanel.style.position = '';\n outPanel.style.clipPath = '';\n (outPanel as HTMLElement).inert = true;\n outPanel.style.pointerEvents = 'none';\n\n inPanel.style.display = 'block';\n inPanel.style.position = '';\n inPanel.style.clipPath = '';\n (inPanel as HTMLElement).inert = false;\n inPanel.style.pointerEvents = '';\n return;\n }\n\n const { gsap } = gsapInstance;\n\n return new Promise<void>((resolve) => {\n const tl = gsap.timeline({\n onComplete: () => {\n // Final cleanup after animation\n outPanel.style.display = 'none';\n outPanel.style.position = '';\n outPanel.style.clipPath = '';\n (outPanel as HTMLElement).inert = true;\n outPanel.style.pointerEvents = 'none';\n\n inPanel.style.position = '';\n inPanel.style.clipPath = '';\n (inPanel as HTMLElement).inert = false;\n inPanel.style.pointerEvents = '';\n\n resolve();\n },\n defaults: { duration: duration, ease: 'power1.inOut' },\n });\n\n // Set old panel to absolute position with full clip\n tl.set(outPanel, {\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n clipPath: 'inset(0% 0% 0% 0%)',\n });\n\n // Set new panel to visible with bottom clipped\n tl.set(inPanel, { display: 'block', position: 'relative', clipPath: 'inset(0% 0% 100% 0%)' });\n\n // Clip out old panel (top to bottom)\n tl.to(outPanel, { clipPath: 'inset(100% 0% 0% 0%)' });\n\n // Clip in new panel (bottom to top, starts at 40% through clip out)\n tl.to(inPanel, { clipPath: 'inset(0% 0% 0% 0%)' }, '<40%');\n });\n }\n\n // Setup individual tab system\n function setupTabSystem(wrapper: Element): void {\n const linksWrapper = querySelector(moduleConfig as any, 'links', wrapper);\n const listWrapper = querySelector(moduleConfig as any, 'list', wrapper);\n\n if (!linksWrapper || !listWrapper) {\n return;\n }\n\n // Get tab links (direct children of links wrapper)\n const tabLinkElements = Array.from(linksWrapper.children);\n\n // Get tab panels (direct children of list wrapper)\n const tabPanels = Array.from(listWrapper.children) as HTMLElement[];\n\n // Find clickable buttons within each tab link element\n const clickableSelector = getSelector(globalConfig.clickable as any, 'button');\n const tabButtons = tabLinkElements\n .map((linkEl) => linkEl.querySelector(clickableSelector))\n .filter((btn) => btn !== null) as HTMLElement[];\n\n if (tabButtons.length === 0) {\n return;\n }\n\n // Get options from attributes\n const autoplayAttr = (wrapper as HTMLElement).getAttribute(\n moduleConfig.attributes.properties?.autoplay || 'data-hs-tab-autoplay'\n );\n const durationAttr = (wrapper as HTMLElement).getAttribute(\n moduleConfig.attributes.properties?.duration || 'data-hs-tab-duration'\n );\n const hoverAttr = (wrapper as HTMLElement).getAttribute(\n moduleConfig.attributes.properties?.hover || 'data-hs-tab-hover'\n );\n const animationAttr = (wrapper as HTMLElement).getAttribute(\n moduleConfig.attributes.properties?.animation || 'data-hs-tab-animation'\n );\n const animDurationAttr = (wrapper as HTMLElement).getAttribute(\n moduleConfig.attributes.properties?.animationDuration || 'data-hs-tab-animation-duration'\n );\n\n const autoplayEnabled = autoplayAttr === 'true';\n const duration = durationAttr ? parseFloat(durationAttr) : 6;\n const pauseOnHover = hoverAttr === 'pause';\n const animationType = animationAttr as 'fade' | 'clip' | null;\n const animationDuration = animDurationAttr ? parseFloat(animDurationAttr) : 0.3;\n\n // Generate unique ID for this tab system\n const tabSystemId = generateId('hs-tab');\n\n // Setup ARIA and IDs\n tabPanels.forEach((panel, index) => {\n const panelId = panel.id || `${tabSystemId}-panel-${index}`;\n const tabId = `${tabSystemId}-tab-${index}`;\n\n panel.id = panelId;\n if (tabButtons[index]) {\n tabButtons[index].id = tabId;\n tabButtons[index].setAttribute('aria-controls', panelId);\n }\n });\n\n // State\n let currentIndex = 0;\n let autoplayTimer: number | null = null;\n let progressAnimationFrame: number | null = null;\n let progressStartTime: number | null = null;\n let isPaused = false;\n let isTransitioning = false;\n let isInView = false;\n\n // Activate tab\n async function activateTab(index: number, skipAnimation = false): Promise<void> {\n // Block if transition in progress\n if (isTransitioning) return;\n\n // Validate index\n if (index < 0 || index >= tabPanels.length) return;\n if (index === currentIndex && !skipAnimation) return;\n\n // Lock IMMEDIATELY to block any further calls\n isTransitioning = true;\n\n const previousIndex = currentIndex;\n currentIndex = index;\n\n // Update button ARIA and active classes\n tabButtons.forEach((btn, i) => {\n btn.setAttribute('aria-selected', i === index ? 'true' : 'false');\n btn.setAttribute('tabindex', i === index ? '0' : '-1');\n });\n\n tabLinkElements.forEach((linkEl, i) => {\n linkEl.classList.toggle(globalConfig.classes.active, i === index);\n });\n\n // Handle progress transfer\n if (autoplayEnabled) {\n if (!isPaused) {\n startAutoplay();\n } else {\n const currentProgress = tabLinkElements[previousIndex]\n ? parseFloat(\n getComputedStyle(tabLinkElements[previousIndex] as HTMLElement).getPropertyValue(\n getProgressVarName()\n ) || '0'\n )\n : 0;\n\n tabLinkElements.forEach((linkEl, i) =>\n setProgress(linkEl as HTMLElement, i === index ? currentProgress : 0)\n );\n }\n }\n\n // Update panel visibility with animation\n const previousPanel = tabPanels[previousIndex];\n const currentPanel = tabPanels[index];\n\n if (animationType === 'fade' && !skipAnimation) {\n await animateFade(previousPanel, currentPanel, animationDuration);\n } else if (animationType === 'clip' && !skipAnimation) {\n await animateClip(previousPanel, currentPanel, animationDuration);\n } else {\n // Instant switch (no animation or skip)\n tabPanels.forEach((panel, i) => {\n if (i === index) {\n if (animationType === 'fade' || animationType === 'clip') {\n (panel as HTMLElement).style.position = '';\n (panel as HTMLElement).style.display = 'block';\n if (animationType === 'fade') {\n (panel as HTMLElement).style.opacity = '1';\n } else {\n (panel as HTMLElement).style.clipPath = '';\n }\n } else {\n (panel as HTMLElement).style.display = 'block';\n }\n (panel as HTMLElement).inert = false;\n (panel as HTMLElement).style.pointerEvents = '';\n panel.classList.add(globalConfig.classes.active);\n } else {\n if (animationType === 'fade' || animationType === 'clip') {\n (panel as HTMLElement).style.display = 'none';\n if (animationType === 'fade') {\n (panel as HTMLElement).style.opacity = '0';\n } else {\n (panel as HTMLElement).style.clipPath = '';\n }\n } else {\n (panel as HTMLElement).style.display = 'none';\n }\n (panel as HTMLElement).inert = true;\n (panel as HTMLElement).style.pointerEvents = 'none';\n panel.classList.remove(globalConfig.classes.active);\n }\n });\n }\n\n // Release lock\n isTransitioning = false;\n }\n\n // Progress animation\n function updateProgress(timestamp: number): void {\n if (autoplayEnabled) {\n if (!progressStartTime) progressStartTime = timestamp;\n const progress = Math.min((timestamp - progressStartTime) / (duration * 1000), 1);\n\n tabLinkElements.forEach((linkEl, i) =>\n setProgress(linkEl as HTMLElement, i === currentIndex ? progress : 0)\n );\n\n if (progress < 1 && !isPaused) {\n progressAnimationFrame = requestAnimationFrame(updateProgress);\n if (progressAnimationFrame) addAnimationFrame(progressAnimationFrame);\n }\n } else {\n tabLinkElements.forEach((linkEl, i) =>\n setProgress(linkEl as HTMLElement, i === currentIndex ? 1 : 0)\n );\n }\n }\n\n // Start autoplay\n function startAutoplay(): void {\n stopAutoplay();\n if (!autoplayEnabled) return updateProgress(0);\n if (isPaused || !isInView) return;\n\n // Get current progress to resume from (if any)\n const currentProgress = tabLinkElements[currentIndex]\n ? parseFloat(\n getComputedStyle(tabLinkElements[currentIndex] as HTMLElement).getPropertyValue(\n getProgressVarName()\n ) || '0'\n )\n : 0;\n\n // Calculate remaining time based on current progress\n const elapsedTime = currentProgress * duration * 1000; // Convert progress to milliseconds\n const remainingTime = Math.max(0, duration * 1000 - elapsedTime);\n\n // Start progress animation from current progress\n progressStartTime = null;\n const startProgress = currentProgress;\n const resumeStartTime = performance.now();\n\n const resumeUpdate = (timestamp: number): void => {\n const totalProgress = Math.min(\n startProgress + (timestamp - resumeStartTime) / (duration * 1000),\n 1\n );\n\n tabLinkElements.forEach((linkEl, i) =>\n setProgress(linkEl as HTMLElement, i === currentIndex ? totalProgress : 0)\n );\n\n if (totalProgress < 1 && !isPaused) {\n progressAnimationFrame = requestAnimationFrame(resumeUpdate);\n if (progressAnimationFrame) addAnimationFrame(progressAnimationFrame);\n }\n };\n\n progressAnimationFrame = requestAnimationFrame(resumeUpdate);\n if (progressAnimationFrame) addAnimationFrame(progressAnimationFrame);\n\n autoplayTimer = window.setTimeout(\n () => activateTab((currentIndex + 1) % tabPanels.length),\n remainingTime\n );\n addTimer(autoplayTimer);\n }\n\n // Stop autoplay\n function stopAutoplay(): void {\n if (autoplayTimer !== null) {\n clearTimeout(autoplayTimer);\n autoplayTimer = null;\n }\n if (progressAnimationFrame !== null) {\n cancelAnimationFrame(progressAnimationFrame);\n progressAnimationFrame = null;\n }\n progressStartTime = null;\n }\n\n // Pause/Resume autoplay\n const pauseAutoplay = () => {\n isPaused = true;\n stopAutoplay();\n };\n const resumeAutoplay = () => {\n isPaused = false;\n startAutoplay();\n };\n\n // Tab click handler\n tabButtons.forEach((button, index) => {\n addHandler(button, 'click', (e: Event) => {\n e.preventDefault();\n activateTab(index);\n });\n });\n\n // Keyboard navigation\n const keydownHandler = (e: KeyboardEvent): void => {\n const index = tabButtons.indexOf(e.target as HTMLElement);\n if (index === -1) return;\n\n let newIndex = index;\n switch (e.key) {\n case 'ArrowLeft':\n case 'ArrowUp':\n e.preventDefault();\n newIndex = index === 0 ? tabButtons.length - 1 : index - 1;\n break;\n case 'ArrowRight':\n case 'ArrowDown':\n e.preventDefault();\n newIndex = index === tabButtons.length - 1 ? 0 : index + 1;\n break;\n case 'Home':\n e.preventDefault();\n newIndex = 0;\n break;\n case 'End':\n e.preventDefault();\n newIndex = tabButtons.length - 1;\n break;\n default:\n return;\n }\n\n if (isTransitioning) return;\n activateTab(newIndex);\n tabButtons[newIndex].focus();\n };\n\n tabButtons.forEach((button) => addHandler(button, 'keydown', keydownHandler));\n\n // Pause on hover\n if (pauseOnHover && autoplayEnabled) {\n addHandler(wrapper, 'mouseenter', pauseAutoplay);\n addHandler(wrapper, 'mouseleave', resumeAutoplay);\n }\n\n // Pause on focus (keyboard only)\n let isUsingKeyboard = false;\n addHandler(document, 'keydown', () => (isUsingKeyboard = true));\n addHandler(document, 'mousedown', () => (isUsingKeyboard = false));\n\n if (autoplayEnabled) {\n addHandler(wrapper, 'focusin', () => {\n if (isUsingKeyboard) {\n pauseAutoplay();\n updateToggleState();\n }\n });\n addHandler(wrapper, 'focusout', () => {\n if (isUsingKeyboard && isPaused) {\n resumeAutoplay();\n updateToggleState();\n }\n });\n }\n\n // Previous/Next/Toggle controls\n const controlsSelector = `[${\n moduleConfig.attributes.properties?.controls || 'data-hs-tab-controls'\n }]`;\n const controls = wrapper.querySelectorAll(controlsSelector);\n\n // Find toggle button for state updates (may be null if no toggle or autoplay disabled)\n let toggleControl: Element | null = null;\n let toggleButton: HTMLElement | null = null;\n\n controls.forEach((control) => {\n const controlType = control.getAttribute(\n moduleConfig.attributes.properties?.controls || 'data-hs-tab-controls'\n );\n const controlButton = control.querySelector(clickableSelector);\n\n if (!controlButton) return;\n\n if (controlType === 'previous') {\n (controlButton as HTMLElement).setAttribute('aria-label', 'Previous tab');\n addHandler(controlButton, 'click', (e: Event) => {\n e.preventDefault();\n activateTab(currentIndex === 0 ? tabPanels.length - 1 : currentIndex - 1);\n });\n } else if (controlType === 'next') {\n (controlButton as HTMLElement).setAttribute('aria-label', 'Next tab');\n addHandler(controlButton, 'click', (e: Event) => {\n e.preventDefault();\n activateTab((currentIndex + 1) % tabPanels.length);\n });\n } else if (controlType === 'toggle') {\n // Hide toggle button if autoplay is disabled\n if (!autoplayEnabled) {\n (control as HTMLElement).style.display = 'none';\n return;\n }\n\n // Store references for updateToggleState function\n toggleControl = control;\n toggleButton = controlButton as HTMLElement;\n\n toggleButton.setAttribute('aria-label', isPaused ? 'Play' : 'Pause');\n toggleControl.classList.toggle(globalConfig.classes.active, !isPaused);\n\n addHandler(controlButton, 'click', (e: Event) => {\n e.preventDefault();\n isPaused ? resumeAutoplay() : pauseAutoplay();\n updateToggleState();\n });\n }\n });\n\n // Helper: Update toggle button state\n const updateToggleState = () => {\n if (!toggleControl || !toggleButton) return;\n toggleControl.classList.toggle(globalConfig.classes.active, !isPaused);\n toggleButton.setAttribute('aria-label', isPaused ? 'Play' : 'Pause');\n };\n\n // Initialize first tab as active\n activateTab(0, true);\n\n // IntersectionObserver for autoplay visibility control\n if (autoplayEnabled) {\n const observer = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n isInView = entry.isIntersecting;\n entry.isIntersecting && !isPaused ? startAutoplay() : stopAutoplay();\n });\n },\n { threshold: 0.1 }\n );\n observer.observe(wrapper);\n addObserver(observer);\n }\n }\n\n // Find all tab wrappers and initialize\n const tabWrappers = querySelectorAll(moduleConfig as any, 'wrapper');\n\n tabWrappers.forEach((wrapper) => {\n setupTabSystem(wrapper);\n });\n\n return {\n result: `tabs initialized (${tabWrappers.length} systems)`,\n destroy: () => {\n // Clear all timers\n cleanup.timers.forEach((timerId) => clearTimeout(timerId));\n cleanup.timers.length = 0;\n\n // Clear all animation frames\n cleanup.animationFrames.forEach((frameId) => cancelAnimationFrame(frameId));\n cleanup.animationFrames.length = 0;\n\n // Disconnect all observers\n cleanup.observers.forEach((observer) => observer.disconnect());\n cleanup.observers.length = 0;\n\n // Remove all event listeners\n cleanup.handlers.forEach(({ element, event, handler, options }) => {\n element.removeEventListener(event, handler, options);\n });\n cleanup.handlers.length = 0;\n },\n };\n}\n","/**\n * Range Slider Component\n *\n * Custom range slider that syncs with native <input type=\"range\"> for proper form submission.\n * Automatically updates output display and sets CSS custom property for progress styling.\n *\n * Features:\n * - Calculates normalized progress (0-1) from min/max values\n * - Sets CSS custom property (--_hs---progress) on wrapper\n * - Updates optional output element with current value\n * - Prevents duplicate initialization with dataset flag\n * - Works with negative min values and custom step sizes\n *\n * HTML Structure:\n * <div data-hs-form-range=\"wrapper\">\n * <input type=\"range\" min=\"0\" max=\"100\" value=\"50\">\n * <span data-hs-form-range=\"output\">50</span>\n * </div>\n *\n * CSS Usage:\n * .range-fill { width: calc(var(--_hs---progress) * 100%); }\n */\n\nimport { querySelectorAll, querySelector } from '@utils';\nimport globalConfig from '@config';\n\ninterface ModuleConfig {\n attributes: {\n elements: Record<string, { primary: string; aliases?: string[] }>;\n };\n cssVars?: {\n progress?: string;\n };\n}\n\nexport function init(config: ModuleConfig) {\n // Centralized cleanup tracking\n const cleanup = {\n handlers: [],\n domContentLoadedHandler: null,\n };\n\n const addHandler = (element: Element, event: string, handler: EventListener) => {\n element.addEventListener(event, handler);\n cleanup.handlers.push({ element, event, handler });\n };\n\n // Helper: Get CSS var name with global prefix\n function getProgressVarName(): string {\n const prefix = globalConfig._global.cssVars.prefix;\n const varName = config.cssVars?.progress || 'progress';\n return `${prefix}${varName}`;\n }\n\n // Initialize all range components\n function initRangeComponents() {\n const rangeWrappers = querySelectorAll(config, 'wrapper');\n\n rangeWrappers.forEach((wrapper) => {\n const htmlWrapper = wrapper as HTMLElement;\n // Prevent duplicate initialization\n if (htmlWrapper.dataset.hsFormRangeInit) return;\n htmlWrapper.dataset.hsFormRangeInit = 'true';\n\n initSingleRange(htmlWrapper, addHandler);\n });\n }\n\n // Initialize a single range component\n function initSingleRange(\n wrapper: HTMLElement,\n addHandler: (element: Element, event: string, handler: EventListener) => void\n ) {\n const input = wrapper.querySelector(\"input[type='range']\") as HTMLInputElement;\n if (!input) {\n console.warn('[range] Missing <input type=\"range\"> element in wrapper', wrapper);\n return;\n }\n\n const output = querySelector(config, 'output', wrapper);\n\n // Update function\n const update = () => {\n const min = input.min ? +input.min : 0;\n const max = input.max ? +input.max : 100;\n const val = +input.value || min;\n const progress = (val - min) / (max - min);\n\n // Set CSS custom property using global config\n wrapper.style.setProperty(getProgressVarName(), String(progress));\n\n // Update output text if exists\n if (output) {\n output.textContent = String(val);\n }\n };\n\n // Add input event listener\n addHandler(input, 'input', update);\n\n // Initialize on load\n update();\n }\n\n // Initialize on DOM ready\n if (document.readyState === 'loading') {\n cleanup.domContentLoadedHandler = initRangeComponents;\n document.addEventListener('DOMContentLoaded', cleanup.domContentLoadedHandler);\n } else {\n initRangeComponents();\n }\n\n return {\n result: 'range initialized',\n destroy: () => {\n // Remove DOMContentLoaded listener\n if (cleanup.domContentLoadedHandler) {\n document.removeEventListener('DOMContentLoaded', cleanup.domContentLoadedHandler);\n cleanup.domContentLoadedHandler = null;\n }\n\n // Remove all event listeners\n cleanup.handlers.forEach(({ element, event, handler }) => {\n element.removeEventListener(event, handler);\n });\n cleanup.handlers.length = 0;\n\n // Remove init flags\n const rangeWrappers = querySelectorAll(config, 'wrapper');\n rangeWrappers.forEach((wrapper) => {\n delete (wrapper as HTMLElement).dataset.hsFormRangeInit;\n });\n },\n };\n}\n","/**\n * US States Select Populator\n *\n * Automatically populates a <select> element with all 50 US states.\n * Maintains the existing placeholder option and adds state options dynamically.\n *\n * Features:\n * - Auto-populates all 50 US states (full names + abbreviations)\n * - Preserves placeholder option (must have empty value)\n * - Validates select has exactly 1 template option\n * - State values use standard 2-letter abbreviations (CA, NY, TX, etc.)\n * - Works with both native and custom select components\n *\n * HTML Structure:\n * <select data-hs-form-select=\"states\">\n * <option value=\"\">Select a state</option>\n * </select>\n *\n * Result:\n * <select data-hs-form-select=\"states\">\n * <option value=\"\">Select a state</option>\n * <option value=\"AL\">Alabama</option>\n * <option value=\"AK\">Alaska</option>\n * ...all 50 states...\n * </select>\n *\n * Validation:\n * - Must be applied to <select> element\n * - Must have exactly 1 existing option (placeholder)\n * - Placeholder must have empty value=\"\"\n */\n\nimport { querySelectorAll } from '@utils';\n\nconst US_STATES = [\n { name: 'Alabama', value: 'AL' },\n { name: 'Alaska', value: 'AK' },\n { name: 'Arizona', value: 'AZ' },\n { name: 'Arkansas', value: 'AR' },\n { name: 'California', value: 'CA' },\n { name: 'Colorado', value: 'CO' },\n { name: 'Connecticut', value: 'CT' },\n { name: 'Delaware', value: 'DE' },\n { name: 'Florida', value: 'FL' },\n { name: 'Georgia', value: 'GA' },\n { name: 'Hawaii', value: 'HI' },\n { name: 'Idaho', value: 'ID' },\n { name: 'Illinois', value: 'IL' },\n { name: 'Indiana', value: 'IN' },\n { name: 'Iowa', value: 'IA' },\n { name: 'Kansas', value: 'KS' },\n { name: 'Kentucky', value: 'KY' },\n { name: 'Louisiana', value: 'LA' },\n { name: 'Maine', value: 'ME' },\n { name: 'Maryland', value: 'MD' },\n { name: 'Massachusetts', value: 'MA' },\n { name: 'Michigan', value: 'MI' },\n { name: 'Minnesota', value: 'MN' },\n { name: 'Mississippi', value: 'MS' },\n { name: 'Missouri', value: 'MO' },\n { name: 'Montana', value: 'MT' },\n { name: 'Nebraska', value: 'NE' },\n { name: 'Nevada', value: 'NV' },\n { name: 'New Hampshire', value: 'NH' },\n { name: 'New Jersey', value: 'NJ' },\n { name: 'New Mexico', value: 'NM' },\n { name: 'New York', value: 'NY' },\n { name: 'North Carolina', value: 'NC' },\n { name: 'North Dakota', value: 'ND' },\n { name: 'Ohio', value: 'OH' },\n { name: 'Oklahoma', value: 'OK' },\n { name: 'Oregon', value: 'OR' },\n { name: 'Pennsylvania', value: 'PA' },\n { name: 'Rhode Island', value: 'RI' },\n { name: 'South Carolina', value: 'SC' },\n { name: 'South Dakota', value: 'SD' },\n { name: 'Tennessee', value: 'TN' },\n { name: 'Texas', value: 'TX' },\n { name: 'Utah', value: 'UT' },\n { name: 'Vermont', value: 'VT' },\n { name: 'Virginia', value: 'VA' },\n { name: 'Washington', value: 'WA' },\n { name: 'West Virginia', value: 'WV' },\n { name: 'Wisconsin', value: 'WI' },\n { name: 'Wyoming', value: 'WY' },\n];\n\nexport function init(config) {\n // Find all select elements with data-hs-form-select=\"states\"\n const stateSelects = querySelectorAll(config, 'states');\n\n stateSelects.forEach((selectElement) => {\n const select = selectElement as HTMLSelectElement;\n if (select.tagName !== 'SELECT') {\n console.warn(\n '[select-states] data-hs-form-select=\"states\" must be on a <select> element',\n select\n );\n return;\n }\n\n const existingOptions = select.querySelectorAll('option') as NodeListOf<HTMLOptionElement>;\n\n // Validate: Must have exactly 1 option (placeholder template)\n if (existingOptions.length !== 1) {\n console.warn(\n '[select-states] Select must have exactly 1 default template option (placeholder). Found:',\n existingOptions.length,\n select\n );\n return;\n }\n\n const templateOption = existingOptions[0];\n\n // Validate: Template option must have empty value\n if (templateOption.value !== '') {\n console.warn(\n '[select-states] Template option must have empty value for placeholder. Found value:',\n templateOption.value,\n select\n );\n return;\n }\n\n // Store placeholder text and clear select\n const placeholderText = templateOption.textContent;\n select.innerHTML = '';\n\n // Re-create placeholder as first option\n const placeholder = document.createElement('option');\n placeholder.value = '';\n placeholder.textContent = placeholderText;\n select.appendChild(placeholder);\n\n // Add all 50 states after placeholder\n US_STATES.forEach((state) => {\n const option = document.createElement('option');\n option.value = state.value;\n option.textContent = state.name;\n select.appendChild(option);\n });\n });\n\n return {\n result: `states initialized on ${stateSelects.length} select${stateSelects.length !== 1 ? 's' : ''}`,\n destroy: () => {\n // No cleanup needed - states are just populated into native select\n },\n };\n}\n","/**\n * Custom Select Component\n *\n * Transforms native <select> elements into fully accessible custom dropdowns.\n * Maintains sync with native select for proper form submission and accessibility.\n *\n * Features:\n * - Full keyboard navigation (Arrow keys, Home/End, Enter, Space, Escape)\n * - Typeahead search (type letters to jump to options)\n * - ARIA-compliant with screen reader support\n * - Syncs with native select value changes and form resets\n * - Disabled state support with mutation observer\n * - Optional height animation with GSAP\n * - Modal scroll prevention when open\n * - Click outside to close\n * - Auto-unwraps Webflow component slot divs\n *\n * HTML Structure:\n * <div data-hs-form-select=\"wrapper\">\n * <label>Choose option</label>\n * <select name=\"example\">\n * <option value=\"\">Select...</option>\n * <option value=\"1\">Option 1</option>\n * </select>\n * <button data-hs-form-select=\"button\">\n * <span>Placeholder text</span>\n * </button>\n * <div data-hs-height=\"element\">\n * <div data-hs-form-select=\"list\">\n * <div role=\"option\"><span>Template</span></div>\n * </div>\n * </div>\n * </div>\n *\n * Keyboard Controls:\n * - Space/Enter (button): Open dropdown\n * - Arrow Up/Down: Navigate options\n * - Home/End: Jump to first/last option\n * - Escape: Close dropdown\n * - Type letters: Typeahead search\n *\n * Accessibility:\n * - Native select hidden but kept for form submission\n * - Custom UI uses role=\"combobox\" and role=\"listbox\"\n * - aria-expanded, aria-selected, aria-activedescendant\n * - Label properly connected to native select\n */\n\nimport {\n querySelectorAll,\n querySelector,\n animateHeight,\n setHeight,\n openModal,\n closeModal,\n} from '@utils';\n\nexport function init(config) {\n // Centralized cleanup tracking\n const cleanup = {\n observers: [] as MutationObserver[],\n handlers: [] as Array<{\n element: Element | Document;\n event: string;\n handler: EventListener;\n options?: boolean | AddEventListenerOptions;\n }>,\n timeouts: [] as number[],\n domContentLoadedHandler: null as (() => void) | null,\n };\n\n const addObserver = (observer: MutationObserver) => cleanup.observers.push(observer);\n const addHandler = (\n element: Element | Document,\n event: string,\n handler: EventListener,\n options?: boolean | AddEventListenerOptions\n ) => {\n element.addEventListener(event, handler, options);\n cleanup.handlers.push({ element, event, handler, options });\n };\n const addTimeout = (timeoutId: number) => cleanup.timeouts.push(timeoutId);\n\n // Initialize all custom selects on the page\n function initCustomSelects() {\n // Unwrap any divs inside select elements (Webflow component slots)\n document.querySelectorAll('select > div').forEach((div) => {\n const select = div.parentElement;\n while (div.firstChild) {\n select.appendChild(div.firstChild);\n }\n div.remove();\n });\n\n const selectWrappers = querySelectorAll(config, 'wrapper');\n\n selectWrappers.forEach((wrapper) => {\n initSingleSelect(wrapper, addHandler, addObserver, addTimeout);\n });\n }\n\n // Initialize a single custom select\n function initSingleSelect(\n wrapper: Element,\n addHandler: (\n element: Element | Document,\n event: string,\n handler: EventListener,\n options?: boolean | AddEventListenerOptions\n ) => void,\n addObserver: (observer: MutationObserver) => void,\n addTimeout: (timeoutId: number) => void\n ) {\n // Find all required elements\n const realSelect = wrapper.querySelector('select') as HTMLSelectElement;\n if (!realSelect) {\n console.warn('[select] Missing <select> element in custom select wrapper', wrapper);\n return;\n }\n\n // Hide real select from screen readers since custom UI provides accessible alternative\n realSelect.setAttribute('aria-hidden', 'true');\n realSelect.setAttribute('tabindex', '-1');\n\n const selectName = realSelect.getAttribute('name') || 'custom-select';\n const customList = querySelector(config, 'list', wrapper) as HTMLElement;\n const button = querySelector(config, 'button', wrapper) as HTMLButtonElement;\n\n if (!customList || !button) {\n console.warn(\n '[select] Missing required elements (list or button) in custom select wrapper',\n wrapper\n );\n return;\n }\n\n // Sync disabled state from native select\n function updateDisabledState() {\n if (realSelect.disabled) {\n button.disabled = true;\n button.setAttribute('aria-disabled', 'true');\n } else {\n button.disabled = false;\n button.removeAttribute('aria-disabled');\n }\n }\n updateDisabledState();\n\n // Get and clone the option template\n const optionTemplate = customList.firstElementChild;\n if (!optionTemplate) {\n console.warn('[select] Missing option template in custom select list', wrapper);\n return;\n }\n\n const templateClone = optionTemplate.cloneNode(true);\n optionTemplate.remove();\n\n // Build options from real select\n const realOptions = realSelect.querySelectorAll('option');\n realOptions.forEach((option: HTMLOptionElement, index: number) => {\n const optionElement = templateClone.cloneNode(true) as HTMLElement;\n const textSpan = optionElement.querySelector('span');\n\n if (textSpan) {\n textSpan.textContent = option.textContent;\n }\n\n // Add attributes\n optionElement.setAttribute('data-value', option.value);\n optionElement.setAttribute('role', 'option');\n optionElement.setAttribute('id', `${selectName}-option-${index}`);\n optionElement.setAttribute('tabindex', '-1');\n\n // Set selected state if this option is selected\n if (option.selected) {\n optionElement.setAttribute('aria-selected', 'true');\n // Update button text\n const buttonText = button.querySelector('span') || button;\n if (buttonText.tagName === 'SPAN') {\n buttonText.textContent = option.textContent;\n }\n // Set initial is-filled state based on value\n if (option.value) {\n button.classList.add('is-filled');\n } else {\n button.classList.remove('is-filled');\n }\n } else {\n optionElement.setAttribute('aria-selected', 'false');\n }\n\n customList.appendChild(optionElement);\n });\n\n // Add ARIA attributes\n customList.setAttribute('role', 'listbox');\n customList.setAttribute('id', `${selectName}-listbox`);\n customList.setAttribute('tabindex', '-1');\n customList.setAttribute('aria-hidden', 'true'); // Initial state: hidden\n customList.inert = true; // Prevent keyboard/mouse interaction when closed\n\n button.setAttribute('role', 'combobox');\n button.setAttribute('aria-haspopup', 'listbox');\n button.setAttribute('aria-controls', `${selectName}-listbox`);\n button.setAttribute('aria-expanded', 'false');\n button.setAttribute('id', `${selectName}-button`);\n\n // Find and connect label if exists\n const label =\n wrapper.querySelector('label') || document.querySelector(`label[for=\"${realSelect.id}\"]`);\n if (label) {\n const labelId = label.id || `${selectName}-label`;\n label.id = labelId;\n // Ensure real select has proper ID for label connection\n if (!realSelect.id) {\n realSelect.id = `${selectName}-select`;\n }\n label.setAttribute('for', realSelect.id);\n button.setAttribute('aria-labelledby', labelId);\n }\n\n // Check for visual height wrapper (optional)\n // Only animate if data-hs-height=\"element\" exists in wrapper\n const heightElement = wrapper.querySelector('[data-hs-height=\"element\"]');\n const animationTarget = heightElement || null;\n\n // Track state\n let searchString = '';\n let searchTimeout: number | null = null;\n let enterPressed = false;\n\n // Function to check if select is open\n function isSelectOpen() {\n return wrapper.classList.contains('is-active');\n }\n\n // Update ARIA states based on current visual state\n function updateARIAStates() {\n const isCurrentlyOpen = isSelectOpen();\n const wasOpen = button.getAttribute('aria-expanded') === 'true';\n\n // If closing and focus is inside list, return focus first\n if (wasOpen && !isCurrentlyOpen && customList.contains(document.activeElement)) {\n button.focus();\n }\n\n // Update ARIA attributes\n button.setAttribute('aria-expanded', isCurrentlyOpen ? 'true' : 'false');\n customList.setAttribute('aria-hidden', isCurrentlyOpen ? 'false' : 'true');\n customList.inert = !isCurrentlyOpen; // Enable/disable interaction\n\n if (isCurrentlyOpen) {\n // Make all options tabbable when opened\n const options = customList.querySelectorAll('[role=\"option\"]');\n options.forEach((opt) => {\n opt.setAttribute('tabindex', '0');\n });\n\n // Register with modal manager to prevent body scroll (only when opening)\n if (!wasOpen) {\n openModal();\n }\n } else {\n // Reset on close\n button.removeAttribute('aria-activedescendant');\n const options = customList.querySelectorAll('[role=\"option\"]');\n options.forEach((opt) => {\n opt.setAttribute('tabindex', '-1');\n });\n\n // Unregister with modal manager to restore body scroll (only when closing)\n if (wasOpen) {\n closeModal();\n }\n }\n\n // Animate height if configured\n if (animationTarget) {\n animateHeight(animationTarget, isCurrentlyOpen, { duration: 300, ease: 'power2.inOut' });\n }\n }\n\n // Set initial height without animation (if configured)\n if (animationTarget) {\n setHeight(animationTarget, isSelectOpen());\n }\n\n // Set initial ARIA states\n updateARIAStates();\n\n // Focus option by index\n function focusOption(index: number) {\n const options = customList.querySelectorAll('[role=\"option\"]') as NodeListOf<HTMLElement>;\n if (index < 0 || index >= options.length) return;\n\n // Remove previous focus\n options.forEach((opt) => {\n opt.classList.remove('focused');\n opt.setAttribute('tabindex', '-1');\n });\n\n // Add new focus\n options[index].classList.add('focused');\n options[index].setAttribute('tabindex', '0');\n options[index].focus();\n button.setAttribute('aria-activedescendant', options[index].id);\n }\n\n // Typeahead search functionality\n function handleTypeahead(key: string) {\n // Only handle printable characters (single character keys)\n if (key.length !== 1) return false;\n\n // Clear existing timeout\n if (searchTimeout !== null) {\n clearTimeout(searchTimeout);\n // Remove from cleanup tracking\n const index = cleanup.timeouts.indexOf(searchTimeout);\n if (index > -1) cleanup.timeouts.splice(index, 1);\n }\n\n // Get all options\n const options = Array.from(customList.querySelectorAll('[role=\"option\"]'));\n if (options.length === 0) return false;\n\n // Append to search string\n searchString += key.toLowerCase();\n\n // Find currently focused option index\n const currentIndex = options.findIndex((opt) => opt.classList.contains('focused'));\n\n // If repeating single letter, cycle through options starting with that letter\n if (\n searchString.length === 1 ||\n searchString.split('').every((char) => char === searchString[0])\n ) {\n const letter = searchString[0];\n let startIndex = currentIndex + 1;\n\n // Search from next option onwards\n for (let i = 0; i < options.length; i++) {\n const index = (startIndex + i) % options.length;\n const text = (\n options[index].querySelector('span')?.textContent || options[index].textContent\n ).toLowerCase();\n if (text.startsWith(letter)) {\n focusOption(index);\n if (!isSelectOpen()) wrapper.classList.add('is-active'); // Open if closed\n searchTimeout = setTimeout(clearSearch, 500);\n addTimeout(searchTimeout);\n return true;\n }\n }\n } else {\n // Multi-character search - find first match starting with search string\n const matchIndex = options.findIndex((opt) => {\n const text = (opt.querySelector('span')?.textContent || opt.textContent).toLowerCase();\n return text.startsWith(searchString);\n });\n\n if (matchIndex !== -1) {\n focusOption(matchIndex);\n if (!isSelectOpen()) wrapper.classList.add('is-active'); // Open if closed\n searchTimeout = setTimeout(clearSearch, 500);\n addTimeout(searchTimeout);\n return true;\n }\n }\n\n // Reset timeout even if no match found\n searchTimeout = setTimeout(clearSearch, 500);\n addTimeout(searchTimeout);\n return false;\n }\n\n // Clear search string\n function clearSearch() {\n searchString = '';\n searchTimeout = null;\n }\n\n // Select option\n function selectOption(optionElement: HTMLElement) {\n const value = optionElement.getAttribute('data-value') || '';\n const text = optionElement.querySelector('span')?.textContent || optionElement.textContent;\n\n // Update real select\n realSelect.value = value;\n realSelect.dispatchEvent(new Event('change', { bubbles: true }));\n\n // Update button text\n const buttonText = button.querySelector('span') || button;\n if (buttonText.tagName === 'SPAN') {\n buttonText.textContent = text;\n }\n\n // Update is-filled class based on value\n if (value) {\n button.classList.add('is-filled');\n } else {\n button.classList.remove('is-filled');\n }\n\n // Update aria-selected\n customList.querySelectorAll('[role=\"option\"]').forEach((opt) => {\n opt.setAttribute('aria-selected', 'false');\n });\n optionElement.setAttribute('aria-selected', 'true');\n\n // Close dropdown by toggling wrapper\n wrapper.classList.remove('is-active');\n }\n\n // Button click handler\n const buttonClickHandler = (e: Event) => {\n // If Enter was pressed, don't toggle - allow form submission\n if (enterPressed) {\n enterPressed = false;\n return;\n }\n e.preventDefault();\n wrapper.classList.toggle('is-active');\n };\n addHandler(button, 'click', buttonClickHandler);\n\n // Button keyboard events\n const buttonKeydownHandler = (e: KeyboardEvent) => {\n switch (e.key) {\n case 'Enter':\n e.preventDefault();\n // Find the form's submit button and click it\n const formElement = button.closest('form');\n if (formElement) {\n const submitButton = (formElement.querySelector(\n 'button[type=\"submit\"], input[type=\"submit\"]'\n ) || formElement.querySelector('button:not([type])')) as HTMLElement | null;\n if (submitButton) {\n submitButton.click();\n }\n }\n break;\n\n case ' ':\n e.preventDefault();\n wrapper.classList.toggle('is-active');\n break;\n\n case 'ArrowDown':\n e.preventDefault();\n if (!isSelectOpen()) {\n wrapper.classList.add('is-active');\n // Wait for dropdown to open, then focus first option\n requestAnimationFrame(() => {\n focusOption(0);\n });\n } else {\n focusOption(0);\n }\n break;\n\n case 'ArrowUp':\n e.preventDefault();\n if (!isSelectOpen()) {\n wrapper.classList.add('is-active');\n // Wait for dropdown to open, then focus first option (matches native)\n requestAnimationFrame(() => {\n focusOption(0);\n });\n } else {\n const options = customList.querySelectorAll('[role=\"option\"]');\n focusOption(options.length - 1);\n }\n break;\n\n case 'Escape':\n if (isSelectOpen()) {\n e.preventDefault();\n wrapper.classList.remove('is-active');\n }\n break;\n\n case 'Home':\n e.preventDefault();\n if (!isSelectOpen()) {\n wrapper.classList.add('is-active');\n }\n focusOption(0);\n break;\n\n case 'End':\n e.preventDefault();\n if (!isSelectOpen()) {\n wrapper.classList.add('is-active');\n }\n const endOptions = customList.querySelectorAll('[role=\"option\"]');\n focusOption(endOptions.length - 1);\n break;\n\n default:\n // Handle typeahead search\n if (handleTypeahead(e.key)) {\n e.preventDefault();\n }\n break;\n }\n };\n addHandler(button, 'keydown', buttonKeydownHandler);\n\n // Option keyboard events (delegated)\n const listKeydownHandler = (e: KeyboardEvent) => {\n const option = (e.target as Element).closest('[role=\"option\"]') as HTMLElement | null;\n if (!option) return;\n\n const options = Array.from(customList.querySelectorAll('[role=\"option\"]'));\n const currentIdx = options.indexOf(option);\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n if (currentIdx < options.length - 1) {\n focusOption(currentIdx + 1);\n }\n break;\n\n case 'ArrowUp':\n e.preventDefault();\n if (currentIdx > 0) {\n focusOption(currentIdx - 1);\n }\n // Stay on first option if already there (matches native)\n break;\n\n case 'Enter':\n e.preventDefault();\n selectOption(option);\n break;\n\n case 'Escape':\n e.preventDefault();\n wrapper.classList.remove('is-active');\n button.focus();\n break;\n\n case 'Home':\n e.preventDefault();\n focusOption(0);\n break;\n\n case 'End':\n e.preventDefault();\n focusOption(options.length - 1);\n break;\n\n default:\n // Handle typeahead search\n if (handleTypeahead(e.key)) {\n e.preventDefault();\n }\n break;\n }\n };\n addHandler(customList, 'keydown', listKeydownHandler);\n\n // Option click events\n const listClickHandler = (e: MouseEvent) => {\n const option = (e.target as Element).closest('[role=\"option\"]') as HTMLElement | null;\n if (option) {\n selectOption(option);\n }\n };\n addHandler(customList, 'click', listClickHandler);\n\n // Handle tabbing out of select list\n const listFocusoutHandler = (e: FocusEvent) => {\n // Check if focus is moving outside the wrapper (or to browser chrome)\n if (\n (!e.relatedTarget || !wrapper.contains(e.relatedTarget as Node)) &&\n wrapper.classList.contains('is-active')\n ) {\n wrapper.classList.remove('is-active'); // Close the dropdown\n }\n };\n addHandler(customList, 'focusout', listFocusoutHandler);\n\n // Handle clicks outside to close dropdown\n const documentClickHandler = (e: MouseEvent) => {\n // If dropdown is open and click is outside wrapper, close it\n if (wrapper.classList.contains('is-active') && !wrapper.contains(e.target as Node)) {\n wrapper.classList.remove('is-active');\n }\n };\n addHandler(document, 'click', documentClickHandler);\n\n // Monitor for class changes on wrapper and update ARIA states\n const observer = new MutationObserver(() => {\n updateARIAStates();\n });\n\n observer.observe(wrapper, {\n attributes: true,\n attributeFilter: ['class'],\n });\n addObserver(observer);\n\n // Observe native select for disabled attribute changes\n const disabledObserver = new MutationObserver(() => {\n updateDisabledState();\n });\n disabledObserver.observe(realSelect, {\n attributes: true,\n attributeFilter: ['disabled'],\n });\n addObserver(disabledObserver);\n\n // Sync with real select changes\n const selectChangeHandler = () => {\n const selectedOption = realSelect.options[realSelect.selectedIndex];\n if (selectedOption) {\n const options = customList.querySelectorAll('[role=\"option\"]');\n const customOption = Array.from(options).find(\n (opt) => opt.getAttribute('data-value') === selectedOption.value\n );\n if (customOption) {\n // Update button text\n const text = customOption.querySelector('span')?.textContent || customOption.textContent;\n const buttonText = button.querySelector('span') || button;\n if (buttonText.tagName === 'SPAN') {\n buttonText.textContent = text;\n }\n\n // Update is-filled class based on value\n if (selectedOption.value) {\n button.classList.add('is-filled');\n } else {\n button.classList.remove('is-filled');\n }\n\n // Update aria-selected\n options.forEach((opt) => {\n opt.setAttribute('aria-selected', 'false');\n });\n customOption.setAttribute('aria-selected', 'true');\n }\n }\n };\n addHandler(realSelect, 'change', selectChangeHandler);\n addHandler(realSelect, 'input', selectChangeHandler);\n\n // Handle form reset\n const form = realSelect.closest('form') as HTMLFormElement | null;\n if (form) {\n const formResetHandler = () => {\n // Native select resets on next tick\n setTimeout(() => {\n selectChangeHandler();\n }, 0);\n };\n addHandler(form, 'reset', formResetHandler);\n }\n }\n\n // Initialize on DOM ready\n if (document.readyState === 'loading') {\n cleanup.domContentLoadedHandler = initCustomSelects;\n document.addEventListener('DOMContentLoaded', cleanup.domContentLoadedHandler);\n } else {\n initCustomSelects();\n }\n\n // INTERNAL API: Exposed for dynamic content reinitialization\n // WARNING: This is an internal API and may change without notice\n // Use window.hsmain.form.reinit() instead (if available in future versions)\n (window as any).initCustomSelects = initCustomSelects;\n\n return {\n result: 'select initialized',\n destroy: () => {\n // Remove DOMContentLoaded listener\n if (cleanup.domContentLoadedHandler) {\n document.removeEventListener('DOMContentLoaded', cleanup.domContentLoadedHandler);\n cleanup.domContentLoadedHandler = null;\n }\n\n // Disconnect all observers\n cleanup.observers.forEach((obs) => obs.disconnect());\n cleanup.observers.length = 0;\n\n // Clear all timeouts\n cleanup.timeouts.forEach((timeoutId) => clearTimeout(timeoutId));\n cleanup.timeouts.length = 0;\n\n // Remove all event listeners\n cleanup.handlers.forEach(({ element, event, handler, options }) => {\n element.removeEventListener(event, handler, options);\n });\n cleanup.handlers.length = 0;\n\n // Remove window API\n if ((window as any).initCustomSelects) {\n delete (window as any).initCustomSelects;\n }\n },\n };\n}\n","/**\n * Select Orchestrator\n *\n * Coordinates initialization of select enhancement functions in proper sequence.\n * Ensures states populate before custom UI is created.\n *\n * Features:\n * - Sequential initialization (states → custom-select)\n * - Error handling with partial cleanup\n * - Centralized cleanup/destroy management\n * - Passes individual configs to sub-functions\n *\n * Initialization Order:\n * 1. states - Populates native <select> with US states\n * 2. custom-select - Creates custom UI over native select\n *\n * This order is critical: custom-select needs to read the populated\n * options from the native select that states creates.\n */\nimport { init as statesInit } from './functions/states.ts';\nimport { init as customSelectInit } from './functions/custom-select.ts';\n\nexport async function init(selectConfig: any) {\n const cleanup = { destroyFunctions: [] as Array<() => void> };\n\n try {\n // IMPORTANT: Load states FIRST to populate native select,\n // then load custom-select to create custom UI\n const statesResult = statesInit(selectConfig.states);\n if (statesResult?.destroy) cleanup.destroyFunctions.push(statesResult.destroy);\n\n const customSelectResult = customSelectInit(selectConfig['custom-select']);\n if (customSelectResult?.destroy) cleanup.destroyFunctions.push(customSelectResult.destroy);\n\n return {\n result: 'select initialized',\n destroy: () => {\n cleanup.destroyFunctions.forEach((destroyFn) => {\n try {\n destroyFn();\n } catch (error) {\n console.error('[select] Error during cleanup:', error);\n }\n });\n cleanup.destroyFunctions.length = 0;\n },\n };\n } catch (error) {\n console.error('[select] Initialization failed:', error);\n // Cleanup any partial initialization\n cleanup.destroyFunctions.forEach((fn) => {\n try {\n fn();\n } catch (cleanupError) {\n console.error('[select] Error during error cleanup:', cleanupError);\n }\n });\n throw error;\n }\n}\n","/**\n * Form Orchestrator\n *\n * Loads form enhancement modules based on element presence.\n * Static imports ensure all modules bundle into single file.\n *\n * Features:\n * - Conditional initialization based on element presence\n * - Centralized cleanup management\n * - Single bundled output file\n *\n * Modules:\n * - honeypot: Spam prevention for forms\n * - range: Range slider with CSS custom properties\n * - test: Development mode form testing\n * - select: Custom select UI (handles states dependency internally)\n */\n\nimport config from '@config';\nimport { getSelector, type ModuleConfig } from '@utils';\nimport { init as honeypotInit } from './functions/honeypot.ts';\nimport { init as rangeInit } from './functions/range.ts';\nimport { init as testInit } from './functions/test.ts';\nimport { init as selectInit } from './functions/select/select.ts';\n\nexport async function init() {\n const moduleConfig = config.default.form;\n const cleanup = {\n destroyFunctions: [] as Array<() => void>,\n };\n\n // Initialize honeypot if form-handler exists\n const honeypotSelector = getSelector(moduleConfig.honeypot as ModuleConfig, 'form-handler');\n if (document.querySelector(honeypotSelector)) {\n try {\n const result = honeypotInit(moduleConfig.honeypot);\n if (result?.destroy) {\n cleanup.destroyFunctions.push(result.destroy);\n }\n } catch (error) {\n console.error('[form] Error initializing honeypot:', error);\n }\n }\n\n // Initialize range if wrapper exists\n const rangeSelector = getSelector(moduleConfig.range as ModuleConfig, 'wrapper');\n if (document.querySelector(rangeSelector)) {\n try {\n const result = rangeInit(moduleConfig.range as any);\n if (result?.destroy) {\n cleanup.destroyFunctions.push(result.destroy);\n }\n } catch (error) {\n console.error('[form] Error initializing range:', error);\n }\n }\n\n // Initialize test if wrapper exists\n const testSelector = getSelector(moduleConfig.test as ModuleConfig, 'wrapper');\n if (document.querySelector(testSelector)) {\n try {\n const result = testInit(moduleConfig.test);\n if (result?.destroy) {\n cleanup.destroyFunctions.push(result.destroy);\n }\n } catch (error) {\n console.error('[form] Error initializing test:', error);\n }\n }\n\n // Initialize select if wrapper exists\n const selectSelector = getSelector(moduleConfig.select as ModuleConfig, 'wrapper');\n if (document.querySelector(selectSelector)) {\n try {\n const result = await selectInit(moduleConfig.select);\n if (result?.destroy) {\n cleanup.destroyFunctions.push(result.destroy);\n }\n } catch (error) {\n console.error('[form] Error initializing select:', error);\n }\n }\n\n return {\n result: `form initialized (${cleanup.destroyFunctions.length} modules active)`,\n destroy: () => {\n cleanup.destroyFunctions.forEach((destroyFn) => {\n try {\n destroyFn();\n } catch (error) {\n console.error('[form] Error during cleanup:', error);\n }\n });\n cleanup.destroyFunctions.length = 0;\n },\n };\n}\n","/**\n * Honeypot Spam Prevention\n *\n * Simple honeypot field implementation to prevent bot form submissions.\n * Bots auto-fill all fields including hidden ones; legitimate users only fill visible fields.\n *\n * Features:\n * - Listens for all form submissions on the page\n * - Checks if honeypot field (hidden) has been filled\n * - Blocks submission if honeypot contains a value (bot detected)\n * - Uses event capture phase for early interception\n *\n * HTML Structure:\n * <form>\n * <input type=\"text\" name=\"website\" data-hs-form=\"form-handler\" style=\"display:none\">\n * </form>\n *\n * Best Practices:\n * - Hide with CSS (display:none), not type=\"hidden\"\n * - Use realistic field names (\"website\", \"company\")\n * - No visible label or placeholder\n */\n\nimport { querySelector } from '@utils';\n\nexport function init(config) {\n // Centralized cleanup tracking\n const cleanup = {\n honeypotHandler: null,\n };\n\n // Honeypot spam prevention\n const honeypotHandler = (e: Event) => {\n const form = e.target as HTMLElement;\n if (form.tagName !== 'FORM') return;\n\n const honeypot = querySelector(config, 'form-handler', form) as HTMLInputElement;\n if (honeypot && honeypot.value) {\n // Honeypot filled - likely a bot\n e.preventDefault();\n e.stopPropagation();\n e.stopImmediatePropagation();\n return false;\n }\n };\n\n cleanup.honeypotHandler = honeypotHandler;\n document.addEventListener('submit', honeypotHandler, true);\n\n return {\n result: 'honeypot initialized',\n destroy: () => {\n // Remove honeypot handler\n if (cleanup.honeypotHandler) {\n document.removeEventListener('submit', cleanup.honeypotHandler, true);\n cleanup.honeypotHandler = null;\n }\n },\n };\n}\n","/**\n * Form Test Mode\n *\n * Development tool that prevents form submissions and displays form data in real-time.\n * Useful for testing forms without actually submitting them to servers or triggering actions.\n *\n * Features:\n * - Prevents all form submissions (preventDefault with capture phase)\n * - Displays live form data as JSON on input/change\n * - Shows formatted submit data with timestamp on submit attempt\n * - Logs browser validation failures\n * - Works with native HTML5 form validation\n *\n * HTML Structure:\n * <div data-hs-form-test=\"wrapper\">\n * <form>\n * <input name=\"email\" required>\n * <button type=\"submit\">Submit</button>\n * </form>\n * <div data-hs-form-test=\"info\"></div>\n * </div>\n *\n * Console Output:\n * [form-test] Submit button clicked\n * [form-test] Submission prevented - displaying test results\n */\n\nimport { querySelectorAll, querySelector } from '@utils';\n\nexport function init(config) {\n // Centralized cleanup tracking\n const cleanup = {\n handlers: [],\n };\n\n const addHandler = (\n element: Element,\n event: string,\n handler: EventListener,\n options?: boolean\n ) => {\n element.addEventListener(event, handler, options);\n cleanup.handlers.push({ element, event, handler, options });\n };\n\n // Find all test wrappers\n const testWrappers = querySelectorAll(config, 'wrapper');\n\n testWrappers.forEach((wrapper) => {\n // Find form element within wrapper\n const form = wrapper.querySelector('form') as HTMLFormElement;\n if (!form) {\n console.warn(\n '[form-test] No <form> element found within data-hs-form-test=\"wrapper\"',\n wrapper\n );\n return;\n }\n\n // Find test info element (optional)\n const testInfo = querySelector(config, 'info', wrapper);\n\n // Function to collect and display current form data\n const updateLiveData = () => {\n const formData = new FormData(form);\n const data = {};\n for (const [key, value] of formData.entries()) {\n data[key] = value;\n }\n\n if (testInfo) {\n // Show live form data\n const liveDisplay = document.createElement('pre');\n liveDisplay.textContent = JSON.stringify(data, null, 2);\n\n testInfo.innerHTML = '';\n testInfo.appendChild(document.createTextNode('Test mode active - Live form data:'));\n testInfo.appendChild(liveDisplay);\n }\n };\n\n // Set initial message and data\n if (testInfo) {\n testInfo.textContent = 'Test mode active, preventing native submissions';\n // Show initial form state\n updateLiveData();\n }\n\n // Listen to all form inputs for live updates\n addHandler(form, 'input', updateLiveData);\n addHandler(form, 'change', updateLiveData);\n\n // Find submit button\n const submitButton =\n form.querySelector('button[type=\"submit\"], input[type=\"submit\"]') ||\n form.querySelector('button:not([type])');\n\n // Track button clicks to detect when browser validation blocks submission\n if (submitButton) {\n const clickHandler = () => {\n console.log('[form-test] Submit button clicked');\n\n // Use requestAnimationFrame to check if form will submit\n // If form is invalid, submit event won't fire\n requestAnimationFrame(() => {\n if (!form.checkValidity()) {\n console.log('[form-test] Browser blocked submission - validation failed');\n }\n });\n };\n addHandler(submitButton, 'click', clickHandler);\n }\n\n // Handle form submission\n const submitHandler = (e: Event) => {\n e.preventDefault(); // Prevent actual submission\n e.stopPropagation(); // Stop event from bubbling\n e.stopImmediatePropagation(); // Stop other listeners on same element\n\n console.log('[form-test] Submission prevented - displaying test results');\n\n // Get form data\n const formData = new FormData(form);\n const data = {};\n for (const [key, value] of formData.entries()) {\n data[key] = value;\n }\n\n // Create success message\n const timestamp = new Date().toLocaleTimeString();\n const message = `✅ Form would submit successfully at ${timestamp}`;\n\n // Display in test info element or console\n if (testInfo) {\n // Show form data in a formatted way\n const dataDisplay = document.createElement('pre');\n dataDisplay.textContent = JSON.stringify(data, null, 2);\n\n testInfo.innerHTML = ''; // Clear previous\n testInfo.appendChild(document.createTextNode(message));\n testInfo.appendChild(dataDisplay);\n } else {\n console.log(message);\n console.log('Form data:', data);\n }\n\n return false; // Extra insurance to prevent submission\n };\n\n // Use capture phase to catch submit event before anything else\n addHandler(form, 'submit', submitHandler, true);\n });\n\n return {\n result: `test initialized on ${testWrappers.length} form${testWrappers.length !== 1 ? 's' : ''}`,\n destroy: () => {\n // Remove all event listeners\n cleanup.handlers.forEach(({ element, event, handler, options }) => {\n element.removeEventListener(event, handler, options);\n });\n cleanup.handlers.length = 0;\n },\n };\n}\n","function e(e,r){(null==r||r>e.length)&&(r=e.length);for(var n=0,t=Array(r);n<r;n++)t[n]=e[n];return t}function r(r,n){var t=\"undefined\"!=typeof Symbol&&r[Symbol.iterator]||r[\"@@iterator\"];if(t)return(t=t.call(r)).next.bind(t);if(Array.isArray(r)||(t=function(r,n){if(r){if(\"string\"==typeof r)return e(r,n);var t={}.toString.call(r).slice(8,-1);return\"Object\"===t&&r.constructor&&(t=r.constructor.name),\"Map\"===t||\"Set\"===t?Array.from(r):\"Arguments\"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?e(r,n):void 0}}(r))||n&&r&&\"number\"==typeof r.length){t&&(r=t);var o=0;return function(){return o>=r.length?{done:!0}:{done:!1,value:r[o++]}}}throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\")}function n(e,r,n,t){var o={headers:{accept:\"*/*\"}};return r||(o.mode=\"no-cors\"),n&&(o.credentials=\"include\"),o.priority=t?\"high\":\"low\",window.fetch?fetch(e,o):function(e,r){return new Promise(function(n,t,o){(o=new XMLHttpRequest).open(\"GET\",e,o.withCredentials=r),o.setRequestHeader(\"Accept\",\"*/*\"),o.onload=function(){200===o.status?n():t()},o.send()})}(e,n)}var t,o=(t=document.createElement(\"link\")).relList&&t.relList.supports&&t.relList.supports(\"prefetch\")?function(e,r){return new Promise(function(n,t,o){(o=document.createElement(\"link\")).rel=\"prefetch\",o.href=e,r&&o.setAttribute(\"crossorigin\",\"anonymous\"),o.onload=n,o.onerror=t,document.head.appendChild(o)})}:n,i=window.requestIdleCallback||function(e){var r=Date.now();return setTimeout(function(){e({didTimeout:!1,timeRemaining:function(){return Math.max(0,50-(Date.now()-r))}})},1)},a=new Set,c=new Set,u=!1;function s(e,r){return Array.isArray(r)?r.some(function(r){return s(e,r)}):(r.test||r).call(r,e.href,e)}function l(e){if(e){if(e.saveData)return new Error(\"Save-Data is enabled\");if(/2g/.test(e.effectiveType))return new Error(\"network conditions are poor\")}return!0}function f(e){if(void 0===e&&(e={}),window.IntersectionObserver&&\"isIntersecting\"in IntersectionObserverEntry.prototype){var r=function(e){e=e||1;var r=[],n=0;function t(){n<e&&r.length>0&&(r.shift()(),n++)}return[function(e){r.push(e)>1||t()},function(){n--,t()}]}(e.throttle||1/0),n=r[0],t=r[1],o=e.limit||1/0,l=e.origins||[location.hostname],f=e.ignores||[],m=e.delay||0,p=[],v=e.timeoutFn||i,g=\"function\"==typeof e.hrefFn&&e.hrefFn,w=e.prerender||!1;u=e.prerenderAndPrefetch||!1;var y=new IntersectionObserver(function(r){r.forEach(function(r){if(r.isIntersecting)p.push((r=r.target).href),function(e,r){r?setTimeout(e,r):e()}(function(){p.includes(r.href)&&(y.unobserve(r),(u||w)&&c.size<o?h(g?g(r):r.href,e.eagerness).catch(function(r){if(!e.onError)throw r;e.onError(r)}):a.size<o&&!w&&n(function(){d(g?g(r):r.href,e.priority,e.checkAccessControlAllowOrigin,e.checkAccessControlAllowCredentials,e.onlyOnMouseover).then(t).catch(function(r){t(),e.onError&&e.onError(r)})}))},m);else{var i=p.indexOf((r=r.target).href);i>-1&&p.splice(i)}})},{threshold:e.threshold||0});return v(function(){(e.el&&e.el.length&&e.el.length>0&&\"A\"===e.el[0].nodeName?e.el:(e.el||document).querySelectorAll(\"a\")).forEach(function(e){l.length&&!l.includes(e.hostname)||s(e,f)||y.observe(e)})},{timeout:e.timeout||2e3}),function(){a.clear(),y.disconnect()}}}function d(e,t,i,s,f){var d=l(navigator.connection);return d instanceof Error?Promise.reject(new Error(\"Cannot prefetch, \"+d.message)):(c.size>0&&!u&&console.warn(\"[Warning] You are using both prefetching and prerendering on the same document\"),Promise.all([].concat(e).map(function(e){return a.has(e)?[]:(a.add(e),function(e,n,t){var o=[].slice.call(arguments,3);if(!t)return e.apply(void 0,[n].concat(o));for(var i,a=Array.from(document.querySelectorAll(\"a\")).filter(function(e){return e.href===n}),c=new Map,u=function(){var r=i.value,t=function(i){var u=setTimeout(function(){return r.removeEventListener(\"mouseenter\",t),r.removeEventListener(\"mouseleave\",a),e.apply(void 0,[n].concat(o))},200);c.set(r,u)},a=function(e){var n=c.get(r);n&&(clearTimeout(n),c.delete(r))};r.addEventListener(\"mouseenter\",t),r.addEventListener(\"mouseleave\",a)},s=r(a);!(i=s()).done;)u()}(t?n:o,new URL(e,location.href).toString(),f,i,s,t))})))}function h(e,n){void 0===n&&(n=\"immediate\");var t=l(navigator.connection);if(t instanceof Error)return Promise.reject(new Error(\"Cannot prerender, \"+t.message));if(!HTMLScriptElement.supports(\"speculationrules\"))return d(e,!0,!1,!1,\"moderate\"===n||\"conservative\"===n),Promise.reject(new Error(\"This browser does not support the speculation rules API. Falling back to prefetch.\"));for(var o,i=r([].concat(e));!(o=i()).done;)c.add(o.value);a.size>0&&!u&&console.warn(\"[Warning] You are using both prefetching and prerendering on the same document\");var s=function(e,r){var n=document.createElement(\"script\");n.type=\"speculationrules\",n.text='{\"prerender\":[{\"source\": \"list\",\\n \"urls\": [\"'+Array.from(e).join('\",\"')+'\"],\\n \"eagerness\": \"'+r+'\"}]}';try{document.head.appendChild(n)}catch(e){return e}return!0}(c,n);return!0===s?Promise.resolve():Promise.reject(s)}export{f as listen,d as prefetch,h as prerender};\n","/**\n * Link Prefetch\n *\n * Preloads internal links on hover/touch for instant navigation.\n * Uses Quicklink library for intelligent prefetching with built-in safeguards.\n *\n * Features:\n * - Hover-based prefetching (desktop)\n * - Touch-based prefetching (mobile)\n * - Intersection Observer for viewport-based prefetching\n * - Respects data saver mode\n * - Throttles concurrent requests\n * - Same-origin only\n */\n\nimport { listen } from 'quicklink';\n\nexport async function init() {\n // Start listening for link interactions\n const cleanup = listen({\n // Listen on entire document\n el: document.body,\n\n // Limit concurrent prefetches (prevents bandwidth overload)\n limit: 3,\n\n // Throttle network requests (spacing between prefetches in seconds)\n throttle: 2,\n\n // Timeout for each prefetch request (ms)\n timeout: 10000,\n\n // Respect user's data saver preference\n ignoreSlowConnection: true,\n\n // Only prefetch links with these origins (defaults to same-origin)\n origins: [window.location.hostname],\n\n // Delay before prefetch starts (ms) - prevents accidental hovers\n delay: 0, // Quicklink has smart built-in delays\n\n // Priority hints for fetch\n priority: 'low',\n });\n\n return {\n result: 'link-prefetch initialized',\n destroy: () => {\n if (cleanup && typeof cleanup === 'function') {\n cleanup();\n }\n },\n };\n}\n","/**\n * Default Orchestrator\n * Manages all default modules with static imports (Phase 2)\n *\n * Transition loads immediately and blocks, then all other modules load in parallel\n */\nimport config from '@config';\nimport { init as transitionInit } from './functions/transition.ts';\nimport { init as smoothScrollInit } from './functions/smooth-scroll.ts';\nimport { init as navbarInit } from './functions/navbar/navbar.ts';\nimport { init as accordionInit } from './functions/accordion.ts';\nimport { init as tocInit } from './functions/toc/toc.ts';\nimport { init as paginationInit } from './functions/pagination.ts';\nimport { init as comparisonInit } from './functions/comparison.ts';\nimport { init as tabsInit } from './functions/tabs.ts';\nimport { init as formInit } from './functions/form/form.ts';\nimport { init as linkPrefetchInit } from './functions/link-prefetch.ts';\n\nconst CONFIG_ROOT = 'default';\n\nexport async function init() {\n const cleanup = { destroyFunctions: [] as Array<() => void> };\n const moduleConfig = config[CONFIG_ROOT];\n\n // Phase 1: Transition must load and init first (blocks other modules)\n // Note: Transition handles IX3 wait internally before triggering enter animation\n try {\n const transitionResult = await transitionInit();\n if (transitionResult?.destroy) {\n cleanup.destroyFunctions.push(transitionResult.destroy);\n }\n } catch (error) {\n console.error('[default] Error initializing transition:', error);\n }\n\n // Phase 2: All other modules run in parallel after transition\n const modulePromises = [\n smoothScrollInit(moduleConfig['smooth-scroll'] as any),\n navbarInit(moduleConfig.navbar),\n accordionInit(moduleConfig.accordion),\n tocInit(),\n paginationInit(moduleConfig.pagination as any),\n comparisonInit(moduleConfig.comparison as any),\n tabsInit(moduleConfig.tabs as any),\n formInit(),\n linkPrefetchInit(),\n ];\n\n const results = await Promise.allSettled(modulePromises);\n\n // Collect destroy functions from successful inits\n results.forEach((result) => {\n if (result.status === 'fulfilled' && result.value?.destroy) {\n cleanup.destroyFunctions.push(result.value.destroy);\n }\n });\n\n // Log summary\n const succeeded = results.filter((r) => r.status === 'fulfilled').length;\n const failed = results.length - succeeded;\n if (failed > 0) {\n console.warn(\n `[default] ${succeeded + 1}/${results.length + 1} modules loaded successfully. ${failed} failed but won't affect other modules.`\n );\n }\n\n return {\n result: 'default initialized',\n destroy: () => {\n cleanup.destroyFunctions.forEach((destroyFn) => {\n try {\n destroyFn();\n } catch (error) {\n console.error('[default] Error during cleanup:', error);\n }\n });\n cleanup.destroyFunctions.length = 0;\n },\n };\n}\n"],"names":["globalConfig","config","_global","moduleConfig","default","transition","API_NAME","apiName","async","init","transitionWrapper","querySelector","result","destroy","initializedAttr","hasAttribute","setAttribute","isSPA","window","settings","eventHandlers","Map","delayTimeout","loadingTimeout","findTrigger","type","namespace","root","triggerAttr","getSelector","namespaceAttr","newSyntaxTriggers","querySelectorAll","length","namespaceWrapper","namespaceTrigger","defaultTrigger","Array","from","find","trigger","parent","parentElement","separateTriggerAttr","separateTriggers","playExitAnimation","Promise","resolve","exitTrigger","exitTime","exitTimeAttr","value","getAttribute","parseFloat","getExitTime","click","setTimeout","playEnterAnimation","enterTrigger","isFirstLoad","sessionStorage","getItem","firstDelay","firstDelayAttr","getFirstDelay","triggerAnimation","setItem","handleExitEvent","event","detail","handleEnterEvent","set","addEventListener","linkClickHandler","e","link","target","closest","hostname","location","indexOf","preventDefault","href","then","document","pageShowHandler","persisted","reload","resizeHandler","style","display","domReadyHandler","isWebflow","classList","add","classes","loading","waitForIx3","clearTimeout","remove","once","forEach","handler","removeEventListener","clear","removeAttribute","clickHandler","keydownHandler","handleAnchorActivation","targetId","substring","targetElement","getElementById","history","replaceState","id","offset","gsapLib","getGsap","prefersReducedMotion","targetPosition","getBoundingClientRect","top","scrollY","scrollTo","focus","preventScroll","gsap","to","duration","y","offsetY","ease","onComplete","scrollToElement","proxyElement","console","log","HTMLElement","computedTop","getComputedStyle","getScrollOffset","$","off","documentElement","scrollBehavior","body","key","cleanup","observers","handlers","addObserver","addHandler","dropdownWrappers","hoverDropdowns","wrapper","clickableSelector","clickable","toggle","dropdownList","warn","heightWrapper","animationTarget","toggleText","textContent","trim","sanitizedText","toLowerCase","replace","toggleId","listId","inert","menuItems","item","index","currentMenuItemIndex","isDropdownOpen","contains","active","updateARIAStates","isOpen","activeElement","animateHeight","setHeight","observer","MutationObserver","observe","attributes","attributeFilter","push","mouseenterHandler","mouseleaveHandler","dropdownKeydownHandler","focusinHandler","setupDropdown","element","options","obs","disconnect","navbarConfig","state","focusTrapHandler","menuButtons","menu","navbarWrapper","menuId","Date","now","menuButton","shouldAutoFocus","isMenuOpen","updateMenuState","wasOpen","openModal","btn","clickableItems","formElements","focusableArray","firstElement","lastElement","shiftKey","createFocusTrap","menuClickableSelector","allElements","closeModal","removeFocusTrap","setupMenu","previousState","handleStateChange","currentState","getPropertyValue","cssVariables","cssVars","values","inactive","stateObserver","ResizeObserver","setupMenuDisplayObserver","navbar","openDropdown","allNavbarElements","focusableElements","filter","el","menuSelector","elements","primary","split","skipSelector","computedStyle","htmlEl","visibility","opacity","offsetWidth","offsetHeight","parentStyle","parentHtmlEl","currentIndex","menuContainer","currentFocusIndex","current","getFocusableElements","tagName","setupMenuArrowNavigation","destroyFunctions","results","allSettled","dropdownInit","dropdown","menuInit","arrowNavigationInit","status","succeeded","r","failed","destroyFn","error","accordionWrappers","initializedCount","button","content","heightSelector","height","heightValue","buttonId","contentId","openText","properties","open","closedText","closed","hasTextSwap","stateElements","stateSelector","isAccordionOpen","text","defaultState","setupAccordionAccessibility","activeClass","scrollTimeout","headings","contentAreas","tocLists","contentArea","tocList","children","template","cloneNode","templateLink","innerHTML","h2Headings","heading","sectionId","tocItem","number","createElement","appendChild","createTextNode","tocLinks","currentActive","updateActiveLink","innerHeight","newActive","i","activeLink","IntersectionObserver","rootMargin","threshold","toc","headingLinksSelector","headingLinksInit","progressBarSelector","configObj","progressConfig","tocConfig","ScrollTrigger","registerPlugin","scrollTriggers","wrappers","primaryAttr","attr","cleanValue","bar","width","scrollTrigger","start","end","scrub","invalidateOnRefresh","onUpdate","self","includes","st","kill","progressBarInit","liveRegions","container","instance","list","controls","counter","dotsWrap","nextButton","prevButton","initialized","nextClickable","prevClickable","desktopItems","parseInt","show","mobileItems","showMobile","String","isMobileLayout","allItems","totalItems","totalPages","currentPage","isAnimating","itemsPerPage","dotTemplates","wrapperChildren","liveRegion","className","cssText","updateCounter","announcePageChange","manageFocus","page","htmlPage","updateHeight","targetPage","initializeDots","existingDots","activeDot","dot","inactiveDot","navigateToPage","keyHandler","updateActiveDot","initializePagination","forceItemsPerPage","currentIsMobile","Math","ceil","child","removeChild","blur","Object","assign","pageLists","_","pageList","startIndex","endIndex","min","slice","insertBefore","transform","currentLayoutIsMobile","resizeObserver","newIsMobile","clearance","targetScrollPosition","bottom","pageYOffset","behavior","transitionTimeout","handleTransitionEnd","navigate","direction","nextHandler","prevHandler","initPaginationInstance","parentNode","Draggable","warnMissingDependencies","draggables","templateNameSelector","templateDescSelector","templateBeforeImageSelector","templateAfterImageSelector","updateClipPath","percentage","setProperty","clip","loadSlide","templateItem","templateItems","templateName","nameElement","templateDesc","descElement","templateBeforeImage","beforeImage","src","alt","templateAfterImage","afterImage","applyMode","paginationContainer","dotIndex","updatePagination","slider","mode","sliderPosition","navigateSlide","newIndex","maxIndex","targetIndex","templateList","templateItemsSelector","imageWrapper","beforeImageWrapper","afterImageWrapper","missing","join","draggable","draggableInstance","create","bounds","onDrag","rect","x","left","max","clickX","clientX","offsetX","update","modeType","modeWrapper","modeButtons","setMode","leftArrow","navType","rightArrow","setupNavigation","templateDot","setupPagination","setupKeyboardNav","d","timers","animationFrames","addAnimationFrame","getProgressVarName","prefix","progress","setProgress","setupTabSystem","linksWrapper","listWrapper","tabLinkElements","tabPanels","tabButtons","map","linkEl","autoplayAttr","autoplay","durationAttr","hoverAttr","hover","animationAttr","animation","animDurationAttr","animationDuration","autoplayEnabled","pauseOnHover","animationType","tabSystemId","random","toString","panel","panelId","tabId","autoplayTimer","progressAnimationFrame","progressStartTime","isPaused","isTransitioning","isInView","activateTab","skipAnimation","previousIndex","currentProgress","startAutoplay","previousPanel","currentPanel","position","clipPath","pointerEvents","outPanel","inPanel","gsapInstance","tl","timeline","defaults","animateClip","animateFade","updateProgress","timestamp","requestAnimationFrame","stopAutoplay","elapsedTime","remainingTime","startProgress","resumeStartTime","performance","resumeUpdate","totalProgress","cancelAnimationFrame","pauseAutoplay","resumeAutoplay","isUsingKeyboard","updateToggleState","controlsSelector","toggleControl","toggleButton","control","controlType","controlButton","entries","entry","isIntersecting","tabWrappers","timerId","frameId","domContentLoadedHandler","initRangeComponents","htmlWrapper","dataset","hsFormRangeInit","input","output","val","initSingleRange","readyState","US_STATES","name","timeouts","addTimeout","timeoutId","initCustomSelects","div","select","firstChild","realSelect","selectName","customList","updateDisabledState","disabled","optionTemplate","firstElementChild","templateClone","option","optionElement","textSpan","selected","buttonText","label","labelId","heightElement","searchString","searchTimeout","isSelectOpen","isCurrentlyOpen","opt","focusOption","handleTypeahead","splice","findIndex","every","char","letter","startsWith","clearSearch","matchIndex","selectOption","dispatchEvent","Event","bubbles","buttonClickHandler","buttonKeydownHandler","formElement","submitButton","listKeydownHandler","currentIdx","listFocusoutHandler","relatedTarget","documentClickHandler","disabledObserver","selectChangeHandler","selectedOption","selectedIndex","customOption","form","initSingleSelect","selectConfig","statesResult","stateSelects","selectElement","existingOptions","templateOption","placeholderText","placeholder","statesInit","states","customSelectResult","customSelectInit","fn","cleanupError","honeypotSelector","honeypot","honeypotHandler","stopPropagation","stopImmediatePropagation","honeypotInit","rangeSelector","range","rangeInit","testSelector","test","testWrappers","testInfo","updateLiveData","formData","FormData","data","liveDisplay","JSON","stringify","checkValidity","message","toLocaleTimeString","dataDisplay","testInit","selectSelector","selectInit","n","t","Symbol","iterator","call","next","bind","isArray","constructor","o","done","TypeError","headers","accept","credentials","priority","fetch","XMLHttpRequest","withCredentials","setRequestHeader","onload","send","relList","supports","rel","onerror","head","requestIdleCallback","didTimeout","timeRemaining","a","Set","c","u","s","some","l","saveData","Error","effectiveType","f","IntersectionObserverEntry","prototype","shift","throttle","limit","origins","ignores","m","delay","p","v","timeoutFn","g","hrefFn","w","prerender","prerenderAndPrefetch","unobserve","size","navigator","connection","reject","HTMLScriptElement","concat","h","eagerness","catch","onError","checkAccessControlAllowOrigin","checkAccessControlAllowCredentials","onlyOnMouseover","nodeName","timeout","all","has","arguments","apply","get","delete","URL","listen","ignoreSlowConnection","transitionResult","transitionInit","modulePromises","smoothScrollInit","navbarInit","accordionInit","accordion","tocInit","paginationInit","pagination","comparisonInit","comparison","tabsInit","tabs","formInit","linkPrefetchInit"],"mappings":"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","x_google_ignoreList":[20]}