{"webLayers":[],"experiments":[],"constantManagedTags":[{"uses_overlay":false,"type":"html","parametrized_definition":"\u003cstyle\u003e\n\n/* ================================================ */\n/* Chat Window */\n/* ================================================ */\n\n/* specially for search orchestrator and search trigger */\n@keyframes slideFromRight {\n  to { transform: translateX(0); }\n}\n@keyframes slideToRight {\n  to { transform: translateX(100%); }\n}\n@keyframes fadeIn {\n  to { opacity: 1; }\n}\n@keyframes fadeOut {\n  to { opacity: 0; }\n}\n#cocoaas_chat_wrapper .clarity-with-animation-in {\n  /*transform: translateX(100%);*/\n  opacity: 0;\n  transform: unset;\n}\n#cocoaas_chat_wrapper .clarity-with-animation-in.clarity-minimized,\n#cocoaas_chat_wrapper .clarity-with-animation-in.clarity-resizable-chat-wrapper,\n#cocoaas_chat_wrapper .clarity-with-animation-in.clarity-survey-feedback {\n  animation-name: fadeIn;\n  animation-duration: 0.15s;\n}\n\n#cocoaas_chat_wrapper .clarity-with-animation-out {\n  /*transform: translateX(100%);*/\n  opacity: 1;\n  transform: unset;\n}\n#cocoaas_chat_wrapper .clarity-with-animation-out.clarity-minimized,\n#cocoaas_chat_wrapper .clarity-with-animation-out.clarity-resizable-chat-wrapper,\n#cocoaas_chat_wrapper .clarity-with-animation-out.clarity-survey-feedback {\n  animation-name: fadeOut;\n  animation-duration: 0.15s;\n}\n\n#cocoaas_chat_wrapper .clarity-resizable-chat-wrapper {\n\tborder-radius: 0;\n}\n\n#cocoaas_chat_wrapper .clarity-minimized {\n\tdisplay: none;\n}\n\n/*#cocoaas_chat_wrapper .clarity-resize-handle {*/\n/*  background-color: rgba(236, 237, 237);*/\n/*}*/\n\n#cocoaas_chat_wrapper\n  .clarity-mini-pdp--inside-container-overlay\n  .clarity-resize-handle {\n  background-color: transparent;\n}\n\n@media (min-width: 1024px) {\n\t#cocoaas_chat_wrapper#cocoaas_chat_wrapper .clarity-resizable-chat-wrapper .clarity-chat-container {\n\t\tmin-width: 47.5rem;\n\t\tmax-width: 47.5rem;\n\t  /*width: 47.5rem;*/\n\t}\n}\n\n#cocoaas_chat_wrapper .clarity-resizable-chat-wrapper .clarity-chat-container {\n\tmin-width: 100%;\n\tmax-width: 100%;\n}\n\n@media (min-width: 600px) {\n\t#cocoaas_chat_wrapper .clarity-resizable-chat-wrapper {\n\t  height: 100%;\n\t}\n}\n\n/*#cocoaas_chat_wrapper .clarity-header-content {*/\n/*  background: rgba(236, 237, 237);*/\n/*}*/\n\n#cocoaas_chat_wrapper .clarity-header-content .clarity-header-avatar-wrapper {\n  width: 16px;\n  height: 16px;\n}\n\n#cocoaas_chat_wrapper .clarity-header-content .clarity-chevron-down-icon {\n  width: 24px;\n  height: 24px;\n  fill: var(--icons-color-default, #262527);\n}\n\n#cocoaas_chat_wrapper .clarity-header-info .clarity-header-avatar-wrapper {\n  display: none;\n}\n\n#cocoaas_chat_wrapper .clarity-header-actions {\n  display: none;\n}\n\n#cocoaas_chat_wrapper .clarity-header-name {\n  font-size: 12px;\n  color: var(--typography-color-default, #262424);\n  font-style: normal;\n\n  font-weight: var(--typography-font-size-14-px-50, 400);\n  line-height: var(--typography-font-line-height-accent-overline-1, 16px); /* 114.286% */\n  letter-spacing: var(--typography-font-letter-spacing-accent-caption-1, 0);\n}\n\n#cocoaas_chat_wrapper .clarity-header-description {\n  display: none;\n}\n\n#cocoaas_chat_wrapper\n  .clarity-agent-carousel-product-spacer {\n  flex: none;\n  min-height: unset;\n}\n\n#cocoaas_chat_wrapper\n  .clarity-agent-carousel-product-subtitle,\n#cocoaas_chat_wrapper\n  .clarity-agent-carousel-product-title {\n  color: var(--typography-color-default, #2a1e17);\n\n  /* Accent/Overline 1 */\n  font-size: var(--typography-font-size-accent-overline-1, 12px);\n  font-style: normal;\n  font-weight: 400;\n  line-height: var(\n    --typography-font-line-height-accent-overline-1,\n    16px\n  ); /* 133.333% */\n  letter-spacing: var(--typography-font-letter-spacing-accent-overline-1, 0);\n}\n\n#cocoaas_chat_wrapper\n  .clarity-agent-carousel-product-content-footer {\n  display: none;\n}\n\n#cocoaas_chat_wrapper .clarity-agent-carousel-item-container,\n#cocoaas_chat_wrapper .clarity-assistant-carousel-item-container {\n\tdisplay: grid;\n\tgrid-template-columns: repeat(3, 1fr);\n\tgap: 24 4px;\n}\n\n@media (max-width: 768px) {\n\t#cocoaas_chat_wrapper .clarity-agent-carousel-item-container,\n\t#cocoaas_chat_wrapper .clarity-assistant-carousel-item-container {\n\t\tgrid-template-columns: repeat(2, 1fr);\n\t}\n}\n\n#cocoaas_chat_wrapper .clarity-agent-carousel-item-content {\n\tborder-radius: unset;\n}\n\n#cocoaas_chat_wrapper .clarity-agent-carousel-item-shadow,\n#cocoaas_chat_wrapper .clarity-assistant-carousel-item-shadow {\n\tmax-width: unset;\n\tmin-width: unset;\n\twidth: 100%;\n}\n\n#cocoaas_chat_wrapper .clarity-assistant-carousel-item-content {\n  background: white;\n  border-radius: 4px;\n  border: unset;\n}\n\n#cocoaas_chat_wrapper .clarity-see-all-results-button {\n\tcolor: var(--components-buttons-style-secondary-primary-inverse-transparent-text, #2A1E17);\n\tpadding: 8px 24px;\n\ttext-align: center;\n\tborder-radius: var(--components-buttons-radius-button, 2px);\n\tborder: var(--components-buttons-style-secondary-primary-inverse-transparent-secondary-stroke-width, 1px) solid var(--components-buttons-style-secondary-primary-inverse-transparent-secondary-stroke, #2A1E17);\n\tbackground: var(--page-background, #FFF);\n\t\n\t/* Buttons/Buttons 2 */\n\tfont-size: var(--typography-font-size-buttons-buttons-2, 14px);\n\tfont-style: normal;\n\tfont-weight: 500;\n\tline-height: var(--typography-font-line-height-buttons-buttons-2, 18px); /* 128.571% */\n\tletter-spacing: var(--typography-font-letter-spacing-buttons-buttons-2, 0.175px);\n}\n\n#cocoaas_chat_wrapper .clarity-message-container {\n\t/* Body/Body Copy 1/Default */\n\tfont-size: var(--typography-font-size-body-body-1, 16px);\n\tfont-style: normal;\n\tfont-weight: 400;\n\tline-height: var(--typography-font-line-height-body-body-1, 20px); /* 125% */\n\tletter-spacing: var(--typography-font-letter-spacing-body-body-1, 0);\n}\n\n#cocoaas_chat_wrapper .clarity-message-timestamp {\n  /* Accent/Caption 1 */\n  /*font-family: var(--typography-font-family-caption, \"Helvetica Neue LT Std\");*/\n  font-size: 10px;\n  color: #606263;\n  font-style: normal;\n  font-weight: 400;\n  line-height: var(\n    --typography-font-line-height-action-overline-1,\n    16px\n  ); /* 133.333% */\n  letter-spacing: var(\n    --typography-font-letter-spacing-action-caption-1,\n    0.06px\n  );\n}\n\n#cocoaas_chat_wrapper .clarity-user-text-message {\n\tpadding: 16px 15px;\n\tborder-radius: 16px 16px 0 16px;\n\tbackground: var(--surface-neutral-neutrals-3, #E1E1E1);\n\tbox-shadow: 0 4px 4px 0 rgba(0, 0, 0, 0.02);\n\t\n\t/* Body/Body Copy 1/Strong */\n\tfont-size: var(--typography-font-size-body-body-1, 16px);\n\tfont-style: normal;\n\tline-height: var(--typography-font-line-height-body-body-1, 20px); /* 125% */\n\tletter-spacing: var(--typography-font-letter-spacing-body-body-1, 0);\n}\n\n#cocoaas_chat_wrapper .clarity-assistant-text-message {\n  color: var(--typography-color-default, #262424);\n\n\t/* Body/Body Copy 1/Default */\n\tfont-size: var(--typography-font-size-body-body-1, 16px);\n\tfont-style: normal;\n\tfont-weight: 400;\n\tline-height: var(--typography-font-line-height-body-body-1, 20px); /* 125% */\n\tletter-spacing: var(--typography-font-letter-spacing-body-body-1, 0);\n}\n\n#cocoaas_chat_wrapper .clarity-assistant-carousel-product {\n\tpadding: 12px;\n}\n\n#cocoaas_chat_wrapper .clarity-assistant-carousel-product-title {\n  color: var(--typography-color-default, #262424);\n  text-decoration: unset;\n\n\t/* Body/Body Copy 1/Strong */\n\tfont-size: var(--typography-font-size-body-body-1, 16px);\n\tfont-style: normal;\n\tfont-weight: 500;\n\tline-height: var(--typography-font-line-height-body-body-1, 20px); /* 125% */\n\tletter-spacing: var(--typography-font-letter-spacing-body-body-1, 0);\n}\n\n#cocoaas_chat_wrapper .clarity-assistant-carousel-product-variants {\n\tdisplay: none;\n}\n\n#cocoaas_chat_wrapper .clarity-assistant-carousel-product-spacer {\n\tflex: none;\n\tmin-height: 8px;\n}\n\n#cocoaas_chat_wrapper .clarity-assistant-carousel-product-price {\n  color: var(--typography-color-default, #262424);\n\n\t/* Accent/Overline 1 */\n\tfont-size: var(--typography-font-size-accent-overline-1, 12px);\n\tfont-style: normal;\n\tfont-weight: 400;\n\tline-height: var(--typography-font-line-height-accent-overline-1, 16px); /* 133.333% */\n\tletter-spacing: var(--typography-font-letter-spacing-accent-overline-1, 0);\n}\n\n#cocoaas_chat_wrapper .clarity-assistant-carousel-product-original-price {\n\tcolor: #D51920;\n}\n\n#cocoaas_chat_wrapper .clarity-assistant-carousel-product-content-footer-buttons {\n\tdisplay: none;\n}\n\n#cocoaas_chat_wrapper .clarity-assistant-quick-reply-prompt-button,\n#cocoaas_chat_wrapper .clarity-mini-pdp-dimensions-option {\n  padding: 12px;\n  border-radius: 100px;\n  border: 1px solid var(--border-color-light, #E1E1E1);\n  box-shadow: 0 4px 4px 0 rgba(0, 0, 0, 0.02);\n  background-color: unset;\n}\n\n#cocoaas_chat_wrapper .clarity-assistant-quick-reply-button-text,\n#cocoaas_chat_wrapper .clarity-mini-pdp-dimensions-option {\n\ttext-align: center;\n\t\n\t/* Accent/Caption 1 */\n\tfont-size: var(--typography-font-size-overline-overline-1, 12px);\n\tfont-style: normal;\n\tfont-weight: 400;\n\tline-height: var(--typography-font-line-height-action-overline-1, 16px); /* 133.333% */\n\tletter-spacing: var(--typography-font-letter-spacing-action-caption-1, 0);\n}\n\n#cocoaas_chat_wrapper .clarity-assistant-quick-reply-prompt-button:hover,\n#cocoaas_chat_wrapper .clarity-mini-pdp-dimensions-option:hover,\n#cocoaas_chat_wrapper .clarity-mini-pdp-dimensions-option.active {\n\tborder: 1px solid #111112;\n\tbackground: var(--components-AI-search-chips-pill, #262424);\n\tbox-shadow: 0 4px 4px 0 rgba(0, 0, 0, 0.02);\n}\n\n#cocoaas_chat_wrapper .clarity-assistant-quick-reply-prompt-button:hover .clarity-assistant-quick-reply-button-text,\n#cocoaas_chat_wrapper .clarity-assistant-quick-reply-prompt-button.active .clarity-assistant-quick-reply-button-text,\n#cocoaas_chat_wrapper .clarity-mini-pdp-dimensions-option:hover,\n#cocoaas_chat_wrapper .clarity-mini-pdp-dimensions-option.active {\n\tcolor: var(--typography-color-default-inverse, #F3F3F3);\n}\n\n#cocoaas_chat_wrapper\n  .clarity-assistant-quick-reply-prompt-button\n  .clarity-prompt-icon {\n  display: none;\n}\n\n#cocoaas_chat_wrapper\n  .clarity-assistant-quick-reply-prompt-button:hover\n  .clarity-prompt-icon {\n  display: none;\n}\n\n#cocoaas_chat_wrapper .clarity-input-shadow.clarity-focused::before,\n#cocoaas_chat_wrapper .clarity-input-shadow.clarity-focused::after {\n\tcontent: unset;\n}\n\n#cocoaas_chat_wrapper .clarity-input-shadow .clarity-input-container {\n\tborder: unset;\n\tpadding: 12px 8px;\n\tborder-radius: 2px;\n\tbackground: var(--Vans-colors-off-white, #F3F3F3);\n}\n\n#cocoaas_chat_wrapper .clarity-input-container {\n  display: flex;\n  align-items: center;\n  gap: 8px;\n}\n\n#cocoaas_chat_wrapper .clarity-input-container::before {\n  content: \"\";\n  display: block;\n  flex-shrink: 0;\n  width: 24px;\n  height: 24px;\n  background-image: url(\"data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M11.0028 3C6.5831 3 3 6.58313 3 11.0029C3 15.4226 6.5831 19.0058 11.0028 19.0058C12.988 19.0058 14.8044 18.2829 16.2031 17.086L19.9342 20.8171L20.0207 20.8894C20.264 21.0579 20.6004 21.0339 20.8171 20.8171C21.061 20.5733 21.061 20.178 20.8171 19.9342L17.086 16.203C18.2828 14.8043 19.0056 12.988 19.0056 11.0029C19.0056 6.58313 15.4225 3 11.0028 3ZM11.0028 4.24869C14.7329 4.24869 17.757 7.27277 17.757 11.0029C17.757 14.733 14.7329 17.7571 11.0028 17.7571C7.2727 17.7571 4.24865 14.733 4.24865 11.0029C4.24865 7.27277 7.2727 4.24869 11.0028 4.24869Z' fill='%23262424'/%3E%3Cpath d='M13.3108 12.0018C11.5727 12.576 10.994 13.1549 10.4197 14.8928C10.3725 15.0357 10.1704 15.0357 10.1232 14.8928C9.54898 13.1548 8.97011 12.576 7.23216 12.0018C7.08928 11.9546 7.08928 11.7525 7.23216 11.7053C8.9702 11.1311 9.54896 10.5522 10.1232 8.81427C10.1704 8.67139 10.3725 8.67139 10.4197 8.81427C10.9939 10.5523 11.5728 11.1311 13.3108 11.7053C13.4536 11.7525 13.4536 11.9546 13.3108 12.0018Z' fill='%23262424'/%3E%3Cpath d='M14.5714 9.14755C13.7026 9.43447 13.413 9.72407 13.1257 10.5933C13.1023 10.6647 13.0013 10.6647 12.9774 10.5933C12.6905 9.72445 12.4009 9.43486 11.5317 9.14755C11.4603 9.12412 11.4603 9.02311 11.5317 8.99929C12.4005 8.71237 12.6901 8.42277 12.9774 7.55358C13.0009 7.48214 13.1019 7.48214 13.1257 7.55358C13.4126 8.42239 13.7022 8.71198 14.5714 8.99929C14.6429 9.02272 14.6429 9.12374 14.5714 9.14755Z' fill='%23262424'/%3E%3C/svg%3E\");\n  background-size: contain;\n  background-repeat: no-repeat;\n  background-position: center;\n}\n\n#cocoaas_chat_wrapper .clarity-input-textarea::-webkit-input-placeholder {\n  color: var(--typography-color-secondary, #707070);\n\n\t/* Body/Body Copy 1/Default */\n\tfont-size: var(--typography-font-size-body-body-1, 16px);\n\tfont-style: normal;\n\tfont-weight: 400;\n\tline-height: var(--typography-font-line-height-body-body-1, 24px); /* 125% */\n\tletter-spacing: var(--typography-font-letter-spacing-body-body-1, 0);\n}\n\n#cocoaas_chat_wrapper .clarity-input-textarea::-moz-placeholder {\n  color: var(--typography-color-secondary, #707070);\n\n\t/* Body/Body Copy 1/Default */\n\tfont-size: var(--typography-font-size-body-body-1, 16px);\n\tfont-style: normal;\n\tfont-weight: 400;\n\tline-height: var(--typography-font-line-height-body-body-1, 24px); /* 125% */\n\tletter-spacing: var(--typography-font-letter-spacing-body-body-1, 0);\n}\n\n#cocoaas_chat_wrapper .clarity-input-textarea::placeholder {\n  color: var(--typography-color-secondary, #707070);\n\n\t/* Body/Body Copy 1/Default */\n\tfont-size: var(--typography-font-size-body-body-1, 16px);\n\tfont-style: normal;\n\tfont-weight: 400;\n\tline-height: var(--typography-font-line-height-body-body-1, 24px); /* 125% */\n\tletter-spacing: var(--typography-font-letter-spacing-body-body-1, 0);\n}\n\n#cocoaas_chat_wrapper .clarity-chat-legal-notice-container {\n  display: none;\n}\n\n#cocoaas_chat_wrapper .clarity-mini-pdp-title {\n  color: var(--typography-color-default, #262424);\n\n\t/* Title/Title 2/Desktop */\n\tfont-size: var(--typography-font-size-title-title-2-desktop, 20px);\n\tfont-style: normal;\n\tfont-weight: 700;\n\tline-height: var(--typography-font-line-height-title-title-2-desktop, 25px); /* 125% */\n\tletter-spacing: var(--typography-font-letter-spacing-title-title-2-desktop, 0);\n}\n\n#cocoaas_chat_wrapper .clarity-mini-pdp-price {\n  color: var(--typography-color-default, #262424);\n\n\t/* Subtitle/Subtitle 2/desktop */\n\tfont-size: var(--typography-font-size-subtitle-subtitle-2, 20px);\n\tfont-style: normal;\n\tfont-weight: 400;\n\tline-height: var(--typography-font-line-height-subtitle-subtitle-2, 24px); /* 120% */\n\tletter-spacing: var(--typography-font-letter-spacing-subtitle-subtitle-2, 0);\n}\n\n#cocoaas_chat_wrapper .clarity-mini-pdp-dimensions-name,\n#cocoaas_chat_wrapper .clarity-mini-pdp .clarity-attribute-name {\n  color: var(--typography-color-default, #262424);\n  text-transform: capitalize;\n\n\t/* Accent/Overline 1 */\n\tfont-size: var(--typography-font-size-accent-overline-1, 12px);\n\tfont-style: normal;\n\tfont-weight: 400;\n\tline-height: var(--typography-font-line-height-accent-overline-1, 16px); /* 133.333% */\n\tletter-spacing: var(--typography-font-letter-spacing-accent-overline-1, 0);\n}\n\n#cocoaas_chat_wrapper .clarity-mini-pdp .clarity-attribute-value {\n  color: var(--typography-color-default, #262424);\n  \n\t/* Accent/Overline 1 */\n\tfont-size: var(--typography-font-size-accent-overline-1, 12px);\n\tfont-style: normal;\n\tfont-weight: 400;\n\tline-height: var(--typography-font-line-height-accent-overline-1, 16px); /* 133.333% */\n\tletter-spacing: var(--typography-font-letter-spacing-accent-overline-1, 0);\n}\n\u003c/style\u003e","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"6a0de0e3fbe4f84383791b70"},{"uses_overlay":false,"type":"js","parametrized_definition":"const pdpWeblayerId = \"6a1f305c87d86cb5decfb775\";\nconst searchWeblayerId = \"6a0de0e3fbe4f84383791b61\";\n\nconst loadClarityUtils = async () =\u003e {\n  const url = 'https://unpkg.com/@bloomreach/clarity-utils@1.0.8/dist/index.global.js'\n  for (let attempt = 1; attempt \u003c= 5; attempt++) {\n    try {\n      await new Promise((resolve, reject) =\u003e {\n        const s = document.createElement('script')\n        s.src = url\n        s.onload = resolve\n        s.onerror = () =\u003e reject(new Error(`Failed to load ${url}`))\n        document.head.appendChild(s)\n      })\n      return\n    } catch (err) {\n      console.warn(`clarity-utils load attempt ${attempt}/5 failed`, err)\n      if (attempt === 5) throw err\n      await new Promise(r =\u003e setTimeout(r, 200 * attempt))\n    }\n  }\n}\n\nconst clarityUtilsLoaded = loadClarityUtils()\n\nwindow.CLARITY_HELPER = {\n\t...(window.CLARITY_HELPER || {}),\n\tinvokePDP: () =\u003e {\n\t  window.CLARITY.setSource(pdpWeblayerId);\n      window.CLARITY.call('show_badge');\n      window.CLARITY.call('open_chat');\n\t},\n    invokeSearchHubOrch: input =\u003e {\n\t  window.CLARITY.setSource(searchWeblayerId);\n      window.CLARITY.call('show_badge');\n      window.CLARITY.call('open_chat');\n      window.CLARITY.call('user_send_message', {\n        input,\n        type: 'text',\n        force: true,\n        source: 'DEFAULT',\n      });\n\t},\n\tisSearch: async (input, config) =\u003e {\n\t  if (!input?.trim()) return;\n\t  console.log('clarity is search', input, config)\n\t  await clarityUtilsLoaded\n\t  const result = window.clarityUtils.isSearch(input, { mode: 'score', ...(config ?? {}) })\n\t  const logger = window.brweb ?? window.exponea\n\t  logger.track('clarity', {\n\t  \taction: 'search_orchestrator',\n\t  \tsearch_string: input,\n\t  \tis_conversational: !result\n\t  });\n\t  return result;\n\t},\n}","trigger":{"include_pages":[{"url":"/en-us","type":"contains"}],"exclude_pages":null},"_id":"6a0de0e3fbe4f84383791b75"},{"uses_overlay":false,"type":"js","parametrized_definition":"// A customized MiniPDP that combines tblBaseMiniPDP's variant/dimension UI\n// with timberlandATC's stock check + add-to-cart, and adds an \"Add to Cart\"\n// footer button.\n//\n// Behavior:\n//   - On product change, fetches the product inventory once. Out-of-stock\n//     variants render their dimension chips as `is-disabled` (greyed out and\n//     diagonal-striped), but remain CLICKABLE so the consumer can still\n//     navigate to the variant. The Add-to-Cart button switches to a disabled\n//     \"Out of Stock\" state when the active variant is out of stock.\n//   - The Add-to-Cart button posts to Timberland's cart API, persisting the\n//     cartId in localStorage so the next add appends to the same cart.\n//\n// CSS: load tblCusotmized.css — it is self-contained (base layout + ATC\n// footer additions). Do NOT also load tblBaseMiniPDP.css.\n//\n// Usage: load this file as a plain script (not a module) alongside the two\n// CSS files. It registers tblCusotmized + tblCusotmizedATC on\n// window.CLARITY_GLOBAL_CONFIG.\n\nconst ORIGIN = location.origin;\n\nconst DIMENSION_NAMES = ['color', 'size', 'length', 'width', 'material', 'style', 'flavor']\n\nconst FAKE_LENGTHS = ['Medium', 'Wide']\n\n// ATC animation: progress bar fills over ATC_ANIMATION_MS while the request is\n// in flight; the result label (View Cart / Failed) shows for ATC_RESET_MS, then\n// the button reverts to \"Add to Cart\".\nconst ATC_ANIMATION_MS = 1800\nconst ATC_RESET_MS = 3000\n\n\nconst injectFakeLengthDimension = product =\u003e {\n  if (!product?.variants?.length) return product\n  if (product.variants[0]?.length != null \u0026\u0026 product.variants[0].length !== '') return product\n  const augmented = []\n  product.variants.forEach(v =\u003e {\n    FAKE_LENGTHS.forEach(length =\u003e augmented.push({ ...v, length }))\n  })\n  return { ...product, variants: augmented }\n}\n\n// === Timberland ATC helpers (mirrors timberlandATC.js) ===\n\nconst getChatId = () =\u003e {\n  try {\n    const raw = localStorage.getItem('BR:CLARITY') ?? sessionStorage.getItem('BR:CLARITY') ?? '{}'\n    const chatIdStore = JSON.parse(raw)?.chatId ?? {}\n    const version = Object.keys(chatIdStore)[0]\n    return (version \u0026\u0026 chatIdStore[version]?.CHAT_ID) ?? crypto.randomUUID()\n  } catch {\n    return crypto.randomUUID()\n  }\n}\n\nconst getLocale = () =\u003e {\n  const seg = window.location.pathname.split('/').filter(Boolean)[0] ?? 'en-us'\n  return /^[a-z]{2}-[a-z]{2}$/.test(seg) ? seg : 'en-us'\n}\n\nconst getCartStorageKey = locale =\u003e `cart_${locale.slice(-2).toUpperCase()}`\n\n// localStorage stores a JSON object like { basketId, ... }. Read/write the\n// basketId field; tolerate legacy plain-string values on read.\nconst getCartId = locale =\u003e {\n  const raw = localStorage.getItem(getCartStorageKey(locale))\n  if (!raw) return ''\n  try {\n    const parsed = JSON.parse(raw)\n    return parsed?.basketId ?? ''\n  } catch {\n    return raw\n  }\n}\n\nconst setCartId = (locale, cartId) =\u003e {\n  if (!cartId) return\n  const key = getCartStorageKey(locale)\n  let existing = {}\n  try {\n    existing = JSON.parse(localStorage.getItem(key) ?? '{}') ?? {}\n    if (typeof existing !== 'object') existing = {}\n  } catch {\n    existing = {}\n  }\n  localStorage.setItem(key, JSON.stringify({ ...existing, basketId: cartId }))\n}\n\nconst getProductIdFromVariantId = id =\u003e (id?.includes('TB:') ? id.split(':').slice(0, 3).join('') : id)\n\nconst tblHeaders = locale =\u003e {\n  const chatId = getChatId()\n  const country = locale.slice(-2).toUpperCase()\n  const language = locale.slice(0, 2).toLowerCase()\n  return {\n    'x-transaction-id': chatId,\n    'x-correlation-id': chatId,\n    channel: 'ECOMM',\n    locale: `${language}_${country}`,\n    brand: 'TBL',\n    siteid: `TBL-${country}`,\n    source: 'ECOM15',\n    region: country === 'US' || country === 'CA' ? 'NORA' : 'EMEA',\n    'content-type': 'application/json',\n  }\n}\n\n// One inventory call returns stock for every variant of the product, keyed by\n// variant id — fetch once per product instead of once per variant.\nconst fetchAllVariantStock = async (productId, locale) =\u003e {\n  const res = await fetch(`${ORIGIN}/api/products/v2/products/${productId}/inventory?locale=${locale}`, {\n    headers: tblHeaders(locale),\n  })\n  if (!res.ok) throw new Error(`Inventory request failed: ${res.status}`)\n  const body = await res.json()\n  return body?.variants ?? {}\n}\n\nconst fetchVariantStock = async (variantId, locale) =\u003e {\n  const productId = getProductIdFromVariantId(variantId)\n  const variants = await fetchAllVariantStock(productId, locale)\n  return variants?.[variantId]\n}\n\nconst isVariantInStock = stockEntry =\u003e !!stockEntry \u0026\u0026 stockEntry.inStock \u0026\u0026 stockEntry.quantity \u003e 0\n\nconst postAddToCart = async a =\u003e {\n  const hasCart = !!a.cartId\n  const path = hasCart ? '/api/cart/v1/item' : '/api/cart/v1/cartWithItem'\n  const res = await fetch(`${ORIGIN}${path}?locale=${a.locale}`, {\n    method: 'POST',\n    headers: tblHeaders(a.locale),\n    body: JSON.stringify({\n      cartId: a.cartId,\n      maxQty: 10,\n      productId: a.productId,\n      qty: 1,\n      upc: a.upc,\n    }),\n  })\n  if (!res.ok) throw new Error(`Add-to-cart request failed: ${res.status}`)\n  return res.json()\n}\n\nconst addVariantToCart = async variant =\u003e {\n  const variantId = variant?.id\n  const upc = variant?.upc?.[0]\n  if (!variantId) throw new Error('missing variant id')\n  if (!upc) throw new Error('missing upc on variant')\n  const locale = getLocale()\n  const cartId = getCartId(locale)\n  const result = await postAddToCart({ cartId, productId: variantId, upc, locale })\n  const newCartId = result?.cartId ?? result?.id\n  if (!cartId \u0026\u0026 newCartId) setCartId(locale, newCartId)\n  return result\n}\n\n// Standalone ATC function — mirrors timberlandATC's contract (fetch stock,\n// bail if out of stock, post to cart). Always resolves with a result object\n// of shape { status: 'success' | 'failed', message?: string } so callers\n// (e.g. webChatPlugin's CocoConfig.fn.addToCart) can react to the outcome.\nconst tblCusotmizedATC = async product =\u003e {\n  console.log('[AMA] Clarity - Customized - tblCusotmizedATC', product)\n  const variantId = product?.id\n  const upc = product?.upc?.[0]\n  if (!variantId) {\n    console.warn('[tblCusotmizedATC] missing product id')\n    return { status: 'failed', message: 'missing product id' }\n  }\n  if (!upc) {\n    console.warn('[tblCusotmizedATC] missing upc on product', product)\n    return { status: 'failed', message: 'missing upc on product' }\n  }\n  try {\n    const stock = await fetchVariantStock(variantId, getLocale())\n    if (!isVariantInStock(stock)) {\n      console.warn('[tblCusotmizedATC] variant out of stock', variantId, stock)\n      return { status: 'failed', message: 'variant out of stock' }\n    }\n    await addVariantToCart(product)\n    return { status: 'success' }\n  } catch (err) {\n    console.error('[tblCusotmizedATC]', err)\n    return { status: 'failed', message: err?.message ?? 'add to cart failed' }\n  }\n}\n\n// === shared utils (mirrors tblBaseMiniPDP.js) ===\n\nconst toTitleCase = str =\u003e\n  String(str || '')\n    .split(' ')\n    .map(w =\u003e (w.length ? w[0].toUpperCase() + w.slice(1).toLowerCase() : w))\n    .join(' ')\n\nconst formatPrice = (amount, currency) =\u003e {\n  if (amount == null || amount === '') return ''\n  try {\n    return new Intl.NumberFormat('en-US', {\n      style: 'currency',\n      currency: currency || 'USD',\n    }).format(amount)\n  } catch {\n    return `${currency || ''} ${amount}`\n  }\n}\n\nconst isPriceHigher = (a, b) =\u003e {\n  const x = parseFloat(a)\n  const y = parseFloat(b)\n  if (Number.isNaN(x) || Number.isNaN(y)) return false\n  return x \u003e y\n}\n\n// True only when the trimmed string parses as a finite number AND has no\n// trailing non-numeric junk (so \"8\" / \"8.5\" sort numerically, but \"8W\" /\n// \"Medium\" stay as strings).\nconst isPureNumber = value =\u003e {\n  if (typeof value === 'number') return Number.isFinite(value)\n  const str = String(value ?? '').trim()\n  if (str === '') return false\n  return !Number.isNaN(Number(str)) \u0026\u0026 /^-?\\d+(\\.\\d+)?$/.test(str)\n}\n\nconst sortDimensionValues = values =\u003e {\n  if (values.length \u003c= 1) return values\n  if (values.every(isPureNumber)) {\n    return [...values].sort((a, b) =\u003e Number(a) - Number(b))\n  }\n  return values\n}\n\nconst generateDimensions = variants =\u003e {\n  if (!variants?.length) return []\n  const out = []\n  DIMENSION_NAMES.forEach(name =\u003e {\n    const allHaveValue = variants.every(v =\u003e v[name] != null \u0026\u0026 v[name] !== '')\n    if (!allHaveValue) return\n    const values = []\n    variants.forEach(v =\u003e {\n      if (!values.includes(v[name])) values.push(v[name])\n    })\n    if (values.length \u003e 1) out.push({ name, values: sortDimensionValues(values) })\n  })\n  return out\n}\n\nconst findExactVariant = (variants, criteria) =\u003e {\n  if (!variants?.length) return undefined\n  return variants.find(v =\u003e Object.keys(criteria).every(k =\u003e v[k] === criteria[k]))\n}\n\nconst tblCusotmized = (el, initialProps) =\u003e {\n  let props = { ...initialProps, product: injectFakeLengthDimension(initialProps.product) }\n  let dimensions = []\n  let activated = {}\n  // stockMap is { [variantId]: stockEntry }; stockLoaded gates display logic\n  // so chips/buttons aren't prematurely flagged out-of-stock before the\n  // inventory call resolves. stockProductId guards against stale responses\n  // when the user flips between products faster than the network.\n  let stockMap = {}\n  let stockLoaded = false\n  let stockProductId = null\n  // ATC phase machine:\n  //   'idle'    → default; button reads \"Add to Cart\"\n  //   'pending' → progress-bar animation running + ATC request in flight\n  //   'success' → animation done + request succeeded; button reads \"View Cart\"\n  //               (clickable → cart page); auto-resets to 'idle' after ATC_RESET_MS\n  //   'failed'  → animation done + request failed; button reads \"Failed\";\n  //               auto-resets to 'idle' after ATC_RESET_MS\n  // atcGen invalidates in-flight requests when the user changes variant\n  // mid-flight so a stale resolve can't flip the new variant's button.\n  let atcPhase = 'idle'\n  let atcResetTimerId = null\n  let atcGen = 0\n\n  const cancelAtcResetTimer = () =\u003e {\n    if (atcResetTimerId) {\n      clearTimeout(atcResetTimerId)\n      atcResetTimerId = null\n    }\n  }\n\n  const resetAtcStatus = () =\u003e {\n    atcGen += 1\n    cancelAtcResetTimer()\n    atcPhase = 'idle'\n  }\n\n  // Toast container lives inside the MiniPDP root so it's positioned relative\n  // to the panel, not the page viewport. Created lazily on first showAtcToast.\n  let atcToastContainer = null\n  const ensureAtcToastContainer = () =\u003e {\n    if (atcToastContainer \u0026\u0026 root.contains(atcToastContainer)) return atcToastContainer\n    atcToastContainer = document.createElement('div')\n    atcToastContainer.className = 'tbl-customized-toast-container'\n    root.appendChild(atcToastContainer)\n    return atcToastContainer\n  }\n  const showAtcToast = (message, opts) =\u003e {\n    const container = ensureAtcToastContainer()\n    const toast = document.createElement('div')\n    toast.className = 'tbl-customized-toast'\n    toast.textContent = message\n    container.appendChild(toast)\n    requestAnimationFrame(() =\u003e toast.classList.add('is-visible'))\n    const duration = opts?.duration ?? 2500\n    setTimeout(() =\u003e {\n      toast.classList.remove('is-visible')\n      setTimeout(() =\u003e toast.remove(), 250)\n    }, duration)\n  }\n\n  const root = document.createElement('div')\n  root.id = 'tbl-base-mini-pdp-root'\n  root.className = 'tbl-base-mini-pdp tbl-customized-mini-pdp'\n  root.innerHTML = `\n    \u003cdiv class=\"tbl-base-mini-pdp__top-bar\"\u003e\n      \u003cbutton class=\"tbl-base-mini-pdp__icon-btn\" data-action=\"close\" type=\"button\"\u003e\n        Close\n      \u003c/button\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"tbl-base-mini-pdp__scroll\"\u003e\n      \u003cdiv class=\"tbl-base-mini-pdp__hero\"\u003e\n        \u003cimg class=\"tbl-base-mini-pdp__image\" alt=\"\" /\u003e\n      \u003c/div\u003e\n      \u003cdiv class=\"tbl-base-mini-pdp__details\"\u003e\n        \u003cdiv class=\"tbl-base-mini-pdp__heading\"\u003e\n          \u003cdiv class=\"tbl-base-mini-pdp__name-block\"\u003e\n            \u003cspan class=\"tbl-base-mini-pdp__title\"\u003e\u003c/span\u003e\n            \u003cbutton class=\"tbl-base-mini-pdp__view\" data-action=\"view\" type=\"button\" hidden\u003eView Product\u003c/button\u003e\n          \u003c/div\u003e\n          \u003cdiv class=\"tbl-base-mini-pdp__price-row is-hidden\"\u003e\n            \u003cspan class=\"tbl-base-mini-pdp__price\"\u003e\u003c/span\u003e\n            \u003cspan class=\"tbl-base-mini-pdp__original-price is-hidden\"\u003e\u003c/span\u003e\n          \u003c/div\u003e\n        \u003c/div\u003e\n        \u003cdiv class=\"tbl-base-mini-pdp__dimensions\"\u003e\u003c/div\u003e\n      \u003c/div\u003e\n      \u003cdiv class=\"tbl-customized-mini-pdp__atc-container\"\u003e\n        \u003cbutton class=\"tbl-customized-mini-pdp__atc-btn\" data-action=\"atc\" type=\"button\"\u003e\n          \u003cspan class=\"tbl-customized-mini-pdp__atc-progress\"\u003e\u003c/span\u003e\n          \u003cspan class=\"tbl-customized-mini-pdp__atc-label\"\u003eAdd to Cart\u003c/span\u003e\n        \u003c/button\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e\n  `\n  el.appendChild(root)\n\n  const refs = {\n    root,\n    image: root.querySelector('.tbl-base-mini-pdp__image'),\n    title: root.querySelector('.tbl-base-mini-pdp__title'),\n    viewBtn: root.querySelector('[data-action=\"view\"]'),\n    priceRow: root.querySelector('.tbl-base-mini-pdp__price-row'),\n    price: root.querySelector('.tbl-base-mini-pdp__price'),\n    originalPrice: root.querySelector('.tbl-base-mini-pdp__original-price'),\n    dimensions: root.querySelector('.tbl-base-mini-pdp__dimensions'),\n    atcBtn: root.querySelector('[data-action=\"atc\"]'),\n    atcLabel: root.querySelector('.tbl-customized-mini-pdp__atc-label'),\n    atcProgress: root.querySelector('.tbl-customized-mini-pdp__atc-progress'),\n  }\n\n  // Treat variants as available until inventory loads to avoid flashing all\n  // chips disabled on first paint.\n  const isVariantAvailable = variantId =\u003e {\n    if (!stockLoaded) return true\n    return isVariantInStock(stockMap[variantId])\n  }\n\n  const getActiveVariant = () =\u003e {\n    const product = props.product\n    const selected = props.selectedVariant\n    if (selected) {\n      const merged = {}\n      Object.keys(product || {}).forEach(k =\u003e {\n        if (k === 'variants') return\n        merged[k] = product[k]\n      })\n      Object.keys(selected).forEach(k =\u003e {\n        if (selected[k] !== undefined \u0026\u0026 selected[k] !== null \u0026\u0026 selected[k] !== '') merged[k] = selected[k]\n      })\n      return merged\n    }\n    return product || {}\n  }\n\n  const buildDimensionsDOM = () =\u003e {\n    refs.dimensions.innerHTML = ''\n    dimensions.forEach(dim =\u003e {\n      const row = document.createElement('div')\n      row.className = `tbl-base-mini-pdp__dimension-row tbl-base-mini-pdp__dimension--${dim.name.toLowerCase()}`\n      row.dataset.dimensionName = dim.name\n\n      const label = document.createElement('div')\n      label.className = 'tbl-base-mini-pdp__dimension-label'\n      label.textContent = toTitleCase(dim.name)\n      row.appendChild(label)\n\n      const grid = document.createElement('div')\n      grid.className = 'tbl-base-mini-pdp__chip-grid'\n      dim.values.forEach(value =\u003e {\n        const chip = document.createElement('button')\n        chip.type = 'button'\n        chip.className = 'tbl-base-mini-pdp__chip'\n        chip.dataset.dimensionName = dim.name\n        chip.dataset.dimensionValue = String(value)\n        chip.setAttribute('aria-pressed', 'false')\n        chip.textContent = toTitleCase(String(value))\n        grid.appendChild(chip)\n      })\n      row.appendChild(grid)\n      refs.dimensions.appendChild(row)\n    })\n  }\n\n  // Whether the dimension combo resolves to an actual variant. Stock is NOT\n  // considered here on purpose — out-of-stock variants must remain selectable\n  // so the consumer can navigate to them (the ATC button then renders as\n  // \"Out of Stock\"). isApplicable gates click handling; visual disabled is\n  // computed separately.\n  const isApplicable = (name, value) =\u003e\n    !!findExactVariant(props.product?.variants, { ...activated, [name]: value })\n\n  const syncActiveChips = () =\u003e {\n    const chips = refs.dimensions.querySelectorAll('.tbl-base-mini-pdp__chip')\n    chips.forEach(chip =\u003e {\n      const name = chip.dataset.dimensionName\n      const value = chip.dataset.dimensionValue\n      const active = String(activated[name]) === value\n      const target = findExactVariant(props.product?.variants, { ...activated, [name]: value })\n      const applicable = !!target\n      const inStock = target ? isVariantAvailable(target.id) : false\n      const disabled = !active \u0026\u0026 (!applicable || !inStock)\n      chip.classList.toggle('is-active', active)\n      chip.classList.toggle('is-disabled', disabled)\n      chip.setAttribute('aria-pressed', active ? 'true' : 'false')\n      chip.setAttribute('aria-disabled', disabled ? 'true' : 'false')\n    })\n  }\n\n  const setHidden = (node, hidden) =\u003e {\n    node.classList.toggle('is-hidden', hidden)\n  }\n\n  const syncAtcButton = () =\u003e {\n    const v = getActiveVariant()\n    const variantId = v?.id\n    const outOfStock = stockLoaded \u0026\u0026 !!variantId \u0026\u0026 !isVariantAvailable(variantId)\n    let label\n    let disabled\n    if (atcPhase === 'pending') {\n      label = 'Add to Cart'\n      disabled = true\n    } else if (atcPhase === 'success') {\n      label = 'View Cart'\n      disabled = false\n    } else if (atcPhase === 'failed') {\n      label = 'Failed'\n      disabled = true\n    } else if (outOfStock) {\n      label = 'Out of Stock'\n      disabled = true\n    } else {\n      label = 'Add to Cart'\n      disabled = false\n    }\n    // Pending phase keeps the disabled attribute (so the click doesn't re-fire)\n    // but skips the is-disabled class so the button stays at full opacity and\n    // the red progress bar reads cleanly.\n    refs.atcBtn.classList.toggle('is-disabled', disabled \u0026\u0026 atcPhase !== 'pending')\n    refs.atcBtn.disabled = disabled\n    if (refs.atcLabel) refs.atcLabel.textContent = label\n    else refs.atcBtn.textContent = label\n\n    const progress = refs.atcProgress\n    if (progress) {\n      // 'pending' is set up by handleAddToCart (it triggers the width transition\n      // on its own to guarantee a from→to repaint); only handle the resting\n      // states here so re-syncs don't reset an in-flight animation.\n      if (atcPhase === 'success' || atcPhase === 'failed') {\n        progress.classList.remove('is-animating')\n        progress.classList.add('is-filled')\n      } else if (atcPhase === 'idle') {\n        progress.classList.remove('is-animating', 'is-filled')\n      }\n    }\n  }\n\n  const syncVariantContent = () =\u003e {\n    const v = getActiveVariant()\n\n    if (v.image \u0026\u0026 refs.image.src !== v.image) refs.image.src = v.image\n    refs.image.alt = v.title || ''\n\n    refs.title.textContent = v.title || ''\n\n    if (v.url) {\n      refs.viewBtn.hidden = false\n      refs.viewBtn.dataset.url = v.url\n    } else {\n      refs.viewBtn.hidden = true\n      delete refs.viewBtn.dataset.url\n    }\n\n    const priceStr = formatPrice(v.price, v.currency)\n    refs.price.textContent = priceStr\n    setHidden(refs.priceRow, !priceStr)\n\n    const originalStr = formatPrice(v.originalPrice, v.currency)\n    const showOriginal = !!originalStr \u0026\u0026 isPriceHigher(v.originalPrice, v.price)\n    refs.originalPrice.textContent = showOriginal ? originalStr : ''\n    setHidden(refs.originalPrice, !showOriginal)\n\n    syncAtcButton()\n  }\n\n  const initActivatedFromProps = () =\u003e {\n    activated = {}\n    const variants = props.product?.variants ?? []\n    if (!variants.length) return\n    const source = props.selectedVariant ?? variants[0]\n    dimensions.forEach(dim =\u003e {\n      activated[dim.name] = source?.[dim.name] ?? dim.values[0]\n    })\n  }\n\n  const chooseDimension = (name, value) =\u003e {\n    const variants = props.product?.variants ?? []\n    if (!variants.length) return\n    if (!isApplicable(name, value)) return\n    const target = findExactVariant(variants, { ...activated, [name]: value })\n    if (!target) return\n    if (stockLoaded \u0026\u0026 !isVariantAvailable(target.id)) return\n    activated[name] = value\n    syncActiveChips()\n    const previousId = props.selectedVariant?.id\n    props = { ...props, selectedVariant: target }\n    if (target.id !== previousId) resetAtcStatus()\n    syncVariantContent()\n    if (target.id \u0026\u0026 target.id !== previousId) {\n      props.onVariantSelect?.(target.id)\n    }\n  }\n\n  // Walk the cartesian product of dimension values in their sorted order\n  // (dimensions[0].values × dimensions[1].values × ...) and return the first\n  // combination that resolves to an in-stock variant. With dimensions\n  // [size, length], this checks size[0]+length[0], size[0]+length[1], …,\n  // size[1]+length[0], … in that order.\n  const findFirstAvailableVariant = () =\u003e {\n    const variants = props.product?.variants ?? []\n    if (!variants.length) return undefined\n    if (!dimensions.length) return variants.find(v =\u003e isVariantAvailable(v.id))\n\n    let found\n    const walk = (idx, criteria) =\u003e {\n      if (found) return\n      if (idx === dimensions.length) {\n        const v = findExactVariant(variants, criteria)\n        if (v \u0026\u0026 isVariantAvailable(v.id)) found = v\n        return\n      }\n      const dim = dimensions[idx]\n      for (const val of dim.values) {\n        if (found) return\n        walk(idx + 1, { ...criteria, [dim.name]: val })\n      }\n    }\n    walk(0, {})\n    return found\n  }\n\n  // After inventory loads, if the activated combo points at an out-of-stock\n  // variant, jump to the first in-stock variant so the user lands on\n  // something actually buyable.\n  const ensureInStockSelection = () =\u003e {\n    if (!stockLoaded) return\n    const variants = props.product?.variants ?? []\n    if (!variants.length) return\n    const current = findExactVariant(variants, activated)\n    if (current \u0026\u0026 isVariantAvailable(current.id)) return\n    const firstAvailable = findFirstAvailableVariant()\n    if (!firstAvailable) return\n    dimensions.forEach(dim =\u003e {\n      const v = firstAvailable[dim.name]\n      if (v !== undefined \u0026\u0026 v !== null) activated[dim.name] = v\n    })\n    const previousId = props.selectedVariant?.id\n    props = { ...props, selectedVariant: firstAvailable }\n    if (firstAvailable.id !== previousId) resetAtcStatus()\n    syncActiveChips()\n    syncVariantContent()\n    if (firstAvailable.id \u0026\u0026 firstAvailable.id !== previousId) {\n      props.onVariantSelect?.(firstAvailable.id)\n    }\n  }\n\n  const loadStockForCurrentProduct = async () =\u003e {\n    console.log('[AMA] Clarity - Customized - loadStockForCurrentProduct')\n    const variants = props.product?.variants ?? []\n    if (!variants.length) return\n    const sampleId = props.selectedVariant?.id ?? variants.find(v =\u003e v.id)?.id\n    if (!sampleId) return\n    const productId = getProductIdFromVariantId(sampleId)\n    if (!productId || productId === stockProductId) return\n    stockProductId = productId\n    stockLoaded = false\n    stockMap = {}\n    syncActiveChips()\n    syncAtcButton()\n    try {\n      const stock = await fetchAllVariantStock(productId, getLocale())\n      // Bail if the user changed product mid-flight.\n      if (stockProductId !== productId) return\n      stockMap = stock\n      stockLoaded = true\n      ensureInStockSelection()\n      syncActiveChips()\n      syncAtcButton()\n    } catch (err) {\n      console.error('[tblCusotmized] stock fetch failed', err)\n    }\n  }\n\n  const fullRender = () =\u003e {\n    resetAtcStatus()\n    dimensions = generateDimensions(props.product?.variants)\n    buildDimensionsDOM()\n    const variants = props.product?.variants ?? []\n    // On product change always start at variants[0] — any selectedVariant\n    // passed by the parent is ignored because it may be stale or from a\n    // different product. Once inventory loads, ensureInStockSelection jumps\n    // to the first in-stock variant.\n    if (variants.length) {\n      props = { ...props, selectedVariant: variants[0] }\n    }\n    initActivatedFromProps()\n    syncActiveChips()\n    syncVariantContent()\n    if (variants[0]?.id) props.onVariantSelect?.(variants[0].id)\n    loadStockForCurrentProduct()\n  }\n\n  const startAtcProgressAnimation = () =\u003e {\n    const progress = refs.atcProgress\n    if (!progress) return\n    progress.classList.remove('is-animating', 'is-filled')\n    // Force reflow so the next class change actually triggers a transition.\n    void progress.offsetWidth\n    progress.classList.add('is-animating')\n  }\n\n  const handleAddToCart = async () =\u003e {\n    if (atcPhase !== 'idle') return\n    const v = getActiveVariant()\n    if (!v?.id) return\n    if (stockLoaded \u0026\u0026 !isVariantAvailable(v.id)) return\n\n    cancelAtcResetTimer()\n    const myGen = ++atcGen\n    atcPhase = 'pending'\n    syncAtcButton()\n    startAtcProgressAnimation()\n\n    const animationPromise = new Promise(resolve =\u003e setTimeout(resolve, ATC_ANIMATION_MS))\n    // Re-check stock at click time (same flow as tblCusotmizedATC) so a stale\n    // cached map doesn't let the user add an item that just sold out.\n    const requestPromise = (async () =\u003e {\n      try {\n        return await tblCusotmizedATC(v)\n      } catch {\n        return { status: 'failed' }\n      }\n    })()\n\n    const [, result] = await Promise.all([animationPromise, requestPromise])\n    if (myGen !== atcGen) return\n\n    const success = result?.status === 'success'\n    atcPhase = success ? 'success' : 'failed'\n    syncAtcButton()\n    showAtcToast(success ? 'Added!' : 'Failed to add to cart', { duration: ATC_RESET_MS })\n\n    atcResetTimerId = setTimeout(() =\u003e {\n      atcResetTimerId = null\n      if (myGen !== atcGen) return\n      atcPhase = 'idle'\n      syncAtcButton()\n    }, ATC_RESET_MS)\n  }\n\n  const goToCheckout = () =\u003e {\n    window.location.href = `${ORIGIN}/${getLocale()}/cart`\n  }\n\n  root.addEventListener('click', e =\u003e {\n    const target = e.target\n    if (!(target instanceof Element)) return\n\n    const closeBtn = target.closest('[data-action=\"close\"]')\n    if (closeBtn) {\n      props.onClose?.()\n      return\n    }\n\n    const viewBtn = target.closest('[data-action=\"view\"]')\n    if (viewBtn) {\n      const url = viewBtn.dataset.url\n      if (url) window.open(url, '_self')\n      return\n    }\n\n    const atcBtn = target.closest('[data-action=\"atc\"]')\n    if (atcBtn) {\n      if (atcBtn.classList.contains('is-disabled')) return\n      if (atcPhase === 'success') {\n        goToCheckout()\n        return\n      }\n      handleAddToCart()\n      return\n    }\n\n    const chip = target.closest('.tbl-base-mini-pdp__chip')\n    if (chip) {\n      chooseDimension(chip.dataset.dimensionName, chip.dataset.dimensionValue)\n    }\n  })\n\n  fullRender()\n\n  return {\n    update(newProps) {\n      console.log('[AMA] Clarity - Customized - update', newProps)\n      const productChanged = newProps.product?.id !== props.product?.id\n      props = { ...newProps, product: injectFakeLengthDimension(newProps.product) }\n      if (productChanged) {\n        fullRender()\n      } else {\n        const variants = props.product?.variants ?? []\n        if (variants.length \u0026\u0026 props.selectedVariant) {\n          dimensions.forEach(dim =\u003e {\n            const v = props.selectedVariant[dim.name]\n            if (v !== undefined \u0026\u0026 v !== null) activated[dim.name] = v\n          })\n          syncActiveChips()\n        }\n        syncVariantContent()\n      }\n    },\n    cleanup() {\n      atcGen += 1\n      cancelAtcResetTimer()\n      el.innerHTML = ''\n    },\n  }\n}\n\nconst seeAllResults = params =\u003e {\n  const query = params.queries?.at(-1) ?? params.rephrasedQuery ?? params.categoryName ?? ''\n  if (!query) return\n  const locale = getLocale()\n  const origin = location.origin\n  const ps = new URLSearchParams()\n  ps.set('q', query)\n  window.location.href = `${origin}/${locale}/search?${ps.toString()}`\n}\n\nconsole.log('[AMA] Clarity - Customized')\nwindow.CLARITY_GLOBAL_CONFIG = {\n  ...(window.CLARITY_GLOBAL_CONFIG || {}),\n  component: {\n    ...(window.CLARITY_GLOBAL_CONFIG?.component || {}),\n    // MiniPDP: tblCusotmized,\n  },\n  fn: {\n    ...(window.CLARITY_GLOBAL_CONFIG?.fn || {}),\n    // addToCart: tblCusotmizedATC,\n    seeAllResults,\n  },\n}\n","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"6a1dbba79df19aa293ca354e"},{"uses_overlay":false,"type":"html","parametrized_definition":"\u003cstyle\u003e\n/*\n * Self-contained styles for tblCusotmized — combines tblBaseMiniPDP.css\n * (base layout, top bar, hero, dimensions, chips) with the ATC footer\n * additions. Load this file alone; do NOT also load tblBaseMiniPDP.css.\n *\n * The atc-container sits inside the existing scroll area and uses flex: 1\n * to absorb leftover vertical space, anchoring the Add to Cart button to\n * the bottom of the visible scroll viewport. When content is taller than\n * the viewport, the button scrolls into view at the very end.\n */\n\n#cocoaas_chat_wrapper .clarity-mini-pdp--inside-input-container {\n  display: none;\n}\n\n#cocoaas_chat_wrapper .clarity-mini-pdp--inside-container-overlay {\n\theight: 90%;\n}\n\n#tbl-base-mini-pdp-root {\n  position: relative;\n  display: flex;\n  width: 100%;\n  height: 100%;\n  flex-direction: column;\n  align-items: flex-start;\n  gap: 32px;\n  flex-shrink: 0;\n  align-self: stretch;\n}\n\n#tbl-base-mini-pdp-root *,\n#tbl-base-mini-pdp-root *::before,\n#tbl-base-mini-pdp-root *::after {\n  box-sizing: border-box;\n}\n\n#tbl-base-mini-pdp-root button {\n  border: none;\n  padding: 0;\n  margin: 0;\n  cursor: pointer;\n  background: unset;\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__top-bar {\n  width: 100%;\n  padding: 32px 16px 0;\n  display: flex;\n  align-items: center;\n  justify-content: flex-start;\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__icon-btn {\n  text-transform: uppercase;\n  color: #000;\n  /* Accent/Overline 1 */\n  font-size: var(--typography-font-size-accent-overline-1, 12px);\n  font-style: normal;\n  font-weight: 400;\n  line-height: var(--typography-font-line-height-accent-overline-1, 16px);\n  letter-spacing: var(--typography-font-letter-spacing-accent-overline-1, 0);\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__icon-btn svg {\n  display: none;\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__scroll {\n  padding: 0 16px 32px;\n  width: 100%;\n  flex: 1;\n  overflow: hidden auto;\n  display: flex;\n  flex-direction: column;\n  gap: 32px;\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__hero {\n  position: relative;\n  width: 100%;\n  aspect-ratio: 1 / 1;\n  border-radius: var(--border-radius-none, 0);\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__hero img {\n  position: absolute;\n  inset: 0;\n  width: 100%;\n  height: 100%;\n  object-fit: cover;\n  display: block;\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__details {\n  display: flex;\n  flex-direction: column;\n  gap: 32px;\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__heading {\n  display: flex;\n  flex-direction: column;\n  gap: 20px;\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__name-block {\n  display: flex;\n  flex-direction: column;\n  gap: 12px;\n  align-items: flex-start;\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__title {\n  margin: 0;\n  color: var(--typography-color-default, #2a1e17);\n  /* Title/Title 2/Desktop */\n  font-size: var(--typography-font-size-title-title-2-desktop, 20px);\n  font-style: normal;\n  font-weight: 500;\n  line-height: var(--typography-font-line-height-title-title-2-desktop, 24px);\n  letter-spacing: var(\n    --typography-font-letter-spacing-title-title-2-desktop,\n    0\n  );\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__view {\n  color: var(--typography-color-default, #2a1e17);\n  /* Body/Body Copy 2/Default */\n  font-size: var(--typography-font-size-body-body-2, 14px);\n  font-style: normal;\n  font-weight: 400;\n  line-height: var(--typography-font-line-height-body-body-2, 18px);\n  letter-spacing: var(--typography-font-letter-spacing-body-body-2, 0);\n  text-decoration-line: underline;\n  text-decoration-style: solid;\n  text-decoration-skip-ink: auto;\n  text-decoration-thickness: auto;\n  text-underline-offset: auto;\n  text-underline-position: from-font;\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__view[hidden] {\n  display: none;\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__price-row {\n  display: flex;\n  align-items: center;\n  gap: 8px;\n  /* Body/Body Copy 2/Strong */\n  font-size: var(--typography-font-size-body-body-2, 14px);\n  font-style: normal;\n  font-weight: 500;\n  line-height: var(--typography-font-line-height-body-body-2, 18px);\n  letter-spacing: var(--typography-font-letter-spacing-body-body-2, 0);\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__price-row.is-hidden {\n  display: none;\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__price {\n  color: var(--typography-color-default, #2a1e17);\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__original-price {\n  color: #d51920;\n  font-weight: 500;\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__original-price.is-hidden {\n  display: none;\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__dimensions {\n  display: flex;\n  flex-direction: column;\n  gap: 32px;\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__dimension-row {\n  display: flex;\n  flex-direction: column;\n  gap: 12px;\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__dimension-label {\n  color: var(--typography-color-default, #2a1e17);\n  /* Accent/Overline 1 */\n  font-size: var(--typography-font-size-accent-overline-1, 12px);\n  font-style: normal;\n  font-weight: 400;\n  line-height: var(--typography-font-line-height-accent-overline-1, 16px);\n  letter-spacing: var(--typography-font-letter-spacing-accent-overline-1, 0);\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__dimension-label::after {\n  content: \":\";\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__chip-grid {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 8px;\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__chip {\n  text-align: center;\n  flex: 1;\n  padding: 12px 16px;\n  border-radius: var(--border-radius-default, 0);\n  border: 1px solid var(--border-color-light, #e1e1e1);\n  white-space: nowrap;\n  transition: border-color 0.15s;\n  color: var(--typography-color-default, #2a1e17);\n  /* Accent/Overline 1 */\n  font-size: var(--typography-font-size-accent-overline-1, 12px);\n  font-style: normal;\n  font-weight: 400;\n  line-height: var(--typography-font-line-height-accent-overline-1, 16px);\n  letter-spacing: var(--typography-font-letter-spacing-accent-overline-1, 0);\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__chip.is-active {\n  border-color: var(--border-color-dark, #2a2a2a);\n}\n\n#tbl-base-mini-pdp-root .tbl-base-mini-pdp__chip.is-disabled {\n  background-color: var(--components-buttons-style-disabled-default, #eee);\n  background-image: linear-gradient(\n    to bottom right,\n    transparent calc(50% - 0.5px),\n    var(--border-color-disabled, #9a9a9a) calc(50% - 0.5px),\n    var(--border-color-disabled, #9a9a9a) calc(50% + 0.5px),\n    transparent calc(50% + 0.5px)\n  );\n  border-color: var(--border-color-disabled, #9a9a9a);\n  color: var(--typography-color-disabled, #707070);\n  cursor: not-allowed;\n}\n\n#tbl-base-mini-pdp-root\n  .tbl-base-mini-pdp__dimension--size\n  .tbl-base-mini-pdp__chip {\n  flex: none;\n  width: 40px;\n  height: 40px;\n  overflow: hidden;\n  padding: 0;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n\n/* === Customized: Add to Cart footer === */\n\n#tbl-base-mini-pdp-root .tbl-customized-mini-pdp__atc-container {\n  flex: 1;\n  display: flex;\n  flex-direction: column;\n  justify-content: flex-end;\n  width: 100%;\n  min-height: 44px;\n}\n\n#tbl-base-mini-pdp-root .tbl-customized-mini-pdp__atc-btn {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  width: 100%;\n  height: 44px;\n  background: var(--components-buttons-style-primary-default, #2a1e17);\n  color: var(--components-buttons-style-primary-text, #faf6ec);\n\n  /* Buttons/Buttons 1 */\n  font-size: var(--typography-font-size-buttons-buttons-1, 16px);\n  font-style: normal;\n  font-weight: 500;\n  line-height: var(\n    --typography-font-line-height-buttons-buttons-1,\n    20px\n  ); /* 125% */\n  letter-spacing: var(\n    --typography-font-letter-spacing-buttons-buttons-1,\n    0.24px\n  );\n  cursor: pointer;\n  transition: opacity 0.15s;\n}\n\n/* Cursor reflects any non-clickable state (pending / out of stock / failed).\n   Only fade for `is-disabled` (out of stock / failed); during the pending\n   ATC phase the button stays at full opacity so the red progress bar reads\n   cleanly, but the cursor still signals it can't be clicked again. */\n#tbl-base-mini-pdp-root .tbl-customized-mini-pdp__atc-btn:disabled,\n#tbl-base-mini-pdp-root .tbl-customized-mini-pdp__atc-btn.is-disabled {\n  cursor: not-allowed;\n}\n\n#tbl-base-mini-pdp-root .tbl-customized-mini-pdp__atc-btn.is-disabled {\n  opacity: 0.5;\n}\n\n/*\n * ATC button: progress-bar fill animation. Layered over the button background\n * during the \"pending\" phase (after the user clicks Add to Cart, before the\n * cart request resolves). The label sits on top via z-index.\n *\n * NOTE: the 1800ms duration must stay in sync with ATC_ANIMATION_MS in\n * tblCusotmized.js — that JS constant gates the parallel setTimeout that\n * waits for the visual fill to finish before showing the result label.\n */\n\n#tbl-base-mini-pdp-root .tbl-customized-mini-pdp__atc-btn {\n  position: relative;\n  overflow: hidden;\n}\n\n#tbl-base-mini-pdp-root .tbl-customized-mini-pdp__atc-progress {\n  position: absolute;\n  top: 0;\n  left: 0;\n  bottom: 0;\n  width: 0%;\n  background: #896340;\n  z-index: 1;\n  pointer-events: none;\n}\n\n/* Use a CSS animation rather than a transition. A transition would require the\n   `transition: width …` rule to already be on the element's computed style\n   *before* the width changes — toggling a class that adds both the transition\n   rule and the new width in the same recalc lets the browser skip the animation.\n   @keyframes plays unambiguously whenever the class is applied. */\n@keyframes tbl-atc-fill {\n  from { width: 0%; }\n  to { width: 100%; }\n}\n\n#tbl-base-mini-pdp-root\n  .tbl-customized-mini-pdp__atc-progress.is-animating {\n  animation: tbl-atc-fill 1800ms cubic-bezier(0.4, 0, 0.2, 1) forwards;\n}\n\n#tbl-base-mini-pdp-root .tbl-customized-mini-pdp__atc-progress.is-filled {\n  width: 100%;\n}\n\n#tbl-base-mini-pdp-root .tbl-customized-mini-pdp__atc-label {\n  position: relative;\n  z-index: 2;\n}\n\n/* === Customized: ATC top toast === */\n\n/* Toast is anchored to the MiniPDP root (which is position: relative) so it\n   appears inside the MiniPDP panel rather than at the page viewport top. */\n#tbl-base-mini-pdp-root .tbl-customized-toast-container {\n  position: absolute;\n  top: 16px;\n  left: 50%;\n  transform: translateX(-50%);\n  z-index: 10;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  gap: 8px;\n  pointer-events: none;\n}\n\n.tbl-customized-toast {\n  background: #000;\n  color: #fff;\n  border-radius: 8px;\n  padding: 12px 18px;\n  font-size: 14px;\n  font-family: inherit;\n  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n  opacity: 0;\n  transform: translateY(-12px);\n  transition:\n    opacity 0.2s ease,\n    transform 0.2s ease;\n  pointer-events: auto;\n  min-width: 200px;\n  text-align: center;\n}\n\n.tbl-customized-toast.is-visible {\n  opacity: 1;\n  transform: translateY(0);\n}\n\n\u003c/style\u003e","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"6a1dbbe7d538b7cc809b7d9f"},{"uses_overlay":false,"type":"js","parametrized_definition":"const pdpWeblayerId = \"6a1f42e9adfc414176f41e04\";\nconst searchWeblayerId = \"6a1f42be775548df4d3e8f44\";\n\nconst loadClarityUtils = async () =\u003e {\n  const url = 'https://unpkg.com/@bloomreach/clarity-utils@1.0.8/dist/index.global.js'\n  for (let attempt = 1; attempt \u003c= 5; attempt++) {\n    try {\n      await new Promise((resolve, reject) =\u003e {\n        const s = document.createElement('script')\n        s.src = url\n        s.onload = resolve\n        s.onerror = () =\u003e reject(new Error(`Failed to load ${url}`))\n        document.head.appendChild(s)\n      })\n      return\n    } catch (err) {\n      console.warn(`clarity-utils load attempt ${attempt}/5 failed`, err)\n      if (attempt === 5) throw err\n      await new Promise(r =\u003e setTimeout(r, 200 * attempt))\n    }\n  }\n}\n\nconst clarityUtilsLoaded = loadClarityUtils()\n\nwindow.CLARITY_HELPER = {\n\t...(window.CLARITY_HELPER || {}),\n\tinvokePDP: () =\u003e {\n\t  window.CLARITY.setSource(pdpWeblayerId);\n      window.CLARITY.call('show_badge');\n      window.CLARITY.call('open_chat');\n\t},\n    invokeSearchHubOrch: input =\u003e {\n\t  window.CLARITY.setSource(searchWeblayerId);\n      window.CLARITY.call('show_badge');\n      window.CLARITY.call('open_chat');\n      window.CLARITY.call('user_send_message', {\n        input,\n        type: 'text',\n        force: true,\n        source: 'DEFAULT',\n      });\n\t},\n\tisSearch: async (input, config) =\u003e {\n\t  if (!input?.trim()) return;\n\t  console.log('clarity is search', input, config)\n\t  await clarityUtilsLoaded\n\t  const result = window.clarityUtils.isSearch(input, { mode: 'score', ...(config ?? {}) })\n\t  const logger = window.brweb ?? window.exponea\n\t  logger.track('clarity', {\n\t  \taction: 'search_orchestrator',\n\t  \tsearch_string: input,\n\t  \tis_conversational: !result\n\t  });\n\t  return result;\n\t},\n}","trigger":{"include_pages":[{"url":"/en-ca","type":"contains"}],"exclude_pages":null},"_id":"6a1dbf969df19aa293ca3612"},{"uses_overlay":false,"type":"js","parametrized_definition":"const pdpWeblayerId = \"6a1f434fd5cca585e17002c2\";\nconst searchWeblayerId = \"6a1f43c2740d1b8e60499962\";\n\nconst loadClarityUtils = async () =\u003e {\n  const url = 'https://unpkg.com/@bloomreach/clarity-utils@1.0.8/dist/index.global.js'\n  for (let attempt = 1; attempt \u003c= 5; attempt++) {\n    try {\n      await new Promise((resolve, reject) =\u003e {\n        const s = document.createElement('script')\n        s.src = url\n        s.onload = resolve\n        s.onerror = () =\u003e reject(new Error(`Failed to load ${url}`))\n        document.head.appendChild(s)\n      })\n      return\n    } catch (err) {\n      console.warn(`clarity-utils load attempt ${attempt}/5 failed`, err)\n      if (attempt === 5) throw err\n      await new Promise(r =\u003e setTimeout(r, 200 * attempt))\n    }\n  }\n}\n\nconst clarityUtilsLoaded = loadClarityUtils()\n\nwindow.CLARITY_HELPER = {\n\t...(window.CLARITY_HELPER || {}),\n\tinvokePDP: () =\u003e {\n\t  window.CLARITY.setSource(pdpWeblayerId);\n      window.CLARITY.call('show_badge');\n      window.CLARITY.call('open_chat');\n\t},\n    invokeSearchHubOrch: input =\u003e {\n\t  window.CLARITY.setSource(searchWeblayerId);\n      window.CLARITY.call('show_badge');\n      window.CLARITY.call('open_chat');\n      window.CLARITY.call('user_send_message', {\n        input,\n        type: 'text',\n        force: true,\n        source: 'DEFAULT',\n      });\n\t},\n\tisSearch: async (input, config) =\u003e {\n\t  if (!input?.trim()) return;\n\t  console.log('clarity is search', input, config)\n\t  await clarityUtilsLoaded\n\t  const result = window.clarityUtils.isSearch(input, { mode: 'score', ...(config ?? {}) })\n\t  const logger = window.brweb ?? window.exponea\n\t  logger.track('clarity', {\n\t  \taction: 'search_orchestrator',\n\t  \tsearch_string: input,\n\t  \tis_conversational: !result\n\t  });\n\t  return result;\n\t},\n}","trigger":{"include_pages":[{"url":"/fr-ca","type":"contains"}],"exclude_pages":null},"_id":"6a1dc06dcf2e2cf9f7938958"},{"uses_overlay":false,"type":"js","parametrized_definition":"console.log('Purchased Count Banner Tag - US');\n\nfunction debounce(fn, delay) {\n    let timeoutId;\n\n    return function (...args) {\n        clearTimeout(timeoutId);\n        timeoutId = setTimeout(() =\u003e {\n            fn.apply(this, args);\n        }, delay);\n    };\n}\n\nconst throttle = (fn, delay) =\u003e {\n    let last = 0;\n    return (...args) =\u003e {\n        let now = new Date().getTime();\n        if (now - last \u003c delay) {\n            return;\n        }\n        last = now;\n        return fn(...args);\n    }\n}\n\n/**\n * Function to extract the product ID from the current page URL.\n * @returns {string} The product ID extracted from the URL.\n */\nfunction getProductId() {\n    const path = window.location.pathname;\n    const pathArray = path.split('/');\n    const lastSegment = pathArray[pathArray.length - 1];\n    const lastSegmentArray = lastSegment.split('-');\n    const productId = lastSegmentArray[lastSegmentArray.length - 1];\n    return productId;\n}\n\n/**\n * Function to extract the product ID from the image URL.\n * @param {string} url\n * @returns {string} The product ID extracted from the image URL.\n */\nfunction getProductIdFromImageUrl(url) {\n    // Example: .../VN000D5VEMQ-HERO/washed-black-swatch.jpg\n    // Extract the segment before the last '/' and split by '-' to get the product id\n    if (!url) return '';\n    const parts = url.split('/');\n    if (parts.length \u003c 2) return '';\n    const segment = parts[parts.length - 2]; // e.g., 'VN000D5VEMQ-HERO'\n    return segment.split('-')[0]; // e.g., 'VN000D5VEMQ'\n}\n\n\nconst productId = getProductId();\n// console.log('Product ID:', productId);\nvar productIDs= ['VN000XW46X7', 'VN000XW49Y1', 'VN000XW4CJG', 'VN000XW4E0L', 'VN000XW4N5B', 'VN000DB824O', 'VN000DB8MCG', 'VN000DB8Z11','VN000EGWBLA','VN000EGWWVD','VN000EGWDFP','VN000EFUBLA','VN000EFUWVD','VN000D9PBKA','VN000D9PCAK','VN000D9PIND','VN000E8VYA6'];\n\nif (productIDs.includes(productId)) {\n    console.log('Product ID is in the list, skipping social login.');\n} else {\n    // Banner - Top Right on PDP\n\texponea.showWebLayer('68a64cf67007a25bb347722b', { \"product_id\": productId });\n\t// Banner - Over First Product Image\n\texponea.showWebLayer('68a64da036ba0101a6419cd6', { \"product_id\": productId });\n}\n\ndocument.addEventListener('click', debounce(function (event) {\n    if (event.target.matches('button[data-test-id=\"vf-color-picker\"] img')) {\n        const imageUrl = event.target.src;\n        const swatchProductId = getProductIdFromImageUrl(imageUrl);\n\t\n\t\n        const bannerTopRight = document.querySelector('div.exp_social-proof__top-right[data-product-id=\"' + swatchProductId + '\"]');\n        const bannerOverImage = document.querySelector('div.exp_social-proof__over-image[data-product-id=\"' + swatchProductId + '\"]');\n\n        if (bannerTopRight || bannerOverImage) {\n            return;\n        }\n\t\tif (productIDs.includes(swatchProductId)) {\n\t\t\t    console.log('Product ID is in the list, skipping social login.');\n\t\t\t    exponea.showWebLayer('68a64cf67007a25bb347722b', { \"product_id\": '123' });\n\t\t} else {\n\t\t\t// Banner - Top Right on PDP\n\t        exponea.showWebLayer('68a64cf67007a25bb347722b', { \"product_id\": swatchProductId });\n\t\n\t        // Banner - Over First Product Image\n\t        exponea.showWebLayer('68a64da036ba0101a6419cd6', { \"product_id\": swatchProductId });\n\t\t}\n        \n\n    }\n}, 350), false);\n","trigger":{"include_pages":[{"url":"/en-us/p/","type":"contains"}],"exclude_pages":[{"url":"www3","type":"contains"},{"url":"VN000XW46X7","type":"contains"},{"url":"VN000XW49Y1","type":"contains"},{"url":"VN000XW4CJG","type":"contains"},{"url":"VN000XW4E0L","type":"contains"},{"url":"VN000XW4N5B","type":"contains"},{"url":"VN000DB824O","type":"contains"},{"url":"VN000DB8MCG","type":"contains"},{"url":"VN000DB8Z11","type":"contains"},{"url":"VN000EGWBLA","type":"contains"},{"url":"VN000EGWWVD","type":"contains"},{"url":"VN000EGWDFP","type":"contains"},{"url":"VN000EFUBLA","type":"contains"},{"url":"VN000EFUWVD","type":"contains"},{"url":"VN000D9PBKA","type":"contains"},{"url":"VN000D9PCAK","type":"contains"},{"url":"VN000D9PIND","type":"contains"},{"url":"VN000E8VYA6","type":"contains"},{"url":"VN000D9RCJK","type":"contains"},{"url":"VN000D9RGRK","type":"contains"},{"url":"VN000Z6KBLA","type":"contains"},{"url":"VN000Z6KCJ7","type":"contains"},{"url":"VN000Y1D2BO","type":"contains"},{"url":"VN000Y1DICP","type":"contains"},{"url":"VN000E8VFST","type":"contains"},{"url":"VN000EFEBLK","type":"contains"},{"url":"VN000EFF3KY","type":"contains"},{"url":"VN000EFFHB1","type":"contains"},{"url":"VN000DC0IVG","type":"contains"},{"url":"VN000DC0UXM","type":"contains"},{"url":"VN000EKSGED","type":"contains"},{"url":"VN000Y1CHAD","type":"contains"},{"url":"VN000Y1CHAY","type":"contains"},{"url":"VN000D9RDJR","type":"contains"},{"url":"VN000D9RH91","type":"contains"},{"url":"VN000DB8BER","type":"contains"},{"url":"VN000DB8BML","type":"contains"}]},"_id":"68a64cc6994728798f73f9ea"},{"uses_overlay":false,"type":"js","parametrized_definition":"console.log('Purchased Count Banner Tag - US');\n\nfunction debounce(fn, delay) {\n    let timeoutId;\n\n    return function (...args) {\n        clearTimeout(timeoutId);\n        timeoutId = setTimeout(() =\u003e {\n            fn.apply(this, args);\n        }, delay);\n    };\n}\n\nconst throttle = (fn, delay) =\u003e {\n    let last = 0;\n    return (...args) =\u003e {\n        let now = new Date().getTime();\n        if (now - last \u003c delay) {\n            return;\n        }\n        last = now;\n        return fn(...args);\n    }\n}\n\n/**\n * Function to extract the product ID from the current page URL.\n * @returns {string} The product ID extracted from the URL.\n */\nfunction getProductId() {\n    const path = window.location.pathname;\n    const pathArray = path.split('/');\n    const lastSegment = pathArray[pathArray.length - 1];\n    const lastSegmentArray = lastSegment.split('-');\n    const productId = lastSegmentArray[lastSegmentArray.length - 1];\n    return productId;\n}\n\n/**\n * Function to extract the product ID from the image URL.\n * @param {string} url\n * @returns {string} The product ID extracted from the image URL.\n */\nfunction getProductIdFromImageUrl(url) {\n    // Example: .../VN000D5VEMQ-HERO/washed-black-swatch.jpg\n    // Extract the segment before the last '/' and split by '-' to get the product id\n    if (!url) return '';\n    const parts = url.split('/');\n    if (parts.length \u003c 2) return '';\n    const segment = parts[parts.length - 2]; // e.g., 'VN000D5VEMQ-HERO'\n    return segment.split('-')[0]; // e.g., 'VN000D5VEMQ'\n}\n\n\nconst productId = getProductId();\n// console.log('Product ID:', productId);\n\n// Banner - Top Right on PDP\nexponea.showWebLayer('68a652339111d29e88387f79', { \"product_id\": productId });\n\n// Banner - Over First Product Image\nexponea.showWebLayer('68a652563c5977ee1e31e9c6', { \"product_id\": productId });\n\n\ndocument.addEventListener('click', debounce(function (event) {\n    if (event.target.matches('button[data-test-id=\"vf-color-picker\"] img')) {\n        const imageUrl = event.target.src;\n        const swatchProductId = getProductIdFromImageUrl(imageUrl);\n\n        const bannerTopRight = document.querySelector('div.exp_social-proof__top-right[data-product-id=\"' + swatchProductId + '\"]');\n        const bannerOverImage = document.querySelector('div.exp_social-proof__over-image[data-product-id=\"' + swatchProductId + '\"]');\n\n        if (bannerTopRight || bannerOverImage) {\n            return;\n        }\n\n        // Banner - Top Right on PDP\n        exponea.showWebLayer('68a652339111d29e88387f79', { \"product_id\": swatchProductId });\n\n        // Banner - Over First Product Image\n        exponea.showWebLayer('68a652563c5977ee1e31e9c6', { \"product_id\": swatchProductId });\n\n    }\n}, 350), false);\n","trigger":{"include_pages":[{"url":"/en-ca/p/","type":"contains"},{"url":"/fr-ca/p/","type":"contains"}],"exclude_pages":[{"url":"www3","type":"contains"}]},"_id":"68a6521986a3e8e137b1b75e"}],"vars":{"data":[{"id":"67bc74e6aa7034bb355fcb50","name":"Subdomain","variable":{"type":"custom_function","custom_function":{"body":"const host = window.location.host;\nconst subdomain = window.location.host.match(/([^.\\/]+)(?=\\.vans\\.com)/)[1];\nreturn subdomain;"}}},{"id":"67bc7bed918a683daac200a2","name":"Locale","variable":{"type":"custom_function","custom_function":{"body":"const locale = document.querySelector('html').getAttribute('lang');\nreturn locale;"}}},{"id":"69a732012aa593e0ecccf3e4","name":"Locale","variable":{"type":"custom_function","custom_function":{"body":"const locale = document.querySelector('html').getAttribute('lang');\nconsole.log('locale:', locale);\nreturn locale;"}}}]}}