{"version":3,"file":"modal-cart-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/modal-cart/alert/index.ts","webpack://lange/./scripts/sections/modal-cart/alert/index.scss","webpack://lange/./scripts/sections/modal-cart/alert/index.html","webpack://lange/./scripts/sections/modal-cart/cart-messages/index.ts","webpack://lange/./scripts/lib/splide-slidebar-extension.ts","webpack://lange/./scripts/lib/webpack-path.ts","webpack://lange/./scripts/sections/modal-cart/upsell-section/index.ts","webpack://lange/./scripts/sections/modal-cart/upsell-section/index.scss","webpack://lange/./scripts/sections/modal-cart/upsell-section/index.html","webpack://lange/../node_modules/@integrabeauty/shopify-ajax-api/src/cart.ts","webpack://lange/./scripts/lib/call-utils.ts","webpack://lange/./scripts/common/liquid-global.ts","webpack://lange/./scripts/sections/modal-cart/update-cart-html.ts","webpack://lange/./scripts/sections/modal-cart/cart-item-remove-button/remove-items.ts","webpack://lange/./scripts/sections/modal-cart/cart-item-remove-button/index.ts","webpack://lange/./scripts/sections/modal-cart/cart-item-remove-button/index.scss","webpack://lange/./scripts/sections/modal-cart/cart-item-remove-button/index.html","webpack://lange/./scripts/sections/modal-cart/cart-service/update-cart.ts","webpack://lange/./scripts/sections/modal-cart/cart-attribution.ts","webpack://lange/./scripts/sections/modal-cart/cart-page.ts","webpack://lange/./scripts/sections/modal-cart/modal-cart.ts","webpack://lange/./scripts/sections/modal-cart/cart-service/get-cart.ts","webpack://lange/./scripts/sections/modal-cart/cart-quantity-input.ts","webpack://lange/./scripts/sections/modal-cart/delivery-message/index.ts","webpack://lange/./scripts/sections/modal-cart/delivery-message/index.scss","webpack://lange/./scripts/sections/modal-cart/delivery-message/index.html"],"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\"modal-cart-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 type { CustomElement } from '@integrabeauty/custom-elements';\nimport html from './index.html';\nimport styles from './index.scss';\n\n/**\n * Renders an customer messaging\n */\nexport class AlertElement extends HTMLElement implements CustomElement {\n  timerId: ReturnType<typeof setTimeout>;\n\n  public static get observedAttributes() {\n    return [\n      'data-type'\n    ];\n  }\n\n  readonly dataset!: {\n    /**\n     * Boolean represented as string to render the close button.\n     */\n    close: 'false' | 'true';\n\n    /**\n     * Boolean represented as string to hide/show the messaging component.\n     */\n    hidden: 'false' | 'true';\n\n    /**\n     * Position of the messaging component. Makes the component absolute and place the component\n     * according to the attribute value.\n     */\n    position: 'bottom-left' | 'bottom-right' | 'full' | 'top-left' | 'top-right';\n\n    /**\n     * Boolean represented as string to set the component as `position: fixe;`. It might be helpful\n     * in some cases with combination of the data-position attribute.\n     */\n    positionFixed: 'false' | 'true';\n\n    /**\n     * Time in milliseconds after which the component should hide.\n     */\n    timer: string;\n\n    /**\n     * Messaging severity level.\n     */\n    type: 'error' | 'info' | 'success';\n  };\n\n  private onCloseClickedBound = this.onCloseClicked.bind(this);\n\n  constructor() {\n    super();\n\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 closeButton = this.shadowRoot.querySelector('.close-button');\n    closeButton.removeEventListener('click', this.onCloseClickedBound);\n\n    if (this.timerId) {\n      clearTimeout(this.timerId);\n    }\n  }\n\n  private render() {\n    const closeButton = this.shadowRoot.querySelector('.close-button');\n    closeButton.addEventListener('click', this.onCloseClickedBound);\n\n    if (this.dataset.timer) {\n      this.timerId = setTimeout(() => {\n        this.remove();\n      }, parseInt(this.dataset.timer, 10));\n    }\n  }\n\n  private onCloseClicked(_event: Event) {\n    this.remove();\n  }\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'alert-element': AlertElement;\n  }\n}\n\nif (!customElements.get('alert-element')) {\n  customElements.define('alert-element', AlertElement);\n}\n","export default \":host{border:1px solid;border-radius:2px;display:block;margin-bottom:16px;padding:16px 42px 16px 16px;position:relative}:host([data-hidden=true]){display:none}:host([data-type=info]){background-color:#ffe5ad;border-color:#ffb619;color:#000;font-weight:600}:host([data-type=success]){background-color:#f9fef6;border-color:#3c8f12;color:#378410}:host([data-type=error]){background-color:#edcccc;border-color:#d50407;color:#d50407}:host([data-position]){max-width:300px;position:absolute;width:100%;z-index:99999}:host([data-position-fixed=true]){position:fixed}:host([data-position=top-left]){left:16px;top:16px}:host([data-position=top-right]){right:16px;top:16px}:host([data-position=bottom-left]){bottom:16px;left:16px}:host([data-position=bottom-right]){bottom:16px;right:16px}.close-button{appearance:none;background-color:#0000;border:none;box-sizing:initial;cursor:pointer;display:none;height:14px;line-height:1;padding:8px;position:absolute;right:0;top:0;width:14px}:host([data-close=true]) .close-button{display:block}::slotted([slot=content]){padding-left:0!important;padding-right:0!important}\";","// Module\nvar code = \"<div role=\\\"alert\\\"><button class=\\\"close-button\\\" aria-label=\\\"Close notification\\\"><svg stroke=\\\"black\\\" fill=\\\"none\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" viewBox=\\\"0 0 24 24\\\"><path d=\\\"M0.600006 23.4L23.4 0.6\\\" stroke-width=\\\"1.5\\\" stroke-miterlimit=\\\"10\\\"></path><path d=\\\"M23.4 23.4L0.600006 0.6\\\" stroke-width=\\\"1.5\\\" stroke-miterlimit=\\\"10\\\"></path></svg></button><slot name=\\\"content\\\"></slot></div>\";\n// Exports\nexport default code;","import type { CustomElement } from '@integrabeauty/custom-elements';\n\n/**\n * This component renders the cart messages by building and appending\n * to the DOM an alert-element component.\n */\nexport class CartMessages extends HTMLElement implements CustomElement {\n  constructor() {\n    super();\n    this.attachShadow({ mode: 'open' });\n  }\n\n  connectedCallback() {\n    addEventListener('ofir-add-to-cart', <EventListener>this.onAddToCart.bind(this));\n    addEventListener('ofir-update-line-item',\n      <EventListener>this.onUpdateLineItem.bind(this));\n  }\n\n  onAddToCart(event: OfirCustomEvents.AddToCartEvent) {\n    this.clearMessages();\n\n    if (!event.detail.success) {\n      this.showErrorMessage('There was an issue processing your request, please try again later.');\n      return;\n    }\n\n    const lineItems = event.detail.items;\n    const addedLineItemsString = lineItems.map(item => item.title).join(', ');\n    const messageHtml = `You added ${addedLineItemsString} to your shopping bag!`;\n    this.showSuccessMessage(messageHtml);\n  }\n\n  onUpdateLineItem(event: OfirCustomEvents.UpdateLineItemEvent) {\n    this.clearMessages();\n\n    if (!event.detail.success) {\n      this.showErrorMessage('There was an issue processing your request, please try again later.');\n      return;\n    }\n\n    let messageHtml;\n    if (event.detail.item_deleted) {\n      messageHtml = 'Item was removed successfully from your shopping bag.';\n    } else {\n      const updatedItemId = parseInt(event.detail.item.id, 10);\n      const lineItems = event.detail.cart.items;\n      const updatedLineItem = lineItems.find(\n        (item: ShopifyAjaxApi.LineItem) => item.id === updatedItemId);\n      messageHtml = `${updatedLineItem.title} was updated successfully in your shopping bag!`;\n    }\n\n    this.showSuccessMessage(messageHtml);\n  }\n\n  showSuccessMessage(messageHtml: string) {\n    const message = document.createElement('div');\n    message.setAttribute('slot', 'content');\n    message.innerHTML = messageHtml;\n\n    const messaging = document.createElement('alert-element');\n    messaging.dataset.type = 'success';\n    messaging.dataset.timer = '5000';\n    messaging.append(message);\n\n    this.shadowRoot.append(messaging);\n  }\n\n  showErrorMessage(messageHtml: string) {\n    const message = document.createElement('div');\n    message.setAttribute('slot', 'content');\n    message.innerHTML = messageHtml;\n\n    const messaging = document.createElement('alert-element');\n    messaging.dataset.type = 'error';\n    messaging.dataset.timer = '5000';\n    messaging.append(message);\n\n    this.shadowRoot.append(messaging);\n  }\n\n  clearMessages() {\n    const messages = this.shadowRoot.querySelectorAll('alert-element');\n    for (const message of messages) {\n      message.remove();\n    }\n  }\n}\n\nif (!customElements.get('cart-messages')) {\n  customElements.define('cart-messages', CartMessages);\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\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","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","import '../../../lib/webpack-path';\nimport { CustomElement } from '@integrabeauty/custom-elements';\nimport type { Splide } from '@splidejs/splide';\nimport { splideSlidebarExtension } from '../../../lib/splide-slidebar-extension';\nimport html from './index.html';\nimport styles from './index.scss';\n\n/**\n * A custom element for the upsell section in the modal cart.\n */\nclass UpsellSection extends HTMLElement implements CustomElement {\n  public shadowRoot!: ShadowRoot;\n\n  public splide: Splide;\n\n  private onCarouselSlotChangeBound = this.onCarouselSlotChange.bind(this);\n  private onCartModalOpenedBound = this.onCartModalOpened.bind(this);\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.render();\n  }\n\n  public disconnectedCallback() {\n    const carouselSlot = this.shadowRoot.querySelector('slot[name=\"carousel\"]');\n    carouselSlot.removeEventListener('slotchange', this.onCarouselSlotChangeBound);\n\n    removeEventListener('cart-modal-opened', this.onCartModalOpenedBound);\n\n    if (this.splide) {\n      this.splide.destroy();\n    }\n  }\n\n  private render() {\n    const carouselSlot = this.shadowRoot.querySelector('slot[name=\"carousel\"]');\n    carouselSlot.addEventListener('slotchange', this.onCarouselSlotChangeBound);\n\n    addEventListener('cart-modal-opened', this.onCartModalOpenedBound);\n  }\n\n  /**\n   * Handles the `slotchange` event. Listening to DOMContentLoaded is not reliable. Splide doesn't\n   * work properly.\n   */\n  private onCarouselSlotChange(event: Event) {\n    const slot = <HTMLSlotElement>event.target;\n    const assignedElements = slot.assignedElements();\n    if (assignedElements.length > 0) {\n      this.initCarousel().catch(console.warn);\n    }\n  }\n\n  /**\n   * Handles the `cart-modal-opened` event. We need to refresh the carousel when the modal is\n   * opened, because the carousel is initialized while the modal is hidden (display: none), and\n   * Splide cannot calculate and display slidebar correctly in this case.\n   */\n  private onCartModalOpened(_event: Event) {\n    if (this.splide) {\n      this.splide.refresh();\n    }\n  }\n\n  private async initCarousel() {\n    const { Splide } = await import('@splidejs/splide');\n    const element = this.querySelector<HTMLElement>('.upsell__carousel.splide');\n    if (!element) {\n      return;\n    }\n\n    const splide = new Splide(element, {\n      type: 'slide',\n      fixedWidth: 170,\n      perMove: 1,\n      rewind: false,\n      arrows: false,\n      pagination: false,\n      gap: 12,\n      keyboard: true,\n      slidebar: true,\n      omitEnd: true\n    });\n\n    splide.mount({\n      splideSlidebarExtension\n    });\n\n    this.splide = splide;\n  }\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'upsell-section': UpsellSection;\n  }\n}\n\nif (!customElements.get('upsell-section')) {\n  customElements.define('upsell-section', UpsellSection);\n}\n","export default \":host{background-color:#f5f5f5;display:block;padding:24px 16px}.title{font-size:1.125rem;font-weight:300;letter-spacing:.07rem;margin-bottom:18px;text-align:center;text-transform:uppercase}slot[name=subtitle]{display:block;font-weight:600}\";","// Module\nvar code = \"<h3 class=\\\"title\\\"><slot name=\\\"title\\\"></slot><slot name=\\\"subtitle\\\"></slot></h3><slot name=\\\"carousel\\\"></slot>\";\n// Exports\nexport default code;","import * as _ShopifyBrowserTypes from '@integrabeauty/shopify-browser-types';\n\n/**\n * Represents the value of a cart attribute. Ordinarily values are strings. However, Shopify also\n * supports storing nested objects as values.\n */\nexport type AttributeValue = Record<string, string> | string;\n\n/**\n * The type of the value of `Cart['attributes']`\n */\nexport type Attributes = Record<string, AttributeValue>;\n\n/**\n * @todo selling plan properties\n * @todo endpoint request body response body types\n *\n * @see https://shopify.dev/docs/api/ajax/reference/cart\n */\nexport interface Cart {\n  /**\n   * An object where the key is the attribute name and the value is the attribute value.\n   */\n  attributes: Attributes;\n\n  /**\n   * A discount application represents a type of discount.\n   *\n   * When a discount is applied to one or more line items, it is said to be _allocated_ to the\n   * line items. That is why line level discount allocation objects have a nested application\n   * object that will correlate with one of the applications in this array.\n   *\n   * When a discount is applied to the whole cart, it will only be present in this array because it\n   * is not allocated to particular lines.\n   */\n  cart_level_discount_applications: DiscountApplication[];\n\n  /**\n   * The ISO currency code for the cart.\n   *\n   * @example \"USD\"\n   */\n  currency: string;\n\n  /**\n   * Discount codes that have been applied to the cart.\n   *\n   * Not all codes are applicable. It is possible for a code to be applied but inapplicable.\n   *\n   * This does not provide information about the amount of each discount. Refer to the cart level\n   * discount applications or line level discount allocations for that information.\n   *\n   * This array will include shipping discounts. A shipping discount will be present in the array\n   * if applied but in the inapplicable state while in the cart. The discount will appear as\n   * applicable at checkout automatically.\n   */\n  discount_codes: DiscountCode[];\n\n  /**\n   * Total quantity of items in a cart\n   */\n  item_count: number;\n\n  /**\n   * The cart's line items.\n   *\n   * A cart will always have a defined items array, even if the cart is empty.\n   */\n  items: Item[];\n\n  items_subtotal_price: number;\n\n  /**\n   * An optional textual note that may be applied to the cart. If a cart becomes a checkout, and\n   * then the checkout becomes an order, the cart note will carry over to the order note.\n   *\n   * An order's note, and an order's note attributes, are two completely separate concepts.\n   */\n  note: string;\n\n  original_total_price: number;\n\n  /**\n   * This is true when at least one item in the cart requires shipping.\n   *\n   * This is false when no items in the cart require shipping.\n   *\n   * Shopify supports digital-only carts. These are carts that when purchased do not require the\n   * creation of a fulfillment. For example, a cart that consists only of a digital gift card.\n   */\n  requires_shipping: boolean;\n\n  /**\n   * This property is defined when there are cart mutations that involve the use of liquid-rendered\n   * sections.\n   *\n   * @see https://shopify.dev/docs/api/ajax/reference/cart#request-sections\n   */\n  sections: Record<string, string>;\n\n  /**\n   * This is the publicly visible cart id.\n   *\n   * If a checkout is created from this cart, the checkout's cart token will be equal to this value.\n   *\n   * Never write logic that parses this value. The format can change at any time, and has changed\n   * several times in the past.\n   *\n   * The value may contain url-like values, e.g. \"abc?key=123\"\n   */\n  token: string;\n\n  /**\n   * The total reduction in price in currency subunits (e.g. in cents for USD).\n   *\n   * @example 5010\n   */\n  total_discount: number;\n\n  /**\n   * Total price in currency subunits. For example, if the currency is USD, this is in cents.\n   *\n   * @example 1050\n   */\n  total_price: number;\n\n  /**\n   * The total weight of the cart (in grams?). This is a simple sum of the weight of the items of\n   * the cart (unit weight * quantity).\n   *\n   * @example 123.456\n   */\n  total_weight: number;\n}\n\n/**\n * Represents a discount that has been applied to an item.\n */\nexport interface Discount {\n  amount: number;\n  title: string;\n}\n\n/**\n * Represents a discount application that has been allocated to a line item.\n */\nexport interface DiscountAllocation {\n  /**\n   * The amount of the application that was allocated to a particular line item.\n   *\n   * When a discount application is allocated to several line items, this is a partial value of the\n   * full discount application amount that is allocated to this particular line. When the discount\n   * application is only allocated to a single line, this value will be equal to the total value of\n   * the discount application.\n   *\n   * For example, let's say we have cart with 2 line items and 10 dollar off discount application.\n   * The total value of the discount application is 10 dollars. Let's say the discount is allocated\n   * to both lines. The value of each allocation is 5 dollars. For each line this amount will\n   * contain the value 500. Within the nested application object, the application's total amount\n   * will be 1000. This is because each nested application object is a copy of the one application\n   * that happens to have multiple allocations (the discount is applied to multiple lines).\n   *\n   * The amount is in currency subunits. For example, for USD, this is the value of cents. For\n   * example, a discount of $2.50 is 250.\n   *\n   * @example 1050\n   */\n  amount: number;\n\n  /**\n   * The corresponding discount application that was allocated to a particular line item.\n   */\n  discount_application: DiscountApplication;\n}\n\n/**\n * A discount application represents a discount of some kind. There are automatically applied\n * discount applications, discount code applications, and script applied discount applications.\n */\nexport interface DiscountApplication {\n  allocation_method: string;\n  created_at: string;\n  description: string;\n  key: string;\n  target_selection: string;\n  target_type: string;\n  title: string;\n  total_allocated_amount: number;\n  type: string;\n  value: string;\n  value_type: string;\n}\n\n/**\n * The details of an image resource, such as the hero image for a product.\n */\nexport interface Image {\n  alt: string;\n  aspect_ratio: number;\n  height: number;\n  url: string;\n  width: number;\n}\n\n/**\n * Represents a line item in a cart.\n */\nexport interface Item {\n  /**\n   * The price of the line item after discounts\n   */\n  discounted_price: number;\n\n  /**\n   * Discount codes applied to the line item.\n   *\n   * @deprecated\n   */\n  discounts: Discount[];\n\n  /**\n   * The main image for the product\n   */\n  featured_image: Image;\n\n  /**\n   * The combined price, in the currency's subunit, of all of the items in the line item. This\n   * includes any line-level discounts.\n   *\n   * The value is equal to line_item.final_price multiplied by line_item.quantity. It's output in\n   * the customer's local (presentment) currency.\n   *\n   * For currencies without subunits, such as JPY and KRW, tenths and hundredths of a unit are\n   * appended. For example, 1000 Japanese yen is output as 100000.\n   */\n  final_line_price: number;\n\n  /**\n   * The price of the line item in the currency's subunit. This includes any line-level discounts.\n   *\n   * The value is output in the customer's local (presentment) currency.\n   *\n   * For currencies without subunits, such as JPY and KRW, tenths and hundredths of a unit are\n   * appended. For example, 1000 Japanese yen is output as 100000.\n   */\n  final_price: number;\n\n  /**\n   * Returns true if the product associated with the line item is a gift card. Returns false if not.\n   */\n  gift_card: boolean;\n\n  /**\n   * The weight of the line item in the store's default weight unit.\n   */\n  grams: number;\n\n  handle: string;\n\n  has_components: boolean;\n\n  /**\n   * The ID of the line item. The ID differs depending on the context. The following table outlines\n   * the possible contexts and their associated values:\n   *\n   * Context Value\n   *\n   * * cart.items The ID of the line item's variant. This ID isn't unique, and can be shared by\n   *   multiple items with the same variant.\n   * * checkout.line_items A temporary unique hash generated for the checkout.\n   * * order.line_items A unique integer ID.\n   */\n  id: number;\n\n  image: string;\n\n  key: string;\n\n  /**\n   * The discount allocations that apply to the line item.\n   */\n  line_level_discount_allocations: DiscountAllocation[];\n\n  /**\n   * The total amount of any discounts applied to the line item in the currency's subunit.\n   *\n   * The value is output in the customer's local (presentment) currency.\n   *\n   * For currencies without subunits, such as JPY and KRW, tenths and hundredths of a unit are\n   * appended. For example, 1000 Japanese yen is output as 100000.\n   */\n  line_level_total_discount: number;\n\n  /**\n   * @deprecated https://shopify.dev/docs/api/liquid/objects/line_item\n   */\n  line_price: number;\n\n  /**\n   * The name and value pairs for each option of the variant associated with the line item.\n   *\n   * The array is never empty because variants with no options still have a default option. Because\n   * of this, you should use line_item.product.has_only_default_variant to check whether there's any\n   * information to output.\n   */\n  options_with_values: Option[];\n\n  /**\n   * The combined price of all of the items in a line item in the currency's subunit, before any\n   * discounts have been applied.\n   *\n   * The value is equal to line_item.original_price multiplied by line_item.quantity. It's output in\n   * the customer's local (presentment) currency.\n   *\n   * For currencies without subunits, such as JPY and KRW, tenths and hundredths of a unit are\n   * appended. For example, 1000 Japanese yen is output as 100000.\n   */\n  original_line_price: number;\n\n  /**\n   * The price of the line item in the currency's subunit, before discounts have been applied.\n   *\n   * The value is output in the customer's local (presentment) currency.\n   *\n   * For currencies without subunits, such as JPY and KRW, tenths and hundredths of a unit are\n   * appended. For example, 1000 Japanese yen is output as 100000.\n   */\n  original_price: number;\n\n  presentment_price: number;\n\n  /**\n   * @deprecated https://shopify.dev/docs/api/liquid/objects/line_item\n   */\n  price: number;\n\n  product_description: string;\n\n  product_has_only_default_variant: boolean;\n\n  /**\n   * The ID of the line item's product.\n   */\n  product_id: number;\n\n  product_title: string;\n\n  product_type: string;\n\n  properties: Record<string, string>;\n  quantity: number;\n\n  quantity_rule: QuantityRule;\n\n  requires_shipping: boolean;\n\n  /**\n   * The selling plan allocation of the line item.\n   */\n  selling_plan_allocation: SellingPlanAllocation;\n\n  /**\n   * The SKU of the variant in the line item.\n   *\n   * Stock Keeping Unit.\n   */\n  sku: string;\n\n  successfully_fulfilled_quantity: number;\n\n  taxable: boolean;\n\n  /**\n   * The title of the line item. The title is a combination of line_item.product.title and\n   * line_item.variant.title, separated by a hyphen.\n   *\n   * In most contexts, the line item title appears in the customer's preferred language. However, in\n   * the context of an order, the line item title appears in the language that the customer checked\n   * out in. The title can receive an override value from the Cart Transform API. Overrides take\n   * precedence over translations.\n   *\n   * #### Line item title history\n   *\n   * When referencing line item, product, and variant titles in the context of an order, the\n   * following changes might result in a different output than you expect:\n   * * A product or variant being deleted\n   * * A product or variant title being edited\n   *\n   * When line_item.title is referenced for an order, the line item title at the time of the order\n   * is returned. However, when line_item.product.title and line_item.variant.title are referenced,\n   * the current value for each title is returned.\n   */\n  title: string;\n\n  /**\n   * @deprecated https://shopify.dev/docs/api/liquid/objects/line_item\n   */\n  total_discount: number;\n\n  unit_price_measurement: {\n    measured_type: string;\n    quantity_unit: string;\n    quantity_value: string;\n    reference_unit: string;\n    reference_value: number;\n  };\n\n  untranslated_produce_title: string;\n\n  untranslated_variant_title: string;\n\n  /**\n   * The relative URL of the variant associated with the line item.\n   */\n  url: string;\n\n  /**\n   * The ID of the line item's variant.\n   */\n  variant_id: number;\n\n  variant_options: string[];\n\n  variant_title: string;\n\n  /**\n   * The vendor of the variant associated with the line item.\n   */\n  vendor: string;\n}\n\nexport interface SellingPlanAllocation {\n  compare_at_price: number;\n\n  per_delivery_price: number;\n\n  /**\n   * @example 900\n   */\n  price: number;\n\n  price_adjustments: SellingPlanAllocationPriceAdjustment[];\n  selling_plan: SellingPlan;\n}\n\nexport interface SellingPlanAllocationPriceAdjustment {\n  /**\n   * @example 1\n   */\n  position: number;\n\n  /**\n   * @example 900\n   */\n  price: number;\n}\n\nexport interface SellingPlan {\n  description: unknown;\n\n  fixed_selling_plan: boolean;\n\n  id: number;\n  name: string;\n\n  options: SellingPlanOption[];\n\n  price_adjustments: SellingPlanPriceAdjustment[];\n\n  recurring_deliveries: boolean;\n}\n\nexport interface SellingPlanOption {\n  name: string;\n  position: number;\n  value: string;\n}\n\nexport interface SellingPlanPriceAdjustment {\n  order_count: unknown;\n  position: number;\n  value: number;\n  value_type: string;\n}\n\nexport interface Option {\n  name: string;\n  value: string;\n}\n\nexport interface QuantityRule {\n  increment: number;\n  max: number;\n  min: number;\n}\n\nexport interface DiscountCode {\n  /**\n   * Whether the discount is currently applicable. It is possible to apply a discount code to a\n   * cart but have it not yet be applicable. When not applicable, there will not be any associated\n   * discount applications or allocations. The moment someone performs an action that makes the\n   * discount code applicable, Shopify will update the property to true.\n   */\n  applicable: boolean;\n\n  /**\n   * The discount code string.\n   *\n   * This is NOT guaranteed to be uppercase. Discount codes entered at checkout are captured in\n   * whatever case was used during input.\n   *\n   * @example \"MONEY1234\"\n   * @example \"Abc123def\"\n   */\n  code: string;\n}\n\n/**\n * Returns the request id header from the ajax cart api response. Capturing this value is important\n * when helping Shopify support investigate issues.\n *\n * This does not error. If there is a problem, this returns null or undefined.\n */\nfunction getRequestId(response: Response) {\n  try {\n    return response.headers.get('X-Request-Id');\n  } catch (error) {\n    // ignore\n  }\n}\n\n/**\n * An item to add to the cart\n */\nexport interface AddItem {\n  /**\n   * Variant id\n   *\n   * Shopify says that it supports variant ids as numbers, but we have witnessed strange errors when\n   * using numbers so we impose an artificial limitation on the type here and require strings.\n   */\n  id: string;\n\n  /**\n   * Line item properties to include.\n   *\n   * If the variant does not already exist in the cart, then the logic is straightforward. This will\n   * result in a new line item with these properties.\n   *\n   * If the variant exists in the cart, then the logic is convoluted. If the specified properties\n   * are identical to the existing properties, then the quantity of the existing line item\n   * increments. If the specified properties are different, then a new line item is created with\n   * these properties, resulting in the same variant being present in multiple line items.\n   */\n  properties?: Attributes;\n\n  /**\n   * The amount of the variant to add.\n   *\n   * @see https://shopify.dev/docs/api/ajax/reference/cart#post-locale-cart-add-js\n   */\n  quantity: number;\n\n  selling_plan?: number | string;\n}\n\n/**\n * Adds items to the cart. At least one item should be specified.\n *\n * This does not fetch the response body. The raw response body does not contain the full cart\n * state. The raw response body may not be the latest state of cart items. The raw response body\n * may contain zero-quantity items still present after prior removal.\n *\n * This validates the response status. If the status is not ok this throws an error.\n *\n * This specifies fetch mode no-store so that the call is not unintentionally cached.\n *\n * Adding an item the cart does not necessarily mean a new line item is created. For each item in\n * the input, Shopify makes a server side determination of whether to update the quantity of an\n * existing line item or add a new line item. The factors in that decision are related to how a line\n * item key is determined, which is poorly documented. Basically, if an item has some different\n * properties, e.g. line item properties, or pricing, then the item will always be added as a new\n * line item, even though the variant id is the same as an existing line item.\n *\n * The line item scripts run on every mutation. The scripts will remove any orphaned value set line\n * items implicitly. Keep this in mind when debugging.\n *\n * The content type header must be specified in the request or Shopify interprets the request as a\n * form submission, which we are not doing here, which leads to an error.\n *\n * Shopify's injected front end code (e.g. Trekkie, Monorail) triggers a console warning when it\n * detects that the number of items requested to be added is less than the number that was added.\n * This is not necessarily an error. It can indicate that the line item scripts removed one or more\n * line items during the add mutation.\n *\n * @see https://shopify.dev/docs/api/ajax/reference/cart#post-locale-cart-add-js\n * @see https://help.shopify.com/en/manual/checkout-settings/script-editor/shopify-scripts\n */\nexport async function cartAdd(items: AddItem[]) {\n  const response = await fetch(Shopify.routes.root + 'cart/add.js', {\n    body: JSON.stringify({ items }),\n    headers: {\n      'Content-Type': 'application/json'\n    },\n    cache: 'no-store',\n    method: 'POST'\n  });\n\n  if (!response.ok) {\n    const error: any = new Error(`Received status ${response.status} adding to cart`);\n    error.items = items;\n    error.request_id = getRequestId(response);\n\n    try {\n      error.response_body = await response.json();\n    } catch (error) {\n      // ignore\n    }\n\n    error.response_status = response.status;\n\n    // For certain error responses, Shopify provides a clearer error message in the response body.\n    // Extract the message from the response and use that as the thrown error message.\n\n    if (typeof error.response_body?.message === 'string') {\n      error.message = error.response_body.message;\n    }\n\n    throw error;\n  }\n\n  return response;\n}\n\n/**\n * Either id or line must be specified.\n */\nexport interface CartChangeInput {\n  /**\n   * Can be either the variant id or the line item key.\n   */\n  id?: number | string;\n\n  /**\n   * A cart can have multiple line items that share the same variant_id. For example, when variants\n   * have different line item properties, or automatic discounts create variants at different\n   * prices. To account for this, you can use the line property when updating the cart.\n   *\n   * The value of line is the 1-based index position of the item in the cart.\n   */\n  line?: number;\n\n  /**\n   * The properties property sets the line item properties. Its value must be an object of key-value\n   * pairs.\n   *\n   * Whenever a POST request includes properties, it overwrites the entire properties object. Any\n   * key-value pairs that were already in the properties object are erased.\n   *\n   * It's not possible to set a line item's properties property to an empty object once a value is\n   * set. If you need to remove all line item properties, then you need to remove the entire line\n   * item.\n   *\n   * You can visually hide line item properties at checkout by creating private properties. This\n   * technique might be an alternative to removing a line item when managing properties.\n   */\n  properties?: Record<string, any>;\n\n  /**\n   * The value of the quantity property represents the new quantity you want for the line item. It\n   * must be an integer.\n   *\n   * You can remove a line item by setting the quantity to 0.\n   *\n   * It is not clear from the documentation, but based on the description of the selling plan\n   * property, it looks like quantity is actually optional and defaults to 1 when not specified.\n   */\n  quantity?: number;\n\n  /**\n   * The selling_plan property sets the line item selling plan. Its value must be one of the\n   * following:\n   *\n   * * The selling plan ID: To set a specific selling plan for the line item.\n   * * null or an empty string: To remove any selling plan from the line item.\n   *\n   * When specifying the selling_plan property, consider the following:\n   * * You can use only the line property for identifying the line item.\n   * * You should always specify the quantity property. If the quantity isn't specified, then it's\n   *   assumed to be 1.\n   */\n  selling_plan?: number;\n}\n\n/**\n * Use the /{locale}/cart/change.js endpoint to change the quantity, properties, and selling_plan\n * properties of a cart line item. Only items already in your cart can be changed, and you can\n * change only one line item at a time.\n *\n * The POST data requires either an id or line property to identify the line item to be changed.\n *\n * The value of the id property can be one of the following:\n *\n * * The line item's variant_id\n * * The line item's key\n *\n * A cart can have multiple line items that share the same variant_id. For example, when variants\n * have different line item properties, or automatic discounts create variants at different prices.\n * Because of this, it's recommended to use the line item key to ensure that you're only changing\n * the intended line item.\n *\n * If the item that you're attempting to change isn't already in the cart, then\n * /{locale}/cart/change.js doesn't add it. Instead, it returns a 404 error.\n *\n * The documentation states that the response body is the JSON of the cart. This exposes the\n * response object but does not fetch the response body.\n *\n * ### Removing out of stock items\n * It is unclear but based on a conversation with Shopify support, prefer to use cart/change instead\n * of cart/update to avoid issues with removing an out of stock item from the cart. Using update\n * results in a 422 error but supposedly cart/change does not.\n */\nexport async function cartChange(input: CartChangeInput) {\n  const response = await fetch(Shopify.routes.root + 'cart/change.js', {\n    body: JSON.stringify(input),\n    cache: 'no-store',\n    headers: {\n      'Content-Type': 'application/json'\n    },\n    method: 'POST'\n  });\n\n  if (!response.ok) {\n    const error: any = new Error(`Received status ${response.status} changing cart`);\n    error.request_body = input;\n    error.request_id = getRequestId(response);\n\n    try {\n      error.response_body = await response.json();\n    } catch (error) {\n      // ignore\n    }\n\n    error.response_status = response.status;\n    error.response_url = response.url;\n\n    // For certain error responses, Shopify provides a clearer error message in the response body.\n    // Extract the message from the response and use that as the thrown error message.\n\n    if (typeof error.response_body?.message === 'string') {\n      error.message = error.response_body.message;\n    }\n\n    throw error;\n  }\n\n  return response;\n}\n\n/**\n * Use the GET /{locale}/cart.js endpoint to get the cart as JSON.\n *\n * All monetary properties are returned in the customer's presentment currency. To check the\n * customer's presentment currency, you can use the currency field in the response.\n *\n * @see https://shopify.dev/docs/api/ajax/reference/cart#get-locale-cart-js\n */\nexport async function cartFetch() {\n  const url = Shopify.routes.root + 'cart.js';\n\n  let response;\n  try {\n    response = await fetch(url, { cache: 'no-store' });\n  } catch (error) {\n    error.url = url;\n    throw error;\n  }\n\n  if (!response.ok) {\n    const error: any = new Error(`Received status ${response.status} fetching cart`);\n    error.request_id = getRequestId(response);\n\n    try {\n      error.response_body = await response.json();\n    } catch (error) {\n      // ignore\n    }\n\n    error.status = response.status;\n    error.url = response.url;\n    throw error;\n  }\n\n  let body;\n  try {\n    body = await response.json();\n  } catch (error) {\n    error.status = response.status;\n    error.url = response.url;\n    throw error;\n  }\n\n  if (!isCart(body)) {\n    const error: any = new Error('Unexpected get cart response body');\n    error.response_body = body;\n    error.status = response.status;\n    error.url = response.url;\n    throw error;\n  }\n\n  return body;\n}\n\nexport interface CartUpdateInput {\n  /**\n   * New cart attributes. Existing cart attributes are overwritten.\n   */\n  attributes?: Attributes;\n\n  /**\n   * Beta shopify feature. Essentially works like Storefront discount apply mutation.\n   *\n   * Pass an empty string to remove discount(s).\n   */\n  discount?: string;\n\n  /**\n   * Cart note.\n   */\n  note?: string;\n\n  /**\n   * Even though Shopify supports specifying variant ids as numbers, we impose the restriction that\n   * the property names of the updates object must be strings due to some strange looking errors\n   * when specifying numbers.\n   */\n  updates?: Record<string, any>;\n}\n\n/**\n * Performs a cart update.\n *\n * This does not return the cart updated state. You will need to do a followup call to fetch the\n * updated state of the cart. One reason this does also return the updated state is that we must\n * perform a second call to fetch the updated state but not all callers are interested in doing so.\n *\n * This does not return the response body of the call. There is no need to fetch the body because\n * the body does not contain useful data. The response body can contain 0 quantity items and other\n * kinds of strange things.\n *\n * This must specify the content type header. Shopify supports both a JSON request body and a form\n * data request body. Shopify defaults to interpreting requests as form submissions. This uses the\n * JSON format so the header is required.\n *\n * Backend scripts may affect the output.\n *\n * @see https://shopify.dev/docs/api/ajax/reference/cart#post-locale-cart-update-js\n * @see https://shopify.dev/docs/api/ajax/reference/cart#update-line-item-quantities\n * @see https://shopify.dev/docs/api/ajax/reference/cart#private-cart-attributes\n */\nexport async function cartUpdate(input: CartUpdateInput) {\n  const response = await fetch(Shopify.routes.root + 'cart/update.js', {\n    body: JSON.stringify(input),\n    cache: 'no-store',\n    headers: {\n      'Content-Type': 'application/json'\n    },\n    method: 'POST'\n  });\n\n  if (!response.ok) {\n    const error: any = new Error(`Received status ${response.status} updating cart`);\n    error.request_body = input;\n    error.request_id = getRequestId(response);\n\n    try {\n      error.response_body = await response.json();\n    } catch (error) {\n      // ignore\n    }\n\n    error.response_status = response.status;\n\n    // For certain error responses, Shopify provides a clearer error message in the response body.\n    // Extract the message from the response and use that as the thrown error message.\n\n    if (typeof error.response_body?.message === 'string') {\n      error.message = error.response_body.message;\n    }\n\n    throw error;\n  }\n\n  return response;\n}\n\n/**\n * Returns whether the error indicates the add failed because one of the products is out of stock\n * (not available for sale). In this case Shopify provides an error response body that looks like\n * this:\n *\n * ```json\n * {\n *   \"description\": \"All 0 <product title> are in your cart\",\n *   \"message\": \"Cart Error\",\n *   \"status\": 422\n * }\n * ```\n *\n * ```json\n * {\n *   \"description\": \"The product '<title>' is already sold out.\",\n *   \"message\": \"Cart Error\",\n *   \"status\": 422\n * }\n * ```\n *\n * This error can happen both when adding an item or updating the quantity of an item.\n *\n * This assumes error messages are in English.\n */\nexport function isUnavailableError(error: any) {\n  if (error instanceof Error && 'response_body' in error && isObject(error.response_body) &&\n    error.response_body.status === 422) {\n    const description = error.response_body.description;\n    if (typeof description === 'string') {\n      // this one is only present in the add error response\n      if (description.startsWith('All 0') && description.includes('in your cart')) {\n        return true;\n      }\n\n      // this string is sometimes present in the update error response, not just the add response\n      if (description.includes('already sold out')) {\n        return true;\n      }\n    }\n  }\n\n  return false;\n}\n\n/**\n * Returns whether the given value looks like a cart object.\n *\n * This is not a complete validation. This is a shallow check that examines whether the value is\n * an object containing an items property that is an array. Any value that meets that criteria\n * satisfies the meaning of a cart.\n */\nexport function isCart(value: any): value is Cart {\n  return isObject(value) && Array.isArray(value.items);\n}\n\nfunction isObject(value: any): value is Record<string, any> {\n  return typeof value === 'object' && value !== null;\n}\n","// Keeps track of the timeout timer between the start and end of all calls\nlet timerId: ReturnType<typeof setTimeout>;\n\n/**\n * Called at the beginning of most service operations. This signals to the view that an operation\n * has started.\n *\n * @see http://jdebp.info/FGA/function-perilogues.html\n */\nexport function startCall(...args: any[]) {\n  // This should never happen because we always clear the timeout and set the variable value back\n  // to undefined in the epilogue. This might help debug some screwy things.\n\n  if (typeof timerId !== 'undefined') {\n    window.console.error('concurrent call detected!');\n    window.console.error('[call-utils.ts] args: ', args);\n\n    window.Sentry?.captureException(new Error('Concurrent checkout service call detected'), {\n      extra: {\n        args\n      },\n      level: 'warning'\n    });\n  }\n\n  // Guarantee that the end event will fire by starting a timer.\n  timerId = setTimeout(() => {\n    endCall(false, true);\n  }, 30 * 1000, true);\n\n  const event = new Event('ofir-cart-call-started', { cancelable: false });\n  dispatchEvent(event);\n}\n\n/**\n * Called at the end of most service operations. This signals to the view that an operation has\n * completed (successfully or not).\n *\n * This is called either manually whenever the operation completed, or automatically, if the\n * operation errored or has not completed after a certain amount of time. We do this to prevent\n * the situation of never firing an end event in case of extremely messed up code. Sometimes that\n * kind of thing happens and we never want to fully lock someone out of cart interactions.\n *\n * @see http://jdebp.info/FGA/function-perilogues.html\n */\nexport function endCall(notifyView = true, didTimeOut = false) {\n  // Unconditionally clear the timeout timer, regardless of whether the timer id is set.\n  clearTimeout(timerId);\n\n  // Reset the timer id. Not really needed but it makes it crystal clear that there is no timer id\n  // active.\n  timerId = undefined;\n\n  // If we got here from a timeout, just make sure something is logged. In theory, nothing ever\n  // times out.\n  if (didTimeOut) {\n    console.warn('epilogue timed out');\n  }\n\n  const event = new CustomEvent('ofir-cart-call-ended', {\n    cancelable: false,\n    detail: {\n      is_timeout: didTimeOut,\n      notify_view: notifyView\n    }\n  });\n\n  dispatchEvent(event);\n}\n","/* eslint-disable @typescript-eslint/naming-convention */\n/**\n * Do not use this export. This is a hacky fix to a strange inlining optimization performed by\n * webpack where it removes this module and points identifiers directly to the global values.\n * Without this export, webpack fails to understand that `window.__ofir` must also be inlined.\n *\n * @type {unknown}\n */\nexport const __ofir: unknown = window.__ofir;\n\n/**\n * Cart should never be undefined\n */\nexport const Cart: OfirLiquidGlobals.Cart = window.__ofir?.Cart;\n\n/**\n * Checkout is undefined if user is not loading a checkout page.\n *\n * @type {OfirLiquidGlobals.Checkout}\n */\nexport const Checkout: OfirLiquidGlobals.Checkout = window.__ofir?.Checkout;\n\n/**\n * Collection is undefined if user is not loading a product or collection page.\n *\n * @type {OfirLiquidGlobals.Collection}\n */\nexport const Collection: OfirLiquidGlobals.Collection = window.__ofir?.Collection;\n\n/**\n * Customer is undefined if user is not logged in.\n *\n * @type {OfirLiquidGlobals.Customer}\n */\nexport const Customer: OfirLiquidGlobals.Customer = window.__ofir?.Customer;\n\n/**\n * GiftCard is undefined if user is not on gift card page.\n *\n * @type {OfirLiquidGlobals.GiftCard}\n */\nexport const GiftCard: OfirLiquidGlobals.GiftCard = window.__ofir?.GiftCard;\n\n/**\n * Order is undefined unless user is on thank_you page, order status page or account/order detail\n * page.\n *\n * @type {OfirLiquidGlobals.Order}\n */\nexport const Order: OfirLiquidGlobals.Order = window.__ofir?.Order;\n\n/** @type {OfirLiquidGlobals.Page} */\nexport const Page: OfirLiquidGlobals.Page = window.__ofir?.Page;\n\n/** @type {OfirLiquidGlobals.Pagination} */\nexport const Pagination: OfirLiquidGlobals.Pagination = window.__ofir?.Pagination;\n\n/**\n * Product is undefined if not accessing a product page template.\n *\n * @type {OfirLiquidGlobals.Product}\n */\nexport const Product: OfirLiquidGlobals.Product = window.__ofir?.Product;\n\n/** @type {OfirLiquidGlobals.Request} */\nexport const Request: OfirLiquidGlobals.Request = window.__ofir?.Request;\n\n/** @type {OfirLiquidGlobals.Scripts} */\nexport const Scripts: OfirLiquidGlobals.Scripts = window.__ofir?.Scripts;\n\n/** @type {OfirLiquidGlobals.Search} */\nexport const Search: OfirLiquidGlobals.Search = window.__ofir?.Search;\n\n/** @type {OfirLiquidGlobals.SearchEngineListing} */\nexport const SearchEngineListing: OfirLiquidGlobals.SearchEngineListing =\n  window.__ofir?.SearchEngineListing;\n\n/** @type {OfirLiquidGlobals.SectionSettings} */\nexport const SectionSettings: OfirLiquidGlobals.SectionSettings = window.__ofir?.SectionSettings;\n\n/** @type {OfirLiquidGlobals.Shop} */\nexport const Shop: OfirLiquidGlobals.Shop = window.__ofir?.Shop;\n\n/** @type {OfirLiquidGlobals.Template} */\nexport const Template: OfirLiquidGlobals.Template = window.__ofir?.Template;\n\n/** @type {OfirLiquidGlobals.Theme} */\nexport const Theme: OfirLiquidGlobals.Theme = window.__ofir?.Theme;\n\n/** @type {OfirLiquidGlobals.ThemeSettings} */\nexport const ThemeSettings: OfirLiquidGlobals.ThemeSettings = window.__ofir?.ThemeSettings;\n","import * as LiquidGlobals from '../../common/liquid-global';\n\nexport default function updateCartHtml(html: string) {\n  const element = document.createElement('div');\n  element.innerHTML = html;\n\n  const cartContentElement = element.querySelector('.modal-content');\n  if (!cartContentElement) {\n    return;\n  }\n\n  if (LiquidGlobals.Template.name !== 'cart') {\n    const cartModalElement = document.getElementById('cart-modal');\n    const modalContentElement = cartModalElement?.querySelector('.modal-content');\n    if (!modalContentElement) {\n      return;\n    }\n\n    const modalContentCartHeaderElement = modalContentElement.querySelector('.cart__header');\n    modalContentCartHeaderElement.innerHTML =\n      cartContentElement.querySelector('.cart__header').innerHTML;\n\n    const modalContentCartContentElement = modalContentElement.querySelector('.cart__main');\n    modalContentCartContentElement.innerHTML =\n      cartContentElement.querySelector('.cart__main').innerHTML;\n\n    const cartCount =\n      cartContentElement.querySelector('.cart__header > span').textContent.replace(/\\D+/, '');\n    const cartCounterElement = document.querySelector('#cart-counter');\n    cartCounterElement.textContent = cartCount;\n\n    if (parseInt(cartCount, 10) === 0) {\n      cartCounterElement.classList.add('hidden');\n    } else {\n      cartCounterElement.classList.remove('hidden');\n    }\n  } else {\n    // Update cart content if user landed on cart page\n    const cartPageElement = document.getElementById('cart-page');\n    if (cartPageElement.classList.contains('cart--empty')) {\n      return;\n    }\n\n    const cartPageCartHeaderElement = cartPageElement.querySelector('.cart__header');\n    cartPageCartHeaderElement.innerHTML =\n      cartContentElement.querySelector('.cart__header').innerHTML;\n\n    const cartPageCartContentElement = cartPageElement.querySelector('.cart__main');\n    cartPageCartContentElement.innerHTML =\n      cartContentElement.querySelector('.cart__main').innerHTML;\n  }\n\n  const event = new Event('cart-html-updated');\n  dispatchEvent(event);\n}\n\ndeclare global {\n  interface WindowEventMap {\n    'cart-html-updated': Event;\n  }\n}\n","import * as ajax from '@integrabeauty/shopify-ajax-api';\nimport * as CallUtils from '../../../lib/call-utils';\nimport updateCartHtml from '../update-cart-html';\n\n/**\n * Utility method to remove Shopify cart line item in the shopping cart using the provided Ajax\n * API endpoint.\n *\n * CAUTION: This endpoint does not validate inventory levels for variants already in the cart,\n * meaning it is possible to add more inventory than is available in this particular use case.\n *\n * The imported CallUtils methods emit events to notify any view layer logic listening so it can\n * implement any required changes to update the user of the application state. You only need to use\n * these methods if you want the UX/UI to represent and/or provide messaging for the asynchronous\n * request.\n *\n * @param lineItemKeys line_item keys\n * @param notifyView passed on to ofir-cart-call-ended event to for view layer listeners\n *\n * @returns cart data\n *\n * @see https://shopify.dev/api/ajax/reference/cart#post-locale-cart-update-js\n */\n\nexport async function removeItems(\n  lineItemKeys: string[],\n  notifyView = true\n) {\n  CallUtils.startCall('updateCart');\n\n  const updateStartedEvent = new Event('cart-update-started');\n  dispatchEvent(updateStartedEvent);\n\n  let response;\n  let cart: ajax.Cart;\n\n  const updates: Record<string, 0> = {};\n  for (const lineItemKey of lineItemKeys) {\n    updates[lineItemKey] = 0;\n  }\n\n  const payload = {\n    updates,\n    sections: ['modal-cart']\n  };\n\n  try {\n    const previousCart = await ajax.cartFetch();\n    response = await ajax.cartUpdate(payload);\n\n    if (!response.ok) {\n      throw new Error(`CartService.updateCart Error: ${response.status} ${response.statusText} ` +\n        response.url);\n    }\n\n    cart = await response.json();\n\n    if (cart.sections?.['modal-cart']) {\n      updateCartHtml(cart.sections['modal-cart']);\n    }\n\n    type CartUpdatedEventDetail = WindowEventMap['cart-updated']['detail'];\n    const cartUpdatedEvent = new CustomEvent<CartUpdatedEventDetail>('cart-updated', {\n      detail: {\n        cart,\n        payload,\n        success: true\n      }\n    });\n    dispatchEvent(cartUpdatedEvent);\n\n    for (const lineItemKey of lineItemKeys) {\n      const lineItem = previousCart.items.find(item => item.key === lineItemKey);\n\n      if (!lineItem) {\n        throw Error(`Line item not found in cart. Key: ${lineItemKey}`);\n      }\n\n      type LineItemRemovedEventDetail = WindowEventMap['line-item-removed']['detail'];\n      const removedEvent = new CustomEvent<LineItemRemovedEventDetail>('line-item-removed', {\n        detail: {\n          item: lineItem\n        }\n      });\n      dispatchEvent(removedEvent);\n    }\n  } catch (error) {\n    const detail = {\n      error_code: response?.status,\n      error_message: response?.statusText,\n      updates,\n      success: false,\n      payload\n    };\n\n    window.Sentry?.captureException(error, {\n      extra: {\n        ...detail,\n        source: 'cart-service-update-cart'\n      }\n    });\n\n    type Detail = WindowEventMap['cart-updated']['detail'];\n    const event = new CustomEvent<Detail>('cart-updated', {\n      detail\n    });\n    dispatchEvent(event);\n  } finally {\n    CallUtils.endCall(notifyView, false);\n  }\n\n  return cart;\n}\n\ntype LineItemRemovedEvent = CustomEvent<{\n  /**\n   * Item object from the cart before the update. It's important to have the original item because\n   * the Google Analytics event needs data of the item that was removed (as well as other scripts\n   * may need it), and the updated cart doesn't contain it.\n   */\n  item: ajax.Item;\n}>;\n\ndeclare global {\n  interface WindowEventMap {\n    'line-item-removed': LineItemRemovedEvent;\n  }\n}\n","import type { CustomElement } from '@integrabeauty/custom-elements';\nimport html from './index.html';\nimport styles from './index.scss';\nimport { removeItems } from './remove-items';\n\n/**\n * A custom web component representing a button for removing items from the cart.\n */\nclass CartItemRemoveButton extends HTMLElement implements CustomElement {\n  readonly dataset!: {\n    /* eslint-disable @stylistic/max-len */\n    /**\n     * Comma-separated list of the product variant key, e.g.\n     * \"41770561273907:da3939d2d5d7db8847bca5d8880c2ad1,41770561273907:da3939d2d5d7db8847bca5d8880c2ad1\"\n     *\n     * @see https://shopify.dev/docs/api/liquid/objects/line_item#line_item-key\n     */\n    lineItemKeys: string;\n    /* eslint-enable @stylistic/max-len */\n  };\n\n  public shadowRoot!: ShadowRoot;\n\n  private onClickedBound = this.onClicked.bind(this);\n  private onCartUpdateStartedBound = this.onCartUpdateStarted.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 button = this.shadowRoot.querySelector('button');\n    button.removeEventListener('click', this.onClickedBound);\n    removeEventListener('cart-update-started', this.onCartUpdateStartedBound);\n  }\n\n  private render() {\n    const button = this.shadowRoot.querySelector('button');\n    button.addEventListener('click', this.onClickedBound);\n\n    addEventListener('cart-update-started', this.onCartUpdateStartedBound);\n  }\n\n  private onClicked(event: Event) {\n    const button = <HTMLButtonElement>event.currentTarget;\n\n    // We don't need to enable this button when cart update ended because the whole cart component\n    // rerenders when cart update.\n    button.disabled = true;\n    const lineItemKeys = this.dataset.lineItemKeys.split(',');\n    removeItems(lineItemKeys).catch(() => {\n      // ignore catch as it never happens.\n    });\n  }\n\n  private onCartUpdateStarted(_event: Event) {\n    // Prevent button click during the cart update\n    const button = this.shadowRoot.querySelector('button');\n\n    // We don't need to enable this button when cart update ended because the whole cart component\n    // rerenders when cart update.\n    button.disabled = true;\n  }\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'cart-item-remove-button': CartItemRemoveButton;\n  }\n}\n\nif (!customElements.get('cart-item-remove-button')) {\n  customElements.define('cart-item-remove-button', CartItemRemoveButton);\n}\n","export default \":host{display:inline-block}button{appearance:none;background:none;border:none;cursor:pointer;display:block;padding:0}button:disabled{opacity:.3;pointer-events:none}svg{display:block;height:24px;width:24px}@media only screen and (min-width:768px){svg{height:32px;width:32px}}\";","// Module\nvar code = \"<button aria-label=\\\"Remove item\\\"><svg xmlns=\\\"http://www.w3.org/2000/svg\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\"><title>Remove item</title><path d=\\\"M20.4 4.3L18.7 23.4H5.09999L3.39999 4.3\\\" stroke=\\\"black\\\" stroke-width=\\\"1.5\\\" stroke-miterlimit=\\\"10\\\"></path><path d=\\\"M7.70001 3.7V2.1C7.70001 1.5 8.00001 1 8.30001 1H15.6C15.9 1 16.2 1.5 16.2 2.1V3.7\\\" stroke=\\\"black\\\" stroke-width=\\\"1.5\\\" stroke-miterlimit=\\\"10\\\"></path><path d=\\\"M1 4.3H22.8\\\" stroke=\\\"black\\\" stroke-width=\\\"1.5\\\" stroke-miterlimit=\\\"10\\\"></path></svg></button>\";\n// Exports\nexport default code;","import type * as ajax from '@integrabeauty/shopify-ajax-api';\nimport * as CallUtils from '../../../lib/call-utils';\nimport updateCartHtml from '../update-cart-html';\n\n/**\n * Utility method to update a users Shopify cart note or attributes and multiple line item\n * quantities in the shopping cart using the provided Ajax API endpoint.\n *\n * CAUTION: This endpoint does not validate inventory levels for variants already in the cart,\n * meaning it is possible to add more inventory than is available in this particular use case.\n *\n * The imported CallUtils methods emit events to notify any view layer logic listening so it can\n * implement any required changes to update the user of the application state. You only need to use\n * these methods if you want the UX/UI to represent and/or provide messaging for the asynchronous\n * request.\n *\n * @param payload update cart request payload\n * @param notifyView passed on to ofir-cart-call-ended event to for view layer listeners\n *\n * @returns cart data\n *\n * @see https://shopify.dev/api/ajax/reference/cart#post-locale-cart-update-js\n */\n\nexport async function updateCart(\n  payload: ajax.CartUpdateInput,\n  notifyView = true\n) {\n  CallUtils.startCall('updateCart');\n\n  const updateStartedEvent = new Event('cart-update-started', {\n    cancelable: false\n  });\n  dispatchEvent(updateStartedEvent);\n\n  let response;\n  let cart;\n\n  try {\n    const body = JSON.stringify({ ...payload, sections: 'modal-cart' });\n    response = await fetch('/cart/update.js', {\n      method: 'POST',\n      body,\n      headers: {\n        'Content-Type': 'application/json'\n      }\n    });\n\n    if (!response.ok) {\n      throw new Error(`CartService.updateCart Error: ${response.status} ${response.statusText} ` +\n        response.url);\n    }\n\n    cart = <ajax.Cart> await response.json();\n\n    if (cart.sections?.['modal-cart']) {\n      updateCartHtml(cart.sections['modal-cart']);\n    }\n\n    const customEvent = new CustomEvent('cart-updated', {\n      cancelable: false,\n      detail: {\n        cart,\n        payload,\n        success: true\n      }\n    });\n    dispatchEvent(customEvent);\n  } catch (error) {\n    const detail = {\n      error_code: response?.status,\n      error_message: response?.statusText,\n      payload,\n      success: false\n    };\n\n    window.Sentry?.captureException(error, {\n      extra: {\n        ...detail,\n        source: 'cart-service-update-cart'\n      }\n    });\n\n    const customEvent = new CustomEvent('cart-updated', {\n      cancelable: false,\n      detail\n    });\n    dispatchEvent(customEvent);\n  } finally {\n    CallUtils.endCall(notifyView, false);\n  }\n\n  return cart;\n}\n\ntype CartUpdateStartedEvent = Event;\n\ntype CartUpdatedEvent = CustomEvent<{\n  /**\n   * In case of an error while updating the cart the event will be sent without the `cart`\n   * property.\n   */\n  cart?: ajax.Cart;\n  error_code?: number;\n  error_message?: string;\n\n  /**\n   * The payload that was sent to the server for the cart update.\n   * This is optional because we dispatch the 'cart-updated' event also when adding a product to\n   * the cart, and in that case there is no payload for cart update. This is neccessary to support\n   * the upsell modal.\n   *\n   * @todo the whole cart flow should be refactored in a L'ange way\n   */\n  payload?: ajax.CartUpdateInput;\n  success: boolean;\n}>;\n\ndeclare global {\n  interface WindowEventMap {\n    'cart-update-started': CartUpdateStartedEvent;\n    'cart-updated': CartUpdatedEvent;\n  }\n}\n","import * as CartService from './cart-service';\n\n/**\n * Build an array of attributes based on page state.\n *\n * We collect some attributes from the currently loaded page and stash them in the checkout,\n * treating it like a server-side session store. These are important attributes to retain across\n * multiple browser sessions, such as when a visitor resumes an abandoned cart in a new browser\n * session. We could probably come up with other ways to stitch session data together but a lot of\n * backend functionality is currently written that assumes these properties exist.\n *\n * An ideal system would be something like Segment. We send values we want to retain at session\n * scope in misc. track or identify or page events to Segment, and then we aggregate by session\n * within Segment across multiple events to get a whole picture. However, we did not originally use\n * Segment when the site was first designed, and for now are continuing the legacy practice.\n *\n * The facebook attribution service uses some of these properties to link LittleData order completed\n * events to ad click events captured in Segment.\n */\nfunction gatherAttributes() {\n  const url = new URL(location.href);\n  const attributes = [];\n\n  attributes.push({\n    key: 'checkout_started_ua',\n    value: navigator.userAgent\n  });\n\n  // google related url param\n  const gclid = url.searchParams.get('gclid')?.trim();\n  if (gclid) {\n    attributes.push({\n      key: 'gclid',\n      value: gclid\n    });\n  }\n\n  // google related url param, related to impersonal aggregated user identification\n  const gbraid = url.searchParams.get('gbraid')?.trim();\n  if (gbraid) {\n    attributes.push({\n      key: 'gbraid',\n      value: gbraid\n    });\n  }\n\n  // google related url param, related to impersonal aggregated user identification\n  const wbraid = url.searchParams.get('wbraid')?.trim();\n  if (wbraid) {\n    attributes.push({\n      key: 'wbraid',\n      value: wbraid\n    });\n  }\n\n  const transactionId = url.searchParams.get('transaction_id')?.trim();\n  if (transactionId) {\n    attributes.push({\n      key: 'hasoffers',\n      value: location.href\n    });\n    attributes.push({\n      key: 'hasoffers_updated_at',\n      value: Date.now().toString()\n    });\n  }\n\n  const adId = url.searchParams.get('ad.id')?.trim();\n  if (adId && adId !== '{ad.id}' && adId !== '{{ad.id}}') {\n    attributes.push({\n      key: 'facebook_ad_id',\n      value: adId\n    });\n  }\n\n  const fbclid = url.searchParams.get('fbclid')?.trim();\n  if (fbclid && fbclid !== '{fbclid}' && fbclid !== '{{fbclid}}') {\n    attributes.push({\n      key: 'fbclid',\n      value: fbclid\n    });\n  }\n\n  const utmCampaign = url.searchParams.get('utm_campaign')?.trim();\n  if (utmCampaign) {\n    attributes.push({\n      key: 'utm_campaign',\n      value: utmCampaign\n    });\n  }\n\n  const utmSource = url.searchParams.get('utm_source')?.trim();\n  if (utmSource) {\n    attributes.push({\n      key: 'utm_source',\n      value: utmSource\n    });\n  }\n\n  const utmMedium = url.searchParams.get('utm_medium')?.trim();\n  if (utmMedium) {\n    attributes.push({\n      key: 'utm_medium',\n      value: utmMedium\n    });\n  }\n\n  if (utmSource?.toLowerCase() === 'attentive' && utmMedium?.toLowerCase() === 'sms') {\n    attributes.push({\n      key: 'attentive_last_click_epoch',\n      value: Date.now().toString()\n    });\n  }\n\n  const affiliate = url.searchParams.get('aff');\n  if (affiliate) {\n    attributes.push({\n      key: 'affiliate',\n      value: affiliate\n    });\n  }\n\n  const klaviyoId = getKlaviyoId();\n  if (klaviyoId) {\n    attributes.push({\n      key: 'klaviyo_id',\n      value: klaviyoId\n    });\n  }\n\n  const clickId = getKlaviyoClickId();\n  if (clickId) {\n    attributes.push({\n      key: 'klaviyo_click_id',\n      value: clickId\n    }, {\n      key: 'klaviyo_last_click_epoch',\n      value: Date.now().toString()\n    });\n  }\n\n  const fbp = getCookie('fbp');\n  if (fbp) {\n    attributes.push({\n      key: 'fbp',\n      value: fbp\n    });\n  }\n\n  const fbc = getCookie('fbc');\n  if (fbc) {\n    attributes.push({\n      key: 'fbc',\n      value: fbc\n    });\n  }\n\n  try {\n    // For some reason the value is sometimes wrapped in quotes\n    const tiktokSessionId = sessionStorage?.getItem('tt_sessionId')?.trim()?.replace(/\"/g, '');\n    if (tiktokSessionId) {\n      attributes.push({\n        key: 'tiktok_session_id',\n        value: tiktokSessionId\n      });\n    }\n  } catch (error) {\n    // ignore\n  }\n\n  return attributes;\n}\n\n/**\n * @param cookieName key value of cookie being retrieved\n */\nfunction getCookie(cookieName: string) {\n  const name = cookieName + '=';\n  const cookies = document.cookie.split(';');\n  for (let cookie of cookies) {\n    while (cookie.charAt(0) === ' ') {\n      cookie = cookie.substring(1);\n    }\n\n    if (cookie.indexOf(name) === 0) {\n      return cookie.substring(name.length, cookie.length);\n    }\n  }\n\n  return undefined;\n}\n\nfunction getKlaviyoId() {\n  const encoded = getCookie('__kla_id');\n  if (encoded) {\n    const decoded = atob(encoded);\n    const parsed: { cid: string; } = JSON.parse(decoded);\n    if (parsed.cid) {\n      return atob(parsed.cid);\n    }\n  }\n}\n\n/**\n * @see https://help.klaviyo.com/hc/en-us/articles/115005076767#h_01HADAYAACVVC4BXQ0ES5Y50TC\n */\nfunction getKlaviyoClickId() {\n  const url = new URL(location.href);\n  const kx = url.searchParams.get('_kx');\n  if (kx) {\n    return kx;\n  }\n}\n\nfunction onDOMContentLoaded() {\n  const attributeKeyValues = gatherAttributes();\n  const attributes: Record<string, string> = {};\n\n  for (const attribute of attributeKeyValues) {\n    attributes[attribute.key] = attribute.value;\n  }\n\n  CartService.updateCart({ attributes }, false)\n    .catch(error => {\n      window.Sentry?.captureException(error, {\n        extra: {\n          ...attributes,\n          source: 'cart-attribution-update-cart'\n        }\n      });\n    });\n}\n\naddEventListener('DOMContentLoaded', onDOMContentLoaded);\n","import * as LiquidGlobals from '../../common/liquid-global';\n\nfunction loadCheckoutHandler() {\n  const cartPage = document.getElementById('cart-page');\n  if (!cartPage) {\n    return;\n  }\n\n  const checkoutCta = cartPage.querySelector('.cart__checkout');\n  if (checkoutCta) {\n    checkoutCta.addEventListener('click', onCheckoutClicked);\n  }\n}\n\n/**\n * Handles the click event on the checkout CTA on the cart page.\n * We want to display the upsell modal when the checkout button is clicked, but only if it wasn't\n * displayed before. If the upsell modal was already displayed, we want to proceed to checkout as\n * normal.\n */\nfunction onCheckoutClicked(event: Event) {\n  const upsellModal = document.querySelector('#modal-upsell');\n  if (!upsellModal) {\n    console.warn('#modal-upsell element not found');\n    return;\n  }\n\n  if (cart_drawer_upsell_modal_displayed) {\n    return;\n  }\n\n  event.preventDefault();\n\n  const modalShowEvent = new CustomEvent('upsell-modal-show-requested');\n  dispatchEvent(modalShowEvent);\n\n  cart_drawer_upsell_modal_displayed = true;\n}\n\nif (LiquidGlobals.Template.name === 'cart') {\n  addEventListener('DOMContentLoaded', loadCheckoutHandler);\n  addEventListener('cart-html-updated', loadCheckoutHandler);\n}\n","import type * as ajax from '@integrabeauty/shopify-ajax-api';\nimport * as LiquidGlobal from '../../common/liquid-global';\nimport * as CartService from './cart-service';\n\nexport function loadCartModal() {\n  const cartModalElement = document.getElementById('cart-modal');\n  if (!cartModalElement) {\n    return;\n  }\n\n  const modalContentElement = cartModalElement.querySelector('.modal-content');\n  if (!modalContentElement) {\n    return;\n  }\n\n  const closeModalElement = cartModalElement.querySelector('.cart__close');\n  if (!closeModalElement) {\n    return;\n  }\n\n  closeModalElement.addEventListener('click', onCloseClicked);\n\n  modalContentElement.addEventListener('click', function (event: Event) {\n    // TODO why is this needed? Review, add comments or remove\n    if (!closeModalElement.contains(<HTMLElement>event.target)) {\n      event.stopPropagation();\n    }\n  });\n\n  const checkoutCta = cartModalElement.querySelector('.cart__checkout');\n  if (checkoutCta) {\n    checkoutCta.addEventListener('click', onCheckoutClicked);\n  }\n}\n\nfunction onCloseClicked(event: Event) {\n  event.preventDefault();\n  closeModal();\n}\n\n/**\n * Handles the click event on the checkout CTA in the cart modal.\n * We want to display the upsell modal when the checkout button is clicked, but only if it wasn't\n * displayed before. If the upsell modal was already displayed, we want to proceed to checkout as\n * normal.\n */\nfunction onCheckoutClicked(event: Event) {\n  // check if the upsell modal exists\n  const upsellModal = document.querySelector('#modal-upsell');\n  if (!upsellModal) {\n    console.warn('#modal-upsell element not found');\n    return;\n  }\n\n  // the upsell modal should be displayed only once, if it was already displayed, proceed to\n  // checkout\n  if (cart_drawer_upsell_modal_displayed) {\n    return;\n  }\n\n  // block going to checkout and open the upsell modal instead\n\n  event.preventDefault();\n\n  closeModal();\n\n  const modalShowEvent = new Event('upsell-modal-show-requested');\n  dispatchEvent(modalShowEvent);\n\n  // set a global variable to indicate that the upsell modal was displayed\n  cart_drawer_upsell_modal_displayed = true;\n}\n\nfunction onShroudClicked(event: WindowEventMap['shroud-clicked']) {\n  const modal = document.querySelector('#cart-modal');\n  if (modal === event.detail.element) {\n    closeModal();\n  }\n}\n\nfunction closeModal() {\n  const cartModalElement = document.getElementById('cart-modal');\n  if (!cartModalElement) {\n    console.warn('#cart-modal element not found');\n    return;\n  }\n\n  cartModalElement.classList.add('hidden');\n\n  // send event to modal-manager so it can show the modal shroud and handle accessibility\n  type Detail = WindowEventMap['modal-close-requested']['detail'];\n  const modalCloseEvent = new CustomEvent<Detail>('modal-close-requested', {\n    detail: { element: cartModalElement }\n  });\n  dispatchEvent(modalCloseEvent);\n}\n\nfunction openModal() {\n  const modal = document.getElementById('cart-modal');\n\n  // check if the modal exists, expected to be always in the DOM but just in case, if it doesn't\n  // exist, log a warning and return\n  if (!modal) {\n    console.warn('#modal-upsell element not found');\n    return;\n  }\n\n  // cart is already open, do nothing\n  if (!modal.classList.contains('hidden')) {\n    return;\n  }\n\n  modal.classList.remove('hidden');\n\n  CartService.getCart(false).then((cart: ajax.Cart) => {\n    const detail = <OfirCustomEvents.ViewCartEventDetails>{\n      items: cart.items,\n      source: 'cart-header-icon'\n    };\n    const viewCartEvent = new CustomEvent('ofir-view-cart', {\n      cancelable: false,\n      detail\n    });\n\n    dispatchEvent(viewCartEvent);\n  }).catch(console.error);\n\n  // send event to modal-manager so it can show the modal shroud and handle accessibility\n  type Detail = WindowEventMap['modal-show-requested']['detail'];\n  const modalShowEvent = new CustomEvent<Detail>('modal-show-requested', {\n    detail: { element: modal }\n  });\n  dispatchEvent(modalShowEvent);\n\n  // notify other components that the cart modal was opened, so they can react accordingly\n  const cartModalOpenedEvent = new Event('cart-modal-opened');\n  dispatchEvent(cartModalOpenedEvent);\n}\n\nfunction updateListeners(event: OfirCustomEvents.CartCallEndedEvent) {\n  if (event.detail.notify_view) {\n    loadCartModal();\n    openModal();\n  }\n}\n\nif (LiquidGlobal.Template.name !== 'cart') {\n  addEventListener('ofir-cart-call-ended', <EventListener>updateListeners);\n  addEventListener('DOMContentLoaded', loadCartModal);\n  addEventListener('cart-html-updated', loadCartModal);\n  addEventListener('cart-modal-show-requested', openModal);\n  addEventListener('cart-modal-close-requested', closeModal);\n  addEventListener('shroud-clicked', onShroudClicked);\n}\n\ndeclare global {\n  interface WindowEventMap {\n    'cart-modal-close-requested': Event;\n    'cart-modal-opened': Event;\n    'cart-modal-show-requested': Event;\n  }\n}\n","import type * as ajax from '@integrabeauty/shopify-ajax-api';\nimport * as CallUtils from '../../../lib/call-utils';\n\n/**\n * Utility method to retrieve a users current cart using the provided Shopify Ajax API endpoint.\n *\n * The imported CallUtils methods emit events to notify any view layer logic listening so it can\n * implement any required changes to update the user of the application state. You only need to use\n * these methods if you want the UX/UI to represent and/or provide messaging for the asynchronous\n * request.\n *\n * Since all Shopify cart interaction are done client side asynchronously, there are numorous use\n * cases involving the need for the most up-to-date shopping cart. Examples being after a user adds\n * an item to their cart or changes a quantity. The LiquiGlobal.Cart values would not be accurate,\n * and if required; users should utilize this method with emitStartStop value of false to not\n * interfere with UX/UI operations.\n *\n * @param notifyView passed on to ofir-cart-call-ended event to for view layer listeners (false)\n * @param emitStartStop passed as control to emit start and stop call events (false)\n *\n * @returns cart data\n *\n * @see https://shopify.dev/api/ajax/reference/cart#get-locale-cart-js\n */\nexport async function getCart(notifyView = true, emitStartStop = false) {\n  if (emitStartStop) {\n    CallUtils.startCall('getCart');\n  }\n\n  let response;\n  let cart;\n\n  try {\n    response = await fetch('/cart.js', {\n      method: 'GET',\n      headers: {\n        'Content-Type': 'application/json'\n      }\n    });\n\n    if (!response.ok) {\n      throw new Error(`CartService.getCart Error: ${response.status} ${response.statusText} ` +\n        response.url);\n    }\n\n    cart = <ajax.Cart> await response.json();\n  } catch (error) {\n    window.Sentry?.captureException(error, {\n      extra: {\n        source: 'cart-service-get-cart'\n      }\n    });\n  } finally {\n    if (emitStartStop) {\n      CallUtils.endCall(notifyView);\n    }\n  }\n\n  return cart;\n}\n","import type * as ajax from '@integrabeauty/shopify-ajax-api';\nimport * as CartService from './cart-service';\n\nasync function updateCartVariantQuantity(variantKey: string, quantity: number) {\n  const payload = <ajax.CartUpdateInput>{ updates: {} };\n  payload.updates[variantKey] = quantity;\n\n  await CartService.updateCart(payload);\n}\n\nfunction onQuantityChange(event: WindowEventMap['quantity-input-changed']) {\n  if (!event.detail?.variant_keys) {\n    return;\n  }\n\n  if (event.detail.source === 'cart-variant') {\n    // In the case of regular product variant `variant_keys` contains only one line item key\n    updateCartVariantQuantity(event.detail.variant_keys, event.detail.quantity)\n      .catch(error => {\n        throw new Error(<string>error);\n      });\n  }\n}\n\naddEventListener('quantity-input-changed', onQuantityChange);\n","import type { CustomElement } from '@integrabeauty/custom-elements';\nimport html from './index.html';\nimport styles from './index.scss';\n\n/**\n * Custom element that displays the free shipping progress message in the cart.\n *\n * Shows how much more the customer needs to spend to get free shipping, or confirms they qualify.\n * Updates automatically when the cart is updated via the `cart-updated` event.\n *\n * @example\n * <delivery-message\n *   data-shipping-threshold=\"75\"\n *   data-upsell=\"true\"\n * </delivery-message>\n */\nclass DeliveryMessage extends HTMLElement implements CustomElement {\n  public dataset!: {\n    /**\n     * The price threshold (in dollars) for free shipping. Used to calculate how much more the\n     * customer needs to spend.\n     */\n    shippingThreshold: string;\n\n    /**\n     * Whether the message is rendered in the upsell modal or not. Boolean represented as string.\n     *\n     * There are special visibility rules for the upsell modal:\n     *   - if the user qualify for free shipping before the upsell opens, the message will be hidden\n     *   - if the user doesn't qualify for free shipping before the upsell opens, the message\n     *     will be shown, and it will be updated on each product add to show the remaining amount\n     *     to get free shipping\n     *   - if the upsell modal is open and the user becomes qualified for free shipping after adding\n     *     a product to the cart, the message remains shown\n     */\n    upsell: 'false' | 'true';\n  };\n\n  public shadowRoot!: ShadowRoot;\n\n  /**\n   * Whether the user currently qualifies for free shipping.\n   * We need to keep track of this to know whether to hide the message when the upsell modal is\n   * about to be shown.\n   */\n  private hasFreeShipping = false;\n\n  private onCartUpdatedBound = this.onCartUpdated.bind(this);\n  private onUpsellModalShowRequestedBound = this.onUpsellModalShowRequested.bind(this);\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    addEventListener('cart-updated', this.onCartUpdatedBound);\n\n    if (this.dataset.upsell === 'true') {\n      addEventListener('upsell-modal-show-requested', this.onUpsellModalShowRequestedBound);\n    }\n  }\n\n  public disconnectedCallback() {\n    removeEventListener('cart-updated', this.onCartUpdatedBound);\n    removeEventListener('upsell-modal-show-requested', this.onUpsellModalShowRequestedBound);\n  }\n\n  /**\n   * Handles the `upsell-modal-show-requested` event.\n   * This event is emitted when the upsell modal is about to be shown.\n   */\n  private onUpsellModalShowRequested(_event: Event) {\n    // if the user qualifies for free shipping when the upsell modal is about to be shown, we hide\n    // the delivery message in the modal since it's not relevant anymore\n    if (this.hasFreeShipping) {\n      this.hidden = true;\n    }\n  }\n\n  /**\n   * Handles the `cart-updated` event.\n   * On each cart update, we check if the user qualifies for free shipping and update the message\n   * accordingly.\n   */\n  private onCartUpdated(event: WindowEventMap['cart-updated']) {\n    // it's possible for this event to fire before the element is connected, do nothing in that case\n    if (!this.isConnected) {\n      return;\n    }\n\n    const cart = event.detail?.cart;\n    if (!cart) {\n      return;\n    }\n\n    const hasSubscription = cart.items.some(item => item.selling_plan_allocation);\n\n    // convert from cents to dollars\n    const totalPrice = cart.total_price / 100;\n    const shippingThreshold = parseInt(this.dataset.shippingThreshold, 10);\n    this.hasFreeShipping = shippingThreshold - totalPrice <= 0 || hasSubscription;\n    const noFreeShipping = this.shadowRoot.querySelector('.no-free-shipping');\n    const freeShipping = this.shadowRoot.querySelector('.free-shipping');\n\n    if (this.hasFreeShipping) {\n      noFreeShipping.classList.add('hidden');\n      freeShipping.classList.remove('hidden');\n    } else {\n      // set remaining amount until free shipping\n      const tillFreeShipping = (shippingThreshold - totalPrice).toFixed(2).replace(/\\.00$/, '');\n      const remaining = this.shadowRoot.querySelector('.remaining');\n      remaining.textContent = `$${tillFreeShipping}`;\n\n      // set progress bar\n      const percent = Math.round((totalPrice / shippingThreshold) * 100);\n      const progress = this.shadowRoot.querySelector<HTMLElement>('.progress');\n      progress.style.width = `${percent}%`;\n\n      noFreeShipping.classList.remove('hidden');\n      freeShipping.classList.add('hidden');\n    }\n  }\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'delivery-message': DeliveryMessage;\n  }\n}\n\nif (!customElements.get('delivery-message')) {\n  customElements.define('delivery-message', DeliveryMessage);\n}\n","export default \":host{display:block}:host[hidden]{display:none}.title{font-size:1.125rem;font-weight:600}.subtitle{font-size:.875rem;margin-bottom:10px}.subtitle span{font-weight:600;letter-spacing:.07em;text-transform:uppercase}.progress-bar{background-color:#e6e7e8;border-radius:2px;height:4px;margin-top:10px;overflow:hidden;position:relative}.full,.progress{background-color:#000}.progress{bottom:0;left:0;position:absolute;top:0}.hidden{display:none}\";","// Module\nvar code = \"<div class=\\\"container\\\"><div class=\\\"title\\\">Delivery within the USA?</div><div class=\\\"no-free-shipping\\\"><div class=\\\"subtitle\\\">You're&#32;<span class=\\\"remaining\\\"></span>&#32;away from getting&#32;<span>FREE SHIPPING</span></div><div class=\\\"progress-bar\\\"><div class=\\\"progress\\\"></div></div></div><div class=\\\"free-shipping hidden\\\"><div class=\\\"subtitle\\\">You qualify for&#32;<span>FREE SHIPPING</span></div><div class=\\\"progress-bar full\\\"></div></div></div>\";\n// Exports\nexport default code;"],"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","AlertElement","HTMLElement","observedAttributes","constructor","super","onCloseClickedBound","this","onCloseClicked","attachShadow","mode","shadowRoot","innerHTML","concat","connectedCallback","render","disconnectedCallback","querySelector","removeEventListener","timerId","addEventListener","dataset","timer","remove","parseInt","_event","customElements","define","CartMessages","onAddToCart","onUpdateLineItem","clearMessages","detail","success","showErrorMessage","addedLineItemsString","items","map","item","title","join","messageHtml","showSuccessMessage","item_deleted","updatedItemId","updatedLineItem","cart","find","messaging","append","messages","querySelectorAll","splideSlidebarExtension","splide","components","options","slidebar","handle","maxPosition","maxTrackPosition","hasSlidebarMarkup","position","previousTouchX","enable","Elements","root","classList","onSplideResized","is","on","onSplideDragging","onSplideMoveStarted","onMousedown","onTouchstart","passive","onTransitionend","onSlidebarClicked","disable","add","off","calculateHandleWidth","handleWidth","perPage","Slides","getLength","Layout","listSize","sliderSize","processHandleMove","toPosition","newPosition","getHandlePositionWithinBounds","newSplidePosition","getCalculatedTrackPosition","Move","translate","requestAnimationFrame","style","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","currentTarget","newSlidebarPosition","offsetX","offsetWidth","newTrackPosition","width","onSplideOverflowed","getCalculatedSlidebarPosition","trackPosition","getEnd","getIndex","slidebarPosition","mount","__webpack_public_path__","window","UpsellSection","onCarouselSlotChangeBound","onCarouselSlotChange","onCartModalOpenedBound","onCartModalOpened","destroy","assignedElements","initCarousel","catch","console","warn","refresh","Splide","element","fixedWidth","perMove","rewind","arrows","pagination","gap","keyboard","omitEnd","getRequestId","response","headers","async","cartFetch","Shopify","routes","body","fetch","cache","ok","status","request_id","response_body","json","isObject","value","Array","isArray","startCall","_window$Sentry","_len","arguments","args","_key","Sentry","captureException","extra","level","endCall","Event","cancelable","dispatchEvent","notifyView","didTimeOut","CustomEvent","is_timeout","notify_view","__ofir","_window$__ofir","Cart","_window$__ofir2","Checkout","_window$__ofir3","Collection","_window$__ofir4","Customer","_window$__ofir5","GiftCard","_window$__ofir6","Order","_window$__ofir7","Page","_window$__ofir8","Pagination","_window$__ofir9","Product","_window$__ofir0","Request","_window$__ofir1","Scripts","_window$__ofir10","Search","_window$__ofir11","SearchEngineListing","_window$__ofir12","SectionSettings","_window$__ofir13","Shop","Template","_window$__ofir14","_window$__ofir15","Theme","_window$__ofir16","ThemeSettings","updateCartHtml","html","cartContentElement","LiquidGlobals","cartModalElement","getElementById","modalContentElement","cartCount","textContent","replace","cartCounterElement","cartPageElement","contains","removeItems","lineItemKeys","CallUtils","updateStartedEvent","updates","lineItemKey","payload","sections","_cart$sections","previousCart","ajax","input","JSON","stringify","method","_error$response_body3","request_body","response_status","statusText","cartUpdatedEvent","lineItem","removedEvent","_response","_response2","error_code","error_message","_extends","source","CartItemRemoveButton","onClickedBound","onClicked","onCartUpdateStartedBound","onCartUpdateStarted","disabled","split","updateCart","customEvent","gatherAttributes","_url$searchParams$get","_url$searchParams$get2","_url$searchParams$get3","_url$searchParams$get4","_url$searchParams$get5","_url$searchParams$get6","_url$searchParams$get7","_url$searchParams$get8","_url$searchParams$get9","URL","location","href","attributes","navigator","userAgent","gclid","searchParams","trim","gbraid","wbraid","Date","now","toString","adId","fbclid","utmCampaign","utmSource","utmMedium","toLowerCase","affiliate","klaviyoId","encoded","getCookie","decoded","atob","parsed","parse","cid","getKlaviyoId","clickId","kx","getKlaviyoClickId","fbp","fbc","_sessionStorage","tiktokSessionId","sessionStorage","getItem","cookieName","cookies","cookie","charAt","substring","indexOf","loadCheckoutHandler","cartPage","checkoutCta","onCheckoutClicked","cart_drawer_upsell_modal_displayed","preventDefault","modalShowEvent","loadCartModal","closeModalElement","stopPropagation","closeModal","modalCloseEvent","openModal","modal","emitStartStop","CartService","then","viewCartEvent","cartModalOpenedEvent","_event$detail","variant_keys","variantKey","quantity","updateCartVariantQuantity","attributeKeyValues","attribute","LiquidGlobal","DeliveryMessage","hasFreeShipping","onCartUpdatedBound","onCartUpdated","onUpsellModalShowRequestedBound","onUpsellModalShowRequested","upsell","hidden","isConnected","hasSubscription","selling_plan_allocation","totalPrice","total_price","shippingThreshold","noFreeShipping","freeShipping","tillFreeShipping","toFixed","percent"],"sourceRoot":""}