{
  "version": 3,
  "sources": ["/cdn/shop/t/80/assets/ndi-component-slider.js?nc=22abd770-33b8-4126-90e8-ac72552fe9db"],
  "sourcesContent": ["/*\n  <ndi-slider> \u2014 dependency-free, accessible slider Custom Element.\n  --------------------------------------------------------------\n  Reused across the site (hero banner, product/deal sliders). The sliding is native\n  CSS scroll-snap (see ndi-component-slider.css) \u2014 cheap and touch-friendly. JS adds\n  prev/next, dots, autoplay (pauses on hover / focus / tab-hidden / reduced-motion),\n  looping, keyboard support, mouse click-drag, and active-dot tracking from the scroll\n  position (works whether one or several slides are visible at once). No Dawn code.\n\n  Markup:\n    <ndi-slider data-autoplay data-interval=\"5000\" data-loop>\n      <ul class=\"ndi-slider__track\"> <li class=\"ndi-slider__slide\">\u2026</li> \u2026 </ul>\n      <button data-ndi-slider=\"prev\">\u2026</button>\n      <button data-ndi-slider=\"next\">\u2026</button>\n      <div class=\"ndi-slider__dots\">\n        <button class=\"ndi-slider__dot\" data-ndi-slider-dot=\"0\">\u2026</button> \u2026\n      </div>\n      <button data-ndi-slider=\"toggle\">\u2026</button>   (optional pause/play)\n    </ndi-slider>\n\n  Attributes: data-autoplay (enable), data-interval (ms, default 5000),\n  data-loop (wrap prev/next; implied by data-autoplay),\n  data-infinite (seamless wrap by hand \u2014 clones the end slides, see below).\n\n  data-infinite: clones the last slide before the first and the first after the\n  last, then silently teleports scrollLeft when the user crosses a clone. This is\n  what makes DRAGGING wrap (data-loop only wraps arrows/dots, which jump the\n  index). Opt-in because clones duplicate slide content in the DOM \u2014 only worth it\n  for one-per-view banners, not multi-card product carousels.\n*/\nif (!customElements.get('ndi-slider')) {\n  class NdiSlider extends HTMLElement {\n    connectedCallback() {\n      this.track = this.querySelector('.ndi-slider__track');\n      if (!this.track) return;\n      this.slides = Array.from(this.track.querySelectorAll('.ndi-slider__slide'));\n      if (this.slides.length < 2) return; // single slide \u2192 nothing to do\n\n      this.dotsContainer = this.querySelector('.ndi-slider__dots');\n      // Page dots (one per scroll-page) adapt to how many slides are visible at the\n      // current breakpoint; without it, dots map 1:1 to slides (hero banner).\n      this.pageDots = this.hasAttribute('data-page-dots');\n      this.dots = Array.from(this.querySelectorAll('[data-ndi-slider-dot]'));\n      this.prevBtn = this.querySelector('[data-ndi-slider=\"prev\"]');\n      this.nextBtn = this.querySelector('[data-ndi-slider=\"next\"]');\n      this.toggleBtn = this.querySelector('[data-ndi-slider=\"toggle\"]');\n\n      this.autoplay = this.hasAttribute('data-autoplay');\n      this.loop = this.autoplay || this.hasAttribute('data-loop');\n      // Clone-based wrap is incompatible with page dots (which assume slides map\n      // 1:1 to real content), so the two are mutually exclusive.\n      this.infinite = this.hasAttribute('data-infinite') && !this.pageDots;\n      this.interval = parseInt(this.getAttribute('data-interval'), 10) || 5000;\n      this.reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)');\n\n      this.index = 0;\n      this.perView = 1;\n      this.pageCount = this.slides.length;\n      this._paused = false; // user-toggled\n      this._held = false; // transient (hover/focus/hidden)\n      this._wasDragged = false;\n      this._raf = 0;\n      this._momentum = 0;\n\n      if (this.infinite) this._buildClones();\n\n      this._bindControls();\n      this._bindScroll();\n      this._bindDrag();\n\n      if (this.pageDots && this.dotsContainer) {\n        this._buildPageDots();\n        let resizeTimer;\n        window.addEventListener('resize', () => {\n          clearTimeout(resizeTimer);\n          resizeTimer = setTimeout(() => this._buildPageDots(), 150);\n        });\n      }\n      this._updateActiveFromScroll();\n\n      if (this.autoplay) {\n        this._startTimer();\n        this._reflectToggle();\n      }\n    }\n\n    disconnectedCallback() {\n      this._stopTimer();\n      if (this._raf) cancelAnimationFrame(this._raf);\n      this._stopGlide();\n      this._stopSettle();\n      clearTimeout(this._idleTimer);\n      clearTimeout(this._settleTimer);\n    }\n\n    // \u2500\u2500 Infinite (clone) mode \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    // Layout becomes: [clone of last][real 0..n-1][clone of first]. Real slide i\n    // lives at DOM position i+1, so this.slides[] (real only) stays the source of\n    // truth for dots/index and only _scrollToReal() knows about the offset.\n    _buildClones() {\n      this._realSlides = this.slides;\n      const first = this.slides[0].cloneNode(true);\n      const last = this.slides[this.slides.length - 1].cloneNode(true);\n      [first, last].forEach((clone) => {\n        clone.classList.add('ndi-slider__slide--clone');\n        clone.setAttribute('aria-hidden', 'true');\n        // Clones duplicate real links/buttons \u2014 keep them off the tab order and\n        // out of the a11y tree so they aren't announced or focusable twice.\n        clone.querySelectorAll('a, button, input, [tabindex]').forEach((el) => {\n          el.setAttribute('tabindex', '-1');\n        });\n      });\n      this.track.insertBefore(last, this.slides[0]);\n      this.track.appendChild(first);\n      this._cloneLead = last;\n      this._cloneTail = first;\n      // Start on the first REAL slide, not the leading clone. Synchronous (not in a\n      // rAF) so the first _updateActiveFromScroll() doesn't read scrollLeft 0 and\n      // light the last dot for a frame. offsetLeft forces layout, which is what\n      // makes the value correct here.\n      this._jumpTo(this.slides[0].offsetLeft);\n    }\n\n    // Jump scrollLeft across the seam without animation. Called when a drag or a\n    // scroll lands on a clone: the clone looks identical to the real slide, so\n    // teleporting to the twin is invisible.\n    _wrapIfOnClone() {\n      if (!this.infinite || this._dragging) return false;\n      const sl = this.track.scrollLeft;\n      const n = this.slides.length;\n      const eps = 2;\n      if (sl <= this._cloneLead.offsetLeft + eps) {\n        this._jumpTo(this.slides[n - 1].offsetLeft);\n        return true;\n      }\n      if (sl >= this._cloneTail.offsetLeft - eps) {\n        this._jumpTo(this.slides[0].offsetLeft);\n        return true;\n      }\n      return false;\n    }\n    _jumpTo(left) {\n      const prev = this.track.style.scrollBehavior;\n      this.track.style.scrollBehavior = 'auto'; // teleport, never animate the seam\n      this.track.scrollLeft = left;\n      this.track.style.scrollBehavior = prev;\n    }\n\n    // \u2500\u2500 Navigation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    goTo(i) {\n      const n = this.slides.length;\n      // Infinite mode scrolls THROUGH the clone (so next() from the last slide\n      // slides forward, not backward across the whole track), then wraps on land.\n      // Arrows/dots/autoplay animate through the same _animateTo as a flick \u2014 the\n      // CSS sets scroll-behavior:auto (so drag snaps aren't re-eased by the\n      // browser), which means scrollTo({behavior:'smooth'}) would jump instead.\n      if (this.infinite && this.loop) {\n        let target;\n        if (i >= n) target = this._cloneTail.offsetLeft;\n        else if (i < 0) target = this._cloneLead.offsetLeft;\n        else target = this.slides[i].offsetLeft;\n        this._animateTo(target);\n        return;\n      }\n      const idx = this.loop ? (i + n) % n : Math.max(0, Math.min(i, n - 1));\n      this._animateTo(this.slides[idx].offsetLeft);\n    }\n    next() { this.goTo(this.index + 1); }\n    prev() { this.goTo(this.index - 1); }\n\n    // \u2500\u2500 Autoplay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    _startTimer() {\n      this._stopTimer();\n      this._timer = setInterval(() => {\n        if (this._paused || this._held || this.reduceMotion.matches) return;\n        this.next();\n      }, this.interval);\n    }\n    _stopTimer() {\n      if (this._timer) { clearInterval(this._timer); this._timer = null; }\n    }\n    _isPlaying() { return this.autoplay && !this._paused; }\n\n    // \u2500\u2500 Wiring \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    _bindControls() {\n      if (this.prevBtn) this.prevBtn.addEventListener('click', () => this.prev());\n      if (this.nextBtn) this.nextBtn.addEventListener('click', () => this.next());\n      if (!this.pageDots) {\n        this.dots.forEach((dot) => {\n          dot.addEventListener('click', () =>\n            this.goTo(parseInt(dot.getAttribute('data-ndi-slider-dot'), 10) || 0)\n          );\n        });\n      }\n      if (this.toggleBtn) {\n        this.toggleBtn.addEventListener('click', () => {\n          this._paused = !this._paused;\n          this._reflectToggle();\n        });\n      }\n\n      // Hold autoplay while the user is on/in the slider, or the tab is hidden.\n      this.addEventListener('mouseenter', () => { this._held = true; });\n      this.addEventListener('mouseleave', () => { this._held = false; });\n      this.addEventListener('focusin', () => { this._held = true; });\n      this.addEventListener('focusout', () => { this._held = false; });\n      document.addEventListener('visibilitychange', () => {\n        this._held = document.hidden;\n      });\n\n      // Keyboard navigation when the track is focused.\n      this.track.setAttribute('tabindex', '0');\n      this.track.addEventListener('keydown', (event) => {\n        if (event.key === 'ArrowLeft') { event.preventDefault(); this.prev(); }\n        else if (event.key === 'ArrowRight') { event.preventDefault(); this.next(); }\n      });\n    }\n\n    // Track the active slide from the scroll position \u2014 the slide whose start is\n    // nearest the current scrollLeft. Correct whether 1 or several slides show.\n    _bindScroll() {\n      this.track.addEventListener('scroll', () => {\n        if (this._raf) return;\n        this._raf = requestAnimationFrame(() => {\n          this._raf = 0;\n          // Wrap only once the scroll has settled \u2014 teleporting mid-animation\n          // would fight the browser's own smooth scroll.\n          if (this.infinite) {\n            clearTimeout(this._settleTimer);\n            this._settleTimer = setTimeout(() => this._wrapIfOnClone(), 60);\n          }\n          this._updateActiveFromScroll();\n        });\n\n        // Scroll-idle watchdog. CSS `proximity` snap is allowed to leave the track\n        // resting between slides, and touch/trackpad scrolling never goes through\n        // the mouse drag handler at all \u2014 so whatever moved the track, once it has\n        // been still for a moment, pull it onto a whole slide.\n        clearTimeout(this._idleTimer);\n        this._idleTimer = setTimeout(() => this._settleIfBetween(), 60);\n      }, { passive: true });\n    }\n\n    // Snap to the nearest slide if we're resting off-boundary. No-op while a drag,\n    // glide, or programmatic settle is in flight \u2014 those own the scroll position.\n    _settleIfBetween() {\n      if (this._dragging || this._glideRaf || this._settling) return;\n      const target = this._nearestSlideOffset();\n      if (target === null) return;\n      if (Math.abs(this.track.scrollLeft - target) < 2) return; // already on a slide\n      this._scrollToSettle(target);\n    }\n    _updateActiveFromScroll() {\n      const sl = this.track.scrollLeft;\n      // Leftmost slide (drives arrows + goTo's notion of position).\n      let best = 0;\n      let bestDist = Infinity;\n      for (let i = 0; i < this.slides.length; i++) {\n        const dist = Math.abs(this.slides[i].offsetLeft - sl);\n        if (dist < bestDist) { bestDist = dist; best = i; }\n      }\n      this.index = best;\n\n      // Active dot: a page index mapped evenly across the scroll range (so the last\n      // page lights up even though the final cards can't reach the left edge), or the\n      // slide index for 1:1 dots.\n      // On a clone the nearest REAL slide is the far end of the track, which would\n      // light the wrong dot for the moment before the wrap lands. Map to the twin.\n      let activeDot = best;\n      if (this.infinite) {\n        if (sl <= this._cloneLead.offsetLeft + 2) activeDot = this.slides.length - 1;\n        else if (sl >= this._cloneTail.offsetLeft - 2) activeDot = 0;\n      }\n      if (this.pageDots) {\n        const maxScroll = this.track.scrollWidth - this.track.clientWidth;\n        activeDot = maxScroll <= 1\n          ? 0\n          : Math.round((sl / maxScroll) * (this.pageCount - 1));\n      }\n      this._setActiveDot(activeDot);\n\n      if (!this.loop) {\n        if (this.prevBtn) this.prevBtn.disabled = best === 0;\n        if (this.nextBtn) this.nextBtn.disabled = best === this.slides.length - 1;\n      }\n    }\n\n    _setActiveDot(i) {\n      this.dots.forEach((dot, di) => {\n        const active = di === i;\n        dot.classList.toggle('is-active', active);\n        dot.setAttribute('aria-current', active ? 'true' : 'false');\n      });\n    }\n\n    // \u2500\u2500 Page dots (multi-visible carousels) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    _slideStride() {\n      if (this.slides.length < 2) return this.slides[0] ? this.slides[0].offsetWidth : 1;\n      const stride = this.slides[1].offsetLeft - this.slides[0].offsetLeft;\n      return stride > 0 ? stride : (this.slides[0].offsetWidth || 1);\n    }\n    _buildPageDots() {\n      this.perView = Math.max(1, Math.round(this.track.clientWidth / this._slideStride()));\n      this.pageCount = Math.max(1, Math.ceil(this.slides.length / this.perView));\n      this.dotsContainer.innerHTML = '';\n      for (let p = 0; p < this.pageCount; p++) {\n        const dot = document.createElement('button');\n        dot.type = 'button';\n        dot.className = 'ndi-slider__dot';\n        dot.setAttribute('aria-label', 'Go to page ' + (p + 1) + ' of ' + this.pageCount);\n        dot.addEventListener('click', () => {\n          this.goTo(Math.min(p * this.perView, this.slides.length - 1));\n        });\n        this.dotsContainer.appendChild(dot);\n      }\n      this.dots = Array.from(this.dotsContainer.children);\n      this._updateActiveFromScroll();\n    }\n\n    // Mouse click-drag to scroll (touch/pen use native scrolling).\n    _bindDrag() {\n      let down = false;\n      let captured = false;\n      let startX = 0;\n      let startScroll = 0;\n      let lastX = 0;\n\n      // Block the browser's native link/image drag so a drag that starts on a\n      // product name or image still swipes the carousel.\n      this.track.addEventListener('dragstart', (e) => e.preventDefault());\n\n      this.track.addEventListener('pointerdown', (e) => {\n        if (e.pointerType !== 'mouse' || e.button !== 0) return;\n        // Arm a potential drag, but DON'T capture the pointer yet \u2014 capturing on a\n        // plain click would steal the click from buttons/links inside the slide\n        // (the click would dispatch to the track). We only capture once the pointer\n        // actually moves past the threshold (see pointermove), so clicks still work.\n        down = true;\n        captured = false;\n        this._wasDragged = false;\n        startX = e.clientX;\n        lastX = e.clientX;\n        this._momentum = 0;\n        startScroll = this.track.scrollLeft;\n      });\n\n      this.track.addEventListener('pointermove', (e) => {\n        if (!down) return;\n        const dx = e.clientX - startX;\n        if (!this._wasDragged && Math.abs(dx) > 4) {\n          // Real drag started \u2014 now take over scrolling.\n          this._wasDragged = true; // click suppression (cleared by the click handler)\n          this._dragging = true; // wrap gate (cleared after the glide settles)\n          this._stopGlide();\n          this._stopSettle();\n          this.classList.add('is-dragging');\n          this.track.style.scrollSnapType = 'none';\n          if (this.track.setPointerCapture) {\n            try { this.track.setPointerCapture(e.pointerId); captured = true; } catch (_) {}\n          }\n        }\n        if (!this._wasDragged) return;\n        this.track.scrollLeft = startScroll - dx;\n        // Velocity for the release glide: px moved since the last move event.\n        this._momentum = e.clientX - (lastX || e.clientX);\n        lastX = e.clientX;\n        this._lastMoveAt = performance.now();\n        // Wrap DURING the drag so you can keep dragging past the ends forever.\n        // Rebase startX/startScroll so the finger stays glued to the same pixel.\n        if (this.infinite) {\n          const n = this.slides.length;\n          const sl = this.track.scrollLeft;\n          if (sl <= this._cloneLead.offsetLeft + 2) {\n            this._jumpTo(this.slides[n - 1].offsetLeft + (sl - this._cloneLead.offsetLeft));\n            startX = e.clientX; startScroll = this.track.scrollLeft;\n          } else if (sl >= this._cloneTail.offsetLeft - 2) {\n            this._jumpTo(this.slides[0].offsetLeft + (sl - this._cloneTail.offsetLeft));\n            startX = e.clientX; startScroll = this.track.scrollLeft;\n          }\n        }\n      });\n\n      const end = (e) => {\n        if (!down) return;\n        down = false;\n        if (captured && this.track.releasePointerCapture) {\n          try { this.track.releasePointerCapture(e.pointerId); } catch (_) {}\n        }\n        captured = false;\n        if (this._wasDragged) {\n          this.classList.remove('is-dragging');\n          // Held still before releasing? Then there's no throw \u2014 drop the stale\n          // velocity from the last move so it settles instead of drifting.\n          if (performance.now() - (this._lastMoveAt || 0) > 100) this._momentum = 0;\n          this._glide();\n        }\n      };\n      this.track.addEventListener('pointerup', end);\n      this.track.addEventListener('pointercancel', end);\n      // Releasing outside the element (or off-window) must still end the drag,\n      // else the track stays stuck in is-dragging with snap disabled.\n      window.addEventListener('pointerup', end);\n\n      // Suppress the click that fires at the end of a drag (so it doesn't navigate /\n      // add to cart). A plain click never set _wasDragged, so it passes through.\n      this.track.addEventListener('click', (e) => {\n        if (this._wasDragged) {\n          e.preventDefault();\n          e.stopPropagation();\n          this._wasDragged = false;\n        }\n      }, true);\n    }\n\n    // \u2500\u2500 Release \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n    // Decide where the gesture should land, then animate there over a fixed\n    // duration. Two cases:\n    //   flick  \u2014 released with speed: commit to the NEXT slide in that direction,\n    //            even if barely moved. This is what makes a quick flick work.\n    //   drag   \u2014 released slowly: land on whichever slide is nearest.\n    // The animation itself is _animateTo (see there for why it's hand-rolled).\n    _glide() {\n      this._stopGlide();\n      if (this.reduceMotion.matches) return this._settleAfterGlide();\n\n      const FLICK = 4; // px/frame \u2014 above this it's a throw, not a drag\n      const v = this._momentum;\n      if (Math.abs(v) < FLICK) return this._settleAfterGlide();\n\n      // v is +ve when the finger moved right (content scrolls left \u2192 previous).\n      const dir = v > 0 ? -1 : 1;\n      const from = this.track.scrollLeft;\n      const bounds = this._settleBounds();\n      // Nearest boundary in the flick's direction, so a flick always advances.\n      const target = dir === 1\n        ? bounds.find((o) => o > from + 1)\n        : [...bounds].reverse().find((o) => o < from - 1);\n      if (target == null) return this._settleAfterGlide();\n      this._animateTo(target);\n    }\n    // Settle to a whole slide. CSS `proximity` snap deliberately does NOT do this \u2014\n    // it lets a gesture rest mid-slide \u2014 so the landing is driven from JS: pick the\n    // nearest boundary and animate to it, then hand control back to CSS snap.\n    _settleAfterGlide() {\n      this._glideRaf = 0;\n      const target = this._nearestSlideOffset();\n      if (target === null || Math.abs(this.track.scrollLeft - target) < 1) {\n        return this._endSettle();\n      }\n      this._scrollToSettle(target);\n    }\n    // All snap positions, clones included, ascending.\n    _settleBounds() {\n      const list = this.infinite\n        ? [this._cloneLead, ...this.slides, this._cloneTail]\n        : this.slides;\n      return list.map((s) => s.offsetLeft).sort((a, b) => a - b);\n    }\n\n    _scrollToSettle(target) {\n      this._animateTo(target);\n    }\n\n    // Animate scrollLeft to a boundary over a fixed duration.\n    //\n    // Snap is held 'none' for the whole animation and restored only on landing \u2014\n    // with snap live the browser discards these writes (measured: the ease moved\n    // nothing and merely delayed the native snap). The CSS sets\n    // `scroll-behavior: auto` so each write lands immediately instead of being\n    // re-animated by the browser, which is what makes this controllable at all.\n    // ponytail: one duration constant + a cubic. Tune DUR; don't add a spring lib.\n    _animateTo(target) {\n      this._settling = true;\n      this._stopGlide();\n      this._stopSettle();\n      this.track.style.scrollSnapType = 'none';\n\n      const from = this.track.scrollLeft;\n      const dist = target - from;\n      if (Math.abs(dist) < 1 || this.reduceMotion.matches) {\n        this.track.scrollLeft = target;\n        return this._endSettle();\n      }\n\n      const DUR = 260; // ms \u2014 long enough to read as a slide, short enough to feel snappy\n      const t0 = performance.now();\n      const step = (now) => {\n        const k = Math.min(1, (now - t0) / DUR);\n        this.track.scrollLeft = from + dist * (1 - Math.pow(1 - k, 3)); // ease-out cubic\n        if (k < 1 && this.isConnected) {\n          this._settleRaf = requestAnimationFrame(step);\n          return;\n        }\n        this.track.scrollLeft = target;\n        this._settleRaf = 0;\n        this._endSettle();\n      };\n      this._settleRaf = requestAnimationFrame(step);\n    }\n    _endSettle() {\n      this._settling = false;\n      this.track.style.scrollSnapType = '';\n      requestAnimationFrame(() => {\n        this._dragging = false; // re-arm wrap-on-settle\n        this._updateActiveFromScroll();\n      });\n    }\n    // Nearest slide boundary to the current scroll position, clones included (so a\n    // drag that ends on a clone settles there and wraps invisibly afterwards).\n    _nearestSlideOffset() {\n      const candidates = this.infinite\n        ? [this._cloneLead, ...this.slides, this._cloneTail]\n        : this.slides;\n      let best = null;\n      let bestDist = Infinity;\n      const sl = this.track.scrollLeft;\n      candidates.forEach((slide) => {\n        const dist = Math.abs(slide.offsetLeft - sl);\n        if (dist < bestDist) { bestDist = dist; best = slide.offsetLeft; }\n      });\n      return best;\n    }\n    _stopGlide() {\n      if (this._glideRaf) { cancelAnimationFrame(this._glideRaf); this._glideRaf = 0; }\n    }\n    // Grabbing the track mid-settle must kill the settle animation, else it keeps\n    // yanking scrollLeft while the finger is dragging.\n    _stopSettle() {\n      if (this._settleRaf) { cancelAnimationFrame(this._settleRaf); this._settleRaf = 0; }\n      this._settling = false;\n    }\n\n    _reflectToggle() {\n      if (!this.toggleBtn) return;\n      const playing = this._isPlaying();\n      this.toggleBtn.classList.toggle('is-paused', !playing);\n      this.toggleBtn.setAttribute('aria-pressed', playing ? 'false' : 'true');\n    }\n  }\n\n  customElements.define('ndi-slider', NdiSlider);\n}\n"],
  "mappings": "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",
  "names": []
}
