1(()=>{const MANAGER_SELECTOR="vl-product-compare-manager";function escapeHtml(value){return String(value??"").replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""").replaceAll("'","'")}function formatSpecValueHtml(value){return String(value??"").split(/\s*\|\|\s*|\r?\n/).map(line=>line.trim()).filter(Boolean).map(escapeHtml).join("<br>")}function comparableSpecValue(value){return String(value??"").replace(/\s*(?:\|\||\r?\n)\s*/g,` 2`).trim().toLowerCase()}function formatMoney(value,currency){if(value==null||value==="")return"";const amount=Number(value)/100,hasFraction=Math.round(amount*100)%100!==0;return new Intl.NumberFormat(document.documentElement.lang||"en",{style:"currency",currency:currency||"USD",minimumFractionDigits:hasFraction?2:0,maximumFractionDigits:hasFraction?2:0}).format(amount)}function variantImage(variant){return variant?.featured_image?.src||variant?.featured_image||""}function productVariantUrl(productState){const handle=productState.product?.handle||"",variantId=productState.variant?.id;return`/products/${handle}${variantId?`?variant=${encodeURIComponent(variantId)}`:""}`}function domToken(value){return String(value||"specifications").toLowerCase().replace(/[^a-z0-9_-]+/g,"-")}function swatchBackground(value,patterns=""){const colorName=String(value||"").trim(),swatchValue=String(patterns).split(/\r?\n/).reduce((match,pattern)=>{const[label,...parts]=pattern.split("::");return label?.trim().toLowerCase()===colorName.toLowerCase()?parts.join("::").trim():match},"")||colorName;if(/\.(png|jpe?g|webp)$/i.test(swatchValue))return`url("/cdn/shop/files/${encodeURIComponent(swatchValue)}")`;const colors=swatchValue.split("/").map(color=>color.trim()).filter(color=>window.CSS?.supports?.("color",color));if(colors.length>1){const legacyStops={2:["-6.77%","85.41%"],3:["15.26%","49.98%","84.7%"],5:["25.68%","36.63%","52.32%","64%","74.29%"]}[colors.length];if(legacyStops)return`linear-gradient(44deg, ${colors.map((color,index)=>`${color} ${legacyStops[index]}`).join(", ")})`;const step=100/(colors.length-1);return`linear-gradient(44deg, ${colors.map((color,index)=>`${color} ${index*step}%`).join(", ")})`}return colors[0]||"#d9d9d9"}function colorValuesForSelection(productState,colorIndex){const variants=Array.isArray(productState.product?.variants)?productState.product.variants:[],selectedOptionFields=["style","size"].filter(field=>productState.optionIndexes?.[field]!=null&&productState.selection?.[field]!=null);return Array.from(new Set(variants.filter(variant=>selectedOptionFields.every(field=>variant.options?.[productState.optionIndexes[field]]===productState.selection[field])).map(variant=>variant.options?.[colorIndex]).filter(Boolean)))}function renderOptionGroups(productState,fields=productState.optionSchema){const{product,optionSchema,selection}=productState;return fields.map(field=>{const index=optionSchema.indexOf(field),optionIndex=productState.optionIndexes?.[field]??index,option=product.options?.[optionIndex],label=typeof option=="string"?option:option?.name||field,values=field==="color"?colorValuesForSelection(productState,optionIndex):Array.from(new Set((product.variants||[]).map(variant=>variant.options?.[optionIndex]).filter(Boolean)));return field==="color"?` 3 <fieldset class="vl-product-compare__option-group vl-product-compare__option-group--color" data-option-field="${escapeHtml(field)}"> 4 <legend>${escapeHtml(label)}</legend> 5 <div class="vl-product-compare__color-values"> 6 ${values.map(value=>` 7 <label class="vl-product-compare__color-value" title="${escapeHtml(value)}"> 8 <input 9 type="radio" 10 name="compare-${escapeHtml(productState.id)}-${escapeHtml(field)}" 11 value="${escapeHtml(value)}" 12 data-vl-product-compare-option 13 data-product-id="${escapeHtml(productState.id)}" 14 data-option-field="${escapeHtml(field)}" 15 ${selection[field]===value?"checked":""} 16 >
17 <span style="--vl-compare-swatch: ${escapeHtml(swatchBackground(value,productState.swatchPatterns))}"></span> 18 <span class="visually-hidden">${escapeHtml(value)}</span> 19 </label> 20 `).join("")} 21 </div> 22 </fieldset> 23 `:` 24 <label class="vl-product-compare__option-select"> 25 <span class="vl-product-compare__option-label">${escapeHtml(label)}</span> 26 <span class="vl-product-compare__select-wrap"> 27 <span class="vl-product-compare__select-value" aria-hidden="true">${escapeHtml(selection[field]||values[0]||"")}</span> 28 <span class="vl-product-compare__select-chevron" aria-hidden="true"> 29 <svg width="14" height="14" viewBox="0 0 20 20" fill="none"> 30 <path d="M9.71886 13.702C9.88158 13.8647 10.1453 13.8647 10.3081 13.702L17.0846 6.92546C17.2472 6.76275 17.2472 6.49895 17.0846 6.33627L16.4954 5.74708C16.3327 5.5844 16.0689 5.58448 15.9062 5.74708L10.0135 11.6398L4.12071 5.74708C3.95799 5.5844 3.69422 5.58437 3.53152 5.74708L2.94233 6.33627C2.77963 6.49897 2.77966 6.76274 2.94233 6.92546L9.71886 13.702Z" fill="#1F1F1F"/> 31 </svg> 32 </span> 33 <select 34 data-vl-product-compare-option 35 data-product-id="${escapeHtml(productState.id)}" 36 data-option-field="${escapeHtml(field)}" 37 aria-label="${escapeHtml(label)}" 38 > 39 ${values.map(value=>`<option value="${escapeHtml(value)}" ${selection[field]===value?"selected":""}>${escapeHtml(value)}</option>`).join("")} 40 </select> 41 </span> 42 </label> 43 `}).join("")}function renderChoiceOptions(productState,labels){const choiceFields=productState.optionSchema.filter(field=>field!=="color");return choiceFields.length?renderOptionGroups(productState,choiceFields):productState.optionSchema.includes("color")?` 44 <span class="vl-product-compare__option-select vl-product-compare__option-select--static"> 45 <span class="vl-product-compare__select-wrap vl-product-compare__select-wrap--static"> 46 <span class="vl-product-compare__select-value">${escapeHtml(labels.oneSize||"One Size")}</span> 47 </span> 48 </span> 49 `:""}function renderProductImage(productState,index,linkToProduct){const image=variantImage(productState.variant);if(!image)return"";const imageAlt=linkToProduct?"":productState.fullName,imageMarkup=`<img src="${escapeHtml(image)}" alt="${escapeHtml(imageAlt)}" loading="${index===0?"eager":"lazy"}" decoding="async" data-vl-product-compare-image>`;return linkToProduct?` 50 <a 51 class="vl-product-compare__image-link" 52 href="${escapeHtml(productVariantUrl(productState))}" 53 aria-hidden="true" 54 tabindex="-1" 55 > 56 ${imageMarkup} 57 </a> 58 `:imageMarkup}function renderProduct(productState,index,labels,linkImageToProduct){const{variant}=productState,currency=window.Shopify?.currency?.active||"USD";return` 59 <article class="vl-product-compare__product" data-product-id="${escapeHtml(productState.id)}"> 60 <div class="vl-product-compare__product-primary"> 61 <div class="vl-product-compare__image-frame"> 62 ${renderProductImage(productState,index,linkImageToProduct)} 63 </div> 64 <h2 class="visually-hidden">${escapeHtml(productState.fullName)}</h2> 65 <div class="vl-product-compare__options vl-product-compare__options--choices">${renderChoiceOptions(productState,labels)}</div> 66 </div> 67 <div class="vl-product-compare__product-colors"> 68 <div class="vl-product-compare__options vl-product-compare__options--colors">${renderOptionGroups(productState,productState.optionSchema.filter(field=>field==="color"))}</div> 69 </div> 70 <div class="vl-product-compare__product-commerce"> 71 <div class="vl-product-compare__product-commerce-copy"> 72 <div class="vl-product-compare__variant-price"> 73 <span>${escapeHtml(formatMoney(variant?.price,currency))}</span> 74 ${Number(variant?.compare_at_price||0)>Number(variant?.price||0)?`<s>${escapeHtml(formatMoney(variant.compare_at_price,currency))}</s>`:""} 75 </div> 76 ${variant?.price?`<p class="vl-product-compare__financing affirm-as-low-as" data-page-type="product" data-amount="${escapeHtml(variant.price)}"></p>`:""} 77 ${variant?.sku?`<p class="vl-product-compare__sku visually-hidden">SKU: ${escapeHtml(variant.sku)}</p>`:""} 78 ${variant?.available===!1?`<p class="vl-product-compare__availability">${escapeHtml(labels.unavailable||"Unavailable")}</p>`:""} 79 </div> 80 <a class="vl-product-compare__explore" href="${escapeHtml(productVariantUrl(productState))}"> 81 ${escapeHtml(labels.exploreEbike||"Explore EBike")}
82 <span class="visually-hidden">: ${escapeHtml(productState.fullName)}</span> 83 </a> 84 </div> 85 </article> 86 `}function renderEmptyProduct(index,labels){return` 87 <article class="vl-product-compare__product vl-product-compare__product--empty"> 88 <button type="button" class="vl-product-compare__empty-button" data-vl-product-compare-selector data-slot-index="${index}" aria-haspopup="dialog"> 89 <span aria-hidden="true"> 90 <svg viewBox="0 0 20 20" fill="none"> 91 <path d="M10 2.5v15M2.5 10h15" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/> 92 </svg> 93 </span> 94 <span class="visually-hidden">${escapeHtml(labels.selectThirdEbike||"Select a third ebike to compare")}</span> 95 </button> 96 </article> 97 `}function slotsFor(products){const slots=[...products];for(;slots.length<3;)slots.push(null);return slots}function renderProducts(manager,products){const productsContainer=manager.querySelector("[data-vl-product-compare-products]"),selectorsContainer=manager.querySelector("[data-vl-product-compare-selectors]"),stickyActionsContainer=manager.querySelector("[data-vl-product-compare-sticky-actions]");if(!productsContainer||!selectorsContainer)return;const slots=slotsFor(products);selectorsContainer.innerHTML=slots.map((product,index)=>{const fixedPdpProduct=manager.mode==="pdp"&&index===0;return` 98 <button type="button" class="${product?"":"vl-product-compare__selector--empty"}" data-vl-product-compare-selector data-slot-index="${index}" aria-haspopup="dialog" ${fixedPdpProduct?'disabled aria-disabled="true"':""}> 99 <span class="vl-product-compare__selector-title" title="${escapeHtml(product?.shortName||manager.labels?.selectEbike||"Select Ebike")}">${escapeHtml(product?.shortName||manager.labels?.selectEbike||"Select Ebike")}</span> 100 ${fixedPdpProduct?"":`<span class="vl-product-compare__selector-chevron" aria-hidden="true"> 101 <svg width="20" height="20" viewBox="0 0 20 20" fill="none"> 102 <path d="M9.71886 13.702C9.88158 13.8647 10.1453 13.8647 10.3081 13.702L17.0846 6.92546C17.2472 6.76275 17.2472 6.49895 17.0846 6.33627L16.4954 5.74708C16.3327 5.5844 16.0689 5.58448 15.9062 5.74708L10.0135 11.6398L4.12071 5.74708C3.95799 5.5844 3.69422 5.58437 3.53152 5.74708L2.94233 6.33627C2.77963 6.49897 2.77966 6.76274 2.94233 6.92546L9.71886 13.702Z" fill="#1F1F1F"/> 103 </svg> 104 </span>`} 105 </button> 106 `}).join(""),productsContainer.innerHTML=slots.map((product,index)=>product?renderProduct(product,index,manager.labels||{},manager.mode==="page"):renderEmptyProduct(index,manager.labels||{})).join(""),stickyActionsContainer&&(stickyActionsContainer.innerHTML=slots.map(product=>product?`<a class="vl-product-compare__sticky-explore" href="${escapeHtml(productVariantUrl(product))}"> 107 ${escapeHtml(manager.labels?.exploreEbike||"Explore EBike")} 108 <span class="visually-hidden">: ${escapeHtml(product.fullName)}</span> 109 </a>`:'<span class="vl-product-compare__sticky-explore-placeholder" aria-hidden="true"></span>').join(""))}function updateVariantProduct(manager,products,productId,optionField){const index=products.findIndex(product=>String(product.id)===String(productId)),productsContainer=manager.querySelector("[data-vl-product-compare-products]"),productState=products[index],productElement=productsContainer?.children[index];if(!productState||!productElement||productElement.dataset.productId!==String(productId))return{updated:!1,affirmChanged:!1};const restoreOptionFocus=document.activeElement?.closest?.("[data-vl-product-compare-option]")?.dataset.productId===String(productId),{variant}=productState,image=variantImage(variant),imageFrame=productElement.querySelector(".vl-product-compare__image-frame"),currentImage=imageFrame?.querySelector("[data-vl-product-compare-image]"),productUrl=productVariantUrl(productState);if(imageFrame){imageFrame.classList.remove("has-image-error");const imageLink=imageFrame.querySelector(".vl-product-compare__image-link");imageLink&&(imageLink.href=productUrl),image?currentImage?(currentImage.src=image,currentImage.alt=manager.mode==="page"?"":productState.fullName||"",currentImage.hidden=!1):imageFrame.innerHTML=renderProductImage(productState,index,manager.mode==="page"):imageFrame.replaceChildren()}const exploreLink=productElement.querySelector(".vl-product-compare__explore");exploreLink&&(exploreLink.href=productUrl);const stickyExploreLink=manager.querySelector("[data-vl-product-compare-sticky-actions]")?.children[index];stickyExploreLink?.matches(".vl-product-compare__sticky-explore")&&(stickyExploreLink.href=productUrl);const choiceOptions=productElement.querySelector(".vl-product-compare__options--choices"),colorOptions=productElement.querySelector(".vl-product-compare__options--colors");choiceOptions&&(choiceOptions.innerHTML=renderChoiceOptions(productState,manager.labels||{})),colorOptions&&(colorOptions.innerHTML=renderOptionGroups(productState,productState.optionSchema.filter(field=>field==="color")));const currency=window.Shopify?.currency?.active||"USD",price=productElement.querySelector(".vl-product-compare__variant-price");price&&(price.innerHTML=`
110 <span>${escapeHtml(formatMoney(variant?.price,currency))}</span> 111 ${Number(variant?.compare_at_price||0)>Number(variant?.price||0)?`<s>${escapeHtml(formatMoney(variant.compare_at_price,currency))}</s>`:""} 112 `);const commerceCopy=productElement.querySelector(".vl-product-compare__product-commerce-copy");let financing=productElement.querySelector(".vl-product-compare__financing"),affirmChanged=!1;const amount=variant?.price?String(variant.price):"";if(amount){if(!financing){financing=document.createElement("p"),financing.className="vl-product-compare__financing affirm-as-low-as",financing.dataset.pageType="product";const nextCommerceDetail=commerceCopy?.querySelector(".vl-product-compare__sku, .vl-product-compare__availability");nextCommerceDetail?nextCommerceDetail.before(financing):commerceCopy?.append(financing),affirmChanged=!0}financing.dataset.amount!==amount&&(financing.dataset.amount=amount,affirmChanged=!0)}else financing&&financing.remove();let sku=productElement.querySelector(".vl-product-compare__sku");if(variant?.sku){if(!sku){sku=document.createElement("p"),sku.className="vl-product-compare__sku visually-hidden";const availabilityDetail=commerceCopy?.querySelector(".vl-product-compare__availability");availabilityDetail?availabilityDetail.before(sku):commerceCopy?.append(sku)}sku.textContent=`SKU: ${variant.sku}`}else sku?.remove();let availability=productElement.querySelector(".vl-product-compare__availability");return variant?.available===!1?(availability||(availability=document.createElement("p"),availability.className="vl-product-compare__availability",commerceCopy?.append(availability)),availability.textContent=manager.labels?.unavailable||"Unavailable"):availability?.remove(),restoreOptionFocus&&Array.from(productElement.querySelectorAll("[data-vl-product-compare-option]")).find(input=>input.dataset.optionField===optionField&&(input.tagName==="SELECT"||input.checked))?.focus({preventScroll:!0}),{updated:!0,affirmChanged}}function normalizedSpecValue(value,definition,labels){if(value==null||value==="")return labels.notAvailable||"\u2014";if(typeof value=="boolean")return value?labels.yes||"Yes":labels.no||"No";const formattedValue=String(value).trim(),unit=String(definition.unit||"").trim();return!unit||formattedValue.toLowerCase().endsWith(unit.toLowerCase())?formattedValue:`${formattedValue} ${unit}`}function specGroups(manager){const definitions=(manager.specDefinitions||[]).filter(definition=>definition.enabled!==!1&&definition.group?.enabled!==!1&&definition.key).sort((left,right)=>Number(left.group?.order||0)-Number(right.group?.order||0)||Number(left.order||0)-Number(right.order||0)),groups=new Map;return definitions.forEach(definition=>{const key=definition.group?.key||"specifications";groups.has(key)||groups.set(key,{...definition.group,key,definitions:[]}),groups.get(key).definitions.push(definition)}),Array.from(groups.values())}
112function renderSpecs(manager,products){const container=manager.querySelector("[data-vl-product-compare-specs]"),navs=manager.querySelectorAll("[data-vl-product-compare-spec-nav]");if(!container||!navs.length)return;const groups=specGroups(manager),slots=slotsFor(products),navHtml=groups.filter(group=>group.name).map((group,index)=>{const groupToken=domToken(group.key);return`<a href="#vl-compare-${groupToken}" data-vl-product-compare-nav data-group-key="${groupToken}" ${index===0?'class="is-active" aria-current="true"':""}>${escapeHtml(group.name)}</a>`}).join("");navs.forEach(nav=>{nav.innerHTML=navHtml}),container.innerHTML=groups.map(group=>` 113 <section class="vl-product-compare__spec-group${group.name?"":" vl-product-compare__spec-group--unheaded"}" id="vl-compare-${domToken(group.key)}" data-group-key="${domToken(group.key)}" role="rowgroup"> 114 ${group.name?`<h2>${escapeHtml(group.name)}</h2>`:""} 115 <div class="vl-product-compare__spec-group-scroll" data-vl-product-compare-scroll tabindex="0" aria-label="${escapeHtml(`${group.name||manager.labels?.specifications||"Specifications"}. ${manager.labels?.horizontalScrollHint||""}`.trim())}"> 116 <div class="vl-product-compare__spec-group-rows"> 117 ${group.definitions.map(definition=>{const presentValues=products.map(product=>normalizedSpecValue(product.specs?.[definition.key],definition,manager.labels||{})),isDifferent=new Set(presentValues.map(comparableSpecValue)).size>1,isNumeric=!!String(definition.unit||"").trim();return` 118 <div class="vl-product-compare__spec-row${definition.icon?" vl-product-compare__spec-row--with-icon":""}${isDifferent?" is-different":""}" role="row"> 119 <div class="vl-product-compare__spec-values"> 120 ${slots.map(product=>` 121 <div class="vl-product-compare__spec-value${definition.icon?" vl-product-compare__spec-value--with-icon":""}${isNumeric?" vl-product-compare__spec-value--numeric":""}" role="cell"> 122 ${definition.icon?`<img class="vl-product-compare__spec-icon" src="${escapeHtml(definition.icon)}" alt="" loading="lazy">`:""} 123 <span class="vl-product-compare__spec-field">${escapeHtml(definition.label||definition.key)}</span> 124 <span class="vl-product-compare__spec-data">${formatSpecValueHtml(product?normalizedSpecValue(product.specs?.[definition.key],definition,manager.labels||{}):"\u2014")}</span> 125 </div> 126 `).join("")} 127 </div> 128 </div> 129 `}).join("")} 130 </div> 131 </div> 132 </section> 133 `).join("")}function applyDifferenceFilter(manager){const differencesOnly=!!manager.querySelector("[data-vl-product-compare-differences]")?.checked;manager.classList.toggle("is-showing-differences",differencesOnly),manager.querySelectorAll(".vl-product-compare__spec-row").forEach(row=>{row.hidden=differencesOnly&&!row.classList.contains("is-different")}),manager.querySelectorAll(".vl-product-compare__spec-group").forEach(group=>{group.hidden=differencesOnly&&!group.querySelector(".vl-product-compare__spec-row.is-different")}),manager.querySelectorAll("[data-vl-product-compare-nav]").forEach(link=>{const group=manager.querySelector(`.vl-product-compare__spec-group[data-group-key="${link.dataset.groupKey}"]`);link.hidden=!!group?.hidden}),manager.querySelector("[data-vl-product-compare-nav].is-active:not([hidden])")||setActiveNav(manager,manager.querySelector("[data-vl-product-compare-nav]:not([hidden])")?.dataset.groupKey)}function navigableGroupKey(manager,groupKey){if(!groupKey)return null;const navKeys=new Set(Array.from(manager.querySelectorAll("[data-vl-product-compare-nav]:not([hidden])")).map(link=>link.dataset.groupKey));if(navKeys.has(groupKey))return groupKey;const groups=Array.from(manager.querySelectorAll(".vl-product-compare__spec-group:not([hidden])")),groupIndex=groups.findIndex(group=>group.dataset.groupKey===groupKey);if(groupIndex>=0){for(let index=groupIndex+1;index<groups.length;index+=1)if(navKeys.has(groups[index].dataset.groupKey))return groups[index].dataset.groupKey;for(let index=groupIndex-1;index>=0;index-=1)if(navKeys.has(groups[index].dataset.groupKey))return groups[index].dataset.groupKey}return navKeys.values().next().value||null}function setActiveNav(manager,groupKey){const activeGroupKey=navigableGroupKey(manager,groupKey);if(!activeGroupKey)return;const navLinks=Array.from(manager.querySelectorAll("[data-vl-product-compare-nav]"));if(navLinks.length>0&&navLinks.every(link=>link.classList.contains("is-active")===(link.dataset.groupKey===activeGroupKey)))return;let activeHorizontalLink=null;navLinks.forEach(link=>{const active=link.dataset.groupKey===activeGroupKey;link.classList.toggle("is-active",active),active?link.setAttribute("aria-current","true"):link.removeAttribute("aria-current"),active&&link.closest(".vl-product-compare__spec-nav-mobile")&&(activeHorizontalLink=link)});const nav=activeHorizontalLink?.closest(".vl-product-compare__spec-nav-mobile");if(!nav||nav.scrollWidth<=nav.clientWidth)return;const targetLeft=activeHorizontalLink.offsetLeft-(nav.clientWidth-activeHorizontalLink.offsetWidth)/2;nav.scrollTo({left:Math.max(0,targetLeft),behavior:window.matchMedia("(prefers-reduced-motion: reduce)").matches?"auto":"smooth"})}function specScrollRoot(manager){return manager.classList.contains("vl-product-compare--pdp")&&manager.closest("#compare_popup")?.querySelector(".popup__content-container")||null}function clearSpecNavScrollLock(manager){manager.specNavScrollRoot&&manager.specNavScrollHandler&&manager.specNavScrollRoot.removeEventListener("scroll",manager.specNavScrollHandler),window.clearTimeout(manager.specNavScrollEndTimer),window.clearTimeout(manager.specNavScrollFallbackTimer),delete manager.specNavLockedKey,delete manager.specNavScrollRoot,delete manager.specNavScrollHandler,delete manager.specNavScrollEndTimer,delete manager.specNavScrollFallbackTimer,delete manager.specNavScrollTarget,delete manager.specNavAlignmentAttempts}function alignSpecGroup(manager,target,scrollRoot,behavior="auto"){const targetRect=target.getBoundingClientRect(),rootRect=scrollRoot?.getBoundingClientRect(),currentTop=targetRect.top-(rootRect?.top||0),expectedTop=Number.parseFloat(window.getComputedStyle(target).scrollMarginTop)||0,delta=currentTop-expectedTop;return Math.abs(delta)<=1||(scrollRoot?scrollRoot.scrollTo({top:scrollRoot.scrollTop+delta,behavior}):window.scrollTo({top:window.scrollY+delta,behavior})),delta}function finishSpecNavScroll(manager){const target=manager.specNavScrollTarget;if(target?.isConnected&&manager.specNavLockedKey){const delta=alignSpecGroup(manager,target,specScrollRoot(manager));if(manager.specNavAlignmentAttempts=(manager.specNavAlignmentAttempts||0)+1,Math.abs(delta)>2&&manager.specNavAlignmentAttempts<3){window.clearTimeout(manager.specNavScrollEndTimer),manager.specNavScrollEndTimer=window.setTimeout(()=>finishSpecNavScroll(manager),120);return}}clearSpecNavScrollLock(manager)}function lockSpecNavDuringScroll(manager,groupKey,scrollRoot,target){clearSpecNavScrollLock(manager),manager.specNavLockedKey=groupKey,manager.specNavScrollRoot=scrollRoot||window,manager.specNavScrollTarget=target,manager.specNavAlignmentAttempts=0,manager.specNavScrollHandler=()=>{window.clearTimeout(manager.specNavScrollEndTimer),manager.specNavScrollEndTimer=window.setTimeout(()=>finishSpecNavScroll(manager),180)},manager.specNavScrollRoot.addEventListener("scroll",manager.specNavScrollHandler,{passive:!0}),manager.specNavScrollEndTimer=window.setTimeout(()=>finishSpecNavScroll(manager),220),manager.specNavScrollFallbackTimer=window.setTimeout(()=>finishSpecNavScroll(manager),2400)}function scrollToSpecGroup(manager,groupKey){const target=manager.querySelector(`.vl-product-compare__spec-group[data-group-key="${groupKey}"]`);if(!target)return;const scrollRoot=specScrollRoot(manager),behavior=window.matchMedia("(prefers-reduced-motion: reduce)").matches?"auto":"smooth";lockSpecNavDuringScroll(manager,groupKey,scrollRoot,target),setActiveNav(manager,groupKey),alignSpecGroup(manager,target,scrollRoot,behavior)}function currentSpecGroup(manager,scrollRoot){const groups=Array.from(manager.querySelectorAll(".vl-product-compare__spec-group:not([hidden])"));if(!groups.length)return null;const scrollTop=scrollRoot?scrollRoot.scrollTop:window.scrollY,viewportHe
133ight=scrollRoot?scrollRoot.clientHeight:window.innerHeight,scrollHeight=scrollRoot?scrollRoot.scrollHeight:document.documentElement.scrollHeight,remainingScroll=Math.max(0,scrollHeight-viewportHeight-scrollTop);if(remainingScroll<=2?manager.specNavAtEnd=!0:remainingScroll>32&&(manager.specNavAtEnd=!1),manager.specNavAtEnd)return groups.at(-1);const rootRect=scrollRoot?.getBoundingClientRect(),rootTop=rootRect?.top||0,rootHeight=rootRect?.height||window.innerHeight,activationLine=rootTop+rootHeight*.2,reachedGroups=groups.filter(group=>group.getBoundingClientRect().top<=activationLine);return reachedGroups.length?reachedGroups.at(-1):groups[0]}function observeSpecGroups(manager){manager.specNavObserver?.disconnect(),manager.specNavTrackingTarget?.removeEventListener("scroll",manager.specNavTrackingHandler),manager.specNavTrackingFrame!=null&&window.cancelAnimationFrame(manager.specNavTrackingFrame),manager.specNavAtEnd=!1;const scrollRoot=specScrollRoot(manager);manager.specNavTrackingTarget=scrollRoot||window,manager.specNavTrackingHandler=()=>{manager.specNavTrackingFrame==null&&(manager.specNavTrackingFrame=window.requestAnimationFrame(()=>{if(manager.specNavTrackingFrame=null,manager.specNavLockedKey)return;const activeGroup=currentSpecGroup(manager,scrollRoot);activeGroup&&setActiveNav(manager,activeGroup.dataset.groupKey)}))},manager.specNavTrackingTarget.addEventListener("scroll",manager.specNavTrackingHandler,{passive:!0}),manager.specNavObserver=new IntersectionObserver(()=>{manager.specNavTrackingHandler()},{root:scrollRoot,rootMargin:"-20% 0px -65% 0px"}),manager.querySelectorAll(".vl-product-compare__spec-group").forEach(group=>manager.specNavObserver.observe(group))}function renderCandidates(manager,candidates,slotIndex){const container=manager.querySelector("[data-vl-product-compare-candidates]");if(!container)return;const selectedHandles=new Set(manager.products.map(product=>product.handle)),groups=new Map;candidates.forEach(candidate=>{const rawCategory=candidate.category,category=rawCategory&&typeof rawCategory=="object"?rawCategory:{key:rawCategory||"other",name:rawCategory||"Other",order:999,enabled:!0};if(category.enabled===!1)return;const categoryKey=String(category.key||category.name||"other");groups.has(categoryKey)||groups.set(categoryKey,{key:categoryKey,name:category.name||"Other",order:Number.isFinite(Number(category.order))?Number(category.order):999,products:[]}),groups.get(categoryKey).products.push(candidate)});const sortedGroups=Array.from(groups.values()).sort((left,right)=>left.order-right.order||left.name.localeCompare(right.name));sortedGroups.forEach(group=>{group.products.sort((left,right)=>(Number.isFinite(Number(left.selectorOrder))?Number(left.selectorOrder):999)-(Number.isFinite(Number(right.selectorOrder))?Number(right.selectorOrder):999)||String(left.title||"").localeCompare(String(right.title||"")))}),container.innerHTML=sortedGroups.map(group=>` 134 <details class="vl-product-compare__candidate-group" open> 135 <summary> 136 <span>${escapeHtml(group.name)}</span> 137 <span class="vl-product-compare__candidate-chevron" aria-hidden="true"> 138 <svg class="vl-product-compare__chevron-down" width="18" height="18" viewBox="0 0 20 20" fill="none"> 139 <path d="M9.71886 13.702C9.88158 13.8647 10.1453 13.8647 10.3081 13.702L17.0846 6.92546C17.2472 6.76275 17.2472 6.49895 17.0846 6.33627L16.4954 5.74708C16.3327 5.5844 16.0689 5.58448 15.9062 5.74708L10.0135 11.6398L4.12071 5.74708C3.95799 5.5844 3.69422 5.58437 3.53152 5.74708L2.94233 6.33627C2.77963 6.49897 2.77966 6.76274 2.94233 6.92546L9.71886 13.702Z" fill="#1F1F1F"/> 140 </svg> 141 <svg class="vl-product-compare__chevron-up" width="18" height="18" viewBox="0 0 18 18" fill="none"> 142 <path d="M8.74775 5.17238C8.8942 5.02597 9.13159 5.02594 9.27803 5.17238L15.3769 11.2713C15.5232 11.4177 15.5233 11.6551 15.3769 11.8015L14.8466 12.3318C14.7002 12.4782 14.4628 12.4781 14.3164 12.3318L9.01289 7.02833L3.70942 12.3318C3.56297 12.4782 3.32558 12.4782 3.17915 12.3318L2.64888 11.8015C2.50244 11.6551 2.50247 11.4177 2.64888 11.2713L8.74775 5.17238Z" fill="#1F1F1F"/> 143 </svg> 144 </span> 145 </summary> 146 <div class="vl-product-compare__candidate-grid"> 147 ${group.products.map(candidate=>{const selected=selectedHandles.has(candidate.handle);return` 148 <button type="button" class="vl-product-compare__candidate${selected?" is-selected":""}" 149 data-vl-product-compare-candidate data-handle="${escapeHtml(candidate.handle)}" data-slot-index="${slotIndex}" 150 ${selected?'disabled aria-disabled="true"':""}> 151 ${candidate.subtitle?`<span class="vl-product-compare__candidate-subtitle">${escapeHtml(candidate.subtitle)}</span>`:""}
152 <span class="vl-product-compare__candidate-image"> 153 ${candidate.image?`<img src="${escapeHtml(candidate.imageSmall||candidate.image)}"${candidate.imageSmall?` srcset="${escapeHtml(candidate.imageSmall)} 1x, ${escapeHtml(candidate.image)} 2x"`:""} alt="" loading="lazy" decoding="async">`:""} 154 </span> 155 <span class="vl-product-compare__candidate-title">${escapeHtml(candidate.title)}</span> 156 ${selected?`<span class="vl-product-compare__candidate-status">${escapeHtml(manager.labels?.selected||"Selected")}</span>`:""} 157 ${candidate.available===!1?`<span class="vl-product-compare__candidate-status">${escapeHtml(manager.labels?.unavailable||"Unavailable")}</span>`:""} 158 </button> 159 `}).join("")} 160 </div> 161 </details> 162 `).join("")}function syncScrollAreas(manager){const areas=Array.from(manager.querySelectorAll("[data-vl-product-compare-scroll]"));manager.vlScrollAreas=areas,manager.vlScrollResizeBound||(manager.vlScrollResizeBound=!0,window.addEventListener("resize",()=>{window.clearTimeout(manager.vlScrollResizeTimer),manager.vlScrollResizeTimer=window.setTimeout(()=>syncScrollAreas(manager),120)},{signal:manager.abortController?.signal}));const mobileLayout=window.matchMedia("(max-width: 1079px)").matches;areas.forEach(area=>{if(mobileLayout)area.dataset.vlScrollAriaLabel&&area.setAttribute("aria-label",area.dataset.vlScrollAriaLabel),area.matches(".vl-product-compare__sticky-actions-scroll")||(area.tabIndex=0);else{const ariaLabel=area.getAttribute("aria-label");ariaLabel&&(area.dataset.vlScrollAriaLabel=ariaLabel),area.removeAttribute("aria-label"),area.removeAttribute("tabindex"),area.scrollLeft=0}}),manager.vlScrollVisibilityObserver?.disconnect(),manager.vlScrollVisibilityObserver=null,mobileLayout&&typeof IntersectionObserver=="function"&&(manager.vlScrollVisibilityObserver=new IntersectionObserver(entries=>{entries.forEach(entry=>{!entry.isIntersecting||entry.target.hidden||Math.abs(entry.target.scrollLeft-manager.vlScrollSyncLeft)<=.5||(entry.target.vlExpectedScrollLeft=manager.vlScrollSyncLeft,entry.target.scrollLeft=manager.vlScrollSyncLeft)})}),areas.forEach(area=>manager.vlScrollVisibilityObserver.observe(area)));const shouldSyncArea=area=>{if(area.hidden)return!1;if(area.matches(".vl-product-compare__selectors-scroll, .vl-product-compare__sticky-actions-scroll"))return!0;const rect=area.getBoundingClientRect();return rect.bottom>0&&rect.top<window.innerHeight},wheelDelta=(event,value)=>event.deltaMode===WheelEvent.DOM_DELTA_LINE?value*16:event.deltaMode===WheelEvent.DOM_DELTA_PAGE?value*window.innerHeight:value,handleWheel=(area,event)=>{if(!window.matchMedia("(max-width: 1079px)").matches||event.ctrlKey||!event.cancelable)return;const deltaX=wheelDelta(event,event.deltaX),deltaY=wheelDelta(event,event.deltaY);if(!deltaX&&!deltaY)return;if(manager.vlWheelAxis||(manager.vlWheelAxis=Math.abs(deltaX)>Math.abs(deltaY)?"x":"y"),window.clearTimeout(manager.vlWheelAxisTimer),manager.vlWheelAxisTimer=window.setTimeout(()=>{manager.vlWheelAxis=null},140),event.preventDefault(),manager.vlWheelAxis==="x"){area.scrollLeft+=deltaX||deltaY;return}const popupScroller=manager.mode==="pdp"?manager.closest("#compare_popup")?.querySelector(".popup__content-container"):null;popupScroller?popupScroller.scrollTop+=deltaY:window.scrollBy({top:deltaY,left:0,behavior:"auto"})};mobileLayout&&areas.forEach(area=>{area.dataset.vlScrollSync!=="true"&&(area.dataset.vlScrollSync="true",area.addEventListener("wheel",event=>handleWheel(area,event),{passive:!1}),area.addEventListener("scroll",()=>{if(window.matchMedia("(max-width: 1079px)").matches){if(area!==manager.vlScrollSyncSource&&area.vlExpectedScrollLeft!=null&&Math.abs(area.scrollLeft-area.vlExpectedScrollLeft)<=.5){area.vlExpectedScrollLeft=null;return}area.vlExpectedScrollLeft=null,manager.vlScrollSyncSource=area,manager.vlScrollSyncLeft=area.scrollLeft,manager.vlScrollSyncFrame==null&&(manager.vlScrollSyncFrame=window.requestAnimationFrame(()=>{const source=manager.vlScrollSyncSource,scrollLeft=manager.vlScrollSyncLeft;manager.vlScrollSyncFrame=null,(manager.vlScrollAreas||[]).forEac
162h(other=>{other.isConnected&&other!==source&&shouldSyncArea(other)&&Math.abs(other.scrollLeft-scrollLeft)>.5&&(other.vlExpectedScrollLeft=scrollLeft,other.scrollLeft=scrollLeft)})}))}},{passive:!0}))})}function refreshAffirm(){const affirm=window.affirm;if(!affirm?.ui)return;const refresh=()=>{typeof affirm.ui.refresh=="function"&&affirm.ui.refresh()};try{typeof affirm.ui.ready=="function"?affirm.ui.ready(refresh):refresh()}catch{}}function lockSelectorPageScroll(manager,dialog){if(!window.matchMedia("(max-width: 1079px)").matches||manager.selectorScrollLock)return;const body=document.body,root=document.documentElement,scrollY=window.scrollY;manager.selectorScrollLock={scrollY,rootOverflow:root.style.overflow,bodyOverflow:body.style.overflow,bodyPosition:body.style.position,bodyTop:body.style.top,bodyLeft:body.style.left,bodyRight:body.style.right,bodyWidth:body.style.width},root.classList.add("vl-product-compare-dialog-open"),body.classList.add("vl-product-compare-dialog-open"),root.style.overflow="hidden",body.style.overflow="hidden",body.style.position="fixed",body.style.top=`${-scrollY}px`,body.style.left="0",body.style.right="0",body.style.width="100%",dialog.dataset.vlPageScrollLocked="true"}function unlockSelectorPageScroll(manager,dialog){const lock=manager.selectorScrollLock;if(!lock)return;const body=document.body,root=document.documentElement;root.classList.remove("vl-product-compare-dialog-open"),body.classList.remove("vl-product-compare-dialog-open"),root.style.overflow=lock.rootOverflow,body.style.overflow=lock.bodyOverflow,body.style.position=lock.bodyPosition,body.style.top=lock.bodyTop,body.style.left=lock.bodyLeft,body.style.right=lock.bodyRight,body.style.width=lock.bodyWidth,delete dialog.dataset.vlPageScrollLocked,delete manager.selectorScrollLock,window.scrollTo({top:lock.scrollY,left:0,behavior:"auto"})}async function openSelector(manager,slotIndex,trigger){const dialog=manager.querySelector("[data-vl-product-compare-dialog]");if(!dialog)return;manager.selectorTrigger=trigger,manager.selectorSlotIndex=slotIndex,dialog.setAttribute("aria-busy","true");const container=manager.querySelector("[data-vl-product-compare-candidates]");if(container&&!manager.candidates&&(container.innerHTML=`<div class="vl-product-compare__candidate-loading" role="status"> 163 <span class="vl-product-compare__candidate-spinner" aria-hidden="true"></span> 164 <span>${escapeHtml(manager.labels?.loading||"Loading ebikes...")}</span> 165 </div>`),window.matchMedia("(min-width: 1080px)").matches){const rect=trigger.getBoundingClientRect(),dialogWidth=704,dialogHeight=616,viewportGap=16,left=Math.max(viewportGap,Math.min(rect.left,window.innerWidth-dialogWidth-viewportGap)),top=Math.max(viewportGap,Math.min(rect.bottom+8,window.innerHeight-dialogHeight-viewportGap));dialog.style.setProperty("--vl-compare-dialog-left",`${left}px`),dialog.style.setProperty("--vl-compare-dialog-top",`${top}px`)}else dialog.style.removeProperty("--vl-compare-dialog-left"),dialog.style.removeProperty("--vl-compare-dialog-top");dialog.open||dialog.showModal(),lockSelectorPageScroll(manager,dialog);try{const candidates=await manager.getCandidates();if(!dialog.open||manager.selectorSlotIndex!==slotIndex)return;renderCandidates(manager,candidates,slotIndex),dialog.querySelector("button:not([disabled])")?.focus()}catch(error){dialog.open&&dialog.close(),manager.emitError("candidate-load-failed",error)}finally{dialog.removeAttribute("aria-busy")}}function mount(manager){if(manager.dataset.vlCompareViewMounted==="true")return;manager.dataset.vlCompareViewMounted="true";const status=manager.querySelector("[data-vl-product-compare-status]"),content=manager.querySelector("[data-vl-product-compare-content]"),error=manager.querySelector("[data-vl-product-compare-error]"),live=manager.querySelector("[data-vl-product-compare-live]"),dialog=manager.querySelector("[data-vl-product-compare-dialog]");manager.addEventListener("vl:product-compare-change",event=>{if(event.detail.source==="variant-option"&&event.detail.productId){const update=updateVariantProduct(manager,event.detail.products||[],event.detail.productId,event.detail.optionField);if(update.updated){update.affirmChanged&&refreshAffirm(),status&&(status.hidden=!0),error&&(error.hidden=!0),content&&(content.hidden=!1);return}}renderProducts(manager,event.detail.products||[]),renderSpecs(manager,event.detail.products||[]),applyDifferenceFilter(manager),observeSpecGroups(manager),syncScrollAreas(manager),refreshAffirm(),status&&(status.hidden=!0),error&&(error.hidden=!0),content&&(content.hidden=!1),live&&(live.textContent=String(manager.labels?.productsReady||"{count} products ready for comparison.").replace("{count}",event.detail.products.length)),manager.trackRenderedView(),event.detail.source==="replace-product"&&manager.trackA
165nalytics("compare_product_change",{previousProductHandle:event.detail.previousProductHandle,operatedProductHandle:event.detail.operatedProductHandle,operatedSlot:event.detail.operatedSlot,action:"replace"})}),manager.addEventListener("vl:product-compare-error",event=>{event.detail?.code!=="candidate-load-failed"&&(status&&(status.hidden=!0),content&&(content.hidden=!0),error&&(error.hidden=!1))}),manager.addEventListener("change",event=>{const input=event.target.closest("[data-vl-product-compare-option]");if(input){manager.selectVariantOption(input.dataset.productId,input.dataset.optionField,input.value);return}event.target.matches("[data-vl-product-compare-differences]")&&(applyDifferenceFilter(manager),manager.trackAnalytics("compare_difference_toggle",{action:event.target.checked?"enable":"disable"}),live&&(live.textContent=event.target.checked?manager.labels?.differencesShown||"Only differences are shown.":manager.labels?.allSpecificationsShown||"All specifications are shown."))}),manager.addEventListener("error",event=>{const image=event.target.closest("img");image&&(image.hidden=!0,image.closest(".vl-product-compare__image-frame")?.classList.add("has-image-error"))},!0),manager.addEventListener("click",async event=>{const productLink=event.target.closest(".vl-product-compare__explore, .vl-product-compare__sticky-explore, .vl-product-compare__image-link");if(productLink){const selector2=productLink.matches(".vl-product-compare__sticky-explore")?".vl-product-compare__sticky-explore":".vl-product-compare__explore",productElement=productLink.closest(".vl-product-compare__product"),operatedSlot=productElement?Array.from(productElement.parentElement.children).indexOf(productElement)+1:Array.from(manager.querySelectorAll(selector2)).indexOf(productLink)+1,product=manager.products[operatedSlot-1];product&&manager.trackAnalytics("compare_product_click",{operatedProductHandle:product.handle,operatedSlot,action:productLink.matches(".vl-product-compare__image-link")?"image":"explore"})}const selector=event.target.closest("[data-vl-product-compare-selector]");if(selector){await openSelector(manager,Number(selector.dataset.slotIndex),selector);return}const candidate=event.target.closest("[data-vl-product-compare-candidate]");if(candidate){if(dialog?.hasAttribute("aria-busy"))return;dialog?.setAttribute("aria-busy","true"),candidate.classList.add("is-loading"),candidate.setAttribute("aria-disabled","true"),await manager.replaceProduct(Number(candidate.dataset.slotIndex),candidate.dataset.handle)?dialog?.close():(dialog?.removeAttribute("aria-busy"),candidate.classList.remove("is-loading"),candidate.removeAttribute("aria-disabled"));return}event.target.closest("[data-vl-product-compare-dialog-close]")&&dialog?.close(),event.target.closest("[data-vl-product-compare-retry]")&&manager.initialize();const navLink=event.target.closest("[data-vl-product-compare-nav]");navLink&&(event.preventDefault(),scrollToSpecGroup(manager,navLink.dataset.groupKey))}),dialog?.addEventListener("close",()=>{unlockSelectorPageScroll(manager,dialog),dialog.style.removeProperty("--vl-compare-dialog-left"),dialog.style.removeProperty("--vl-compare-dialog-top"),manager.selectorTrigger?.isConnected&&manager.selectorTrigger.focus()}),dialog?.addEventListener("click",event=>{event.target===dialog&&dialog.close()}),Array.isArray(manager.products)&&manager.products.length&&(renderProducts(manager,manager.products),renderSpecs(manager,manager.products),applyDifferenceFilter(manager),observeSpecGroups(manager),syncScrollAreas(manager),refreshAffirm(),status&&(status.hidden=!0),error&&(error.hidden=!0),content&&(content.hidden=!1),manager.trackRenderedView())}function scan(root=document){root.querySelectorAll?.(MANAGER_SELECTOR).forEach(mount)}scan(),new MutationObserver(mutations=>{mutations.forEach(mutation=>mutation.addedNodes.forEach(node=>{node.nodeType===Node.ELEMENT_NODE&&(node.matches?.(MANAGER_SELECTOR)&&mount(node),scan(node))}))}).observe(document.documentElement,{childList:!0,subtree:!0})})(); 166//# sourceMappingURL=/cdn/shop/t/644/assets/vl-product-compare-view.js.map?v=111758915719549997561789470656
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.