{"version":3,"file":"header-section-xxxxxxxxxxxxxxxxxxxx.min.js","mappings":"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","sources":["webpack://lange/./scripts/sections/header/sticky-header.ts","webpack://lange/webpack/bootstrap","webpack://lange/webpack/runtime/define property getters","webpack://lange/webpack/runtime/ensure chunk","webpack://lange/webpack/runtime/get javascript chunk filename","webpack://lange/webpack/runtime/get mini-css chunk filename","webpack://lange/webpack/runtime/hasOwnProperty shorthand","webpack://lange/webpack/runtime/load script","webpack://lange/webpack/runtime/publicPath","webpack://lange/webpack/runtime/jsonp chunk loading","webpack://lange/./scripts/sections/header/search-panel-manager/index.ts","webpack://lange/./scripts/lib/debounce.ts","webpack://lange/./scripts/sections/header/search-input/index.ts","webpack://lange/./scripts/sections/header/search-panel/index.ts","webpack://lange/./scripts/sections/header/search-panel/get-search-results.ts","webpack://lange/./scripts/sections/header/main-menu-manager/index.ts","webpack://lange/./scripts/lib/splide-slidebar-extension.ts","webpack://lange/./scripts/lib/webpack-path.ts","webpack://lange/./scripts/sections/header/mobile-menu-manager/index.ts","webpack://lange/./scripts/sections/header/top-banner-carousel.ts","webpack://lange/./scripts/sections/header/countdown-timer.ts","webpack://lange/./scripts/sections/header/top-banner/index.ts"],"sourcesContent":["let header: HTMLElement;\nlet mainMenu: HTMLElement;\nlet container: HTMLElement;\n\nfunction onDOMContentLoaded() {\n  header = document.querySelector<HTMLElement>('#shopify-section-header');\n  mainMenu = document.querySelector<HTMLElement>('#main-menu');\n  container = document.querySelector<HTMLElement>('#shopify-section-header .header-container');\n  if (!header || !mainMenu || !container) {\n    console.warn('sticky header: header, main menu or container not found');\n    return;\n  }\n\n  // intersection observer is used to detect when the header becomes sticky or unstuck, it's\n  // necessary to apply different styles in each state on desktop.\n  const intersectionObserver = new IntersectionObserver((entries) => {\n    for (const entry of entries) {\n      if (entry.intersectionRatio < 1) {\n        header.classList.remove('unstuck');\n        header.classList.add('stuck');\n      } else {\n        if (header.classList.contains('stuck')) {\n          header.classList.remove('stuck');\n          header.classList.add('unstuck');\n        }\n      }\n    }\n  }, {\n    rootMargin: '-1px 0px 0px 0px', // Trigger when header moves up by 1px\n    threshold: 1 // Trigger when less than 100% visible\n  });\n\n  // Resize observer is used to update the top offset CSS variable when the header size changes\n  const resizeObserver = new ResizeObserver((_entries) => {\n    const newOffsetTop = calculateTopOffset();\n    header.style.setProperty('--sticky-offset-top', `${newOffsetTop}px`);\n\n    // on mobile, the main menu is hidden, so we don't need to observe it\n    if (mainMenu.offsetParent === null) {\n      intersectionObserver.disconnect();\n      mainMenu.classList.remove('stuck');\n      mainMenu.classList.remove('unstuck');\n    } else {\n      intersectionObserver.observe(mainMenu);\n    }\n  });\n  resizeObserver.observe(header);\n}\n\n/**\n * Calculates the top offset for the sticky header.\n */\nfunction calculateTopOffset() {\n  if (mainMenu.offsetParent === null) {\n    // the main menu is hidden on mobile, so we use the container height instead\n    return container.offsetHeight - header.offsetHeight + 1;\n  }\n\n  // The offset is the distance from the top of the page to the top of the main menu\n  return mainMenu.offsetHeight - header.offsetHeight + 1;\n}\n\ndocument.addEventListener('DOMContentLoaded', onDOMContentLoaded);\n","// The module cache\nlet __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tlet cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tlet module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","// define getter/value functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tif(Array.isArray(definition)) {\n\t\tvar i = 0;\n\t\twhile(i < definition.length) {\n\t\t\tvar key = definition[i++];\n\t\t\tvar binding = definition[i++];\n\t\t\tif(!__webpack_require__.o(exports, key)) {\n\t\t\t\tif(binding === 0) {\n\t\t\t\t\tObject.defineProperty(exports, key, { enumerable: true, value: definition[i++] });\n\t\t\t\t} else {\n\t\t\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: binding });\n\t\t\t\t}\n\t\t\t} else if(binding === 0) { i++; }\n\t\t}\n\t} else {\n\t\tfor(var key in definition) {\n\t\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t\t}\n\t\t}\n\t}\n};","__webpack_require__.f = {};\n// This file contains only the entry chunk.\n// The chunk loading function for additional chunks\n__webpack_require__.e = function(chunkId) {\n\treturn Promise.all(Object.keys(__webpack_require__.f).reduce(function(promises, key) {\n\t\t__webpack_require__.f[key](chunkId, promises);\n\t\treturn promises;\n\t}, []));\n};","// This function allow to reference async chunks\n__webpack_require__.u = function(chunkId) {\n\t// return url for filenames based on template\n\treturn \"\" + chunkId + \"-\" + \"2d5466ec02b4471f0a5d\" + \".min.js\";\n};","// This function allow to reference async chunks\n__webpack_require__.miniCssF = function(chunkId) {\n\t// return url for filenames based on template\n\treturn undefined;\n};","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","let inProgress = {};\nlet dataWebpackPrefix = \"lange:\";\n// loadScript function to load a script via script tag\n__webpack_require__.l = function(url, done, key, chunkId) {\n\tif(inProgress[url]) { inProgress[url].push(done); return; }\n\tlet script, needAttach;\n\tif(key !== undefined) {\n\t\tlet scripts = document.getElementsByTagName(\"script\");\n\t\tfor(var i = 0; i < scripts.length; i++) {\n\t\t\tlet s = scripts[i];\n\t\t\tif(s.getAttribute(\"src\") == url || s.getAttribute(\"data-webpack\") == dataWebpackPrefix + key) { script = s; break; }\n\t\t}\n\t}\n\tif(!script) {\n\t\tneedAttach = true;\n\t\tscript = document.createElement('script');\n\n\t\tscript.charset = 'utf-8';\n\t\tif (__webpack_require__.nc) {\n\t\t\tscript.setAttribute(\"nonce\", __webpack_require__.nc);\n\t\t}\n\t\tscript.setAttribute(\"data-webpack\", dataWebpackPrefix + key);\n\n\t\tscript.src = url;\n\t}\n\tinProgress[url] = [done];\n\tlet onScriptComplete = function(prev, event) {\n\t\t// avoid mem leaks in IE.\n\t\tscript.onerror = script.onload = null;\n\t\tclearTimeout(timeout);\n\t\tlet doneFns = inProgress[url];\n\t\tdelete inProgress[url];\n\t\tscript.parentNode && script.parentNode.removeChild(script);\n\t\tdoneFns && doneFns.forEach(function(fn) { return fn(event); });\n\t\tif(prev) return prev(event);\n\t}\n\tlet timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000);\n\tscript.onerror = onScriptComplete.bind(null, script.onerror);\n\tscript.onload = onScriptComplete.bind(null, script.onload);\n\tneedAttach && document.head.appendChild(script);\n};","__webpack_require__.p = \"\";","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nlet installedChunks = {\n\t\"header-section\": 0\n};\n\n__webpack_require__.f.j = function(chunkId, promises) {\n\t\t// JSONP chunk loading for javascript\n\t\tlet installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;\n\t\tif(installedChunkData !== 0) { // 0 means \"already installed\".\n\n\t\t\t// a Promise means \"currently loading\".\n\t\t\tif(installedChunkData) {\n\t\t\t\tpromises.push(installedChunkData[2]);\n\t\t\t} else {\n\t\t\t\tif(true) { // all chunks have JS\n\t\t\t\t\t// setup Promise in chunk cache\n\t\t\t\t\tlet promise = new Promise(function(resolve, reject) { installedChunkData = installedChunks[chunkId] = [resolve, reject]; });\n\t\t\t\t\tpromises.push(installedChunkData[2] = promise);\n\n\t\t\t\t\t// start chunk loading\n\t\t\t\t\tlet url = __webpack_require__.p + __webpack_require__.u(chunkId);\n\t\t\t\t\t// create error before stack unwound to get useful stacktrace later\n\t\t\t\t\tlet error = new Error();\n\t\t\t\t\tlet loadingEnded = function(event) {\n\t\t\t\t\t\tif(__webpack_require__.o(installedChunks, chunkId)) {\n\t\t\t\t\t\t\tinstalledChunkData = installedChunks[chunkId];\n\t\t\t\t\t\t\tif(installedChunkData !== 0) installedChunks[chunkId] = undefined;\n\t\t\t\t\t\t\tif(installedChunkData) {\n\t\t\t\t\t\t\t\tlet errorType = event && (event.type === 'load' ? 'missing' : event.type);\n\t\t\t\t\t\t\t\tlet realSrc = event && event.target && event.target.src;\n\t\t\t\t\t\t\t\terror.message = 'Loading chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realSrc + ')';\n\t\t\t\t\t\t\t\terror.name = 'ChunkLoadError';\n\t\t\t\t\t\t\t\terror.type = errorType;\n\t\t\t\t\t\t\t\terror.request = realSrc;\n\t\t\t\t\t\t\t\tinstalledChunkData[1](error);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\t__webpack_require__.l(url, loadingEnded, \"chunk-\" + chunkId, chunkId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n};\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n// no on chunks loaded\n\n// install a JSONP callback for chunk loading\nlet webpackJsonpCallback = function(parentChunkLoadingFunction, data) {\n\tlet chunkIds = data[0];\n\tlet moreModules = data[1];\n\tlet runtime = data[2];\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some(function(id) { return installedChunks[id] !== 0; })) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\n}\n\nlet chunkLoadingGlobal = self[\"webpackChunklange\"] = self[\"webpackChunklange\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","import { CustomElement } from '@integrabeauty/custom-elements';\n\n/**\n * Manages the search panel behavior. Listens for show and close requests and handles the panel\n * visibility and positioning. Also interacts with a modal system to display the panel as a modal.\n */\nclass SearchPanelManager extends HTMLElement implements CustomElement {\n  /**\n   * Stores the element to return focus to when the search panel is closed.\n   */\n  private returnFocusTo: HTMLElement;\n\n  private onSearchPanelShowRequestedBound = this.onSearchPanelShowRequested.bind(this);\n  private onSearchPanelCloseRequestedBound = this.onSearchPanelCloseRequested.bind(this);\n  private onShroudClickedBound = this.onShroudClicked.bind(this);\n  private onAddToCardBound = this.onAddToCard.bind(this);\n\n  public connectedCallback() {\n    addEventListener('search-panel-show-requested', this.onSearchPanelShowRequestedBound);\n    addEventListener('search-panel-close-requested', this.onSearchPanelCloseRequestedBound);\n    addEventListener('shroud-clicked', this.onShroudClickedBound);\n    addEventListener('ofir-add-to-cart', this.onAddToCardBound);\n  }\n\n  public disconnectedCallback() {\n    removeEventListener('search-panel-show-requested', this.onSearchPanelShowRequestedBound);\n    removeEventListener('search-panel-close-requested', this.onSearchPanelCloseRequestedBound);\n    removeEventListener('shroud-clicked', this.onShroudClickedBound);\n    removeEventListener('ofir-add-to-cart', this.onAddToCardBound);\n  }\n\n  private onSearchPanelShowRequested(event: WindowEventMap['search-panel-show-requested']) {\n    if (event.detail.returnFocusTo) {\n      this.returnFocusTo = event.detail.returnFocusTo;\n    }\n\n    this.showPanel();\n  }\n\n  private onSearchPanelCloseRequested(_event: WindowEventMap['search-panel-close-requested']) {\n    this.closePanel();\n  }\n\n  private onShroudClicked(event: WindowEventMap['shroud-clicked']) {\n    const searchPanel = this.querySelector('search-panel');\n    if (event.detail.element === searchPanel) {\n      this.closePanel();\n    }\n  }\n\n  /**\n   * Handles the event when an item is added to the cart. If a user adds an item to the cart while\n   * the search panel is active, the panel should be closed so the search panel does not obstruct\n   * the view of the cart modal.\n   */\n  private onAddToCard(_event: Event) {\n    const searchPanel = this.querySelector<HTMLElement>('search-panel');\n    const isActive = searchPanel.dataset.active === 'true';\n    if (isActive) {\n      this.closePanel();\n    }\n  }\n\n  private showPanel() {\n    type Element = HTMLElementTagNameMap['search-panel'];\n    const searchPanel = this.querySelector<Element>('search-panel');\n    searchPanel.dataset.active = 'true';\n\n    const headerOffsetBottom = getHeaderOffsetBottom();\n    searchPanel.style.top = `${headerOffsetBottom}px`;\n    searchPanel.focus();\n\n    type Detail = WindowEventMap['modal-show-requested']['detail'];\n    const modalShowEvent = new CustomEvent<Detail>('modal-show-requested', {\n      detail: { element: searchPanel }\n    });\n    dispatchEvent(modalShowEvent);\n  }\n\n  private closePanel() {\n    type Element = HTMLElementTagNameMap['search-panel'];\n    const searchPanel = this.querySelector<Element>('search-panel');\n    searchPanel.dataset.active = 'false';\n\n    if (this.returnFocusTo) {\n      // return focus to the element that requested the panel. Delay to ensure inert attributes are\n      // removed. The inert attribute are controlled by the modal manager, this functionality should\n      // be moved to the modal manager in the future.\n      setTimeout(() => {\n        this.returnFocusTo.focus();\n        this.returnFocusTo = null;\n      }, 100);\n    }\n\n    type Detail = WindowEventMap['modal-close-requested']['detail'];\n    const modalCloseEvent = new CustomEvent<Detail>('modal-close-requested', {\n      detail: { element: searchPanel }\n    });\n    dispatchEvent(modalCloseEvent);\n  }\n}\n\nfunction getHeaderOffsetBottom() {\n  const header = document.querySelector<HTMLElement>('#shopify-section-header');\n  const headerRect = header.getBoundingClientRect();\n  return headerRect.height + headerRect.top;\n}\n\n// TODO move return focus functionality to the modal-manager like on Lange to be default behavior\n// for all modals\ntype SearchPanelShowRequestedEvent = CustomEvent<{\n  returnFocusTo?: HTMLElement;\n}>;\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'search-panel-manager': SearchPanelManager;\n  }\n\n  interface WindowEventMap {\n    'search-panel-close-requested': CustomEvent;\n    'search-panel-show-requested': SearchPanelShowRequestedEvent;\n  }\n}\n\nif (!customElements.get('search-panel-manager')) {\n  customElements.define('search-panel-manager', SearchPanelManager);\n}\n","export default function debounce<F extends (...params: any[]) => unknown>(func: F, timeout = 300) {\n  let timer: ReturnType<typeof setTimeout> = null;\n  return (...args: unknown[]) => {\n    clearTimeout(timer);\n    timer = setTimeout(() => func(...args), timeout);\n  };\n}\n","import type { CustomElement } from '@integrabeauty/custom-elements';\nimport debounce from '../../../lib/debounce.js';\nimport html from './index.html';\nimport styles from './index.scss';\n\n/**\n * Search input component with an input field, a submit button, and a clear button. Dispatches\n * 'search-input-changed' events when the input value changes so the parent component can handle the\n * search logic.\n */\nclass SearchInput extends HTMLElement implements CustomElement {\n  private onInputBound = this.onInput.bind(this);\n  private onSubmitBound = this.onSubmit.bind(this);\n  private onResetBound = this.onReset.bind(this);\n  private onCloseClickedBound = this.onCloseClicked.bind(this);\n  private onShroudClickedBound = this.onShroudClicked.bind(this);\n  private sendSearchInputChangedEventBound = this.sendSearchInputChangedEvent.bind(this);\n  private sendSearchInputChangedEventDebounced =\n    debounce(this.sendSearchInputChangedEventBound, 250);\n\n  public connectedCallback() {\n    this.initializeShadowRoot();\n    this.render();\n  }\n\n  public disconnectedCallback() {\n    const input = this.shadowRoot.querySelector('input');\n    input.removeEventListener('input', this.onInputBound);\n\n    const form = this.shadowRoot.querySelector('form');\n    form.removeEventListener('submit', this.onSubmitBound);\n    form.removeEventListener('reset', this.onResetBound);\n\n    const closeButton = this.shadowRoot.querySelector<HTMLElement>('.close');\n    closeButton.removeEventListener('click', this.onCloseClickedBound);\n\n    removeEventListener('shroud-clicked', this.onShroudClickedBound);\n  }\n\n  private initializeShadowRoot() {\n    if (!this.shadowRoot) {\n      // delegatesFocus allows the shadow DOM to forward focus to the input element when the search\n      // modal is opened.\n      this.attachShadow({ mode: 'open', delegatesFocus: true });\n      this.shadowRoot.innerHTML = `<style>${styles}</style>${html}`;\n    }\n  }\n\n  private render() {\n    const input = this.shadowRoot.querySelector('input');\n    input.addEventListener('input', this.onInputBound);\n\n    const form = this.shadowRoot.querySelector('form');\n    form.addEventListener('submit', this.onSubmitBound);\n    form.addEventListener('reset', this.onResetBound);\n\n    const closeButton = this.shadowRoot.querySelector<HTMLElement>('.close');\n    closeButton.addEventListener('click', this.onCloseClickedBound);\n\n    addEventListener('shroud-clicked', this.onShroudClickedBound);\n  }\n\n  /**\n   * Handles the search input field input event.\n   */\n  private onInput(event: Event) {\n    const input = <HTMLInputElement>event.target;\n    const clearButton = this.shadowRoot.querySelector<HTMLButtonElement>('button[type=\"reset\"]');\n    const query = input.value.trim();\n    clearButton.disabled = query === '';\n    this.sendSearchInputChangedEventDebounced(query);\n  }\n\n  /**\n   * Handles the form submit event.\n   */\n  private onSubmit(event: Event) {\n    event.preventDefault();\n    const input = this.shadowRoot.querySelector<HTMLInputElement>('input');\n    const query = input.value.trim();\n    if (query === '') {\n      return;\n    }\n\n    this.sendSearchInputChangedEvent(query);\n  }\n\n  /**\n   * Handles the form reset event.\n   */\n  private onReset(_event: Event) {\n    // disable the clear button. oninput listener controls its state based on input value but input\n    // event is not called on reset as well as change event.\n    const clearButton = this.shadowRoot.querySelector<HTMLButtonElement>('button[type=\"reset\"]');\n    clearButton.disabled = true;\n\n    // Reset focus on the input field. Because of delegatesFocus, focusing the root will focus the\n    // input.\n    this.focus();\n\n    this.sendSearchInputChangedEvent('');\n  }\n\n  /**\n   * Handles the close button click event. Resets the form, disables the clear button, and\n   * dispatches a 'search-panel-close-requested' event.\n   */\n  private onCloseClicked(_event: Event) {\n    const form = this.shadowRoot.querySelector('form');\n    form.reset();\n\n    const clearButton = this.shadowRoot.querySelector<HTMLButtonElement>('button[type=\"reset\"]');\n    clearButton.disabled = true;\n\n    const event = new Event('search-panel-close-requested');\n    dispatchEvent(event);\n  }\n\n  /**\n   * Handles the shroud clicked event. Resets the form and disables the clear button. We don't need\n   * to dispatch any event here because the parent component is already listening to the 'shroud-\n   * clicked' event.\n   */\n  private onShroudClicked(event: WindowEventMap['shroud-clicked']) {\n    if (!event.detail || !event.detail.element) {\n      return;\n    }\n\n    // Only reset the form if the search panel shroud was clicked, not any other shroud (e.g. cart\n    // drawer shroud).\n    if (event.detail.element.tagName !== 'SEARCH-PANEL') {\n      return;\n    }\n\n    const form = this.shadowRoot.querySelector('form');\n    form.reset();\n\n    const clearButton = this.shadowRoot.querySelector<HTMLButtonElement>('button[type=\"reset\"]');\n    clearButton.disabled = true;\n  }\n\n  /**\n   * Dispatches a 'search-input-changed' event with the given query. It should be debounced because\n   * it's called on every input event.\n   */\n  private sendSearchInputChangedEvent(query: string) {\n    type Detail = HTMLElementEventMap['search-input-changed']['detail'];\n    const customEvent = new CustomEvent<Detail>('search-input-changed', {\n      detail: {\n        query\n      }\n    });\n    this.dispatchEvent(customEvent);\n  }\n}\n\ntype SearchInputChangedEvent = CustomEvent<{\n  query: string;\n}>;\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'search-input': SearchInput;\n  }\n\n  interface HTMLElementEventMap {\n    'search-input-changed': SearchInputChangedEvent;\n  }\n}\n\nif (!customElements.get('search-input')) {\n  customElements.define('search-input', SearchInput);\n}\n","import { CustomElement } from '@integrabeauty/custom-elements';\nimport getSearchResults from './get-search-results.js';\nimport html from './index.html';\nimport styles from './index.scss';\n\n/**\n * Search panel with an input and search results triggered by the search button in the header\n */\nclass SearchPanel extends HTMLElement implements CustomElement {\n  declare readonly dataset: {\n    /**\n     * Indicates whether the search panel is active (open) or not.\n     */\n    active: 'false' | 'true';\n  };\n\n  private onSearchInputChangedBound = this.onSearchInputChanged.bind(this);\n  private onSearchPanelCloseRequestedBound = this.onSearchPanelCloseRequested.bind(this);\n\n  public connectedCallback() {\n    this.initializeShadowRoot();\n    this.render();\n  }\n\n  public disconnectedCallback() {\n    type SearchInput = HTMLElementTagNameMap['search-input'];\n    const searchInput = this.shadowRoot.querySelector<SearchInput>('search-input');\n    searchInput.removeEventListener('search-input-changed', this.onSearchInputChangedBound);\n\n    removeEventListener('search-panel-close-requested', this.onSearchPanelCloseRequestedBound);\n  }\n\n  private initializeShadowRoot() {\n    if (!this.shadowRoot) {\n      this.attachShadow({ mode: 'open', delegatesFocus: true });\n      this.shadowRoot.innerHTML = `<style>${styles}</style>${html}`;\n    }\n  }\n\n  private render() {\n    type SearchInput = HTMLElementTagNameMap['search-input'];\n    const searchInput = this.shadowRoot.querySelector<SearchInput>('search-input');\n    searchInput.addEventListener('search-input-changed', this.onSearchInputChangedBound);\n\n    addEventListener('search-panel-close-requested', this.onSearchPanelCloseRequestedBound);\n  }\n\n  private async onSearchInputChanged(event: HTMLElementEventMap['search-input-changed']) {\n    this.renderSearchResults('');\n\n    if (!event.detail.query) {\n      return;\n    }\n\n    this.showLoader();\n\n    try {\n      const response = await getSearchResults(event.detail.query);\n\n      if (!response.ok) {\n        const error = new Error(response.statusText);\n        console.error(error);\n        // this.hideDropdown();\n        throw error;\n      }\n\n      const html = await response.text();\n      this.renderSearchResults(html);\n    } catch (e) {\n      console.log(e);\n      this.renderSearchResults('');\n    }\n  }\n\n  private onSearchPanelCloseRequested(_event: WindowEventMap['search-panel-close-requested']) {\n    this.renderSearchResults('');\n  }\n\n  private showLoader() {\n    const loader = this.shadowRoot.querySelector<HTMLElement>('.loader');\n    loader.classList.remove('hidden');\n  }\n\n  private hideLoader() {\n    const loader = this.shadowRoot.querySelector<HTMLElement>('.loader');\n    loader.classList.add('hidden');\n  }\n\n  private renderSearchResults(html: string) {\n    this.innerHTML = html;\n    this.hideLoader();\n  }\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'search-panel': SearchPanel;\n  }\n}\n\nfunction onDOMContentLoaded(_event?: Event) {\n  if (!customElements.get('search-panel')) {\n    customElements.define('search-panel', SearchPanel);\n  }\n}\n\n// This is loaded via a script tag with the async script attribute. Wait for the DOM to be loaded\n// before defining the custom element.\n\nif (document.readyState === 'complete' || document.readyState === 'interactive') {\n  onDOMContentLoaded(null);\n} else {\n  addEventListener('DOMContentLoaded', onDOMContentLoaded);\n}\n","/**\n * Fetch search results for the given query.\n *\n * This is a request to the search suggestions endpoint with the additional section_id parameter. It\n * says to Shopify that we want the rendered search-results.liquid section HTML to be returned in\n * the response.\n *\n * @see https://shopify.dev/docs/api/ajax/reference/predictive-search#get--locale-search-suggest\n */\nexport default function getSearchResults(query: string) {\n  const params = new URLSearchParams();\n\n  // The search query.\n  params.set('q', query);\n\n  // Searching only for products.\n  params.set('resources[type]', 'product');\n\n  // Section name. Shopify will render `search-results.liquid` and return its HTML.\n  params.set('section_id', 'search-results');\n\n  const url = `/search/suggest?${params}`;\n  return fetch(url);\n}\n","import { CustomElement } from '@integrabeauty/custom-elements';\n\n/**\n * Manages the main menu panels behavior.\n */\nclass MainMenuManager extends HTMLElement implements CustomElement {\n  private activePanel: string;\n\n  private onDOMContentLoadedBound = this.onDOMContentLoaded.bind(this);\n  private onButtonClickedBound = this.onButtonClicked.bind(this);\n  private onHamburgerButtonClickedBound = this.onHamburgerButtonClicked.bind(this);\n  private onPointerEnterBound = this.onPointerEnter.bind(this);\n  private onMainMenuMouseLeaveBound = this.onMainMenuMouseLeave.bind(this);\n  private onPanelMouseLeaveBound = this.onPanelMouseLeave.bind(this);\n\n  public connectedCallback() {\n    addEventListener('DOMContentLoaded', this.onDOMContentLoadedBound);\n  }\n\n  public disconnectedCallback() {\n    removeEventListener('DOMContentLoaded', this.onDOMContentLoadedBound);\n\n    const panelButtons = this.querySelectorAll<HTMLButtonElement>('.menu-panel-button');\n    for (const button of panelButtons) {\n      button.removeEventListener('click', this.onButtonClickedBound);\n      button.removeEventListener('pointerdown', onPointerDown);\n      button.removeEventListener('pointerenter', this.onPointerEnterBound);\n    }\n\n    const hamburgerButton = this.querySelector('#main-menu-hamburger');\n    if (hamburgerButton) {\n      hamburgerButton.removeEventListener('click', this.onHamburgerButtonClickedBound);\n    }\n\n    const panels = this.querySelectorAll<HTMLElement>('.menu-panel:not(#menu-panel-main-mobile)');\n    for (const panel of panels) {\n      panel.removeEventListener('mouseleave', this.onPanelMouseLeaveBound);\n    }\n\n    const searchButton = this.querySelector('.search-button');\n    if (searchButton) {\n      searchButton.removeEventListener('click', onSearchClicked);\n    }\n\n    const cartButton = this.querySelector('#cart-link');\n    if (cartButton) {\n      searchButton.removeEventListener('click', onCartClicked);\n    }\n\n    const mainMenu = this.querySelector<HTMLElement>('#main-menu');\n    mainMenu.removeEventListener('mouseleave', this.onMainMenuMouseLeaveBound);\n  }\n\n  private onDOMContentLoaded() {\n    const panelButtons = this.querySelectorAll<HTMLElement>('.menu-panel-button');\n    for (const button of panelButtons) {\n      button.addEventListener('click', this.onButtonClickedBound);\n      button.addEventListener('pointerdown', onPointerDown);\n      button.addEventListener('pointerenter', this.onPointerEnterBound);\n    }\n\n    const hamburgerButton = this.querySelector('#main-menu-hamburger');\n    if (hamburgerButton) {\n      hamburgerButton.addEventListener('click', this.onHamburgerButtonClickedBound);\n    }\n\n    const panels = this.querySelectorAll<HTMLElement>('.menu-panel:not(#menu-panel-main-mobile)');\n    for (const panel of panels) {\n      panel.addEventListener('mouseleave', this.onPanelMouseLeaveBound);\n    }\n\n    const searchButton = this.querySelector('.search-button');\n    if (searchButton) {\n      searchButton.addEventListener('click', onSearchClicked);\n    }\n\n    const cartButton = this.querySelector('#cart-link');\n    if (cartButton) {\n      cartButton.addEventListener('click', onCartClicked);\n    }\n\n    const mainMenu = this.querySelector<HTMLElement>('#main-menu');\n    mainMenu.addEventListener('mouseleave', this.onMainMenuMouseLeaveBound);\n  }\n\n  /**\n   * Handles click events on menu panel buttons to open or close panels.\n   */\n  private onButtonClicked(event: Event) {\n    const button = <HTMLButtonElement>event.currentTarget;\n    if (button.classList.contains('active')) {\n      this.clearActiveState();\n      return;\n    }\n\n    this.clearActiveState();\n    this.setActiveState(button);\n  }\n\n  private onHamburgerButtonClicked(event: Event) {\n    const button = <HTMLButtonElement>event.currentTarget;\n    if (button.classList.contains('active')) {\n      button.classList.remove('active');\n      button.setAttribute('aria-expanded', 'false');\n\n      this.clearActiveState();\n      type MainMenuHamburgerClickedEventDetail =\n        WindowEventMap['main-menu-hamburger-clicked']['detail'];\n      const hamburgerClickedEvent =\n        new CustomEvent<MainMenuHamburgerClickedEventDetail>('main-menu-hamburger-clicked', {\n          detail: { isActive: false }\n        });\n      dispatchEvent(hamburgerClickedEvent);\n      return;\n    }\n\n    this.clearActiveState();\n    this.setActiveState(button);\n\n    type MainMenuHamburgerClickedEventDetail =\n      WindowEventMap['main-menu-hamburger-clicked']['detail'];\n    const hamburgerClickedEvent =\n      new CustomEvent<MainMenuHamburgerClickedEventDetail>('main-menu-hamburger-clicked', {\n        detail: { isActive: true }\n      });\n    dispatchEvent(hamburgerClickedEvent);\n  }\n\n  private setActiveState(button: HTMLElement) {\n    const panelId = button.getAttribute('aria-controls');\n    const panel = this.querySelector(`#${panelId}`);\n    if (!panel) {\n      console.warn(`Main menu: panel with ID ${panelId} not found`);\n      return;\n    }\n\n    const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;\n    if (Number.isInteger(scrollbarWidth)) {\n      document.documentElement.style.setProperty('--scrollbar-width', scrollbarWidth + 'px');\n    }\n\n    document.documentElement.classList.add('js-no-scroll');\n\n    this.activePanel = panelId;\n\n    panel.removeAttribute('inert');\n    panel.classList.remove('hidden');\n    button.classList.add('active');\n    button.setAttribute('aria-expanded', 'true');\n  }\n\n  private clearActiveState() {\n    document.documentElement.classList.remove('js-no-scroll');\n\n    // check all active buttons for safety, in fact there should be only one\n    const activeButtons = this.querySelectorAll('.menu-panel-button.active');\n    for (const button of activeButtons) {\n      button.classList.remove('active');\n      button.setAttribute('aria-expanded', 'false');\n    }\n\n    if (this.activePanel) {\n      const panel = this.querySelector<HTMLElement>(`#${this.activePanel}`);\n      if (panel) {\n        panel.setAttribute('inert', '');\n        panel.classList.add('hidden');\n      }\n\n      this.activePanel = '';\n    }\n  }\n\n  /**\n   * Handles pointer enter events on menu panel buttons to open panels on mouse hover.\n   */\n  private onPointerEnter(event: PointerEvent) {\n    if (event.pointerType !== 'mouse') {\n      return;\n    }\n\n    const button = <HTMLElement>event.currentTarget;\n    this.clearActiveState();\n    this.setActiveState(button);\n  }\n\n  /**\n   * Closes the active panel when the mouse leaves the main menu area, unless the mouse is moving\n   * into the active panel itself.\n   */\n  private onMainMenuMouseLeave(event: MouseEvent) {\n    const relatedTarget = <HTMLElement>event.relatedTarget;\n\n    // If there's no related target, it means the mouse left the window, so we should close the\n    // active panel.\n    if (!relatedTarget) {\n      this.clearActiveState();\n      return false;\n    }\n\n    const closestPanel = relatedTarget.closest('.menu-panel');\n    if (closestPanel && closestPanel.id === this.activePanel) {\n      return false;\n    } else {\n      this.clearActiveState();\n    }\n  }\n\n  /**\n   * Closes the active panel when the mouse leaves the panel area, unless the mouse is moving back\n   * to the main menu area.\n   */\n  private onPanelMouseLeave(event: MouseEvent) {\n    const relatedTarget = <HTMLElement>event.relatedTarget;\n\n    // If there's no related target, it means the mouse left the window, so we should close the\n    // active panel.\n    if (!relatedTarget) {\n      this.clearActiveState();\n      return false;\n    }\n\n    const closestPanel = relatedTarget.closest('#main-menu');\n    if (closestPanel) {\n      return false;\n    } else {\n      this.clearActiveState();\n    }\n  }\n}\n\n/**\n * Go to provided URL if it's a mouse click.\n *\n * This is our businness requirement to navigate on mouse clicks. For accessibility reasons, we need\n * to keep the menu button element as a button, so we handle navigation manually here.\n */\nfunction onPointerDown(event: PointerEvent) {\n  if (event.pointerType !== 'mouse') {\n    return;\n  }\n\n  const button = <HTMLElement>event.currentTarget;\n  const url = button.dataset.href;\n  if (url) {\n    window.location.href = url;\n  }\n}\n\nfunction onSearchClicked(event: Event) {\n  const searchPanelShowRequstedEvent = new CustomEvent('search-panel-show-requested', {\n    detail: {\n      returnFocusTo: <HTMLElement>event.currentTarget\n    }\n  });\n  dispatchEvent(searchPanelShowRequstedEvent);\n}\n\nfunction onCartClicked(_event: Event) {\n  const modalShowEvent = new Event('cart-modal-show-requested');\n  dispatchEvent(modalShowEvent);\n}\n\ntype MainMenuHamburgerClickedEvent = CustomEvent<{\n  isActive: boolean;\n}>;\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'main-menu-manager': MainMenuManager;\n  }\n\n  interface WindowEventMap {\n    'main-menu-hamburger-clicked': MainMenuHamburgerClickedEvent;\n  }\n}\n\nif (!customElements.get('main-menu-manager')) {\n  customElements.define('main-menu-manager', MainMenuManager);\n}\n","import type { Splide, Components, Options } from '@splidejs/splide';\n\n/**\n * Extension to add a custom slidebar to the Splide slider for visualizing and controlling the slide\n * position.\n *\n * If you want to render a sidebar in a specific place in the HTML, add the sidebar's markup\n * directly to your template. If no markup is provided, the sidebar will be automatically created\n * and inserted right before the closing tag of the Splide root element.\n *\n * This library was copy-paged from Lange.\n *\n * @param splide The main Splide instance\n * @param components Splide components\n * @param options Splide options object, containing customization options\n *\n * @see https://splidejs.com/components/\n * @see https://splidejs.com/guides/options/\n * @see https://splidejs.com/guides/extension/\n */\nexport function splideSlidebarExtension(splide: Splide, components: Components, options: Options) {\n  /**\n   * Root slidebar element\n   */\n  let slidebar: HTMLElement;\n\n  /**\n   * Indicates whether the sidebar markup is already present in the HTML or not.\n   */\n  let hasSlidebarMarkup = false;\n\n  /**\n   * Slide bar handle element\n   */\n  let handle: HTMLElement;\n\n  /**\n   * Slidebar current position\n   */\n  let position = 0;\n\n  /**\n   * Maximum allowable position value for the slidebar handle\n   */\n  let maxPosition: number;\n\n  /**\n   * Maximum allowable position value for the Splide's track. Store the value to not calculate all\n   * the time when the slider is dragged.\n   */\n  let maxTrackPosition: number;\n\n  /**\n   * Previous x-coordinate of the touch, needed to calculate the touch movement distance.\n   */\n  let previousTouchX = 0;\n\n  /**\n   * Mounts the extension, setting up the slidebar and initializing event listeners. Splide call\n   * this method automatically when the slider is ready.\n   *\n   * @see https://splidejs.com/guides/extension/\n   */\n  function mount() {\n    slidebar = components.Elements.root.querySelector('.splide__slider');\n    handle = components.Elements.root.querySelector('.splide__slider-handle');\n\n    if (slidebar && handle) {\n      hasSlidebarMarkup = true;\n    } else {\n      renderSlidebar();\n    }\n\n    slidebar.classList.add('hidden');\n\n    splide.on('ready', onSplideReady);\n    splide.on('updated', onSplideOptionsUpdated);\n    splide.on('overflow', onSplideOverflowed);\n  }\n\n  /**\n   * Enables the slidebar functionality, adding the necessary event listeners.\n   */\n  function enable() {\n    if (!hasSlidebarMarkup) {\n      components.Elements.root.appendChild(slidebar);\n    }\n\n    slidebar.classList.remove('hidden');\n\n    // Without this delay, the first page of the carousel is not clickable. There’s an issue with\n    // calling the components.Controller.go() method immediately when the extension is mounted.\n    setTimeout(onSplideResized);\n\n    if (!splide.is('fade')) {\n      splide.on('dragging.slidebar', onSplideDragging);\n    }\n\n    splide.on('move.slidebar', onSplideMoveStarted);\n    splide.on('resized.slidebar', onSplideResized);\n    handle.addEventListener('mousedown', onMousedown);\n    handle.addEventListener('touchstart', onTouchstart, { passive: true });\n    handle.addEventListener('transitionend', onTransitionend);\n    slidebar.addEventListener('click', onSlidebarClicked);\n  }\n\n  /**\n   * Disables the slidebar functionality, removing the event listeners and slidebar element.\n   */\n  function disable() {\n    slidebar.classList.add('hidden');\n\n    splide.off('move.slidebar');\n    splide.off('resized.slidebar');\n    splide.off('dragging.slidebar');\n    handle.removeEventListener('mousedown', onMousedown);\n    handle.removeEventListener('touchstart', onTouchstart);\n    handle.removeEventListener('transitionend', onTransitionend);\n    slidebar.removeEventListener('click', onSlidebarClicked);\n  }\n\n  /**\n   * Creates elements, calculates, and sets the handle width based on the number of slides, but does\n   * not append the element to the DOM.\n   */\n  function renderSlidebar() {\n    slidebar = document.createElement('div');\n    slidebar.classList.add('splide__slider');\n\n    handle = document.createElement('div');\n    handle.classList.add('splide__slider-handle');\n\n    handle.style.width = calculateHandleWidth();\n\n    slidebar.appendChild(handle);\n  }\n\n  /**\n   * Calculates the width of the handle.\n   *\n   * The function works depending upon the 'mode' the Splide is in. If it's in 'fade' mode, the\n   * width is calculated based on the proportion of 'perPage' option to the total number of slides,\n   * scaled to fit a percentage scale (0-100).\n   *\n   * For other modes, the handle width is determined by the ratio of list size to slider size, also\n   * expressed as a percentage.\n   *\n   * @returns The calculated width of the handle.\n   */\n  function calculateHandleWidth() {\n    let handleWidth;\n    if (splide.is('fade')) {\n      handleWidth = (options.perPage / components.Slides.getLength()) * 100;\n    } else {\n      handleWidth = (components.Layout.listSize() / components.Layout.sliderSize()) * 100;\n    }\n\n    return `${handleWidth}%`;\n  }\n\n  /**\n   * Calculates maximum values for the slidebar and track, ensuring they stay in sync.\n   */\n  function recalculateSlidebarAndTrackPosition() {\n    maxPosition = slidebar.offsetWidth - handle.offsetWidth;\n    maxTrackPosition = components.Layout.sliderSize() - components.Layout.listSize();\n\n    components.Controller.go(splide.index, true);\n  }\n\n  /**\n   * Processes and restricts handle movement within the slidebar bounds.\n   *\n   * @param toPosition Desired new position of the handle.\n   */\n  function processHandleMove(toPosition: number) {\n    const newPosition = getHandlePositionWithinBounds(toPosition);\n\n    // avoid position update if handle position hasn't changed.\n    if (position === newPosition) {\n      return;\n    }\n\n    position = getHandlePositionWithinBounds(toPosition);\n\n    if (!splide.is('fade')) {\n      const newSplidePosition = getCalculatedTrackPosition(position);\n      components.Move.translate(newSplidePosition);\n    }\n\n    // it ensures the DOM updates are synchronized with the browser's refresh rate, avoiding\n    // unnecessary reflows and keeping animations smooth\n    requestAnimationFrame(() => {\n      handle.style.transform = `translateX(${position}px)`;\n    });\n  }\n\n  /**\n   * Adjusts and returns the intended position of the handle within the boundaries of a slider.\n   * Checks whether the new position is within the range [0, maxPosition]. If the intended position\n   * is less than 0, it will be set to 0. If it's larger than maxPosition, it will be set to\n   * maxPosition. If it's the same as the current position, it will return this value without\n   * changes.\n   *\n   * @param toPosition - The intended new position.\n   * @returns newPosition - The adjusted position within the range [0, maxPosition].\n   */\n  function getHandlePositionWithinBounds(toPosition: number) {\n    let newPosition = toPosition;\n    if (newPosition <= 0) {\n      newPosition = 0;\n    } else if (newPosition >= maxPosition) {\n      newPosition = maxPosition;\n    }\n\n    return newPosition;\n  }\n\n  /**\n   * Aligns the track position based on the current position of the handle.\n   */\n  function alignTrackPosition() {\n    let index: number;\n\n    if (splide.is('fade')) {\n      index = Math.round(position / (maxPosition / components.Slides.getLength()));\n    } else {\n      const currentSplidePosition = components.Move.getPosition();\n      index = components.Move.toIndex(currentSplidePosition);\n    }\n\n    components.Controller.go(index, true);\n  }\n\n  function onSplideOptionsUpdated(_options: Options) {\n    toggleSlidebar();\n  }\n\n  function onSplideReady() {\n    toggleSlidebar();\n  }\n\n  function toggleSlidebar() {\n    // We need to both check isEnough() and isOverflow(). Depending on the Splide options or due to\n    // some Splide bugs, solely relying on one of these methods has led to issues.\n    if (options.slidebar && components.Slides.isEnough() && components.Layout.isOverflow()) {\n      enable();\n    } else {\n      disable();\n    }\n  }\n\n  function onMousedown() {\n    addEventListener('mousemove', onMousemove);\n    addEventListener('mouseup', onMouseup);\n  }\n\n  function onMouseup() {\n    // TODO: \"mouseup\" event is fired on touch devices right after \"touchend\". Need to investigate,\n    // if we can replace mouse and touch events with \"pointerdown\" and \"pointerup\" events.\n\n    alignTrackPosition();\n\n    removeEventListener('mousemove', onMousemove);\n    removeEventListener('mouseup', onMouseup);\n  }\n\n  function onMousemove(event: MouseEvent) {\n    const newPosition = position + event.movementX;\n    processHandleMove(newPosition);\n  }\n\n  function onTouchstart(event: TouchEvent) {\n    const touch = event.touches[0];\n    previousTouchX = touch.clientX;\n\n    addEventListener('touchmove', onTouchmove);\n    addEventListener('touchend', onTouchend);\n  }\n\n  function onTouchend(_event: TouchEvent) {\n    previousTouchX = 0;\n\n    alignTrackPosition();\n\n    removeEventListener('touchmove', onTouchmove);\n    removeEventListener('touchend', onTouchend);\n  }\n\n  function onTouchmove(event: TouchEvent) {\n    const touch = event.touches[0];\n    const movementX = touch.clientX - previousTouchX;\n    const newPosition = position + movementX;\n    previousTouchX = touch.clientX;\n\n    processHandleMove(newPosition);\n  }\n\n  /**\n   * Resets handle transition style once transition ends\n   */\n  function onTransitionend() {\n    handle.style.transition = '';\n  }\n\n  function onSlidebarClicked(event: MouseEvent) {\n    if (event.target !== event.currentTarget) {\n      return;\n    }\n\n    const newSlidebarPosition = event.offsetX - handle.offsetWidth / 2;\n    let index: number;\n\n    if (splide.is('fade')) {\n      index = Math.round(newSlidebarPosition / (maxPosition / components.Slides.getLength()));\n    } else {\n      const newTrackPosition = getCalculatedTrackPosition(newSlidebarPosition);\n      index = components.Move.toIndex(newTrackPosition);\n    }\n\n    components.Controller.go(index, true);\n  }\n\n  function onSplideResized() {\n    handle.style.width = calculateHandleWidth();\n\n    recalculateSlidebarAndTrackPosition();\n  }\n\n  function onSplideOverflowed(isOverflow: boolean) {\n    if (isOverflow) {\n      enable();\n    } else {\n      disable();\n    }\n  }\n\n  /**\n   * Sets the handle position based on the active slide's position.\n   *\n   * @param index Active Slide index.\n   */\n  function onSplideMoveStarted(index: number) {\n    let newSlidebarPosition;\n    if (splide.is('fade')) {\n      newSlidebarPosition = (options.perPage / (components.Slides.getLength() - 1)) * maxPosition *\n        index;\n    } else {\n      const newTrackPosition = components.Move.toPosition(index);\n      newSlidebarPosition = getCalculatedSlidebarPosition(newTrackPosition);\n    }\n\n    position = getHandlePositionWithinBounds(newSlidebarPosition);\n    handle.style.transform = `translateX(${position}px)`;\n    handle.style.transition = 'transform 400ms cubic-bezier(0.25, 1, 0.5, 1)';\n  }\n\n  function onSplideDragging() {\n    const newPosition = getCalculatedSlidebarPosition();\n    position = getHandlePositionWithinBounds(newPosition);\n    handle.style.transform = `translateX(${position}px)`;\n  }\n\n  /**\n   * Calculates the handle's position based on the current track position.\n   *\n   * @param trackPosition Optional track position for calculation. If not provided the value from\n   *   the Move component is taken. We don't need to pass a new track position if this function used\n   *   to get the slidebar position when the slider is dragged, but it's necessary if used when the\n   *   slider is moved to a certain slide because the position at the end of moving should be taken\n   *   instead of the current Splide's track position.\n   */\n  function getCalculatedSlidebarPosition(trackPosition?: number) {\n    // Use the max track position for the last reachable slide index rather than computing from\n    // layout dimensions. The arithmetic below doesn't work if the last slide is reached. It's good\n    // enough for the slide position in the middle of the slider but causes the slidebar handle to\n    // never fully reach the end.\n    const endIndex = components.Controller.getEnd();\n    const currentIndex = components.Controller.getIndex();\n    if (endIndex === currentIndex) {\n      return maxPosition;\n    }\n\n    const currentTrackPosition = -1 * (trackPosition ?? components.Move.getPosition());\n    const ratio = currentTrackPosition / maxTrackPosition;\n    const newSlideBarPosition = ratio * maxPosition;\n    return newSlideBarPosition;\n  }\n\n  /**\n   * Calculates the track's position based on the handle's position.\n   *\n   * @param slidebarPosition Position of the slidebar handle.\n   */\n  function getCalculatedTrackPosition(slidebarPosition: number) {\n    const ratio = slidebarPosition / maxPosition;\n    const newTrackPosition = -1 * ratio * maxTrackPosition;\n    return newTrackPosition;\n  }\n\n  /**\n   * Cleans up the slidebar when Splide is destroyed. Splide calls this automatically when a\n   * breakpoint sets `destroy: true` (e.g. when all slides fit on screen). Without this handler the\n   * slidebar would remain visible after Splide tears down.\n   */\n  function destroy() {\n    disable();\n  }\n\n  return {\n    mount,\n    destroy\n  };\n}\n","export {};\n\n// See webpack.md for help. This MUST be included in any module that performs dynamic imports.\n\ndeclare global {\n  /**\n   * This is a global that is defined in a liquid snippet to point to the Shopify asset path.\n   * Webpack compilation is transpiled to point the variable to the global. Because Webpack\n   * compilation involves raw string replacement, this variable has to actually exist. Because we do\n   * not know the public path at compile time this is basically a hack that allows to define the\n   * public path at runtime. This public path is needed for webpack to perform its dynamic module\n   * loading, e.g. to support dynamic imports.\n   */\n  // eslint-disable-next-line @typescript-eslint/naming-convention\n  var __webpack_public_path__: string;\n}\n\n__webpack_public_path__ = window.__webpack_public_path__;\n","import '../../../lib/webpack-path.js';\nimport { CustomElement } from '@integrabeauty/custom-elements';\nimport type { Options, Splide } from '@splidejs/splide';\nimport { splideSlidebarExtension } from '../../../lib/splide-slidebar-extension.js';\n\nclass MobileMenuManager extends HTMLElement implements CustomElement {\n  private carousels = new Map<string, Splide>();\n  private panelsHistory = ['mobile-menu-panel-main'];\n\n  private onDOMContentLoadedBound = this.onDOMContentLoaded.bind(this);\n  private onButtonClickedBound = this.onButtonClicked.bind(this);\n  private onMainMenuHamburgerClickedBound = this.onMainMenuHamburgerClicked.bind(this);\n  private onBackButtonClickedBound = this.onBackButtonClicked.bind(this);\n\n  public connectedCallback() {\n    addEventListener('DOMContentLoaded', this.onDOMContentLoadedBound);\n    addEventListener('main-menu-hamburger-clicked', this.onMainMenuHamburgerClickedBound);\n  }\n\n  public disconnectedCallback() {\n    removeEventListener('DOMContentLoaded', this.onDOMContentLoadedBound);\n    removeEventListener('main-menu-hamburger-clicked', this.onMainMenuHamburgerClickedBound);\n\n    const panelButtons = this.querySelectorAll('button.mobile-menu-button');\n    for (const button of panelButtons) {\n      button.removeEventListener('click', this.onButtonClickedBound);\n    }\n\n    const backButtons = this.querySelectorAll('.menu-back-button');\n    for (const backButton of backButtons) {\n      backButton.addEventListener('click', this.onBackButtonClickedBound);\n    }\n  }\n\n  private onDOMContentLoaded() {\n    const panelButtons = this.querySelectorAll('button.mobile-menu-button');\n    for (const button of panelButtons) {\n      button.addEventListener('click', this.onButtonClickedBound);\n    }\n\n    const backButtons = this.querySelectorAll('.menu-back-button');\n    for (const backButton of backButtons) {\n      backButton.addEventListener('click', this.onBackButtonClickedBound);\n    }\n\n    this.initCarousel().catch(console.warn);\n  }\n\n  private onButtonClicked(event: Event) {\n    const button = <HTMLButtonElement>event.currentTarget;\n    const panelId = button.getAttribute('aria-controls');\n    this.clearActiveState();\n    this.setActiveState(panelId);\n    this.panelsHistory.push(panelId);\n  }\n\n  private onMainMenuHamburgerClicked(event: WindowEventMap['main-menu-hamburger-clicked']) {\n    // hide all open panels, omitting the main panel\n    const activePanels = this.querySelectorAll('.mobile-menu-panel:not(.hidden)');\n    for (const activePanel of activePanels) {\n      activePanel.classList.add('hidden');\n    }\n\n    // hide all expanded buttons\n    const activeButtons = this.querySelectorAll('button.mobile-menu-button[aria-expanded=\"true\"]');\n    for (const activeButton of activeButtons) {\n      activeButton.setAttribute('aria-expanded', 'false');\n    }\n\n    // set the initial panel history state\n    this.panelsHistory = ['mobile-menu-panel-main'];\n\n    // the main panel should be visible by default\n    const mainPanel = this.querySelector<HTMLElement>('#mobile-menu-panel-main');\n    mainPanel.classList.remove('hidden');\n\n    // set focus to a first interactive element if the menu is opened\n    if (event.detail.isActive) {\n      const firstInteractiveElement = mainPanel.querySelector<HTMLElement>('.mobile-menu-button');\n      firstInteractiveElement.focus();\n    }\n  }\n\n  private onBackButtonClicked(_event: Event) {\n    this.clearActiveState();\n    this.panelsHistory.pop();\n    const newActivePanelId = this.panelsHistory[this.panelsHistory.length - 1];\n    this.setActiveState(newActivePanelId);\n  }\n\n  private setActiveState(panelId: string) {\n    const panel = this.querySelector(`#${panelId}`);\n    panel.classList.remove('hidden');\n\n    // set focus to a first interactive element in the panel\n    const firstButton = panel.querySelector<HTMLElement>('.mobile-menu-button, .menu-back-button');\n    if (firstButton) {\n      firstButton.focus();\n    }\n\n    const button = this.querySelector(`button[aria-controls=\"${panelId}\"]`);\n    if (button) {\n      button.setAttribute('aria-expanded', 'true');\n    }\n\n    // Refresh carousel if exists. It should fix issues with the missing slidebar\n    const splide = this.carousels.get(panelId);\n    if (splide) {\n      splide.refresh();\n    }\n  }\n\n  private clearActiveState() {\n    const activePanelId = this.panelsHistory[this.panelsHistory.length - 1];\n    const activePanel = this.querySelector(`#${activePanelId}`);\n    if (activePanel) {\n      activePanel.classList.add('hidden');\n    }\n\n    const activeButton = this.querySelector(`button[aria-controls=\"${activePanelId}\"]`);\n    if (activeButton) {\n      activeButton.classList.remove('active');\n      activeButton.setAttribute('aria-expanded', 'false');\n    }\n  }\n\n  /**\n   * Initialize special offers carousels inside mobile menu panels\n   */\n  private async initCarousel() {\n    const { Splide } = await import('@splidejs/splide');\n\n    const options: Options = {\n      type: 'slide',\n      fixedWidth: 180,\n      arrows: false,\n      pagination: false,\n      gap: '20px',\n      perPage: 1,\n      perMove: 1,\n      keyboard: true,\n      slidebar: true,\n      mediaQuery: 'min',\n      breakpoints: {\n        992: {\n          destroy: true\n        }\n      }\n    };\n\n    // this.querySelectorAll() doesn't work with Splide, only document.querySelectorAll()!\n    const carouselElements =\n      document.querySelectorAll<HTMLElement>('mobile-menu-manager .splide--menu-special-offers');\n    for (const carouselElement of carouselElements) {\n      const parentPanel = carouselElement.closest('.mobile-menu-panel');\n      const parentPanelId = parentPanel.getAttribute('id');\n      const splide = new Splide(carouselElement, options);\n      this.carousels.set(parentPanelId, splide);\n      splide.mount({\n        splideSlidebarExtension\n      });\n    }\n  }\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'mobile-menu-manager': MobileMenuManager;\n  }\n}\n\nif (!customElements.get('mobile-menu-manager')) {\n  customElements.define('mobile-menu-manager', MobileMenuManager);\n}\n","/**\n * Full-width promo banner carousel at the top of the page.\n *\n * Displays multiple banners that automatically rotate based on a customizable interval. The top-\n * banner custom element can hide himself based on counter calculation or if the user clicked the\n * close button. When that happens the \"top-banner-updated\" event is fired, and we need to refresh\n * the Splide carousel.\n */\n\nimport '../../lib/webpack-path.js';\nimport type { Options, Splide } from '@splidejs/splide';\n\nlet splide: Splide;\n\nasync function onDOMContentLoaded() {\n  const carousel = document.querySelector<HTMLElement>('.top-banner-carousel');\n  if (!carousel) {\n    return;\n  }\n\n  const { Splide } = await import('@splidejs/splide');\n  const options: Options = {\n    type: 'fade',\n    pagination: false,\n    rewind: true\n  };\n\n  options.arrows = carousel.dataset.showArrows === 'true';\n\n  // We need to enable autoplay only if the interval is a valid positive number, otherwise we don't\n  // need to enable it.\n  const interval = parseInt(carousel.dataset.interval, 10);\n  if (interval > 0) {\n    options.autoplay = true;\n    options.interval = interval;\n  }\n\n  splide = new Splide(carousel, options);\n  splide.mount();\n\n  splide.on('mounted', (_event: Event) => {\n    const event = new Event('top-banner-carousel-updated');\n    dispatchEvent(event);\n  });\n\n  splide.on('refresh', (_event: Event) => {\n    const event = new Event('top-banner-carousel-updated');\n    dispatchEvent(event);\n  });\n\n  for (const event of top_banner_carousel_event_queue) {\n    if (isTopBannerUpdatedEvent(event)) {\n      try {\n        onTopBannerUpdated(event);\n      } catch (error) {\n        console.warn(error);\n      }\n    }\n  }\n}\n\nfunction onTopBannerUpdated(_event: Event) {\n  if (!splide) {\n    return;\n  }\n\n  splide.refresh();\n}\n\nfunction isTopBannerUpdatedEvent(value: any): value is WindowEventMap['top-banner-updated'] {\n  return value?.type === 'top-banner-updated';\n}\n\naddEventListener('DOMContentLoaded', onDOMContentLoaded);\naddEventListener('top-banner-updated', onTopBannerUpdated);\n\ndeclare global {\n  // eslint-disable-next-line @typescript-eslint/naming-convention\n  var top_banner_carousel_event_queue: Event[];\n  // eslint-disable-next-line @typescript-eslint/naming-convention\n  var top_banner_carousel_event_listener: (event: Event) => void;\n\n  interface WindowEventMap {\n    'top-banner-carousel-updated': Event;\n  }\n}\n","// This library was copied from Lange to support top banner component. So some documentation can be\n// related to lange only, but I'd like to keep it as it is to have fewer differences between Ofir\n// and Lange because that should help to move this library/component to a shared app.\n//\n// We have now more than one element that displays a countdown clock on the page. When the elements\n// use separate `setInterval()` calls to display their time the effect of them not being\n// synchronized can be seen even if the interval is low (50-100ms).\n//\n// This module provides a very simple synchronization method and some shared utilities for timestamp\n// calculations.\n//\n// Clock synchronization is based on a single `setInterval()` call. This starts a timer which emits\n// `timer-tick` events. Each page element can listen to the events to update the displayed time at\n// the very same moment other elements do.\n//\n// The timer has to be initialized with the `startTimer()` function. There is no possibility to stop\n// the timer, as we would have to implement a reference counter which would be prone to problems,\n// i.e. a bug in a simple component could stop all timers on the page. Instead of stopping the timer\n// the components should stop listening to the events.\n\nlet intervalId: ReturnType<typeof setInterval> | null = null;\n\n/**\n * Calculate the remaining time between currentTimestamp and endTimestamp and express it as an\n * object with number of days, hours, minutes, seconds as integers and a human readable `text`\n */\nexport function timeLeft(currentTimestamp: number, endTimestamp: number) {\n  if (currentTimestamp > endTimestamp || !endTimestamp) {\n    return null;\n  }\n\n  const secondsLeft = Math.round((endTimestamp - currentTimestamp) / 1000);\n  const seconds = secondsLeft % 60;\n\n  const minutesLeft = (secondsLeft - seconds) / 60;\n  const minutes = minutesLeft % 60;\n\n  const hoursLeft = (minutesLeft - minutes) / 60;\n  const hours = hoursLeft % 24;\n\n  const days = (hoursLeft - hours) / 24;\n\n  const text = [\n    days.toString(),\n    days === 1 ? 'day' : 'days',\n    hours.toString(),\n    hours === 1 ? 'hour' : 'hours',\n    minutes.toString(),\n    minutes === 1 ? 'minute' : 'minutes',\n    seconds.toString(),\n    seconds === 1 ? 'second' : 'seconds'\n  ].join(' ');\n\n  return {\n    text, days, hours, minutes, seconds\n  };\n}\n\n/**\n * Start emitting `timer-tick` events\n *\n * This function may be called multiple times. It will only start a single timer.\n */\nexport function startTimer() {\n  if (intervalId) {\n    return;\n  }\n\n  // dispatch the first event immediately\n  setTimeout(tick, 0);\n\n  intervalId = setInterval(tick, 1000);\n}\n\nfunction tick() {\n  type Detail = TimerTickEvent['detail'];\n  const event = new CustomEvent<Detail>('timer-tick', {\n    detail: { timestamp: Date.now() }\n  });\n  dispatchEvent(event);\n}\n\ntype TimerTickEvent = CustomEvent<{\n  timestamp: number;\n}>;\n\ndeclare global {\n  interface WindowEventMap {\n    'timer-tick': TimerTickEvent;\n  }\n}\n","import type { CustomElement } from '@integrabeauty/custom-elements';\nimport debounce from '../../../lib/debounce.js';\nimport { startTimer, timeLeft } from '../countdown-timer.js';\nimport html from './index.html';\nimport styles from './index.scss';\n\n/**\n * Custom HTML element representing a top banner with features like a clock, badge, and close\n * button. All of these features are optional and configurable via data-attributes. The component\n * store the hash of the messages closed by user to prevent showing it again. In case of a\n * horizontal overflow the message will be auto scrolled to ensure the entire message is visible.\n */\nclass TopBanner extends HTMLElement implements CustomElement {\n  declare readonly dataset: {\n    /**\n     * Should the badge be displayed\n     */\n    badgeShow: 'false' | 'true';\n\n    /**\n     * The text of the clock badge.\n     *\n     * @default \"Limited Time\"\n     */\n    badgeText: string;\n\n    /**\n     * Stop time as unix epoch time.\n     *\n     * @see https://www.epochconverter.com\n     */\n    clockEndTime: string;\n\n    /**\n     * If false the entire clock and the \"Limited time\" badge will disappear\n     */\n    clockShow: 'false' | 'true';\n\n    /**\n     * Start time as unix epoch time.\n     *\n     * @see https://www.epochconverter.com\n     */\n    clockStartTime: string;\n\n    /**\n     * If false the close button will disappear\n     */\n    closeButtonShow: 'false' | 'true';\n\n    /**\n     * Represents a URL link as a string\n     */\n    link: string;\n\n    /**\n     * Message to be shown. Slot can't be used because of the auto scrolling feature that requires\n     * the message to be cloned and duplicated in the DOM in case of overflow to ensure smooth\n     * scrolling.\n     */\n    message: string;\n\n    /**\n     * Scrolling animation speed in pixels per second. The default value is 80px/s. A number value\n     * represented as a string, for example \"80\".\n     */\n    scrollingSpeed: string;\n  };\n\n  private endTimestamp: number | null = null;\n\n  private onCloseClickedBound = this.onCloseClicked.bind(this);\n  private onTimerTickBound = this.onTimerTick.bind(this);\n  private onWindowResizedBound = this.onWindowResized.bind(this);\n  private onWindowResizedDebounced = debounce(this.onWindowResizedBound, 300);\n  private onTopBannerCarouselUpdatedBound = this.onTopBannerCarouselUpdated.bind(this);\n\n  public connectedCallback() {\n    this.initializeShadowRoot();\n    this.render();\n\n    window.addEventListener('resize', this.onWindowResizedDebounced);\n\n    // If there's multiple banners in the carousel, we need to listen for the carousel update event\n    // triggered after the Splide carousel initialization. In the case of a single banner, there's\n    // no such event, so we can just check the overflow on the initial render without waiting for\n    // any events.\n    if (this.classList.contains('splide__slide')) {\n      addEventListener('top-banner-carousel-updated', this.onTopBannerCarouselUpdatedBound);\n    } else {\n      this.handleOverflow();\n    }\n  }\n\n  public disconnectedCallback() {\n    window.removeEventListener('resize', this.onWindowResizedDebounced);\n    removeEventListener('top-banner-carousel-updated', this.onTopBannerCarouselUpdatedBound);\n    removeEventListener('timer-tick', this.onTimerTickBound);\n    const closeButton = this.shadowRoot.querySelector('button.close');\n    closeButton?.removeEventListener('click', this.onCloseClickedBound);\n  }\n\n  private initializeShadowRoot() {\n    if (!this.shadowRoot) {\n      this.attachShadow({ mode: 'open' });\n      this.shadowRoot.innerHTML = `<style>${styles}</style>${html}`;\n    }\n  }\n\n  private render() {\n    if (this.dataset.clockEndTime) {\n      this.endTimestamp = parseInt(this.dataset.clockEndTime, 10) * 1000;\n    }\n\n    const closeButton = this.shadowRoot.querySelector('button.close');\n    closeButton.addEventListener('click', this.onCloseClickedBound);\n\n    // Check if the user dismissed the current message. We use an extremely simple, non-\n    // cryptographic hash as we just want to detect if the message has changed since the last time\n    // the user clicked close. We accept the extremely rare possibility of collision and storage\n    // failing as the consequence is that the user will (not) see a promo message. The message\n    // length is not bound, so we cannot just save the message itself into storage.\n    const current = this.getCurrentMessageHash();\n    const dismissed = readDismissed();\n    if (current !== dismissed) {\n      // start everything only if the message has not been dismissed\n      startTimer();\n      addEventListener('timer-tick', this.onTimerTickBound);\n      this.showBanner();\n\n      // render message\n      const message = this.shadowRoot.querySelector('.message');\n      message.innerHTML = this.dataset.message;\n\n      // render timer clock\n      const timer = this.shadowRoot.querySelector('.timer');\n      if (this.dataset.clockShow === 'true') {\n        if (this.shouldShowClock()) {\n          // the clock should be displayed - it is active\n          timer.classList.remove('hidden');\n        } else {\n          // the clock was set to be displayed but the message expired already hide the entire\n          // banner\n          this.hideBanner();\n        }\n      } else {\n        // the clock was disabled but we still have a message to show - hide the timer\n        timer.classList.add('hidden');\n      }\n\n      // render badge\n      const badge = this.shadowRoot.querySelector('.badge');\n      if (badge) {\n        badge.textContent = this.dataset.badgeText || 'Limited Time';\n        if (this.dataset.badgeShow === 'true') {\n          badge.classList.remove('hidden');\n        }\n      }\n\n      const closeButton = this.shadowRoot.querySelector('.close');\n      if (this.dataset.closeButtonShow === 'true') {\n        closeButton.classList.remove('hidden');\n      } else {\n        closeButton.classList.add('hidden');\n      }\n\n      // render link\n      const link = this.shadowRoot.querySelector<HTMLAnchorElement>('.link');\n      if (this.dataset.link) {\n        link.href = this.dataset.link;\n      } else {\n        link.removeAttribute('href');\n      }\n\n      this.renderClock(Date.now());\n\n      updatePagePositioning();\n    }\n  }\n\n  /**\n   * We have a few requirements to show the countdown clock. Calculate the decision\n   */\n  private shouldShowClock() {\n    const currentTimestamp = Date.now();\n\n    let startTimestamp = Number.MAX_SAFE_INTEGER;\n    if (this.dataset.clockStartTime) {\n      startTimestamp = parseInt(this.dataset.clockStartTime, 10) * 1000;\n    }\n\n    let endTimestamp = 0;\n    if (this.dataset.clockEndTime) {\n      endTimestamp = parseInt(this.dataset.clockEndTime, 10) * 1000;\n    }\n\n    return this.dataset.clockShow === 'true' &&\n      startTimestamp <= currentTimestamp &&\n      endTimestamp >= currentTimestamp;\n  }\n\n  private onTimerTick(event: WindowEventMap['timer-tick']) {\n    this.renderClock(event.detail.timestamp);\n  }\n\n  private renderClock(timestamp: number) {\n    const timer = this.shadowRoot.querySelector<HTMLElement>('.timer');\n    if (!this.shouldShowClock()) {\n      if (timer && !timer.classList.contains('hidden')) {\n        timer.classList.add('hidden');\n        updatePagePositioning();\n      }\n\n      return;\n    }\n\n    const remaining = timeLeft(timestamp, this.endTimestamp);\n\n    this.setClockSegmentValue('.days', remaining.days);\n    this.setClockSegmentValue('.hours', remaining.hours);\n    this.setClockSegmentValue('.minutes', remaining.minutes);\n    this.setClockSegmentValue('.seconds', remaining.seconds);\n\n    timer?.setAttribute('aria-label', remaining.text);\n  }\n\n  private setClockSegmentValue(selector: string, value: number) {\n    const stringValue = value < 10 ? '0' + value : value.toString();\n    const element = this.shadowRoot.querySelector(selector);\n    if (element && element.textContent !== stringValue) {\n      element.textContent = stringValue;\n    }\n  }\n\n  private hideBanner() {\n    this.parentElement.removeChild(this);\n\n    // ensure the whole page is repositioned\n    updatePagePositioning();\n  }\n\n  private showBanner() {\n    // TODO fix eslint error\n    // eslint-disable-next-line wc/no-self-class\n    this.classList.remove('hidden');\n\n    // ensure the whole page is repositioned\n    updatePagePositioning();\n  }\n\n  private onCloseClicked(_event: Event) {\n    this.hideBanner();\n    const hash = this.getCurrentMessageHash();\n    writeDismissed(hash);\n  }\n\n  private onWindowResized(_event: Event) {\n    this.handleOverflow();\n  }\n\n  /**\n   * Update the overflow state if the banner is a part of a carousel and the carousel was updated.\n   * We need to do that because the Splide carousel is hidden until it's fully initialized and it\n   * cause incorrect overflow state calculation on the initial render of the banner.\n   */\n  private onTopBannerCarouselUpdated(_event: Event) {\n    this.handleOverflow();\n  }\n\n  /**\n   * Check if the message is overflowing horizontally and if so enable auto scrolling animation or\n   * disable it if the window was resized to be bigger. We should check it on every window resize.\n   */\n  private handleOverflow() {\n    const wrapper = this.shadowRoot.querySelector('.wrapper');\n    const overflowed = wrapper.classList.contains('overflowed');\n    const link = this.shadowRoot.querySelector<HTMLElement>('.link');\n\n    // We should always check the actual content width not the link width as the link might contain\n    // a cloned content for the scrolling animation if it's overflowed.\n    const originalContent = this.shadowRoot.querySelector('.link-content:not(.clone)');\n    const contentWidth = originalContent.scrollWidth;\n    const wrapperWidth = wrapper.getBoundingClientRect().width;\n\n    // Calculating the animation duration so the scrolling speed is consistent regardless of the\n    // message length. We need to duplicate the content width because the cloned content. This\n    // calculation might be not 100% precise but still gives a good approximation and ensures the\n    // scrolling speed is consistent across different message lengths.\n    const overflow = contentWidth * 2 - wrapperWidth;\n    const scrollingSpeed = parseInt(this.dataset.scrollingSpeed, 10) || 80;\n    const duration = overflow / scrollingSpeed;\n\n    if (overflowed) {\n      // If it's already overflowed we should disable the scrolling animation in the case there's no\n      // more overflow for the current frame size.\n      if (contentWidth <= wrapperWidth) {\n        const linkContentClone = this.shadowRoot.querySelector('.link-content.clone');\n        if (linkContentClone) {\n          linkContentClone.remove();\n        }\n\n        wrapper.classList.remove('overflowed');\n      } else {\n        // if overflowed and it shouldn't be disabled, we should update the animation duration\n        // because the message window size might be changed\n        link.style.animationDuration = `${duration}s`;\n      }\n    } else {\n      // If it's not overflowed we should enable the scrolling animation in the case there's an\n      // overflow for the current frame size.\n      if (contentWidth > wrapperWidth) {\n        wrapper.classList.add('overflowed');\n        link.style.animationDuration = `${duration}s`;\n\n        // duplicate the link content to imitate infinite scrolling effect with pure CSS animation.\n        const linkContent = this.shadowRoot.querySelector('.link-content');\n        const linkContentClone = <HTMLElement>linkContent.cloneNode(true);\n        linkContentClone.classList.add('clone');\n        link.appendChild(linkContentClone);\n      }\n    }\n  }\n\n  private getCurrentMessageHash() {\n    return jenkinsHash(this.dataset.message);\n  }\n}\n\nfunction readDismissed() {\n  try {\n    return sessionStorage.getItem('top_banner_dismissed');\n  } catch (error) {\n    console.log(error);\n  }\n\n  return '';\n}\n\n/**\n * This writes into session storage so that there is a natural expiration. Previously this was\n * setting a cookie that expired after four hours. This is roughly the same.\n *\n * Errors are logged instead of thrown. This logs at a level not monitored by error instrumentation\n * just to help with development.\n */\nfunction writeDismissed(hash: string) {\n  try {\n    sessionStorage.setItem('top_banner_dismissed', hash);\n  } catch (error) {\n    console.warn(error);\n  }\n}\n\n/**\n * Very simple and fast non-cryptographic string hashing function. Return b)\n a 32-bit\n * unsigned number (as a hex string)\n *\n * See https://en.wikipedia.org/wiki/Jenkins_hash_function#one_at_a_time for details\n * Based on https://www.burtleburtle.net/bob/hash/doobs.html the original C source is Public Domain\n *\n * Modified to work with empty and undefined inputs\n */\nfunction jenkinsHash(key: string | undefined) {\n  let hash = 0;\n  const inputLength = key?.length || 0;\n  for (let i = 0; i < inputLength; i++) {\n    hash += key.charCodeAt(i);\n    hash += hash << 10;\n    // JS has no 32 bit unsigned int values, so we use the trick in the next line to truncate the\n    // value to 32 bits and remove the sign\n    hash = (hash & 0xFFFFFFFF) >>> 0;\n    hash ^= hash >>> 6;\n  }\n\n  hash += hash << 3;\n  // truncate again\n  hash = (hash & 0xFFFFFFFF) >>> 0;\n  hash ^= hash >>> 11;\n  hash += hash << 15;\n\n  // truncate before returning\n  hash = (hash & 0xFFFFFFFF) >>> 0;\n  return hash.toString(16);\n}\n\nfunction updatePagePositioning() {\n  dispatchEvent(new Event('top-banner-updated'));\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'top-banner': TopBanner;\n  }\n\n  interface WindowEventMap {\n    'top-banner-updated': Event;\n  }\n}\n\nif (!customElements.get('top-banner')) {\n  customElements.define('top-banner', TopBanner);\n}\n"],"names":["header","mainMenu","container","document","addEventListener","querySelector","console","warn","intersectionObserver","IntersectionObserver","entries","entry","intersectionRatio","classList","remove","add","contains","rootMargin","threshold","ResizeObserver","_entries","newOffsetTop","offsetParent","offsetHeight","calculateTopOffset","style","setProperty","disconnect","observe","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","module","__webpack_modules__","m","d","definition","Array","isArray","i","length","key","binding","o","Object","defineProperty","enumerable","value","get","f","e","chunkId","Promise","all","keys","reduce","promises","u","miniCssF","obj","prop","prototype","hasOwnProperty","call","inProgress","dataWebpackPrefix","l","url","done","push","script","needAttach","scripts","getElementsByTagName","s","getAttribute","createElement","charset","nc","setAttribute","src","onScriptComplete","prev","event","onerror","onload","clearTimeout","timeout","doneFns","parentNode","removeChild","forEach","fn","setTimeout","bind","type","target","head","appendChild","p","installedChunks","j","installedChunkData","promise","resolve","reject","error","Error","loadingEnded","errorType","realSrc","message","name","request","webpackJsonpCallback","parentChunkLoadingFunction","data","chunkIds","moreModules","runtime","some","id","chunkLoadingGlobal","self","SearchPanelManager","HTMLElement","returnFocusTo","onSearchPanelShowRequestedBound","this","onSearchPanelShowRequested","onSearchPanelCloseRequestedBound","onSearchPanelCloseRequested","onShroudClickedBound","onShroudClicked","onAddToCardBound","onAddToCard","connectedCallback","disconnectedCallback","removeEventListener","detail","showPanel","_event","closePanel","searchPanel","element","dataset","active","headerOffsetBottom","headerRect","getBoundingClientRect","height","top","getHeaderOffsetBottom","focus","modalShowEvent","CustomEvent","dispatchEvent","modalCloseEvent","debounce","func","timer","_len","arguments","args","_key","customElements","define","SearchInput","onInputBound","onInput","onSubmitBound","onSubmit","onResetBound","onReset","onCloseClickedBound","onCloseClicked","sendSearchInputChangedEventBound","sendSearchInputChangedEvent","sendSearchInputChangedEventDebounced","initializeShadowRoot","render","shadowRoot","form","attachShadow","mode","delegatesFocus","innerHTML","input","clearButton","query","trim","disabled","preventDefault","reset","Event","tagName","customEvent","SearchPanel","onSearchInputChangedBound","onSearchInputChanged","renderSearchResults","showLoader","response","params","URLSearchParams","set","fetch","getSearchResults","ok","statusText","html","text","log","hideLoader","onDOMContentLoaded","readyState","MainMenuManager","activePanel","onDOMContentLoadedBound","onButtonClickedBound","onButtonClicked","onHamburgerButtonClickedBound","onHamburgerButtonClicked","onPointerEnterBound","onPointerEnter","onMainMenuMouseLeaveBound","onMainMenuMouseLeave","onPanelMouseLeaveBound","onPanelMouseLeave","panelButtons","querySelectorAll","button","onPointerDown","hamburgerButton","panels","panel","searchButton","onSearchClicked","onCartClicked","cartButton","currentTarget","clearActiveState","setActiveState","hamburgerClickedEvent","isActive","panelId","scrollbarWidth","window","innerWidth","documentElement","clientWidth","Number","isInteger","removeAttribute","activeButtons","pointerType","relatedTarget","closestPanel","closest","href","location","searchPanelShowRequstedEvent","splideSlidebarExtension","splide","components","options","slidebar","handle","maxPosition","maxTrackPosition","hasSlidebarMarkup","position","previousTouchX","enable","Elements","root","onSplideResized","is","on","onSplideDragging","onSplideMoveStarted","onMousedown","onTouchstart","passive","onTransitionend","onSlidebarClicked","disable","off","calculateHandleWidth","handleWidth","perPage","Slides","getLength","Layout","listSize","sliderSize","processHandleMove","toPosition","newPosition","getHandlePositionWithinBounds","newSplidePosition","getCalculatedTrackPosition","Move","translate","requestAnimationFrame","transform","alignTrackPosition","index","Math","round","currentSplidePosition","getPosition","toIndex","Controller","go","onSplideOptionsUpdated","_options","toggleSlidebar","onSplideReady","isEnough","isOverflow","onMousemove","onMouseup","movementX","touch","touches","clientX","onTouchmove","onTouchend","transition","newSlidebarPosition","offsetX","offsetWidth","newTrackPosition","width","onSplideOverflowed","getCalculatedSlidebarPosition","trackPosition","getEnd","getIndex","slidebarPosition","mount","destroy","__webpack_public_path__","MobileMenuManager","carousels","Map","panelsHistory","onMainMenuHamburgerClickedBound","onMainMenuHamburgerClicked","onBackButtonClickedBound","onBackButtonClicked","backButtons","backButton","initCarousel","catch","activePanels","activeButton","mainPanel","pop","newActivePanelId","firstButton","refresh","activePanelId","Splide","then","fixedWidth","arrows","pagination","gap","perMove","keyboard","mediaQuery","breakpoints","carouselElements","carouselElement","parentPanelId","onTopBannerUpdated","isTopBannerUpdatedEvent","async","carousel","rewind","showArrows","interval","parseInt","autoplay","top_banner_carousel_event_queue","intervalId","tick","timestamp","Date","now","TopBanner","endTimestamp","onTimerTickBound","onTimerTick","onWindowResizedBound","onWindowResized","onWindowResizedDebounced","onTopBannerCarouselUpdatedBound","onTopBannerCarouselUpdated","handleOverflow","closeButton","clockEndTime","getCurrentMessageHash","sessionStorage","getItem","readDismissed","setInterval","showBanner","clockShow","shouldShowClock","hideBanner","badge","textContent","badgeText","badgeShow","closeButtonShow","link","renderClock","updatePagePositioning","currentTimestamp","startTimestamp","MAX_SAFE_INTEGER","clockStartTime","remaining","secondsLeft","seconds","minutesLeft","minutes","hoursLeft","hours","days","toString","join","timeLeft","setClockSegmentValue","selector","stringValue","parentElement","hash","setItem","writeDismissed","wrapper","overflowed","contentWidth","scrollWidth","wrapperWidth","duration","scrollingSpeed","linkContentClone","animationDuration","cloneNode","inputLength","charCodeAt","jenkinsHash"],"sourceRoot":""}