{"version":3,"sources":["jsdelivr-header.js","/gh/willmyerscode/horizontal-timeline@1.0.17/horizontalTimeline.js"],"names":[],"mappings":"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","file":"/gh/willmyerscode/horizontal-timeline@1.0.17/horizontalTimeline.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /gh/willmyerscode/horizontal-timeline@1.0.17/horizontalTimeline.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","/**\n * Horizontal Timeline Plugin for Squarespace\n * Transforms list sections into scroll-driven horizontal timelines\n * Copyright Will-Myers.com\n **/\n\nclass WMHorizontalTimeline {\n  static pluginName = 'horizontal-timeline';\n\n  static emitEvent(type, detail = {}, elem = document) {\n    elem.dispatchEvent(new CustomEvent(`wm-${this.pluginName}${type}`, { detail, bubbles: true }));\n  }\n\n  constructor(el, settings = {}) {\n    this.el = el;\n    this.settings = {\n      scrollPerItem: 300, // pixels of scroll per item\n      navigationType: 'scroll', // 'scroll' or 'arrows'\n      itemCards: false, // enable inverted card styling\n      mobileLayout: 'horizontal', // 'horizontal' or 'vertical'\n      arrowPlacement: 'side', // 'side', 'bottom', 'bottom-left', 'bottom-right'\n      arrowPlacementMobile: 'side', // 'side', 'bottom', 'bottom-left', 'bottom-right'\n      ...settings\n    };\n    this.data = null;\n    this.sectionTitle = null;\n    this.sectionButton = null;\n    this.options = null;\n    this.styles = null;\n    this.originalContainer = null;\n    this.pluginName = this.constructor.pluginName;\n    this.isBackend = window.top !== window.self;\n    this.timelineWrapper = null;\n    this.progressFill = null;\n    this.itemsTrack = null;\n    this.dots = [];\n    this.scrollHeight = 0;\n    this.boundHandleScroll = null;\n    this.boundHandleResize = null;\n    this.resizeObserver = null;\n    // Arrow navigation\n    this.currentIndex = 0;\n    this.prevButton = null;\n    this.nextButton = null;\n    this.init();\n  }\n\n  init() {\n    WMHorizontalTimeline.emitEvent(':beforeInit', { el: this.el }, this.el);\n    this.addDataAttribute();\n    this.extractData();\n    this.removeOrHideOriginalListSectionContent();\n    this.buildLayout();\n    this.calculateDimensions();\n    this.bindEvents();\n    WMHorizontalTimeline.emitEvent(':afterInit', { el: this.el }, this.el);\n  }\n\n  addDataAttribute() {\n    this.el.setAttribute('data-wm-plugin', this.pluginName);\n    this.el.setAttribute('data-wm-navigation-type', this.settings.navigationType);\n    if (this.settings.itemCards) {\n      this.el.setAttribute('data-wm-item-cards', '');\n    }\n    if (this.settings.mobileLayout) {\n      this.el.setAttribute('data-wm-mobile-layout', this.settings.mobileLayout);\n    }\n    if (this.settings.arrowPlacement) {\n      this.el.setAttribute('data-wm-arrow-placement', this.settings.arrowPlacement);\n    }\n    if (this.settings.arrowPlacementMobile) {\n      this.el.setAttribute('data-wm-arrow-placement-mobile', this.settings.arrowPlacementMobile);\n    }\n  }\n\n  extractData() {\n    const container = this.el.querySelector('.user-items-list-item-container');\n    if (!container || !container.dataset.currentContext) {\n      console.error(`[${this.pluginName}] No data-current-context found`);\n      return;\n    }\n\n    const contextData = JSON.parse(container.dataset.currentContext);\n    this.originalContainer = container;\n    this.data = contextData.userItems || [];\n    this.options = contextData.options || {};\n    this.styles = contextData.styles || {};\n    this.sectionTitle = contextData.sectionTitle || null;\n    this.sectionButton = contextData.sectionButton || null;\n    this.isSectionButtonEnabled = contextData.isSectionButtonEnabled || false;\n  }\n\n  removeOrHideOriginalListSectionContent() {\n    if (!this.originalContainer) return;\n\n    // Hide the entire user-items-list in the plugin view\n    const userItemsList = this.el.querySelector('.user-items-list');\n    if (userItemsList) {\n      if (this.isBackend) {\n        userItemsList.style.display = 'none';\n      } else {\n        userItemsList.style.display = 'none';\n      }\n    }\n  }\n\n  decodeHtml(html) {\n    const txt = document.createElement('textarea');\n    txt.innerHTML = html;\n    return txt.value;\n  }\n\n  sanitizeTitleHtml(html) {\n    if (!html) return '';\n    // Decode HTML entities\n    const decoded = this.decodeHtml(html);\n    // Create a temporary container\n    const temp = document.createElement('div');\n    temp.innerHTML = decoded;\n    // Remove empty <p> elements\n    const emptyPs = temp.querySelectorAll('p');\n    emptyPs.forEach(p => {\n      if (!p.textContent.trim() && !p.querySelector('img, video, iframe')) {\n        p.remove();\n      }\n    });\n    return temp.innerHTML;\n  }\n\n  buildLayout() {\n    if (!this.data || this.data.length === 0) return;\n\n    // Find the user-items-list to insert the plugin as a sibling\n    const userItemsList = this.el.querySelector('.user-items-list');\n    if (!userItemsList || !userItemsList.parentElement) return;\n\n    const contentElement = userItemsList.parentElement;\n\n    // Create the scroll spacer for sticky behavior\n    const scrollSpacer = document.createElement('div');\n    scrollSpacer.className = 'wm-timeline-scroll-spacer';\n\n    // Create the sticky wrapper\n    const stickyWrapper = document.createElement('div');\n    stickyWrapper.className = 'wm-timeline-sticky-wrapper';\n\n    // Create main timeline wrapper\n    this.timelineWrapper = document.createElement('div');\n    this.timelineWrapper.className = 'wm-timeline-content';\n\n    // Build section title if exists\n    if (this.sectionTitle) {\n      const titleHtml = this.sanitizeTitleHtml(this.sectionTitle);\n      if (titleHtml) {\n        const titleWrapper = document.createElement('div');\n        titleWrapper.className = 'wm-timeline-section-title';\n        // Check if title is just a <p> element (default from Squarespace)\n        // If so, convert to h2\n        const temp = document.createElement('div');\n        temp.innerHTML = titleHtml;\n        const children = temp.children;\n        if (children.length === 1 && children[0].tagName === 'P') {\n          const h2 = document.createElement('h2');\n          h2.innerHTML = children[0].innerHTML;\n          titleWrapper.appendChild(h2);\n        } else {\n          titleWrapper.innerHTML = titleHtml;\n        }\n        this.timelineWrapper.appendChild(titleWrapper);\n      }\n    }\n\n    // Timeline area wrapper (contains progress bar and items)\n    const timelineArea = document.createElement('div');\n    timelineArea.className = 'wm-timeline-area';\n\n    // Build labels track above progress bar\n    const labelsContainer = document.createElement('div');\n    labelsContainer.className = 'wm-timeline-labels-container';\n    \n    this.labelsTrack = document.createElement('div');\n    this.labelsTrack.className = 'wm-timeline-labels-track';\n    \n    labelsContainer.appendChild(this.labelsTrack);\n    timelineArea.appendChild(labelsContainer);\n\n    // Build progress bar container (just the track, dots move with items)\n    const progressContainer = document.createElement('div');\n    progressContainer.className = 'wm-timeline-progress-container';\n\n    const progressTrack = document.createElement('div');\n    progressTrack.className = 'wm-timeline-progress-track';\n\n    this.progressFill = document.createElement('div');\n    this.progressFill.className = 'wm-timeline-progress-fill';\n\n    progressTrack.appendChild(this.progressFill);\n    progressContainer.appendChild(progressTrack);\n    timelineArea.appendChild(progressContainer);\n\n    // Build items track container (dots are now part of each item)\n    const itemsContainer = document.createElement('div');\n    itemsContainer.className = 'wm-timeline-items-container';\n\n    this.itemsTrack = document.createElement('div');\n    this.itemsTrack.className = 'wm-timeline-items-track';\n\n    this.data.forEach((item, index) => {\n      const result = this.buildTimelineItem(item, index);\n      this.itemsTrack.appendChild(result.element);\n      // Store reference to the dot inside the item\n      const dot = result.element.querySelector('.wm-timeline-dot');\n      if (dot) this.dots.push(dot);\n      // Add label to labels track\n      this.labelsTrack.appendChild(result.labelWrapper);\n    });\n\n    itemsContainer.appendChild(this.itemsTrack);\n    timelineArea.appendChild(itemsContainer);\n\n    // Build arrow navigation (list section style with backgrounds)\n    if (this.settings.navigationType === 'arrows') {\n      const arrowsWrapper = document.createElement('div');\n      arrowsWrapper.className = 'wm-timeline-arrows';\n\n      // Previous arrow\n      this.prevButton = document.createElement('button');\n      this.prevButton.className = 'wm-timeline-arrow wm-timeline-arrow--prev';\n      this.prevButton.setAttribute('aria-label', 'Previous');\n      this.prevButton.innerHTML = `<div class=\"wm-timeline-arrow-bg\"></div>\n        <svg viewBox=\"0 0 44 18\" xmlns=\"http://www.w3.org/2000/svg\">\n          <path d=\"M9.90649 16.96L2.1221 9.17556L9.9065 1.39116\"></path>\n          <path d=\"M42.8633 9.18125L3.37868 9.18125\"></path>\n        </svg>`;\n\n      // Next arrow\n      this.nextButton = document.createElement('button');\n      this.nextButton.className = 'wm-timeline-arrow wm-timeline-arrow--next';\n      this.nextButton.setAttribute('aria-label', 'Next');\n      this.nextButton.innerHTML = `<div class=\"wm-timeline-arrow-bg\"></div>\n        <svg viewBox=\"0 0 44 18\" xmlns=\"http://www.w3.org/2000/svg\">\n          <path d=\"M34.1477 1.39111L41.9321 9.17551L34.1477 16.9599\"></path>\n          <path d=\"M1.19088 9.16982H40.6755\"></path>\n        </svg>`;\n\n      arrowsWrapper.appendChild(this.prevButton);\n      arrowsWrapper.appendChild(this.nextButton);\n      timelineArea.appendChild(arrowsWrapper);\n    }\n\n    this.timelineWrapper.appendChild(timelineArea);\n\n    // Build section button if enabled in list section settings\n    if (this.isSectionButtonEnabled && this.sectionButton && this.sectionButton.buttonText) {\n      const buttonWrapper = document.createElement('div');\n      buttonWrapper.className = 'wm-timeline-section-button';\n      \n      const buttonLink = document.createElement('a');\n      buttonLink.className = 'wm-timeline-button sqs-block-button-element sqs-button-element--primary';\n      buttonLink.href = this.sectionButton.buttonLink || '#';\n      buttonLink.textContent = this.sectionButton.buttonText;\n      if (this.sectionButton.buttonNewWindow) {\n        buttonLink.target = '_blank';\n        buttonLink.rel = 'noopener noreferrer';\n      }\n      \n      buttonWrapper.appendChild(buttonLink);\n      this.timelineWrapper.appendChild(buttonWrapper);\n    }\n\n    stickyWrapper.appendChild(this.timelineWrapper);\n    scrollSpacer.appendChild(stickyWrapper);\n    \n    // Insert as sibling to user-items-list (after it)\n    userItemsList.insertAdjacentElement('afterend', scrollSpacer);\n  }\n\n  buildTimelineItem(item, index) {\n    const itemWrapper = document.createElement('div');\n    itemWrapper.className = 'wm-timeline-item';\n    itemWrapper.dataset.index = index;\n\n    // Extract label from title if enclosed in []\n    let titleText = item.title || '';\n    let labelText = '';\n    const labelMatch = titleText.match(/\\[([^\\]]+)\\]/);\n    if (labelMatch) {\n      labelText = labelMatch[1];\n      titleText = titleText.replace(/\\s*\\[[^\\]]+\\]\\s*/, ' ').trim();\n    }\n\n    // Create label wrapper for labels track (always create for alignment)\n    const labelWrapper = document.createElement('div');\n    labelWrapper.className = 'wm-timeline-label-wrapper';\n    labelWrapper.dataset.index = index;\n    \n    if (labelText) {\n      const label = document.createElement('p');\n      label.className = 'wm-timeline-item-label';\n      label.textContent = labelText;\n      labelWrapper.appendChild(label);\n    }\n\n    // Inline label for vertical mobile layout\n    if (labelText) {\n      const inlineLabel = document.createElement('p');\n      inlineLabel.className = 'wm-timeline-item-label-inline';\n      inlineLabel.textContent = labelText;\n      itemWrapper.appendChild(inlineLabel);\n    }\n\n    // Dot (moves with item)\n    const dot = document.createElement('div');\n    dot.className = 'wm-timeline-dot';\n    dot.dataset.index = index;\n    itemWrapper.appendChild(dot);\n\n    // Image\n    if (item.image && item.image.assetUrl && this.options.isMediaEnabled !== false) {\n      const mediaWrapper = document.createElement('div');\n      mediaWrapper.className = 'wm-timeline-item-media';\n      \n      const img = document.createElement('img');\n      img.src = `${item.image.assetUrl}?format=750w`;\n      img.alt = item.title || '';\n      img.loading = 'lazy';\n      \n      const focalX = item.image.mediaFocalPoint?.x ?? 0.5;\n      const focalY = item.image.mediaFocalPoint?.y ?? 0.5;\n      img.style.objectPosition = `${focalX * 100}% ${focalY * 100}%`;\n      \n      mediaWrapper.appendChild(img);\n      itemWrapper.appendChild(mediaWrapper);\n    }\n\n    // Content wrapper for text elements\n    const contentWrapper = document.createElement('div');\n    contentWrapper.className = 'wm-timeline-item-content';\n\n    // Title\n    if (titleText && this.options.isTitleEnabled !== false) {\n      const title = document.createElement('h3');\n      title.className = 'wm-timeline-item-title';\n      title.textContent = titleText;\n      contentWrapper.appendChild(title);\n    }\n\n    // Description\n    if (item.description && this.options.isBodyEnabled !== false) {\n      const description = document.createElement('div');\n      description.className = 'wm-timeline-item-description';\n      description.innerHTML = item.description;\n      contentWrapper.appendChild(description);\n    }\n\n    // Button\n    if (item.button && item.button.buttonText && this.options.isButtonEnabled !== false) {\n      const buttonWrapper = document.createElement('div');\n      buttonWrapper.className = 'wm-timeline-item-button-wrapper';\n      \n      const button = document.createElement('a');\n      button.className = 'wm-timeline-item-button sqs-block-button-element sqs-button-element--secondary';\n      button.href = item.button.buttonLink || '#';\n      button.textContent = item.button.buttonText;\n      if (item.button.buttonNewWindow) {\n        button.target = '_blank';\n        button.rel = 'noopener noreferrer';\n      }\n      \n      buttonWrapper.appendChild(button);\n      contentWrapper.appendChild(buttonWrapper);\n    }\n\n    itemWrapper.appendChild(contentWrapper);\n    return { element: itemWrapper, labelWrapper: labelWrapper };\n  }\n\n  calculateDimensions() {\n    if (!this.data || this.data.length === 0) return;\n\n    const scrollSpacer = this.el.querySelector('.wm-timeline-scroll-spacer');\n    if (!scrollSpacer) return;\n\n    const isMobile = window.innerWidth <= 767;\n    const isVerticalMobile = isMobile && this.settings.mobileLayout === 'vertical';\n\n    // For arrow navigation or vertical mobile layout, no extra scroll height needed\n    if (this.settings.navigationType === 'arrows' || isVerticalMobile) {\n      scrollSpacer.style.height = 'auto';\n      return;\n    }\n\n    // Get viewport height and timeline content height\n    const viewportHeight = window.innerHeight;\n    const stickyWrapper = this.el.querySelector('.wm-timeline-sticky-wrapper');\n    const contentHeight = stickyWrapper ? stickyWrapper.offsetHeight : viewportHeight;\n\n    // Calculate total scroll distance needed\n    // We need enough scroll to move through all items\n    const itemCount = this.data.length;\n    const scrollPerItem = this.settings.scrollPerItem || 300;\n    \n    // Total scroll height = viewport (for initial stick) + scroll distance for all items + viewport (for unstick)\n    this.scrollHeight = contentHeight + (itemCount * scrollPerItem);\n    \n    // Set the scroll spacer height\n    scrollSpacer.style.height = `${this.scrollHeight}px`;\n  }\n\n  updateTimeline() {\n    const scrollSpacer = this.el.querySelector('.wm-timeline-scroll-spacer');\n    if (!scrollSpacer || !this.itemsTrack || !this.progressFill) return;\n\n    const isMobile = window.innerWidth <= 767;\n    const isVertical = isMobile && this.settings.mobileLayout === 'vertical';\n\n    if (isVertical) {\n      const timelineArea = this.el.querySelector('.wm-timeline-area');\n      if (!timelineArea) return;\n      \n      const areaRect = timelineArea.getBoundingClientRect();\n      const viewportHeight = window.innerHeight;\n      const threshold = viewportHeight * 0.3;\n      \n      const scrollStart = threshold - areaRect.top;\n      const scrollRange = areaRect.height - threshold;\n      \n      let progress = Math.max(0, Math.min(1, scrollStart / scrollRange));\n\n      this.progressFill.style.height = `${progress * 100}%`;\n      this.progressFill.style.width = '100%';\n\n      const progressTrack = this.el.querySelector('.wm-timeline-progress-track');\n      if (progressTrack) {\n        const trackRect = progressTrack.getBoundingClientRect();\n        const progressFillBottom = trackRect.top + (progress * trackRect.height);\n\n        this.dots.forEach((dot) => {\n          const dotRect = dot.getBoundingClientRect();\n          const dotCenter = dotRect.top + (dotRect.height / 2);\n          \n          if (progressFillBottom >= dotCenter) {\n            dot.classList.add('wm-timeline-dot--filled');\n          } else {\n            dot.classList.remove('wm-timeline-dot--filled');\n          }\n        });\n      }\n    } else {\n      const rect = scrollSpacer.getBoundingClientRect();\n      const viewportHeight = window.innerHeight;\n      const stickyWrapper = this.el.querySelector('.wm-timeline-sticky-wrapper');\n      const contentHeight = stickyWrapper ? stickyWrapper.offsetHeight : viewportHeight;\n\n      const scrollStart = -rect.top;\n      const scrollRange = this.scrollHeight - contentHeight;\n\n      let progress = Math.max(0, Math.min(1, scrollStart / scrollRange));\n\n      this.progressFill.style.width = `${progress * 100}%`;\n      this.progressFill.style.height = '100%';\n\n      const itemsContainer = this.el.querySelector('.wm-timeline-items-container');\n      const progressTrack = this.el.querySelector('.wm-timeline-progress-track');\n      const timelineContent = this.el.querySelector('.wm-timeline-content');\n      \n      if (itemsContainer && this.itemsTrack) {\n        const containerWidth = itemsContainer.offsetWidth;\n        const trackWidth = this.itemsTrack.scrollWidth;\n        \n        // Get the content padding to inset the end position\n        const contentPadding = timelineContent \n          ? parseFloat(getComputedStyle(timelineContent).paddingLeft) || 0 \n          : 0;\n        \n        const maxTranslate = Math.max(0, trackWidth - containerWidth + contentPadding);\n        const translateX = progress * maxTranslate;\n        this.itemsTrack.style.transform = `translateX(-${translateX}px)`;\n        \n        if (this.labelsTrack) {\n          this.labelsTrack.style.transform = `translateX(-${translateX}px)`;\n        }\n        \n        // Sync progress track with items track\n        if (progressTrack) {\n          progressTrack.style.width = `${trackWidth}px`;\n          progressTrack.style.transform = `translateX(-${translateX}px)`;\n        }\n      }\n\n      // Fill dots based on progress - calculate actual dot positions relative to track\n      if (this.itemsTrack) {\n        const trackWidth = this.itemsTrack.scrollWidth;\n        const progressFillWidth = progress * trackWidth;\n        \n        this.dots.forEach((dot) => {\n          // Get the dot's center position within the items track\n          const item = dot.closest('.wm-timeline-item');\n          if (item) {\n            const itemLeft = item.offsetLeft;\n            const itemWidth = item.offsetWidth;\n            // Dot is centered in the item\n            const dotCenter = itemLeft + (itemWidth / 2);\n            \n            if (progressFillWidth >= dotCenter) {\n              dot.classList.add('wm-timeline-dot--filled');\n            } else {\n              dot.classList.remove('wm-timeline-dot--filled');\n            }\n          }\n        });\n      }\n    }\n  }\n\n  // Arrow navigation methods\n  goToIndex(index) {\n    if (!this.data || this.data.length === 0) return;\n    \n    const itemCount = this.data.length;\n    this.currentIndex = Math.max(0, Math.min(index, itemCount - 1));\n    \n    const itemsContainer = this.el.querySelector('.wm-timeline-items-container');\n    const progressTrack = this.el.querySelector('.wm-timeline-progress-track');\n    const timelineContent = this.el.querySelector('.wm-timeline-content');\n    const items = this.itemsTrack ? this.itemsTrack.querySelectorAll('.wm-timeline-item') : [];\n    \n    if (itemsContainer && this.itemsTrack && items.length > 0 && progressTrack) {\n      const containerWidth = itemsContainer.offsetWidth;\n      const currentItem = items[this.currentIndex];\n      const currentDot = this.dots[this.currentIndex];\n      \n      // Get the content padding to inset the end position\n      const contentPadding = timelineContent \n        ? parseFloat(getComputedStyle(timelineContent).paddingLeft) || 0 \n        : 0;\n      \n      if (currentItem && currentDot) {\n        const itemOffset = currentItem.offsetLeft;\n        const itemWidth = currentItem.offsetWidth;\n        const targetTranslate = Math.max(0, itemOffset - (containerWidth / 2) + (itemWidth / 2));\n        const trackScrollWidth = this.itemsTrack.scrollWidth;\n        const maxTranslate = Math.max(0, trackScrollWidth - containerWidth + contentPadding);\n        const translateX = Math.min(targetTranslate, maxTranslate);\n        \n        // Move items\n        this.itemsTrack.style.transform = `translateX(-${translateX}px)`;\n        \n        // Sync labels track\n        if (this.labelsTrack) {\n          this.labelsTrack.style.transform = `translateX(-${translateX}px)`;\n        }\n        \n        // Sync progress track with items (scrolls off screen)\n        progressTrack.style.width = `${trackScrollWidth}px`;\n        progressTrack.style.transform = `translateX(-${translateX}px)`;\n        \n        // Calculate progress fill to the dot position within the track\n        const dotCenter = itemOffset + (itemWidth / 2);\n        let fillPercent;\n        if (this.currentIndex === itemCount - 1) {\n          fillPercent = 100;\n        } else {\n          fillPercent = (dotCenter / trackScrollWidth) * 100;\n        }\n        \n        this.progressFill.style.width = `${fillPercent}%`;\n      }\n    }\n    \n    // Update dots based on current index\n    this.dots.forEach((dot, i) => {\n      dot.classList.toggle('wm-timeline-dot--filled', i <= this.currentIndex);\n    });\n    \n    this.updateArrowStates();\n  }\n\n  goNext() {\n    if (this.currentIndex < this.data.length - 1) {\n      this.goToIndex(this.currentIndex + 1);\n    }\n  }\n\n  goPrev() {\n    if (this.currentIndex > 0) {\n      this.goToIndex(this.currentIndex - 1);\n    }\n  }\n\n  updateArrowStates() {\n    if (!this.prevButton || !this.nextButton) return;\n    this.prevButton.classList.toggle('wm-timeline-arrow--disabled', this.currentIndex === 0);\n    this.nextButton.classList.toggle('wm-timeline-arrow--disabled', this.currentIndex >= this.data.length - 1);\n  }\n\n  bindEvents() {\n    // Arrow navigation mode (works on desktop and horizontal mobile)\n    if (this.settings.navigationType === 'arrows') {\n      this.isAnimating = false;\n      const arrowDuration = 400; // matches --timeline-arrow-duration default\n      \n      this.prevButton?.addEventListener('click', () => {\n        if (this.isAnimating) return;\n        this.isAnimating = true;\n        this.goPrev();\n        setTimeout(() => { this.isAnimating = false; }, arrowDuration);\n      });\n      this.nextButton?.addEventListener('click', () => {\n        if (this.isAnimating) return;\n        this.isAnimating = true;\n        this.goNext();\n        setTimeout(() => { this.isAnimating = false; }, arrowDuration);\n      });\n      \n      requestAnimationFrame(() => this.goToIndex(0));\n      \n      // For arrow mode, only need resize handler (unless vertical mobile)\n      let resizeTimeout;\n      this.boundHandleResize = () => {\n        clearTimeout(resizeTimeout);\n        resizeTimeout = setTimeout(() => {\n          const currentIsMobile = window.innerWidth <= 767;\n          const currentIsVertical = currentIsMobile && this.settings.mobileLayout === 'vertical';\n          \n          this.calculateDimensions();\n          \n          if (currentIsVertical) {\n            this.updateTimeline();\n          } else {\n            this.goToIndex(this.currentIndex);\n          }\n        }, 100);\n      };\n      window.addEventListener('resize', this.boundHandleResize, { passive: true });\n      \n      // Also need scroll handler for vertical mobile layout\n      if (this.settings.mobileLayout === 'vertical') {\n        let ticking = false;\n        this.boundHandleScroll = () => {\n          if (!ticking) {\n            requestAnimationFrame(() => {\n              const currentIsMobile = window.innerWidth <= 767;\n              const currentIsVertical = currentIsMobile && this.settings.mobileLayout === 'vertical';\n              \n              if (currentIsVertical) {\n                this.updateTimeline();\n              }\n              ticking = false;\n            });\n            ticking = true;\n          }\n        };\n        window.addEventListener('scroll', this.boundHandleScroll, { passive: true });\n      }\n      return;\n    }\n\n    // Scroll navigation mode (default) - works on all layouts\n    let ticking = false;\n    this.boundHandleScroll = () => {\n      if (!ticking) {\n        requestAnimationFrame(() => {\n          this.updateTimeline();\n          ticking = false;\n        });\n        ticking = true;\n      }\n    };\n\n    // Debounced resize handler\n    let resizeTimeout;\n    this.boundHandleResize = () => {\n      clearTimeout(resizeTimeout);\n      resizeTimeout = setTimeout(() => {\n        this.calculateDimensions();\n        this.updateTimeline();\n      }, 100);\n    };\n\n    window.addEventListener('scroll', this.boundHandleScroll, { passive: true });\n    window.addEventListener('resize', this.boundHandleResize, { passive: true });\n\n    // Also observe for size changes\n    if (typeof ResizeObserver !== 'undefined') {\n      this.resizeObserver = new ResizeObserver(() => {\n        this.calculateDimensions();\n        this.updateTimeline();\n      });\n      const itemsTrack = this.el.querySelector('.wm-timeline-items-track');\n      if (itemsTrack) {\n        this.resizeObserver.observe(itemsTrack);\n      }\n    }\n\n    // Initial update\n    requestAnimationFrame(() => {\n      this.updateTimeline();\n    });\n  }\n\n  destroy() {\n    // Remove event listeners\n    if (this.boundHandleScroll) {\n      window.removeEventListener('scroll', this.boundHandleScroll);\n    }\n    if (this.boundHandleResize) {\n      window.removeEventListener('resize', this.boundHandleResize);\n    }\n    if (this.resizeObserver) {\n      this.resizeObserver.disconnect();\n    }\n\n    // Remove custom content\n    const scrollSpacer = this.el.querySelector('.wm-timeline-scroll-spacer');\n    if (scrollSpacer) {\n      scrollSpacer.remove();\n    }\n\n    // Restore original list section visibility\n    const userItemsList = this.el.querySelector('.user-items-list');\n    if (userItemsList) {\n      userItemsList.style.display = '';\n    }\n\n    // Remove data attribute\n    this.el.removeAttribute('data-wm-plugin');\n\n    // Clear references\n    this.timelineWrapper = null;\n    this.progressFill = null;\n    this.itemsTrack = null;\n    this.dots = [];\n\n    WMHorizontalTimeline.emitEvent(':destroy', { el: this.el }, this.el);\n  }\n}\n\n// Immediate initialization\n(function() {\n  const pluginName = 'horizontal-timeline';\n  const sections = document.querySelectorAll(`[id^=\"${pluginName}\"]`);\n  const instances = [];\n\n  sections.forEach(section => {\n    const sectionId = section.id;\n    const settings = window.wmHorizontalTimelineSettings?.[sectionId] || {};\n    const instance = new WMHorizontalTimeline(section, settings);\n    instances.push(instance);\n  });\n\n  // Backend teardown when edit mode activates\n  if (window.top !== window.self) {\n    const observer = new MutationObserver(() => {\n      if (document.body.classList.contains('sqs-edit-mode-active')) {\n        instances.forEach(instance => {\n          if (instance && typeof instance.destroy === 'function') {\n            instance.destroy();\n          }\n        });\n        observer.disconnect();\n      }\n    });\n\n    observer.observe(document.body, {\n      attributes: true,\n      attributeFilter: ['class']\n    });\n  }\n})();\n"]}