{"version":3,"file":"product-details-section-xxxxxxxxxxxxxxxxxxxx.min.js","mappings":"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","sources":["webpack://lange/webpack/runtime/load script","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/publicPath","webpack://lange/webpack/runtime/jsonp chunk loading","webpack://lange/./scripts/sections/product-details/paired-product/index.ts","webpack://lange/./scripts/sections/product-details/paired-product/index.scss","webpack://lange/./scripts/sections/product-details/paired-product/index.html","webpack://lange/./scripts/sections/product-details/findation-widget-button/index.ts","webpack://lange/./scripts/sections/product-details/findation-widget-button/index.html","webpack://lange/./scripts/sections/product-details/product-details/index.ts","webpack://lange/./scripts/sections/product-details/product-variant-selector/index.ts","webpack://lange/./scripts/sections/product-details/product-variant-selector/index.scss","webpack://lange/./scripts/sections/product-details/product-variant-selector/index.html","webpack://lange/./scripts/sections/product-details/sticky-cta/index.ts","webpack://lange/./scripts/sections/product-details/sticky-cta/index.scss","webpack://lange/./scripts/sections/product-details/sets-subproduct/index.ts","webpack://lange/./scripts/sections/product-details/sets-subproduct/index.scss","webpack://lange/./scripts/sections/product-details/sets-subproduct/index.html","webpack://lange/./scripts/sections/product-details/product-description/index.ts","webpack://lange/./scripts/sections/product-details/product-description/index.scss","webpack://lange/./scripts/sections/product-details/product-description/index.html","webpack://lange/./scripts/sections/product-details/product-detail-countdown-timer/index.ts","webpack://lange/./scripts/sections/product-details/product-detail-countdown-timer/index.scss","webpack://lange/./scripts/sections/product-details/product-detail-countdown-timer/index.html","webpack://lange/./scripts/sections/product-details/zoomable-image/index.ts","webpack://lange/./scripts/sections/product-details/zoomable-image/index.scss","webpack://lange/./scripts/sections/product-details/zoomable-image/index.html","webpack://lange/./scripts/lib/splide-slidebar-extension.ts","webpack://lange/./scripts/sections/product-details/product-gallery.ts","webpack://lange/./scripts/lib/webpack-path.ts"],"sourcesContent":["var inProgress = {};\nvar 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\tvar script, needAttach;\n\tif(key !== undefined) {\n\t\tvar scripts = document.getElementsByTagName(\"script\");\n\t\tfor(var i = 0; i < scripts.length; i++) {\n\t\t\tvar 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\tscript.timeout = 120;\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\tvar 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\tvar 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\tvar 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};","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar 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\tvar 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 functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\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 + \"-\" + \"4c2b34155a625ff7db66\" + \".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); }","__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\nvar installedChunks = {\n\t\"product-details-section\": 0\n};\n\n__webpack_require__.f.j = function(chunkId, promises) {\n\t\t// JSONP chunk loading for javascript\n\t\tvar 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\tvar 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\tvar 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\tvar error = new Error();\n\t\t\t\t\tvar 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\tvar errorType = event && (event.type === 'load' ? 'missing' : event.type);\n\t\t\t\t\t\t\t\tvar 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\nvar webpackJsonpCallback = function(parentChunkLoadingFunction, data) {\n\tvar chunkIds = data[0];\n\tvar moreModules = data[1];\n\tvar 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\nvar 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';\nimport html from './index.html';\nimport styles from './index.scss';\n\n/**\n * A paired product component that displays simplified product card in the product details on PDP.\n * It accepts promo link URL and label as data attributes and renders the promo link accordingly.\n */\n// @ts-ignore TODO remove it when the custom element will be updated to match newest L'ange style\nclass PairedProduct extends HTMLElement implements CustomElement {\n  public shadowRoot!: ShadowRoot;\n\n  public constructor() {\n    super();\n    this.attachShadow({ mode: 'open' });\n    this.shadowRoot.innerHTML = `<style>${styles}</style>${html}`;\n  }\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'paired-product': PairedProduct;\n  }\n}\n\nif (!customElements.get('paired-product')) {\n  customElements.define('paired-product', PairedProduct);\n}\n","export default \":host{display:block}slot{display:block}h2{font-size:.875rem;font-weight:300;letter-spacing:.07em;margin-top:0;text-transform:uppercase}@media only screen and (min-width:768px){h2{font-size:1rem}}slot[name=promo]{font-size:.75rem;letter-spacing:.07em;margin-top:10px;text-transform:uppercase}\";","// Module\nvar code = \"<h2><slot name=\\\"title\\\"></slot></h2><slot name=\\\"product\\\"></slot><slot name=\\\"promo\\\"></slot>\";\n// Exports\nexport default code;","import type { CustomElement } from '@integrabeauty/custom-elements';\nimport html from './index.html';\n\n/**\n * Hosts the Findation shade-finder widget and wires up its callbacks to the Ofir event system.\n */\nclass FindationWidgetButton extends HTMLElement implements CustomElement {\n  public shadowRoot!: ShadowRoot;\n  private shouldOpenModal = false;\n\n  private onWidgetEmbeddedBound = this.onWidgetEmbedded.bind(this);\n  private onDOMContentLoadedBound = this.onDOMContentLoaded.bind(this);\n  private onWidgetOpenedBound = this.onWidgetOpened.bind(this);\n  private onWidgetClosedBound = this.onWidgetClosed.bind(this);\n  private onAdClickedBound = this.onAdClicked.bind(this);\n\n  public constructor() {\n    super();\n    this.attachShadow({ mode: 'open' });\n    this.shadowRoot.innerHTML = html;\n  }\n\n  public connectedCallback() {\n    window.Findation = window.Findation || <Window['Findation']>{};\n\n    addEventListener('message', onMessage);\n    addEventListener('ofir-ad-clicked', this.onAdClickedBound);\n\n    if (document.readyState === 'complete' || document.readyState === 'interactive') {\n      setTimeout(this.onDOMContentLoadedBound);\n    } else {\n      addEventListener('DOMContentLoaded', this.onDOMContentLoadedBound);\n    }\n\n    // Replay any queued `ofir-ad-clicked` events that fired before this element connected.\n    for (const event of window.ofir.queue) {\n      if (event?.type === 'ofir-ad-clicked') {\n        this.onAdClickedBound(<WindowEventMap['ofir-ad-clicked']>event);\n      }\n    }\n  }\n\n  public disconnectedCallback() {\n    removeEventListener('DOMContentLoaded', this.onDOMContentLoadedBound);\n    removeEventListener('message', onMessage);\n    removeEventListener('ofir-ad-clicked', this.onAdClickedBound);\n\n    const button = this.querySelector('button');\n    button.removeEventListener('click', onButtonClicked);\n  }\n\n  private onDOMContentLoaded(_event: Event) {\n    if (!this.isConnected) {\n      return;\n    }\n\n    this.render();\n\n    window.Findation.widgetEmbedded = this.onWidgetEmbeddedBound;\n    window.Findation.widgetDidOpen = this.onWidgetOpenedBound;\n    window.Findation.widgetDidClose = this.onWidgetClosedBound;\n    window.Findation.onSearchComplete = onSearchCompleted;\n\n    addEventListener('message', onMessage);\n  }\n\n  /**\n   * We must use slot and an element in light DOM for the widget's button to render correctly,\n   * because their script can't handle it if it's rendered in the shadow DOM.\n   */\n  private render() {\n    // The Findation scripts create an iframe above the given element, so we need to render a\n    // placeholder element in the light DOM and pass it to their init function.\n    const placeholder = document.createElement('div');\n    placeholder.id = 'findation-widget-button';\n    placeholder.style.display = 'none';\n    this.appendChild(placeholder);\n\n    window.Findation.init(\n      placeholder,\n      'cc9d02b6b78746ede9bb4fa953cd8921090f36330c2cda6f35ece9adf925',\n      {}\n    );\n\n    const button = this.querySelector('button');\n    button.addEventListener('click', onButtonClicked);\n  }\n\n  private onWidgetEmbedded(iframe: HTMLIFrameElement) {\n    // we don't want to display the original Findation button iframe, since we have our own custom\n    // button in the page that opens the widget, so we hide it.\n    iframe.style.display = 'none';\n\n    // Slotted content is hidden by default to avoid showing it before the widget is ready. Now that\n    // the widget is embedded, we can show the slotted content (custom button). It should be done in\n    // 2 steps: first hiding the original iframe, then showing the slotted content with the button\n    // to prevent the original Findation button iframe from briefly flashing on the screen before\n    // being hidden.\n    const slot = this.shadowRoot.querySelector('slot');\n    slot.hidden = false;\n\n    const event = new Event('ofir-findation-widget-embedded', { cancelable: true });\n    dispatchEvent(event);\n\n    if (this.shouldOpenModal) {\n      window.postMessage('overlayOpen');\n    }\n  }\n\n  private onAdClicked(event: WindowEventMap['ofir-ad-clicked']) {\n    if (event.detail.findationModal) {\n      this.shouldOpenModal = true;\n    }\n  }\n\n  /**\n   * Triggers each time the widget is opened.\n   */\n  private onWidgetOpened() {\n    const button = this.querySelector('button');\n    button.setAttribute('aria-expanded', 'true');\n\n    const event = new Event('ofir-findation-widget-did-open', { cancelable: true });\n    dispatchEvent(event);\n  }\n\n  /**\n   * Triggers each time the widget is closed\n   */\n  private onWidgetClosed() {\n    const button = this.querySelector('button');\n    button.setAttribute('aria-expanded', 'false');\n\n    const event = new Event('ofir-findation-widget-did-close', { cancelable: true });\n    dispatchEvent(event);\n  }\n}\n\n/**\n * Handle our custom button click and trigger the widget to open by posting a message that the\n * widget listens to. There's also a function Findation.openWidget() in their script that can be\n * used to open the widget, but we used this message-based approach, so I'm not sure if it's safe to\n * replace with the direct function call.\n */\nfunction onButtonClicked(_event: Event) {\n  window.postMessage('overlayOpen');\n}\n\n/**\n * Handle the search completion event from the Findation widget\n */\nfunction onSearchCompleted(data: FindationSearchResponse) {\n  const event = new CustomEvent('ofir-findation-search-complete', {\n    cancelable: true,\n    detail: data\n  }\n  );\n  dispatchEvent(event);\n\n  if (data.matchSuccess) {\n    window.Findation.iframe.contentWindow.postMessage(\n      {\n        event: 'onSearchComplete',\n        id: data.externalId\n      },\n      window.Findation.iframe.src\n    );\n  }\n}\n\n/**\n * Handle messages from the Findation widget. We only need to handle a message when the search\n * is completed, a match is found, and the user clicks the \"Shop Now\" button in the widget, in which\n * case we redirect the user to the same page with the recommended variant ID as a search parameter,\n * so the page can load with the recommended variant selected.\n */\nfunction onMessage(event: MessageEvent) {\n  if (event.data?.event === 'ofir-findation-shop-now' && event.data?.id) {\n    location.href = `${location.origin}${location.pathname}?variant=${event.data?.id}`;\n  }\n}\n\n/**\n * Represents a shade returned from the Findation widget, the user entered in the widget before\n * completing the search\n */\ntype Shade = {\n  /**\n   * A brand name of the shade, it's not necessarily our brand name.\n   */\n  brandName: string;\n\n  /**\n   * A product name of the shade, it's not necessarily one of our product names.\n   */\n  productName: string;\n\n  /**\n   * A shade name, it's not necessarily one of our product shades.\n   */\n  shadeName: string;\n};\n\n/**\n * Represents the data returned from the Findation widget when a search is completed.\n */\ntype FindationSearchResponse = {\n  /**\n   * The number of shades the user entered in the widget before completing the search\n   */\n  countShadesEntered: number;\n\n  /**\n   * The name of the event that triggered the search. We do see only \"onSearchCompleted\" but not\n   * sure if there are other possible events.\n   */\n  eventName: string;\n\n  /**\n   * A product variant ID of the recommended shade\n   */\n  externalId: string;\n\n  /**\n   * Whether the search was successful in finding a recommended shade for the user based on the\n   * shades they entered.\n   */\n  matchSuccess: boolean;\n\n  /**\n   * A product variant name of the recommended shade\n   */\n  recommendedShade: string;\n\n  /**\n   * An array of the shades the user entered in the widget before completing the search\n   */\n  shadesEntered: Shade[];\n};\n\ntype FindationSearchResponseEvent = CustomEvent<FindationSearchResponse>;\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'findation-widget-button': FindationWidgetButton;\n  }\n\n  interface WindowEventMap {\n    'notify-me-modal-close-requested': Event;\n    'ofir-findation-search-complete': FindationSearchResponseEvent;\n  }\n\n  interface Window {\n    Findation: {\n      iframe: HTMLIFrameElement;\n      init(element: HTMLElement, apiKey: string, options: Record<string, any>): void;\n      onSearchComplete(data: FindationSearchResponse): void;\n      widgetDidClose(): void;\n      widgetDidOpen(): void;\n      widgetEmbedded(iframe: HTMLIFrameElement): void;\n    };\n  }\n}\n\nif (!customElements.get('findation-widget-button')) {\n  customElements.define('findation-widget-button', FindationWidgetButton);\n}\n","// Module\nvar code = \"<slot hidden></slot>\";\n// Exports\nexport default code;","import { CustomElement } from '@integrabeauty/custom-elements';\n\n/**\n * A custom element that manages logic related to displaying product details on PDP.\n */\nclass ProductDetails extends HTMLElement implements CustomElement {\n  readonly dataset!: {\n    /**\n     * Whether the product is a bundle, boolean value represented as a string\n     */\n    isBundle: 'false' | 'true';\n  };\n\n  private onVariantChangedBound = this.onVariantChanged.bind(this);\n\n  public constructor() {\n    super();\n  }\n\n  public connectedCallback() {\n    this.addEventListener('variant-changed', this.onVariantChangedBound);\n  }\n\n  public disconnectedCallback() {\n    this.removeEventListener('variant-changed', this.onVariantChangedBound);\n  }\n\n  private onVariantChanged(event: WindowEventMap['variant-changed']) {\n    const { variant } = event.detail;\n\n    // If the product is a bundle, we don't want to update the price and compare at price on variant\n    // change. In the case of a bundle, the variant-changed event is emitted by a variant selector\n    // component of each subproduct, so the price and compare at price in the event detail are\n    // related to the subproduct variant, not the main product variant. At the moment, we don't\n    // need to support price change on bundle products.\n    if (this.dataset.isBundle !== 'true') {\n      this.updatePrice(variant.price);\n      this.updateCompareAtPrice(variant.compareAtPrice, variant.compareAtPriceModalContent);\n    }\n\n    this.updateTopBadge(variant.topBadge, variant.topBadgeStyle);\n    this.updateProductDescription(variant.categoryDescription);\n  }\n\n  private updatePrice(price: number) {\n    const priceElement = this.querySelector('.price__final');\n    const previousValue = priceElement.textContent || '';\n    priceElement.textContent =\n      previousValue.replace(/\\d+/g, (price / 100).toFixed(0));\n  }\n\n  private updateCompareAtPrice(price: string, modalContent: string) {\n    const compareAtPrice = this.querySelector('.price__compare-at');\n    compareAtPrice.textContent = price || '';\n\n    // create a compare at price info button if needed\n    if (modalContent) {\n      const compareAtPriceInfo = document.createElement('compare-at-price-info');\n      compareAtPriceInfo.dataset.content = modalContent;\n      compareAtPrice.appendChild(compareAtPriceInfo);\n    }\n  }\n\n  private updateTopBadge(value: string, style: string) {\n    type ProductTopBadge = HTMLElementTagNameMap['product-top-badge'];\n    const topBadge = this.querySelector<ProductTopBadge>('product-top-badge');\n    if (!topBadge) {\n      return;\n    }\n\n    topBadge.dataset.value = value;\n    topBadge.dataset.style = style;\n  }\n\n  /**\n   * Updates the product description element with the provided description.\n   * This should cover the variant category alternative description feature. When a variant is\n   * selected that belongs to a category with an alternative description, this description will be\n   * shown instead of the main product description. If there's no alternative description,\n   * the description parameter will be null, and the original product description will be shown.\n   * The original product description is stored in the product-description element's data attribute.\n   */\n  private updateProductDescription(description: string | null) {\n    const descriptionElement = this.querySelector('product-description');\n    if (!descriptionElement) {\n      return;\n    }\n\n    if (description) {\n      descriptionElement.dataset.productDescription = description;\n    } else {\n      const description = descriptionElement.dataset.originalDescription;\n      descriptionElement.dataset.productDescription = description;\n    }\n  }\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'product-details': ProductDetails;\n  }\n}\n\nif (!customElements.get('product-details')) {\n  customElements.define('product-details', ProductDetails);\n}\n","import type { CustomElement } from '@integrabeauty/custom-elements';\nimport html from './index.html';\nimport styles from './index.scss';\n\n/**\n * A custom element that manages displaying the selected variant's details and the functionality\n * for the dropdown variant selector on PDP.\n */\nexport class ProductVariantSelector extends HTMLElement implements CustomElement {\n  readonly dataset!: {\n    /**\n     * Boolean represented as string indicates whether the URL should be updated or not.\n     *\n     * Controls whether this component is allowed to update the url with a new variant parameter\n     * when a new variant is selected. For Lange this happens all the time, but for other brands\n     * where we eventually plan to share this code, this is not always true. For example, on one of\n     * our other brands you can change the selected variant on certain collection pages.\n     *\n     * This is not an observed attribute. We only set this in the connected callback during init and\n     * do not update its value again later. We do not expect it to ever change.\n     */\n    shouldUpdateUrl: 'false' | 'true';\n  };\n\n  private onVariantChangedBound = this.onVariantChanged.bind(this);\n  private onShowOptionsClickedBound = this.onShowOptionsClicked.bind(this);\n\n  constructor() {\n    super();\n    this.attachShadow({ mode: 'open' });\n    this.shadowRoot.innerHTML = `<style>${styles}</style>${html}`;\n  }\n\n  public connectedCallback() {\n    this.render();\n  }\n\n  private render() {\n    const button = this.shadowRoot.querySelector('.show-options');\n    button.addEventListener('click', this.onShowOptionsClickedBound);\n\n    for (const event of product_variant_selector_event_queue) {\n      if (isVariantChangedEvent(event)) {\n        try {\n          this.onVariantChangedBound(event);\n        } catch (error) {\n          console.warn(error);\n        }\n      }\n    }\n\n    this.addEventListener('variant-changed', this.onVariantChangedBound);\n\n    this.shadowRoot.host.classList.remove('hidden');\n  }\n\n  public disconnectedCallback() {\n    const button = this.shadowRoot.querySelector('.show-options');\n    button.removeEventListener('click', this.onShowOptionsClickedBound);\n\n    this.removeEventListener('variant-changed', this.onVariantChangedBound);\n  }\n\n  private onShowOptionsClicked() {\n    const button = this.shadowRoot.querySelector('.show-options');\n    const optionsContainer = this.shadowRoot.querySelector('slot[name=\"variant-selector\"]');\n    const isExpanded = button?.getAttribute('aria-expanded') === 'true';\n\n    if (isExpanded) {\n      button.setAttribute('aria-expanded', 'false');\n      optionsContainer.classList.add('collapsed');\n      optionsContainer.classList.remove('expanded');\n    } else {\n      button.setAttribute('aria-expanded', 'true');\n      optionsContainer.classList.add('expanded');\n      optionsContainer.classList.remove('collapsed');\n    }\n  }\n\n  private onVariantChanged(event: WindowEventMap['variant-changed']) {\n    const variantId = event.detail.variant.id;\n\n    this.updateVariantTitle(event.detail.variant.option);\n    this.updateColorSwatch(event.detail.variant.color);\n\n    if (this.dataset.shouldUpdateUrl === 'true') {\n      updateUrl(variantId.toString());\n    }\n  }\n\n  /**\n   * Updates the selected variant title in the dropdown button on mobile.\n   */\n  private updateVariantTitle(selectedOption: string) {\n    const dropdownText =\n      this.shadowRoot.querySelector<HTMLElement>('.selected-variant');\n\n    dropdownText.textContent = selectedOption;\n    dropdownText.setAttribute('aria-label', `Selected variant: ${selectedOption}`);\n  }\n\n  /**\n   * Updates the color title in the dropdown button on mobile.\n   */\n  private updateColorSwatch(color: string) {\n    const swatch = this.shadowRoot.querySelector<HTMLElement>('.swatch');\n\n    if (color) {\n      swatch.style.backgroundColor = color;\n      swatch.classList.remove('hidden');\n    } else {\n      swatch.style.backgroundColor = null;\n      swatch.classList.add('hidden');\n    }\n  }\n}\n\nfunction updateUrl(variantId: string) {\n  const url = new URL(location.href);\n  const variantSearchParam = url.searchParams.get('variant');\n  if (variantSearchParam === variantId) {\n    // When the page loads, there might be a \"variant\" search parameter. If it matches the\n    // currently selected variant ID, don’t do anything.\n    return;\n  }\n\n  url.searchParams.set('variant', variantId.toString());\n  window.history.replaceState({}, '', url);\n\n  const historyEvent = new Event('history-change', { cancelable: true });\n  dispatchEvent(historyEvent);\n}\n\nfunction isVariantChangedEvent(value: any): value is WindowEventMap['variant-changed'] {\n  return value?.type === 'variant-changed';\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'product-variant-selector': ProductVariantSelector;\n  }\n\n  // eslint-disable-next-line @typescript-eslint/naming-convention\n  var product_variant_selector_event_queue: Event[];\n  // eslint-disable-next-line @typescript-eslint/naming-convention\n  var product_variant_selector_event_listener: (event: Event)=> void;\n}\n\nif (!customElements.get('product-variant-selector')) {\n  customElements.define('product-variant-selector', ProductVariantSelector);\n}\n","export default \"*{box-sizing:border-box}:host{display:inline-flex;flex-direction:column-reverse}@media only screen and (min-width:992px){:host{flex-direction:column}}.show-options{align-items:center;appearance:none;background-color:#0000;border:1px solid #1e1e1e;color:#1e1e1e;column-gap:4px;cursor:pointer;display:flex;flex-grow:1;font-family:inherit;font-size:.875rem;justify-content:space-between;line-height:1;min-height:48px;padding:8px;text-align:left}@media only screen and (min-width:768px){.show-options{display:none}}.show-options:focus{outline:2px solid #000;outline-offset:1px}.show-options svg{flex-shrink:0;transform:rotate(180deg);width:10px}@media only screen and (min-width:768px){.show-options svg{width:auto}}@media only screen and (min-width:992px){.show-options svg{transform:rotate(0)}}.show-options[aria-expanded=true] svg{transform:rotate(0)}@media only screen and (min-width:992px){.show-options[aria-expanded=true] svg{transform:rotate(180deg)}}.swatch{border-radius:100px;display:inline-block;flex-shrink:0;height:18px;width:18px}@media only screen and (min-width:768px){.swatch{height:24px;width:24px}}.selected-variant{line-height:1.3;margin-right:auto;max-width:100%;overflow:hidden;overflow-wrap:break-word}slot[name=variant-selector]{animation-duration:.2s;animation-fill-mode:forwards;animation-timing-function:ease;border:1px solid #1e1e1e;display:block;margin-bottom:16px;overflow:hidden;padding:8px 12px;width:calc(200% + 8px)}@media only screen and (min-width:768px){slot[name=variant-selector]{border:none;border-top:1px solid #dbdbdb;font-size:.875rem;margin-bottom:0;margin-top:24px;overflow:visible;padding:24px 0 0;width:auto}}@media only screen and (min-width:992px){slot[name=variant-selector]{font-size:1rem;margin-top:16px}}slot[name=variant-selector].expanded{animation-name:expand}slot[name=variant-selector].collapsed{animation-name:collapse}.hidden{display:none}@keyframes expand{0%{max-height:0;transform:scaleY(0);visibility:hidden}to{max-height:500px;transform:scaleY(1);visibility:visible}}@keyframes collapse{0%{max-height:500px;transform:scaleY(1);visibility:visible}to{border-width:0;margin:0;max-height:0;padding:0;transform:scaleY(0);visibility:hidden}}\";","// Module\nvar code = \"<button class=\\\"show-options\\\" aria-expanded=\\\"true\\\" aria-controls=\\\"variant-selector\\\"><span class=\\\"swatch hidden\\\" role=\\\"img\\\"></span><span class=\\\"selected-variant\\\" role=\\\"img\\\"></span><svg role=\\\"presentation\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"14\\\" height=\\\"9\\\" viewBox=\\\"0 0 14 9\\\" fill=\\\"none\\\"><path d=\\\"M13 1L7 8L1 0.999998\\\" stroke=\\\"#1E1E1E\\\" stroke-linecap=\\\"square\\\" stroke-linejoin=\\\"round\\\"/></svg></button><slot id=\\\"variant-selector\\\" name=\\\"variant-selector\\\"></slot>\";\n// Exports\nexport default code;","import type { CustomElement } from '@integrabeauty/custom-elements';\nimport styles from './index.scss';\n\n/**\n * A sticky call-to-action component on PDP that becomes fixed at the bottom of the viewport on\n * mobile devices.\n */\nclass StickyCTA extends HTMLElement implements CustomElement {\n  private mediaQuery: MediaQueryList;\n  private matchesMediaQuery: boolean;\n\n  private onVariantChangedBound = this.onVariantChanged.bind(this);\n  private onDOMContentLoadedBound = this.onDOMContentLoaded.bind(this);\n  private updateElementsBasedOnViewportBound = this.updateElementsBasedOnViewport.bind(this);\n\n  constructor() {\n    super();\n    this.mediaQuery = window.matchMedia('(max-width: 767px)');\n    this.matchesMediaQuery = false;\n  }\n\n  public connectedCallback() {\n    const styleElement = document.createElement('style');\n    styleElement.textContent = styles;\n    this.append(styleElement);\n    this.addEventListener('variant-changed', this.onVariantChangedBound);\n\n    if (document.readyState === 'complete' || document.readyState === 'interactive') {\n      setTimeout(this.onDOMContentLoadedBound);\n    } else {\n      addEventListener('DOMContentLoaded', this.onDOMContentLoadedBound);\n    }\n  }\n\n  public disconnectedCallback() {\n    this.removeEventListener('variant-changed', this.onVariantChangedBound);\n    this.mediaQuery.removeEventListener('change', this.updateElementsBasedOnViewportBound);\n    removeEventListener('DOMContentLoaded', this.onDOMContentLoadedBound);\n  }\n\n  private onDOMContentLoaded(_event: Event) {\n    this.mediaQuery.addEventListener('change', this.updateElementsBasedOnViewportBound);\n    this.updateElementsBasedOnViewport();\n    this.removeEventListener('DOMContentLoaded', this.onDOMContentLoadedBound);\n  }\n\n  private updateElementsBasedOnViewport() {\n    if (this.mediaQuery.matches === this.matchesMediaQuery) {\n      return;\n    }\n\n    this.matchesMediaQuery = this.mediaQuery.matches;\n    if (this.matchesMediaQuery) {\n      document.querySelector<HTMLElement>('#shopify-section-footer').style.paddingBottom =\n        this.offsetHeight + 'px';\n    } else {\n      document.querySelector<HTMLElement>('#shopify-section-footer').style.paddingBottom =\n        '';\n    }\n  }\n\n  private onVariantChanged(event: WindowEventMap['variant-changed']) {\n    const discountMessage = this.querySelector('discount-message');\n    if (!discountMessage) {\n      return;\n    }\n\n    discountMessage.dataset.message = event.detail.variant.discountMessage;\n  }\n}\n\nif (!customElements.get('sticky-cta')) {\n  customElements.define('sticky-cta', StickyCTA);\n}\n","export default \"sticky-cta{display:flex;flex-wrap:wrap;gap:16px;width:100%}@media only screen and (min-width:768px){sticky-cta{flex-direction:column;max-width:670px}}@media(max-width:767px){sticky-cta{align-items:flex-end;background-color:#fff;border-top:1px solid #0003;bottom:0;column-gap:8px;display:flex;left:0;padding:16px;position:fixed;z-index:50}#shopify-section-footer{padding-bottom:100px}}@media(min-width:768px){sticky-cta{align-items:flex-end}}@media(min-width:992px){sticky-cta{align-items:flex-start}}sticky-cta .product-v2__backorder{color:#616161;display:block;font-size:.75rem;margin-bottom:-8px;text-align:center;width:100%}@media only screen and (min-width:768px){sticky-cta .product-v2__backorder{font-size:.875rem;margin-bottom:0}}.product-v2__actions{width:100%}findation-widget-button .cta{border-color:#e6e7e8;margin-top:16px}@media only screen and (min-width:768px){findation-widget-button .cta{margin-top:32px}}sticky-cta product-variant-selector,sticky-cta product-variant-selector~.product-v2__actions{width:calc(50% - 4px)}@media only screen and (min-width:768px){sticky-cta product-variant-selector,sticky-cta product-variant-selector~.product-v2__actions{width:100%}}\";","import html from './index.html';\nimport styles from './index.scss';\n\n/**\n * Custom element that renders a set's subproduct and handles image updates based on the selected\n * variant.\n */\nclass SetsSubproduct extends HTMLElement {\n  private onVariantChangedBound = this.onVariantChanged.bind(this);\n  public shadowRoot!: ShadowRoot;\n\n  public constructor() {\n    super();\n    this.attachShadow({ mode: 'open' });\n    this.shadowRoot.innerHTML = `<style>${styles}</style>${html}`;\n  }\n\n  public connectedCallback() {\n    this.addEventListener('variant-changed', this.onVariantChangedBound);\n  }\n\n  public disconnectedCallback() {\n    this.removeEventListener('variant-changed', this.onVariantChangedBound);\n  }\n\n  private onVariantChanged(event: WindowEventMap['variant-changed']) {\n    const imageSrc = event.detail.variant.image;\n    const image = this.querySelector('img[slot=\"image\"]');\n    image.setAttribute('src', imageSrc);\n  }\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'sets-subproduct': SetsSubproduct;\n  }\n}\n\nif (!customElements.get('sets-subproduct')) {\n  customElements.define('sets-subproduct', SetsSubproduct);\n}\n","export default \":host{display:flex;min-height:112px;padding-bottom:12px;padding-top:8px;text-align:left;width:100%}slot[name=image]{display:block;flex-shrink:0;height:100px;width:100px}::slotted([slot=image]){object-fit:contain;object-position:center}.main{flex-grow:1;padding-left:4px}.header{align-items:center;display:flex;justify-content:space-between;margin-bottom:4px}.title{font-size:.875rem;margin-bottom:0;margin-top:0}slot[name=rating]{display:block;margin-top:-7px}slot[name=subtitle]{font-size:.875rem}slot[name=variant-selector]{display:block;font-size:.875rem;margin-top:12px}\";","// Module\nvar code = \"<slot name=\\\"image\\\"></slot><div class=\\\"main\\\"><div class=\\\"header\\\"><h3 class=\\\"title\\\"><slot name=\\\"title\\\"></slot></h3><slot name=\\\"rating\\\"></slot></div><slot name=\\\"subtitle\\\"></slot><slot name=\\\"variant-selector\\\"></slot></div>\";\n// Exports\nexport default code;","import type { CustomElement } from '@integrabeauty/custom-elements';\nimport html from './index.html';\nimport styles from './index.scss';\n\n/**\n * This component renders a product description. If in mobile view and the description visually\n * spans more than two lines, it will be truncated with an option to expand the view.\n */\nclass ProductDescription extends HTMLElement implements CustomElement {\n  public static get observedAttributes() {\n    return [\n      'data-product-description'\n    ];\n  }\n\n  readonly dataset: {\n    /**\n     * The original description of a product.\n     * Used to reset the description if needed. It's a possible case when variant categories are\n     * used and one of the categories misses a description, so the original product description\n     * should be restored. Also, it's technically possible that there are be variants without\n     * categories among other variants with categories. We don't expect this to happen, but just in\n     * case.\n     */\n    originalDescription: string;\n\n    /**\n     * The description of a product.\n     * Can be updated dynamically when the variant changes.\n     */\n    productDescription: string;\n  };\n\n  public shadowRoot!: ShadowRoot;\n  private listenersInitialized = false;\n\n  private onClickReadMoreBound = this.onClickReadMore.bind(this);\n\n  constructor() {\n    super();\n    this.attachShadow({ mode: 'open' });\n    this.shadowRoot.innerHTML = `<style>${styles}</style>${html}`;\n  }\n\n  public connectedCallback() {\n    this.render();\n  }\n\n  public disconnectedCallback() {\n    const readMore = this.shadowRoot.querySelector('.read-more');\n    readMore.removeEventListener('click', this.onClickReadMoreBound);\n  }\n\n  public attributeChangedCallback(_name: string, _oldValue: string, _newValue: string) {\n    this.render();\n  }\n\n  private render() {\n    if (!this.listenersInitialized) {\n      this.listenersInitialized = true;\n\n      const readMore = this.shadowRoot.querySelector('.read-more');\n      readMore.addEventListener('click', this.onClickReadMoreBound);\n    }\n\n    const description = this.shadowRoot.querySelector<HTMLElement>('.description');\n    description.innerHTML = this.dataset.productDescription;\n  }\n\n  private onClickReadMore(event: Event) {\n    event.preventDefault();\n\n    const host = <HTMLElement>this.shadowRoot.host;\n    const readMore = this.shadowRoot.querySelector<HTMLElement>('.read-more');\n    const readMoreLabel = readMore.querySelector('span');\n\n    if (host.dataset.expanded === 'true') {\n      host.removeAttribute('data-expanded');\n      readMore.setAttribute('aria-expanded', 'false');\n      readMoreLabel.textContent = 'Read More';\n    } else {\n      host.setAttribute('data-expanded', 'true');\n      readMore.setAttribute('aria-expanded', 'true');\n      readMoreLabel.textContent = 'Read Less';\n    }\n  }\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'product-description': ProductDescription;\n  }\n}\n\nif (!customElements.get('product-description')) {\n  customElements.define('product-description', ProductDescription);\n}\n","export default \":host{font-size:.875rem;line-height:1.5}:host([data-expanded=true]) .description{max-height:none;overflow:initial}:host([data-expanded=true]) .read-more{display:flex}:host([data-expanded=true]) svg{transform:rotate(180deg)}strong{font-weight:600}.description{display:flex;flex-direction:column;gap:1em;max-height:3em;overflow:hidden}.description *{margin:0;padding:0}.description a{color:currentcolor;text-decoration:underline}.description a:hover{text-decoration:none}@media screen and (min-width:1024px){.description{max-height:none;overflow:initial}}.read-more{align-items:center;background-color:#0000;border:none;border-radius:0;color:currentcolor;cursor:pointer;display:flex;font-family:inherit;font-size:inherit;font-weight:600;justify-content:space-between;margin-top:4px;padding:0;text-decoration:underline;width:100%}@media screen and (min-width:1024px){.read-more{display:none}}\";","// Module\nvar code = \"<div id=\\\"description\\\" class=\\\"description\\\"></div><button class=\\\"read-more\\\" aria-expanded=\\\"false\\\" aria-controls=\\\"description\\\"><span>Read More</span><svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"14\\\" height=\\\"9\\\" viewBox=\\\"0 0 14 9\\\" fill=\\\"none\\\"><path d=\\\"M13 1L7 8L1 0.999998\\\" stroke=\\\"#1E1E1E\\\" stroke-linecap=\\\"square\\\" stroke-linejoin=\\\"round\\\"/></svg></button>\";\n// Exports\nexport default code;","import type { CustomElement } from '@integrabeauty/custom-elements';\nimport html from './index.html';\nimport styles from './index.scss';\n\n/**\n * Renders product related countdown timer. It is used in a product template context.\n */\nclass ProductDetailCountdownTimer extends HTMLElement implements CustomElement {\n  public static get observedAttributes() {\n    return [\n      'data-end-time',\n      'data-start-time'\n    ];\n  }\n\n  readonly dataset!: {\n    /**\n     * Stop time as unix epoch time.\n     *\n     * @see https://www.epochconverter.com\n     */\n    endTime: string;\n\n    /**\n     * Start time as unix epoch time.\n     *\n     * @see https://www.epochconverter.com\n     */\n    startTime: string;\n  };\n\n  public shadowRoot!: ShadowRoot;\n  private endTime?: number;\n  private startTime?: number;\n  private timer?: ReturnType<typeof setInterval>;\n  private timeRemainingElement?: HTMLElement;\n  private listenersInitialized = false;\n\n  constructor() {\n    super();\n    this.hide();\n    this.attachShadow({ mode: 'open' });\n    this.shadowRoot.innerHTML = `<style>${styles}</style>${html}`;\n  }\n\n  public connectedCallback() {\n    this.render();\n  }\n\n  public attributeChangedCallback(name: string, _oldValue: string, newValue: string) {\n    switch (name) {\n      case 'data-start-time':\n        this.startTime = parseInt(newValue, 10) * 1000;\n        break;\n      case 'data-end-time':\n        this.endTime = parseInt(newValue, 10) * 1000;\n        break;\n    }\n\n    this.render();\n  }\n\n  private render() {\n    if (!this.listenersInitialized) {\n      this.listenersInitialized = true;\n\n      this.timeRemainingElement = this.shadowRoot.querySelector<HTMLElement>('.time-remaining');\n    }\n\n    if (!this.isConnected || !this.startTime || !this.endTime) {\n      return;\n    }\n\n    const nowTime = Date.now();\n\n    if (nowTime < this.startTime) {\n      return;\n    }\n\n    if (nowTime >= this.endTime) {\n      return;\n    }\n\n    this.show();\n    clearInterval(this.timer);\n    this.timer = setInterval(this.renderTime.bind(this), 100);\n  }\n\n  private renderTime() {\n    const nowTime = Date.now();\n    if (this.endTime - nowTime < 0) {\n      this.hide();\n      clearInterval(this.timer);\n      return;\n    }\n\n    const remaining = getTimeRemaining(this.endTime, nowTime);\n    const daysRemaining = remaining.days > 0 ?\n      `${remaining.days} ${remaining.days === 1 ? 'day' : 'days'}` :\n      '';\n    const timeRemaining = formatTime(remaining.hours, remaining.minutes,\n      remaining.seconds);\n\n    this.timeRemainingElement.textContent = `${daysRemaining} ${timeRemaining}`;\n  }\n\n  /**\n   * Hide the whole component.\n   */\n  private hide() {\n    this.style.display = 'none';\n  }\n\n  /**\n   * Show the whole component.\n   */\n  private show() {\n    this.style.display = null;\n  }\n}\n\nfunction formatTime(hours: number, minutes: number, seconds: number) {\n  const h = hours.toString();\n  const m = minutes.toString();\n  const s = seconds.toString();\n  return `${h}h ${m}m ${s}s`;\n}\n\nfunction getTimeRemaining(endingMs: number, currentMs: number) {\n  let timeRemainingSeconds = (endingMs - currentMs) / 1000;\n\n  const days = Math.floor(timeRemainingSeconds / 86400);\n  timeRemainingSeconds -= days * 86400;\n\n  const hours = Math.floor(timeRemainingSeconds / 3600) % 24;\n  timeRemainingSeconds -= hours * 3600;\n\n  const minutes = Math.floor(timeRemainingSeconds / 60) % 60;\n  timeRemainingSeconds -= minutes * 60;\n\n  const seconds = Math.floor(timeRemainingSeconds % 60);\n\n  return {\n    days,\n    hours,\n    minutes,\n    seconds\n  };\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'product-detail-countdown-timer': ProductDetailCountdownTimer;\n  }\n}\n\nif (!customElements.get('product-detail-countdown-timer')) {\n  customElements.define('product-detail-countdown-timer', ProductDetailCountdownTimer);\n}\n","export default \":host{display:block;font-size:.875rem}.time-remaining{color:#7c0d3f;font-weight:600;margin-left:8px}\";","// Module\nvar code = \"Sale Ends in<time class=\\\"time-remaining\\\"></time>\";\n// Exports\nexport default code;","import { CustomElement } from '@integrabeauty/custom-elements';\nimport html from './index.html';\nimport styles from './index.scss';\n\n/**\n * A custom element that displays a zoomable image when clicked.\n *\n * It should only be used on devices that support hover and have a minimum width of 768px. We don't\n * need this feature on mobile devices as users can pinch to zoom.\n */\nclass ZoomableImage extends HTMLElement implements CustomElement {\n  readonly dataset!: {\n    /**\n     * The scale coefficient of the zoomable image, number represented as a string, e.g. \"1.5\"\n     * Defaults to \"2\" if not set or invalid.\n     */\n    scale: string;\n\n    /**\n     * The URL of the large zoomable image.\n     */\n    zoomableImage: string;\n  };\n\n  private onClickedBound = this.onClicked.bind(this);\n  private onMouseEnterBound = this.onMouseEnter.bind(this);\n  private onMouseLeaveBound = this.onMouseLeave.bind(this);\n  private onMouseMoveBound = this.onMouseMove.bind(this);\n  private onMediaQueryChangeBound = this.onMediaQueryChange.bind(this);\n\n  public shadowRoot!: ShadowRoot;\n  private animationFrameId: number | null = null;\n  private isPreloaded = false;\n  private state: 'zoomedIn' | 'zoomedOut' = 'zoomedOut';\n  private imageContainer: HTMLDivElement | null = null;\n  private mediaQuery = matchMedia('(hover: hover) and (min-width: 768px)');\n\n  public constructor() {\n    super();\n    this.attachShadow({ mode: 'open' });\n    this.shadowRoot.innerHTML = `<style>${styles}</style>${html}`;\n  }\n\n  public connectedCallback() {\n    if (this.mediaQuery.matches) {\n      this.addEventListeners();\n    }\n\n    this.mediaQuery.addEventListener('change', this.onMediaQueryChangeBound);\n  }\n\n  public disconnectedCallback() {\n    this.removeEventListeners();\n  }\n\n  private addEventListeners() {\n    this.addEventListener('click', this.onClickedBound);\n    this.addEventListener('mouseenter', this.onMouseEnterBound);\n    this.addEventListener('mouseleave', this.onMouseLeaveBound);\n    this.addEventListener('mousemove', this.onMouseMoveBound);\n  }\n\n  private removeEventListeners() {\n    this.removeEventListener('click', this.onClickedBound);\n    this.removeEventListener('mouseenter', this.onMouseEnterBound);\n    this.removeEventListener('mouseleave', this.onMouseLeaveBound);\n  }\n\n  private onMediaQueryChange(event: MediaQueryListEvent) {\n    if (event.matches) {\n      this.addEventListeners();\n    } else {\n      this.removeEventListeners();\n      if (this.state === 'zoomedIn') {\n        this.hideImage();\n      }\n    }\n  }\n\n  private onClicked(_event: Event) {\n    if (this.state === 'zoomedOut') {\n      this.showImage();\n    } else if (this.state === 'zoomedIn') {\n      this.hideImage();\n    }\n  }\n\n  /**\n   * Preload the zoomable image on mouse enter. It improves user experience by reducing the delay\n   * when the user clicks to zoom in and sees the large image.\n   */\n  private onMouseEnter(_event: Event) {\n    // preload only once\n    if (this.isPreloaded) {\n      return;\n    }\n\n    preloadImage(this.dataset.zoomableImage);\n    this.removeEventListener('mouseenter', this.onMouseEnter);\n  }\n\n  private onMouseLeave(_event: Event) {\n    if (this.state === 'zoomedIn') {\n      this.hideImage();\n    }\n  }\n\n  private onMouseMove(event: MouseEvent) {\n    if (!this.imageContainer) {\n      return;\n    }\n\n    if (this.animationFrameId) {\n      cancelAnimationFrame(this.animationFrameId);\n    }\n\n    this.animationFrameId = requestAnimationFrame(() => {\n      // it's possible that the imageContainer is null when the animation frame is executed\n      if (!this.imageContainer) {\n        return;\n      }\n\n      const translateX = (event.offsetX * 100) / this.offsetWidth;\n      const translateY = (event.offsetY * 100) / this.offsetHeight;\n      this.imageContainer.style.backgroundPosition =\n        `${translateX.toFixed(2)}% ${translateY.toFixed(2)}%`;\n    });\n  }\n\n  private showImage() {\n    this.state = 'zoomedIn';\n\n    if (!this.dataset.zoomableImage) {\n      return;\n    }\n\n    const div = document.createElement('div');\n    div.style.backgroundImage = `url(${this.dataset.zoomableImage})`;\n\n    // default to 2 if not a valid number\n    const scale = parseFloat(this.dataset.scale) || 2;\n    div.style.backgroundSize = `${scale * 100}%`;\n\n    this.shadowRoot.appendChild(div);\n    this.imageContainer = div;\n  }\n\n  private hideImage() {\n    this.state = 'zoomedOut';\n\n    const imageContainer = this.shadowRoot.querySelector('div');\n    if (imageContainer) {\n      this.shadowRoot.removeChild(imageContainer);\n    }\n\n    this.imageContainer = null;\n  }\n}\n\nfunction preloadImage(src: string) {\n  const img = new Image();\n  img.src = src;\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'zoomable-image': ZoomableImage;\n  }\n}\n\nif (!customElements.get('zoomable-image')) {\n  customElements.define('zoomable-image', ZoomableImage);\n}\n","export default \":host{display:block;position:relative}@media only screen and (min-width:768px)and (hover:hover){:host{cursor:zoom-in}}div{background-position:50% 50%;background-repeat:no-repeat;background-size:150%;cursor:zoom-out;display:block;height:100%;left:50%;position:absolute;top:50%;transform:translate(-50%,-50%);width:100%;z-index:2}\";","// Module\nvar code = \"<slot></slot>\";\n// Exports\nexport default code;","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\n * slide 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    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\n   * to slider size, also 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\n   * to 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\n    // to 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\n   *   the slider is moved to a certain slide because the position at the end of moving should be\n   *   taken 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  return {\n    mount\n  };\n}\n","import '../../lib/webpack-path';\nimport type Splide from '@splidejs/splide';\nimport { splideSlidebarExtension } from '../../lib/splide-slidebar-extension';\n\nlet productId: number;\nlet mainSplide: Splide;\nlet navSplide: Splide;\nlet mainImages: HTMLElement;\nlet navImages: HTMLElement;\n\nfunction showAndFadeOutCountIndicator() {\n  const elems = document.querySelectorAll('.splide__count-indicator');\n  if (elems.length === 0) {\n    return;\n  }\n\n  for (const elem of elems) {\n    elem.classList.remove('fade-out');\n  }\n\n  setTimeout(() => {\n    for (const elem of elems) {\n      elem.classList.add('fade-out');\n    }\n  }, 1000);\n}\n\nfunction recalculateCarousel() {\n  const gallery = document.getElementById('product-image-gallery');\n  if (!gallery) {\n    return;\n  }\n\n  gallery.style.cssText = '';\n}\n\nfunction onDOMContentLoaded() {\n  const mainCarousel = document.querySelector('.splide--product-gallery-main-carousel');\n  if (!mainCarousel) {\n    return;\n  }\n\n  const gallery = document.querySelector<HTMLElement>('#product-image-gallery');\n  productId = parseInt(gallery.dataset.productId, 10);\n  if (!productId) {\n    return;\n  }\n\n  initCarousel()\n    .then(() => {\n      recalculateCarousel();\n    })\n    .catch(console.warn);\n\n  addEventListener('resize', recalculateCarousel);\n\n  // Listen only to events from the PDP variant selector. It prevents collisions between a product\n  // card with the same product on the page, e.g. in the predictive search or recommended products,\n  // and the product details.\n  const productPage = document.querySelector<HTMLElement>('.product-v2');\n  productPage.addEventListener('variant-changed', onVariantChanged);\n}\n\nfunction onVariantChanged(event: WindowEventMap['variant-changed']) {\n  const detail = event.detail;\n\n  // We need this check for the bundles. Currently, on the PDP of a bundle product, we have\n  // multiple variant selectors for each subproduct, and each of them emits the\n  // `variant-changed` event with the detail.product_id related NOT to the main product. So we need\n  // to make sure that we update the carousel only when the event is emitted by the variant selector\n  // of the main product. It happens on a regular PDP or on a bundle PDP when there's only one\n  // variant selector related to the main product.\n  if (detail.variant.product_id !== productId) {\n    return;\n  }\n\n  updateCarouselImages(detail.variant.id.toString());\n}\n\nfunction updateCarouselImages(variantId: string) {\n  // Update images per variant on main carousel\n  mainSplide.Components.Slides.remove(item => item.slide.dataset.variantId);\n  let index = 0;\n  const variantMainImages =\n    mainImages.querySelectorAll(`[data-variant-id=\"${variantId}\"]`);\n  for (const slide of variantMainImages) {\n    const newSlide = <HTMLElement>(slide.cloneNode(true));\n    mainSplide.Components.Slides.add(newSlide, index++);\n  }\n\n  const singleImage = variantMainImages.length <= 1;\n  const mainSliderFooter = mainSplide.Components.Elements.root.querySelector('.splide__footer');\n  if (singleImage) {\n    mainSliderFooter.classList.add('hidden');\n  } else {\n    mainSliderFooter.classList.remove('hidden');\n  }\n\n  // Update images per variant on nav carousel\n  if (navSplide) {\n    if (singleImage) {\n      navSplide.Components.Elements.root.classList.add('hidden');\n    } else {\n      navSplide.Components.Elements.root.classList.remove('hidden');\n    }\n\n    navSplide.Components.Slides.remove(item => item.slide.dataset.variantId);\n    let index = 0;\n    const variantNavImages =\n      navImages.querySelectorAll(`[data-variant-id=\"${variantId}\"]`);\n    for (const slide of variantNavImages) {\n      const newSlide = <HTMLElement>(slide.cloneNode(true));\n      navSplide.Components.Slides.add(newSlide, index++);\n    }\n  }\n\n  // Scroll to first slide\n  mainSplide.go(0);\n}\n\nasync function initCarousel() {\n  const { Splide } = await import('@splidejs/splide');\n  const mainCarousel =\n    document.querySelector<HTMLElement>('.splide--product-gallery-main-carousel');\n\n  // Cache main carousel markup\n  mainImages = document.createElement('div');\n  mainImages.innerHTML = mainCarousel.innerHTML;\n\n  // Init main carousel\n  mainSplide = new Splide(mainCarousel, {\n    type: 'fade',\n    perPage: 1,\n    perMove: 1,\n    rewind: true,\n    pagination: false,\n    arrows: true,\n    lazyLoad: 'nearby',\n    mediaQuery: 'min',\n    slidebar: true,\n    breakpoints: {\n      768: {\n        arrows: false,\n        slidebar: false\n      }\n    }\n  });\n\n  const navCarousel = document.querySelector('.splide--product-gallery-nav-carousel');\n  if (navCarousel) {\n    // Cache nav carousel markup\n    navImages = document.createElement('div');\n    navImages.innerHTML = navCarousel.innerHTML;\n\n    navSplide = new Splide(<HTMLElement>navCarousel, {\n      fixedWidth: 85,\n      fixedHeight: 85,\n      gap: 12,\n      perMove: 1,\n      rewind: true,\n      pagination: false,\n      isNavigation: true,\n      arrows: true,\n      lazyLoad: 'nearby',\n      keyboard: true,\n      breakpoints: {\n        767: {\n          // SPLIDE BUG regarding `destroy: true`\n          // @see https://github.com/Splidejs/splide/issues/1268\n          // I reported this bug, but temporarily we are leveraging CSS to hide\n          // the nav carousel so it doesn't break syncing after resize.\n          // destroy: true\n        },\n        768: {\n          arrows: false\n        }\n      }\n    });\n  }\n\n  // Pause video when slide is not active\n  mainSplide.on('move', (newIndex, prevIndex) => {\n    showAndFadeOutCountIndicator();\n    const oldSlideContainer = mainSplide.Components.Slides.getAt(prevIndex);\n    const video = oldSlideContainer?.slide.querySelector('video');\n    if (video && !video.paused) {\n      video.pause();\n    }\n  });\n\n  // Start to play video when slide became active\n  mainSplide.on('moved', (newIndex, prevIndex, destIndex) => {\n    showAndFadeOutCountIndicator();\n    const newSlideContainer = mainSplide.Components.Slides.getAt(destIndex);\n    const video = newSlideContainer?.slide.querySelector('video');\n    video?.play().catch(console.warn);\n  });\n\n  // Mount carousels\n  // Order specific per\n  // @see https://splidejs.com/guides/apis/#sync\n  if (navSplide) {\n    mainSplide.sync(navSplide);\n  }\n\n  mainSplide.mount({\n    splideSlidebarExtension\n  });\n\n  type Detail = WindowEventMap['product-carousel-initialized']['detail'];\n  const event = new CustomEvent<Detail>('product-carousel-initialized', {\n    detail: { splide: mainSplide }\n  });\n  dispatchEvent(event);\n\n  if (navSplide) {\n    navSplide.mount();\n  }\n\n  // Update carousel according to the selected variant if applicable\n  const selectedVariant = mainCarousel.dataset.selectedVariant;\n  const hasVariantImages = mainCarousel.dataset.hasVariantImages === 'true';\n  if (selectedVariant && hasVariantImages) {\n    updateCarouselImages(selectedVariant);\n  }\n}\n\n/**\n * Occurs when a product image gallery is initialized on a PDP page.\n */\ntype ProductCarouselInitializedEvent = CustomEvent<{\n  splide: Splide;\n}>;\n\ndeclare global {\n  interface WindowEventMap {\n    'product-carousel-initialized': ProductCarouselInitializedEvent;\n  }\n}\n\naddEventListener('DOMContentLoaded', onDOMContentLoaded);\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\n   * do 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"],"names":["inProgress","dataWebpackPrefix","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","module","__webpack_modules__","m","d","definition","key","o","Object","defineProperty","enumerable","get","f","e","chunkId","Promise","all","keys","reduce","promises","u","miniCssF","obj","prop","prototype","hasOwnProperty","call","l","url","done","push","script","needAttach","scripts","document","getElementsByTagName","i","length","s","getAttribute","createElement","charset","timeout","nc","setAttribute","src","onScriptComplete","prev","event","onerror","onload","clearTimeout","doneFns","parentNode","removeChild","forEach","fn","setTimeout","bind","type","target","head","appendChild","p","installedChunks","j","installedChunkData","promise","resolve","reject","error","Error","errorType","realSrc","message","name","request","webpackJsonpCallback","parentChunkLoadingFunction","data","chunkIds","moreModules","runtime","some","id","chunkLoadingGlobal","self","PairedProduct","HTMLElement","constructor","super","this","attachShadow","mode","shadowRoot","innerHTML","concat","customElements","define","FindationWidgetButton","shouldOpenModal","onWidgetEmbeddedBound","onWidgetEmbedded","onDOMContentLoadedBound","onDOMContentLoaded","onWidgetOpenedBound","onWidgetOpened","onWidgetClosedBound","onWidgetClosed","onAdClickedBound","onAdClicked","connectedCallback","window","Findation","addEventListener","onMessage","readyState","ofir","queue","disconnectedCallback","removeEventListener","querySelector","onButtonClicked","_event","isConnected","render","widgetEmbedded","widgetDidOpen","widgetDidClose","onSearchComplete","onSearchCompleted","placeholder","style","display","init","iframe","hidden","Event","cancelable","dispatchEvent","postMessage","detail","findationModal","CustomEvent","matchSuccess","contentWindow","externalId","_event$data","_event$data2","_event$data3","location","href","origin","pathname","ProductDetails","onVariantChangedBound","onVariantChanged","variant","dataset","isBundle","updatePrice","price","updateCompareAtPrice","compareAtPrice","compareAtPriceModalContent","updateTopBadge","topBadge","topBadgeStyle","updateProductDescription","categoryDescription","priceElement","previousValue","textContent","replace","toFixed","modalContent","compareAtPriceInfo","content","value","description","descriptionElement","productDescription","originalDescription","ProductVariantSelector","onShowOptionsClickedBound","onShowOptionsClicked","product_variant_selector_event_queue","isVariantChangedEvent","console","warn","host","classList","remove","button","optionsContainer","add","variantId","updateVariantTitle","option","updateColorSwatch","color","shouldUpdateUrl","URL","searchParams","set","toString","history","replaceState","historyEvent","updateUrl","selectedOption","dropdownText","swatch","backgroundColor","StickyCTA","updateElementsBasedOnViewportBound","updateElementsBasedOnViewport","mediaQuery","matchMedia","matchesMediaQuery","styleElement","append","matches","paddingBottom","offsetHeight","discountMessage","SetsSubproduct","imageSrc","image","ProductDescription","observedAttributes","listenersInitialized","onClickReadMoreBound","onClickReadMore","attributeChangedCallback","_name","_oldValue","_newValue","preventDefault","readMore","readMoreLabel","expanded","removeAttribute","ProductDetailCountdownTimer","hide","newValue","startTime","parseInt","endTime","timeRemainingElement","nowTime","Date","now","show","clearInterval","timer","setInterval","renderTime","remaining","endingMs","currentMs","timeRemainingSeconds","days","Math","floor","hours","minutes","seconds","getTimeRemaining","daysRemaining","timeRemaining","h","formatTime","ZoomableImage","onClickedBound","onClicked","onMouseEnterBound","onMouseEnter","onMouseLeaveBound","onMouseLeave","onMouseMoveBound","onMouseMove","onMediaQueryChangeBound","onMediaQueryChange","animationFrameId","isPreloaded","state","imageContainer","addEventListeners","removeEventListeners","hideImage","showImage","zoomableImage","Image","cancelAnimationFrame","requestAnimationFrame","translateX","offsetX","offsetWidth","translateY","offsetY","backgroundPosition","div","backgroundImage","scale","parseFloat","backgroundSize","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","transform","alignTrackPosition","index","round","currentSplidePosition","getPosition","toIndex","Controller","go","onSplideOptionsUpdated","_options","toggleSlidebar","onSplideReady","isEnough","isOverflow","onMousemove","onMouseup","movementX","touch","touches","clientX","onTouchmove","onTouchend","transition","currentTarget","newSlidebarPosition","newTrackPosition","width","onSplideOverflowed","getCalculatedSlidebarPosition","trackPosition","getEnd","getIndex","slidebarPosition","mount","productId","mainSplide","navSplide","mainImages","navImages","showAndFadeOutCountIndicator","elems","querySelectorAll","elem","recalculateCarousel","gallery","getElementById","cssText","product_id","updateCarouselImages","Components","item","slide","variantMainImages","newSlide","cloneNode","singleImage","mainSliderFooter","variantNavImages","__webpack_public_path__","async","Splide","mainCarousel","perMove","rewind","pagination","arrows","lazyLoad","breakpoints","navCarousel","fixedWidth","fixedHeight","gap","isNavigation","keyboard","newIndex","prevIndex","oldSlideContainer","getAt","video","paused","pause","destIndex","newSlideContainer","play","catch","sync","selectedVariant","hasVariantImages","initCarousel","then"],"sourceRoot":""}