{
  "version": 3,
  "sources": ["/cdn/shop/t/20/assets/product.js?mdsv=20260719h"],
  "sourcesContent": ["/*\n  \u00A9 2024 KondaSoft\n  https://www.kondasoft.com\n*/\n\n/*\n  \u00AB Achetez-le maintenant \u00BB (bouton principal et barre sticky) : ajoute le\n  contenu du formulaire au panier (les propri\u00E9t\u00E9s du form, dont le contenu\n  des bundles, sont conserv\u00E9es) puis redirige vers la page panier. Plus de\n  modale \u00AB Acc\u00E8s \u00E0 votre rue \u00BB sur ce flux : le service v\u00E9hicule adapt\u00E9 se\n  choisit via la case d\u00E9di\u00E9e de la page panier. Le bouton reste en\n  \u00AB loading \u00BB pendant la navigation ; au retour bfcache, le pageshow de\n  delivery-access-modal.js retire ce spinner.\n*/\nconst buyNowToCart = async (formData, button) => {\n  if (button.classList.contains('loading')) return\n  button.classList.add('loading')\n\n  const routes = (window.Shopify && window.Shopify.routes) || {}\n\n  try {\n    const response = await fetch(`${routes.cart_add_url || '/cart/add'}.js`, {\n      method: 'POST',\n      body: formData\n    })\n    if (!response.ok) throw new Error(`HTTP ${response.status}`)\n    window.location.href = routes.cart_url || '/cart'\n  } catch (error) {\n    console.error('MDS achat direct :', error)\n    button.classList.remove('loading')\n  }\n}\n\nclass ProductForm extends HTMLElement {\n  constructor () {\n    super()\n\n    this.form = this.querySelector('form')\n    this.productOptions = this.form.querySelectorAll('.product-options [name*=\"option\"]')\n    this.atcBtn = this.form.querySelector('.btn-atc')\n    this.buyBtn = this.form.querySelector('.btn-buy')\n\n    this.form.addEventListener('submit', event => this.onSubmit(event))\n\n    this.productOptions.forEach(elem =>\n      elem.addEventListener('change', event => this.onChangeProductOption(event)))\n\n    this.buyBtn?.addEventListener('click', event => this.onClickBuyBtn(event))\n\n    const initialVariant = this.getSelectedVariant()\n    this.adjustPricing(initialVariant)\n    this.adjustButtons(initialVariant)\n  }\n\n  getSelectedVariant () {\n    const variantId = Number(this.form.querySelector('[name=\"id\"]')?.value)\n    if (!variantId || !this.form.dataset.variants) return null\n\n    try {\n      const variants = JSON.parse(this.form.dataset.variants)\n      return variants.find(v => v.id === variantId) || null\n    } catch (e) {\n      console.error(e)\n      return null\n    }\n  }\n\n  async onChangeProductOption (event) {\n    event.preventDefault()\n\n    const selectedOptions = []\n\n    this.productOptions.forEach(elem => {\n      if (elem.type === 'radio' && elem.checked) {\n        selectedOptions.push(elem.value)\n      } else if (elem.type === 'select-one') {\n        selectedOptions.push(elem.value)\n      }\n    })\n\n    // console.log(selectedOptions)\n\n    const variants = JSON.parse(this.form.dataset.variants || '[]')\n    const selectedVariant = variants.find(variant =>\n      JSON.stringify(variant.options) === JSON.stringify(selectedOptions)\n    ) || null\n\n    // console.log(selectedVariant)\n\n    this.adjustPricing(selectedVariant)\n    this.adjustButtons(selectedVariant) \n\n    if (!selectedVariant) return\n\n    const idInput = this.querySelector('[name=\"id\"]')\n    if (idInput) idInput.value = selectedVariant.id\n\n    const url = new URL(window.location.href)\n    url.searchParams.set('variant', String(selectedVariant.id))\n    window.history.replaceState({}, '', url)\n\n    window.dispatchEvent(new CustomEvent('kt.product.variant.change', {\n      detail: selectedVariant\n    }))\n  }\n\n  adjustPricing (selectedVariant) {\n    if (!selectedVariant) return\n\n    const comparePrice = this.form.querySelector('.product-price-compare')\n    const finalPrice = this.form.querySelector('.product-price-final')\n    const saleBadges = this.closest('.product-main')?.querySelectorAll(\n      '.product-price .product-sale-badge, .product-media-gallery .product-sale-badge'\n    ) || []\n    const soldOutBadge = this.form.querySelector('.product-sold-out-badge')\n\n    if (!comparePrice || !finalPrice) return\n\n    if (selectedVariant.compare_at_price > selectedVariant.price) {\n      comparePrice.textContent = window.Shopify.formatMoney(selectedVariant.compare_at_price)\n      comparePrice.removeAttribute('hidden')\n      finalPrice.innerHTML = `<span class=\"visually-hidden\">${window.theme.locales.product.sale_price}</span>${window.Shopify.formatMoney(selectedVariant.price)} <small class=\"product-price-ttc\">TTC</small>`\n      finalPrice.classList.add('product-price-final-sale')\n      saleBadges.forEach(badge => badge.removeAttribute('hidden'))\n      if (saleBadges[0]?.dataset.discountType === 'percentage') {\n        const savings = 100 - (Math.round(selectedVariant.price / selectedVariant.compare_at_price * 100)) + '%'\n        saleBadges.forEach(badge => { badge.textContent = `${window.theme.locales.product.save} ${savings}` })\n      } else {\n        const savings = window.Shopify.formatMoney(selectedVariant.compare_at_price - selectedVariant.price)\n        saleBadges.forEach(badge => { badge.textContent = `${window.theme.locales.product.save} ${savings}` })\n      }\n    } else {\n      comparePrice.textContent = ''\n      comparePrice.setAttribute('hidden', 'hidden')\n      finalPrice.innerHTML = `${window.Shopify.formatMoney(selectedVariant.price)} <small class=\"product-price-ttc\">TTC</small>`\n      finalPrice.classList.remove('product-price-final-sale')\n      saleBadges.forEach(badge => {\n        badge.textContent = ''\n        badge.setAttribute('hidden', 'hidden')\n      })\n    }\n\n    // Badge remise \u00AB carte \u00BB de la galerie (fiche 1a, product-card-sale-flag) :\n    // pastille \u00AB -X % \u00BB (product-card-sale-flag--percent), m\u00EAme arrondi que le\n    // Liquid (round), \u00E0 jour au changement de variante.\n    const galleryFlag = this.closest('.product-main')?.querySelector('.product-media-gallery .product-card-sale-flag')\n    if (galleryFlag) {\n      if (selectedVariant.compare_at_price > selectedVariant.price) {\n        const galleryPct = Math.round((selectedVariant.compare_at_price - selectedVariant.price) * 100 / selectedVariant.compare_at_price)\n        galleryFlag.textContent = '-' + galleryPct + '\u202F%'\n        galleryFlag.removeAttribute('hidden')\n      } else {\n        galleryFlag.textContent = ''\n        galleryFlag.setAttribute('hidden', 'hidden')\n      }\n    }\n\n    if (soldOutBadge) {\n      if (selectedVariant.available) {\n        soldOutBadge.setAttribute('hidden', 'hidden')\n      } else {\n        soldOutBadge.removeAttribute('hidden')\n      }\n    }\n  }\n\n  adjustButtons (selectedVariant) {\n    const qtyWrapper = this.form.querySelector('.qty-input-wrapper')\n    const dynamicButtons = this.form.querySelector('.product-dynamic-buttons')\n\n    if (selectedVariant) {\n      if (selectedVariant.available) {\n        this.atcBtn?.removeAttribute('disabled')\n        qtyWrapper?.removeAttribute('hidden')\n        dynamicButtons?.removeAttribute('hidden')\n\n        this.buyBtn?.removeAttribute('disabled')\n\n        if (this.atcBtn) {\n          this.atcBtn.innerHTML = window.theme.locales.product.add_to_cart\n        }\n      } else {\n        this.atcBtn?.setAttribute('disabled', 'disabled')\n        qtyWrapper?.setAttribute('hidden', 'hidden')\n        dynamicButtons?.setAttribute('hidden', 'hidden')\n\n        this.buyBtn?.setAttribute('disabled', 'disabled')\n\n        if (this.atcBtn) {\n          this.atcBtn.innerHTML = window.theme.locales.product.sold_out\n        }\n      }\n    } else {\n      this.atcBtn?.setAttribute('disabled', 'disabled')\n      qtyWrapper?.setAttribute('hidden', 'hidden')\n      dynamicButtons?.setAttribute('hidden', 'hidden')\n\n      this.buyBtn?.setAttribute('disabled', 'disabled')\n\n      if (this.atcBtn) {\n        this.atcBtn.innerHTML = window.theme.locales.product.unavailable\n      }\n    }\n  }\n\n  async onSubmit (event) {\n    event.preventDefault()\n\n    if (!this.atcBtn) return\n\n    const selectedVariant = this.getSelectedVariant()\n    if (!selectedVariant || !selectedVariant.available || this.atcBtn?.disabled) {\n      this.adjustButtons(selectedVariant)\n      return\n    }\n\n    this.atcBtn.classList.add('loading')\n    this.atcBtn.disabled = true\n    this.atcBtn.setAttribute('aria-busy', 'true')\n\n    const formData = new FormData(this.form)\n\n    try {\n      await document.querySelector('cart-container').add(formData)\n    } finally {\n      this.atcBtn.classList.remove('loading')\n      this.atcBtn.disabled = false\n      this.atcBtn.setAttribute('aria-busy', 'false')\n      this.adjustButtons(this.getSelectedVariant())\n    }\n\n  }\n\n  onClickBuyBtn () {\n    const selectedVariant = this.getSelectedVariant()\n    if (!selectedVariant || !selectedVariant.available || this.buyBtn?.disabled) return\n\n    buyNowToCart(new FormData(this.form), this.buyBtn)\n  }\n}\ncustomElements.define('product-form', ProductForm)\n\nclass ProductMediaGallery extends HTMLElement {\n  constructor () {\n    super()\n\n    const initialSlide = Number(this.dataset.initialSlide)\n    this.mainWrapper = this.querySelector('.swiper-main-wrapper')\n\n    /** @type {Swiper} */\n    this.thumbs = new window.Swiper(this.querySelector('.swiper-thumbs'), this.thumbsOptions())\n\n    /** @type {Swiper} */\n    this.main = new window.Swiper(this.querySelector('.swiper-main'), this.mainOptions())\n\n    this.main.slideTo(initialSlide)\n\n    this.initThumbsNav()\n    this.initMediaPlaybackState()\n    this.setStickyPosition()\n    this.listenVariantChange()\n  }\n\n  thumbsOptions () {\n    /** @type {SwiperOptions} */\n    const options = {\n      slidesPerView: Number(this.dataset.thumbsPerView),\n      spaceBetween: 10,\n      watchOverflow: true\n    }\n    // Fiche 1a (.pdp) : largeur de vignette port\u00E9e par le CSS (76px) et\n    // conteneur ajust\u00E9 au contenu \u2014 les fl\u00E8ches restent coll\u00E9es aux\n    // vignettes. Les kits gardent le d\u00E9coupage num\u00E9rique de leur colonne.\n    if (this.closest('.pdp')) options.slidesPerView = 'auto'\n    return options\n  }\n\n  // Fl\u00E8ches des vignettes (format page panier) : elles changent l'image\n  // PRINCIPALE (pr\u00E9c\u00E9dente/suivante) \u2014 les vignettes li\u00E9es suivent toutes\n  // seules. Le carrousel principal a rewind: true, donc les fl\u00E8ches bouclent\n  // et restent actives ; visibles d\u00E8s que le produit a au moins 2 m\u00E9dias\n  // (verrou rendu c\u00F4t\u00E9 Liquid sinon).\n  initThumbsNav () {\n    if (!this.main) return\n\n    const prevEl = this.querySelector('.pdp-thumbs-nav--prev')\n    const nextEl = this.querySelector('.pdp-thumbs-nav--next')\n\n    // La bande de vignettes \u00AB tourne \u00BB avec l'image active : l'active reste\n    // en t\u00EAte de fen\u00EAtre et les suivantes d\u00E9filent d'un cran \u00E0 chaque\n    // navigation (Swiper borne la translation en fin de bande). S'applique\n    // quelle que soit la navigation (fl\u00E8ches, glissement, puces).\n    const syncThumbs = () => {\n      if (this.thumbs) this.thumbs.slideTo(this.main.activeIndex)\n    }\n\n    // Fl\u00E8che gauche interdite sur la premi\u00E8re image (pas de rebouclage\n    // arri\u00E8re) ; la droite reste active et reboucle vers la premi\u00E8re.\n    const syncPrevState = () => {\n      if (!prevEl) return\n      const atStart = this.main.activeIndex === 0\n      prevEl.disabled = atStart\n      prevEl.classList.toggle('swiper-button-disabled', atStart)\n    }\n\n    this.main.on('slideChange', () => {\n      syncThumbs()\n      syncPrevState()\n    })\n    syncThumbs()\n    syncPrevState()\n\n    if (!prevEl || !nextEl) return\n    prevEl.addEventListener('click', () => {\n      if (!prevEl.disabled) this.main.slidePrev()\n    })\n    nextEl.addEventListener('click', () => this.main.slideNext())\n  }\n\n  mainOptions () {\n    /** @type {SwiperOptions} */\n    const options = {\n      speed: Number(this.dataset.speed),\n      rewind: true,\n      pagination: {\n        type: 'bullets',\n        el: '.swiper-pagination',\n        // Mobile (maquette \u00AB Page Produit Mobile \u00BB) : toutes les puces visibles,\n        // styl\u00E9es en pilules \u2014 les transformations dynamicBullets les fausseraient.\n        dynamicBullets: window.matchMedia('(min-width: 768px)').matches,\n        dynamicMainBullets: 2,\n        renderFraction: function (currentClass, totalClass) {\n          return `<span class=\"${currentClass}\"></span>/<span class=\"${totalClass}\"></span>`\n        }\n      },\n      navigation: {\n        nextEl: this.querySelector('.swiper-button-next'),\n        prevEl: this.querySelector('.swiper-button-prev')\n      },\n      thumbs: {\n        swiper: this.thumbs,\n        autoScrollOffset: 1\n      }\n    }\n    return options\n  }\n\n  setStickyPosition () {\n    if (this.closest('.product-main') && window.matchMedia('(min-width: 1200px)').matches) {\n      const headerGroup = document.querySelector('#header-group.sticky-top') || document.querySelector('#header-group')\n\n      const setTopOffset = () => {\n        const headerHeight = headerGroup?.getBoundingClientRect().height || 0\n        const headerPosition = headerGroup ? window.getComputedStyle(headerGroup).position : ''\n        const topOffset = headerPosition === 'fixed' ? headerHeight : 0\n        this.style.setProperty('--product-media-sticky-top', `${Math.round(topOffset)}px`)\n      }\n\n      setTopOffset()\n\n      const onResize = () => setTopOffset()\n      window.addEventListener('resize', onResize)\n\n      if ('ResizeObserver' in window && headerGroup) {\n        const ro = new ResizeObserver(() => setTopOffset())\n        ro.observe(headerGroup)\n      }\n    }\n  }\n\n  initMediaPlaybackState () {\n    if (!this.mainWrapper || !this.main) return\n\n    const videos = this.querySelectorAll('.swiper-main video')\n\n    const syncMediaPlaybackState = () => {\n      const activeSlide = this.querySelector('.swiper-main .swiper-slide-active')\n\n      if (!activeSlide) {\n        this.setMediaPlaybackState(false)\n        return\n      }\n\n      if (activeSlide.dataset.mediaType === 'external_video') {\n        this.setMediaPlaybackState(true)\n        return\n      }\n\n      const activeVideo = activeSlide.querySelector('video')\n      const isPlaying = Boolean(activeVideo && !activeVideo.paused && !activeVideo.ended)\n      this.setMediaPlaybackState(isPlaying)\n    }\n\n    videos.forEach(video => {\n      video.addEventListener('play', syncMediaPlaybackState)\n      video.addEventListener('pause', syncMediaPlaybackState)\n      video.addEventListener('ended', syncMediaPlaybackState)\n    })\n\n    this.main.on('slideChangeTransitionStart', () => {\n      this.setMediaPlaybackState(false)\n    })\n\n    this.main.on('slideChangeTransitionEnd', syncMediaPlaybackState)\n    syncMediaPlaybackState()\n  }\n\n  setMediaPlaybackState (isPlaying) {\n    this.mainWrapper.classList.toggle('is-media-playing', isPlaying)\n  }\n\n  listenVariantChange () {\n    window.addEventListener('kt.product.variant.change', (event) => {\n      const selectedVariant = event.detail\n\n      if (selectedVariant.featured_media) {\n        this.main.slideTo(selectedVariant.featured_media.position - 1)\n        this.setMediaPlaybackState(false)\n      }\n    }, false)\n  }\n}\ncustomElements.define('product-media-gallery', ProductMediaGallery)\n\n// Shopify Subscriptions app\nconst adjustShopifySubscriptionsStyling = () => {\n  document.querySelectorAll('.shopify_subscriptions_app_block [type=\"radio\"]').forEach(radio => {\n    radio.classList.add('form-check-input')\n  })\n}\nadjustShopifySubscriptionsStyling()\nwindow.addEventListener('kt.product.quick_view.modal_shown', adjustShopifySubscriptionsStyling)\n\n/*\n  Fiche produit \u2014 maquette \u00AB Fiche 1a \u00BB (2026-07-17)\n  - Barre d'achat sticky bas de page (miroir du formulaire principal :\n    l'ajout passe par ProductForm.onSubmit \u2192 cart-container.add \u2192 kt.cart.added,\n    donc le popup \u00AB Ajout\u00E9 au panier \u00BB continue de fonctionner).\n  - Bouton \u00AB Copier le lien \u00BB des boutons de partage.\n*/\nconst initPdpStickyBar = () => {\n  const bar = document.querySelector('[data-pdp-sticky-bar]')\n  const productForm = document.querySelector('.product-main.pdp product-form form')\n  if (!bar || !productForm) return\n\n  const mainQtyInput = productForm.querySelector('input[name=\"quantity\"]')\n  const mainAtcBtn = productForm.querySelector('.btn-atc')\n  const barQtyInput = bar.querySelector('[data-sticky-qty]')\n  const barAtcBtn = bar.querySelector('[data-sticky-atc]')\n  const barBuyBtn = bar.querySelector('[data-sticky-buy]')\n  const barFinal = bar.querySelector('[data-sticky-price]')\n  const barCompare = bar.querySelector('[data-sticky-compare]')\n  const barBadge = bar.querySelector('[data-sticky-badge]')\n\n  // --- Synchronisation de la quantit\u00E9 (bidirectionnelle) ---\n  if (barQtyInput && mainQtyInput) {\n    barQtyInput.min = mainQtyInput.min || '1'\n    barQtyInput.value = mainQtyInput.value || '1'\n\n    const syncToMain = (evtType) => {\n      if (mainQtyInput.value === barQtyInput.value) return\n      mainQtyInput.value = barQtyInput.value\n      mainQtyInput.dispatchEvent(new Event(evtType || 'change', { bubbles: true }))\n    }\n    // Le \u00AB - \u00BB du stepper principal est rendu `disabled` et n'est r\u00E9activ\u00E9 que\n    // par le onclick inline du \u00AB + \u00BB voisin : sans cette resynchronisation, une\n    // quantit\u00E9 mont\u00E9e depuis la barre sticky laissait le \u00AB - \u00BB gris\u00E9 et\n    // l'acheteur ne pouvait plus redescendre la quantit\u00E9 depuis la buy-box.\n    const mainMinusBtn = productForm.querySelector('.qty-input-wrapper .btn-qty-minus')\n\n    const syncFromMain = () => {\n      if (barQtyInput.value !== mainQtyInput.value) barQtyInput.value = mainQtyInput.value\n      if (barQtyInput.min !== mainQtyInput.min && mainQtyInput.min) barQtyInput.min = mainQtyInput.min\n      if (mainMinusBtn) {\n        const min = Number(mainQtyInput.min || 1)\n        mainMinusBtn.disabled = Number(mainQtyInput.value || min) <= min\n      }\n    }\n\n    barQtyInput.addEventListener('input', () => syncToMain('input'))\n    barQtyInput.addEventListener('change', () => {\n      const min = Number(barQtyInput.min || 1)\n      if (Number(barQtyInput.value) < min || !barQtyInput.value) barQtyInput.value = min\n      syncToMain('change')\n    })\n    mainQtyInput.addEventListener('input', syncFromMain)\n    mainQtyInput.addEventListener('change', syncFromMain)\n\n    // Les boutons +/- du stepper principal mutent l'input via onclick inline\n    // SANS \u00E9mettre d'\u00E9v\u00E9nement : on resynchronise apr\u00E8s leur clic (le handler\n    // inline s'ex\u00E9cute avant ce listener d\u00E9l\u00E9gu\u00E9).\n    productForm.addEventListener('click', (event) => {\n      if (event.target.closest('.qty-input-wrapper .btn')) syncFromMain()\n    })\n\n    bar.querySelector('[data-sticky-qty-minus]')?.addEventListener('click', () => {\n      syncFromMain()\n      const min = Number(barQtyInput.min || 1)\n      barQtyInput.value = Math.max(min, Number(barQtyInput.value || min) - 1)\n      syncToMain('change')\n    })\n    bar.querySelector('[data-sticky-qty-plus]')?.addEventListener('click', () => {\n      syncFromMain()\n      barQtyInput.value = Number(barQtyInput.value || 0) + 1\n      syncToMain('change')\n    })\n  }\n\n  // --- Actions ---\n  barAtcBtn?.addEventListener('click', () => {\n    if (barAtcBtn.disabled) return\n    if (typeof productForm.requestSubmit === 'function') {\n      productForm.requestSubmit()\n    } else {\n      productForm.dispatchEvent(new Event('submit', { bubbles: true, cancelable: true }))\n    }\n  })\n\n  barBuyBtn?.addEventListener('click', () => {\n    if (barBuyBtn.disabled) return\n    const variantId = productForm.querySelector('[name=\"id\"]')?.value\n    if (!variantId) return\n    const qty = Math.max(1, Number(mainQtyInput?.value || barQtyInput?.value) || 1)\n\n    // M\u00EAme achat direct que le bouton principal (product-form) : la quantit\u00E9\n    // est r\u00E9impos\u00E9e au cas o\u00F9 la barre et le form seraient d\u00E9synchronis\u00E9s.\n    const formData = new FormData(productForm)\n    formData.set('id', variantId)\n    formData.set('quantity', String(qty))\n    buyNowToCart(formData, barBuyBtn)\n  })\n\n  // --- Mise \u00E0 jour au changement de variante ---\n  window.addEventListener('kt.product.variant.change', (event) => {\n    const variant = event.detail\n    if (!variant) return\n\n    if (barFinal) barFinal.textContent = window.Shopify.formatMoney(variant.price)\n\n    const onSale = variant.compare_at_price > variant.price\n    if (barCompare) {\n      if (onSale) {\n        barCompare.textContent = window.Shopify.formatMoney(variant.compare_at_price)\n        barCompare.removeAttribute('hidden')\n      } else {\n        barCompare.textContent = ''\n        barCompare.setAttribute('hidden', 'hidden')\n      }\n    }\n    if (barBadge) {\n      if (onSale) {\n        // M\u00EAme arithm\u00E9tique que le Liquid (division enti\u00E8re) pour que le badge\n        // ne change pas d'un point au premier changement de variante.\n        const pct = Math.floor((variant.compare_at_price - variant.price) * 100 / variant.compare_at_price)\n        barBadge.textContent = `\u2013${pct}\u00A0%`\n        barBadge.removeAttribute('hidden')\n      } else {\n        barBadge.textContent = ''\n        barBadge.setAttribute('hidden', 'hidden')\n      }\n    }\n\n    const disable = !variant.available\n    if (barAtcBtn) {\n      barAtcBtn.disabled = disable\n      barAtcBtn.textContent = disable\n        ? window.theme.locales.product.sold_out\n        : window.theme.locales.product.add_to_cart\n    }\n    if (barBuyBtn) barBuyBtn.disabled = disable\n  })\n\n  // --- Apparition quand le bloc d'achat principal sort de l'\u00E9cran ---\n  let barVisible = false\n  const toggleBar = (visible) => {\n    if (visible === barVisible) return\n    barVisible = visible\n    bar.classList.toggle('is-visible', visible)\n    bar.setAttribute('aria-hidden', visible ? 'false' : 'true')\n  }\n\n  const watchTarget = mainAtcBtn?.closest('.product-block-atc') || mainAtcBtn || productForm\n  if ('IntersectionObserver' in window && watchTarget) {\n    const observer = new IntersectionObserver((entries) => {\n      entries.forEach(entry => {\n        const scrolledPast = !entry.isIntersecting && entry.boundingClientRect.top < 0\n        toggleBar(scrolledPast)\n      })\n    }, { threshold: 0 })\n    observer.observe(watchTarget)\n  } else {\n    window.addEventListener('scroll', () => {\n      toggleBar(window.scrollY > 800)\n    }, { passive: true })\n  }\n\n  // --- \u00C9pinglage au-dessus du footer ---\n  // La barre est d\u00E9plac\u00E9e dans le flux du document, juste avant #footer-group,\n  // et passe en position: sticky (classe --docked) : le navigateur la colle en\n  // bas de l'\u00E9cran pendant la lecture et, en fin de page, elle reprend sa place\n  // STATIQUE au-dessus du footer et d\u00E9file avec lui \u2014 aucun suivi JS au scroll\n  // (l'ancien recalcul rAF de bottom tra\u00EEnait derri\u00E8re le rendu et faisait\n  // vibrer la barre une fois \u00E9pingl\u00E9e).\n  const footerGroup = document.getElementById('footer-group')\n  if (footerGroup && footerGroup.parentNode === document.body) {\n    document.body.insertBefore(bar, footerGroup)\n    bar.classList.add('pdp-sticky-bar--docked')\n  }\n\n  // Footer \u00E0 l'\u00E9cran : les widgets flottants (chat, R\u00E9compenses) s'estompent\n  // au lieu de rester par-dessus (voir .pdp-footer-in-view dans product-fiche.css).\n  const footer = document.getElementById('footer')\n  if (footer && 'IntersectionObserver' in window) {\n    const footerObserver = new IntersectionObserver((entries) => {\n      entries.forEach(entry => {\n        document.documentElement.classList.toggle('pdp-footer-in-view', entry.isIntersecting)\n      })\n    })\n    footerObserver.observe(footer)\n  }\n}\ninitPdpStickyBar()\n\n/*\n  \u00AB Avis clients \u00BB (avis \u00E9pingl\u00E9s Judge.me) \u2014 remplit le squelette rendu par\n  snippets/product-avis-epingles.liquid depuis window.jdgm.data.reviewWidget\n  (JSON judgeme.review_widget_data, inlin\u00E9 par le bloc Judge.me apr\u00E8s la FAQ).\n  La section reste masqu\u00E9e tant qu'aucun avis n'a \u00AB pinned \u00BB truthy.\n  Contenu UGC : uniquement createElement + textContent (jamais innerHTML).\n*/\n// Lightbox m\u00E9dia (avis \u00E9pingl\u00E9s, garantie, galerie) : modal Bootstrap unique \u2014\n// image, vid\u00E9o h\u00E9berg\u00E9e ou embed YouTube/Vimeo sur fond sombre, fermeture par\n// croix / clic hors m\u00E9dia / \u00C9chap. Un tableau optionnel active les fl\u00E8ches \u2039 \u203A\n// (et les touches \u2190/\u2192) et les vignettes. Pas de bouclage : la fl\u00E8che gauche\n// dispara\u00EEt sur le premier m\u00E9dia, la droite sur le dernier.\n// Entr\u00E9e : URL (image) ou objet {type: 'image'|'video'|'embed', src, thumb}.\nlet lightboxItems = []\nlet lightboxIndex = 0\n\nconst normalizeLightboxItem = (item) =>\n  typeof item === 'string' ? { type: 'image', src: item } : item\n\n// Pr\u00E9chargement des grandes images (1600 px) : sans lui, le t\u00E9l\u00E9chargement ne\n// part qu'au moment o\u00F9 l'image doit s'afficher \u2014 popup lent \u00E0 l'ouverture et\n// chaque fl\u00E8che \u2039 \u203A attend le r\u00E9seau. Le Set \u00E9vite de re-demander une URL\n// (retir\u00E9e en cas d'\u00E9chec pour qu'une nouvelle tentative reste possible).\n// \u00C9conomiseur de donn\u00E9es activ\u00E9 : aucun octet sp\u00E9culatif \u2014 seuls les\n// voisins imm\u00E9diats du m\u00E9dia zoom\u00E9 partent en avance.\nconst lightboxSaveData = Boolean(navigator.connection && navigator.connection.saveData)\nconst lightboxPreloaded = new Set()\nconst preloadLightboxImage = (src, priority) => {\n  if (!src || lightboxPreloaded.has(src)) return\n  lightboxPreloaded.add(src)\n  const img = new Image()\n  img.decoding = 'async'\n  if (priority) img.fetchPriority = priority\n  img.addEventListener('error', () => lightboxPreloaded.delete(src))\n  img.src = src\n}\n\n// Voisines de l'image affich\u00E9e : les fl\u00E8ches deviennent instantan\u00E9es\nconst preloadLightboxNeighbors = () => {\n  [lightboxIndex + 1, lightboxIndex - 1].forEach((index) => {\n    const item = lightboxItems[index]\n    if (item && item.type === 'image') preloadLightboxImage(item.src)\n  })\n}\n\n// Affichage d'une image : d\u00E9j\u00E0 en cache \u2192 telle quelle. Sinon l'aper\u00E7u 800 px\n// de la galerie (item.preview, d\u00E9j\u00E0 d\u00E9cod\u00E9 \u00E0 l'\u00E9cran) s'affiche imm\u00E9diatement\n// pendant que la 1600 px se t\u00E9l\u00E9charge, puis bascule sans \u00E0-coup ; sans\n// aper\u00E7u (photos d'avis, garantie), un anneau de chargement (--loading)\n// occupe l'attente. Le jeton annule la bascule si l'utilisateur a d\u00E9j\u00E0\n// navigu\u00E9 vers un autre m\u00E9dia.\n// L'aper\u00E7u inline est un recadrage carr\u00E9 alors que la 1600 px garde son\n// ratio naturel : item.ratio (aspect_ratio du m\u00E9dia) pr\u00E9-dimensionne l'img\n// \u00E0 la g\u00E9om\u00E9trie finale (object-fit: cover) pour que le cadre \u2014 et la croix,\n// les fl\u00E8ches, les vignettes qui s'y accrochent \u2014 ne saute pas \u00E0 la bascule.\nlet lightboxLoadToken = 0\nconst setLightboxImg = (modal, img, item) => {\n  const token = ++lightboxLoadToken\n\n  // Image d\u00E9j\u00E0 affich\u00E9e avec succ\u00E8s (r\u00E9ouverture, retour sur le m\u00EAme m\u00E9dia) :\n  // rien \u00E0 charger \u2014 et surtout pas d'anneau par-dessus une image correcte\n  if (img.getAttribute('src') === item.src && img.complete && img.naturalWidth > 0) {\n    modal.classList.remove('pdp-photo-lightbox--loading')\n    return\n  }\n\n  const full = new Image()\n  full.decoding = 'async'\n  full.src = item.src\n  lightboxPreloaded.add(item.src)\n\n  const applyFull = () => {\n    if (token !== lightboxLoadToken) return\n    modal.classList.remove('pdp-photo-lightbox--loading')\n    // Une <img> cass\u00E9e (\u00E9chec r\u00E9seau pass\u00E9) ne retente le chargement que si\n    // son src est r\u00E9-assign\u00E9 \u2014 ne pas sauter l'assignation dans ce cas\n    const broken = img.complete && img.naturalWidth === 0\n    if (broken || img.getAttribute('src') !== item.src) img.src = item.src\n    img.style.aspectRatio = ''\n    img.style.width = ''\n    img.style.objectFit = ''\n  }\n\n  if (full.complete) {\n    applyFull()\n    return\n  }\n\n  if (item.preview && img.getAttribute('src') !== item.src) {\n    modal.classList.remove('pdp-photo-lightbox--loading')\n    if (item.ratio) {\n      // M\u00EAme bo\u00EEte que la future 1600 px (born\u00E9e par max-width/max-height CSS)\n      img.style.aspectRatio = String(item.ratio)\n      img.style.width = '1600px'\n      img.style.objectFit = 'cover'\n    }\n    img.src = item.preview\n  } else {\n    modal.classList.add('pdp-photo-lightbox--loading')\n  }\n\n  full.addEventListener('load', applyFull)\n  full.addEventListener('error', () => {\n    if (token !== lightboxLoadToken) return\n    lightboxPreloaded.delete(item.src) // une nouvelle tentative restera possible\n    modal.classList.remove('pdp-photo-lightbox--loading')\n    // Aper\u00E7u affich\u00E9 : on le garde plut\u00F4t que d'afficher une image cass\u00E9e ;\n    // sans aper\u00E7u, comportement d'avant (l'ic\u00F4ne cass\u00E9e signale l'\u00E9chec)\n    if (!item.preview) img.src = item.src\n  })\n}\n\n// Navigation d'iframe par location.replace : changer iframe.src empile une\n// entr\u00E9e d'historique (le bouton retour rejouerait chaque vid\u00E9o affich\u00E9e).\nconst setLightboxFrameSrc = (iframe, url) => {\n  try {\n    iframe.contentWindow.location.replace(url)\n  } catch (err) {\n    iframe.src = url\n  }\n}\n\nconst showLightboxImage = (modal) => {\n  const item = lightboxItems[lightboxIndex]\n  const img = modal.querySelector('.pdp-photo-lightbox__img')\n  const video = modal.querySelector('.pdp-photo-lightbox__video')\n  const iframe = modal.querySelector('.pdp-photo-lightbox__iframe')\n\n  // Loupe : repartir cach\u00E9e \u00E0 chaque changement de m\u00E9dia \u2014 elle r\u00E9appara\u00EEtra\n  // au prochain mouvement de souris si le nouveau m\u00E9dia est une image pr\u00EAte\n  modal.querySelector('.pdp-photo-lightbox__lens').hidden = true\n\n  img.hidden = item.type !== 'image'\n  video.hidden = item.type !== 'video'\n  iframe.hidden = item.type !== 'embed'\n\n  if (item.type === 'image') {\n    setLightboxImg(modal, img, item)\n  } else {\n    lightboxLoadToken++ // annule une bascule d'image encore en vol\n    modal.classList.remove('pdp-photo-lightbox--loading')\n  }\n\n  if (item.type === 'video') {\n    if (video.getAttribute('src') !== item.src) video.src = item.src\n    // Lanc\u00E9e depuis un geste utilisateur ; si le navigateur refuse,\n    // les contr\u00F4les restent disponibles\n    video.play().catch(() => {})\n  } else if (!video.paused) {\n    video.pause()\n  }\n\n  if (item.type === 'embed') {\n    const joiner = item.src.includes('?') ? '&' : '?'\n    setLightboxFrameSrc(iframe, item.src + joiner + 'autoplay=1')\n    iframe.dataset.playing = '1'\n  } else if (iframe.dataset.playing) {\n    setLightboxFrameSrc(iframe, 'about:blank')\n    delete iframe.dataset.playing\n  }\n\n  modal.querySelector('.pdp-photo-lightbox__nav--prev').hidden = lightboxIndex === 0\n  modal.querySelector('.pdp-photo-lightbox__nav--next').hidden = lightboxIndex >= lightboxItems.length - 1\n  modal.querySelectorAll('.pdp-photo-lightbox__thumb').forEach((thumb, index) => {\n    thumb.classList.toggle('is-active', index === lightboxIndex)\n    if (index === lightboxIndex) thumb.scrollIntoView({ block: 'nearest', inline: 'nearest' })\n  })\n\n  preloadLightboxNeighbors()\n}\n\n// Vignette : m\u00EAme image en petite largeur quand l'URL CDN porte un param\u00E8tre\n// width ; sinon (photos d'avis Judge.me) l'URL d'origine sert telle quelle.\nconst lightboxThumbUrl = (url) => {\n  try {\n    const u = new URL(url, window.location.origin)\n    if (u.searchParams.has('width')) u.searchParams.set('width', '180')\n    return u.toString()\n  } catch (err) {\n    return url\n  }\n}\n\n// Rang\u00E9e de vignettes sous le m\u00E9dia, reconstruite \u00E0 chaque ouverture ; masqu\u00E9e\n// (et m\u00E9dia pleine hauteur) quand il n'y a qu'un seul m\u00E9dia. Les vignettes\n// vid\u00E9o portent une pastille \u25B6 (poster fourni par la galerie).\nconst buildLightboxThumbs = (modal) => {\n  const row = modal.querySelector('.pdp-photo-lightbox__thumbs')\n  const hasThumbs = lightboxItems.length > 1\n  row.hidden = !hasThumbs\n  modal.classList.toggle('pdp-photo-lightbox--thumbs', hasThumbs)\n  row.replaceChildren(...lightboxItems.map((item, index) => {\n    const btn = document.createElement('button')\n    btn.type = 'button'\n    btn.className = 'pdp-photo-lightbox__thumb'\n    btn.setAttribute('aria-label', item.type === 'image' ? `Afficher l'image ${index + 1}` : `Lire la vid\u00E9o ${index + 1}`)\n    const img = document.createElement('img')\n    img.src = item.thumb || (item.type === 'image' ? lightboxThumbUrl(item.src) : '')\n    img.alt = ''\n    img.loading = 'lazy'\n    img.decoding = 'async'\n    btn.appendChild(img)\n    if (item.type !== 'image') {\n      const icon = document.createElement('i')\n      icon.className = 'fa fa-play'\n      icon.setAttribute('aria-hidden', 'true')\n      btn.appendChild(icon)\n    }\n    btn.addEventListener('click', () => {\n      lightboxIndex = index\n      showLightboxImage(modal)\n    })\n    return btn\n  }))\n}\n\nconst stepLightbox = (modal, delta) => {\n  const target = lightboxIndex + delta\n  if (target < 0 || target >= lightboxItems.length) return\n  lightboxIndex = target\n  showLightboxImage(modal)\n}\n\nconst openPhotoLightbox = (url, urls) => {\n  let modal = document.getElementById('pdp-photo-lightbox')\n  if (!modal) {\n    modal = document.createElement('div')\n    modal.id = 'pdp-photo-lightbox'\n    modal.className = 'modal fade pdp-photo-lightbox'\n    modal.tabIndex = -1\n    modal.setAttribute('aria-label', 'Photo agrandie')\n\n    const dialog = document.createElement('div')\n    dialog.className = 'modal-dialog modal-dialog-centered modal-lg'\n    const content = document.createElement('div')\n    content.className = 'modal-content'\n\n    // Cadre \u00E0 la taille exacte de la photo : la croix et les fl\u00E8ches restent\n    // coll\u00E9es aux bords de l'image, quelle que soit sa largeur.\n    const frame = document.createElement('div')\n    frame.className = 'pdp-photo-lightbox__frame'\n\n    const img = document.createElement('img')\n    img.className = 'pdp-photo-lightbox__img'\n    img.alt = ''\n\n    const video = document.createElement('video')\n    video.className = 'pdp-photo-lightbox__video'\n    video.controls = true\n    video.playsInline = true\n    video.hidden = true\n\n    const iframe = document.createElement('iframe')\n    iframe.className = 'pdp-photo-lightbox__iframe'\n    iframe.title = 'Vid\u00E9o du produit'\n    iframe.allow = 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share'\n    iframe.allowFullscreen = true\n    iframe.hidden = true\n\n    // Loupe : rectangle qui suit le curseur au survol de la photo et montre\n    // la zone survol\u00E9e agrandie (fond = m\u00EAme image, repositionn\u00E9e \u00E0 chaque\n    // mouvement). D\u00E9coratif et transparent aux clics \u2014 rien pour un lecteur\n    // d'\u00E9cran ni au clavier.\n    const lens = document.createElement('div')\n    lens.className = 'pdp-photo-lightbox__lens'\n    lens.hidden = true\n    lens.setAttribute('aria-hidden', 'true')\n\n    const closeBtn = document.createElement('button')\n    closeBtn.type = 'button'\n    closeBtn.className = 'pdp-photo-lightbox__close'\n    closeBtn.setAttribute('data-bs-dismiss', 'modal')\n    closeBtn.setAttribute('aria-label', 'Fermer')\n    const closeIcon = document.createElement('i')\n    closeIcon.className = 'fa fa-times'\n    closeIcon.setAttribute('aria-hidden', 'true')\n    closeBtn.appendChild(closeIcon)\n\n    const navBtn = (label, iconClass, extraClass, delta) => {\n      const btn = document.createElement('button')\n      btn.type = 'button'\n      btn.className = 'pdp-photo-lightbox__nav ' + extraClass\n      btn.setAttribute('aria-label', label)\n      const icon = document.createElement('i')\n      icon.className = iconClass\n      icon.setAttribute('aria-hidden', 'true')\n      btn.appendChild(icon)\n      btn.addEventListener('click', () => stepLightbox(modal, delta))\n      return btn\n    }\n    const prevBtn = navBtn('Image pr\u00E9c\u00E9dente', 'fa fa-chevron-left', 'pdp-photo-lightbox__nav--prev', -1)\n    const nextBtn = navBtn('Image suivante', 'fa fa-chevron-right', 'pdp-photo-lightbox__nav--next', 1)\n\n    frame.append(img, video, iframe, lens, closeBtn, prevBtn, nextBtn)\n\n    // Souris uniquement (hover + pointer fine) : au tactile, pincer/\u00E9carter\n    // zoome d\u00E9j\u00E0 nativement. Inerte tant que la 1600 px n'est pas affich\u00E9e \u2014\n    // l'aper\u00E7u 800 px est un recadrage carr\u00E9 (object-fit: cover) dont la\n    // g\u00E9om\u00E9trie ne correspondrait pas au fond agrandi. Le grossissement\n    // ram\u00E8ne la photo \u00E0 sa r\u00E9solution d'origine (jamais moins de \u00D72).\n    const lensPointer = window.matchMedia('(hover: hover) and (pointer: fine)')\n    const moveLens = (event) => {\n      const item = lightboxItems[lightboxIndex]\n      const ready = lensPointer.matches && item && item.type === 'image' &&\n        img.getAttribute('src') === item.src && img.complete && img.naturalWidth > 0\n      if (!ready) {\n        lens.hidden = true\n        return\n      }\n      lens.hidden = false // avant les mesures : [hidden] \u2192 offsetWidth = 0\n      const lensW = lens.offsetWidth\n      const lensH = lens.offsetHeight\n      const rect = img.getBoundingClientRect()\n      // Photo \u00E0 peine plus grande que la loupe (petites photos d'avis) :\n      // le rectangle masquerait presque tout \u2014 pas de zoom utile\n      if (rect.width < lensW * 1.25 || rect.height < lensH * 1.25) {\n        lens.hidden = true\n        return\n      }\n      const frameRect = frame.getBoundingClientRect()\n      const factor = Math.max(2, img.naturalWidth / rect.width)\n      // Centre de la loupe : le curseur, born\u00E9 pour qu'elle reste enti\u00E8re\n      // sur la photo ; le fond montre la zone couverte par le rectangle\n      const cx = Math.min(Math.max(event.clientX - rect.left, lensW / 2), rect.width - lensW / 2)\n      const cy = Math.min(Math.max(event.clientY - rect.top, lensH / 2), rect.height - lensH / 2)\n      lens.style.left = (rect.left - frameRect.left + cx - lensW / 2) + 'px'\n      lens.style.top = (rect.top - frameRect.top + cy - lensH / 2) + 'px'\n      lens.style.backgroundImage = 'url(\"' + (img.currentSrc || item.src) + '\")'\n      lens.style.backgroundSize = (rect.width * factor) + 'px ' + (rect.height * factor) + 'px'\n      lens.style.backgroundPosition = (lensW / 2 - cx * factor) + 'px ' + (lensH / 2 - cy * factor) + 'px'\n    }\n    img.addEventListener('pointermove', moveLens)\n    img.addEventListener('pointerleave', () => { lens.hidden = true })\n\n    const thumbsRow = document.createElement('div')\n    thumbsRow.className = 'pdp-photo-lightbox__thumbs'\n\n    content.append(frame, thumbsRow)\n    dialog.appendChild(content)\n    modal.appendChild(dialog)\n    document.body.appendChild(modal)\n\n    modal.addEventListener('keydown', (event) => {\n      if (lightboxItems.length < 2) return\n      if (event.key === 'ArrowLeft') stepLightbox(modal, -1)\n      else if (event.key === 'ArrowRight') stepLightbox(modal, 1)\n    })\n\n    // Fermeture : couper la lecture en cours (vid\u00E9o h\u00E9berg\u00E9e ou embed)\n    modal.addEventListener('hide.bs.modal', () => {\n      if (!video.paused) video.pause()\n      if (iframe.dataset.playing) {\n        setLightboxFrameSrc(iframe, 'about:blank')\n        delete iframe.dataset.playing\n      }\n    })\n  }\n\n  const list = Array.isArray(urls) && urls.length ? urls : [url]\n  lightboxItems = list.map(normalizeLightboxItem)\n  const current = normalizeLightboxItem(url)\n  lightboxIndex = Math.max(0, lightboxItems.findIndex(item => item.src === current.src))\n  buildLightboxThumbs(modal)\n  showLightboxImage(modal)\n  window.bootstrap.Modal.getOrCreateInstance(modal).show()\n\n  // L'utilisateur feuillette : le reste de la s\u00E9rie part en priorit\u00E9 basse\n  // (l'image courante et ses voisines sont d\u00E9j\u00E0 demand\u00E9es en priorit\u00E9 normale),\n  // pour que les sauts par vignette soient instantan\u00E9s eux aussi. Annul\u00E9 si\n  // le popup est referm\u00E9 avant l'\u00E9ch\u00E9ance ; jamais en mode \u00E9conomie de donn\u00E9es.\n  if (!lightboxSaveData) {\n    const items = lightboxItems\n    const burstTimer = setTimeout(() => {\n      items.forEach((item) => {\n        if (item.type === 'image') preloadLightboxImage(item.src, 'low')\n      })\n    }, 400)\n    modal.addEventListener('hide.bs.modal', () => clearTimeout(burstTimer), { once: true })\n  }\n}\n\n// Chrome mobile de la galerie (fiche 1a) : bouton retour. Visiteur arriv\u00E9\n// de l'ext\u00E9rieur (Google, r\u00E9seaux, e-mail \u2014 referrer absent ou d'un autre\n// domaine) ou dans un onglet neuf : on reste dans la boutique en allant \u00E0\n// la collection du produit (data-pdp-back-fallback, pos\u00E9 par le Liquid).\n// Navigation interne : v\u00E9ritable retour arri\u00E8re.\ndocument.addEventListener('click', (event) => {\n  const backBtn = event.target instanceof Element ? event.target.closest('[data-pdp-back]') : null\n  if (!backBtn) return\n\n  const fallback = backBtn.getAttribute('data-pdp-back-fallback') || '/collections/all'\n\n  let referrerInterne = false\n  try {\n    referrerInterne = document.referrer !== '' &&\n      new URL(document.referrer).origin === window.location.origin\n  } catch (err) {\n    referrerInterne = false\n  }\n\n  if (referrerInterne && window.history.length > 1) {\n    window.history.back()\n  } else {\n    window.location.href = fallback\n  }\n})\n\n// Images de garantie (onglet Garantie) : m\u00EAme lightbox que les photos d'avis,\n// avec toutes les images de la rang\u00E9e pour d\u00E9filer aux fl\u00E8ches ; sans\n// Bootstrap, le lien ouvre l'image en nouvel onglet (comportement natif).\ndocument.addEventListener('click', (event) => {\n  const link = event.target instanceof Element ? event.target.closest('.pdp-garantie__photo') : null\n  if (!link || !window.bootstrap) return\n  event.preventDefault()\n  const row = link.closest('.pdp-garantie__images')\n  const urls = row ? [...row.querySelectorAll('.pdp-garantie__photo')].map(a => a.href) : [link.href]\n  openPhotoLightbox(link.href, urls)\n})\n\n// Galerie (fiche 1a) : clic sur un m\u00E9dia \u2192 m\u00EAme lightbox, avec tous les\n// m\u00E9dias de la galerie pour d\u00E9filer aux fl\u00E8ches \u2014 images zoom\u00E9es, vid\u00E9os\n// (h\u00E9berg\u00E9es ou YouTube/Vimeo) lues dans le popup (les m\u00E9dias inline sont\n// neutralis\u00E9s en CSS au profit du popup). Le clic qui suit un glissement est\n// aval\u00E9 par Swiper (preventClicks), donc pas de popup apr\u00E8s un swipe.\nconst LIGHTBOX_SLIDE_SELECTOR = '.swiper-main .swiper-slide[data-lightbox-url], .swiper-main .swiper-slide[data-lightbox-video], .swiper-main .swiper-slide[data-lightbox-embed]'\n\nconst galleryLightboxItem = (slide) => {\n  if (slide.dataset.lightboxVideo) return { type: 'video', src: slide.dataset.lightboxVideo, thumb: slide.dataset.lightboxPoster }\n  if (slide.dataset.lightboxEmbed) return { type: 'embed', src: slide.dataset.lightboxEmbed, thumb: slide.dataset.lightboxPoster }\n  // preview : l'image 800 px inline (d\u00E9j\u00E0 d\u00E9cod\u00E9e \u00E0 l'\u00E9cran) sert d'affichage\n  // imm\u00E9diat dans le popup pendant que la 1600 px arrive ; ratio : g\u00E9om\u00E9trie\n  // naturelle du m\u00E9dia pour pr\u00E9-dimensionner le cadre (l'aper\u00E7u est carr\u00E9)\n  return {\n    type: 'image',\n    src: slide.dataset.lightboxUrl,\n    preview: slide.querySelector('img')?.currentSrc || undefined,\n    ratio: parseFloat(slide.dataset.lightboxRatio) || undefined\n  }\n}\n\ndocument.addEventListener('click', (event) => {\n  const slide = event.target instanceof Element ? event.target.closest(LIGHTBOX_SLIDE_SELECTOR) : null\n  if (!slide || !window.bootstrap) return\n  const gallery = slide.closest('product-media-gallery')\n  const slides = gallery ? gallery.querySelectorAll(LIGHTBOX_SLIDE_SELECTOR) : [slide]\n  openPhotoLightbox(galleryLightboxItem(slide), [...slides].map(galleryLightboxItem))\n})\n\n// Pr\u00E9chauffage : la 1600 px de la slide visible part AVANT le clic de zoom \u2014\n// au premier survol (desktop) ou toucher (mobile) de la galerie, \u00E0 chaque\n// changement de slide (l'utilisateur feuillette : il zoomera probablement\n// celle qu'il regarde), et pour la slide initiale d\u00E8s que le navigateur est\n// au repos (priorit\u00E9 basse : ne concurrence pas le chargement de la page).\nconst warmGalleryLightbox = (event) => {\n  if (lightboxSaveData) return\n  const slide = event.target instanceof Element ? event.target.closest('.swiper-main .swiper-slide[data-lightbox-url]') : null\n  if (slide) preloadLightboxImage(slide.dataset.lightboxUrl)\n}\ndocument.addEventListener('pointerover', warmGalleryLightbox, { passive: true })\ndocument.addEventListener('touchstart', warmGalleryLightbox, { passive: true })\n\n// Re-c\u00E2bl\u00E9 sur shopify:section:load : l'\u00E9diteur de th\u00E8me re-rend la section\n// avec une galerie neuve (le garde-fou \u00E9vite les doubles \u00E9couteurs)\nconst wireGalleryLightboxPreload = () => {\n  document.querySelectorAll('product-media-gallery').forEach((gallery) => {\n    if (!gallery.main || gallery.dataset.lightboxPreloadWired) return\n    gallery.dataset.lightboxPreloadWired = 'true'\n    gallery.main.on('slideChange', () => {\n      if (lightboxSaveData) return\n      const active = gallery.main.slides[gallery.main.activeIndex]\n      if (active?.dataset.lightboxUrl) preloadLightboxImage(active.dataset.lightboxUrl, 'low')\n    })\n  })\n}\nwireGalleryLightboxPreload()\ndocument.addEventListener('shopify:section:load', wireGalleryLightboxPreload)\n\nconst warmInitialLightboxSlide = () => {\n  document.querySelectorAll('product-media-gallery .swiper-main .swiper-slide-active[data-lightbox-url]').forEach((slide) => {\n    preloadLightboxImage(slide.dataset.lightboxUrl, 'low')\n  })\n}\nif (!lightboxSaveData) {\n  if ('requestIdleCallback' in window) {\n    window.requestIdleCallback(warmInitialLightboxSlide, { timeout: 4000 })\n  } else {\n    setTimeout(warmInitialLightboxSlide, 2500)\n  }\n}\n\nconst initPdpPinnedReviews = () => {\n  const root = document.querySelector('[data-pinned-reviews]')\n  if (!root) return\n\n  const grid = root.querySelector('[data-pinned-grid]')\n  if (!grid || grid.childElementCount) return // d\u00E9j\u00E0 rempli (re-rendu de section)\n\n  const data = window.jdgm?.data?.reviewWidget?.[root.dataset.productId]\n  if (!data || !Array.isArray(data.reviews)) return\n\n  const pinned = data.reviews.filter(review => review && review.pinned)\n  if (!pinned.length) return\n\n  const el = (tag, className, text) => {\n    const node = document.createElement(tag)\n    if (className) node.className = className\n    if (text) node.textContent = text\n    return node\n  }\n\n  const starsEl = (rating, className) => {\n    const wrap = el('span', className)\n    const icons = el('span')\n    icons.setAttribute('aria-hidden', 'true')\n    for (let i = 1; i <= 5; i++) {\n      const icon = document.createElement('i')\n      icon.className = rating >= i ? 'fa fa-star' : (rating >= i - 0.5 ? 'fa fa-star-half-o' : 'fa fa-star-o')\n      icons.appendChild(icon)\n    }\n    wrap.appendChild(icons)\n    const srNote = (Math.round(rating * 10) / 10).toLocaleString('fr-FR')\n    wrap.appendChild(el('span', 'visually-hidden', `Note : ${srNote} sur 5`))\n    return wrap\n  }\n\n  const reviewText = (review) => {\n    if (review.body) return String(review.body)\n    if (review.body_html) {\n      // DOMParser : document inerte, aucun chargement de ressource ni handler.\n      // Texte extrait bloc par bloc pour ne pas souder les paragraphes.\n      const body = new DOMParser().parseFromString(review.body_html, 'text/html').body\n      const blocks = [...body.children].map(node => (node.textContent || '').trim()).filter(Boolean)\n      return blocks.length ? blocks.join('\\n\\n') : (body.textContent || '')\n    }\n    return ''\n  }\n\n  // Photos jointes \u00E0 l'avis. Cl\u00E9 V\u00C9RIFI\u00C9E sur le JSON live (2026-07-18) :\n  // \u00AB pictures_urls \u00BB = tableau de { original, small, compact, huge } (URLs\n  // review-images.judge.me directes, sans objet imbriqu\u00E9). \u00AB pictures \u00BB gard\u00E9\n  // en repli au cas o\u00F9 Judge.me change de forme. Seules les URLs http(s)\n  // sont retenues (UGC).\n  const reviewPictures = (review) => {\n    const list = Array.isArray(review.pictures_urls)\n      ? review.pictures_urls\n      : (Array.isArray(review.pictures) ? review.pictures : [])\n    const safeUrl = (u) => (typeof u === 'string' && /^https?:\\/\\//i.test(u) ? u : '')\n    return list\n      .filter(pic => pic && !pic.hidden)\n      .map(pic => {\n        if (typeof pic === 'string') return { thumb: safeUrl(pic), full: safeUrl(pic) }\n        const urls = pic.urls || pic\n        const thumb = safeUrl(urls.compact || urls.small || urls.original || urls.huge || pic.image_url || pic.url)\n        const full = safeUrl(urls.huge || urls.original) || thumb\n        return { thumb, full }\n      })\n      .filter(pic => pic.thumb)\n  }\n\n  const relativeDateFr = (iso) => {\n    const date = new Date(iso)\n    if (Number.isNaN(date.getTime())) return ''\n    const days = Math.floor((Date.now() - date.getTime()) / 86400000)\n    if (days <= 0) return \"aujourd'hui\"\n    if (days === 1) return 'hier'\n    if (days < 7) return `il y a ${days} jours`\n    if (days < 30) { const w = Math.floor(days / 7); return `il y a ${w} semaine${w > 1 ? 's' : ''}` }\n    if (days < 365) return `il y a ${Math.floor(days / 30)} mois`\n    const y = Math.floor(days / 365)\n    return `il y a ${y} an${y > 1 ? 's' : ''}`\n  }\n\n  // R\u00E9sum\u00E9 (note moyenne r\u00E9elle du produit) \u2014 cl\u00E9s v\u00E9rifi\u00E9es sur le JSON live\n  const avg = parseFloat(data.average_rating) || 0\n  if (avg > 0) {\n    const score = root.querySelector('[data-pinned-score]')\n    if (score) score.textContent = `${avg.toLocaleString('fr-FR', { minimumFractionDigits: 1, maximumFractionDigits: 1 })}/5`\n    const summaryStars = root.querySelector('[data-pinned-stars]')\n    if (summaryStars) summaryStars.replaceChildren(...starsEl(avg).childNodes)\n  }\n  const count = root.querySelector('[data-pinned-count]')\n  if (count && data.number_of_reviews) {\n    count.textContent = `${data.number_of_reviews} avis`\n  }\n\n  // Cartes (max 5 avis \u00E9pingl\u00E9s c\u00F4t\u00E9 Judge.me)\n  pinned.forEach(review => {\n    const card = el('article', 'pdp-pinned-reviews__card')\n    card.appendChild(starsEl(Number(review.rating) || 0, 'pdp-pinned-reviews__card-stars'))\n    if (review.title) card.appendChild(el('strong', 'pdp-pinned-reviews__card-title', review.title))\n    const text = reviewText(review).trim()\n    if (text) card.appendChild(el('p', 'pdp-pinned-reviews__card-body', text))\n\n    const pictures = reviewPictures(review)\n    if (pictures.length) {\n      const photos = el('div', 'pdp-pinned-reviews__card-photos')\n      pictures.forEach(pic => {\n        const link = document.createElement('a')\n        link.href = pic.full\n        link.target = '_blank'\n        link.rel = 'noopener noreferrer'\n        link.className = 'pdp-pinned-reviews__card-photo'\n        link.setAttribute('aria-label', \"Afficher la photo jointe \u00E0 l'avis\")\n        const img = document.createElement('img')\n        img.src = pic.thumb\n        img.alt = ''\n        img.loading = 'lazy'\n        img.decoding = 'async'\n        link.appendChild(img)\n        // Popup (lightbox Bootstrap) plut\u00F4t qu'un nouvel onglet ; le lien\n        // href reste le repli si Bootstrap n'est pas charg\u00E9.\n        link.addEventListener('click', (event) => {\n          if (!window.bootstrap) return\n          event.preventDefault()\n          openPhotoLightbox(pic.full)\n        })\n        photos.appendChild(link)\n      })\n      card.appendChild(photos)\n    }\n\n    const footer = el('span', 'pdp-pinned-reviews__card-meta')\n    const author = review.reviewer_name || (review.reviewer && review.reviewer.name) || ''\n    const when = relativeDateFr(review.created_at)\n    footer.append([author, when].filter(Boolean).join(' \u2014 '))\n    if (review.verified_buyer) {\n      footer.append(' \u00B7 ')\n      const verified = el('span', 'pdp-pinned-reviews__card-verified')\n      const check = document.createElement('i')\n      check.className = 'fa fa-check'\n      check.setAttribute('aria-hidden', 'true')\n      verified.append(check, ' Achat v\u00E9rifi\u00E9')\n      footer.appendChild(verified)\n    }\n    card.appendChild(footer)\n    grid.appendChild(card)\n  })\n\n  root.hidden = false\n}\ninitPdpPinnedReviews()\n// \u00C9diteur de th\u00E8me : re-remplir le squelette apr\u00E8s un re-rendu de la section\n// (le JSON window.jdgm.data du chargement initial survit, seul le DOM change).\ndocument.addEventListener('shopify:section:load', () => initPdpPinnedReviews())\n\nconst initPdpShareCopy = () => {\n  const btn = document.querySelector('[data-share-copy]')\n  if (!btn) return\n\n  const feedback = btn.parentElement?.querySelector('.pdp-share__copied')\n  let feedbackTimer = null\n\n  btn.addEventListener('click', async () => {\n    const url = btn.dataset.shareUrl || window.location.href\n    let copied = false\n\n    try {\n      await navigator.clipboard.writeText(url)\n      copied = true\n    } catch (error) {\n      // Repli pour les contextes sans Clipboard API\n      const input = document.createElement('input')\n      input.value = url\n      input.setAttribute('readonly', '')\n      input.style.position = 'fixed'\n      input.style.opacity = '0'\n      document.body.appendChild(input)\n      input.select()\n      try {\n        copied = document.execCommand('copy')\n      } catch (e) { /* noop */ }\n      input.remove()\n    }\n\n    if (copied && feedback) {\n      feedback.removeAttribute('hidden')\n      clearTimeout(feedbackTimer)\n      feedbackTimer = setTimeout(() => feedback.setAttribute('hidden', 'hidden'), 2000)\n    }\n  })\n}\ninitPdpShareCopy()\n"],
  "mappings": "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",
  "names": []
}
